update image thumb
This commit is contained in:
@@ -48,8 +48,9 @@ const customerName = computed(() => customer.value?.name || customer.value?.code
|
|||||||
const avatarText = computed(() => customerName.value.slice(0, 1));
|
const avatarText = computed(() => customerName.value.slice(0, 1));
|
||||||
const customerCode = computed(() => customer.value?.code || "");
|
const customerCode = computed(() => customer.value?.code || "");
|
||||||
const customerTelephone = computed(() => customer.value?.telephone || "");
|
const customerTelephone = computed(() => customer.value?.telephone || "");
|
||||||
const photoURL = computed(() => customer.value ? getCustomerPhotoURL(customer.value) : "");
|
const photoURL = computed(() => customer.value ? getCustomerPhotoURL(customer.value, 64) : "");
|
||||||
const photoViewerImages = computed(() => photoURL.value ? [photoURL.value] : []);
|
const originalPhotoURL = computed(() => customer.value ? getCustomerPhotoURL(customer.value) : "");
|
||||||
|
const photoViewerImages = computed(() => originalPhotoURL.value ? [originalPhotoURL.value] : []);
|
||||||
|
|
||||||
function handlePhotoClick(event: MouseEvent): void {
|
function handlePhotoClick(event: MouseEvent): void {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ type AddAction = {
|
|||||||
|
|
||||||
type PhotoItem = {
|
type PhotoItem = {
|
||||||
attachType?: string;
|
attachType?: string;
|
||||||
|
previewUrl?: string;
|
||||||
url: string;
|
url: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -182,7 +183,7 @@ function removePhoto(index: number): void {
|
|||||||
|
|
||||||
function openPhotoViewer(index: number): void {
|
function openPhotoViewer(index: number): void {
|
||||||
const photoList = [...displayPhotoList.value.slice(index), ...displayPhotoList.value.slice(0, index)];
|
const photoList = [...displayPhotoList.value.slice(index), ...displayPhotoList.value.slice(0, index)];
|
||||||
photoViewerImages.value = photoList.map(item => item.url);
|
photoViewerImages.value = photoList.map(item => item.previewUrl || item.url);
|
||||||
photoViewerVisible.value = true;
|
photoViewerVisible.value = true;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -144,7 +144,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Message } from "@/utils/message";
|
import { Message } from "@/utils/message";
|
||||||
import { AttachmentAPI, PassTimeLabel, Text, useUserStore } from "timi-web";
|
import { PassTimeLabel, Text, useUserStore } from "timi-web";
|
||||||
import CustomerAPI from "@/api/CustomerAPI";
|
import CustomerAPI from "@/api/CustomerAPI";
|
||||||
import PointAPI from "@/api/PointAPI";
|
import PointAPI from "@/api/PointAPI";
|
||||||
import TagAPI from "@/api/TagAPI";
|
import TagAPI from "@/api/TagAPI";
|
||||||
@@ -158,6 +158,7 @@ import type { BodyAreaValue, Customer } from "@/types/Customer";
|
|||||||
import type { PointAccount } from "@/types/Point";
|
import type { PointAccount } from "@/types/Point";
|
||||||
import type { Tag } from "@/types/Tag";
|
import type { Tag } from "@/types/Tag";
|
||||||
import { bodyAreaLabelMap } from "@/utils/bodyArea";
|
import { bodyAreaLabelMap } from "@/utils/bodyArea";
|
||||||
|
import { getAttachmentReadURL } from "@/utils/attachment";
|
||||||
import { normalizeBodyAreaValue } from "@/utils/customer";
|
import { normalizeBodyAreaValue } from "@/utils/customer";
|
||||||
import { corePermissionCodes, permissionCodes } from "@/utils/permission";
|
import { corePermissionCodes, permissionCodes } from "@/utils/permission";
|
||||||
import { LunarCalendar } from "@/utils/LunarCalendar";
|
import { LunarCalendar } from "@/utils/LunarCalendar";
|
||||||
@@ -192,15 +193,14 @@ const solarBirthdateText = computed(() => formatSolarBirthdate(customer.value));
|
|||||||
const birthdateText = computed(() => showSolarBirthdate.value && isLunarBirthdate.value ? solarBirthdateText.value : formatBirthdate(customer.value));
|
const birthdateText = computed(() => showSolarBirthdate.value && isLunarBirthdate.value ? solarBirthdateText.value : formatBirthdate(customer.value));
|
||||||
const ageText = computed(() => customer.value?.age === undefined || customer.value?.age === null ? "" : `${customer.value.age} 岁`);
|
const ageText = computed(() => customer.value?.age === undefined || customer.value?.age === null ? "" : `${customer.value.age} 岁`);
|
||||||
const inviteeCountText = computed(() => `${customer.value?.invitedCount ?? 0} 人`);
|
const inviteeCountText = computed(() => `${customer.value?.invitedCount ?? 0} 人`);
|
||||||
const photoList = computed(() => (customer.value?.attachmentList || [])
|
|
||||||
.filter(item => !!item.id)
|
|
||||||
.map(item => AttachmentAPI.getReadURL(item.id || "")));
|
|
||||||
const photoItemList = computed(() => (customer.value?.attachmentList || [])
|
const photoItemList = computed(() => (customer.value?.attachmentList || [])
|
||||||
.filter(item => !!item.id)
|
.filter(item => !!item.id)
|
||||||
.map(item => ({
|
.map(item => ({
|
||||||
attachType: item.attachType || "PHOTO",
|
attachType: item.attachType || "PHOTO",
|
||||||
url: AttachmentAPI.getReadURL(item.id || "")
|
previewUrl: getAttachmentReadURL(item.id || ""),
|
||||||
|
url: getAttachmentReadURL(item.id || "", 64)
|
||||||
})));
|
})));
|
||||||
|
const photoList = computed(() => photoItemList.value.map(item => item.url));
|
||||||
const selectedAreas = computed<BodyAreaValue>({
|
const selectedAreas = computed<BodyAreaValue>({
|
||||||
get() {
|
get() {
|
||||||
return normalizeBodyAreaValue(customer.value?.conditioningPart);
|
return normalizeBodyAreaValue(customer.value?.conditioningPart);
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ import { useSettingStore } from "@/store/settingStore";
|
|||||||
import type { BodyAreaValue, Customer, CustomerAttachmentType, EditableCustomerPhoto } from "@/types/Customer";
|
import type { BodyAreaValue, Customer, CustomerAttachmentType, EditableCustomerPhoto } from "@/types/Customer";
|
||||||
import type { Tag } from "@/types/Tag";
|
import type { Tag } from "@/types/Tag";
|
||||||
import { bodyAreaLabelMap } from "@/utils/bodyArea";
|
import { bodyAreaLabelMap } from "@/utils/bodyArea";
|
||||||
|
import { getAttachmentReadURL } from "@/utils/attachment";
|
||||||
import { normalizeBodyAreaValue } from "@/utils/customer";
|
import { normalizeBodyAreaValue } from "@/utils/customer";
|
||||||
import { corePermissionCodes, gaoRoleCodes, permissionCodes } from "@/utils/permission";
|
import { corePermissionCodes, gaoRoleCodes, permissionCodes } from "@/utils/permission";
|
||||||
import { compressUploadImage } from "@/utils/imageCompression";
|
import { compressUploadImage } from "@/utils/imageCompression";
|
||||||
@@ -388,7 +389,8 @@ async function loadDetail() {
|
|||||||
.map(item => ({
|
.map(item => ({
|
||||||
attachment: item,
|
attachment: item,
|
||||||
attachType: normalizeAttachmentType(item.attachType),
|
attachType: normalizeAttachmentType(item.attachType),
|
||||||
url: AttachmentAPI.getReadURL(item.id || "")
|
previewUrl: getAttachmentReadURL(item.id || ""),
|
||||||
|
url: getAttachmentReadURL(item.id || "", 64)
|
||||||
}));
|
}));
|
||||||
selectedAreas.value = normalizeBodyAreaValue(customer.conditioningPart);
|
selectedAreas.value = normalizeBodyAreaValue(customer.conditioningPart);
|
||||||
introducerCustomerId.value = customer.introducerCustomerId || customer.introducerCustomer?.id || "";
|
introducerCustomerId.value = customer.introducerCustomerId || customer.introducerCustomer?.id || "";
|
||||||
|
|||||||
@@ -42,9 +42,9 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #leftIcon>
|
<template #leftIcon>
|
||||||
<t-image
|
<t-image
|
||||||
v-if="getCustomerPhotoURL(item)"
|
v-if="getCustomerPhotoURL(item, 64)"
|
||||||
class="avatar"
|
class="avatar"
|
||||||
:src="getCustomerPhotoURL(item)"
|
:src="getCustomerPhotoURL(item, 64)"
|
||||||
:alt="item.name"
|
:alt="item.name"
|
||||||
fit="cover"
|
fit="cover"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
<section v-if="record" class="photo-panel">
|
<section v-if="record" class="photo-panel">
|
||||||
<photo-scroller
|
<photo-scroller
|
||||||
:model-value="recordPhotoList"
|
:model-value="recordPhotoList"
|
||||||
|
:photo-items="recordPhotoItemList"
|
||||||
:show-add="false"
|
:show-add="false"
|
||||||
:show-remove="false"
|
:show-remove="false"
|
||||||
title="登记照片"
|
title="登记照片"
|
||||||
@@ -54,10 +55,12 @@ const record = ref<EventRecord>();
|
|||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
|
|
||||||
const canUpdateRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.update));
|
const canUpdateRecord = computed(() => userStore.hasPermissions(permissionCodes.eventRecord.update));
|
||||||
const recordPhotoList = computed(() => {
|
const recordPhotoItemList = computed(() => {
|
||||||
const url = getEventRecordPhotoURL(record.value);
|
const url = getEventRecordPhotoURL(record.value);
|
||||||
return url ? [url] : [];
|
const thumbnailURL = getEventRecordPhotoURL(record.value, 64);
|
||||||
|
return thumbnailURL ? [{ url: thumbnailURL, previewUrl: url }] : [];
|
||||||
});
|
});
|
||||||
|
const recordPhotoList = computed(() => recordPhotoItemList.value.map(item => item.url));
|
||||||
|
|
||||||
function getNumberValueText(value: EventRecord): string {
|
function getNumberValueText(value: EventRecord): string {
|
||||||
return formatEventNumberValue(value.event, value.numberValue);
|
return formatEventNumberValue(value.event, value.numberValue);
|
||||||
|
|||||||
@@ -112,7 +112,12 @@
|
|||||||
</t-form-item>
|
</t-form-item>
|
||||||
|
|
||||||
<div class="photo-part">
|
<div class="photo-part">
|
||||||
<photo-scroller v-model="photoList" :loading="isPhotoUploading" @add="capturePhoto" />
|
<photo-scroller
|
||||||
|
v-model="photoList"
|
||||||
|
:photo-items="photoItemList"
|
||||||
|
:loading="isPhotoUploading"
|
||||||
|
@add="capturePhoto"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</t-form>
|
</t-form>
|
||||||
<t-cell-group
|
<t-cell-group
|
||||||
@@ -200,6 +205,7 @@ import type { Customer } from "@/types/Customer";
|
|||||||
import type { EventItem } from "@/types/EventItem";
|
import type { EventItem } from "@/types/EventItem";
|
||||||
import type { EventRecord } from "@/types/EventRecord";
|
import type { EventRecord } from "@/types/EventRecord";
|
||||||
import type { PointAction } from "@/types/Point";
|
import type { PointAction } from "@/types/Point";
|
||||||
|
import { getAttachmentReadURL } from "@/utils/attachment";
|
||||||
import { getEventRecordPhotoURL } from "@/utils/eventRecord";
|
import { getEventRecordPhotoURL } from "@/utils/eventRecord";
|
||||||
import { getEventNumberValuePlaceholder, resolveEventNumberValue } from "@/utils/eventValue";
|
import { getEventNumberValuePlaceholder, resolveEventNumberValue } from "@/utils/eventValue";
|
||||||
import { permissionCodes } from "@/utils/permission";
|
import { permissionCodes } from "@/utils/permission";
|
||||||
@@ -218,6 +224,7 @@ const navBarStore = useNavBarStore();
|
|||||||
|
|
||||||
type EditablePhoto = {
|
type EditablePhoto = {
|
||||||
attachment?: Partial<Attachment>;
|
attachment?: Partial<Attachment>;
|
||||||
|
previewUrl?: string;
|
||||||
tempFileId?: string;
|
tempFileId?: string;
|
||||||
url: string;
|
url: string;
|
||||||
};
|
};
|
||||||
@@ -344,7 +351,7 @@ function getRecordEventName(record: EventRecord): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getRecordPhotoURL(record: EventRecord): string {
|
function getRecordPhotoURL(record: EventRecord): string {
|
||||||
return getEventRecordPhotoURL(record);
|
return getEventRecordPhotoURL(record, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- 扫码 ----------
|
// ---------- 扫码 ----------
|
||||||
@@ -724,7 +731,8 @@ async function loadRecordForEdit(): Promise<void> {
|
|||||||
.filter(item => !!item.id)
|
.filter(item => !!item.id)
|
||||||
.map(item => ({
|
.map(item => ({
|
||||||
attachment: item,
|
attachment: item,
|
||||||
url: AttachmentAPI.getReadURL(item.id || "")
|
previewUrl: getAttachmentReadURL(item.id || ""),
|
||||||
|
url: getAttachmentReadURL(item.id || "", 64)
|
||||||
}));
|
}));
|
||||||
await loadRecentRecordList();
|
await loadRecentRecordList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ function getRecordCustomerName(record: EventRecordListItemView): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getRecordPhotoURL(record: EventRecordListItemView): string {
|
function getRecordPhotoURL(record: EventRecordListItemView): string {
|
||||||
return getCustomerPhotoURL(record.customer);
|
return getCustomerPhotoURL(record.customer, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRecordCustomerInitial(record: EventRecordListItemView): string {
|
function getRecordCustomerInitial(record: EventRecordListItemView): string {
|
||||||
|
|||||||
@@ -57,8 +57,8 @@
|
|||||||
>
|
>
|
||||||
<template #left-icon>
|
<template #left-icon>
|
||||||
<t-image
|
<t-image
|
||||||
v-if="getCustomerPhotoURL(item.customer)"
|
v-if="getCustomerPhotoURL(item.customer, 64)"
|
||||||
:src="getCustomerPhotoURL(item.customer)"
|
:src="getCustomerPhotoURL(item.customer, 64)"
|
||||||
:alt="getCustomerName(item)"
|
:alt="getCustomerName(item)"
|
||||||
fit="cover"
|
fit="cover"
|
||||||
class="avatar"
|
class="avatar"
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ import type { Customer } from "@/types/Customer";
|
|||||||
import type { EventItem } from "@/types/EventItem";
|
import type { EventItem } from "@/types/EventItem";
|
||||||
import type { PointAction } from "@/types/Point";
|
import type { PointAction } from "@/types/Point";
|
||||||
import { getEventNumberValuePlaceholder, resolveEventNumberValue } from "@/utils/eventValue";
|
import { getEventNumberValuePlaceholder, resolveEventNumberValue } from "@/utils/eventValue";
|
||||||
|
import { getAttachmentReadURL } from "@/utils/attachment";
|
||||||
import { permissionCodes } from "@/utils/permission";
|
import { permissionCodes } from "@/utils/permission";
|
||||||
import { loadSourceValueConfig, type SourceValueConfig } from "@/utils/point";
|
import { loadSourceValueConfig, type SourceValueConfig } from "@/utils/point";
|
||||||
import { compressUploadImage, compressUploadImageList } from "@/utils/imageCompression";
|
import { compressUploadImage, compressUploadImageList } from "@/utils/imageCompression";
|
||||||
@@ -261,6 +262,7 @@ type CustomerAttachmentType = "PHOTO" | "POINT_CARD" | "OTHER";
|
|||||||
type QuickCustomerPhoto = {
|
type QuickCustomerPhoto = {
|
||||||
attachment?: Attachment;
|
attachment?: Attachment;
|
||||||
attachType: CustomerAttachmentType;
|
attachType: CustomerAttachmentType;
|
||||||
|
previewUrl?: string;
|
||||||
tempFileId?: string;
|
tempFileId?: string;
|
||||||
url: string;
|
url: string;
|
||||||
};
|
};
|
||||||
@@ -530,7 +532,8 @@ function syncCustomerPhoto(customer?: Customer): void {
|
|||||||
.map(item => ({
|
.map(item => ({
|
||||||
attachment: item,
|
attachment: item,
|
||||||
attachType: normalizeCustomerAttachmentType(item.attachType),
|
attachType: normalizeCustomerAttachmentType(item.attachType),
|
||||||
url: AttachmentAPI.getReadURL(item.id || "")
|
previewUrl: getAttachmentReadURL(item.id || ""),
|
||||||
|
url: getAttachmentReadURL(item.id || "", 64)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,8 +54,8 @@
|
|||||||
>
|
>
|
||||||
<template #leftIcon>
|
<template #leftIcon>
|
||||||
<t-image
|
<t-image
|
||||||
v-if="getEventRecordPhotoURL(item)"
|
v-if="getEventRecordPhotoURL(item, 64)"
|
||||||
:src="getEventRecordPhotoURL(item)"
|
:src="getEventRecordPhotoURL(item, 64)"
|
||||||
:alt="item.event?.name || '未知事件'"
|
:alt="item.event?.name || '未知事件'"
|
||||||
fit="cover"
|
fit="cover"
|
||||||
class="record-photo"
|
class="record-photo"
|
||||||
|
|||||||
@@ -82,8 +82,8 @@
|
|||||||
>
|
>
|
||||||
<template #leftIcon>
|
<template #leftIcon>
|
||||||
<t-image
|
<t-image
|
||||||
v-if="getCustomerPhotoURL(item.customer!)"
|
v-if="getCustomerPhotoURL(item.customer!, 64)"
|
||||||
:src="getCustomerPhotoURL(item.customer!)"
|
:src="getCustomerPhotoURL(item.customer!, 64)"
|
||||||
fit="cover"
|
fit="cover"
|
||||||
class="avatar"
|
class="avatar"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export type CustomerAttachmentType = "PHOTO" | "POINT_CARD" | "OTHER";
|
|||||||
export type EditableCustomerPhoto = {
|
export type EditableCustomerPhoto = {
|
||||||
attachment?: Attachment;
|
attachment?: Attachment;
|
||||||
attachType: CustomerAttachmentType;
|
attachType: CustomerAttachmentType;
|
||||||
|
previewUrl?: string;
|
||||||
tempFileId?: string;
|
tempFileId?: string;
|
||||||
url: string;
|
url: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { AttachmentAPI } from "timi-web";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取附件读取地址。
|
||||||
|
*
|
||||||
|
* @param id 附件 ID
|
||||||
|
* @param thumbnailSize 缩略图尺寸,不传时返回原图地址
|
||||||
|
*/
|
||||||
|
export function getAttachmentReadURL(id: string, thumbnailSize?: number): string {
|
||||||
|
const url = AttachmentAPI.getReadURL(id);
|
||||||
|
if (thumbnailSize === undefined) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
thumbWidth: String(thumbnailSize),
|
||||||
|
thumbHeight: String(thumbnailSize)
|
||||||
|
});
|
||||||
|
const separator = url.includes("?") ? "&" : "?";
|
||||||
|
return `${url}${separator}${params.toString()}`;
|
||||||
|
}
|
||||||
+2
-11
@@ -1,5 +1,5 @@
|
|||||||
import { AttachmentAPI } from "timi-web";
|
|
||||||
import type { BodyAreaValue, Customer } from "@/types/Customer";
|
import type { BodyAreaValue, Customer } from "@/types/Customer";
|
||||||
|
import { getAttachmentReadURL } from "@/utils/attachment";
|
||||||
|
|
||||||
export function getCustomerPhotoURL(customer?: Customer, thumbnailSize?: number): string {
|
export function getCustomerPhotoURL(customer?: Customer, thumbnailSize?: number): string {
|
||||||
return getCustomerAttachmentURL(customer, "PHOTO", thumbnailSize);
|
return getCustomerAttachmentURL(customer, "PHOTO", thumbnailSize);
|
||||||
@@ -14,16 +14,7 @@ function getCustomerAttachmentURL(customer: Customer | undefined, attachType: st
|
|||||||
if (!attachment?.id) {
|
if (!attachment?.id) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
const url = AttachmentAPI.getReadURL(attachment.id);
|
return getAttachmentReadURL(attachment.id, thumbnailSize);
|
||||||
if (thumbnailSize === undefined) {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
const params = new URLSearchParams({
|
|
||||||
thumbWidth: String(thumbnailSize),
|
|
||||||
thumbHeight: String(thumbnailSize)
|
|
||||||
});
|
|
||||||
return `${url}?${params.toString()}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function normalizeBodyAreaValue(value: unknown): BodyAreaValue {
|
export function normalizeBodyAreaValue(value: unknown): BodyAreaValue {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { AttachmentAPI } from "timi-web";
|
|
||||||
import type { EventRecord } from "@/types/EventRecord";
|
import type { EventRecord } from "@/types/EventRecord";
|
||||||
|
import { getAttachmentReadURL } from "@/utils/attachment";
|
||||||
|
|
||||||
export function getEventRecordPhotoURL(record?: EventRecord): string {
|
export function getEventRecordPhotoURL(record?: EventRecord, thumbnailSize?: number): string {
|
||||||
const attachment = record?.attachmentList?.find(item => item.attachType === "PHOTO") || record?.attachmentList?.[0];
|
const attachment = record?.attachmentList?.find(item => item.attachType === "PHOTO") || record?.attachmentList?.[0];
|
||||||
if (!attachment?.id) {
|
if (!attachment?.id) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return AttachmentAPI.getReadURL(attachment.id);
|
return getAttachmentReadURL(attachment.id, thumbnailSize);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user