修改了 预设的图片上传 和 授权文档
This commit is contained in:
parent
65e3ca3ce1
commit
8ab4835270
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,3 +10,4 @@ resources/project
|
||||
Database
|
||||
build
|
||||
src/renderer/src/components/Original/MainHome/OriginalTaskCard.vue
|
||||
resources/image/预设
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "laitool-pro",
|
||||
"productName": "LaiToolPro",
|
||||
"version": "v3.4.7",
|
||||
"version": "v3.4.8",
|
||||
"description": "来推 Pro - 一款集音频处理、文案生成、图片生成、视频生成等功能于一体的多合一AI工具软件。",
|
||||
"main": "./out/main/index.js",
|
||||
"author": "xiangbei",
|
||||
|
||||
@ -12,7 +12,9 @@ interface ISoftwareData {
|
||||
/** 软件文档 */
|
||||
softwareUrl: string
|
||||
/** WIKI */
|
||||
wikiUrl: string
|
||||
wikiUrl: string,
|
||||
/** 授权文档 */
|
||||
authUrl: string
|
||||
}
|
||||
/** MJ相关文档链接 */
|
||||
mjDoc: {
|
||||
@ -35,7 +37,8 @@ export const SoftwareData: ISoftwareData = {
|
||||
updateUrl: 'https://pvwu1oahp5m.feishu.cn/docx/CAjGdTDlboJ3nVx0cQccOuNHnvd',
|
||||
softwareUrl: 'https://pvwu1oahp5m.feishu.cn/docx/FONZdfnrOoLlMrxXHV0czJ3jnkd',
|
||||
wikiUrl:
|
||||
'https://rvgyir5wk1c.feishu.cn/wiki/space/7481893355360190492?ccm_open_type=lark_wiki_spaceLink&open_tab_from=wiki_home'
|
||||
'https://rvgyir5wk1c.feishu.cn/wiki/space/7481893355360190492?ccm_open_type=lark_wiki_spaceLink&open_tab_from=wiki_home',
|
||||
authUrl: "https://rvgyir5wk1c.feishu.cn/wiki/UUbrwAalJiq9BUkHymscD0E8nCc"
|
||||
},
|
||||
mjDoc: {
|
||||
mjAPIDoc: 'https://rvgyir5wk1c.feishu.cn/wiki/OEj7wIdD6ivvCAkez4OcUPLcnIf',
|
||||
|
||||
@ -988,6 +988,7 @@ export default {
|
||||
'正在初始化预设库模块': "Initializing preset library module",
|
||||
'释放添加图片': 'Release to add image',
|
||||
'点击或拖拽添加图片': 'Click or drag to add image',
|
||||
'仅支持图片格式': 'Only image formats supported',
|
||||
'预设名称': 'Preset Name',
|
||||
'请输入预设名称': 'Please enter preset name',
|
||||
'预设分类': 'Preset Category',
|
||||
@ -1054,6 +1055,8 @@ export default {
|
||||
'选择文件失败,{error}': 'Failed to select file, {error}',
|
||||
"选择文件夹失败,{error}": "Failed to select folder, {error}",
|
||||
"在相同类型下已存在当前的预设名字,请修改后再试!": "Preset name already exists under the same type, please modify and try again!",
|
||||
"选择文件失败,无效的文件对象": "Failed to select file, invalid file object",
|
||||
"选择文件失败,只能上传图片文件": "Failed to select file, only image files can be uploaded",
|
||||
//#endregion
|
||||
|
||||
//#region 原创
|
||||
|
||||
@ -988,6 +988,7 @@ export default {
|
||||
'正在初始化预设库模块': "正在初始化预设库模块",
|
||||
'释放添加图片': '释放添加图片',
|
||||
'点击或拖拽添加图片': '点击或拖拽添加图片',
|
||||
'仅支持图片格式': '仅支持图片格式',
|
||||
'预设名称': '预设名称',
|
||||
'请输入预设名称': '请输入预设名称',
|
||||
'预设分类': '预设分类',
|
||||
@ -1054,6 +1055,8 @@ export default {
|
||||
'选择文件失败,{error}': '选择文件失败,{error}',
|
||||
"选择文件夹失败,{error}": "选择文件夹失败,{error}",
|
||||
"在相同类型下已存在当前的预设名字,请修改后再试!": "在相同类型下已存在当前的预设名字,请修改后再试!",
|
||||
"选择文件失败,无效的文件对象": "选择文件失败,无效的文件对象",
|
||||
"选择文件失败,只能上传图片文件": "选择文件失败,只能上传图片文件",
|
||||
//#endregion
|
||||
|
||||
//#region 原创
|
||||
|
||||
@ -7,28 +7,32 @@
|
||||
<div class="image-preview-container">
|
||||
<n-image-group>
|
||||
<div class="image-grid">
|
||||
<!-- 上传卡片 - 始终显示在第一位,添加拖拽事件 -->
|
||||
<div
|
||||
class="image-item upload-card"
|
||||
@click="openFileSelector"
|
||||
@dragover.prevent="handleDragOver"
|
||||
@dragleave.prevent="handleDragLeave"
|
||||
@drop.prevent="handleDrop"
|
||||
:class="{ dragging: isDragging }"
|
||||
>
|
||||
<div class="upload-placeholder">
|
||||
<n-icon size="32" :depth="3" class="upload-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 4a1 1 0 0 1 1 1v6h6a1 1 0 1 1 0 2h-6v6a1 1 0 1 1-2 0v-6H5a1 1 0 1 1 0-2h6V5a1 1 0 0 1 1-1z"
|
||||
></path>
|
||||
</svg>
|
||||
</n-icon>
|
||||
<div class="upload-text">
|
||||
{{ isDragging ? t('释放添加图片') : t('点击或拖拽添加图片') }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- 上传卡片 - 使用 Naive UI 上传组件 -->
|
||||
<div class="image-item upload-card">
|
||||
<n-upload
|
||||
multiple
|
||||
:show-file-list="false"
|
||||
:custom-request="handleUpload"
|
||||
directory-dnd
|
||||
class="upload-wrapper"
|
||||
>
|
||||
<n-upload-dragger>
|
||||
<div class="upload-placeholder">
|
||||
<n-icon size="32" :depth="3" class="upload-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 4a1 1 0 0 1 1 1v6h6a1 1 0 1 1 0 2h-6v6a1 1 0 1 1-2 0v-6H5a1 1 0 1 1 0-2h6V5a1 1 0 0 1 1-1z"
|
||||
></path>
|
||||
</svg>
|
||||
</n-icon>
|
||||
<div class="upload-text">
|
||||
{{ t('点击或拖拽添加图片') }}
|
||||
<div class="upload-hint">{{ t('仅支持图片格式') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</n-upload-dragger>
|
||||
</n-upload>
|
||||
</div>
|
||||
|
||||
<!-- 已选图片预览 -->
|
||||
@ -124,10 +128,12 @@ import {
|
||||
NFormItem,
|
||||
NButton,
|
||||
NEmpty,
|
||||
NImageGroup
|
||||
NImageGroup,
|
||||
NUpload,
|
||||
NUploadDragger
|
||||
} from 'naive-ui'
|
||||
import { getPresetCategoryOptions, PresetCategory } from '@/define/data/presetData'
|
||||
import { usePresetStore } from '@/renderer/src/stores'
|
||||
import { usePresetStore, useThemeStore } from '@/renderer/src/stores'
|
||||
import StylePreset from './StylePreset.vue'
|
||||
import ScenePreset from './ScenePreset.vue'
|
||||
import CharacterPreset from './CharacterPreset.vue'
|
||||
@ -138,6 +144,7 @@ import { Trash } from '@vicons/ionicons5'
|
||||
import { t } from '@/i18n'
|
||||
|
||||
const presetStore = usePresetStore()
|
||||
const themeStore = useThemeStore()
|
||||
|
||||
const presetCategoryRef = ref(PresetCategory)
|
||||
|
||||
@ -146,80 +153,58 @@ const message = useMessage()
|
||||
|
||||
let categoryOptions = getPresetCategoryOptions()
|
||||
|
||||
// 添加拖拽状态标志
|
||||
const isDragging = ref(false)
|
||||
|
||||
// 打开文件选择器
|
||||
const openFileSelector = async () => {
|
||||
try {
|
||||
const res = await window.system.SelectMultipleFile(['jpg', 'png', 'jpeg', 'webp'])
|
||||
console.log('选择的文件:', res)
|
||||
|
||||
if (res.code != 1) {
|
||||
message.error(res.message)
|
||||
return
|
||||
}
|
||||
if (res.data.length == 0) {
|
||||
message.error(t('没有选择任何文件'))
|
||||
return
|
||||
}
|
||||
|
||||
// 处理选中的文件
|
||||
const newFiles = res.data.map((filePath) => {
|
||||
return `file://${filePath}` + `?${Date.now()}`
|
||||
})
|
||||
|
||||
// 更新文件列表
|
||||
presetStore.selectPreset.showImage.push(...newFiles)
|
||||
} catch (error) {
|
||||
console.error('选择文件时出错:', error)
|
||||
message.error(t('选择文件失败,{error}', { error: error.message }))
|
||||
// 处理文件上传
|
||||
const handleUpload = ({ file, onFinish, onError }) => {
|
||||
debugger
|
||||
// 获取实际的文件对象
|
||||
let actualFile = file
|
||||
// 如果 file 有 file 属性,则使用该属性(Naive UI 的包装对象)
|
||||
if (file.file && file.file instanceof File) {
|
||||
actualFile = file.file
|
||||
}
|
||||
}
|
||||
|
||||
// 处理拖动开始悬停在上传区域
|
||||
const handleDragOver = (event) => {
|
||||
isDragging.value = true
|
||||
// 确保只接受文件
|
||||
if (event.dataTransfer) {
|
||||
event.dataTransfer.dropEffect = 'copy'
|
||||
// 如果有 originFileObj 属性(某些上传组件的格式)
|
||||
else if (file.originFileObj && file.originFileObj instanceof File) {
|
||||
actualFile = file.originFileObj
|
||||
}
|
||||
// 如果直接就是 File 对象
|
||||
else if (file instanceof File) {
|
||||
actualFile = file
|
||||
} else {
|
||||
console.log('❌ 无法获取有效的 File 对象:', file)
|
||||
message.error(t('选择文件失败,无效的文件对象'))
|
||||
onError()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 处理拖动离开上传区域
|
||||
const handleDragLeave = () => {
|
||||
isDragging.value = false
|
||||
}
|
||||
// 检查是否是图片文件
|
||||
if (!actualFile.type.startsWith('image/')) {
|
||||
console.log('❌ 文件类型不符合要求:', actualFile.type)
|
||||
message.error(t('选择文件失败,只能上传图片文件'))
|
||||
onError()
|
||||
return
|
||||
}
|
||||
|
||||
// 处理拖放文件 - 修改后的版本,不依赖主进程
|
||||
const handleDrop = (event) => {
|
||||
isDragging.value = false
|
||||
// 读取文件的 base64 数据
|
||||
const reader = new FileReader()
|
||||
|
||||
// 获取拖放的文件
|
||||
const files = event.dataTransfer.files
|
||||
|
||||
if (files.length > 0) {
|
||||
// 处理所有拖放的文件
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i]
|
||||
|
||||
// 检查是否是图片文件
|
||||
if (file.type.startsWith('image/')) {
|
||||
// 创建文件读取器,读取为Data URL
|
||||
const reader = new FileReader()
|
||||
reader.onload = (e) => {
|
||||
// 直接使用base64数据作为图片源
|
||||
const base64Data = e.target.result
|
||||
|
||||
if (!presetStore.selectPreset.showImage) {
|
||||
presetStore.selectPreset.showImage = []
|
||||
}
|
||||
presetStore.selectPreset.showImage.push(base64Data)
|
||||
}
|
||||
reader.readAsDataURL(file)
|
||||
}
|
||||
reader.onload = (e) => {
|
||||
const base64Data = e.target.result
|
||||
if (presetStore.selectPreset.showImage == null) {
|
||||
presetStore.selectPreset.showImage = []
|
||||
}
|
||||
presetStore.selectPreset.showImage.push(base64Data)
|
||||
message.success(t('已选择文件:{fileName}', { fileName: actualFile.name }))
|
||||
onFinish()
|
||||
}
|
||||
|
||||
reader.onerror = (e) => {
|
||||
console.log('❌ 文件读取失败:', e)
|
||||
message.error(t('文件读取失败'))
|
||||
onError()
|
||||
}
|
||||
|
||||
// 开始读取文件为 Data URL (base64)
|
||||
reader.readAsDataURL(actualFile)
|
||||
}
|
||||
|
||||
// 移除文件
|
||||
@ -291,6 +276,15 @@ const handleSave = async () => {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 这边做一个动态的主题色
|
||||
const borderColor = computed(() => {
|
||||
return themeStore.menuPrimaryColor
|
||||
})
|
||||
// 背景色
|
||||
const backgroundColor = computed(() => {
|
||||
return themeStore.menuPrimaryShadow
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -326,19 +320,74 @@ const handleSave = async () => {
|
||||
|
||||
/* 上传卡片样式 */
|
||||
.upload-card {
|
||||
cursor: pointer;
|
||||
border: 2px dashed #e0e0e0;
|
||||
height: 168px; /* 与图片项高度保持一致 */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.upload-card:hover {
|
||||
border-color: #2080f0;
|
||||
}
|
||||
|
||||
/* 自定义上传组件样式 */
|
||||
.upload-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.upload-wrapper :deep(.n-upload) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.upload-wrapper :deep(.n-upload-trigger) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.upload-wrapper :deep(.n-upload-dragger) {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
border: none !important;
|
||||
background: transparent !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
.upload-wrapper :deep(.n-upload-dragger):hover {
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.upload-wrapper :deep(.n-upload-dragger.n-upload-dragger--drag-over) {
|
||||
background-color: rgba(24, 160, 88, 0.1) !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
/* 拖拽悬停时的外部边框效果 */
|
||||
.upload-card:has(.n-upload-dragger--drag-over),
|
||||
.upload-wrapper:has(.n-upload-dragger--drag-over) ~ .upload-card,
|
||||
.upload-card:hover {
|
||||
border-color: v-bind(borderColor);
|
||||
background-color: v-bind(backgroundColor);
|
||||
}
|
||||
|
||||
.upload-placeholder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -355,11 +404,10 @@ const handleSave = async () => {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 添加拖拽状态样式 */
|
||||
.upload-card.dragging {
|
||||
border-color: #18a058;
|
||||
background-color: rgba(24, 160, 88, 0.1);
|
||||
box-shadow: 0 0 10px rgba(24, 160, 88, 0.3);
|
||||
.upload-hint {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* 保留原有样式 */
|
||||
|
||||
@ -110,7 +110,7 @@ const { validateAuthorization, updateAuthorizationInfo, syncAuthorizationToMain
|
||||
useAuthorization()
|
||||
|
||||
const authUrl = computed(() => {
|
||||
return SoftwareData.systemInfo.wikiUrl
|
||||
return SoftwareData.systemInfo.authUrl
|
||||
})
|
||||
|
||||
const softwareStore = useSoftwareStore()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user