Files
lingji-work-fe/src/views/property-marketing/assignment-management/index.vue

967 lines
30 KiB
Vue
Raw Normal View History

2025-08-29 14:05:27 +08:00
<template>
<div class="flex-column justify-between">
<div class="flex justify-between items-start" style="width: 100%">
<div class="flex justify-between items-center" style="width: 100%">
<div class="flex items-center">
<a-date-picker
class="w-188px size-14px"
v-if="choseType === '日'"
@change="onChangeDate"
v-model="dayModel"
format="YYYY年MM月DD日周dd"
/>
<a-week-picker
class="w-188px size-14px"
v-else-if="choseType === '周'"
@change="onChangeWeek"
v-model="weekModel"
2025-08-29 16:39:14 +08:00
format="YYYY年MM月DD日"
2025-08-29 14:05:27 +08:00
/>
<a-month-picker
class="w-188px size-14px"
v-else
@change="onChangeMonth"
v-model="monthModel"
format="YYYY年MM月"
/>
<div class="flex items-center ml-12px">
<a-button class="mr-4px" @click="handlePrev">
<template #icon>
<icon-left />
</template>
</a-button>
<a-button @click="handleToday">今天</a-button>
<a-button class="ml-4px" @click="handleNext">
<template #icon>
<icon-right />
</template>
</a-button>
</div>
<div class="flex items-center ml-12px">
<a-space class="flex justify-between">
<a-dropdown position="bottom" @select="handleSelect">
<a-button class="w-80px flex justify-between">{{ choseType }}<icon-down /></a-button>
<template #content>
<a-doption value="日" class="w-80px"></a-doption>
<a-doption value="周" class="w-80px"></a-doption>
<a-doption value="月" class="w-80px"></a-doption>
</template>
</a-dropdown>
</a-space>
</div>
</div>
</div>
<div class="flex items-start">
<a-trigger
trigger="click"
style="
background-color: #ffffff;
border: 1px solid #d9d9d9;
border-radius: 4px;
box-shadow: #00000010 0px 2px 8px;
width: 120px;
height: 64px;
padding: 8px;
margin-top: 8px;
"
>
2025-08-30 15:54:54 +08:00
<a-button size="small" class="mr-12px color-scheme-btn" :bordered="false">
2025-08-29 14:05:27 +08:00
<template #icon>
<icon-info-circle-fill size="16" class="color-#55585F" />
</template>
<template #default>颜色示意</template>
</a-button>
<template #content>
<div class="flex items-center mb-8px">
<div
style="background-color: #6d4cfe; width: 16px; height: 16px; margin-right: 5px; border-radius: 4px"
></div>
<div>选题</div>
</div>
<div class="flex items-center">
<div
style="background-color: #ffae00; width: 16px; height: 16px; margin-right: 5px; border-radius: 4px"
></div>
<div>内容稿件</div>
</div>
</template>
</a-trigger>
2025-09-03 18:22:51 +08:00
<a-trigger
trigger="click"
style="
background-color: #ffffff;
border: 1px solid #d9d9d9;
border-radius: 4px;
box-shadow: #00000010 0px 2px 8px;
width: 308px;
max-height: 400px;
overflow-y: auto;
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
placeholder="请选择运营人员"
:options="operators"
v-model="query.operator"
@change="
(val) => {
handleFilterChange('operator_id', val, operators);
}
"
class="!w-200px"
/>
</a-space>
</div>
<div class="flex items-center mb-24px">
<div class="w-70px">发布平台</div>
<a-space class="w-200px">
<CommonSelect
:options="platformOptions"
v-model="query.platform"
@change="
(val) => {
handleFilterChange('platform', val, platformOptions);
}
"
class="!w-200px"
placeholder="请选择发布平台"
/>
</a-space>
</div>
<div class="flex items-center">
<div class="w-80px">账号名称</div>
<a-space class="w-200px">
<CommonSelect
v-model="query.tag_ids"
:options="accountList"
@change="handleSearch"
class="!w-200px"
placeholder="请选择账号名称"
/>
</a-space>
</div>
</div>
2025-08-29 14:05:27 +08:00
</template>
2025-09-03 18:22:51 +08:00
</a-trigger>
2025-08-29 14:05:27 +08:00
</div>
</div>
<div class="flex justify-between items-start mt-16px" style="width: 100%">
2025-09-03 17:57:09 +08:00
<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
:src="getPlatformIcon(record.platform)"
style="border-radius: 8px; width: 16px; height: 16px; margin-right: 8px"
/>
{{ record.name || '-' }}
</div>
</template>
2025-08-29 14:05:27 +08:00
2025-09-03 17:57:09 +08:00
<!-- 动态日期列渲染 -->
<template #dateCell="{ record, column }">
<div v-if="record[column.dataIndex] && record[column.dataIndex].length > 0" class="task-container">
<div v-if="record[column.dataIndex].length >= 3" class="task-more">
<div
:key="record[column.dataIndex][0].id"
class="task-item size-12px"
:title="record[column.dataIndex][0].name || '-'"
>
<a-trigger trigger="click" position="br">
<div class="task-item size-12px">
<div class="size-12px color-#211F24 mr-4px">
{{ timestampToTime(record[column.dataIndex][0].execution_time) }}
</div>
<div
class="size-12px"
:style="{
color: getTaskColor(
record[column.dataIndex][0].type,
record[column.dataIndex][0].execution_time,
),
}"
style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis"
>
{{ formatTaskName(record[column.dataIndex][0].name) }}
</div>
</div>
<template #content>
<TaskDetail
:task="record[column.dataIndex][0]"
:record="record"
:get-platform-icon="getPlatformIcon"
@edit-time="handleModifyTime"
@delete="handleDelete"
@delete-task="handleDelete"
@gotoDetail="handleGoToDetail"
/>
</template>
</a-trigger>
</div>
2025-08-30 15:54:54 +08:00
<a-trigger trigger="click" position="br">
2025-09-03 17:57:09 +08:00
<div class="size-12px color-#8f959f" style="padding: 0px 8px">
还有{{ record[column.dataIndex].length - 1 }}
</div>
<template #content>
<div
class="flex flex-col items-start"
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>
<div class="flex items-start mb-8px">
<div class="size-12px color-#211F24 mr-4px">
{{ timestampToTime(task.execution_time) }}
</div>
<div class="size-12px" :style="{ color: getTaskColor(task.type, task.execution_time) }">
{{ task.name || '未命名' }}
</div>
</div>
<template #content>
<TaskDetail
:task="task"
:record="record"
:get-platform-icon="getPlatformIcon"
@edit-time="handleModifyTime"
@delete="handleDelete"
@delete-task="handleDelete"
@gotoDetail="handleGoToDetail"
/>
</template>
</a-trigger>
</div>
</div>
</template>
</a-trigger>
</div>
<div v-else v-for="task in record[column.dataIndex]" :key="task.id" :title="task.name || '-'">
<a-trigger trigger="click" align-point>
<div class="task-item">
2025-08-30 15:54:54 +08:00
<div class="size-12px color-#211F24 mr-4px">
2025-09-03 17:57:09 +08:00
{{ timestampToTime(task.execution_time) }}
2025-08-30 15:54:54 +08:00
</div>
<div
2025-09-03 17:57:09 +08:00
:style="{ color: getTaskColor(task.type, task.execution_time) }"
2025-08-30 15:54:54 +08:00
style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis"
>
2025-09-03 17:57:09 +08:00
{{ formatTaskName(task.name) }}
2025-08-30 15:54:54 +08:00
</div>
</div>
<template #content>
2025-09-02 14:30:42 +08:00
<TaskDetail
2025-09-03 17:57:09 +08:00
:task="task"
2025-09-02 14:30:42 +08:00
:record="record"
:get-platform-icon="getPlatformIcon"
@edit-time="handleModifyTime"
@delete="handleDelete"
2025-09-03 17:57:09 +08:00
@gotoDetail="handleGoToDetail"
2025-09-02 14:30:42 +08:00
/>
2025-08-30 15:54:54 +08:00
</template>
</a-trigger>
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>
<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-02 14:30:42 +08:00
<a-modal v-model:visible="showModal" @ok="handleOk" @cancel="handleCancel" ok-text="确认删除">
<template #title> {{ deleteTitle }} </template>
<div>
{{ deleteContent }}
</div>
</a-modal>
2025-08-29 14:05:27 +08:00
</template>
<script lang="ts" setup>
2025-08-29 16:39:14 +08:00
import { ref, reactive, onMounted, watch, computed, nextTick } from 'vue';
import type { TableColumnData } from '@arco-design/web-vue';
2025-09-03 17:57:09 +08:00
import { getTaskSchedules, delTaskSchedules, getTaskSchedulesDetail } from '@/api/all/assignment-management';
import { fetchAccountOperators, getMediaAccountList } from '@/api/all/propertyMarketing';
2025-08-29 14:05:27 +08:00
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';
import icon4 from '@/assets/img/platform/icon-sph.png';
import icon5 from '@/assets/img/platform/icon-wb.png';
import icon6 from '@/assets/img/platform/icon-gzh.png';
import icon7 from '@/assets/img/platform/icon-ks.png';
import icon8 from '@/assets/img/platform/icon-bilibili.png';
import DateUtils from '@/utils/DateUtils';
2025-09-02 14:30:42 +08:00
import TaskDetail from './components/TaskDetail.vue';
2025-09-03 17:57:09 +08:00
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) => {
// 获取当前排序的列信息
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) {
if (column.date) {
// 获取格式化的日期字符串
const formattedDate = DateUtils.formatDate(column.date);
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);
2025-09-02 14:30:42 +08:00
const currentTask = ref();
2025-08-30 15:54:54 +08:00
const visible = ref(false);
2025-09-02 14:30:42 +08:00
const deleteTitle = ref('');
const deleteContent = ref('');
const showModal = ref(false);
2025-08-30 15:54:54 +08:00
const modalVisible = ref(false);
const selectedTask = ref<any>(null);
2025-08-30 13:53:53 +08:00
const choseType = ref('周');
2025-08-29 16:39:14 +08:00
const dayModel = ref(new Date());
const weekModel = ref(new Date());
const monthModel = ref(new Date());
2025-08-29 14:05:27 +08:00
const currentDateRange = reactive({
start: '',
end: '',
});
2025-08-29 16:39:14 +08:00
const columns = ref<TableColumnData[]>([]);
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-08-29 14:05:27 +08:00
const platformOptions = ref([
{ value: 0, label: '抖音' },
{ value: 1, label: '小红书' },
{ value: 2, label: 'B站' },
{ value: 3, label: '快手' },
{ value: 4, label: '视频号' },
{ value: 5, label: '微博' },
{ value: 6, label: '公众号' },
]);
const query = reactive({
page: 1,
page_size: 20,
platform: '',
2025-09-03 18:22:51 +08:00
operator_ids: undefined,
2025-08-29 14:05:27 +08:00
name: '',
2025-09-03 18:22:51 +08:00
top_execution_time: '' as string | undefined,
execution_time: undefined,
2025-09-03 17:57:09 +08:00
operator: '',
2025-09-03 18:22:51 +08:00
ids: [],
2025-08-29 14:05:27 +08:00
});
2025-09-02 14:30:42 +08:00
// 处理删除操作
const handleDelete = (task: any) => {
currentTask.value = task;
if (task.type == 1) {
deleteTitle.value = '删除内容稿件排期';
} else {
deleteTitle.value = '删除选题排期';
}
deleteContent.value = '确认删除“' + task.name + '”吗?';
showModal.value = true;
};
2025-09-03 17:57:09 +08:00
const handleGoToDetail = (task: any) => {
console.log('跳转详情', task);
};
2025-09-02 14:30:42 +08:00
const handleOk = () => {
showModal.value = false;
delTaskSchedules(currentTask.value.id).then(() => {
handleSearch();
});
2025-08-29 14:05:27 +08:00
};
2025-09-02 14:30:42 +08:00
const handleCancel = () => {
showModal.value = false;
};
2025-09-03 17:57:09 +08:00
const handleAddAccount = () => {};
2025-09-02 14:30:42 +08:00
const handleModifyTime = (task: any) => {
console.log('修改时间', task);
// modalVisible.value = false;
// // 重新获取数据
// getTaskSchedules(query).then((res) => {
// data.value = res.data;
// });
2025-08-30 15:54:54 +08:00
};
2025-08-29 14:05:27 +08:00
// 计算当前日期范围内的所有日期,统一返回 number 数组
const currentDateHeaders = computed(() => {
if (choseType.value === '周') {
2025-08-29 16:39:14 +08:00
const specificWeek = DateUtils.getWeekDaysByDate(new Date(weekModel.value), 0);
return specificWeek.map((item) => parseInt(item.day.toString(), 10)); // 转换为数字数组
2025-08-29 14:05:27 +08:00
} else if (choseType.value === '月') {
2025-08-29 16:39:14 +08:00
const date = new Date(monthModel.value);
const tabTitle = DateUtils.getDaysAndWeekdays(date.getFullYear(), date.getMonth());
return tabTitle.map((item) => parseInt(item.day.toString(), 10)); // 转换为数字数组
2025-08-29 14:05:27 +08:00
} else {
// 日维度,返回当天的日期数字
const day = new Date(dayModel.value).getDate();
return [day];
}
});
// 获取平台图标
const getPlatformIcon = (platform: number) => {
const platformIcons: Record<number, any> = {
0: icon1, // 抖音
1: icon2, // 小红书
2: icon8, // B站
3: icon7, // 快手
4: icon4, // 视频号
5: icon5, // 微博
6: icon6, // 公众号
};
return platformIcons[platform] || icon3; // 默认图标
};
// 获取任务颜色
2025-08-30 15:54:54 +08:00
const getTaskColor = (taskType: number, executionTime: number) => {
// 判断任务是否已过期
const isExpired = executionTime * 1000 < Date.now();
// 如果已过期,根据任务类型返回对应颜色
if (isExpired) {
return taskType === 0 ? '#A794FE' : '#FFCF66';
}
// 未过期根据API文档type: 0=选题1=内容稿件
2025-08-29 14:05:27 +08:00
return taskType === 0 ? '#6d4cfe' : '#ffae00';
};
// 格式化任务名称
const formatTaskName = (name: string) => {
if (!name) return '未命名';
return name.length > 8 ? name.substring(0, 8) + '...' : name;
};
// 时间戳转日期格式,并提取日期数字
const timestampToDayNumber = (timestamp: number) => {
const date = new Date(timestamp * 1000); // 假设时间戳是秒级
2025-08-29 16:39:14 +08:00
return date.getDate(); // 返回数字类型的日期
2025-08-29 14:05:27 +08:00
};
// 时间戳转时间格式 (HH:MM)
const timestampToTime = (timestamp: number): string => {
const date = new Date(timestamp * 1000); // 假设时间戳是秒级
// 获取小时和分钟
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
return `${hours}:${minutes}`;
};
// 处理表格数据,使其与动态表头匹配
const processTableData = (apiData: any[]) => {
const processedData: any[] = [];
// 处理每条账号数据
apiData.forEach((account) => {
const rowData: any = {
id: account.id,
name: account.name,
platform: account.platform,
};
// 初始化所有日期列为空数组
currentDateHeaders.value.forEach((day) => {
rowData[day] = [];
});
// 将任务按日期分组
if (account.task_schedules && account.task_schedules.length > 0) {
account.task_schedules.forEach((task: any) => {
const taskDay = timestampToDayNumber(task.execution_time);
// 如果这个日期在当前表头中,则添加到对应列
if (currentDateHeaders.value.includes(taskDay)) {
rowData[taskDay].push({
id: task.id,
name: task.name,
type: task.type,
execution_time: task.execution_time,
});
}
});
}
processedData.push(rowData);
});
return processedData;
};
// 设置日期范围
const setDateRange = () => {
if (choseType.value === '周') {
const weekRange = DateUtils.getWeekRangeByDate(new Date(weekModel.value));
currentDateRange.start = weekRange.startFormatted;
currentDateRange.end = weekRange.endFormatted;
query.execution_time = [currentDateRange.start, currentDateRange.end];
} else if (choseType.value === '月') {
const monthRange = DateUtils.getMonthRangeByYearMonth(
new Date(monthModel.value).getFullYear(),
2025-08-29 16:39:14 +08:00
new Date(monthModel.value).getMonth() + 1,
2025-08-29 14:05:27 +08:00
);
currentDateRange.start = monthRange.startFormatted;
currentDateRange.end = monthRange.endFormatted;
query.execution_time = [currentDateRange.start, currentDateRange.end];
} else {
// 日维度
2025-08-29 16:39:14 +08:00
const date = new Date(dayModel.value);
currentDateRange.start = DateUtils.formatDate(date);
currentDateRange.end = DateUtils.formatDate(date);
2025-08-29 14:05:27 +08:00
query.execution_time = [currentDateRange.start, currentDateRange.end];
}
};
// 设置table的头部
const setTableSpecific = () => {
columns.value = [
{
title: '账号与发布平台',
slotName: 'name',
width: 150,
2025-08-30 13:53:53 +08:00
ellipsis: true,
tooltip: true,
2025-08-29 14:05:27 +08:00
},
];
let dateHeaders: any[] = [];
if (choseType.value === '周') {
2025-08-29 16:39:14 +08:00
const specificWeek = DateUtils.getWeekDaysByDate(new Date(weekModel.value), 0);
2025-08-29 14:05:27 +08:00
dateHeaders = specificWeek;
} else if (choseType.value === '月') {
2025-08-29 16:39:14 +08:00
const date = new Date(monthModel.value);
const tabTitle = DateUtils.getDaysAndWeekdays(date.getFullYear(), date.getMonth());
2025-08-30 13:53:53 +08:00
// 为月视图添加日期对象,以便后续判断是否为周末
dateHeaders = tabTitle.map((item) => {
const dayDate = new Date(date.getFullYear(), date.getMonth(), item.day);
return {
...item,
date: dayDate,
};
});
2025-08-29 14:05:27 +08:00
} else {
// 日维度
const date = new Date(dayModel.value);
2025-08-29 16:39:14 +08:00
const day = date.getDate();
2025-08-29 14:05:27 +08:00
const weekday = DateUtils.formatDateToWeekdayDay(date);
2025-08-30 13:53:53 +08:00
dateHeaders = [{ day: day, weekday, date: date }];
2025-08-29 14:05:27 +08:00
}
2025-09-03 17:57:09 +08:00
// 判断是否为今天
const isToday = (date: Date) => {
const today = new Date();
return (
date.getDate() === today.getDate() &&
date.getMonth() === today.getMonth() &&
date.getFullYear() === today.getFullYear()
);
};
2025-08-29 14:05:27 +08:00
// 添加日期列
dateHeaders.forEach((item) => {
2025-08-30 13:53:53 +08:00
// 检查是否为周末周日为0周六为6
const isWeekend = item.date ? item.date.getDay() === 0 || item.date.getDay() === 6 : false;
2025-09-03 17:57:09 +08:00
const todayFlag = item.date ? isToday(item.date) : false;
2025-08-29 14:05:27 +08:00
columns.value.push({
title: `${item.weekday}`,
dataIndex: item.day, // 使用日期数字作为dataIndex
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-03 17:57:09 +08:00
sorter: true, // 禁用默认排序
2025-08-29 14:05:27 +08:00
},
2025-09-03 17:57:09 +08:00
// 存储额外信息用于表头渲染
weekday: item.weekday,
todayFlag: todayFlag,
2025-08-30 13:53:53 +08:00
// 如果是周末,添加自定义样式
cellClass: isWeekend ? 'weekend-column' : '',
2025-08-29 14:05:27 +08:00
});
});
};
2025-08-29 16:39:14 +08:00
// 日期变化处理(日维度)
2025-08-29 14:05:27 +08:00
const onChangeDate = (val: any) => {
if (val) {
2025-08-29 16:39:14 +08:00
// 确保val是Date对象
const selectedDate = val instanceof Date ? val : new Date(val);
dayModel.value = selectedDate;
// 更新日期范围和其他相关状态
2025-08-29 14:05:27 +08:00
setDateRange();
setTableSpecific();
2025-08-29 16:39:14 +08:00
// 在下一个tick中执行搜索确保DOM更新完成
nextTick(() => {
handleSearch();
});
2025-08-29 14:05:27 +08:00
}
};
2025-08-29 16:39:14 +08:00
// 日期变化处理(周维度)
2025-08-29 14:05:27 +08:00
const onChangeWeek = (val: any) => {
if (val) {
2025-08-29 16:39:14 +08:00
// 确保val是Date对象
const selectedDate = val instanceof Date ? val : new Date(val);
weekModel.value = selectedDate;
// 更新日期范围和其他相关状态
setDateRange();
2025-08-29 14:05:27 +08:00
setTableSpecific();
2025-08-29 16:39:14 +08:00
// 在下一个tick中执行搜索确保DOM更新完成
nextTick(() => {
handleSearch();
});
2025-08-29 14:05:27 +08:00
}
};
const onChangeMonth = (val: any) => {
2025-08-29 16:39:14 +08:00
if (typeof val === 'string') {
val = DateUtils.MonthStrToDate(val);
}
2025-08-29 14:05:27 +08:00
if (val) {
2025-08-29 16:39:14 +08:00
// 确保val是Date对象
const selectedDate = val instanceof Date ? val : new Date(val);
monthModel.value = selectedDate;
// 更新日期范围和其他相关状态
setDateRange();
2025-08-29 14:05:27 +08:00
setTableSpecific();
2025-08-29 16:39:14 +08:00
// 在下一个tick中执行搜索确保DOM更新完成
nextTick(() => {
handleSearch();
});
2025-08-29 14:05:27 +08:00
}
};
// 设置维度
const handleSelect = (val: string) => {
choseType.value = val;
setDateRange();
setTableSpecific();
2025-08-29 16:39:14 +08:00
nextTick(() => {
handleSearch();
});
2025-08-29 14:05:27 +08:00
};
// 日期导航
const handlePrev = () => {
// 根据当前维度向前导航
if (choseType.value === '周') {
const prevWeek = new Date(weekModel.value);
prevWeek.setDate(prevWeek.getDate() - 7);
2025-08-29 16:39:14 +08:00
onChangeWeek(prevWeek);
2025-08-29 14:05:27 +08:00
} else if (choseType.value === '月') {
const prevMonth = new Date(monthModel.value);
prevMonth.setMonth(prevMonth.getMonth() - 1);
2025-08-29 16:39:14 +08:00
onChangeMonth(prevMonth);
2025-08-29 14:05:27 +08:00
} else {
const prevDay = new Date(dayModel.value);
prevDay.setDate(prevDay.getDate() - 1);
2025-08-29 16:39:14 +08:00
onChangeDate(prevDay);
2025-08-29 14:05:27 +08:00
}
};
const handleNext = () => {
// 根据当前维度向后导航
if (choseType.value === '周') {
const nextWeek = new Date(weekModel.value);
nextWeek.setDate(nextWeek.getDate() + 7);
2025-08-29 16:39:14 +08:00
onChangeWeek(nextWeek);
2025-08-29 14:05:27 +08:00
} else if (choseType.value === '月') {
const nextMonth = new Date(monthModel.value);
nextMonth.setMonth(nextMonth.getMonth() + 1);
2025-08-29 16:39:14 +08:00
onChangeMonth(nextMonth);
2025-08-29 14:05:27 +08:00
} else {
const nextDay = new Date(dayModel.value);
nextDay.setDate(nextDay.getDate() + 1);
2025-08-29 16:39:14 +08:00
onChangeDate(nextDay);
2025-08-29 14:05:27 +08:00
}
};
const handleToday = () => {
// 回到今天
const today = new Date();
if (choseType.value === '周') {
2025-08-29 16:39:14 +08:00
onChangeWeek(today);
2025-08-29 14:05:27 +08:00
} else if (choseType.value === '月') {
2025-08-29 16:39:14 +08:00
onChangeMonth(today);
2025-08-29 14:05:27 +08:00
} else {
2025-08-29 16:39:14 +08:00
onChangeDate(today);
2025-08-29 14:05:27 +08:00
}
};
2025-09-03 17:57:09 +08:00
// 处理筛选项选择事件
const handleFilterChange = (field: string, value: any, options?: any[]) => {
console.log(`筛选项 ${field} 发生变化:`, value);
// 根据不同的筛选字段执行不同的操作
switch (field) {
case 'operator_id':
2025-09-03 18:22:51 +08:00
console.log('运营人员选择:', value, typeof value, Array.isArray(value), options);
2025-09-03 17:57:09 +08:00
// 查找选中的运营人员完整信息
if (options && value) {
if (Array.isArray(value)) {
// 多选情况
2025-09-03 18:22:51 +08:00
const selectedOperators = options.filter((op) => value.includes(op.name)).map((op) => op.value);
query.operator_ids = selectedOperators;
2025-09-03 17:57:09 +08:00
console.log('选中的运营人员完整信息(多选):', selectedOperators);
2025-09-03 18:22:51 +08:00
handleSearch();
break;
2025-09-03 17:57:09 +08:00
}
}
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);
}
};
2025-08-29 14:05:27 +08:00
// 获取数据
const handleSearch = () => {
2025-09-03 18:22:51 +08:00
console.log('handleSearch查询参数:', query);
2025-08-29 14:05:27 +08:00
query.page = pageInfo.page;
query.page_size = pageInfo.page_size;
getTaskSchedules(query)
.then((response) => {
if (response.data) {
// 根据API响应结构调整
const apiData = response.data.data || response.data;
data.value = processTableData(apiData);
2025-09-03 17:57:09 +08:00
pageInfo.value.total = response.data.total || apiData.length;
2025-08-29 14:05:27 +08:00
}
})
.catch((error) => {
data.value = [];
});
};
// 获取运营人员
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) {
console.error('获取运营人员数据失败:', error);
}
};
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,
name: account.name,
}));
}
} catch (error) {}
};
2025-08-29 14:05:27 +08:00
// 监听日期维度变化
watch(choseType, (newVal) => {
2025-08-29 16:39:14 +08:00
// 重置对应模型的值为当前日期
const now = new Date();
if (newVal === '日') {
dayModel.value = now;
} else if (newVal === '周') {
weekModel.value = now;
} else if (newVal === '月') {
monthModel.value = now;
}
nextTick(() => {
setDateRange();
setTableSpecific();
handleSearch();
});
2025-08-29 14:05:27 +08:00
});
onMounted(() => {
setDateRange();
setTableSpecific();
handleSearch();
getOperators();
2025-09-03 17:57:09 +08:00
getAccountList();
2025-08-29 14:05:27 +08:00
});
</script>
<style scoped>
.content {
background: white;
width: 100%;
height: 600px;
padding: 12px;
}
.arco-dropdown-open .arco-icon-down {
transform: rotate(180deg);
}
.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-08-30 13:53:53 +08:00
height: 30px;
display: flex;
align-items: center;
justify-content: center;
2025-08-29 14:05:27 +08:00
}
2025-08-30 13:53:53 +08:00
/* 周末列背景色 */
:deep(.weekend-column) {
background-color: #fbfaff !important;
2025-08-29 14:05:27 +08:00
}
2025-08-30 15:54:54 +08:00
/* 颜色示意按钮样式 */
:deep(.color-scheme-btn) {
border: none !important;
background: none !important;
box-shadow: none !important;
}
.cell-detail {
background-color: #fff;
border: 1px solid #d9d9d9;
border-radius: 4px;
box-shadow: #00000010 0px 2px 8px;
padding: 8px 16px;
margin-top: 8px;
}
.opt-btn {
font-size: 12px;
width: 138px;
height: 28px;
background-color: #f2f3f5;
text-align: center;
line-height: 28px;
border-radius: 4px;
margin-right: 12px;
}
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-08-29 14:05:27 +08:00
</style>