2025-03-05 17:13:23 +08:00
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { Button } from 'ant-design-vue'
|
2025-03-05 18:12:55 +08:00
|
|
|
|
import { ref, watchEffect } from 'vue'
|
|
|
|
|
import { useFileDialog } from '@vueuse/core'
|
2025-03-06 14:24:08 +08:00
|
|
|
|
import { useRouter } from 'vue-router'
|
2025-03-05 17:13:23 +08:00
|
|
|
|
import { IFrame } from '@/components/IFrame'
|
|
|
|
|
import { FileSelectModal } from '@/components/FileSelect'
|
|
|
|
|
import { useModal } from '@/components/Modal'
|
|
|
|
|
import type { FileVO } from '@/api/infra/file'
|
|
|
|
|
import { initFilePreviewUrl } from '@/utils/file/preview'
|
2025-03-06 14:24:08 +08:00
|
|
|
|
import type { BookmarkGenData, BookmarkQueryRespVo, PictureExData, TextExData } from '@/api/infra/bookmark'
|
|
|
|
|
import { getAllBookmarks, getDoBookmarkReplace } from '@/api/infra/bookmark'
|
2025-03-05 18:12:55 +08:00
|
|
|
|
import { useMessage } from '@/hooks/web/useMessage'
|
2025-03-06 14:24:08 +08:00
|
|
|
|
import { convertFileToBase64 } from '@/utils/file/base64Conver'
|
2025-03-05 17:13:23 +08:00
|
|
|
|
|
|
|
|
|
defineOptions({ name: 'BookmarkReplace' })
|
|
|
|
|
|
|
|
|
|
const previewUrl = ref<string | undefined>(undefined)
|
|
|
|
|
|
|
|
|
|
const [registerModal, { openModal }] = useModal()
|
|
|
|
|
|
|
|
|
|
const currentEditFile = ref<FileVO | undefined>(undefined)
|
|
|
|
|
|
|
|
|
|
async function handleSelect(file: FileVO) {
|
|
|
|
|
currentEditFile.value = file
|
|
|
|
|
|
|
|
|
|
previewUrl.value = await initFilePreviewUrl(file.id)
|
2025-03-05 18:12:55 +08:00
|
|
|
|
|
|
|
|
|
await handleQueryBookmark()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bookmarks = ref<BookmarkQueryRespVo[]>([])
|
|
|
|
|
|
|
|
|
|
interface FormItemType {
|
|
|
|
|
name: string
|
2025-03-06 14:24:08 +08:00
|
|
|
|
type: 'PICTURE_DESC' | 'PICTURE' | 'TEXT'
|
2025-03-05 18:12:55 +08:00
|
|
|
|
value: string | File
|
2025-03-06 14:24:08 +08:00
|
|
|
|
fileName: string
|
|
|
|
|
width: number
|
|
|
|
|
height: number
|
2025-03-05 18:12:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const formItems = ref<FormItemType[]>([])
|
2025-03-06 14:24:08 +08:00
|
|
|
|
const initFinish = ref<boolean>(false)
|
2025-03-05 18:12:55 +08:00
|
|
|
|
watchEffect(() => {
|
|
|
|
|
if (currentEditFile.value) {
|
|
|
|
|
bookmarks.value = []
|
|
|
|
|
formItems.value = []
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const { createMessage } = useMessage()
|
|
|
|
|
|
|
|
|
|
async function handleQueryBookmark() {
|
|
|
|
|
bookmarks.value = []
|
|
|
|
|
formItems.value = []
|
2025-03-06 14:24:08 +08:00
|
|
|
|
initFinish.value = false
|
2025-03-05 18:12:55 +08:00
|
|
|
|
if (currentEditFile.value)
|
|
|
|
|
bookmarks.value = await getAllBookmarks(currentEditFile.value.id)
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
createMessage.error('请选择文件!')
|
|
|
|
|
|
2025-03-06 14:24:08 +08:00
|
|
|
|
for (const bk of bookmarks.value)
|
|
|
|
|
formItems.value.push({ name: bk.name, type: bk.type, value: '', fileName: '', width: 0, height: 0 })
|
2025-03-05 18:12:55 +08:00
|
|
|
|
|
2025-03-06 14:24:08 +08:00
|
|
|
|
initFinish.value = true
|
2025-03-05 18:12:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const { files, open, reset, onChange } = useFileDialog({
|
|
|
|
|
accept: 'image/*',
|
|
|
|
|
directory: false,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
let currentEdit
|
|
|
|
|
|
|
|
|
|
function handleSelectPicture(item: FormItemType) {
|
|
|
|
|
reset()
|
|
|
|
|
open()
|
|
|
|
|
currentEdit = item
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onChange(() => {
|
|
|
|
|
if (files.value?.length && files.value?.length > 0 && currentEdit) {
|
|
|
|
|
const file = files.value.item(0)
|
|
|
|
|
if (file) {
|
|
|
|
|
currentEdit.value = file
|
|
|
|
|
currentEdit.fileName = file.name
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2025-03-06 14:24:08 +08:00
|
|
|
|
const router = useRouter()
|
|
|
|
|
|
|
|
|
|
async function handleGenerateNew() {
|
|
|
|
|
if (currentEditFile.value) {
|
|
|
|
|
const data: BookmarkGenData[] = []
|
|
|
|
|
for (const item of formItems.value) {
|
|
|
|
|
if (!item.value)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if (item.type === 'TEXT') {
|
|
|
|
|
data.push({ name: item.name, extData: {
|
|
|
|
|
type: 'TEXT',
|
|
|
|
|
value: item.value as string,
|
|
|
|
|
} as TextExData })
|
|
|
|
|
}
|
|
|
|
|
if (item.type === 'PICTURE') {
|
|
|
|
|
const file = item.value as File
|
|
|
|
|
data.push({ name: item.name, extData: {
|
|
|
|
|
type: 'PICTURE',
|
|
|
|
|
value: await convertFileToBase64(item.value as File),
|
|
|
|
|
width: item.width,
|
|
|
|
|
height: item.height,
|
|
|
|
|
pictureName: file.name,
|
|
|
|
|
dataType: 'BASE64',
|
|
|
|
|
} as PictureExData })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item.type === 'PICTURE_DESC') {
|
|
|
|
|
const file = item.value as File
|
|
|
|
|
data.push({ name: item.name, extData: {
|
|
|
|
|
type: 'PICTURE_DESC',
|
|
|
|
|
value: await convertFileToBase64(item.value as File),
|
|
|
|
|
pictureName: file.name,
|
|
|
|
|
dataType: 'BASE64',
|
|
|
|
|
} as PictureExData })
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-03-05 18:12:55 +08:00
|
|
|
|
|
2025-03-06 14:24:08 +08:00
|
|
|
|
if (data.length <= 0) {
|
|
|
|
|
createMessage.error('请填写替换值!')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const result = await getDoBookmarkReplace(currentEditFile.value.id, data)
|
|
|
|
|
const previewUrl = await initFilePreviewUrl(result)
|
|
|
|
|
const encode = encodeURIComponent(previewUrl)
|
|
|
|
|
await router.push(`/infra/file/file-preview?url=${encode}`)
|
|
|
|
|
}
|
2025-03-05 17:13:23 +08:00
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<div>
|
|
|
|
|
<div class="flex flex-col p-2 pt-4">
|
|
|
|
|
<div class="h-[calc(100vh-105px)] w-full flex flex-row">
|
|
|
|
|
<div class="mr-2 h-full w-25% flex flex-col">
|
|
|
|
|
<div class="mb-2 flex flex-row items-center justify-between rounded bg-white px-2 py-2 dark:bg-black">
|
|
|
|
|
<div class="flex flex-row items-center">
|
|
|
|
|
<Button type="primary" class="mr-2" @click="openModal()">
|
|
|
|
|
选择文件
|
|
|
|
|
</Button>
|
|
|
|
|
: {{ currentEditFile?.name }}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="flex flex-row items-center">
|
2025-03-05 18:12:55 +08:00
|
|
|
|
<Button @click="handleQueryBookmark">
|
2025-03-05 17:13:23 +08:00
|
|
|
|
获取书签
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-03-05 18:12:55 +08:00
|
|
|
|
<div class="h-full w-full overflow-scroll rounded bg-white p-4 dark:bg-black">
|
|
|
|
|
<a-form
|
2025-03-06 14:24:08 +08:00
|
|
|
|
v-if="initFinish"
|
2025-03-05 18:12:55 +08:00
|
|
|
|
class="w-full"
|
|
|
|
|
layout="vertical"
|
|
|
|
|
:label-col="{ span: 16 }"
|
|
|
|
|
>
|
|
|
|
|
<a-col v-for="(item) in formItems" :key="item.name">
|
|
|
|
|
<a-form-item :label="item.name">
|
2025-03-06 14:24:08 +08:00
|
|
|
|
<a-radio-group v-model:value="item.type" :disabled="item.type === 'PICTURE_DESC'" @change="item.value = null">
|
2025-03-05 18:12:55 +08:00
|
|
|
|
<a-radio value="TEXT">
|
|
|
|
|
文本
|
|
|
|
|
</a-radio>
|
|
|
|
|
<a-radio value="PICTURE">
|
|
|
|
|
图片
|
|
|
|
|
</a-radio>
|
|
|
|
|
<a-radio v-if="item.type === 'PICTURE_DESC'" value="PICTURE_DESC" :disabled="true">
|
|
|
|
|
图片(替换)
|
|
|
|
|
</a-radio>
|
|
|
|
|
</a-radio-group>
|
2025-03-06 14:24:08 +08:00
|
|
|
|
</a-form-item>
|
|
|
|
|
<a-form-item label="替换值">
|
|
|
|
|
<a-input v-if="item.type === 'TEXT'" v-model:value="item.value" />
|
2025-03-05 18:12:55 +08:00
|
|
|
|
<a-button v-if="item.type.includes('PICTURE')" @click="handleSelectPicture(item)">
|
|
|
|
|
选择图片
|
|
|
|
|
</a-button>
|
|
|
|
|
<p v-if="item.type.includes('PICTURE') && item.value && item?.fileName" class="overflow-hidden">
|
|
|
|
|
{{ item?.fileName }}
|
|
|
|
|
</p>
|
|
|
|
|
</a-form-item>
|
2025-03-06 14:24:08 +08:00
|
|
|
|
<a-form-item v-if="item.type === 'PICTURE'" label="图片 宽(px)">
|
|
|
|
|
<a-input v-model:value="item.width" type="number" />
|
|
|
|
|
</a-form-item>
|
|
|
|
|
<a-form-item v-if="item.type === 'PICTURE'" label="图片 高(px)">
|
|
|
|
|
<a-input v-model:value="item.height" type="number" />
|
|
|
|
|
</a-form-item>
|
2025-03-05 18:12:55 +08:00
|
|
|
|
<a-divider />
|
|
|
|
|
</a-col>
|
|
|
|
|
</a-form>
|
|
|
|
|
|
|
|
|
|
<a-button v-if="formItems.length > 0" type="primary" @click="handleGenerateNew">
|
|
|
|
|
生成替换后文件
|
|
|
|
|
</a-button>
|
2025-03-05 17:13:23 +08:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="w-75% flex flex-row bg-white dark:bg-black">
|
|
|
|
|
<i-frame v-if="previewUrl" class="w-full bg-white dark:bg-black" :src="previewUrl" height="calc(100vh - 105px)" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<FileSelectModal v-bind="$attrs" @register="registerModal" @select="handleSelect" />
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|