fix store diary style
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user