From aa16a494bdf8a44f57ac832756f565dfbf94772b Mon Sep 17 00:00:00 2001 From: lq1405 <2769838458@qq.com> Date: Sun, 21 Sep 2025 10:20:33 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=89=AA=E6=98=A0=E8=8D=89?= =?UTF-8?q?=E7=A8=BF=E7=94=9F=E6=88=90=EF=BC=8C=E4=BF=AE=E6=94=B9=E5=AD=97?= =?UTF-8?q?=E5=B9=95=E5=88=86=E7=BB=84=E6=8A=A5=E9=94=99=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=8A=A0=E8=BD=BD=E6=A0=87=E7=AD=BE=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E9=A2=84=E8=AE=BE=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 3 +- src/define/data/softwareData.ts | 2 +- src/define/db/service/book/bookTaskService.ts | 8 ++ src/i18n/locales/en.ts | 2 +- src/i18n/locales/zh-cn.ts | 2 +- .../book/subBookHandle/bookExportHandle.ts | 13 --- src/renderer/src/common/book.ts | 87 ----------------- .../BookTaskDetail/AllImagePreview.vue | 96 +++++++++++-------- .../DatatableCharacterAndSceneAndStyle.vue | 3 +- .../DatatableHeaderCharacter.vue | 10 ++ .../BookTaskDetail/MessageAndProgress.vue | 9 +- .../Original/Copywriter/EditWord.vue | 1 - .../Original/Copywriter/HandGroup.vue | 2 +- .../composables/useWordGroupBase.js | 32 +++++-- .../Original/MainHome/OriginalTaskCard.vue | 10 +- .../src/components/Preset/PresetShowCard.vue | 1 + .../src/components/common/CommonDialog.vue | 7 +- src/renderer/src/stores/subStore/preset.ts | 56 +++++++++++ src/renderer/src/views/PresetLibraryHome.vue | 1 - 19 files changed, 179 insertions(+), 166 deletions(-) diff --git a/package.json b/package.json index 7e7923e..29170cc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "laitool-pro", "productName": "LaiToolPro", - "version": "v3.4.9", + "version": "v4.0.0", "description": "来推 Pro - 一款集音频处理、文案生成、图片生成、视频生成等功能于一体的多合一AI工具软件。", "main": "./out/main/index.js", "author": "xiangbei", @@ -84,6 +84,7 @@ "resources/image/zhanwei.png", "resources/scripts/model/**", "resources/scripts/Lai.exe", + "resources/scripts/xiangbei_jianying_main.exe", "resources/scripts/discordScript.js", "resources/tmp/**", "resources/icon.ico" diff --git a/src/define/data/softwareData.ts b/src/define/data/softwareData.ts index a3e191a..4479c98 100644 --- a/src/define/data/softwareData.ts +++ b/src/define/data/softwareData.ts @@ -31,7 +31,7 @@ interface ISoftwareData { export const SoftwareData: ISoftwareData = { version: 'V3.4.2', - date: '2025-08-08', + date: '2025-09.09', systemInfo: { documentationUrl: 'https://rvgyir5wk1c.feishu.cn/wiki/WdaWwAfDdiLOnjkywIgcaQoKnog', updateUrl: 'https://pvwu1oahp5m.feishu.cn/docx/CAjGdTDlboJ3nVx0cQccOuNHnvd', diff --git a/src/define/db/service/book/bookTaskService.ts b/src/define/db/service/book/bookTaskService.ts index b309307..391f3c4 100644 --- a/src/define/db/service/book/bookTaskService.ts +++ b/src/define/db/service/book/bookTaskService.ts @@ -462,6 +462,14 @@ export class BookTaskService extends RealmBaseService { modifyBookTask.subImageFolder = [] modifyBookTask.srtPath = book.srtPath ?? undefined modifyBookTask.audioPath = book.audioPath ?? undefined + } else { + // 不重置基础数据的话,做一下数据的继承 + if (isEmpty(modifyBookTask.srtPath)) { + modifyBookTask.srtPath = book.srtPath ?? undefined + } + if (isEmpty(modifyBookTask.audioPath)) { + modifyBookTask.audioPath = book.audioPath ?? undefined + } } // 继承小说的srt和配音文件 diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index 2de917e..30dd27b 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -1411,7 +1411,7 @@ export default { '智能合并失败,{error}': 'Smart merge failed, {error}', '智能批量合并完成,所有字幕都已正确匹配': 'Smart batch merge completed, all subtitles matched correctly', '智能合并完成,{count} 个剩余字幕已写入后续行': 'Smart merge completed, {count} remaining subtitles written to subsequent lines', - '处理过程中遇到错误,已停止智能匹配:\n\n{message}\n\n已处理字幕:${totalProcessed} 个\n剩余字幕:${totalRemaining} 个\n\n剩余字幕已按顺序写入后续行中,请手动调整文案匹配。': 'Error encountered during processing, smart matching stopped:\n\n{message}\n\nProcessed subtitles: ${totalProcessed}\nRemaining subtitles: ${totalRemaining}\n\nRemaining subtitles have been written to subsequent lines in order, please manually adjust content matching.', + '处理过程中遇到错误,已停止智能匹配:\n\n{message}\n\n已处理字幕:{totalProcessed} 个\n剩余字幕:{totalRemaining} 个\n\n剩余字幕已按顺序写入后续行中,请手动调整文案匹配。': 'Error encountered during processing, smart matching stopped:\n\n{message}\n\nProcessed subtitles: ${totalProcessed}\nRemaining subtitles: ${totalRemaining}\n\nRemaining subtitles have been written to subsequent lines in order, please manually adjust content matching.', '第 {rowIndex} 行没有找到任何匹配的字幕': 'No matching subtitles found for line {rowIndex}', '第 {rowIndex} 行在处理字幕 “{subtitleText}” 时无法匹配,已累积文本 “{accumulatedText}” 与目标文案 “{text}”不匹配': 'Unable to match subtitle "{subtitleText}" on line {rowIndex}, accumulated text "{accumulatedText}" does not match target content "{text}"', '第 {rowIndex} 行的第一个字幕 “{subtitleText}” 与文案 “{text}” 不匹配': 'The first subtitle "{subtitleText}" on line {rowIndex} does not match the content "{text}"', diff --git a/src/i18n/locales/zh-cn.ts b/src/i18n/locales/zh-cn.ts index 54d7fb3..a9eb9f4 100644 --- a/src/i18n/locales/zh-cn.ts +++ b/src/i18n/locales/zh-cn.ts @@ -1411,7 +1411,7 @@ export default { '智能合并失败,{error}': '智能合并失败,{error}', '智能批量合并完成,所有字幕都已正确匹配': '智能批量合并完成,所有字幕都已正确匹配', '智能合并完成,{count} 个剩余字幕已写入后续行': '智能合并完成,{count} 个剩余字幕已写入后续行', - '处理过程中遇到错误,已停止智能匹配:\n\n{message}\n\n已处理字幕:${totalProcessed} 个\n剩余字幕:${totalRemaining} 个\n\n剩余字幕已按顺序写入后续行中,请手动调整文案匹配。': '处理过程中遇到错误,已停止智能匹配:\n\n{message}\n\n已处理字幕:${totalProcessed} 个\n剩余字幕:${totalRemaining} 个\n\n剩余字幕已按顺序写入后续行中,请手动调整文案匹配。', + '处理过程中遇到错误,已停止智能匹配:\n\n{message}\n\n已处理字幕:{totalProcessed} 个\n剩余字幕:{totalRemaining} 个\n\n剩余字幕已按顺序写入后续行中,请手动调整文案匹配。': '处理过程中遇到错误,已停止智能匹配:\n\n{message}\n\n已处理字幕:{totalProcessed} 个\n剩余字幕:{totalRemaining} 个\n\n剩余字幕已按顺序写入后续行中,请手动调整文案匹配。', '第 {rowIndex} 行没有找到任何匹配的字幕': '第 {rowIndex} 行没有找到任何匹配的字幕', '第 {rowIndex} 行在处理字幕 “{subtitleText}” 时无法匹配,已累积文本 “{accumulatedText}” 与目标文案 “{text}”不匹配': '第 {rowIndex} 行在处理字幕 “{subtitleText}” 时无法匹配,已累积文本 “{accumulatedText}” 与目标文案 “{text}”不匹配', '第 {rowIndex} 行的第一个字幕 “{subtitleText}” 与文案 “{text}” 不匹配': '第 {rowIndex} 行的第一个字幕 “{subtitleText}” 与文案 “{text}” 不匹配', diff --git a/src/main/service/book/subBookHandle/bookExportHandle.ts b/src/main/service/book/subBookHandle/bookExportHandle.ts index 2c13361..7f93168 100644 --- a/src/main/service/book/subBookHandle/bookExportHandle.ts +++ b/src/main/service/book/subBookHandle/bookExportHandle.ts @@ -18,7 +18,6 @@ import { isEmpty } from 'lodash' import { define } from '@/define/define' import util from 'util' import { exec } from 'child_process' -import { BookTaskDetail } from '@/define/model/book/bookTaskDetail' import { ValidateJson } from '@/define/Tools/validate' const execAsync = util.promisify(exec) import JianyingService from '../../jianying/jianyingService' @@ -184,18 +183,6 @@ export class BookExportHandle extends BookBasicHandle { } } - // 时间单位转换:从毫秒转换为秒 - element.startTime = (element.startTime as number) / 1000 - element.endTime = (element.endTime as number) / 1000 - - // 处理子字幕数组,同样进行时间单位转换 - element.subValue = Array.isArray(element.subValue) - ? (element.subValue as BookTaskDetail.CopywritingSubValue[]).map((sub) => { - sub.start_time = sub.start_time / 1000 - sub.end_time = sub.end_time / 1000 - return sub - }) - : [] // 构建单帧数据对象 let frameData = { diff --git a/src/renderer/src/common/book.ts b/src/renderer/src/common/book.ts index bab8567..b0cd8e6 100644 --- a/src/renderer/src/common/book.ts +++ b/src/renderer/src/common/book.ts @@ -1,96 +1,9 @@ -import { PresetCategory } from '@/define/data/presetData' import { Book } from '@/define/model/book/book' import { ErrorItem, SuccessItem } from '@/define/model/generalResponse' -import { PresetModel } from '@/define/model/preset' import { errorMessage, successMessage } from '@/public/generalTools' -import { usePresetStore } from '@renderer/stores' import { isEmpty } from 'lodash' import { checkImageExists } from './image' import { t } from '@/i18n' -const presetStore = usePresetStore() - -/** - * 获取并处理预设列表数据 - * - * 该方法根据指定条件从数据库获取预设数据,并进行适当处理后按类别分组返回。 - * 处理内容包括: - * - 确保图片路径格式正确(添加file://前缀) - * - 添加时间戳避免缓存问题 - * - 初始化选中状态标记 - * - 将预设按类型分组(角色、风格、场景) - * - * @param {PresetModel.QueryPresetCondition} [condition] - 查询条件,不提供则使用预设仓库的当前条件 - * - * @returns {Promise} 按类别分组的预设集合 - * - character: 角色类预设数组 - * - style: 风格类预设数组 - * - scene: 场景类预设数组 - * - * @throws {Error} 当获取预设数据失败时抛出错误 - * - * @example - * // 使用默认条件获取预设 - * const presets = await getShowTagsData(); - * - * // 使用自定义条件获取预设 - * const presets = await getShowTagsData({ - * keyword: '自然', - * category: PresetCategory.Scene - * }); - */ -export async function getShowTagsData( - condition?: PresetModel.QueryPresetCondition -): Promise { - - if (!condition) { - condition = { - ...presetStore.queryPresetCondition - } - } - let res = await window.preset.GetPresetByCondition(condition) - - if (res.code != 1) { - throw new Error(res.message) - } - - let characterShowPreset: PresetModel.Preset[] = [] - let styleShowPreset: PresetModel.Preset[] = [] - let sceneShowPreset: PresetModel.Preset[] = [] - - for (let i = 0; res.data.presetArray && i < res.data.presetArray.length; i++) { - const element = res.data.presetArray[i] as PresetModel.Preset - if (element.showImage && element.showImage.length > 0) { - // 处理路径中的特殊字符和中文 - let imagePath = element.showImage[0] - // 确保本地文件路径有file://前缀 - if ( - !imagePath.startsWith('file://') && - (imagePath.startsWith('/') || imagePath.includes(':\\') || imagePath.startsWith('..')) - ) { - imagePath = `file://${imagePath}`.replaceAll(/\\/g, '/') - } - - element.coverImage = imagePath + `?${Date.now()}` // 添加时间戳以避免缓存问题 - element.checked = false // 初始化checked属性 - } else { - element.coverImage = '' - element.checked = false // 初始化checked属性 - } - - if (element.type == PresetCategory.Character) { - characterShowPreset.push(element) - } else if (element.type == PresetCategory.Style) { - styleShowPreset.push(element) - } else if (element.type == PresetCategory.Scene) { - sceneShowPreset.push(element) - } - } - return { - character: characterShowPreset, - style: styleShowPreset, - scene: sceneShowPreset - } -} /** * 检查分镜图片是否全部存在 diff --git a/src/renderer/src/components/Original/BookTaskDetail/AllImagePreview.vue b/src/renderer/src/components/Original/BookTaskDetail/AllImagePreview.vue index 193b5f2..69be3ba 100644 --- a/src/renderer/src/components/Original/BookTaskDetail/AllImagePreview.vue +++ b/src/renderer/src/components/Original/BookTaskDetail/AllImagePreview.vue @@ -1,42 +1,50 @@ @@ -48,16 +56,24 @@ import { LocateOutline } from '@vicons/ionicons5' // 添加定位图标 import { useBookStore, useThemeStore } from '@/renderer/src/stores' import { isEmpty } from 'lodash' import { t } from '@/i18n' +import { checkImageExists } from '@/renderer/src/common/image' const bookStore = useBookStore() const themeStore = useThemeStore() const message = useMessage() const images = ref([]) +const comLoading = ref(true) -onMounted(() => { - bookStore.selectBookTaskDetail.forEach((item) => { - if (!isEmpty(item.outImagePath)) { +onMounted(async () => { + await waitForImagesToLoad() + window.addEventListener('locate-table-row', handleLocateTableRow) +}) + +async function waitForImagesToLoad() { + for (let i = 0; i < bookStore.selectBookTaskDetail.length; i++) { + const item = bookStore.selectBookTaskDetail[i] + if (!isEmpty(item.outImagePath) && (await checkImageExists(item.outImagePath))) { images.value.push({ url: item.outImagePath.split('?t')[0] + '?t=' + Date.now(), // 添加时间戳以避免缓存 alt: t('分镜_{name}', { @@ -76,9 +92,9 @@ onMounted(() => { id: item.id // 保存ID用于定位 }) } - }) - window.addEventListener('locate-table-row', handleLocateTableRow) -}) + } + comLoading.value = false +} onUnmounted(() => { window.removeEventListener('locate-table-row', handleLocateTableRow) @@ -151,7 +167,7 @@ const labelBackgroundColor = computed(() => { } .image-item:hover .image-wrapper { - transform: scale(1.2); + transform: scale(1.05); } /* 添加阴影效果到父元素 */ diff --git a/src/renderer/src/components/Original/BookTaskDetail/DatatableCharacterAndSceneAndStyle.vue b/src/renderer/src/components/Original/BookTaskDetail/DatatableCharacterAndSceneAndStyle.vue index 6bd9b16..09423f1 100644 --- a/src/renderer/src/components/Original/BookTaskDetail/DatatableCharacterAndSceneAndStyle.vue +++ b/src/renderer/src/components/Original/BookTaskDetail/DatatableCharacterAndSceneAndStyle.vue @@ -177,6 +177,7 @@ watch( watch( () => presetStore.presetChangeCount, (newValue, oldValue) => { + console.log('presetChangeCount变化了,重新获取标签数据', newValue, oldValue) if (newValue !== oldValue) { fecthTagsData() } @@ -241,7 +242,7 @@ function fecthTagsData() { }) } catch (error) { message.error(t('获取标签数据失败,{error}', { error: error.message })) - } + } } // 角色标签的点击事件 diff --git a/src/renderer/src/components/Original/BookTaskDetail/DatatableHeaderCharacter.vue b/src/renderer/src/components/Original/BookTaskDetail/DatatableHeaderCharacter.vue index c36a839..9ea33f8 100644 --- a/src/renderer/src/components/Original/BookTaskDetail/DatatableHeaderCharacter.vue +++ b/src/renderer/src/components/Original/BookTaskDetail/DatatableHeaderCharacter.vue @@ -36,6 +36,7 @@ :width="dialogWidth" :height="dialogHeight" :content-component="dialogComponent" + @close="handleOnclose" /> @@ -127,4 +128,13 @@ async function SelectConfirm(selectedStyles) { function OpenPresetLibraryHome() { dialogVisible.value = true } + +// 关闭预设库 +async function handleOnclose() { + // 重新加载一个预设数据 + await presetStore.LoadPresetArray({ + isShow: true + }) + presetStore.presetChangeCount++ +} diff --git a/src/renderer/src/components/Original/BookTaskDetail/MessageAndProgress.vue b/src/renderer/src/components/Original/BookTaskDetail/MessageAndProgress.vue index 6aca1f8..264a4b2 100644 --- a/src/renderer/src/components/Original/BookTaskDetail/MessageAndProgress.vue +++ b/src/renderer/src/components/Original/BookTaskDetail/MessageAndProgress.vue @@ -221,7 +221,7 @@ onMounted(() => { }, 15000) }) -function ErrorPosition(type) { +async function ErrorPosition(type) { let id = '' softwareStore.skipRowIndex = 0 if (type == 'gptPrompt') { @@ -249,7 +249,12 @@ function ErrorPosition(type) { } } else if (type == 'image') { for (let i = 0; i < bookStore.selectBookTaskDetail.length; i++) { - if (isEmpty(bookStore.selectBookTaskDetail[i].outImagePath)) { + let item = bookStore.selectBookTaskDetail[i] + if ( + !item.outImagePath || + isEmpty(item.outImagePath) || + !(await checkImageExists(item.outImagePath)) + ) { id = bookStore.selectBookTaskDetail[i].id break } diff --git a/src/renderer/src/components/Original/Copywriter/EditWord.vue b/src/renderer/src/components/Original/Copywriter/EditWord.vue index 2fb1c50..42830b8 100644 --- a/src/renderer/src/components/Original/Copywriter/EditWord.vue +++ b/src/renderer/src/components/Original/Copywriter/EditWord.vue @@ -100,7 +100,6 @@ async function handleSave() { // 初始化数据 onMounted(() => { console.log('初始化数据:', props.initData) - debugger if (props.initData.value && props.initData.value.length > 0) { const lines = props.initData.value .map((item) => { diff --git a/src/renderer/src/components/Original/Copywriter/HandGroup.vue b/src/renderer/src/components/Original/Copywriter/HandGroup.vue index ffb5e95..5f999cb 100644 --- a/src/renderer/src/components/Original/Copywriter/HandGroup.vue +++ b/src/renderer/src/components/Original/Copywriter/HandGroup.vue @@ -253,7 +253,7 @@ const columns = [ function computedInputContent() { inputContent.value = tableData.value .map((item) => { - let w = item.afterGpt || '' + let w = item.afterGpt || item.subValue?.map(v => v.srt_value).join(',') || '' if (!w.endsWith('。')) { w = w + '。' } diff --git a/src/renderer/src/components/Original/Copywriter/composables/useWordGroupBase.js b/src/renderer/src/components/Original/Copywriter/composables/useWordGroupBase.js index 306e53f..8fc7a21 100644 --- a/src/renderer/src/components/Original/Copywriter/composables/useWordGroupBase.js +++ b/src/renderer/src/components/Original/Copywriter/composables/useWordGroupBase.js @@ -132,9 +132,6 @@ export function useWordGroupBase(initData) { // 从后往前遍历,避免删除时索引变化的问题 for (let i = data.value.length - 1; i >= 0; i--) { const currentRow = data.value[i] - if (i == 64) { - debugger - } // 检查当前行是否为空 if (isRowEmpty(currentRow)) { @@ -381,7 +378,7 @@ export function useWordGroupBase(initData) { initData: data, onSaveWord: (newWords) => { da?.destroy() - + debugger for (let i = 0; i < data.value.length; i++) { const element = data.value[i] element.afterGpt = '' @@ -444,11 +441,32 @@ export function useWordGroupBase(initData) { onPositiveClick: async () => { try { da?.destroy() + debugger + + // 深度清理数据,移除不可序列化的属性 + const cleanData = toRaw(data.value).map(item => ({ + no: item.no, + id: item.id, + lastId: item.lastId, + word: item.word || '', + afterGpt: item.afterGpt || '', + startTime: item.startTime || 0, + endTime: item.endTime || 0, + timeLimit: item.timeLimit || '', + subValue: (item.subValue || []).map(subItem => ({ + id: subItem.id, + srt_value: subItem.srt_value, + start_time: subItem.start_time, + end_time: subItem.end_time + })) + })) + + console.log("保存的数据", cleanData) softwareStore.spin.spinning = true softwareStore.spin.tip = t('正在保存文案信息...') let res = await window.book.SaveCopywritingInfo( bookStore.selectBookTask.id, - toRaw(data.value), + cleanData, OperateBookType.BOOKTASK ) if (res.code != 1) { @@ -514,7 +532,7 @@ export function useWordGroupBase(initData) { title: t('智能批量合并'), showIcon: true, content: t('确定要进行智能批量合并吗?将从第 {startIndex} 行开始处理。此操作会根据分镜文案内容自动将字幕合并到对应的行中。', { - startFromIndex: startFromIndex + startIndex: startFromIndex }), style: 'width: 500px', maskClosable: false, @@ -853,7 +871,7 @@ export function useWordGroupBase(initData) { dialog.create({ type: 'warning', title: t('智能合并部分完成'), - content: t('处理过程中遇到错误,已停止智能匹配:\n\n{message}\n\n已处理字幕:${totalProcessed} 个\n剩余字幕:${totalRemaining} 个\n\n剩余字幕已按顺序写入后续行中,请手动调整文案匹配。', { + content: t('处理过程中遇到错误,已停止智能匹配:\n\n{message}\n\n已处理字幕:{totalProcessed} 个\n剩余字幕:{totalRemaining} 个\n\n剩余字幕已按顺序写入后续行中,请手动调整文案匹配。', { message: processingError.message, totalProcessed: totalProcessed, totalRemaining: totalRemaining diff --git a/src/renderer/src/components/Original/MainHome/OriginalTaskCard.vue b/src/renderer/src/components/Original/MainHome/OriginalTaskCard.vue index f608647..f73f627 100644 --- a/src/renderer/src/components/Original/MainHome/OriginalTaskCard.vue +++ b/src/renderer/src/components/Original/MainHome/OriginalTaskCard.vue @@ -210,7 +210,7 @@ import { useBookStore } from '@/renderer/src/stores' -import { checBookTaskDetailImageExist, getShowTagsData } from '@/renderer/src/common/book' +import { checBookTaskDetailImageExist } from '@/renderer/src/common/book' import { useRouter } from 'vue-router' import { useBookTaskCardOption } from '@/renderer/src/hooks/useBookTaskCardOption' import TooltipDropdown from '../../common/TooltipDropdown.vue' @@ -368,14 +368,10 @@ async function handleOpenTask() { bookStore.selectBookTaskDetail = res.data bookStore.selectBookTask = { ...props.bookTask } - // 加载标签信息 - let tagRes = await getShowTagsData({ + // 加载一个预设数据 + await presetStore.LoadPresetArray({ isShow: true }) - // 做一下数据的处理 - presetStore.showCharacterPresetArray = tagRes.character - presetStore.showScenePresetArray = tagRes.scene - presetStore.showStylePresetArray = tagRes.style router.push('/original-book-detail/' + props.bookTask.id) } catch (error) { diff --git a/src/renderer/src/components/Preset/PresetShowCard.vue b/src/renderer/src/components/Preset/PresetShowCard.vue index 189fc71..fbaa5bb 100644 --- a/src/renderer/src/components/Preset/PresetShowCard.vue +++ b/src/renderer/src/components/Preset/PresetShowCard.vue @@ -179,6 +179,7 @@ let contentBackgroundColor = computed(() => { .preset-card { transition: all 0.3s; height: 280px; /* 固定卡片高度 */ + width: 200px; /* 固定卡片宽度 */ display: flex; flex-direction: column; position: relative; diff --git a/src/renderer/src/components/common/CommonDialog.vue b/src/renderer/src/components/common/CommonDialog.vue index 1ac826b..6a504fb 100644 --- a/src/renderer/src/components/common/CommonDialog.vue +++ b/src/renderer/src/components/common/CommonDialog.vue @@ -68,10 +68,14 @@ const he = ref(props.height) // 使用const而不是let // 每次visible变为true时,重新计算尺寸 watch( visible, - (newVal) => { + (newVal, oldVal) => { if (newVal === true) { calculateDimensions() } + // 当 modal 从显示变为隐藏时,发出 close 事件 + if (oldVal === true && newVal === false) { + emit('close') + } emit('update:show', newVal) } ) @@ -107,7 +111,6 @@ const actualHeight = computed(() => he.value) const handleClose = () => { visible.value = false - emit('close') } const handleConfirm = () => { diff --git a/src/renderer/src/stores/subStore/preset.ts b/src/renderer/src/stores/subStore/preset.ts index 3886d7d..0528a98 100644 --- a/src/renderer/src/stores/subStore/preset.ts +++ b/src/renderer/src/stores/subStore/preset.ts @@ -45,6 +45,62 @@ export const usePresetStore = defineStore('preset', { }), getters: {}, actions: { + + async LoadPresetArray(condition?: PresetModel.QueryPresetCondition) { + try { + if (!condition) { + condition = { + ...this.queryPresetCondition + } + } + let res = await window.preset.GetPresetByCondition(condition) + + if (res.code != 1) { + throw new Error(res.message) + } + + let characterShowPreset: PresetModel.Preset[] = [] + let styleShowPreset: PresetModel.Preset[] = [] + let sceneShowPreset: PresetModel.Preset[] = [] + + for (let i = 0; res.data.presetArray && i < res.data.presetArray.length; i++) { + const element = res.data.presetArray[i] as PresetModel.Preset + if (element.showImage && element.showImage.length > 0) { + // 处理路径中的特殊字符和中文 + let imagePath = element.showImage[0] + // 确保本地文件路径有file://前缀 + if ( + !imagePath.startsWith('file://') && + (imagePath.startsWith('/') || imagePath.includes(':\\') || imagePath.startsWith('..')) + ) { + imagePath = `file://${imagePath}`.replaceAll(/\\/g, '/') + } + + element.coverImage = imagePath + `?${Date.now()}` // 添加时间戳以避免缓存问题 + element.checked = false // 初始化checked属性 + } else { + element.coverImage = '' + element.checked = false // 初始化checked属性 + } + + if (element.type == PresetCategory.Character) { + characterShowPreset.push(element) + } else if (element.type == PresetCategory.Style) { + styleShowPreset.push(element) + } else if (element.type == PresetCategory.Scene) { + sceneShowPreset.push(element) + } + } + + // 更新数据 + this.showCharacterPresetArray = characterShowPreset + this.showScenePresetArray = sceneShowPreset + this.showStylePresetArray = styleShowPreset + } catch (error) { + console.error('加载预设数据失败:', error) + throw error + } + }, ResetSelectPreset() { const now = new Date() const formattedDate = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}` diff --git a/src/renderer/src/views/PresetLibraryHome.vue b/src/renderer/src/views/PresetLibraryHome.vue index 7c4bb78..f361fb4 100644 --- a/src/renderer/src/views/PresetLibraryHome.vue +++ b/src/renderer/src/views/PresetLibraryHome.vue @@ -195,7 +195,6 @@ let selectBorderColor = computed(() => { } .preset-flex-item { - width: 200px; /* 固定卡片宽度 */ flex-grow: 0; flex-shrink: 0; }