wip: bookmark replace
This commit is contained in:
parent
de38bca939
commit
0ed5dd9d06
@ -9,7 +9,7 @@ export interface BookmarkQueryRespVo {
|
|||||||
name: string
|
name: string
|
||||||
|
|
||||||
/** 类型 */
|
/** 类型 */
|
||||||
type?: BookmarkType
|
type: BookmarkType
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BookmarkGenData {
|
export interface BookmarkGenData {
|
||||||
@ -17,7 +17,7 @@ export interface BookmarkGenData {
|
|||||||
name: string
|
name: string
|
||||||
|
|
||||||
/** 扩展类型 */
|
/** 扩展类型 */
|
||||||
extData: PictureExData | TextExData
|
extData: AbstractExData
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 书签需要替换的数据类型(文本,图片,图片(描述)) */
|
/** 书签需要替换的数据类型(文本,图片,图片(描述)) */
|
||||||
@ -38,8 +38,8 @@ interface AbstractExData {
|
|||||||
* 图片数据
|
* 图片数据
|
||||||
*/
|
*/
|
||||||
export interface PictureExData extends AbstractExData {
|
export interface PictureExData extends AbstractExData {
|
||||||
width: number
|
width?: number
|
||||||
height: number
|
height?: number
|
||||||
pictureName: string
|
pictureName: string
|
||||||
dataType: PictureProvideDataType
|
dataType: PictureProvideDataType
|
||||||
}
|
}
|
||||||
@ -65,6 +65,6 @@ export function getAllBookmarks(fileId: string | number) {
|
|||||||
* @param fileId 文件id
|
* @param fileId 文件id
|
||||||
* @param data 数据
|
* @param data 数据
|
||||||
*/
|
*/
|
||||||
export function getDoBookmarkReplace(fileId: string | number, data: BookmarkGenData) {
|
export function getDoBookmarkReplace(fileId: string | number, data: BookmarkGenData[]) {
|
||||||
return defHttp.post({ url: `/infra/word/bookmark/file/${fileId}/generate`, data })
|
return defHttp.post({ url: `/infra/word/bookmark/file/${fileId}/generate`, data })
|
||||||
}
|
}
|
||||||
|
@ -40,3 +40,36 @@ export function urlToBase64(url: string, mineType?: string): Promise<string> {
|
|||||||
img.src = url
|
img.src = url
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function convertFileToBase64(file: File): Promise<string> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader()
|
||||||
|
|
||||||
|
reader.onload = () => {
|
||||||
|
if (reader.result === null) {
|
||||||
|
reject(new Error('FileReader result is null'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataUrl = reader.result.toString()
|
||||||
|
const base64Data = dataUrl.split(',')[1]
|
||||||
|
|
||||||
|
if (!base64Data) {
|
||||||
|
reject(new Error('Data URL does not contain base64 data'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(base64Data)
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.onerror = () => {
|
||||||
|
reject(reader.error || new Error('Unknown error occurred while reading the file'))
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.onabort = () => {
|
||||||
|
reject(new Error('File reading was aborted'))
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.readAsDataURL(file)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { getConfigKey } from '@/api/infra/config'
|
import { getConfigKey } from '@/api/infra/config'
|
||||||
|
import { getAccessToken } from '@/utils/auth'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取文件预览地址
|
* 获取文件预览地址
|
||||||
@ -7,5 +8,6 @@ import { getConfigKey } from '@/api/infra/config'
|
|||||||
export async function initFilePreviewUrl(fileId: string | number): Promise<string> {
|
export async function initFilePreviewUrl(fileId: string | number): Promise<string> {
|
||||||
const wopi_client = await getConfigKey('wopi_client_addr')
|
const wopi_client = await getConfigKey('wopi_client_addr')
|
||||||
const wopi_server = await getConfigKey('wopi_server_ip_addr')
|
const wopi_server = await getConfigKey('wopi_server_ip_addr')
|
||||||
return `${wopi_client}?lang=zh-cn&WOPISrc=${wopi_server}/admin-api/infra/file/preview/wopi/files/${fileId}`
|
const wopi = `${wopi_server}/admin-api/infra/file/preview/wopi/files/${fileId}?access_token=${getAccessToken()}`
|
||||||
|
return `${wopi_client}?lang=zh-cn&WOPISrc=${encodeURIComponent(wopi)}`
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,16 @@
|
|||||||
import { Button } from 'ant-design-vue'
|
import { Button } from 'ant-design-vue'
|
||||||
import { ref, watchEffect } from 'vue'
|
import { ref, watchEffect } from 'vue'
|
||||||
import { useFileDialog } from '@vueuse/core'
|
import { useFileDialog } from '@vueuse/core'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
import { IFrame } from '@/components/IFrame'
|
import { IFrame } from '@/components/IFrame'
|
||||||
import { FileSelectModal } from '@/components/FileSelect'
|
import { FileSelectModal } from '@/components/FileSelect'
|
||||||
import { useModal } from '@/components/Modal'
|
import { useModal } from '@/components/Modal'
|
||||||
import type { FileVO } from '@/api/infra/file'
|
import type { FileVO } from '@/api/infra/file'
|
||||||
import { initFilePreviewUrl } from '@/utils/file/preview'
|
import { initFilePreviewUrl } from '@/utils/file/preview'
|
||||||
import type { BookmarkQueryRespVo } from '@/api/infra/bookmark'
|
import type { BookmarkGenData, BookmarkQueryRespVo, PictureExData, TextExData } from '@/api/infra/bookmark'
|
||||||
import { getAllBookmarks } from '@/api/infra/bookmark'
|
import { getAllBookmarks, getDoBookmarkReplace } from '@/api/infra/bookmark'
|
||||||
import { useMessage } from '@/hooks/web/useMessage'
|
import { useMessage } from '@/hooks/web/useMessage'
|
||||||
|
import { convertFileToBase64 } from '@/utils/file/base64Conver'
|
||||||
|
|
||||||
defineOptions({ name: 'BookmarkReplace' })
|
defineOptions({ name: 'BookmarkReplace' })
|
||||||
|
|
||||||
@ -31,13 +33,15 @@ const bookmarks = ref<BookmarkQueryRespVo[]>([])
|
|||||||
|
|
||||||
interface FormItemType {
|
interface FormItemType {
|
||||||
name: string
|
name: string
|
||||||
type: string
|
type: 'PICTURE_DESC' | 'PICTURE' | 'TEXT'
|
||||||
value: string | File
|
value: string | File
|
||||||
fileName?: string
|
fileName: string
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const formItems = ref<FormItemType[]>([])
|
const formItems = ref<FormItemType[]>([])
|
||||||
|
const initFinish = ref<boolean>(false)
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (currentEditFile.value) {
|
if (currentEditFile.value) {
|
||||||
bookmarks.value = []
|
bookmarks.value = []
|
||||||
@ -50,21 +54,17 @@ const { createMessage } = useMessage()
|
|||||||
async function handleQueryBookmark() {
|
async function handleQueryBookmark() {
|
||||||
bookmarks.value = []
|
bookmarks.value = []
|
||||||
formItems.value = []
|
formItems.value = []
|
||||||
|
initFinish.value = false
|
||||||
if (currentEditFile.value)
|
if (currentEditFile.value)
|
||||||
bookmarks.value = await getAllBookmarks(currentEditFile.value.id)
|
bookmarks.value = await getAllBookmarks(currentEditFile.value.id)
|
||||||
|
|
||||||
else
|
else
|
||||||
createMessage.error('请选择文件!')
|
createMessage.error('请选择文件!')
|
||||||
|
|
||||||
for (const bk of bookmarks.value) {
|
for (const bk of bookmarks.value)
|
||||||
let type = ''
|
formItems.value.push({ name: bk.name, type: bk.type, value: '', fileName: '', width: 0, height: 0 })
|
||||||
if (!bk.type)
|
|
||||||
type = 'TEXT'
|
|
||||||
else
|
|
||||||
type = bk.type
|
|
||||||
|
|
||||||
formItems.value.push({ name: bk.name, type, value: '' })
|
initFinish.value = true
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { files, open, reset, onChange } = useFileDialog({
|
const { files, open, reset, onChange } = useFileDialog({
|
||||||
@ -90,8 +90,54 @@ onChange(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
function handleGenerateNew() {
|
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 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -115,13 +161,14 @@ function handleGenerateNew() {
|
|||||||
</div>
|
</div>
|
||||||
<div class="h-full w-full overflow-scroll rounded bg-white p-4 dark:bg-black">
|
<div class="h-full w-full overflow-scroll rounded bg-white p-4 dark:bg-black">
|
||||||
<a-form
|
<a-form
|
||||||
|
v-if="initFinish"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
:label-col="{ span: 16 }"
|
:label-col="{ span: 16 }"
|
||||||
>
|
>
|
||||||
<a-col v-for="(item) in formItems" :key="item.name">
|
<a-col v-for="(item) in formItems" :key="item.name">
|
||||||
<a-form-item :label="item.name">
|
<a-form-item :label="item.name">
|
||||||
<a-radio-group v-model:value="item.type" class="mb-2" :disabled="item.type === 'PICTURE_DESC'">
|
<a-radio-group v-model:value="item.type" :disabled="item.type === 'PICTURE_DESC'" @change="item.value = null">
|
||||||
<a-radio value="TEXT">
|
<a-radio value="TEXT">
|
||||||
文本
|
文本
|
||||||
</a-radio>
|
</a-radio>
|
||||||
@ -132,7 +179,9 @@ function handleGenerateNew() {
|
|||||||
图片(替换)
|
图片(替换)
|
||||||
</a-radio>
|
</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
<a-input v-if="item.type === 'TEXT'" />
|
</a-form-item>
|
||||||
|
<a-form-item label="替换值">
|
||||||
|
<a-input v-if="item.type === 'TEXT'" v-model:value="item.value" />
|
||||||
<a-button v-if="item.type.includes('PICTURE')" @click="handleSelectPicture(item)">
|
<a-button v-if="item.type.includes('PICTURE')" @click="handleSelectPicture(item)">
|
||||||
选择图片
|
选择图片
|
||||||
</a-button>
|
</a-button>
|
||||||
@ -140,6 +189,12 @@ function handleGenerateNew() {
|
|||||||
{{ item?.fileName }}
|
{{ item?.fileName }}
|
||||||
</p>
|
</p>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<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>
|
||||||
<a-divider />
|
<a-divider />
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
Loading…
Reference in New Issue
Block a user