add event record verify photo
This commit is contained in:
@@ -0,0 +1,197 @@
|
|||||||
|
<template>
|
||||||
|
<t-dialog
|
||||||
|
class="event-record-verify-dialog"
|
||||||
|
v-model:visible="visible"
|
||||||
|
title="核销登记记录"
|
||||||
|
:confirm-btn="{ content: '核销', disabled: isPhotoUploading || isSubmitting }"
|
||||||
|
cancel-btn="取消"
|
||||||
|
:before-close="beforeClose"
|
||||||
|
>
|
||||||
|
<div class="content">
|
||||||
|
<div v-text="confirmText" />
|
||||||
|
<div v-if="canUpdate" class="photo-part">
|
||||||
|
<photo-scroller
|
||||||
|
title="核销照片(可选)"
|
||||||
|
:model-value="photoList"
|
||||||
|
v-model:photo-items="photoItemList"
|
||||||
|
:edit-mode="true"
|
||||||
|
:loading="isPhotoUploading"
|
||||||
|
:show-remove="false"
|
||||||
|
:show-viewer-actions="false"
|
||||||
|
@add="capturePhoto"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</t-dialog>
|
||||||
|
<input
|
||||||
|
ref="photoInputRef"
|
||||||
|
class="file-input"
|
||||||
|
type="file"
|
||||||
|
accept="image/*"
|
||||||
|
multiple
|
||||||
|
@change="handlePhotoSelected"
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { AttachmentAPI, type Attachment } from "timi-web-api";
|
||||||
|
import PhotoScroller from "@/components/PhotoScroller.vue";
|
||||||
|
import type { EventRecord } from "@/types/EventRecord";
|
||||||
|
import type { PhotoItem } from "@/types/Photo";
|
||||||
|
import { getAttachmentReadURL } from "@/utils/attachment";
|
||||||
|
import { getErrorMessage } from "@/utils/error";
|
||||||
|
import { compressUploadImageList } from "@/utils/imageCompression";
|
||||||
|
import { Message } from "@/utils/message";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "EventRecordVerifyDialog"
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
canUpdate?: boolean;
|
||||||
|
record?: EventRecord;
|
||||||
|
submit: (record: EventRecord, attachmentList: Attachment[]) => Promise<void>;
|
||||||
|
visible?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
canUpdate: false,
|
||||||
|
visible: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
"update:visible": [visible: boolean];
|
||||||
|
verified: [record: EventRecord];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const photoInputRef = ref<HTMLInputElement>();
|
||||||
|
const photoItemList = ref<PhotoItem[]>([]);
|
||||||
|
const isPhotoUploading = ref(false);
|
||||||
|
const isSubmitting = ref(false);
|
||||||
|
const visible = computed({
|
||||||
|
get: () => props.visible,
|
||||||
|
set: (value: boolean) => emit("update:visible", value)
|
||||||
|
});
|
||||||
|
const photoList = computed<string[]>(() => photoItemList.value.map(item => item.url));
|
||||||
|
const confirmText = computed(() => `确定核销 ${props.record?.customer?.name || "未知客户"} 的 ${props.record?.event?.name || "未知事件"} 记录吗?`);
|
||||||
|
|
||||||
|
watch([() => props.visible, () => props.record?.id], ([isVisible]) => {
|
||||||
|
if (isVisible) {
|
||||||
|
photoItemList.value = buildPhotoItemList(props.record?.attachmentList);
|
||||||
|
}
|
||||||
|
}, { immediate: true });
|
||||||
|
|
||||||
|
function buildPhotoItemList(attachmentList?: Attachment[]): PhotoItem[] {
|
||||||
|
return (attachmentList || [])
|
||||||
|
.filter(item => !!item.id)
|
||||||
|
.map(item => ({
|
||||||
|
attachment: item,
|
||||||
|
attachType: item.attachType || "PHOTO",
|
||||||
|
previewUrl: getAttachmentReadURL(item.id || ""),
|
||||||
|
url: getAttachmentReadURL(item.id || "", 90)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function capturePhoto(): void {
|
||||||
|
photoInputRef.value?.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handlePhotoSelected(event: Event): Promise<void> {
|
||||||
|
const input = event.target as HTMLInputElement;
|
||||||
|
const fileList = Array.from(input.files || []);
|
||||||
|
if (!fileList.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isPhotoUploading.value = true;
|
||||||
|
try {
|
||||||
|
const compressedFileList = await compressUploadImageList(fileList);
|
||||||
|
const tempFileList = await AttachmentAPI.upload(compressedFileList);
|
||||||
|
for (const item of tempFileList) {
|
||||||
|
if (!item.id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
photoItemList.value.push({
|
||||||
|
attachType: "PHOTO",
|
||||||
|
tempFileId: item.id,
|
||||||
|
url: AttachmentAPI.getTempReadURL(item.id)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
Message.error(getErrorMessage(error, "登记照片上传失败"));
|
||||||
|
} finally {
|
||||||
|
isPhotoUploading.value = false;
|
||||||
|
input.value = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function beforeClose(trigger: "confirm" | "cancel" | "overlay" | "close-btn"): Promise<void> {
|
||||||
|
if (trigger !== "confirm") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!props.record?.id) {
|
||||||
|
Message.warning("登记事件记录不存在");
|
||||||
|
throw new Error("登记事件记录不存在");
|
||||||
|
}
|
||||||
|
if (isPhotoUploading.value || isSubmitting.value) {
|
||||||
|
Message.warning("照片正在上传,请稍候");
|
||||||
|
throw new Error("照片正在上传");
|
||||||
|
}
|
||||||
|
|
||||||
|
isSubmitting.value = true;
|
||||||
|
try {
|
||||||
|
await props.submit(props.record, buildAttachmentList());
|
||||||
|
Message.success("登记记录已核销");
|
||||||
|
emit("verified", props.record);
|
||||||
|
} catch (error) {
|
||||||
|
Message.error(getErrorMessage(error, "登记记录核销失败"));
|
||||||
|
throw error;
|
||||||
|
} finally {
|
||||||
|
isSubmitting.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildAttachmentList(): Attachment[] {
|
||||||
|
return photoItemList.value.flatMap(item => {
|
||||||
|
if (item.attachment) {
|
||||||
|
return [{
|
||||||
|
...item.attachment,
|
||||||
|
attachType: item.attachType || item.attachment.attachType || "PHOTO"
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
if (item.tempFileId) {
|
||||||
|
return [{
|
||||||
|
attachType: item.attachType || "PHOTO",
|
||||||
|
tempFileId: item.tempFileId
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.event-record-verify-dialog {
|
||||||
|
.content {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-part {
|
||||||
|
margin-top: 1rem;
|
||||||
|
padding-top: 1rem;
|
||||||
|
border-top: 1px solid var(--td-component-border);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(html.theme-dark) {
|
||||||
|
.event-record-verify-dialog {
|
||||||
|
.photo-part {
|
||||||
|
border-color: var(--td-component-border);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -56,14 +56,21 @@
|
|||||||
</div>
|
</div>
|
||||||
<t-empty v-if="!record" :description="isLoading ? '正在加载登记事件记录' : '登记事件记录不存在'" />
|
<t-empty v-if="!record" :description="isLoading ? '正在加载登记事件记录' : '登记事件记录不存在'" />
|
||||||
</div>
|
</div>
|
||||||
|
<event-record-verify-dialog
|
||||||
|
v-model:visible="verifyDialogVisible"
|
||||||
|
:record="record"
|
||||||
|
:can-update="canUpdateRecord"
|
||||||
|
:submit="submitVerifyRecord"
|
||||||
|
@verified="handleVerifySuccess"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DialogPlugin } from "tdesign-mobile-vue";
|
|
||||||
import { PassTimeLabel, Text } from "timi-web";
|
import { PassTimeLabel, Text } from "timi-web";
|
||||||
import { useUserStore, type Attachment } from "timi-web-api";
|
import { useUserStore, type Attachment } from "timi-web-api";
|
||||||
import EventRecordAPI from "@/api/EventRecordAPI";
|
import EventRecordAPI from "@/api/EventRecordAPI";
|
||||||
import CustomerProfileCard from "@/components/CustomerProfileCard.vue";
|
import CustomerProfileCard from "@/components/CustomerProfileCard.vue";
|
||||||
|
import EventRecordVerifyDialog from "@/components/EventRecordVerifyDialog.vue";
|
||||||
import PhotoScroller from "@/components/PhotoScroller.vue";
|
import PhotoScroller from "@/components/PhotoScroller.vue";
|
||||||
import { useNavBarStore } from "@/store/navBarStore";
|
import { useNavBarStore } from "@/store/navBarStore";
|
||||||
import type { EventRecord } from "@/types/EventRecord";
|
import type { EventRecord } from "@/types/EventRecord";
|
||||||
@@ -71,8 +78,6 @@ import type { PhotoItem } from "@/types/Photo";
|
|||||||
import type { PointLedgerChangeType } from "@/types/Point";
|
import type { PointLedgerChangeType } from "@/types/Point";
|
||||||
import { getAttachmentReadURL } from "@/utils/attachment";
|
import { getAttachmentReadURL } from "@/utils/attachment";
|
||||||
import { formatEventNumberValue } from "@/utils/eventValue";
|
import { formatEventNumberValue } from "@/utils/eventValue";
|
||||||
import { getErrorMessage } from "@/utils/error";
|
|
||||||
import { Message } from "@/utils/message";
|
|
||||||
import { permissionCodes } from "@/utils/permission";
|
import { permissionCodes } from "@/utils/permission";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@@ -89,6 +94,7 @@ const userStore = useUserStore();
|
|||||||
const record = ref<EventRecord>();
|
const record = ref<EventRecord>();
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
const isVerifying = ref(false);
|
const isVerifying = ref(false);
|
||||||
|
const verifyDialogVisible = ref(false);
|
||||||
|
|
||||||
const canUpdateRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.update));
|
const canUpdateRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.update));
|
||||||
const canVerifyRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.verify));
|
const canVerifyRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.verify));
|
||||||
@@ -198,42 +204,41 @@ async function loadRecord(): Promise<void> {
|
|||||||
|
|
||||||
async function confirmVerifyRecord(): Promise<void> {
|
async function confirmVerifyRecord(): Promise<void> {
|
||||||
const currentRecord = record.value;
|
const currentRecord = record.value;
|
||||||
if (!currentRecord?.id || currentRecord.verificationStatus !== "PENDING") {
|
if (!currentRecord?.id || currentRecord.verificationStatus !== "PENDING" || isVerifying.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dialog = DialogPlugin.confirm({
|
verifyDialogVisible.value = true;
|
||||||
title: "核销登记记录",
|
|
||||||
content: `确定核销 ${currentRecord.customer?.name || "未知客户"} 的 ${currentRecord.event?.name || "未知事件"} 记录吗?`,
|
|
||||||
cancelBtn: "取消",
|
|
||||||
confirmBtn: "核销",
|
|
||||||
onCancel() {
|
|
||||||
dialog.destroy();
|
|
||||||
},
|
|
||||||
async onConfirm() {
|
|
||||||
dialog.destroy();
|
|
||||||
await verifyRecord(currentRecord.id || "");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function verifyRecord(id: string): Promise<void> {
|
async function submitVerifyRecord(record: EventRecord, attachmentList: Attachment[]): Promise<void> {
|
||||||
if (!id || isVerifying.value) {
|
const id = record.id;
|
||||||
return;
|
if (!id) {
|
||||||
|
throw new Error("登记事件记录不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
isVerifying.value = true;
|
isVerifying.value = true;
|
||||||
try {
|
try {
|
||||||
|
if (canUpdateRecord.value) {
|
||||||
|
await EventRecordAPI.update({
|
||||||
|
id,
|
||||||
|
remark: record.remark || "",
|
||||||
|
attachmentList
|
||||||
|
});
|
||||||
|
}
|
||||||
await EventRecordAPI.verify(id);
|
await EventRecordAPI.verify(id);
|
||||||
record.value = await EventRecordAPI.detail(id);
|
|
||||||
Message.success("登记记录已核销");
|
|
||||||
} catch (error) {
|
|
||||||
Message.error(getErrorMessage(error, "登记记录核销失败"));
|
|
||||||
} finally {
|
} finally {
|
||||||
isVerifying.value = false;
|
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> {
|
async function toEdit(): Promise<void> {
|
||||||
|
|||||||
@@ -102,7 +102,7 @@
|
|||||||
v-if="canVerifyRecord && item.verificationStatus === 'PENDING'"
|
v-if="canVerifyRecord && item.verificationStatus === 'PENDING'"
|
||||||
class="action verify bg-orange white"
|
class="action verify bg-orange white"
|
||||||
variant="text"
|
variant="text"
|
||||||
:loading="isVerifying && verifyingId === item.id"
|
:loading="(isVerifying && verifyingId === item.id) || (isLoadingVerifyRecord && verifyLoadingId === item.id)"
|
||||||
@click.stop="confirmVerifyRecord(item)"
|
@click.stop="confirmVerifyRecord(item)"
|
||||||
>
|
>
|
||||||
核销
|
核销
|
||||||
@@ -125,6 +125,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</t-pull-down-refresh>
|
</t-pull-down-refresh>
|
||||||
</div>
|
</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" />
|
<nav-bar-action-menu v-if="canShowActionMenu" :actions="actionList" />
|
||||||
<t-popup v-model="startVisible" placement="bottom">
|
<t-popup v-model="startVisible" placement="bottom">
|
||||||
<t-date-time-picker
|
<t-date-time-picker
|
||||||
@@ -155,12 +162,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DialogPlugin, type DropdownValue } from "tdesign-mobile-vue";
|
import { DialogPlugin, type DropdownValue } from "tdesign-mobile-vue";
|
||||||
import { Time, WebToolkit } from "timi-web";
|
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 EventAPI from "@/api/EventAPI";
|
||||||
import EventRecordAPI from "@/api/EventRecordAPI";
|
import EventRecordAPI from "@/api/EventRecordAPI";
|
||||||
|
import EventRecordVerifyDialog from "@/components/EventRecordVerifyDialog.vue";
|
||||||
import { useNavBarStore } from "@/store/navBarStore";
|
import { useNavBarStore } from "@/store/navBarStore";
|
||||||
import type { EventItem } from "@/types/EventItem";
|
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 type { NavBarAction } from "@/types/NavBarAction";
|
||||||
import { getCustomerPhotoURL } from "@/utils/customer";
|
import { getCustomerPhotoURL } from "@/utils/customer";
|
||||||
import { getErrorMessage } from "@/utils/error";
|
import { getErrorMessage } from "@/utils/error";
|
||||||
@@ -239,6 +247,7 @@ const selectedNumberEvent = computed(() => {
|
|||||||
const canExportRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.export));
|
const canExportRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.export));
|
||||||
const canDeleteRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.delete));
|
const canDeleteRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.delete));
|
||||||
const canVerifyRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.verify));
|
const canVerifyRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.verify));
|
||||||
|
const canUpdateRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.update));
|
||||||
const canShowActionMenu = computed(() => canCreateRecord.value || canExportRecord.value);
|
const canShowActionMenu = computed(() => canCreateRecord.value || canExportRecord.value);
|
||||||
|
|
||||||
const actionList = computed<NavBarAction[]>(() => {
|
const actionList = computed<NavBarAction[]>(() => {
|
||||||
@@ -382,6 +391,10 @@ const isDeleting = ref(false);
|
|||||||
const deletingId = ref("");
|
const deletingId = ref("");
|
||||||
const isVerifying = ref(false);
|
const isVerifying = ref(false);
|
||||||
const verifyingId = ref("");
|
const verifyingId = ref("");
|
||||||
|
const isLoadingVerifyRecord = ref(false);
|
||||||
|
const verifyLoadingId = ref("");
|
||||||
|
const verifyDialogVisible = ref(false);
|
||||||
|
const verifyTarget = ref<EventRecord>();
|
||||||
|
|
||||||
async function loadActions(): Promise<void> {
|
async function loadActions(): Promise<void> {
|
||||||
eventList.value = await EventAPI.listValid();
|
eventList.value = await EventAPI.listValid();
|
||||||
@@ -467,45 +480,57 @@ async function exportExcel(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function confirmVerifyRecord(record: EventRecordListItemView): 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const recordId = record.id;
|
const recordId = record.id;
|
||||||
const dialog = DialogPlugin.confirm({
|
isLoadingVerifyRecord.value = true;
|
||||||
title: "核销登记记录",
|
verifyLoadingId.value = recordId;
|
||||||
content: `确定核销 ${getRecordCustomerName(record)} 的 ${getRecordEventName(record)} 记录吗?`,
|
try {
|
||||||
cancelBtn: "取消",
|
verifyTarget.value = await EventRecordAPI.detail(recordId);
|
||||||
confirmBtn: "核销",
|
verifyDialogVisible.value = true;
|
||||||
onCancel() {
|
} catch (error) {
|
||||||
dialog.destroy();
|
Message.error(getErrorMessage(error, "登记记录加载失败"));
|
||||||
},
|
} finally {
|
||||||
async onConfirm() {
|
isLoadingVerifyRecord.value = false;
|
||||||
dialog.destroy();
|
verifyLoadingId.value = "";
|
||||||
await verifyRecord(recordId);
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function verifyRecord(id: string): Promise<void> {
|
async function submitVerifyRecord(record: EventRecord, attachmentList: Attachment[]): Promise<void> {
|
||||||
if (isVerifying.value) {
|
const id = record.id;
|
||||||
return;
|
if (!id) {
|
||||||
|
throw new Error("登记事件记录不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
isVerifying.value = true;
|
isVerifying.value = true;
|
||||||
verifyingId.value = id;
|
verifyingId.value = id;
|
||||||
try {
|
try {
|
||||||
|
if (canUpdateRecord.value) {
|
||||||
|
await EventRecordAPI.update({
|
||||||
|
id,
|
||||||
|
remark: record.remark || "",
|
||||||
|
attachmentList
|
||||||
|
});
|
||||||
|
}
|
||||||
await EventRecordAPI.verify(id);
|
await EventRecordAPI.verify(id);
|
||||||
await reloadRecords();
|
|
||||||
Message.success("登记记录已核销");
|
|
||||||
} catch (error) {
|
|
||||||
Message.error(getErrorMessage(error, "登记记录核销失败"));
|
|
||||||
} finally {
|
} finally {
|
||||||
isVerifying.value = false;
|
isVerifying.value = false;
|
||||||
verifyingId.value = "";
|
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> {
|
async function toDetail(id: string): Promise<void> {
|
||||||
if (!id) {
|
if (!id) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user