优化日程增加文件上传功能
This commit is contained in:
@@ -132,6 +132,8 @@
|
||||
<div class="day-sub">
|
||||
{{ selectedItems.length }} 项日程<template v-if="pendingCount > 0"
|
||||
>,{{ pendingCount }} 项未完成</template
|
||||
><template v-if="selectedPendingIds.length > 0"
|
||||
>,已选 {{ selectedPendingIds.length }} 项</template
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
@@ -141,7 +143,9 @@
|
||||
size="small"
|
||||
:icon="Promotion"
|
||||
@click="handleCarryPending"
|
||||
>延期未完成</el-button
|
||||
>延期<template v-if="selectedPendingIds.length > 0"
|
||||
>({{ selectedPendingIds.length }})</template
|
||||
></el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@@ -160,8 +164,11 @@
|
||||
:style="{ '--item-color': item.color }"
|
||||
>
|
||||
<el-checkbox
|
||||
:model-value="item.status === 1"
|
||||
@change="toggleFinish(item)"
|
||||
:model-value="selectedIds.includes(item.id)"
|
||||
:disabled="item.status === 1"
|
||||
:title="item.status === 1 ? '已完成的日程无需延期' : '勾选后批量延期'"
|
||||
@click.stop
|
||||
@change="checked => toggleSelect(item.id, checked)"
|
||||
/>
|
||||
<div class="day-item-main" @click="openDetail(item)">
|
||||
<div class="day-item-title" :class="{ done: item.status === 1 }">
|
||||
@@ -205,6 +212,9 @@
|
||||
/>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="finish">{{
|
||||
item.status === 1 ? "取消完成" : "标记完成"
|
||||
}}</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
command="postpone"
|
||||
:disabled="item.status === 1"
|
||||
@@ -342,6 +352,7 @@
|
||||
@finish="handleDetailFinish"
|
||||
@revert="handleDetailRevert"
|
||||
@postpone="handleDetailPostpone"
|
||||
@changed="reloadAll"
|
||||
/>
|
||||
|
||||
<!-- 延期对话框 -->
|
||||
@@ -370,6 +381,7 @@ import ScheduleDetail from "./components/detail.vue";
|
||||
import SchedulePostpone from "./components/postponeDialog.vue";
|
||||
import {
|
||||
carryPendingSchedules,
|
||||
carrySchedule,
|
||||
deleteSchedule,
|
||||
finishSchedule,
|
||||
getScheduleList,
|
||||
@@ -475,6 +487,10 @@ const calendarMap = computed(() => {
|
||||
}
|
||||
map[item.schedule_date].push(item);
|
||||
}
|
||||
// 同一天内按紧急程度排序:紧急 > 重要 > 普通
|
||||
for (const date of Object.keys(map)) {
|
||||
map[date].sort(compareByPriority);
|
||||
}
|
||||
return map;
|
||||
});
|
||||
|
||||
@@ -487,6 +503,32 @@ const pendingCount = computed(
|
||||
() => selectedItems.value.filter(item => item.status !== 1).length
|
||||
);
|
||||
|
||||
// ---------- 多选(勾选后批量延期,区别于"完成"操作) ----------
|
||||
// 只记录 id,数据刷新后自动失效
|
||||
const selectedIds = ref([]);
|
||||
|
||||
// 已勾选且仍未完成的日程,只有这些才会被延期
|
||||
const selectedPendingIds = computed(() =>
|
||||
selectedIds.value.filter(id => {
|
||||
const item = selectedItems.value.find(i => i.id === id);
|
||||
return item && item.status !== 1;
|
||||
})
|
||||
);
|
||||
|
||||
function toggleSelect(id, checked) {
|
||||
const set = new Set(selectedIds.value);
|
||||
if (checked) {
|
||||
set.add(id);
|
||||
} else {
|
||||
set.delete(id);
|
||||
}
|
||||
selectedIds.value = [...set];
|
||||
}
|
||||
|
||||
function clearSelection() {
|
||||
selectedIds.value = [];
|
||||
}
|
||||
|
||||
const selectedDateLabel = computed(() => {
|
||||
const [y, m, d] = selectedDate.value.split("-").map(Number);
|
||||
const week = "日一二三四五六"[new Date(y, m - 1, d).getDay()];
|
||||
@@ -516,6 +558,8 @@ async function loadCalendarData() {
|
||||
...item,
|
||||
schedule_date: normDate(item.schedule_date)
|
||||
}));
|
||||
// 数据刷新后旧的勾选已失效(id 可能已因延期重新生成),统一清空
|
||||
clearSelection();
|
||||
}
|
||||
|
||||
function changeMonth(delta) {
|
||||
@@ -650,6 +694,8 @@ function handleDetailPostpone(item) {
|
||||
function handleItemCommand(cmd, item) {
|
||||
if (cmd === "postpone") {
|
||||
openPostpone(item);
|
||||
} else if (cmd === "finish") {
|
||||
toggleFinish(item);
|
||||
} else if (cmd === "edit") {
|
||||
openEdit(item);
|
||||
} else if (cmd === "delete") {
|
||||
@@ -670,23 +716,50 @@ function openPostpone(item) {
|
||||
postponeVisible.value = true;
|
||||
}
|
||||
|
||||
// 批量延期:把选中日期的全部未完成日程一次性延期到下一天
|
||||
// 批量延期:优先延期勾选的日程;未勾选时延期选中日期的全部未完成日程
|
||||
async function handleCarryPending() {
|
||||
if (pendingCount.value === 0) {
|
||||
const ids = selectedPendingIds.value;
|
||||
const count = ids.length || pendingCount.value;
|
||||
if (count === 0) {
|
||||
return;
|
||||
}
|
||||
// 目标日期取"选定日期+1天",但不早于今天,避免把过去的任务再延到过去
|
||||
const nextDay = addDays(selectedDate.value, 1);
|
||||
const target = nextDay < todayStr() ? todayStr() : nextDay;
|
||||
const tip = ids.length
|
||||
? `将选中的 ${count} 条日程延期到 ${target}?当天这些日程会标记为已完成。`
|
||||
: `将 ${selectedDate.value} 的 ${count} 条未完成日程延期到 ${target}?当天这些日程会标记为已完成。`;
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`将 ${selectedDate.value} 的 ${pendingCount.value} 条未完成日程延期到 ${target}?当天这些日程会标记为已完成。`,
|
||||
"批量延期",
|
||||
{ type: "warning", confirmButtonText: "延期", cancelButtonText: "取消" }
|
||||
);
|
||||
await ElMessageBox.confirm(tip, "批量延期", {
|
||||
type: "warning",
|
||||
confirmButtonText: "延期",
|
||||
cancelButtonText: "取消"
|
||||
});
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
// 有勾选:逐条调用单条延期接口(后端批量接口只支持按日期整批延期)
|
||||
if (ids.length) {
|
||||
let success = 0;
|
||||
for (const id of ids) {
|
||||
const res = await carrySchedule(id, { target_date: target });
|
||||
if (res?.code === 200) {
|
||||
success++;
|
||||
}
|
||||
}
|
||||
const skipped = ids.length - success;
|
||||
if (success) {
|
||||
ElMessage.success(
|
||||
`已延期 ${success} 条${skipped ? `,跳过 ${skipped} 条` : ""}`
|
||||
);
|
||||
} else {
|
||||
ElMessage.warning("所选日程均无法延期");
|
||||
}
|
||||
await reloadAll();
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await carryPendingSchedules({
|
||||
date: selectedDate.value,
|
||||
target_date: target
|
||||
@@ -769,6 +842,25 @@ function priorityTagType(priority) {
|
||||
return { 1: "warning", 2: "danger" }[priority] || "info";
|
||||
}
|
||||
|
||||
// 排序权重:紧急(2) > 重要(1) > 普通(0)
|
||||
function priorityWeight(priority) {
|
||||
return { 2: 3, 1: 2 }[priority] || 1;
|
||||
}
|
||||
|
||||
// 同天内排序:先按紧急程度降序,再按开始时间升序(全天排在最前),最后按 id
|
||||
function compareByPriority(a, b) {
|
||||
const diff = priorityWeight(b.priority) - priorityWeight(a.priority);
|
||||
if (diff !== 0) {
|
||||
return diff;
|
||||
}
|
||||
const ta = a.all_day === 1 ? "00:00" : a.start_time || "";
|
||||
const tb = b.all_day === 1 ? "00:00" : b.start_time || "";
|
||||
if (ta !== tb) {
|
||||
return ta < tb ? -1 : 1;
|
||||
}
|
||||
return (a.id || 0) - (b.id || 0);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadStats();
|
||||
loadCalendarData();
|
||||
@@ -1038,7 +1130,7 @@ onMounted(() => {
|
||||
|
||||
/* 选中日期侧栏 */
|
||||
.day-panel {
|
||||
width: 320px;
|
||||
width: 400px;
|
||||
flex-shrink: 0;
|
||||
background: #fff;
|
||||
border: 1px solid #ebeef5;
|
||||
|
||||
Reference in New Issue
Block a user