feat(M08-B): 补批量验收驳回
This commit is contained in:
@@ -106,7 +106,9 @@
|
||||
@page-change="changeTaskPage"
|
||||
@assign="handleAssign"
|
||||
@complete="handleComplete"
|
||||
@complete-many="handleCompleteMany"
|
||||
@reject="handleReject"
|
||||
@reject-many="handleRejectMany"
|
||||
@reclaim="handleReclaim"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
@@ -411,6 +413,15 @@ async function handleComplete(input: { taskId: string; note?: string }) {
|
||||
}, '已验收');
|
||||
}
|
||||
|
||||
async function handleCompleteMany(input: { taskIds: string[]; note?: string }) {
|
||||
await runAction(async () => {
|
||||
for (const taskId of input.taskIds) {
|
||||
await completeCleaningTask(session.value, taskId, input.note);
|
||||
}
|
||||
await Promise.all([loadTasks(), loadStatistics()]);
|
||||
}, `已批量验收 ${input.taskIds.length} 个任务`);
|
||||
}
|
||||
|
||||
async function handleReject(input: { taskId: string; reason: string }) {
|
||||
await runAction(async () => {
|
||||
await rejectCleaningTask(session.value, input.taskId, input.reason);
|
||||
@@ -418,6 +429,15 @@ async function handleReject(input: { taskId: string; reason: string }) {
|
||||
}, '已驳回');
|
||||
}
|
||||
|
||||
async function handleRejectMany(input: { taskIds: string[]; reason: string }) {
|
||||
await runAction(async () => {
|
||||
for (const taskId of input.taskIds) {
|
||||
await rejectCleaningTask(session.value, taskId, input.reason);
|
||||
}
|
||||
await Promise.all([loadTasks(), loadStatistics()]);
|
||||
}, `已批量驳回 ${input.taskIds.length} 个任务`);
|
||||
}
|
||||
|
||||
async function handleReclaim(input: { olderThanMinutes: number; limit: number }) {
|
||||
await runAction(async () => {
|
||||
await reclaimCleaningTimeouts(session.value, input);
|
||||
|
||||
@@ -34,6 +34,22 @@
|
||||
<el-button :icon="Search" @click="submitFilters">筛选</el-button>
|
||||
</div>
|
||||
<div class="toolbar-actions">
|
||||
<el-button
|
||||
type="success"
|
||||
:icon="BadgeCheck"
|
||||
:disabled="selectedSubmittedCount === 0"
|
||||
@click="submitBatchComplete"
|
||||
>
|
||||
批量验收
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Undo2"
|
||||
:disabled="selectedSubmittedCount === 0"
|
||||
@click="openBatchReject"
|
||||
>
|
||||
批量驳回
|
||||
</el-button>
|
||||
<el-popover trigger="click" width="280">
|
||||
<template #reference>
|
||||
<el-button :icon="RotateCcw">回收</el-button>
|
||||
@@ -56,7 +72,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-table :data="items" :loading="loading" class="data-table" row-key="id">
|
||||
<el-table
|
||||
:data="items"
|
||||
:loading="loading"
|
||||
class="data-table"
|
||||
row-key="id"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="44" :selectable="canSelectTask" />
|
||||
<el-table-column prop="taskNo" label="任务" min-width="180" fixed>
|
||||
<template #default="{ row }">
|
||||
<div class="stack">
|
||||
@@ -171,6 +194,29 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="batchRejectDialog.open" title="批量驳回待验收任务" width="460px">
|
||||
<div class="dialog-stack">
|
||||
<el-alert
|
||||
:title="`将驳回 ${selectedSubmittedCount} 个已选择的待验收任务`"
|
||||
type="warning"
|
||||
show-icon
|
||||
:closable="false"
|
||||
/>
|
||||
<el-input
|
||||
v-model="batchRejectDialog.reason"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
maxlength="512"
|
||||
show-word-limit
|
||||
placeholder="请输入统一驳回原因"
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="batchRejectDialog.open = false">取消</el-button>
|
||||
<el-button type="danger" @click="submitBatchReject">批量驳回</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="memberDialog.open" title="协作者管理" width="640px">
|
||||
<div class="dialog-stack">
|
||||
<div class="detail-header">
|
||||
@@ -322,7 +368,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, watch } from 'vue';
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import {
|
||||
BadgeCheck,
|
||||
Check,
|
||||
@@ -372,7 +418,9 @@ const emit = defineEmits<{
|
||||
'page-change': [number];
|
||||
assign: [{ taskId: string; cleanerUserId: string; note?: string }];
|
||||
complete: [{ taskId: string; note?: string }];
|
||||
'complete-many': [{ taskIds: string[]; note?: string }];
|
||||
reject: [{ taskId: string; reason: string }];
|
||||
'reject-many': [{ taskIds: string[]; reason: string }];
|
||||
reclaim: [{ olderThanMinutes: number; limit: number }];
|
||||
}>();
|
||||
|
||||
@@ -387,8 +435,10 @@ const statusOptions = [
|
||||
];
|
||||
const filterDraft = reactive({ storeId: props.filters.storeId, cleanerUserId: props.filters.cleanerUserId });
|
||||
const reclaimForm = reactive({ olderThanMinutes: 60, limit: 20 });
|
||||
const selectedTasks = ref<CleaningTask[]>([]);
|
||||
const assignDialog = reactive({ open: false, taskId: '', cleanerUserId: '', note: '' });
|
||||
const rejectDialog = reactive({ open: false, taskId: '', reason: '' });
|
||||
const batchRejectDialog = reactive({ open: false, reason: '' });
|
||||
const detailDialog = reactive<{
|
||||
open: boolean;
|
||||
loadingEvents: boolean;
|
||||
@@ -411,6 +461,9 @@ const memberDialog = reactive({
|
||||
note: '',
|
||||
members: [] as CleaningTaskMember[]
|
||||
});
|
||||
const selectedSubmittedTasks = computed(() => selectedTasks.value
|
||||
.filter((task) => task.status === 'SUBMITTED'));
|
||||
const selectedSubmittedCount = computed(() => selectedSubmittedTasks.value.length);
|
||||
|
||||
watch(
|
||||
() => props.filters,
|
||||
@@ -425,6 +478,14 @@ function taskTag(status: TaskStatus) {
|
||||
return 'info';
|
||||
}
|
||||
|
||||
function canSelectTask(row: CleaningTask) {
|
||||
return row.status === 'SUBMITTED';
|
||||
}
|
||||
|
||||
function handleSelectionChange(rows: CleaningTask[]) {
|
||||
selectedTasks.value = rows;
|
||||
}
|
||||
|
||||
function cleanerLabel(cleaner: ManagedUser) {
|
||||
const name = cleaner.nickname || `ID ${cleaner.id}`;
|
||||
const phone = cleaner.maskedPhone ? ` · ${cleaner.maskedPhone}` : '';
|
||||
@@ -484,6 +545,35 @@ function submitReject() {
|
||||
rejectDialog.open = false;
|
||||
}
|
||||
|
||||
function submitBatchComplete() {
|
||||
const taskIds = selectedSubmittedTasks.value.map((task) => task.id);
|
||||
if (!taskIds.length) {
|
||||
ElMessage.warning('请选择待验收任务');
|
||||
return;
|
||||
}
|
||||
emit('complete-many', { taskIds, note: '后台批量验收通过' });
|
||||
}
|
||||
|
||||
function openBatchReject() {
|
||||
if (!selectedSubmittedCount.value) {
|
||||
ElMessage.warning('请选择待验收任务');
|
||||
return;
|
||||
}
|
||||
batchRejectDialog.open = true;
|
||||
batchRejectDialog.reason = '';
|
||||
}
|
||||
|
||||
function submitBatchReject() {
|
||||
const reason = batchRejectDialog.reason.trim();
|
||||
if (!reason) {
|
||||
ElMessage.warning('请输入驳回原因');
|
||||
return;
|
||||
}
|
||||
const taskIds = selectedSubmittedTasks.value.map((task) => task.id);
|
||||
emit('reject-many', { taskIds, reason });
|
||||
batchRejectDialog.open = false;
|
||||
}
|
||||
|
||||
async function loadMembers() {
|
||||
memberDialog.loading = true;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user