From c77086ad2d7949ab36dd0c4e0b59907e672dd64f Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期五, 18 九月 2026 15:04:42 +0800
Subject: [PATCH] Merge remote-tracking branch 'refs/remotes/origin/dev_pro2.0' into dev_宁夏_九泓化工
---
src/views/aftersales/ticket/detail.vue | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 174 insertions(+), 5 deletions(-)
diff --git a/src/views/aftersales/ticket/detail.vue b/src/views/aftersales/ticket/detail.vue
index b9a6d7e..092ebc2 100644
--- a/src/views/aftersales/ticket/detail.vue
+++ b/src/views/aftersales/ticket/detail.vue
@@ -7,7 +7,17 @@
import { Page } from '@vben/common-ui';
import { AftersaleIssueTypeEnum, AftersaleTicketStatusEnum } from '@vben/constants';
-import { Button, Card, Descriptions, Input, message, Popconfirm, Select, Tag } from 'ant-design-vue';
+import {
+ Button,
+ Card,
+ Descriptions,
+ Input,
+ message,
+ Popconfirm,
+ Select,
+ Switch,
+ Tag,
+} from 'ant-design-vue';
import {
assignTicket,
@@ -17,6 +27,11 @@
getTicket,
resolveTicket,
} from '#/api/aftersales/ticket';
+import type { AftersalesVisitApi } from '#/api/aftersales/visit';
+import {
+ createVisit,
+ getVisitListByTicketId,
+} from '#/api/aftersales/visit';
defineOptions({ name: 'AftersalesTicketDetail' });
@@ -32,6 +47,32 @@
const isPendingReturn = computed(() => ticket.value?.status === AftersaleTicketStatusEnum.PENDING_RETURN);
const isPendingRefund = computed(() => ticket.value?.status === AftersaleTicketStatusEnum.PENDING_REFUND);
const isResolved = computed(() => ticket.value?.status === AftersaleTicketStatusEnum.RESOLVED);
+/** 鍥炶鏄惁宸查�氳繃锛堟弧鎰忎笖鏈鍙戯級 */
+const isVisitPassed = computed(() => ticket.value?.visitStatus === 1);
+
+// 鍥炶璁板綍
+const visits = ref<AftersalesVisitApi.Visit[]>([]);
+const showVisitForm = ref(false);
+const visitForm = ref<AftersalesVisitApi.CreateVisit>({
+ ticketId: 0,
+ visitType: 0,
+ content: '',
+ satisfied: true,
+ recurred: false,
+});
+
+const visitTypeOptions = [
+ { label: '鐢佃瘽鍥炶', value: 0 },
+ { label: '涓婇棬鍥炶', value: 1 },
+ { label: '杩滅▼鍥炶', value: 2 },
+ { label: '鍏朵粬', value: 3 },
+];
+const visitTypeMap: Record<number, string> = {
+ 0: '鐢佃瘽',
+ 1: '涓婇棬',
+ 2: '杩滅▼',
+ 3: '鍏朵粬',
+};
// 鍒嗛厤澶勭悊浜�
const showAssignInput = ref(false);
@@ -86,6 +127,30 @@
} finally {
loading.value = false;
}
+}
+
+async function loadVisits() {
+ visits.value = await getVisitListByTicketId(ticketId.value);
+}
+
+function toggleVisitForm() {
+ showVisitForm.value = !showVisitForm.value;
+ if (showVisitForm.value) {
+ visitForm.value = {
+ ticketId: ticketId.value,
+ visitType: 0,
+ content: '',
+ satisfied: true,
+ recurred: false,
+ };
+ }
+}
+
+async function handleCreateVisit() {
+ await createVisit({ ...visitForm.value, ticketId: ticketId.value });
+ message.success('鍥炶鐧昏鎴愬姛');
+ showVisitForm.value = false;
+ await Promise.all([loadVisits(), loadTicket()]);
}
function toggleAssignInput() {
@@ -161,6 +226,7 @@
onMounted(() => {
loadTicket();
+ loadVisits();
});
</script>
@@ -195,6 +261,14 @@
</Descriptions.Item>
<Descriptions.Item label="璐熻矗浜�">{{ ticket.ownerUserName || '-' }}</Descriptions.Item>
<Descriptions.Item label="澶勭悊浜�">{{ ticket.handlerUserName || '-' }}</Descriptions.Item>
+ <Descriptions.Item label="鍥炶鐘舵��">
+ <Tag v-if="ticket.visitStatus === 1" color="green">宸插洖璁块�氳繃</Tag>
+ <Tag v-else color="orange">寰呭洖璁�</Tag>
+ </Descriptions.Item>
+ <Descriptions.Item label="闂娌夋穩" :span="2">
+ <template v-if="ticket.problemNo">{{ ticket.problemNo }}</template>
+ <template v-else>-</template>
+ </Descriptions.Item>
<Descriptions.Item label="闂鎻忚堪" :span="3">
{{ ticket.issueDescription || '-' }}
</Descriptions.Item>
@@ -253,6 +327,101 @@
>
{{ file.name || '闄勪欢-' + file.id }}
</a>
+ </div>
+ </Card>
+
+ <!-- 鍥炶璁板綍 -->
+ <Card v-if="ticket" title="鍥炶璁板綍" class="mb-4">
+ <template #extra>
+ <Button
+ v-if="isResolved && !showVisitForm"
+ type="primary"
+ size="small"
+ @click="toggleVisitForm"
+ >
+ 鐧昏鍥炶
+ </Button>
+ </template>
+
+ <div v-if="isResolved" class="mb-3 text-sm text-gray-500">
+ 鐧昏銆屾弧鎰� 涓� 鏈鍙戙�嶇殑鍥炶鍚庯紝宸ュ崟鎵嶅彲褰掓。锛涚櫥璁般�屼笉婊℃剰鎴栧鍙戙�嶄細鑷姩閫�鍥炲鐞嗕腑銆�
+ </div>
+
+ <!-- 鐧昏鍥炶琛ㄥ崟 -->
+ <div
+ v-if="showVisitForm"
+ class="mb-4 flex flex-wrap items-center gap-3 rounded bg-gray-50 p-3"
+ >
+ <div class="flex items-center gap-1">
+ <span class="text-sm text-gray-500">鍥炶鏂瑰紡锛�</span>
+ <Select
+ v-model:value="visitForm.visitType"
+ :options="visitTypeOptions"
+ style="width: 120px"
+ />
+ </div>
+ <div class="flex items-center gap-1">
+ <span class="text-sm text-gray-500">鍥炶鍐呭锛�</span>
+ <Input
+ v-model:value="visitForm.content"
+ placeholder="瀹㈡埛鍙嶉鍐呭"
+ style="width: 260px"
+ />
+ </div>
+ <div class="flex items-center gap-1">
+ <span class="text-sm text-gray-500">鏄惁婊℃剰锛�</span>
+ <Switch
+ v-model:checked="visitForm.satisfied"
+ checked-children="婊℃剰"
+ un-checked-children="涓嶆弧鎰�"
+ />
+ </div>
+ <div class="flex items-center gap-1">
+ <span class="text-sm text-gray-500">鏄惁澶嶅彂锛�</span>
+ <Switch
+ v-model:checked="visitForm.recurred"
+ checked-children="澶嶅彂"
+ un-checked-children="鏈鍙�"
+ />
+ </div>
+ <Button type="primary" size="small" @click="handleCreateVisit">鎻愪氦</Button>
+ <Button size="small" @click="toggleVisitForm">鍙栨秷</Button>
+ </div>
+
+ <!-- 鍥炶璁板綍鍒楄〃 -->
+ <div v-if="visits.length === 0" class="text-sm text-gray-400">鏆傛棤鍥炶璁板綍</div>
+ <div v-else class="overflow-x-auto">
+ <table class="w-full border text-sm">
+ <thead class="bg-gray-50">
+ <tr>
+ <th class="border p-2 text-left">鍥炶鏃堕棿</th>
+ <th class="border p-2 text-left">鏂瑰紡</th>
+ <th class="border p-2 text-left">鍥炶浜�</th>
+ <th class="border p-2 text-center">婊℃剰</th>
+ <th class="border p-2 text-center">澶嶅彂</th>
+ <th class="border p-2 text-left">鍐呭</th>
+ <th class="border p-2 text-left">澶囨敞</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr v-for="visit in visits" :key="visit.id">
+ <td class="border p-2">{{ visit.visitTime }}</td>
+ <td class="border p-2">{{ visitTypeMap[visit.visitType!] ?? '-' }}</td>
+ <td class="border p-2">{{ visit.visitorUserName || '-' }}</td>
+ <td class="border p-2 text-center">
+ <Tag :color="visit.satisfied ? 'green' : 'red'">
+ {{ visit.satisfied ? '婊℃剰' : '涓嶆弧鎰�' }}
+ </Tag>
+ </td>
+ <td class="border p-2 text-center">
+ <Tag v-if="visit.recurred" color="orange">澶嶅彂</Tag>
+ <Tag v-else color="default">鏈鍙�</Tag>
+ </td>
+ <td class="border p-2">{{ visit.content || '-' }}</td>
+ <td class="border p-2">{{ visit.remark || '-' }}</td>
+ </tr>
+ </tbody>
+ </table>
</div>
</Card>
@@ -323,13 +492,13 @@
<Button type="primary">瀹岀粨</Button>
</Popconfirm>
- <!-- 鍏抽棴 -->
+ <!-- 褰掓。锛堜粎鍥炶閫氳繃鍚庡彲褰掓。锛涙湭鍥炶璇峰湪鈥滃洖璁胯褰曗�濋噷鐧昏锛� -->
<Popconfirm
- v-if="isResolved"
- title="纭鍏抽棴璇ュ伐鍗曪紵鍏抽棴鍚庝笉鍙仮澶嶃��"
+ v-if="isResolved && isVisitPassed"
+ title="纭褰掓。璇ュ伐鍗曪紵褰掓。鍚庤嚜鍔ㄦ矇娣�涓�鏉¢棶棰橈紝宸ュ崟鍙涓嶅彲鎭㈠銆�"
@confirm="handleClose"
>
- <Button type="primary">鍏抽棴</Button>
+ <Button type="primary">褰掓。</Button>
</Popconfirm>
<!-- 鍙栨秷 -->
--
Gitblit v1.9.3