fix store diary style

This commit is contained in:
Timi
2026-09-01 14:07:23 +08:00
parent 2d94abfb32
commit 9043f7600d
6 changed files with 314 additions and 65 deletions
+126 -8
View File
@@ -21,6 +21,26 @@
placeholder="可填写本篇日记摘要"
/>
</t-form-item>
<section class="photo-wrapper" v-entrance-transition="140">
<photo-scroller
v-model="photoList"
v-model:photo-items="photoItemList"
title="附加照片"
:edit-mode="true"
:loading="isPhotoUploading"
:show-type-label="false"
:show-viewer-actions="false"
@add="openPhotoPicker"
/>
<input
ref="photoInputRef"
class="file-input"
type="file"
accept="image/*"
multiple
@change="handlePhotoSelected"
>
</section>
<section class="editor-wrapper" v-entrance-transition="70">
<article-editor
ref="articleEditorRef"
@@ -44,13 +64,15 @@ import {
type ArticleEditorExpose,
type UploadResult
} from "timi-tdesign-mobile";
import { AttachmentAPI, useUserStore } from "timi-web-api";
import { AttachmentAPI, type Attachment, useUserStore } from "timi-web-api";
import StoreDiaryAPI from "@/api/StoreDiaryAPI";
import PhotoScroller from "@/components/PhotoScroller.vue";
import { useCurrentStoreStore } from "@/store/currentStoreStore";
import { useNavBarStore } from "@/store/navBarStore";
import type { StoreDiary } from "@/types/StoreDiary";
import type { PhotoItem } from "@/types/Photo";
import { getErrorMessage } from "@/utils/error";
import { compressUploadImage } from "@/utils/imageCompression";
import { compressUploadImage, compressUploadImageList } from "@/utils/imageCompression";
import { getAttachmentReadURL } from "@/utils/attachment";
import { Message } from "@/utils/message";
import { permissionCodes } from "@/utils/permission";
@@ -105,6 +127,83 @@ function updateArticle(value: ArticleEditorArticle): void {
};
}
// ---------- 附加照片 ----------
const photoInputRef = ref<HTMLInputElement>();
const photoItemList = ref<PhotoItem[]>([]);
const isPhotoUploading = ref(false);
const photoList = computed<string[]>({
get: () => photoItemList.value.map(item => item.url),
set: value => {
const urlSet = new Set(value);
photoItemList.value = photoItemList.value.filter(item => urlSet.has(item.url));
}
});
function openPhotoPicker(): 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 tempFileList = await AttachmentAPI.upload(await compressUploadImageList(fileList));
for (const tempFile of tempFileList) {
if (!tempFile.id) {
continue;
}
photoItemList.value.push({
tempFileId: tempFile.id,
attachType: "ADDITIONAL",
url: AttachmentAPI.getTempReadURL(tempFile.id)
});
}
} catch (error) {
Message.error(getErrorMessage(error, "附加照片上传失败"));
} finally {
isPhotoUploading.value = false;
input.value = "";
}
}
function buildPhotoItemList(attachmentList?: StoreDiary["attachmentList"]): PhotoItem[] {
return (attachmentList || []).flatMap(item => {
if (item.attachType !== "ADDITIONAL" || !item.id) {
return [];
}
return [{
attachment: item as Partial<Attachment>,
attachType: "ADDITIONAL",
previewUrl: getAttachmentReadURL(item.id),
url: getAttachmentReadURL(item.id, 90)
}];
});
}
function buildAdditionalAttachmentList(): Attachment[] {
return photoItemList.value.flatMap(item => {
if (item.attachment) {
return [{
...item.attachment,
attachType: "ADDITIONAL"
}];
}
if (item.tempFileId) {
return [{
attachType: "ADDITIONAL",
tempFileId: item.tempFileId
}];
}
return [];
});
}
const selectedStoreName = computed(() => {
const store = currentStoreStore.storeList.find(item => item.id === article.value.bizId)
|| (currentStoreStore.loginStore?.id === article.value.bizId ? currentStoreStore.loginStore : undefined);
@@ -187,7 +286,10 @@ async function save(): Promise<void> {
description: article.value.description?.trim() || "",
contentType: normalizeContentType(editorValue?.contentType ?? article.value.contentType),
content: editorValue?.content ?? article.value.content ?? "",
attachmentList: editorValue?.attachmentList ?? article.value.attachmentList ?? [],
attachmentList: [
...(editorValue?.attachmentList ?? article.value.attachmentList ?? []).filter(item => item.attachType !== "ADDITIONAL"),
...buildAdditionalAttachmentList()
],
status: article.value.status || "NORMAL"
};
if (!validateArticle(value)) {
@@ -234,6 +336,7 @@ async function loadArticle(): Promise<void> {
...createEmptyArticle(),
bizId: article.value.bizId || currentStoreStore.currentStoreId
};
photoItemList.value = [];
return;
}
@@ -246,6 +349,7 @@ async function loadArticle(): Promise<void> {
content: result.content || "",
attachmentList: result.attachmentList || []
};
photoItemList.value = buildPhotoItemList(result.attachmentList);
}
onMounted(async () => {
@@ -278,9 +382,10 @@ onUnmounted(() => navBarStore.clearRight());
.editor-wrapper {
width: 100%;
overflow: visible;
min-width: 0;
max-width: 100%;
overflow: visible;
border-top: 1px solid var(--td-component-border);
.editor {
width: 100%;
@@ -292,23 +397,28 @@ onUnmounted(() => navBarStore.clearRight());
:deep(.tp-editor) {
width: 100%;
height: auto;
min-width: 0;
max-width: 100%;
height: auto;
overflow: visible;
}
:deep(.content) {
padding: 0;
overflow: visible;
.value {
border-radius: 0;
}
}
:deep(.toolbar) {
width: 100%;
min-width: 0;
max-width: 100%;
top: var(--app-nav-height);
width: 100%;
z-index: 10;
position: sticky;
min-width: 0;
max-width: 100%;
}
:deep(.toolbar .scroll) {
@@ -317,6 +427,14 @@ onUnmounted(() => navBarStore.clearRight());
max-width: 100%;
}
}
.photo-wrapper {
padding: 1rem;
.file-input {
display: none;
}
}
}
}
</style>