修改剪映草稿生成,修改字幕分组报错,优化加载标签信息,修改预设样式
This commit is contained in:
parent
3db9352a42
commit
aa16a494bd
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "laitool-pro",
|
"name": "laitool-pro",
|
||||||
"productName": "LaiToolPro",
|
"productName": "LaiToolPro",
|
||||||
"version": "v3.4.9",
|
"version": "v4.0.0",
|
||||||
"description": "来推 Pro - 一款集音频处理、文案生成、图片生成、视频生成等功能于一体的多合一AI工具软件。",
|
"description": "来推 Pro - 一款集音频处理、文案生成、图片生成、视频生成等功能于一体的多合一AI工具软件。",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "xiangbei",
|
"author": "xiangbei",
|
||||||
@ -84,6 +84,7 @@
|
|||||||
"resources/image/zhanwei.png",
|
"resources/image/zhanwei.png",
|
||||||
"resources/scripts/model/**",
|
"resources/scripts/model/**",
|
||||||
"resources/scripts/Lai.exe",
|
"resources/scripts/Lai.exe",
|
||||||
|
"resources/scripts/xiangbei_jianying_main.exe",
|
||||||
"resources/scripts/discordScript.js",
|
"resources/scripts/discordScript.js",
|
||||||
"resources/tmp/**",
|
"resources/tmp/**",
|
||||||
"resources/icon.ico"
|
"resources/icon.ico"
|
||||||
|
|||||||
@ -31,7 +31,7 @@ interface ISoftwareData {
|
|||||||
|
|
||||||
export const SoftwareData: ISoftwareData = {
|
export const SoftwareData: ISoftwareData = {
|
||||||
version: 'V3.4.2',
|
version: 'V3.4.2',
|
||||||
date: '2025-08-08',
|
date: '2025-09.09',
|
||||||
systemInfo: {
|
systemInfo: {
|
||||||
documentationUrl: 'https://rvgyir5wk1c.feishu.cn/wiki/WdaWwAfDdiLOnjkywIgcaQoKnog',
|
documentationUrl: 'https://rvgyir5wk1c.feishu.cn/wiki/WdaWwAfDdiLOnjkywIgcaQoKnog',
|
||||||
updateUrl: 'https://pvwu1oahp5m.feishu.cn/docx/CAjGdTDlboJ3nVx0cQccOuNHnvd',
|
updateUrl: 'https://pvwu1oahp5m.feishu.cn/docx/CAjGdTDlboJ3nVx0cQccOuNHnvd',
|
||||||
|
|||||||
@ -462,6 +462,14 @@ export class BookTaskService extends RealmBaseService {
|
|||||||
modifyBookTask.subImageFolder = []
|
modifyBookTask.subImageFolder = []
|
||||||
modifyBookTask.srtPath = book.srtPath ?? undefined
|
modifyBookTask.srtPath = book.srtPath ?? undefined
|
||||||
modifyBookTask.audioPath = book.audioPath ?? 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和配音文件
|
// 继承小说的srt和配音文件
|
||||||
|
|||||||
@ -1411,7 +1411,7 @@ export default {
|
|||||||
'智能合并失败,{error}': 'Smart merge failed, {error}',
|
'智能合并失败,{error}': 'Smart merge failed, {error}',
|
||||||
'智能批量合并完成,所有字幕都已正确匹配': 'Smart batch merge completed, all subtitles matched correctly',
|
'智能批量合并完成,所有字幕都已正确匹配': 'Smart batch merge completed, all subtitles matched correctly',
|
||||||
'智能合并完成,{count} 个剩余字幕已写入后续行': 'Smart merge completed, {count} remaining subtitles written to subsequent lines',
|
'智能合并完成,{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} 行没有找到任何匹配的字幕': '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}” 时无法匹配,已累积文本 “{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}"',
|
'第 {rowIndex} 行的第一个字幕 “{subtitleText}” 与文案 “{text}” 不匹配': 'The first subtitle "{subtitleText}" on line {rowIndex} does not match the content "{text}"',
|
||||||
|
|||||||
@ -1411,7 +1411,7 @@ export default {
|
|||||||
'智能合并失败,{error}': '智能合并失败,{error}',
|
'智能合并失败,{error}': '智能合并失败,{error}',
|
||||||
'智能批量合并完成,所有字幕都已正确匹配': '智能批量合并完成,所有字幕都已正确匹配',
|
'智能批量合并完成,所有字幕都已正确匹配': '智能批量合并完成,所有字幕都已正确匹配',
|
||||||
'智能合并完成,{count} 个剩余字幕已写入后续行': '智能合并完成,{count} 个剩余字幕已写入后续行',
|
'智能合并完成,{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} 行没有找到任何匹配的字幕': '第 {rowIndex} 行没有找到任何匹配的字幕',
|
||||||
'第 {rowIndex} 行在处理字幕 “{subtitleText}” 时无法匹配,已累积文本 “{accumulatedText}” 与目标文案 “{text}”不匹配': '第 {rowIndex} 行在处理字幕 “{subtitleText}” 时无法匹配,已累积文本 “{accumulatedText}” 与目标文案 “{text}”不匹配',
|
'第 {rowIndex} 行在处理字幕 “{subtitleText}” 时无法匹配,已累积文本 “{accumulatedText}” 与目标文案 “{text}”不匹配': '第 {rowIndex} 行在处理字幕 “{subtitleText}” 时无法匹配,已累积文本 “{accumulatedText}” 与目标文案 “{text}”不匹配',
|
||||||
'第 {rowIndex} 行的第一个字幕 “{subtitleText}” 与文案 “{text}” 不匹配': '第 {rowIndex} 行的第一个字幕 “{subtitleText}” 与文案 “{text}” 不匹配',
|
'第 {rowIndex} 行的第一个字幕 “{subtitleText}” 与文案 “{text}” 不匹配': '第 {rowIndex} 行的第一个字幕 “{subtitleText}” 与文案 “{text}” 不匹配',
|
||||||
|
|||||||
@ -18,7 +18,6 @@ import { isEmpty } from 'lodash'
|
|||||||
import { define } from '@/define/define'
|
import { define } from '@/define/define'
|
||||||
import util from 'util'
|
import util from 'util'
|
||||||
import { exec } from 'child_process'
|
import { exec } from 'child_process'
|
||||||
import { BookTaskDetail } from '@/define/model/book/bookTaskDetail'
|
|
||||||
import { ValidateJson } from '@/define/Tools/validate'
|
import { ValidateJson } from '@/define/Tools/validate'
|
||||||
const execAsync = util.promisify(exec)
|
const execAsync = util.promisify(exec)
|
||||||
import JianyingService from '../../jianying/jianyingService'
|
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 = {
|
let frameData = {
|
||||||
|
|||||||
@ -1,96 +1,9 @@
|
|||||||
import { PresetCategory } from '@/define/data/presetData'
|
|
||||||
import { Book } from '@/define/model/book/book'
|
import { Book } from '@/define/model/book/book'
|
||||||
import { ErrorItem, SuccessItem } from '@/define/model/generalResponse'
|
import { ErrorItem, SuccessItem } from '@/define/model/generalResponse'
|
||||||
import { PresetModel } from '@/define/model/preset'
|
|
||||||
import { errorMessage, successMessage } from '@/public/generalTools'
|
import { errorMessage, successMessage } from '@/public/generalTools'
|
||||||
import { usePresetStore } from '@renderer/stores'
|
|
||||||
import { isEmpty } from 'lodash'
|
import { isEmpty } from 'lodash'
|
||||||
import { checkImageExists } from './image'
|
import { checkImageExists } from './image'
|
||||||
import { t } from '@/i18n'
|
import { t } from '@/i18n'
|
||||||
const presetStore = usePresetStore()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取并处理预设列表数据
|
|
||||||
*
|
|
||||||
* 该方法根据指定条件从数据库获取预设数据,并进行适当处理后按类别分组返回。
|
|
||||||
* 处理内容包括:
|
|
||||||
* - 确保图片路径格式正确(添加file://前缀)
|
|
||||||
* - 添加时间戳避免缓存问题
|
|
||||||
* - 初始化选中状态标记
|
|
||||||
* - 将预设按类型分组(角色、风格、场景)
|
|
||||||
*
|
|
||||||
* @param {PresetModel.QueryPresetCondition} [condition] - 查询条件,不提供则使用预设仓库的当前条件
|
|
||||||
*
|
|
||||||
* @returns {Promise<PresetModel.PresetCategoryCollection>} 按类别分组的预设集合
|
|
||||||
* - 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<PresetModel.PresetCategoryCollection> {
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查分镜图片是否全部存在
|
* 检查分镜图片是否全部存在
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="all-image-preview-container">
|
<div>
|
||||||
|
<div v-if="!comLoading" class="all-image-preview-container">
|
||||||
<div v-for="(image, index) in images" :key="index" :style="{ margin: '5px' }">
|
<div v-for="(image, index) in images" :key="index" :style="{ margin: '5px' }">
|
||||||
<div class="image-item" :class="{ placeholder: !isValidImage(image.url) }">
|
<div class="image-item" :class="{ placeholder: !isValidImage(image.url) }">
|
||||||
<!-- 有效图片 -->
|
<!-- 有效图片 -->
|
||||||
@ -9,6 +10,7 @@
|
|||||||
:alt="t('图片 {index}', { index: index + 1 })"
|
:alt="t('图片 {index}', { index: index + 1 })"
|
||||||
object-fit="cover"
|
object-fit="cover"
|
||||||
:width="150"
|
:width="150"
|
||||||
|
lazy="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -30,7 +32,11 @@
|
|||||||
<!-- 左上角文本标识 -->
|
<!-- 左上角文本标识 -->
|
||||||
<div class="image-label">{{ image.name }}</div>
|
<div class="image-label">{{ image.name }}</div>
|
||||||
<!-- 右下角定位图标 -->
|
<!-- 右下角定位图标 -->
|
||||||
<div class="image-locate" @click.stop="locateTableRow(image.id)" :title="t('定位到对应行')">
|
<div
|
||||||
|
class="image-locate"
|
||||||
|
@click.stop="locateTableRow(image.id)"
|
||||||
|
:title="t('定位到对应行')"
|
||||||
|
>
|
||||||
<n-icon size="20" color="#fff">
|
<n-icon size="20" color="#fff">
|
||||||
<locate-outline />
|
<locate-outline />
|
||||||
</n-icon>
|
</n-icon>
|
||||||
@ -38,6 +44,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<LoadingComponent v-else :description="t('加载中...')" size="large" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@ -48,16 +56,24 @@ import { LocateOutline } from '@vicons/ionicons5' // 添加定位图标
|
|||||||
import { useBookStore, useThemeStore } from '@/renderer/src/stores'
|
import { useBookStore, useThemeStore } from '@/renderer/src/stores'
|
||||||
import { isEmpty } from 'lodash'
|
import { isEmpty } from 'lodash'
|
||||||
import { t } from '@/i18n'
|
import { t } from '@/i18n'
|
||||||
|
import { checkImageExists } from '@/renderer/src/common/image'
|
||||||
|
|
||||||
const bookStore = useBookStore()
|
const bookStore = useBookStore()
|
||||||
const themeStore = useThemeStore()
|
const themeStore = useThemeStore()
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
|
||||||
const images = ref([])
|
const images = ref([])
|
||||||
|
const comLoading = ref(true)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
bookStore.selectBookTaskDetail.forEach((item) => {
|
await waitForImagesToLoad()
|
||||||
if (!isEmpty(item.outImagePath)) {
|
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({
|
images.value.push({
|
||||||
url: item.outImagePath.split('?t')[0] + '?t=' + Date.now(), // 添加时间戳以避免缓存
|
url: item.outImagePath.split('?t')[0] + '?t=' + Date.now(), // 添加时间戳以避免缓存
|
||||||
alt: t('分镜_{name}', {
|
alt: t('分镜_{name}', {
|
||||||
@ -76,9 +92,9 @@ onMounted(() => {
|
|||||||
id: item.id // 保存ID用于定位
|
id: item.id // 保存ID用于定位
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
window.addEventListener('locate-table-row', handleLocateTableRow)
|
comLoading.value = false
|
||||||
})
|
}
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
window.removeEventListener('locate-table-row', handleLocateTableRow)
|
window.removeEventListener('locate-table-row', handleLocateTableRow)
|
||||||
@ -151,7 +167,7 @@ const labelBackgroundColor = computed(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.image-item:hover .image-wrapper {
|
.image-item:hover .image-wrapper {
|
||||||
transform: scale(1.2);
|
transform: scale(1.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 添加阴影效果到父元素 */
|
/* 添加阴影效果到父元素 */
|
||||||
|
|||||||
@ -177,6 +177,7 @@ watch(
|
|||||||
watch(
|
watch(
|
||||||
() => presetStore.presetChangeCount,
|
() => presetStore.presetChangeCount,
|
||||||
(newValue, oldValue) => {
|
(newValue, oldValue) => {
|
||||||
|
console.log('presetChangeCount变化了,重新获取标签数据', newValue, oldValue)
|
||||||
if (newValue !== oldValue) {
|
if (newValue !== oldValue) {
|
||||||
fecthTagsData()
|
fecthTagsData()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,7 @@
|
|||||||
:width="dialogWidth"
|
:width="dialogWidth"
|
||||||
:height="dialogHeight"
|
:height="dialogHeight"
|
||||||
:content-component="dialogComponent"
|
:content-component="dialogComponent"
|
||||||
|
@close="handleOnclose"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -127,4 +128,13 @@ async function SelectConfirm(selectedStyles) {
|
|||||||
function OpenPresetLibraryHome() {
|
function OpenPresetLibraryHome() {
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 关闭预设库
|
||||||
|
async function handleOnclose() {
|
||||||
|
// 重新加载一个预设数据
|
||||||
|
await presetStore.LoadPresetArray({
|
||||||
|
isShow: true
|
||||||
|
})
|
||||||
|
presetStore.presetChangeCount++
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -221,7 +221,7 @@ onMounted(() => {
|
|||||||
}, 15000)
|
}, 15000)
|
||||||
})
|
})
|
||||||
|
|
||||||
function ErrorPosition(type) {
|
async function ErrorPosition(type) {
|
||||||
let id = ''
|
let id = ''
|
||||||
softwareStore.skipRowIndex = 0
|
softwareStore.skipRowIndex = 0
|
||||||
if (type == 'gptPrompt') {
|
if (type == 'gptPrompt') {
|
||||||
@ -249,7 +249,12 @@ function ErrorPosition(type) {
|
|||||||
}
|
}
|
||||||
} else if (type == 'image') {
|
} else if (type == 'image') {
|
||||||
for (let i = 0; i < bookStore.selectBookTaskDetail.length; i++) {
|
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
|
id = bookStore.selectBookTaskDetail[i].id
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,7 +100,6 @@ async function handleSave() {
|
|||||||
// 初始化数据
|
// 初始化数据
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
console.log('初始化数据:', props.initData)
|
console.log('初始化数据:', props.initData)
|
||||||
debugger
|
|
||||||
if (props.initData.value && props.initData.value.length > 0) {
|
if (props.initData.value && props.initData.value.length > 0) {
|
||||||
const lines = props.initData.value
|
const lines = props.initData.value
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
|
|||||||
@ -253,7 +253,7 @@ const columns = [
|
|||||||
function computedInputContent() {
|
function computedInputContent() {
|
||||||
inputContent.value = tableData.value
|
inputContent.value = tableData.value
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
let w = item.afterGpt || ''
|
let w = item.afterGpt || item.subValue?.map(v => v.srt_value).join(',') || ''
|
||||||
if (!w.endsWith('。')) {
|
if (!w.endsWith('。')) {
|
||||||
w = w + '。'
|
w = w + '。'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -132,9 +132,6 @@ export function useWordGroupBase(initData) {
|
|||||||
// 从后往前遍历,避免删除时索引变化的问题
|
// 从后往前遍历,避免删除时索引变化的问题
|
||||||
for (let i = data.value.length - 1; i >= 0; i--) {
|
for (let i = data.value.length - 1; i >= 0; i--) {
|
||||||
const currentRow = data.value[i]
|
const currentRow = data.value[i]
|
||||||
if (i == 64) {
|
|
||||||
debugger
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查当前行是否为空
|
// 检查当前行是否为空
|
||||||
if (isRowEmpty(currentRow)) {
|
if (isRowEmpty(currentRow)) {
|
||||||
@ -381,7 +378,7 @@ export function useWordGroupBase(initData) {
|
|||||||
initData: data,
|
initData: data,
|
||||||
onSaveWord: (newWords) => {
|
onSaveWord: (newWords) => {
|
||||||
da?.destroy()
|
da?.destroy()
|
||||||
|
debugger
|
||||||
for (let i = 0; i < data.value.length; i++) {
|
for (let i = 0; i < data.value.length; i++) {
|
||||||
const element = data.value[i]
|
const element = data.value[i]
|
||||||
element.afterGpt = ''
|
element.afterGpt = ''
|
||||||
@ -444,11 +441,32 @@ export function useWordGroupBase(initData) {
|
|||||||
onPositiveClick: async () => {
|
onPositiveClick: async () => {
|
||||||
try {
|
try {
|
||||||
da?.destroy()
|
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.spinning = true
|
||||||
softwareStore.spin.tip = t('正在保存文案信息...')
|
softwareStore.spin.tip = t('正在保存文案信息...')
|
||||||
let res = await window.book.SaveCopywritingInfo(
|
let res = await window.book.SaveCopywritingInfo(
|
||||||
bookStore.selectBookTask.id,
|
bookStore.selectBookTask.id,
|
||||||
toRaw(data.value),
|
cleanData,
|
||||||
OperateBookType.BOOKTASK
|
OperateBookType.BOOKTASK
|
||||||
)
|
)
|
||||||
if (res.code != 1) {
|
if (res.code != 1) {
|
||||||
@ -514,7 +532,7 @@ export function useWordGroupBase(initData) {
|
|||||||
title: t('智能批量合并'),
|
title: t('智能批量合并'),
|
||||||
showIcon: true,
|
showIcon: true,
|
||||||
content: t('确定要进行智能批量合并吗?将从第 {startIndex} 行开始处理。此操作会根据分镜文案内容自动将字幕合并到对应的行中。', {
|
content: t('确定要进行智能批量合并吗?将从第 {startIndex} 行开始处理。此操作会根据分镜文案内容自动将字幕合并到对应的行中。', {
|
||||||
startFromIndex: startFromIndex
|
startIndex: startFromIndex
|
||||||
}),
|
}),
|
||||||
style: 'width: 500px',
|
style: 'width: 500px',
|
||||||
maskClosable: false,
|
maskClosable: false,
|
||||||
@ -853,7 +871,7 @@ export function useWordGroupBase(initData) {
|
|||||||
dialog.create({
|
dialog.create({
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
title: t('智能合并部分完成'),
|
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,
|
message: processingError.message,
|
||||||
totalProcessed: totalProcessed,
|
totalProcessed: totalProcessed,
|
||||||
totalRemaining: totalRemaining
|
totalRemaining: totalRemaining
|
||||||
|
|||||||
@ -210,7 +210,7 @@ import {
|
|||||||
useBookStore
|
useBookStore
|
||||||
} from '@/renderer/src/stores'
|
} 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 { useRouter } from 'vue-router'
|
||||||
import { useBookTaskCardOption } from '@/renderer/src/hooks/useBookTaskCardOption'
|
import { useBookTaskCardOption } from '@/renderer/src/hooks/useBookTaskCardOption'
|
||||||
import TooltipDropdown from '../../common/TooltipDropdown.vue'
|
import TooltipDropdown from '../../common/TooltipDropdown.vue'
|
||||||
@ -368,14 +368,10 @@ async function handleOpenTask() {
|
|||||||
bookStore.selectBookTaskDetail = res.data
|
bookStore.selectBookTaskDetail = res.data
|
||||||
bookStore.selectBookTask = { ...props.bookTask }
|
bookStore.selectBookTask = { ...props.bookTask }
|
||||||
|
|
||||||
// 加载标签信息
|
// 加载一个预设数据
|
||||||
let tagRes = await getShowTagsData({
|
await presetStore.LoadPresetArray({
|
||||||
isShow: true
|
isShow: true
|
||||||
})
|
})
|
||||||
// 做一下数据的处理
|
|
||||||
presetStore.showCharacterPresetArray = tagRes.character
|
|
||||||
presetStore.showScenePresetArray = tagRes.scene
|
|
||||||
presetStore.showStylePresetArray = tagRes.style
|
|
||||||
|
|
||||||
router.push('/original-book-detail/' + props.bookTask.id)
|
router.push('/original-book-detail/' + props.bookTask.id)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -179,6 +179,7 @@ let contentBackgroundColor = computed(() => {
|
|||||||
.preset-card {
|
.preset-card {
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
height: 280px; /* 固定卡片高度 */
|
height: 280px; /* 固定卡片高度 */
|
||||||
|
width: 200px; /* 固定卡片宽度 */
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@ -68,10 +68,14 @@ const he = ref(props.height) // 使用const而不是let
|
|||||||
// 每次visible变为true时,重新计算尺寸
|
// 每次visible变为true时,重新计算尺寸
|
||||||
watch(
|
watch(
|
||||||
visible,
|
visible,
|
||||||
(newVal) => {
|
(newVal, oldVal) => {
|
||||||
if (newVal === true) {
|
if (newVal === true) {
|
||||||
calculateDimensions()
|
calculateDimensions()
|
||||||
}
|
}
|
||||||
|
// 当 modal 从显示变为隐藏时,发出 close 事件
|
||||||
|
if (oldVal === true && newVal === false) {
|
||||||
|
emit('close')
|
||||||
|
}
|
||||||
emit('update:show', newVal)
|
emit('update:show', newVal)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -107,7 +111,6 @@ const actualHeight = computed(() => he.value)
|
|||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
visible.value = false
|
visible.value = false
|
||||||
emit('close')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleConfirm = () => {
|
const handleConfirm = () => {
|
||||||
|
|||||||
@ -45,6 +45,62 @@ export const usePresetStore = defineStore('preset', {
|
|||||||
}),
|
}),
|
||||||
getters: {},
|
getters: {},
|
||||||
actions: {
|
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() {
|
ResetSelectPreset() {
|
||||||
const now = new Date()
|
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')}`
|
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')}`
|
||||||
|
|||||||
@ -195,7 +195,6 @@ let selectBorderColor = computed(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.preset-flex-item {
|
.preset-flex-item {
|
||||||
width: 200px; /* 固定卡片宽度 */
|
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user