add event record verify photo

This commit is contained in:
Timi
2026-08-30 01:40:51 +08:00
parent e1a3df43a9
commit a8958f51f6
3 changed files with 275 additions and 48 deletions
+29 -24
View File
@@ -56,14 +56,21 @@
</div>
<t-empty v-if="!record" :description="isLoading ? '正在加载登记事件记录' : '登记事件记录不存在'" />
</div>
<event-record-verify-dialog
v-model:visible="verifyDialogVisible"
:record="record"
:can-update="canUpdateRecord"
:submit="submitVerifyRecord"
@verified="handleVerifySuccess"
/>
</template>
<script setup lang="ts">
import { DialogPlugin } from "tdesign-mobile-vue";
import { PassTimeLabel, Text } from "timi-web";
import { useUserStore, type Attachment } from "timi-web-api";
import EventRecordAPI from "@/api/EventRecordAPI";
import CustomerProfileCard from "@/components/CustomerProfileCard.vue";
import EventRecordVerifyDialog from "@/components/EventRecordVerifyDialog.vue";
import PhotoScroller from "@/components/PhotoScroller.vue";
import { useNavBarStore } from "@/store/navBarStore";
import type { EventRecord } from "@/types/EventRecord";
@@ -71,8 +78,6 @@ import type { PhotoItem } from "@/types/Photo";
import type { PointLedgerChangeType } from "@/types/Point";
import { getAttachmentReadURL } from "@/utils/attachment";
import { formatEventNumberValue } from "@/utils/eventValue";
import { getErrorMessage } from "@/utils/error";
import { Message } from "@/utils/message";
import { permissionCodes } from "@/utils/permission";
defineOptions({
@@ -89,6 +94,7 @@ const userStore = useUserStore();
const record = ref<EventRecord>();
const isLoading = ref(false);
const isVerifying = ref(false);
const verifyDialogVisible = ref(false);
const canUpdateRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.update));
const canVerifyRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.verify));
@@ -198,42 +204,41 @@ async function loadRecord(): Promise<void> {
async function confirmVerifyRecord(): Promise<void> {
const currentRecord = record.value;
if (!currentRecord?.id || currentRecord.verificationStatus !== "PENDING") {
if (!currentRecord?.id || currentRecord.verificationStatus !== "PENDING" || isVerifying.value) {
return;
}
const dialog = DialogPlugin.confirm({
title: "核销登记记录",
content: `确定核销 ${currentRecord.customer?.name || "未知客户"} 的 ${currentRecord.event?.name || "未知事件"} 记录吗?`,
cancelBtn: "取消",
confirmBtn: "核销",
onCancel() {
dialog.destroy();
},
async onConfirm() {
dialog.destroy();
await verifyRecord(currentRecord.id || "");
}
});
verifyDialogVisible.value = true;
}
async function verifyRecord(id: string): Promise<void> {
if (!id || isVerifying.value) {
return;
async function submitVerifyRecord(record: EventRecord, attachmentList: Attachment[]): Promise<void> {
const id = record.id;
if (!id) {
throw new Error("登记事件记录不存在");
}
isVerifying.value = true;
try {
if (canUpdateRecord.value) {
await EventRecordAPI.update({
id,
remark: record.remark || "",
attachmentList
});
}
await EventRecordAPI.verify(id);
record.value = await EventRecordAPI.detail(id);
Message.success("登记记录已核销");
} catch (error) {
Message.error(getErrorMessage(error, "登记记录核销失败"));
} finally {
isVerifying.value = false;
}
}
async function handleVerifySuccess(): Promise<void> {
verifyDialogVisible.value = false;
if (record.value?.id) {
record.value = await EventRecordAPI.detail(record.value.id);
}
}
// ---------- 导航 ----------
async function toEdit(): Promise<void> {
+49 -24
View File
@@ -102,7 +102,7 @@
v-if="canVerifyRecord && item.verificationStatus === 'PENDING'"
class="action verify bg-orange white"
variant="text"
:loading="isVerifying && verifyingId === item.id"
:loading="(isVerifying && verifyingId === item.id) || (isLoadingVerifyRecord && verifyLoadingId === item.id)"
@click.stop="confirmVerifyRecord(item)"
>
核销
@@ -125,6 +125,13 @@
</div>
</t-pull-down-refresh>
</div>
<event-record-verify-dialog
v-model:visible="verifyDialogVisible"
:record="verifyTarget"
:can-update="canUpdateRecord"
:submit="submitVerifyRecord"
@verified="handleVerifySuccess"
/>
<nav-bar-action-menu v-if="canShowActionMenu" :actions="actionList" />
<t-popup v-model="startVisible" placement="bottom">
<t-date-time-picker
@@ -155,12 +162,13 @@
<script setup lang="ts">
import { DialogPlugin, type DropdownValue } from "tdesign-mobile-vue";
import { Time, WebToolkit } from "timi-web";
import { useUserStore } from "timi-web-api";
import { useUserStore, type Attachment } from "timi-web-api";
import EventAPI from "@/api/EventAPI";
import EventRecordAPI from "@/api/EventRecordAPI";
import EventRecordVerifyDialog from "@/components/EventRecordVerifyDialog.vue";
import { useNavBarStore } from "@/store/navBarStore";
import type { EventItem } from "@/types/EventItem";
import type { EventRecordListItemView, EventRecordPage, EventRecordPageResult, VerificationStatus } from "@/types/EventRecord";
import type { EventRecord, EventRecordListItemView, EventRecordPage, EventRecordPageResult, VerificationStatus } from "@/types/EventRecord";
import type { NavBarAction } from "@/types/NavBarAction";
import { getCustomerPhotoURL } from "@/utils/customer";
import { getErrorMessage } from "@/utils/error";
@@ -239,6 +247,7 @@ const selectedNumberEvent = computed(() => {
const canExportRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.export));
const canDeleteRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.delete));
const canVerifyRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.verify));
const canUpdateRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.update));
const canShowActionMenu = computed(() => canCreateRecord.value || canExportRecord.value);
const actionList = computed<NavBarAction[]>(() => {
@@ -382,6 +391,10 @@ const isDeleting = ref(false);
const deletingId = ref("");
const isVerifying = ref(false);
const verifyingId = ref("");
const isLoadingVerifyRecord = ref(false);
const verifyLoadingId = ref("");
const verifyDialogVisible = ref(false);
const verifyTarget = ref<EventRecord>();
async function loadActions(): Promise<void> {
eventList.value = await EventAPI.listValid();
@@ -467,45 +480,57 @@ async function exportExcel(): Promise<void> {
}
async function confirmVerifyRecord(record: EventRecordListItemView): Promise<void> {
if (!record.id || record.verificationStatus !== "PENDING") {
if (!record.id || record.verificationStatus !== "PENDING" || isVerifying.value || isLoadingVerifyRecord.value) {
return;
}
const recordId = record.id;
const dialog = DialogPlugin.confirm({
title: "核销登记记录",
content: `确定核销 ${getRecordCustomerName(record)} 的 ${getRecordEventName(record)} 记录吗?`,
cancelBtn: "取消",
confirmBtn: "核销",
onCancel() {
dialog.destroy();
},
async onConfirm() {
dialog.destroy();
await verifyRecord(recordId);
}
});
isLoadingVerifyRecord.value = true;
verifyLoadingId.value = recordId;
try {
verifyTarget.value = await EventRecordAPI.detail(recordId);
verifyDialogVisible.value = true;
} catch (error) {
Message.error(getErrorMessage(error, "登记记录加载失败"));
} finally {
isLoadingVerifyRecord.value = false;
verifyLoadingId.value = "";
}
}
async function verifyRecord(id: string): Promise<void> {
if (isVerifying.value) {
return;
async function submitVerifyRecord(record: EventRecord, attachmentList: Attachment[]): Promise<void> {
const id = record.id;
if (!id) {
throw new Error("登记事件记录不存在");
}
isVerifying.value = true;
verifyingId.value = id;
try {
if (canUpdateRecord.value) {
await EventRecordAPI.update({
id,
remark: record.remark || "",
attachmentList
});
}
await EventRecordAPI.verify(id);
await reloadRecords();
Message.success("登记记录已核销");
} catch (error) {
Message.error(getErrorMessage(error, "登记记录核销失败"));
} finally {
isVerifying.value = false;
verifyingId.value = "";
}
}
async function handleVerifySuccess(): Promise<void> {
verifyDialogVisible.value = false;
verifyTarget.value = undefined;
try {
await reloadRecords();
} catch (error) {
Message.error(getErrorMessage(error, "登记记录刷新失败"));
}
}
async function toDetail(id: string): Promise<void> {
if (!id) {
return;