feat(M08-B): 补任务事件流水

This commit is contained in:
Codex
2026-06-30 18:26:53 +08:00
parent 957a29b11e
commit 986a90806b
12 changed files with 178 additions and 14 deletions
+8
View File
@@ -3,6 +3,7 @@ import type {
CleaningSettlementDetail,
CleaningStatistics,
CleaningTask,
CleaningTaskEvent,
CleaningTaskMember,
ManagedUser,
PageResult,
@@ -170,6 +171,13 @@ export function listCleaningTaskMembers(session: ApiSession, taskId: string) {
);
}
export function listCleaningTaskEvents(session: ApiSession, taskId: string) {
return request<CleaningTaskEvent[]>(
session,
`/cleaning/tasks/${encodeURIComponent(taskId)}/events`
);
}
export function addCleaningTaskMember(
session: ApiSession,
taskId: string,
+51 -4
View File
@@ -280,6 +280,29 @@
<span>提交<strong>{{ shortDate(detailDialog.task.submittedAt) }}</strong></span>
<span>完成<strong>{{ shortDate(detailDialog.task.completedAt) }}</strong></span>
</div>
<section class="stat-block">
<header>
<h3>操作流水</h3>
<span>最近 {{ detailDialog.events.length }} </span>
</header>
<el-table :data="detailDialog.events" size="small" v-loading="detailDialog.loadingEvents">
<el-table-column prop="action" label="动作" width="130" />
<el-table-column label="状态" width="150">
<template #default="{ row }">
{{ compactText(row.fromStatus) }} {{ row.toStatus }}
</template>
</el-table-column>
<el-table-column prop="actorId" label="操作人" width="100">
<template #default="{ row }">{{ compactText(row.actorId) }}</template>
</el-table-column>
<el-table-column prop="note" label="备注" min-width="160">
<template #default="{ row }">{{ compactText(row.note) }}</template>
</el-table-column>
<el-table-column prop="createdAt" label="时间" width="130">
<template #default="{ row }">{{ shortDate(row.createdAt) }}</template>
</el-table-column>
</el-table>
</section>
<div class="photo-grid" v-if="detailDialog.task.photoUrls.length">
<el-image
v-for="url in detailDialog.task.photoUrls"
@@ -316,11 +339,19 @@ import {
import { ElMessage } from 'element-plus';
import {
addCleaningTaskMember,
listCleaningTaskEvents,
listCleaningTaskMembers,
removeCleaningTaskMember
} from '../api';
import { compactText, money, shortDate } from '../format';
import type { CleaningTask, CleaningTaskMember, ManagedUser, PageResult, TaskStatus } from '../types';
import type {
CleaningTask,
CleaningTaskEvent,
CleaningTaskMember,
ManagedUser,
PageResult,
TaskStatus
} from '../types';
const props = defineProps<{
session: { token: string };
@@ -358,9 +389,16 @@ const filterDraft = reactive({ storeId: props.filters.storeId, cleanerUserId: pr
const reclaimForm = reactive({ olderThanMinutes: 60, limit: 20 });
const assignDialog = reactive({ open: false, taskId: '', cleanerUserId: '', note: '' });
const rejectDialog = reactive({ open: false, taskId: '', reason: '' });
const detailDialog = reactive<{ open: boolean; task: CleaningTask | null }>({
const detailDialog = reactive<{
open: boolean;
loadingEvents: boolean;
task: CleaningTask | null;
events: CleaningTaskEvent[];
}>({
open: false,
task: null
loadingEvents: false,
task: null,
events: []
});
const memberDialog = reactive({
open: false,
@@ -401,9 +439,18 @@ function submitFilters() {
});
}
function openDetail(row: CleaningTask) {
async function openDetail(row: CleaningTask) {
detailDialog.open = true;
detailDialog.task = row;
detailDialog.events = [];
detailDialog.loadingEvents = true;
try {
detailDialog.events = await listCleaningTaskEvents(props.session, row.id);
} catch (error) {
ElMessage.error(error instanceof Error ? error.message : '任务流水加载失败');
} finally {
detailDialog.loadingEvents = false;
}
}
function openAssign(row: CleaningTask) {
+12
View File
@@ -75,6 +75,18 @@ export interface CleaningTaskMember {
settledAt?: string | null;
}
export interface CleaningTaskEvent {
id: string;
taskId: string;
fromStatus: TaskStatus | null;
toStatus: TaskStatus;
action: string;
actorId: string;
traceId: string;
note: string;
createdAt: string;
}
export interface CleaningSettlement {
id: string;
settlementNo: string;