table的排序

This commit is contained in:
lq
2025-09-03 17:57:09 +08:00
parent 2a38ef9ac3
commit e8b117d29e
2 changed files with 330 additions and 179 deletions

View File

@ -1,5 +1,5 @@
<template>
<div class="flex flex-col items-start cell-detail">
<div class="flex flex-col items-start cell-detail" @click="gotoDetail">
<div class="flex items-center">
<img
:src="getPlatformIcon(record.platform)"
@ -10,9 +10,27 @@
<div class="size-12px color-#939499 mt-2px">
{{ timestampToTime1(task.execution_time) }}
</div>
<div class="size-14px color-#211F24 mt-12px">{{ task.name || '未命名' }}</div>
<div class="size-14px color-#211F24 mt-12px color-#6D4CFE">{{ task.name || '未命名' }}</div>
<div class="flex items-center mt-12px">
<a-trigger trigger="click" align-point>
<div class="opt-btn" @click.stop="handleEditTime">修改发布时间</div>
<template #content>
<div class="custom-time-picker">
<!-- 1. 自定义触发按钮替代原输入框点击弹出面板 -->
<!-- <button @click="toggleTimePanel" class="trigger-btn">选择时间点击弹出面板</button> -->
<!-- 2. a-time-picker 核心隐藏输入框容器仅保留弹出面板 -->
<a-time-picker
format="HH:mm"
:defaultValue="defaultValue"
:visible="isPanelVisible"
@visible-change="handleVisibleChange"
@change="handleTimeChange"
class="hide-input-container"
/>
</div>
</template>
</a-trigger>
<div class="opt-btn" @click.stop="handleDelete" style="margin-right: 0px">删除</div>
</div>
</div>
@ -24,19 +42,31 @@ import { defineProps, defineEmits } from 'vue';
const props = defineProps({
task: {
type: Object,
required: true
required: true,
},
record: {
type: Object,
required: true
required: true,
},
getPlatformIcon: {
type: Function,
required: true
}
required: true,
},
});
const emit = defineEmits(['editTime', 'delete']);
const isPanelVisible = ref(false);
const toggleTimePanel = () => {
isPanelVisible.value = !isPanelVisible.value;
};
const handleVisibleChange = (visible: boolean) => {
isPanelVisible.value = visible;
};
const handleTimeChange = (time: Date | null) => {
if (time) {
console.log('Selected time:', time);
}
};
const defaultValue = ref(new Date());
const emit = defineEmits(['editTime', 'delete', 'gotoDetail']);
// 时间戳转时间格式 (MM月DD HH:MM)
const timestampToTime1 = (timestamp: number): string => {
@ -57,6 +87,11 @@ const handleEditTime = () => {
const handleDelete = () => {
emit('delete', props.task);
};
const gotoDetail = () => {
console.log('跳转详情');
emit('gotoDetail', props.task);
};
</script>
<style scoped>

View File

@ -88,62 +88,33 @@
</template>
</a-trigger>
<a-trigger
trigger="click"
style="
background-color: #ffffff;
border: 1px solid #d9d9d9;
border-radius: 4px;
box-shadow: #00000010 0px 2px 8px;
width: 308px;
height: 180px;
padding: 24px;
margin-top: 8px;
"
>
<a-button size="small">
<template #icon>
<icon-filter size="16" class="color-#55585F" />
</template>
<template #default>筛选</template>
</a-button>
<template #content>
<div>
<div class="flex items-center mb-24px">
<div class="w-70px">运营人员</div>
<a-space class="w-200px">
<CommonSelect
:multiple="false"
:options="operators"
v-model="query.operator_id"
@change="handleSearch"
class="!w-200px"
/>
</a-space>
</div>
<div class="flex items-center mb-24px">
<div class="w-70px">发布平台</div>
<a-space class="w-200px">
<CommonSelect
:multiple="false"
:options="platformOptions"
v-model="query.platform"
@change="handleSearch"
class="!w-200px"
/>
</a-space>
</div>
<div class="flex items-center">
<div class="w-70px">账号名称</div>
<a-input v-model="query.name" class="!w-200px" placeholder="输入账号名称" @change="handleSearch" />
</div>
</div>
</template>
</a-trigger>
</div>
</div>
<div class="flex justify-between items-start mt-16px" style="width: 100%">
<a-table :columns="columns" :data="data" :bordered="{ cell: true }" style="width: 100%" :pagination="false">
<div class="table-wrap bg-#fff rounded-8px px-24px py-24px flex flex-col">
<a-table
:columns="columns"
:data="data"
:bordered="{ cell: true }"
style="width: 100%"
:pagination="false"
@change="handleTableChange"
>
<!-- 表头插槽用于自定义日期列的表头样式 -->
<template #empty>
<div class="flex flex-col items-center justify-center">
<img :src="emptyIcon" class="img mt-20px" alt="" width="106" height="72" />
<div class="text mt-36px">暂无数据</div>
<div class="mt-12px mb-12px">可通过账号管理添加账号进行任务排期管理</div>
<a-button type="primary" @click="handleAddAccount">去添加</a-button>
</div>
</template>
<template #name="{ record }">
<div class="flex items-center">
<img
@ -189,6 +160,7 @@
@edit-time="handleModifyTime"
@delete="handleDelete"
@delete-task="handleDelete"
@gotoDetail="handleGoToDetail"
/>
</template>
</a-trigger>
@ -200,7 +172,12 @@
<template #content>
<div
class="flex flex-col items-start"
style="background-color: #fff; padding: 12px; box-shadow: #00000010 0px 2px 8px; border-radius: 4px"
style="
background-color: #fff;
padding: 12px;
box-shadow: #00000010 0px 2px 8px;
border-radius: 4px;
"
>
<div v-for="task in record[column.dataIndex]" :key="task.id" :title="task.name || '-'">
<a-trigger trigger="click" align-point>
@ -220,6 +197,7 @@
@edit-time="handleModifyTime"
@delete="handleDelete"
@delete-task="handleDelete"
@gotoDetail="handleGoToDetail"
/>
</template>
</a-trigger>
@ -248,6 +226,7 @@
:get-platform-icon="getPlatformIcon"
@edit-time="handleModifyTime"
@delete="handleDelete"
@gotoDetail="handleGoToDetail"
/>
</template>
</a-trigger>
@ -256,6 +235,20 @@
<div v-else class="no-task"></div>
</template>
</a-table>
<div v-if="pageInfo.total > 0" class="pagination-box">
<a-pagination
:total="pageInfo.total"
size="mini"
show-total
show-jumper
show-page-size
:current="pageInfo.page"
:page-size="pageInfo.page_size"
@change="onPageChange"
@page-size-change="onPageSizeChange"
/>
</div>
</div>
</div>
</div>
<a-modal v-model:visible="showModal" @ok="handleOk" @cancel="handleCancel" ok-text="确认删除">
@ -269,9 +262,8 @@
<script lang="ts" setup>
import { ref, reactive, onMounted, watch, computed, nextTick } from 'vue';
import type { TableColumnData } from '@arco-design/web-vue';
import { getTaskSchedules, delTaskSchedules } from '@/api/all/assignment-management';
import { fetchAccountOperators } from '@/api/all/propertyMarketing';
import { getTaskSchedules, delTaskSchedules, getTaskSchedulesDetail } from '@/api/all/assignment-management';
import { fetchAccountOperators, getMediaAccountList } from '@/api/all/propertyMarketing';
import icon1 from '@/assets/img/platform/icon-dy.png';
import icon2 from '@/assets/img/platform/icon-xhs.png';
import icon3 from '@/assets/img/media-account/icon-warn.png';
@ -282,6 +274,67 @@ import icon7 from '@/assets/img/platform/icon-ks.png';
import icon8 from '@/assets/img/platform/icon-bilibili.png';
import DateUtils from '@/utils/DateUtils';
import TaskDetail from './components/TaskDetail.vue';
import { useTableSelectionWithPagination } from '@/hooks/useTableSelectionWithPagination';
import emptyIcon from '@/assets/img/media-account/icon-empty.png';
const {
dataSource,
pageInfo,
rowSelection,
onPageChange,
onPageSizeChange,
resetPageInfo,
selectedRowKeys,
selectedRows,
handleSelectAll,
DEFAULT_PAGE_INFO,
} = useTableSelectionWithPagination({
onPageChange: () => {
handleSearch();
},
onPageSizeChange: () => {
handleSearch();
},
});
const handleTableChange = (pagination: any, sorter: any, extra: any) => {
console.log('分页信息:', pagination);
console.log('排序信息:', sorter);
console.log('额外信息:', extra);
console.log('所有列信息:', columns.value);
// 获取当前排序的列信息
if (sorter && sorter.sorter.direction == 'ascend' && sorter.sorter.field !== undefined) {
// 在columns中查找对应的列
// 注意dataIndex是数字类型而sorter.field可能是字符串类型
const column = columns.value.find((col: any) => {
// 确保比较时类型一致
return col.dataIndex == sorter.sorter.field || col.dataIndex == parseInt(sorter.sorter.field);
});
if (column) {
console.log('找到的列:', column);
if (column.date) {
console.log('当前排序列的日期:', column.date);
// 获取格式化的日期字符串
const formattedDate = DateUtils.formatDate(column.date);
console.log('当前排序列的格式化日期:', formattedDate);
query.top_execution_time = formattedDate;
handleSearch();
}
} else {
console.log('未找到匹配的列尝试查找dataIndex为', sorter.field, '的列');
}
} else {
query.top_execution_time = undefined;
handleSearch();
}
// 获取触发变更的列信息
if (extra && extra.column) {
console.log('触发变更的列:', extra.column);
}
};
const isChartEmpty = ref(true);
const currentTask = ref();
const visible = ref(false);
const deleteTitle = ref('');
@ -301,6 +354,7 @@ const currentDateRange = reactive({
const columns = ref<TableColumnData[]>([]);
const data = ref<any[]>([]);
const operators = ref([]);
const accountList = ref([]);
const platformOptions = ref([
{ value: 0, label: '抖音' },
{ value: 1, label: '小红书' },
@ -311,12 +365,6 @@ const platformOptions = ref([
{ value: 6, label: '公众号' },
]);
const pageInfo = reactive({
page: 1,
page_size: 10,
total: 0,
});
const query = reactive({
page: 1,
page_size: 20,
@ -324,6 +372,7 @@ const query = reactive({
operator_id: undefined,
name: '',
execution_time: [] as string[],
operator: '',
});
// 处理删除操作
@ -337,7 +386,9 @@ const handleDelete = (task: any) => {
deleteContent.value = '确认删除“' + task.name + '”吗?';
showModal.value = true;
};
const handleGoToDetail = (task: any) => {
console.log('跳转详情', task);
};
const handleOk = () => {
showModal.value = false;
delTaskSchedules(currentTask.value.id).then(() => {
@ -349,6 +400,7 @@ const handleCancel = () => {
showModal.value = false;
};
const handleAddAccount = () => {};
const handleModifyTime = (task: any) => {
console.log('修改时间', task);
// modalVisible.value = false;
@ -413,17 +465,6 @@ const timestampToDayNumber = (timestamp: number) => {
return date.getDate(); // 返回数字类型的日期
};
// 时间戳转时间格式 (MM月DD HH:MM)
const timestampToTime1 = (timestamp: number): string => {
const date = new Date(timestamp * 1000); // 假设时间戳是秒级
// 获取月份和日期注意月份从0开始需要+1
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
return `${month}${day} ${hours}:${minutes}`;
};
// 时间戳转时间格式 (HH:MM)
const timestampToTime = (timestamp: number): string => {
const date = new Date(timestamp * 1000); // 假设时间戳是秒级
@ -509,7 +550,6 @@ const setTableSpecific = () => {
];
let dateHeaders: any[] = [];
if (choseType.value === '周') {
const specificWeek = DateUtils.getWeekDaysByDate(new Date(weekModel.value), 0);
dateHeaders = specificWeek;
@ -531,20 +571,33 @@ const setTableSpecific = () => {
const weekday = DateUtils.formatDateToWeekdayDay(date);
dateHeaders = [{ day: day, weekday, date: date }];
}
// 判断是否为今天
const isToday = (date: Date) => {
const today = new Date();
return (
date.getDate() === today.getDate() &&
date.getMonth() === today.getMonth() &&
date.getFullYear() === today.getFullYear()
);
};
// 添加日期列
dateHeaders.forEach((item) => {
// 检查是否为周末周日为0周六为6
const isWeekend = item.date ? item.date.getDay() === 0 || item.date.getDay() === 6 : false;
const todayFlag = item.date ? isToday(item.date) : false;
columns.value.push({
title: `${item.weekday}`,
dataIndex: item.day, // 使用日期数字作为dataIndex
slotName: 'dateCell',
date: item.date,
width: 135,
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true, // 禁用默认排序
},
// 存储额外信息用于表头渲染
weekday: item.weekday,
todayFlag: todayFlag,
// 如果是周末,添加自定义样式
cellClass: isWeekend ? 'weekend-column' : '',
});
@ -663,6 +716,48 @@ const handleToday = () => {
onChangeDate(today);
}
};
// 处理筛选项选择事件
const handleFilterChange = (field: string, value: any, options?: any[]) => {
console.log(`筛选项 ${field} 发生变化:`, value);
// 根据不同的筛选字段执行不同的操作
switch (field) {
case 'operator_id':
console.log('运营人员选择:', value);
// 查找选中的运营人员完整信息
if (options && value) {
if (Array.isArray(value)) {
// 多选情况
const selectedOperators = options.filter((op: any) => value.includes(op.value));
console.log('选中的运营人员完整信息(多选):', selectedOperators);
} else {
// 单选情况
const selectedOperator = options.find((op: any) => op.value == value);
console.log('选中的运营人员完整信息(单选):', selectedOperator);
}
}
break;
case 'platform':
console.log('发布平台选择:', value);
// 查找选中的平台完整信息
if (options && value !== undefined && value !== '') {
if (Array.isArray(value)) {
// 多选情况
const selectedPlatforms = options.filter((op: any) => value.includes(op.value));
console.log('选中的发布平台完整信息(多选):', selectedPlatforms);
} else {
// 单选情况
const selectedPlatform = options.find((op: any) => op.value == value);
console.log('选中的发布平台完整信息(单选):', selectedPlatform);
}
}
break;
default:
console.log('未知筛选字段:', field, value);
}
// 调用原有的搜索函数
handleSearch();
};
// 获取数据
const handleSearch = () => {
@ -674,7 +769,7 @@ const handleSearch = () => {
// 根据API响应结构调整
const apiData = response.data.data || response.data;
data.value = processTableData(apiData);
pageInfo.total = response.data.total || apiData.length;
pageInfo.value.total = response.data.total || apiData.length;
}
})
.catch((error) => {
@ -697,6 +792,18 @@ const getOperators = async () => {
}
};
const getAccountList = async () => {
try {
const { code, data: accountData } = await getMediaAccountList();
if (code === 200) {
accountList.value = accountData.map((account: any) => ({
value: account.id,
name: account.name,
}));
}
} catch (error) {}
};
// 监听日期维度变化
watch(choseType, (newVal) => {
// 重置对应模型的值为当前日期
@ -720,6 +827,7 @@ onMounted(() => {
setTableSpecific();
handleSearch();
getOperators();
getAccountList();
});
</script>
@ -793,4 +901,12 @@ onMounted(() => {
border-radius: 4px;
margin-right: 12px;
}
.pagination-box {
display: flex;
width: 100%;
padding: 16px 0;
justify-content: flex-end;
align-items: center;
}
</style>