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>
|
||||
Reference in New Issue
Block a user