Files
gao-customer-h5/src/pages/event/EventRecordDetail.vue
T
2026-08-24 17:53:21 +08:00

208 lines
5.9 KiB
Vue

<template>
<div v-can="permissionCodes.eventRecord.read" class="registration-record-detail">
<customer-profile-card
v-entrance-transition
v-if="record?.customer"
class="customer-profile"
:customer="record.customer"
@click="toCustomerDetail"
/>
<t-cell-group v-entrance-transition="70" v-if="record" title="登记信息" theme="card">
<t-cell title="登记事件" :note="record.event?.name || '未知事件'" />
<t-cell v-if="record.numberValue !== undefined && record.numberValue !== null" title="事件数值" :note="getNumberValueText(record)" />
<t-cell v-if="record.pointValue !== undefined && record.pointValue !== null" title="提交积分值" :note="getPointValueText(record.pointValue)" />
<t-cell v-if="record.earnedPointValue !== undefined && record.earnedPointValue !== null" title="本次积分变化" :note="getPointValueText(record.earnedPointValue)" />
<t-cell title="登记时间" :note="record.registeredAt ? Time.toPassedDateTime(record.registeredAt) : '-'" />
<t-cell title="登记人" :note="Text.display(record.operator?.nick || record.operator?.name)" />
<t-cell title="客户编码" :note="Text.display(record.customer?.code)" />
<t-cell title="备注" :note="Text.display(record.remark)" />
</t-cell-group>
<photo-scroller
v-entrance-transition="140"
v-if="record"
class="photo-panel"
:model-value="recordPhotoList"
:photo-items="recordPhotoItemList"
:show-viewer-actions="canUpdateRecord"
:show-add="false"
:show-remove="false"
:submit="submitPhotoItems"
title="登记照片"
/>
<t-empty v-else :description="isLoading ? '正在加载登记事件记录' : '登记事件记录不存在'" />
</div>
</template>
<script setup lang="ts">
import { Text, Time, useUserStore, type Attachment } from "timi-web";
import EventRecordAPI from "@/api/EventRecordAPI";
import CustomerProfileCard from "@/components/CustomerProfileCard.vue";
import PhotoScroller from "@/components/PhotoScroller.vue";
import { useNavBarStore } from "@/store/navBarStore";
import type { EventRecord } from "@/types/EventRecord";
import type { PhotoItem } from "@/types/Photo";
import { getAttachmentReadURL } from "@/utils/attachment";
import { formatEventNumberValue } from "@/utils/eventValue";
import { permissionCodes } from "@/utils/permission";
defineOptions({
name: "EventRecordDetail"
});
const route = useRoute();
const router = useRouter();
const navBarStore = useNavBarStore();
const userStore = useUserStore();
// ---------- 记录数据 ----------
const record = ref<EventRecord>();
const isLoading = ref(false);
const canUpdateRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.update));
const recordPhotoItemList = computed(() => (record.value?.attachmentList || [])
.filter(item => !!item.id)
.map(item => ({
attachment: item,
attachType: item.attachType || "PHOTO",
previewUrl: getAttachmentReadURL(item.id || ""),
url: getAttachmentReadURL(item.id || "", 64)
})));
const recordPhotoList = computed(() => recordPhotoItemList.value.map(item => item.url));
async function submitPhotoItems(photoItems: PhotoItem[]): Promise<void> {
const currentRecord = record.value;
if (!currentRecord?.id) {
throw new Error("登记记录不存在");
}
const attachmentList = buildPhotoAttachmentList(photoItems);
await EventRecordAPI.update({
id: currentRecord.id,
remark: currentRecord.remark || "",
attachmentList
});
record.value = {
...currentRecord,
attachmentList
};
}
function buildPhotoAttachmentList(photoItems: PhotoItem[]): Attachment[] {
return photoItems.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 [];
});
}
function getNumberValueText(value: EventRecord): string {
return formatEventNumberValue(value.event, value.numberValue);
}
function getPointValueText(value?: number | null): string {
if (value === undefined || value === null) {
return "-";
}
return `${0 < value ? "获得" : "消耗"} ${Math.abs(value)} 分`;
}
// ---------- 页面数据 ----------
async function loadRecord(): Promise<void> {
const recordId = String(route.params.id || "");
if (!recordId) {
record.value = undefined;
return;
}
isLoading.value = true;
try {
record.value = await EventRecordAPI.detail(recordId);
} catch (err) {
record.value = undefined;
console.warn("登记事件记录加载失败", err);
} finally {
isLoading.value = false;
}
}
// ---------- 导航 ----------
async function toEdit(): Promise<void> {
const recordId = String(route.params.id || "");
if (!recordId) {
return;
}
await router.push(`/management/registration-event-records/${recordId}/edit`);
}
async function toCustomerDetail(): Promise<void> {
const customerId = record.value?.customer?.id;
if (!customerId) {
return;
}
await router.push(`/management/customers/${customerId}`);
}
watch(() => route.params.id, async () => {
await loadRecord();
}, { immediate: true });
onMounted(() => {
navBarStore.clearRight();
if (canUpdateRecord.value) {
navBarStore.setRightText("编辑", "var(--td-brand-color)", toEdit);
}
});
onUnmounted(() => {
navBarStore.clearRight();
});
</script>
<style scoped lang="less">
.registration-record-detail {
gap: 1rem;
min-height: 100vh;
padding: calc(var(--app-nav-height) + 1rem) 0 1rem 0;
display: flex;
flex-direction: column;
.customer-profile {
margin: 0 1rem;
}
.photo-panel {
width: calc(100% - 2rem);
margin: 0 1rem;
padding: 1rem;
background: rgba(255, 255, 255, .92);
box-shadow: var(--td-shadow-1);
border-radius: 1.4rem;
}
}
:global(html.theme-dark) {
.registration-record-detail {
.photo-panel {
background: rgba(15, 23, 42, .88);
box-shadow: 0 .75rem 2rem rgba(2, 6, 23, .32);
}
}
}
</style>