2025-08-29 14:05:27 +08:00
|
|
|
|
<template>
|
2025-09-15 19:40:07 +08:00
|
|
|
|
<div class="flex-column justify-between bg-#fff rounded-8px p-24px">
|
|
|
|
|
|
<!-- 日期选择器和筛选区域 -->
|
|
|
|
|
|
<div class="flex justify-between items-start w-full">
|
|
|
|
|
|
<DateSelector v-model="dateSelectorModel" @date-change="handleDateSelectorChange" />
|
2025-08-29 14:05:27 +08:00
|
|
|
|
<div class="flex items-start">
|
2025-09-12 17:46:01 +08:00
|
|
|
|
<colorTip />
|
|
|
|
|
|
<FilterPopup
|
|
|
|
|
|
:operators="operators"
|
|
|
|
|
|
:platformOptions="platformOptions"
|
|
|
|
|
|
:accountList="accountList"
|
|
|
|
|
|
:query="query"
|
2025-09-15 14:19:43 +08:00
|
|
|
|
@filter-change="handleFilterChange"
|
2025-09-12 17:46:01 +08:00
|
|
|
|
/>
|
2025-09-15 19:40:07 +08:00
|
|
|
|
<Button type="primary" class="w-112px" size="middle" @click="handleAddTask">
|
|
|
|
|
|
<template #default>创建任务</template>
|
|
|
|
|
|
</Button>
|
2025-08-29 14:05:27 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-09-15 19:40:07 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- 表格内容区域 -->
|
|
|
|
|
|
<div class="flex justify-between items-start w-full">
|
2025-09-15 20:26:31 +08:00
|
|
|
|
<div class="table-wrap py-24px flex flex-col" style="width: 100%; overflow-x: auto">
|
2025-09-03 17:57:09 +08:00
|
|
|
|
<a-table
|
|
|
|
|
|
:columns="columns"
|
|
|
|
|
|
:data="data"
|
|
|
|
|
|
:bordered="{ cell: true }"
|
2025-09-25 16:17:51 +08:00
|
|
|
|
:scroll="{ x: 'max-content' }"
|
2025-09-03 17:57:09 +08:00
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
:pagination="false"
|
|
|
|
|
|
@change="handleTableChange"
|
2025-09-23 17:11:51 +08:00
|
|
|
|
@cell-click="handleCellClick"
|
2025-09-03 17:57:09 +08:00
|
|
|
|
>
|
2025-09-15 19:40:07 +08:00
|
|
|
|
<!-- 空数据显示 -->
|
2025-09-03 17:57:09 +08:00
|
|
|
|
<template #empty>
|
2025-09-25 16:20:52 +08:00
|
|
|
|
<div class="flex flex-col items-center justify-center" style="min-height: 400px">
|
2025-09-15 19:40:07 +08:00
|
|
|
|
<img :src="emptyIcon" class="img mt-20px" alt="暂无数据" width="106" height="72" />
|
2025-09-03 17:57:09 +08:00
|
|
|
|
<div class="text mt-36px">暂无数据</div>
|
|
|
|
|
|
<div class="mt-12px mb-12px">可通过账号管理添加账号,进行任务排期管理</div>
|
|
|
|
|
|
<a-button type="primary" @click="handleAddAccount">去添加</a-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
2025-09-15 19:40:07 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- 账号与平台列 -->
|
2025-09-03 17:57:09 +08:00
|
|
|
|
<template #name="{ record }">
|
2025-09-25 16:20:52 +08:00
|
|
|
|
<div class="flex items-center justify-start">
|
2025-09-03 17:57:09 +08:00
|
|
|
|
<img
|
|
|
|
|
|
:src="getPlatformIcon(record.platform)"
|
2025-09-25 16:20:52 +08:00
|
|
|
|
style="border-radius: 8px; width: 16px; height: 16px; margin-right: 8px; margin-left: 20px"
|
2025-09-15 19:40:07 +08:00
|
|
|
|
:alt="getPlatformName(record.platform)"
|
2025-09-03 17:57:09 +08:00
|
|
|
|
/>
|
|
|
|
|
|
{{ record.name || '-' }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
2025-08-29 14:05:27 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
<!-- 动态日期单元格 -->
|
2025-09-03 17:57:09 +08:00
|
|
|
|
<template #dateCell="{ record, column }">
|
2025-09-15 19:40:07 +08:00
|
|
|
|
<div v-if="record[column.dataIndex]?.length" class="task-container">
|
|
|
|
|
|
<!-- 任务数量≥3时显示更多 -->
|
2025-09-03 17:57:09 +08:00
|
|
|
|
<div v-if="record[column.dataIndex].length >= 3" class="task-more">
|
2025-09-15 19:40:07 +08:00
|
|
|
|
<TaskItem :task="record[column.dataIndex][0]" :record="record" @handle-task="handleTaskAction" />
|
2025-08-30 15:54:54 +08:00
|
|
|
|
<a-trigger trigger="click" position="br">
|
2025-09-24 17:12:33 +08:00
|
|
|
|
<div class="size-12px color-#8f959f h-19px ml-4px rounded-2px cursor-pointer" @click.stop>
|
2025-09-19 15:53:12 +08:00
|
|
|
|
还有{{ record[column.dataIndex].length - 1 }}项
|
|
|
|
|
|
</div>
|
2025-09-03 17:57:09 +08:00
|
|
|
|
<template #content>
|
2025-09-24 17:12:33 +08:00
|
|
|
|
<div class="bg-#fff w-160px p-12px rounded-4px flex flex-col more-content">
|
2025-09-15 19:40:07 +08:00
|
|
|
|
<TaskItem
|
|
|
|
|
|
v-for="task in record[column.dataIndex]"
|
|
|
|
|
|
:key="task.id"
|
|
|
|
|
|
:task="task"
|
|
|
|
|
|
:record="record"
|
|
|
|
|
|
@handle-task="handleTaskAction"
|
|
|
|
|
|
/>
|
2025-09-03 17:57:09 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</a-trigger>
|
|
|
|
|
|
</div>
|
2025-09-15 19:40:07 +08:00
|
|
|
|
<!-- 任务数量<3时直接显示 -->
|
|
|
|
|
|
<div v-else>
|
|
|
|
|
|
<TaskItem
|
|
|
|
|
|
v-for="task in record[column.dataIndex]"
|
|
|
|
|
|
:key="task.id"
|
|
|
|
|
|
:task="task"
|
|
|
|
|
|
:record="record"
|
|
|
|
|
|
@handle-task="handleTaskAction"
|
|
|
|
|
|
/>
|
2025-08-29 14:05:27 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-09-03 17:57:09 +08:00
|
|
|
|
<div v-else class="no-task"></div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</a-table>
|
2025-09-15 19:40:07 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- 分页控件 -->
|
2025-09-03 17:57:09 +08:00
|
|
|
|
<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>
|
2025-08-29 14:05:27 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-09-15 19:40:07 +08:00
|
|
|
|
<!-- 删除确认弹窗 -->
|
|
|
|
|
|
<a-modal v-model:visible="showModal" @ok="handleDeleteConfirm" @cancel="showModal = false" ok-text="确认删除">
|
|
|
|
|
|
<template #title>{{ deleteTitle }}</template>
|
|
|
|
|
|
<div>{{ deleteContent }}</div>
|
2025-09-02 14:30:42 +08:00
|
|
|
|
</a-modal>
|
2025-09-23 17:11:51 +08:00
|
|
|
|
<DrowPopup ref="drawerPopupRef" @create-task="handleCreateTask" />
|
2025-08-29 14:05:27 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2025-09-15 20:26:31 +08:00
|
|
|
|
import { ref, reactive, onMounted, computed, inject } from 'vue';
|
2025-09-15 14:19:43 +08:00
|
|
|
|
import type { ColumnProps } from 'ant-design-vue/es/table';
|
2025-09-15 19:40:07 +08:00
|
|
|
|
import router from '@/router';
|
|
|
|
|
|
import DateUtils from '@/utils/DateUtils';
|
|
|
|
|
|
// 组件引入
|
|
|
|
|
|
import DateSelector from './components/date-selector.vue';
|
|
|
|
|
|
import colorTip from './components/colorTip.vue';
|
|
|
|
|
|
import FilterPopup from './components/filter-popup.vue';
|
2025-09-15 20:26:31 +08:00
|
|
|
|
import DrowPopup from './components/draw-popup.vue';
|
2025-09-19 10:34:26 +08:00
|
|
|
|
import TaskItem from './components/task-item.vue';
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// API引入
|
2025-09-24 12:08:21 +08:00
|
|
|
|
import {
|
|
|
|
|
|
getTaskSchedules,
|
|
|
|
|
|
delTaskSchedules,
|
2025-09-24 16:20:33 +08:00
|
|
|
|
editTaskSchedulesTime,
|
2025-09-24 12:08:21 +08:00
|
|
|
|
createTask,
|
|
|
|
|
|
generateContent,
|
|
|
|
|
|
} from '@/api/all/assignment-management';
|
2025-09-03 17:57:09 +08:00
|
|
|
|
import { fetchAccountOperators, getMediaAccountList } from '@/api/all/propertyMarketing';
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 工具引入
|
2025-09-03 17:57:09 +08:00
|
|
|
|
import { useTableSelectionWithPagination } from '@/hooks/useTableSelectionWithPagination';
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 静态资源
|
2025-09-03 17:57:09 +08:00
|
|
|
|
import emptyIcon from '@/assets/img/media-account/icon-empty.png';
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 平台图标
|
|
|
|
|
|
import iconDy from '@/assets/img/platform/icon-dy.png';
|
|
|
|
|
|
import iconXhs from '@/assets/img/platform/icon-xhs.png';
|
|
|
|
|
|
import iconBilibili from '@/assets/img/platform/icon-bilibili.png';
|
|
|
|
|
|
import iconKs from '@/assets/img/platform/icon-ks.png';
|
|
|
|
|
|
import iconSph from '@/assets/img/platform/icon-sph.png';
|
|
|
|
|
|
import iconWb from '@/assets/img/platform/icon-wb.png';
|
|
|
|
|
|
import iconGzh from '@/assets/img/platform/icon-gzh.png';
|
|
|
|
|
|
import iconWarn from '@/assets/img/media-account/icon-warn.png';
|
|
|
|
|
|
import { Checkbox, Button, Space, Pagination, notification } from 'ant-design-vue';
|
2025-09-23 18:16:10 +08:00
|
|
|
|
import { message } from 'ant-design-vue';
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 表格分页逻辑
|
|
|
|
|
|
const { pageInfo, onPageChange, onPageSizeChange } = useTableSelectionWithPagination({
|
|
|
|
|
|
onPageChange: () => handleSearch(),
|
|
|
|
|
|
onPageSizeChange: () => handleSearch(),
|
2025-09-03 17:57:09 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 状态管理
|
|
|
|
|
|
const dateSelectorModel = ref({
|
|
|
|
|
|
choseType: '周' as '日' | '周' | '月',
|
|
|
|
|
|
dayModel: new Date(),
|
|
|
|
|
|
weekModel: new Date(),
|
|
|
|
|
|
monthModel: new Date(),
|
2025-08-29 14:05:27 +08:00
|
|
|
|
});
|
2025-09-15 14:19:43 +08:00
|
|
|
|
const columns = ref<ColumnProps[]>([]);
|
2025-08-29 16:39:14 +08:00
|
|
|
|
const data = ref<any[]>([]);
|
2025-08-29 14:05:27 +08:00
|
|
|
|
const operators = ref([]);
|
2025-09-03 17:57:09 +08:00
|
|
|
|
const accountList = ref([]);
|
2025-09-15 19:40:07 +08:00
|
|
|
|
const showModal = ref(false);
|
|
|
|
|
|
const currentTask = ref<any>(null);
|
|
|
|
|
|
const deleteTitle = ref('');
|
|
|
|
|
|
const deleteContent = ref('');
|
2025-08-29 14:05:27 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 获取当前周的日期范围
|
|
|
|
|
|
const getCurrentWeekRange = () => {
|
|
|
|
|
|
const weekRange = DateUtils.getWeekRangeByDate(new Date());
|
|
|
|
|
|
return [weekRange.startFormatted, weekRange.endFormatted];
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 查询参数
|
2025-08-29 14:05:27 +08:00
|
|
|
|
const query = reactive({
|
2025-09-15 19:40:07 +08:00
|
|
|
|
page: pageInfo.value.page,
|
|
|
|
|
|
page_size: pageInfo.value.page_size,
|
2025-09-04 09:21:18 +08:00
|
|
|
|
platforms: undefined,
|
2025-09-03 18:22:51 +08:00
|
|
|
|
operator_ids: undefined,
|
|
|
|
|
|
ids: [],
|
2025-09-15 19:40:07 +08:00
|
|
|
|
execution_time: getCurrentWeekRange(), // 设置默认值为当前周
|
|
|
|
|
|
top_execution_time: undefined,
|
2025-08-29 14:05:27 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 平台配置
|
|
|
|
|
|
const platformConfig = {
|
|
|
|
|
|
icons: { 0: iconDy, 1: iconXhs, 2: iconBilibili, 3: iconKs, 4: iconSph, 5: iconWb, 6: iconGzh },
|
|
|
|
|
|
names: { 0: '抖音', 1: '小红书', 2: 'B站', 3: '快手', 4: '视频号', 5: '微博', 6: '公众号' },
|
|
|
|
|
|
options: [
|
|
|
|
|
|
{ id: 0, name: '抖音', icon: iconDy },
|
|
|
|
|
|
{ id: 1, name: '小红书', icon: iconXhs },
|
|
|
|
|
|
{ id: 2, name: 'B站', icon: iconBilibili },
|
|
|
|
|
|
{ id: 3, name: '快手', icon: iconKs },
|
|
|
|
|
|
{ id: 4, name: '视频号', icon: iconSph },
|
|
|
|
|
|
{ id: 5, name: '微博', icon: iconWb },
|
|
|
|
|
|
{ id: 6, name: '公众号', icon: iconGzh },
|
|
|
|
|
|
],
|
2025-09-04 15:48:06 +08:00
|
|
|
|
};
|
2025-09-15 19:40:07 +08:00
|
|
|
|
const platformOptions = ref(platformConfig.options);
|
2025-09-04 15:48:06 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 工具函数
|
|
|
|
|
|
const getPlatformIcon = (platform: number) => platformConfig.icons[platform] || iconWarn;
|
|
|
|
|
|
const getPlatformName = (platform: number) => platformConfig.names[platform] || '未知平台';
|
2025-08-29 14:05:27 +08:00
|
|
|
|
|
|
|
|
|
|
const timestampToDayNumber = (timestamp: number) => {
|
2025-09-15 19:40:07 +08:00
|
|
|
|
return new Date(timestamp * 1000).getDate();
|
2025-08-29 14:05:27 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 处理表格数据
|
2025-08-29 14:05:27 +08:00
|
|
|
|
const processTableData = (apiData: any[]) => {
|
|
|
|
|
|
const processedData: any[] = [];
|
2025-09-15 19:40:07 +08:00
|
|
|
|
const dateHeaders = currentDateHeaders.value;
|
|
|
|
|
|
|
2025-08-29 14:05:27 +08:00
|
|
|
|
apiData.forEach((account) => {
|
|
|
|
|
|
const rowData: any = {
|
|
|
|
|
|
id: account.id,
|
|
|
|
|
|
name: account.name,
|
|
|
|
|
|
platform: account.platform,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 初始化日期列
|
|
|
|
|
|
dateHeaders.forEach((day) => {
|
2025-08-29 14:05:27 +08:00
|
|
|
|
rowData[day] = [];
|
|
|
|
|
|
});
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 分配任务到对应日期列
|
|
|
|
|
|
if (account.task_schedules?.length) {
|
2025-08-29 14:05:27 +08:00
|
|
|
|
account.task_schedules.forEach((task: any) => {
|
|
|
|
|
|
const taskDay = timestampToDayNumber(task.execution_time);
|
2025-09-15 19:40:07 +08:00
|
|
|
|
if (dateHeaders.includes(taskDay)) {
|
2025-09-20 11:25:34 +08:00
|
|
|
|
rowData[taskDay].push(task);
|
2025-08-29 14:05:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
processedData.push(rowData);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return processedData;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 创建任务
|
2025-09-15 20:26:31 +08:00
|
|
|
|
const handleAddTask = () => {
|
|
|
|
|
|
drawerPopupRef.value?.showDrawer();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-23 17:11:51 +08:00
|
|
|
|
const handleCreateTask = async (value) => {
|
|
|
|
|
|
const res = await createTask(value);
|
2025-09-23 18:16:10 +08:00
|
|
|
|
if (res && res.code === 200) {
|
|
|
|
|
|
message.success('创建成功');
|
|
|
|
|
|
handleSearch();
|
|
|
|
|
|
}
|
2025-09-23 17:11:51 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-15 20:26:31 +08:00
|
|
|
|
// 添加对DrowPopup组件的引用
|
|
|
|
|
|
const drawerPopupRef = ref();
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 设置表格列
|
|
|
|
|
|
const setTableColumns = () => {
|
2025-08-29 14:05:27 +08:00
|
|
|
|
columns.value = [
|
|
|
|
|
|
{
|
|
|
|
|
|
title: '账号与发布平台',
|
|
|
|
|
|
slotName: 'name',
|
|
|
|
|
|
width: 150,
|
2025-08-30 13:53:53 +08:00
|
|
|
|
ellipsis: true,
|
|
|
|
|
|
tooltip: true,
|
2025-09-15 19:40:07 +08:00
|
|
|
|
fixed: 'left', // 固定列
|
2025-08-29 14:05:27 +08:00
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
let dateHeaders: any[] = [];
|
2025-09-15 19:40:07 +08:00
|
|
|
|
const { choseType } = dateSelectorModel.value;
|
|
|
|
|
|
|
|
|
|
|
|
if (choseType === '周') {
|
|
|
|
|
|
dateHeaders = DateUtils.getWeekDaysByDate(dateSelectorModel.value.weekModel, 0);
|
|
|
|
|
|
} else if (choseType === '月') {
|
|
|
|
|
|
const date = dateSelectorModel.value.monthModel;
|
|
|
|
|
|
dateHeaders = DateUtils.getDaysAndWeekdays(date.getFullYear(), date.getMonth());
|
2025-08-29 14:05:27 +08:00
|
|
|
|
} else {
|
2025-09-15 19:40:07 +08:00
|
|
|
|
const date = dateSelectorModel.value.dayModel;
|
|
|
|
|
|
dateHeaders = [
|
|
|
|
|
|
{
|
|
|
|
|
|
day: date.getDate(),
|
|
|
|
|
|
weekday: DateUtils.formatDateToWeekdayDay(date),
|
|
|
|
|
|
date,
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
2025-08-29 14:05:27 +08:00
|
|
|
|
}
|
2025-09-15 19:40:07 +08:00
|
|
|
|
|
2025-09-03 17:57:09 +08:00
|
|
|
|
// 判断是否为今天
|
|
|
|
|
|
const isToday = (date: Date) => {
|
2025-09-15 19:40:07 +08:00
|
|
|
|
if (!date) return false;
|
2025-09-03 17:57:09 +08:00
|
|
|
|
const today = new Date();
|
2025-09-15 19:40:07 +08:00
|
|
|
|
today.setHours(0, 0, 0, 0);
|
|
|
|
|
|
const targetDate = new Date(date);
|
|
|
|
|
|
targetDate.setHours(0, 0, 0, 0);
|
|
|
|
|
|
return targetDate.getTime() === today.getTime();
|
2025-09-03 17:57:09 +08:00
|
|
|
|
};
|
2025-09-15 19:40:07 +08:00
|
|
|
|
|
2025-08-29 14:05:27 +08:00
|
|
|
|
// 添加日期列
|
|
|
|
|
|
dateHeaders.forEach((item) => {
|
2025-09-15 19:40:07 +08:00
|
|
|
|
const isWeekend = item.date?.getDay() === 0 || item.date?.getDay() === 6;
|
|
|
|
|
|
// 确保item.date存在再进行判断
|
2025-09-03 17:57:09 +08:00
|
|
|
|
const todayFlag = item.date ? isToday(item.date) : false;
|
2025-09-15 20:26:31 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 调试信息
|
|
|
|
|
|
if (todayFlag) {
|
|
|
|
|
|
console.log('Today column detected:', item);
|
|
|
|
|
|
console.log('Today flag value:', todayFlag);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const columnConfig = {
|
2025-08-29 14:05:27 +08:00
|
|
|
|
title: `${item.weekday}`,
|
2025-09-15 19:40:07 +08:00
|
|
|
|
dataIndex: item.day,
|
2025-08-29 14:05:27 +08:00
|
|
|
|
slotName: 'dateCell',
|
2025-09-03 17:57:09 +08:00
|
|
|
|
date: item.date,
|
2025-08-29 14:05:27 +08:00
|
|
|
|
width: 135,
|
|
|
|
|
|
sortable: {
|
|
|
|
|
|
sortDirections: ['ascend', 'descend'],
|
2025-09-15 19:40:07 +08:00
|
|
|
|
sorter: true,
|
2025-08-29 14:05:27 +08:00
|
|
|
|
},
|
2025-09-03 17:57:09 +08:00
|
|
|
|
weekday: item.weekday,
|
2025-09-15 19:40:07 +08:00
|
|
|
|
todayFlag,
|
|
|
|
|
|
// 为周末设置特定的背景色
|
2025-08-30 13:53:53 +08:00
|
|
|
|
cellClass: isWeekend ? 'weekend-column' : '',
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 为今日添加特殊类名
|
|
|
|
|
|
class: todayFlag ? 'today-column' : '',
|
|
|
|
|
|
};
|
2025-09-15 20:26:31 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 更多调试信息
|
|
|
|
|
|
if (todayFlag) {
|
|
|
|
|
|
console.log('Column config for today:', columnConfig);
|
|
|
|
|
|
}
|
2025-09-15 20:26:31 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
columns.value.push(columnConfig);
|
2025-08-29 14:05:27 +08:00
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 当前日期头部计算
|
|
|
|
|
|
const currentDateHeaders = computed(() => {
|
|
|
|
|
|
const { choseType } = dateSelectorModel.value;
|
2025-08-29 16:39:14 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
if (choseType === '周') {
|
|
|
|
|
|
return DateUtils.getWeekDaysByDate(dateSelectorModel.value.weekModel, 0).map((item) =>
|
|
|
|
|
|
parseInt(item.day.toString(), 10),
|
|
|
|
|
|
);
|
|
|
|
|
|
} else if (choseType === '月') {
|
|
|
|
|
|
const date = dateSelectorModel.value.monthModel;
|
|
|
|
|
|
return DateUtils.getDaysAndWeekdays(date.getFullYear(), date.getMonth()).map((item) =>
|
|
|
|
|
|
parseInt(item.day.toString(), 10),
|
|
|
|
|
|
);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return [dateSelectorModel.value.dayModel.getDate()];
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-08-29 16:39:14 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 数据获取
|
|
|
|
|
|
const handleSearch = () => {
|
|
|
|
|
|
query.page = pageInfo.value.page;
|
|
|
|
|
|
query.page_size = pageInfo.value.page_size;
|
|
|
|
|
|
getTaskSchedules(query)
|
|
|
|
|
|
.then((response) => {
|
|
|
|
|
|
if (response.data) {
|
|
|
|
|
|
const apiData = response.data.data || response.data;
|
2025-09-24 16:20:33 +08:00
|
|
|
|
if (apiData) {
|
|
|
|
|
|
data.value = processTableData(apiData);
|
|
|
|
|
|
}
|
2025-09-15 19:40:07 +08:00
|
|
|
|
pageInfo.value.total = response.data.total || apiData.length;
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(() => {
|
|
|
|
|
|
data.value = [];
|
2025-08-29 16:39:14 +08:00
|
|
|
|
});
|
2025-08-29 14:05:27 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 添加一个标志位来避免死循环
|
|
|
|
|
|
let isDateSelectorUpdating = false;
|
|
|
|
|
|
// 日期选择器变化处理
|
|
|
|
|
|
const handleDateSelectorChange = (value: any) => {
|
|
|
|
|
|
// 如果正在更新中,则跳过
|
|
|
|
|
|
if (isDateSelectorUpdating) {
|
|
|
|
|
|
return;
|
2025-08-29 14:05:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
const newStartDate = value.dateRange.start;
|
|
|
|
|
|
const newEndDate = value.dateRange.end;
|
2025-08-29 16:39:14 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 添加空值检查以避免数组越界错误
|
|
|
|
|
|
const currentStart =
|
|
|
|
|
|
Array.isArray(query.execution_time) && query.execution_time.length > 0 ? query.execution_time[0] : null;
|
|
|
|
|
|
const currentEnd =
|
|
|
|
|
|
Array.isArray(query.execution_time) && query.execution_time.length > 1 ? query.execution_time[1] : null;
|
2025-08-29 16:39:14 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 如果日期范围没有变化,则不执行后续操作
|
|
|
|
|
|
if (currentStart === newStartDate && currentEnd === newEndDate) {
|
|
|
|
|
|
return;
|
2025-08-29 14:05:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 设置标志位
|
|
|
|
|
|
isDateSelectorUpdating = true;
|
2025-08-29 14:05:27 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
query.execution_time = [newStartDate, newEndDate];
|
|
|
|
|
|
setTableColumns();
|
|
|
|
|
|
handleSearch();
|
2025-08-29 14:05:27 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 在下一个事件循环重置标志位
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
isDateSelectorUpdating = false;
|
|
|
|
|
|
}, 0);
|
2025-08-29 14:05:27 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 筛选条件变化处理
|
|
|
|
|
|
|
|
|
|
|
|
const handleFilterChange = (filters: any) => {
|
|
|
|
|
|
console.log(filters);
|
|
|
|
|
|
if (typeof filters === 'object' && filters !== null) {
|
|
|
|
|
|
Object.keys(filters).forEach((key) => {
|
2025-09-15 14:19:43 +08:00
|
|
|
|
switch (key) {
|
|
|
|
|
|
case 'operator':
|
2025-09-15 19:40:07 +08:00
|
|
|
|
query.operator_ids = filters[key];
|
2025-09-15 14:19:43 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case 'platform':
|
2025-09-15 19:40:07 +08:00
|
|
|
|
query.platforms = filters[key];
|
2025-09-15 14:19:43 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case 'accounts':
|
2025-09-15 19:40:07 +08:00
|
|
|
|
query.ids = filters[key];
|
2025-09-15 14:19:43 +08:00
|
|
|
|
break;
|
|
|
|
|
|
default:
|
2025-09-15 19:40:07 +08:00
|
|
|
|
query[key] = filters[key];
|
2025-09-03 17:57:09 +08:00
|
|
|
|
}
|
2025-09-15 14:19:43 +08:00
|
|
|
|
});
|
2025-09-15 19:40:07 +08:00
|
|
|
|
console.log(query);
|
2025-09-15 14:19:43 +08:00
|
|
|
|
handleSearch();
|
2025-09-03 17:57:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
2025-08-29 14:05:27 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 表格排序变化
|
|
|
|
|
|
const handleTableChange = (pagination: any, sorter: any) => {
|
|
|
|
|
|
if (sorter && sorter.sorter?.direction === 'ascend' && sorter.sorter?.field) {
|
|
|
|
|
|
const column = columns.value.find((col) => col.dataIndex == sorter.sorter.field);
|
|
|
|
|
|
if (column?.date) {
|
|
|
|
|
|
query.top_execution_time = DateUtils.formatDate(column.date);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
query.top_execution_time = undefined;
|
|
|
|
|
|
}
|
|
|
|
|
|
handleSearch();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-23 17:11:51 +08:00
|
|
|
|
const handleCellClick = (record: any, rowIndex: any, column: any) => {
|
2025-09-19 18:36:20 +08:00
|
|
|
|
const accountInfo = {
|
|
|
|
|
|
id: record.id,
|
|
|
|
|
|
name: record.name,
|
|
|
|
|
|
platform: record.platform,
|
|
|
|
|
|
};
|
2025-09-23 17:11:51 +08:00
|
|
|
|
const selectedDate = rowIndex.date;
|
|
|
|
|
|
|
|
|
|
|
|
// 检查选中的日期是否小于今天,如果是则不处理
|
|
|
|
|
|
const today = new Date();
|
|
|
|
|
|
today.setHours(0, 0, 0, 0);
|
|
|
|
|
|
const selectedDateTime = new Date(selectedDate);
|
|
|
|
|
|
selectedDateTime.setHours(0, 0, 0, 0);
|
|
|
|
|
|
|
|
|
|
|
|
if (selectedDateTime < today) {
|
|
|
|
|
|
console.log('选择的日期已过去,不打开抽屉');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-25 16:33:52 +08:00
|
|
|
|
console.log('selectedDate', selectedDate, accountInfo);
|
2025-09-23 17:11:51 +08:00
|
|
|
|
drawerPopupRef.value.showDrawer(accountInfo, selectedDate);
|
2025-09-19 18:36:20 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 任务操作处理
|
2025-09-24 12:08:21 +08:00
|
|
|
|
const handleTaskAction = async (action: string, task: any, ...args: any[]) => {
|
|
|
|
|
|
console.log('handleTaskAction', action, task, args);
|
2025-09-15 19:40:07 +08:00
|
|
|
|
switch (action) {
|
|
|
|
|
|
case 'delete':
|
|
|
|
|
|
currentTask.value = task;
|
|
|
|
|
|
deleteTitle.value = task.type === 1 ? '删除内容稿件排期' : '删除选题排期';
|
2025-09-24 12:08:21 +08:00
|
|
|
|
deleteContent.value = `确认删除“${task.name || 'AI生成内容'}”吗?`;
|
2025-09-15 19:40:07 +08:00
|
|
|
|
showModal.value = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'edit-time':
|
2025-09-24 16:20:33 +08:00
|
|
|
|
console.log('handleTaskAction edit-time', task, args);
|
|
|
|
|
|
editTaskSchedulesTime(task.id, { execution_time: args[0] }).then((res) => {
|
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
|
message.success(res.message);
|
|
|
|
|
|
handleSearch();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-09-15 19:40:07 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case 'goto-detail':
|
|
|
|
|
|
router.push(`/media-account/management-detail/${task.id}`);
|
|
|
|
|
|
break;
|
2025-09-24 12:08:21 +08:00
|
|
|
|
case 'ai-create':
|
|
|
|
|
|
const res = await generateContent(task.id);
|
|
|
|
|
|
if (res.code === 200) {
|
2025-09-24 16:20:33 +08:00
|
|
|
|
message.success(res.message);
|
2025-09-24 12:08:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
2025-09-25 14:31:39 +08:00
|
|
|
|
case 'edit-task':
|
|
|
|
|
|
console.log('edit-task', args[0], typeof args[0]);
|
|
|
|
|
|
const accountInfo = {
|
|
|
|
|
|
id: args[0].id,
|
|
|
|
|
|
name: args[0].name,
|
|
|
|
|
|
platform: args[0].platform,
|
|
|
|
|
|
};
|
|
|
|
|
|
const selectedDate = task.execution_time;
|
|
|
|
|
|
const date = new Date(selectedDate);
|
2025-09-25 15:37:50 +08:00
|
|
|
|
|
2025-09-25 15:44:29 +08:00
|
|
|
|
// 显示抽屉
|
|
|
|
|
|
drawerPopupRef.value.showDrawer(accountInfo, date);
|
2025-09-25 16:17:51 +08:00
|
|
|
|
|
2025-09-25 14:56:24 +08:00
|
|
|
|
// 等待抽屉打开后再填充数据
|
|
|
|
|
|
nextTick(() => {
|
2025-09-25 15:44:29 +08:00
|
|
|
|
// 将任务信息回填到draw-popup组件
|
|
|
|
|
|
drawerPopupRef.value.fillTaskData(task);
|
2025-09-25 14:56:24 +08:00
|
|
|
|
});
|
2025-09-25 14:31:39 +08:00
|
|
|
|
break;
|
2025-09-15 19:40:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 确认删除
|
|
|
|
|
|
const handleDeleteConfirm = () => {
|
|
|
|
|
|
if (currentTask.value) {
|
|
|
|
|
|
delTaskSchedules(currentTask.value.id).then(() => {
|
|
|
|
|
|
showModal.value = false;
|
|
|
|
|
|
handleSearch();
|
2025-08-29 14:05:27 +08:00
|
|
|
|
});
|
2025-09-15 19:40:07 +08:00
|
|
|
|
}
|
2025-08-29 14:05:27 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 添加账号
|
|
|
|
|
|
const handleAddAccount = () => {
|
|
|
|
|
|
// 跳转到添加账号页面的逻辑
|
|
|
|
|
|
router.push('/media-account/add');
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 获取运营人员列表
|
2025-08-29 14:05:27 +08:00
|
|
|
|
const getOperators = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const { code, data: operatorsData } = await fetchAccountOperators();
|
|
|
|
|
|
if (code === 200) {
|
|
|
|
|
|
operators.value = operatorsData.map((op: any) => ({
|
|
|
|
|
|
value: op.id,
|
2025-08-30 13:53:53 +08:00
|
|
|
|
name: op.name,
|
2025-08-29 14:05:27 +08:00
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2025-09-15 19:40:07 +08:00
|
|
|
|
console.error('获取运营人员失败:', error);
|
2025-08-29 14:05:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 获取账号列表
|
2025-09-03 17:57:09 +08:00
|
|
|
|
const getAccountList = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const { code, data: accountData } = await getMediaAccountList();
|
|
|
|
|
|
if (code === 200) {
|
|
|
|
|
|
accountList.value = accountData.map((account: any) => ({
|
|
|
|
|
|
value: account.id,
|
2025-09-15 19:40:07 +08:00
|
|
|
|
name: `${account.name}(${getPlatformName(account.platform)})`,
|
2025-09-04 11:09:21 +08:00
|
|
|
|
platform: account.platform,
|
|
|
|
|
|
icon: getPlatformIcon(account.platform),
|
2025-09-03 17:57:09 +08:00
|
|
|
|
}));
|
|
|
|
|
|
}
|
2025-09-15 19:40:07 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取账号列表失败:', error);
|
2025-08-29 16:39:14 +08:00
|
|
|
|
}
|
2025-09-15 19:40:07 +08:00
|
|
|
|
};
|
2025-08-29 14:05:27 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 初始化
|
2025-08-29 14:05:27 +08:00
|
|
|
|
onMounted(() => {
|
2025-09-15 19:40:07 +08:00
|
|
|
|
// 确保在初始化时设置表格列和执行搜索
|
|
|
|
|
|
setTableColumns();
|
2025-08-29 14:05:27 +08:00
|
|
|
|
handleSearch();
|
|
|
|
|
|
getOperators();
|
2025-09-03 17:57:09 +08:00
|
|
|
|
getAccountList();
|
2025-08-29 14:05:27 +08:00
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.task-container {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
2025-08-30 13:53:53 +08:00
|
|
|
|
height: 100%;
|
2025-08-29 14:05:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-item {
|
|
|
|
|
|
display: flex;
|
2025-08-30 13:53:53 +08:00
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 2px;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
2025-08-29 14:05:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-30 13:53:53 +08:00
|
|
|
|
.task-more {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
cursor: pointer;
|
2025-08-29 14:05:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.no-task {
|
2025-09-25 16:17:51 +08:00
|
|
|
|
min-height: 42px;
|
2025-08-30 13:53:53 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
2025-08-29 14:05:27 +08:00
|
|
|
|
}
|
2025-08-30 13:53:53 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
/* 周末列样式 */
|
2025-08-30 13:53:53 +08:00
|
|
|
|
:deep(.weekend-column) {
|
2025-09-15 20:26:31 +08:00
|
|
|
|
background-color: #fbfaff !important;
|
2025-09-15 19:40:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 今日列样式 */
|
|
|
|
|
|
:deep(th.today-column),
|
|
|
|
|
|
:deep(td.today-column) {
|
2025-09-15 20:26:31 +08:00
|
|
|
|
background-color: #6d4cfe !important;
|
2025-08-29 14:05:27 +08:00
|
|
|
|
}
|
2025-08-30 15:54:54 +08:00
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
:deep(th.today-column) .arco-table-th-item,
|
|
|
|
|
|
:deep(th.today-column) .arco-table-th-item-title {
|
2025-09-15 20:26:31 +08:00
|
|
|
|
color: #6d4cfe !important;
|
2025-09-15 19:40:07 +08:00
|
|
|
|
background-color: white !important;
|
|
|
|
|
|
font-weight: bold;
|
2025-08-30 15:54:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-15 20:26:31 +08:00
|
|
|
|
:deep(th.today-column) .arco-table-th-item-title {
|
|
|
|
|
|
color: #6d4cfe !important;
|
2025-09-15 19:40:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-19 18:07:33 +08:00
|
|
|
|
/* 只对 td 单元格应用样式,避免影响表头 */
|
|
|
|
|
|
:deep(td .arco-table-cell) {
|
2025-09-19 15:53:12 +08:00
|
|
|
|
padding: 0px !important;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: start;
|
2025-09-25 16:17:51 +08:00
|
|
|
|
min-height: 42px;
|
2025-08-30 15:54:54 +08:00
|
|
|
|
}
|
2025-09-03 17:57:09 +08:00
|
|
|
|
|
2025-09-25 16:20:52 +08:00
|
|
|
|
:deep(td .arco-table-cell:first-child) {
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(td.today-column) .arco-table-cell-wrap {
|
|
|
|
|
|
color: white !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-15 20:26:31 +08:00
|
|
|
|
/* 抽屉左侧圆角样式 */
|
|
|
|
|
|
:deep(.rounded-left .ant-drawer-content) {
|
|
|
|
|
|
border-top-left-radius: 8px !important;
|
|
|
|
|
|
border-bottom-left-radius: 8px !important;
|
2025-09-15 19:40:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-24 17:12:33 +08:00
|
|
|
|
/* 任务弹出框样式 */
|
|
|
|
|
|
:deep(.task-popup-content) {
|
|
|
|
|
|
max-height: 300px;
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-15 19:40:07 +08:00
|
|
|
|
/* 分页样式 */
|
2025-09-03 17:57:09 +08:00
|
|
|
|
.pagination-box {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
padding: 16px 0;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
2025-09-15 19:40:07 +08:00
|
|
|
|
|
|
|
|
|
|
/* 下拉框样式优化 */
|
|
|
|
|
|
:deep(.arco-dropdown-open .arco-icon-down) {
|
|
|
|
|
|
transform: rotate(180deg);
|
|
|
|
|
|
transition: transform 0.2s ease;
|
|
|
|
|
|
}
|
2025-09-24 17:12:33 +08:00
|
|
|
|
|
|
|
|
|
|
.more-content {
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
|
|
|
|
|
|
/* Shadow 2 */
|
|
|
|
|
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
}
|
2025-08-29 14:05:27 +08:00
|
|
|
|
</style>
|