V 3.3.9(2025.05.29)
1. 生图包适配,修复部分任务无法获取图片的问题。 2. 新增聚合推文原创重置功能,直接重置GPT提示词、合并提示词、出图等。 3. 优化加载界面,提升用户体验。 4. 优化主页显示,优化UI界面,提升用户体验。
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
export const SoftwareData = {
|
||||
"version": "V3.3.9",
|
||||
"date": "2025-05-29",
|
||||
"notes": [
|
||||
"修复了音频处理的错误。",
|
||||
"改进了视频处理的性能。",
|
||||
"更新了依赖库以提高安全性。"
|
||||
]
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import Realm, { UpdateMode } from 'realm'
|
||||
import { BookModel } from '../../model/Book/book.js'
|
||||
import path from 'path'
|
||||
import { define } from '../../../define.js'
|
||||
import { define } from '../../../define'
|
||||
import { BookImageCategory, BookTaskStatus, BookType } from '../../../enum/bookEnum.js'
|
||||
import { successMessage } from '../../../../main/Public/generalTools'
|
||||
import { CheckFolderExistsOrCreate, CopyFileOrFolder } from '../../../Tools/file'
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
let define = {}
|
||||
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined'
|
||||
|
||||
if (!isBrowser) {
|
||||
const path = require('path')
|
||||
const { app } = require('electron')
|
||||
if (!app.isPackaged) {
|
||||
define = {
|
||||
discordScript: path.join(__dirname, '../../src/main/discord/discordScript.js'),
|
||||
zhanwei_image: path.join(__dirname, '../../resources/image/zhanwei.png'),
|
||||
config_path: path.join(__dirname, '../../resources/config/global_setting.json'),
|
||||
clip_setting: path.join(__dirname, '../../resources/config/clip_setting.json'),
|
||||
sd_setting: path.join(__dirname, '../../resources/config/sd_config.json'),
|
||||
dynamic_setting: path.join(__dirname, '../../resources/config/dynamic_setting.json'),
|
||||
tag_setting: path.join(__dirname, '../../resources/config/tag_setting.json'),
|
||||
img_base: path.join(__dirname, '../../resources/config/img_base.json'),
|
||||
video_config: path.join(__dirname, '../../resources/config/video_config.json'),
|
||||
system_config: path.join(__dirname, '../../resources/config/system_config.json'),
|
||||
scripts_path: path.join(__dirname, '../../resources/scripts'),
|
||||
db_path: path.join(__dirname, '../../resources/scripts/db'),
|
||||
project_path: path.join(__dirname, '../../project'),
|
||||
tts_path: path.join(__dirname, '../../tts'),
|
||||
logger_path: path.join(__dirname, '../../resources/logger'),
|
||||
package_path: path.join(__dirname, '../../resources/package'),
|
||||
image_path: path.join(__dirname, '../../resources/image'),
|
||||
temp_sd_image: path.join(__dirname, '../../resources/image/TempSDImage'),
|
||||
draft_temp_path: path.join(__dirname, '../../resources/tmp/temp.zip'),
|
||||
init_config_path: path.join(__dirname, '../../resources/tmp/config'),
|
||||
clip_speed_temp_path: path.join(__dirname, '../../resources/tmp/Clip/speeds_tmp.json'),
|
||||
add_canvases_temp_path: path.join(__dirname, '../../resources/tmp/Clip/canvases_tmp.json'),
|
||||
add_sound_channel_mappings_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/sound_channel_mappings_tmp.json'
|
||||
),
|
||||
add_vocal_separations_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/vocal_separations_tmp.json'
|
||||
),
|
||||
add_material_video_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/videoMaterialTemp.json'
|
||||
),
|
||||
add_tracks_segments_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/tracks_segments_tmp.json'
|
||||
),
|
||||
add_tracks_type_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/tracks_type_tmp.json'
|
||||
),
|
||||
add_material_animations_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/material_animations_tmp.json'
|
||||
),
|
||||
add_material_text_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/material_text_temp.json'
|
||||
),
|
||||
add_track_text_segments_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/track_text_segments_temp.json'
|
||||
),
|
||||
add_materials_beats_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/materials_beats_tmp.json'
|
||||
),
|
||||
add_materials_audios_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/materials_audios_tmp.json'
|
||||
),
|
||||
add_tracks_audio_segments_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/tracks_audio_segments_tmp.json'
|
||||
),
|
||||
add_keyframe_tmp_path: path.join(__dirname, '../../resources/tmp/Clip/keyframe_tmp.json')
|
||||
}
|
||||
} else {
|
||||
define = {
|
||||
zhanwei_image: path.join(__dirname, '../../../resources/image/zhanwei.png'),
|
||||
config_path: path.join(__dirname, '../../../resources/config/global_setting.json'),
|
||||
clip_setting: path.join(__dirname, '../../../resources/config/clip_setting.json'),
|
||||
sd_setting: path.join(__dirname, '../../../resources/config/sd_config.json'),
|
||||
dynamic_setting: path.join(__dirname, '../../../resources/config/dynamic_setting.json'),
|
||||
tag_setting: path.join(__dirname, '../../../resources/config/tag_setting.json'),
|
||||
video_config: path.join(__dirname, '../../../resources/config/video_config.json'),
|
||||
system_config: path.join(__dirname, '../../../resources/config/system_config.json'),
|
||||
img_base: path.join(__dirname, '../../../resources/config/img_base.json'),
|
||||
scripts_path: path.join(__dirname, '../../../resources/scripts'),
|
||||
db_path: path.join(__dirname, '../../../resources/scripts/db'),
|
||||
project_path: path.join(__dirname, '../../../project'),
|
||||
tts_path: path.join(__dirname, '../../../tts'),
|
||||
logger_path: path.join(__dirname, '../../../resources/logger'),
|
||||
package_path: path.join(__dirname, '../../../resources/package'),
|
||||
discordScript: path.join(__dirname, '../../../resources/scripts/discordScript.js'),
|
||||
image_path: path.join(__dirname, '../../../resources/image'),
|
||||
temp_sd_image: path.join(__dirname, '../../../resources/image/TempSDImage'),
|
||||
draft_temp_path: path.join(__dirname, '../../../resources/tmp/temp.zip'),
|
||||
init_config_path: path.join(__dirname, '../../../resources/tmp/config'),
|
||||
clip_speed_temp_path: path.join(__dirname, '../../../resources/tmp/Clip/speeds_tmp.json'),
|
||||
add_canvases_temp_path: path.join(__dirname, '../../../resources/tmp/Clip/canvases_tmp.json'),
|
||||
add_sound_channel_mappings_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/sound_channel_mappings_tmp.json'
|
||||
),
|
||||
add_vocal_separations_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/vocal_separations_tmp.json'
|
||||
),
|
||||
add_material_video_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/videoMaterialTemp.json'
|
||||
),
|
||||
add_tracks_segments_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/tracks_segments_tmp.json'
|
||||
),
|
||||
add_tracks_type_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/tracks_type_tmp.json'
|
||||
),
|
||||
add_material_animations_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/material_animations_tmp.json'
|
||||
),
|
||||
add_material_text_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/material_text_temp.json'
|
||||
),
|
||||
add_track_text_segments_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/track_text_segments_temp.json'
|
||||
),
|
||||
add_materials_beats_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/materials_beats_tmp.json'
|
||||
),
|
||||
add_materials_audios_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/materials_audios_tmp.json'
|
||||
),
|
||||
add_tracks_audio_segments_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/tracks_audio_segments_tmp.json'
|
||||
),
|
||||
add_keyframe_tmp_path: path.join(__dirname, '../../../resources/tmp/Clip/keyframe_tmp.json')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
define['remotemj_api'] = 'https://api.laitool.net/'
|
||||
define['serverUrl'] = 'http://lms.laitool.cn'
|
||||
// define['serverUrl'] = 'https://localhost:44362'
|
||||
define['hkServerUrl'] = 'https://laitool.net/'
|
||||
define['bakServerUrl'] = 'https://laitool.net/'
|
||||
define['API'] = 'f85d39ed5a40fd09966f13f12b6cf0f0'
|
||||
|
||||
// define['lms'] =
|
||||
// process.env.NODE_ENV == 'development' ? 'https://localhost:44362' : 'https://lms.laitool.cn'
|
||||
|
||||
define['lms'] = 'https://lms.laitool.cn'
|
||||
|
||||
|
||||
export { define }
|
||||
@@ -0,0 +1,178 @@
|
||||
// 检测当前环境
|
||||
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined'
|
||||
|
||||
// 浏览器环境的路径处理函数
|
||||
function joinPath(...segments: string[]): string {
|
||||
return segments.join('/').replace(/\/+/g, '/');
|
||||
}
|
||||
|
||||
// 统一的路径处理函数
|
||||
const pathJoin = isBrowser ? joinPath : require('path').join;
|
||||
|
||||
// 定义类型接口
|
||||
interface DefineConfig {
|
||||
// 脚本和可执行文件路径
|
||||
discordScript: string | null;
|
||||
|
||||
// 图片资源路径
|
||||
zhanwei_image: string;
|
||||
image_path: string;
|
||||
temp_sd_image: string;
|
||||
|
||||
// 配置文件路径
|
||||
config_path: string | null;
|
||||
clip_setting: string | null;
|
||||
sd_setting: string | null;
|
||||
dynamic_setting: string | null;
|
||||
tag_setting: string | null;
|
||||
img_base: string | null;
|
||||
video_config: string | null;
|
||||
system_config: string | null;
|
||||
|
||||
// 目录路径
|
||||
scripts_path: string | null;
|
||||
db_path: string | null;
|
||||
project_path: string | null;
|
||||
tts_path: string | null;
|
||||
logger_path: string | null;
|
||||
package_path: string | null;
|
||||
|
||||
// 临时文件路径
|
||||
draft_temp_path: string | null;
|
||||
init_config_path: string | null;
|
||||
|
||||
// Clip 相关临时文件路径
|
||||
clip_speed_temp_path: string | null;
|
||||
add_canvases_temp_path: string | null;
|
||||
add_sound_channel_mappings_temp_path: string | null;
|
||||
add_vocal_separations_temp_path: string | null;
|
||||
add_material_video_temp_path: string | null;
|
||||
add_tracks_segments_temp_path: string | null;
|
||||
add_tracks_type_temp_path: string | null;
|
||||
add_material_animations_temp_path: string | null;
|
||||
add_material_text_temp_path: string | null;
|
||||
add_track_text_segments_temp_path: string | null;
|
||||
add_materials_beats_tmp_path: string | null;
|
||||
add_materials_audios_tmp_path: string | null;
|
||||
add_tracks_audio_segments_tmp_path: string | null;
|
||||
add_keyframe_tmp_path: string | null;
|
||||
|
||||
// API 配置
|
||||
remotemj_api: string;
|
||||
serverUrl: string;
|
||||
hkServerUrl: string;
|
||||
bakServerUrl: string;
|
||||
API: string;
|
||||
lms: string;
|
||||
}
|
||||
|
||||
let define: DefineConfig = {} as DefineConfig;
|
||||
|
||||
if (!isBrowser) {
|
||||
const path = require('path')
|
||||
const { app } = require('electron')
|
||||
|
||||
// 根据打包状态确定基础路径
|
||||
const basePath = !app.isPackaged ?
|
||||
path.join(__dirname, '../../') :
|
||||
path.join(__dirname, '../../../');
|
||||
|
||||
define = {
|
||||
discordScript: !app.isPackaged ? pathJoin(__dirname, '../../src/main/discord/discordScript.js') : pathJoin(basePath, 'resources/scripts/discordScript.js'),
|
||||
zhanwei_image: pathJoin(basePath, 'resources/image/zhanwei.png'),
|
||||
config_path: pathJoin(basePath, 'resources/config/global_setting.json'),
|
||||
clip_setting: pathJoin(basePath, 'resources/config/clip_setting.json'),
|
||||
sd_setting: pathJoin(basePath, 'resources/config/sd_config.json'),
|
||||
dynamic_setting: pathJoin(basePath, 'resources/config/dynamic_setting.json'),
|
||||
tag_setting: pathJoin(basePath, 'resources/config/tag_setting.json'),
|
||||
img_base: pathJoin(basePath, 'resources/config/img_base.json'),
|
||||
video_config: pathJoin(basePath, 'resources/config/video_config.json'),
|
||||
system_config: pathJoin(basePath, 'resources/config/system_config.json'),
|
||||
scripts_path: pathJoin(basePath, 'resources/scripts'),
|
||||
db_path: pathJoin(basePath, 'resources/scripts/db'),
|
||||
project_path: pathJoin(basePath, 'project'),
|
||||
tts_path: pathJoin(basePath, 'tts'),
|
||||
logger_path: pathJoin(basePath, 'resources/logger'),
|
||||
package_path: pathJoin(basePath, 'resources/package'),
|
||||
image_path: pathJoin(basePath, 'resources/image'),
|
||||
temp_sd_image: pathJoin(basePath, 'resources/image/TempSDImage'),
|
||||
draft_temp_path: pathJoin(basePath, 'resources/tmp/temp.zip'),
|
||||
init_config_path: pathJoin(basePath, 'resources/tmp/config'),
|
||||
clip_speed_temp_path: pathJoin(basePath, 'resources/tmp/Clip/speeds_tmp.json'),
|
||||
add_canvases_temp_path: pathJoin(basePath, 'resources/tmp/Clip/canvases_tmp.json'),
|
||||
add_sound_channel_mappings_temp_path: pathJoin(basePath, 'resources/tmp/Clip/sound_channel_mappings_tmp.json'),
|
||||
add_vocal_separations_temp_path: pathJoin(basePath, 'resources/tmp/Clip/vocal_separations_tmp.json'),
|
||||
add_material_video_temp_path: pathJoin(basePath, 'resources/tmp/Clip/videoMaterialTemp.json'),
|
||||
add_tracks_segments_temp_path: pathJoin(basePath, 'resources/tmp/Clip/tracks_segments_tmp.json'),
|
||||
add_tracks_type_temp_path: pathJoin(basePath, 'resources/tmp/Clip/tracks_type_tmp.json'),
|
||||
add_material_animations_temp_path: pathJoin(basePath, 'resources/tmp/Clip/material_animations_tmp.json'),
|
||||
add_material_text_temp_path: pathJoin(basePath, 'resources/tmp/Clip/material_text_temp.json'),
|
||||
add_track_text_segments_temp_path: pathJoin(basePath, 'resources/tmp/Clip/track_text_segments_temp.json'),
|
||||
add_materials_beats_tmp_path: pathJoin(basePath, 'resources/tmp/Clip/materials_beats_tmp.json'),
|
||||
add_materials_audios_tmp_path: pathJoin(basePath, 'resources/tmp/Clip/materials_audios_tmp.json'),
|
||||
add_tracks_audio_segments_tmp_path: pathJoin(basePath, 'resources/tmp/Clip/tracks_audio_segments_tmp.json'),
|
||||
add_keyframe_tmp_path: pathJoin(basePath, 'resources/tmp/Clip/keyframe_tmp.json'),
|
||||
// API 配置
|
||||
remotemj_api: 'https://api.laitool.net/',
|
||||
serverUrl: 'http://lms.laitool.cn',
|
||||
hkServerUrl: 'https://laitool.net/',
|
||||
bakServerUrl: 'https://laitool.net/',
|
||||
API: 'f85d39ed5a40fd09966f13f12b6cf0f0',
|
||||
lms: 'https://lms.laitool.cn'
|
||||
};
|
||||
} else {
|
||||
// 浏览器环境
|
||||
const basePath = './';
|
||||
define = {
|
||||
discordScript: null,
|
||||
zhanwei_image: pathJoin(basePath, 'resources/image/zhanwei.png'),
|
||||
config_path: null,
|
||||
clip_setting: null,
|
||||
sd_setting: null,
|
||||
dynamic_setting: null,
|
||||
tag_setting: null,
|
||||
img_base: null,
|
||||
video_config: null,
|
||||
system_config: null,
|
||||
scripts_path: null,
|
||||
db_path: null,
|
||||
project_path: null,
|
||||
tts_path: null,
|
||||
logger_path: null,
|
||||
package_path: null,
|
||||
image_path: pathJoin(basePath, 'resources/image'),
|
||||
temp_sd_image: pathJoin(basePath, 'resources/image/TempSDImage'),
|
||||
draft_temp_path: null,
|
||||
init_config_path: null,
|
||||
clip_speed_temp_path: null,
|
||||
add_canvases_temp_path: null,
|
||||
add_sound_channel_mappings_temp_path: null,
|
||||
add_vocal_separations_temp_path: null,
|
||||
add_material_video_temp_path: null,
|
||||
add_tracks_segments_temp_path: null,
|
||||
add_tracks_type_temp_path: null,
|
||||
add_material_animations_temp_path: null,
|
||||
add_material_text_temp_path: null,
|
||||
add_track_text_segments_temp_path: null,
|
||||
add_materials_beats_tmp_path: null,
|
||||
add_materials_audios_tmp_path: null,
|
||||
add_tracks_audio_segments_tmp_path: null,
|
||||
add_keyframe_tmp_path: null,
|
||||
// API 配置
|
||||
remotemj_api: 'https://api.laitool.net/',
|
||||
serverUrl: 'http://lms.laitool.cn',
|
||||
hkServerUrl: 'https://laitool.net/',
|
||||
bakServerUrl: 'https://laitool.net/',
|
||||
API: 'f85d39ed5a40fd09966f13f12b6cf0f0',
|
||||
lms: 'https://lms.laitool.cn'
|
||||
};
|
||||
}
|
||||
|
||||
// 浏览器环境下挂载到window
|
||||
if (isBrowser && typeof window !== 'undefined') {
|
||||
(window as any).define = define;
|
||||
}
|
||||
|
||||
// 导出类型和实例
|
||||
export type { DefineConfig };
|
||||
export { define };
|
||||
@@ -0,0 +1,12 @@
|
||||
const AXIOS = {
|
||||
/** http的get请求 */
|
||||
HTTP_GET: 'http:get',
|
||||
/** http的post请求 */
|
||||
HTTP_POST: 'http:post',
|
||||
/** http的put请求 */
|
||||
HTTP_PUT: 'http:put',
|
||||
/** http的delete请求 */
|
||||
HTTP_DELETE: 'http:delete'
|
||||
}
|
||||
|
||||
export default AXIOS
|
||||
@@ -6,9 +6,11 @@ import BOOK from "./bookDefineString"
|
||||
import WRITE from "./writeDefineString"
|
||||
import DB from "./dbDefineString"
|
||||
import OPTIONS from "./optionsDefineString"
|
||||
import AXIOS from "./axiosDefineString"
|
||||
|
||||
export const DEFINE_STRING = {
|
||||
SYSTEM: SYSTEM,
|
||||
AXIOS : AXIOS,
|
||||
TASK: TASK,
|
||||
TTS: TTS,
|
||||
BOOK: BOOK,
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
import { ipcMain } from 'electron'
|
||||
import axios from 'axios'
|
||||
import { DEFINE_STRING } from '../../define/define_string'
|
||||
|
||||
function AxiosIpc() {
|
||||
// 通用 GET 请求
|
||||
ipcMain.handle(DEFINE_STRING.AXIOS.HTTP_GET, async (_, url, config = {}) => {
|
||||
try {
|
||||
const response = await axios.get(url, config)
|
||||
return {
|
||||
success: true,
|
||||
data: response.data,
|
||||
status: response.status
|
||||
}
|
||||
} catch (error: any) {
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
message: error.message,
|
||||
status: error.response?.status,
|
||||
data: error.response?.data
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 通用 POST 请求
|
||||
ipcMain.handle(DEFINE_STRING.AXIOS.HTTP_POST, async (_, url, data = {}, config = {}) => {
|
||||
try {
|
||||
const response = await axios.post(url, data, config)
|
||||
return {
|
||||
success: true,
|
||||
data: response.data,
|
||||
status: response.status
|
||||
}
|
||||
} catch (error: any) {
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
message: error.message,
|
||||
status: error.response?.status,
|
||||
data: error.response?.data
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 通用 PUT 请求
|
||||
ipcMain.handle(DEFINE_STRING.AXIOS.HTTP_PUT, async (_, url, data = {}, config = {}) => {
|
||||
try {
|
||||
const response = await axios.put(url, data, config)
|
||||
return {
|
||||
success: true,
|
||||
data: response.data,
|
||||
status: response.status
|
||||
}
|
||||
} catch (error: any) {
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
status: error.response?.status,
|
||||
data: error.response?.data
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 通用 DELETE 请求
|
||||
ipcMain.handle(DEFINE_STRING.AXIOS.HTTP_DELETE, async (_, url, config = {}) => {
|
||||
try {
|
||||
const response = await axios.delete(url, config)
|
||||
return {
|
||||
success: true,
|
||||
data: response.data,
|
||||
status: response.status
|
||||
}
|
||||
} catch (error: any) {
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
status: error.response?.status,
|
||||
data: error.response?.data
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default AxiosIpc
|
||||
@@ -18,6 +18,7 @@ import { DBIpc } from './dbIpc'
|
||||
import { PresetIpc } from './presetIpc'
|
||||
import { TaskIpc } from './taskIpc'
|
||||
import { OptionsIpc } from './optionsIpc'
|
||||
import AxiosIpc from './axiosIpc'
|
||||
|
||||
export async function RegisterIpc(createWindow) {
|
||||
PromptIpc()
|
||||
@@ -40,4 +41,5 @@ export async function RegisterIpc(createWindow) {
|
||||
BookIpc()
|
||||
TTSIpc()
|
||||
OptionsIpc()
|
||||
AxiosIpc()
|
||||
}
|
||||
@@ -619,7 +619,7 @@ export class MJOpt {
|
||||
// }
|
||||
|
||||
// 判断是不是有批量的图片
|
||||
if (task_res.subImagePath.length > 0) {
|
||||
if (task_res.subImagePath && task_res.subImagePath.length > 0) {
|
||||
batchImages = [...task_res.subImagePath]
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,10 @@ export default class SystemInfo {
|
||||
nextDate.setDate(currentDate.getDate() + 1);
|
||||
if (systemConfig && systemConfig.gpu && nextDate > new Date()) {
|
||||
global.gpu = systemConfig.gpu
|
||||
return successMessage(version + ' ' + (global.gpu?.name ? global.gpu.name : ''), '获取成功')
|
||||
return successMessage({
|
||||
version: version,
|
||||
gpu: global.gpu
|
||||
}, '获取版本信息和显卡信息成功', 'SystemIpc_GET_VISION_AND_GPU_MESSAGE');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +106,10 @@ export default class SystemInfo {
|
||||
systemConfig.gpu = global.gpu
|
||||
systemConfig.gpu.updateTime = new Date()
|
||||
await fs.promises.writeFile(systemConfigPath, JSON.stringify(systemConfig));
|
||||
return successMessage(version + ' ' + (global.gpu?.name ? global.gpu.name : ''), '获取成功')
|
||||
return successMessage({
|
||||
version: version,
|
||||
gpu: global.gpu
|
||||
}, '获取版本信息和显卡信息成功', 'SystemIpc_GET_VISION_AND_GPU_MESSAGE');
|
||||
} catch (error) {
|
||||
return errorMessage('获取版本信息和显卡信息错误,错误信息如下:' + error.message, 'SystemIpc_GET_VISION_AND_GPU_MESSAGE')
|
||||
}
|
||||
@@ -116,12 +122,7 @@ export default class SystemInfo {
|
||||
*/
|
||||
public async CheckMachineStatus(value: string) {
|
||||
try {
|
||||
// 判断机器码是不是存在
|
||||
// let res = await axios.post('http://api.yu-zhile.com/GetMachineStatus', {
|
||||
// machineId: value
|
||||
// })
|
||||
// /lms/Machine/GetMachineStatus/{machineId}
|
||||
//
|
||||
|
||||
let res = await axios.get('https://lms.laitool.cn/lms/Machine/GetMachineStatus/' + value);
|
||||
if (res.status != 200) {
|
||||
throw new Error('请求错误')
|
||||
@@ -145,11 +146,6 @@ export default class SystemInfo {
|
||||
public async GetMachineId() {
|
||||
try {
|
||||
let baseId = await machineId(true);
|
||||
let checkRes = await this.CheckMachineStatus(baseId);
|
||||
if (checkRes.code == 1) {
|
||||
global.machineId = baseId;
|
||||
return successMessage(baseId, '获取机器码成功')
|
||||
}
|
||||
let hardwareInfo = '';
|
||||
try {
|
||||
if (process.platform === 'win32') {
|
||||
|
||||
+6
-7
@@ -19,7 +19,7 @@ import { SoftWareServiceBasic } from './Service/ServiceBasic/softwareServiceBasi
|
||||
// ipc
|
||||
import { DiscordIpc, RemoveDiscordIpc } from './IPCEvent/discordIpc.js'
|
||||
import { Logger } from './logger.js'
|
||||
import { RegisterIpc } from './IPCEvent/index.js'
|
||||
import { RegisterIpc } from './IPCEvent/index'
|
||||
|
||||
import { InitRemoteMjSettingType } from './initFunc'
|
||||
|
||||
@@ -47,13 +47,12 @@ function removeIpcHandler(hash) {
|
||||
}
|
||||
}
|
||||
|
||||
async function createWindow(hash = 'ShowMessage', data, url = null) {
|
||||
async function createWindow(hash = 'mainHome', data, url = null) {
|
||||
// Create the browser window.
|
||||
await InitData(global)
|
||||
global.currentHash = hash
|
||||
// 判断当前是不是有设置的宽高,用的话记忆
|
||||
let isRe =
|
||||
global.config.window_wh_bm_remember && hash == 'ShowMessage' && global.config.window_wh_bm
|
||||
let isRe = global.config.window_wh_bm_remember && hash == 'mainHome' && global.config.window_wh_bm
|
||||
const ses = session.fromPartition('persist:my-session')
|
||||
let mainWindow = new BrowserWindow({
|
||||
width: isRe ? global.config.window_wh_bm.width : 900,
|
||||
@@ -112,7 +111,7 @@ async function createWindow(hash = 'ShowMessage', data, url = null) {
|
||||
removeIpcHandler(hash)
|
||||
global.newWindow = global.newWindow.filter((item) => item.id != mainWindow.id)
|
||||
// 判断当前的是不是开启了记录功能
|
||||
if (global.config.window_wh_bm_remember && hash == 'ShowMessage') {
|
||||
if (global.config.window_wh_bm_remember && hash == 'mainHome') {
|
||||
let window_wh_bm = mainWindow.getBounds()
|
||||
// 记录到文件中
|
||||
await setting.ModifySampleSetting(JSON.stringify({ window_wh_bm: window_wh_bm }))
|
||||
@@ -201,7 +200,7 @@ app.whenReady().then(async () => {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
mainWindow = createWindow('ShowMessage', null)
|
||||
mainWindow = createWindow('mainHome', null)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -210,7 +209,7 @@ app.whenReady().then(async () => {
|
||||
await AutoSync()
|
||||
|
||||
global.newWindow = []
|
||||
mainWindow = await createWindow('ShowMessage', null)
|
||||
mainWindow = await createWindow('mainHome', null)
|
||||
|
||||
global.requestQuene = new AsyncQueue(global, global.config.task_number)
|
||||
global.fileQueue = new AsyncQueue(global, 1)
|
||||
|
||||
Vendored
+57
@@ -13,4 +13,61 @@ declare namespace SystemConfig {
|
||||
updateTime?: Date;
|
||||
}
|
||||
|
||||
//#region 更新信息和版本信息
|
||||
|
||||
/**
|
||||
* 更新变更类型
|
||||
*/
|
||||
export type ChangeType = 'bugfix' | 'add' | 'improvement' | 'remove' | 'security' | 'performance'
|
||||
|
||||
/**
|
||||
* 单个变更项
|
||||
*/
|
||||
export interface ChangeItem {
|
||||
/** 变更类型 */
|
||||
type: ChangeType
|
||||
/** 变更描述 */
|
||||
description: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 版本更新信息
|
||||
*/
|
||||
export interface SubUpdateInfo {
|
||||
/** 版本号 */
|
||||
version: string
|
||||
/** 更新日期 */
|
||||
updateDate: string
|
||||
/** 变更列表 */
|
||||
changes: ChangeItem[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 完整的更新信息结构
|
||||
*/
|
||||
export interface UpdateInfo {
|
||||
/** 最新版本号 */
|
||||
latestVersion: string
|
||||
/** 最新更新日期 */
|
||||
updateDate: string
|
||||
/** 所有版本的更新信息 */
|
||||
updateInfo: SubUpdateInfo[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统更新信息
|
||||
*/
|
||||
interface VersionInfo {
|
||||
/** 当前版本 */
|
||||
currentVersion: string
|
||||
/** 最新版本 */
|
||||
latestVersion: string
|
||||
|
||||
/** 更新信息 */
|
||||
updateInfo: UpdateInfo
|
||||
/** 是否可以更新 */
|
||||
canUpdate: boolean
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import { DEFINE_STRING } from '../define/define_string'
|
||||
import { ipcRenderer } from 'electron'
|
||||
|
||||
// 定义请求配置接口
|
||||
interface RequestConfig {
|
||||
headers?: Record<string, string>
|
||||
params?: Record<string, any>
|
||||
timeout?: number
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
// 定义响应接口
|
||||
interface HttpResponse<T = any> {
|
||||
success: boolean
|
||||
data?: T
|
||||
error?: string
|
||||
status?: number
|
||||
}
|
||||
|
||||
// HTTP 客户端接口
|
||||
const axiosPrelod = {
|
||||
/**
|
||||
* 发送 GET 请求
|
||||
* @param url 请求地址
|
||||
* @param config 请求配置
|
||||
*/
|
||||
get: async <T = any>(url: string, config?: RequestConfig): Promise<HttpResponse<T>> =>
|
||||
await ipcRenderer.invoke(DEFINE_STRING.AXIOS.HTTP_GET, url, config),
|
||||
|
||||
/**
|
||||
* 发送 POST 请求
|
||||
* @param url 请求地址
|
||||
* @param data 请求数据
|
||||
* @param config 请求配置
|
||||
*/
|
||||
post: async <T = any>(
|
||||
url: string,
|
||||
data?: any,
|
||||
config?: RequestConfig
|
||||
): Promise<HttpResponse<T>> =>
|
||||
await ipcRenderer.invoke(DEFINE_STRING.AXIOS.HTTP_POST, url, data, config),
|
||||
|
||||
/**
|
||||
* 发送 PUT 请求
|
||||
* @param url 请求地址
|
||||
* @param data 请求数据
|
||||
* @param config 请求配置
|
||||
*/
|
||||
put: async <T = any>(url: string, data?: any, config?: RequestConfig): Promise<HttpResponse<T>> =>
|
||||
await ipcRenderer.invoke(DEFINE_STRING.AXIOS.HTTP_PUT, url, data, config),
|
||||
|
||||
/**
|
||||
* 发送 DELETE 请求
|
||||
* @param url 请求地址
|
||||
* @param config 请求配置
|
||||
*/
|
||||
delete: async <T = any>(url: string, config?: RequestConfig): Promise<HttpResponse<T>> =>
|
||||
await ipcRenderer.invoke(DEFINE_STRING.AXIOS.HTTP_DELETE, url, config)
|
||||
}
|
||||
|
||||
export { axiosPrelod }
|
||||
@@ -17,6 +17,7 @@ import { translate } from './translate'
|
||||
import { preset } from './preset'
|
||||
import { task } from './task'
|
||||
import { options } from './options'
|
||||
import { axiosPrelod } from './axios'
|
||||
// Custom APIs for renderer
|
||||
|
||||
let events = []
|
||||
@@ -480,6 +481,7 @@ if (process.contextIsolated) {
|
||||
contextBridge.exposeInMainWorld('preset', preset)
|
||||
contextBridge.exposeInMainWorld('task', task)
|
||||
contextBridge.exposeInMainWorld('options', options)
|
||||
contextBridge.exposeInMainWorld('axios', axiosPrelod)
|
||||
contextBridge.exposeInMainWorld('darkMode', {
|
||||
toggle: (value) => ipcRenderer.invoke('dark-mode:toggle', value)
|
||||
})
|
||||
@@ -505,4 +507,5 @@ if (process.contextIsolated) {
|
||||
window.task = task
|
||||
window.translate = translate
|
||||
window.options = options
|
||||
window.axios = axiosPrelod
|
||||
}
|
||||
|
||||
Vendored
-6
@@ -13,9 +13,7 @@ declare module 'vue' {
|
||||
NCheckbox: typeof import('naive-ui')['NCheckbox']
|
||||
NCode: typeof import('naive-ui')['NCode']
|
||||
NColorPicker: typeof import('naive-ui')['NColorPicker']
|
||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||
NDataTable: typeof import('naive-ui')['NDataTable']
|
||||
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
|
||||
NDivider: typeof import('naive-ui')['NDivider']
|
||||
NDropdown: typeof import('naive-ui')['NDropdown']
|
||||
NDynamicInput: typeof import('naive-ui')['NDynamicInput']
|
||||
@@ -32,10 +30,6 @@ declare module 'vue' {
|
||||
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
|
||||
NLog: typeof import('naive-ui')['NLog']
|
||||
NMenu: typeof import('naive-ui')['NMenu']
|
||||
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
||||
NModal: typeof import('naive-ui')['NModal']
|
||||
NModalProvider: typeof import('naive-ui')['NModalProvider']
|
||||
NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
||||
NPopover: typeof import('naive-ui')['NPopover']
|
||||
NProgress: typeof import('naive-ui')['NProgress']
|
||||
NSelect: typeof import('naive-ui')['NSelect']
|
||||
|
||||
+31
-40
@@ -7,7 +7,9 @@
|
||||
<n-modal-provider>
|
||||
<n-dialog-provider>
|
||||
<n-notification-provider>
|
||||
<RouterView></RouterView>
|
||||
<LoadingComponent v-if="loading" @loading-complete="onComplete" fullScreen>
|
||||
</LoadingComponent>
|
||||
<RouterView v-else></RouterView>
|
||||
</n-notification-provider>
|
||||
</n-dialog-provider>
|
||||
</n-modal-provider>
|
||||
@@ -35,7 +37,7 @@
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { defineComponent, onMounted } from 'vue'
|
||||
import hljs from 'highlight.js/lib/core'
|
||||
import javascript from 'highlight.js/lib/languages/javascript'
|
||||
@@ -51,49 +53,38 @@ import {
|
||||
} from 'naive-ui'
|
||||
import { useSoftwareStore } from '../../stores/software'
|
||||
import { SoftColor } from '../../define/enum/softwareEnum'
|
||||
import LoadingComponent from './components/Home/LoadingComponent.vue'
|
||||
|
||||
const loading = ref(true)
|
||||
|
||||
const onComplete = () => {
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
hljs.registerLanguage('javascript', javascript)
|
||||
export default defineComponent({
|
||||
components: {
|
||||
NConfigProvider,
|
||||
NDialogProvider,
|
||||
NMessageProvider,
|
||||
NNotificationProvider,
|
||||
NModalProvider,
|
||||
NSpin,
|
||||
NModal
|
||||
},
|
||||
setup() {
|
||||
let softwareStore = useSoftwareStore()
|
||||
|
||||
onMounted(async () => {
|
||||
softwareStore.SoftColor = SoftColor
|
||||
window.api.getSettingDafultData(async (value) => {
|
||||
await window.darkMode.toggle(value.theme)
|
||||
softwareStore.globalSetting = value
|
||||
})
|
||||
let software = await window.setting.GetSoftwareSetting()
|
||||
if (software.code == 0) {
|
||||
throw new Error('初始化信息错误: ' + software.message)
|
||||
}
|
||||
if (software.data == null) {
|
||||
throw new Error('初始化信息错误: 未获取到数据')
|
||||
}
|
||||
if (software.data.length == 0) {
|
||||
throw new Error('初始化信息错误: 未获取到数据')
|
||||
}
|
||||
softwareStore.softWare = software.data
|
||||
console.log(softwareStore.softWare)
|
||||
await window.darkMode.toggle(softwareStore.softWare.theme)
|
||||
})
|
||||
let softwareStore = useSoftwareStore()
|
||||
|
||||
return {
|
||||
javascript,
|
||||
hljs,
|
||||
darkTheme,
|
||||
softwareStore
|
||||
}
|
||||
onMounted(async () => {
|
||||
loading.value = true
|
||||
softwareStore.SoftColor = SoftColor
|
||||
window.api.getSettingDafultData(async (value) => {
|
||||
console.log(value.theme)
|
||||
await window.darkMode.toggle(value.theme)
|
||||
softwareStore.globalSetting = value
|
||||
})
|
||||
let software = await window.setting.GetSoftwareSetting()
|
||||
if (software.code == 0) {
|
||||
throw new Error('初始化信息错误: ' + software.message)
|
||||
}
|
||||
if (software.data == null) {
|
||||
throw new Error('初始化信息错误: 未获取到数据')
|
||||
}
|
||||
if (software.data.length == 0) {
|
||||
throw new Error('初始化信息错误: 未获取到数据')
|
||||
}
|
||||
softwareStore.softWare = software.data
|
||||
console.log(softwareStore.softWare)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 91 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 895 KiB |
@@ -90,6 +90,7 @@ import {
|
||||
import { useRouter } from 'vue-router'
|
||||
import { DEFINE_STRING } from '../../../../../define/define_string'
|
||||
import { isEmpty } from 'lodash'
|
||||
import { TimeDelay } from '@/define/Tools/time'
|
||||
let softwareStore = useSoftwareStore()
|
||||
let reverseManageStore = useReverseManageStore()
|
||||
let dialog = useDialog()
|
||||
@@ -357,6 +358,94 @@ async function ButtonSelect(key) {
|
||||
}
|
||||
}
|
||||
|
||||
// 重置所有的数据
|
||||
async function resetALLData() {
|
||||
let da = dialog.warning({
|
||||
title: '重置所有数据提示',
|
||||
content: `即将开始重置所有的数据,包括GPT提示词、合并提示词、生成图片等,当前的操作不可逆,是否继续?`,
|
||||
positiveText: '继续',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
try {
|
||||
da?.destroy()
|
||||
softwareStore.spin.spinning = true
|
||||
softwareStore.spin.tip = '正在重置GPT提示词数据,请稍后。。。'
|
||||
|
||||
let res = await window.book.ResetGptReverseData(
|
||||
reverseManageStore.selectBookTask.id,
|
||||
OperateBookType.BOOKTASK,
|
||||
BookType.ORIGINAL
|
||||
)
|
||||
softwareStore.spin.spinning = false
|
||||
if (res.code == 1) {
|
||||
// 删掉所有的数据
|
||||
for (let i = 0; i < reverseManageStore.selectBookTaskDetail.length; i++) {
|
||||
reverseManageStore.selectBookTaskDetail[i].gptPrompt = ''
|
||||
}
|
||||
}
|
||||
|
||||
message.success('重置GPT提示词成功')
|
||||
await TimeDelay(500)
|
||||
|
||||
softwareStore.spin.tip = '正在重置合并提示词数据,请稍后。。。'
|
||||
|
||||
for (let i = 0; i < reverseManageStore.selectBookTaskDetail.length; i++) {
|
||||
const element = reverseManageStore.selectBookTaskDetail[i]
|
||||
let res = await window.db.UpdateBookTaskDetailData(element.id, {
|
||||
prompt: ''
|
||||
})
|
||||
if (res.code == 1) {
|
||||
let findIndex = reverseManageStore.selectBookTaskDetail.findIndex(
|
||||
(item) => item.id == element.id
|
||||
)
|
||||
if (findIndex != -1) {
|
||||
reverseManageStore.selectBookTaskDetail[findIndex].prompt = ''
|
||||
}
|
||||
} else {
|
||||
message.error(res.message)
|
||||
}
|
||||
}
|
||||
message.success('重置合并提示词成功')
|
||||
await TimeDelay(500)
|
||||
|
||||
softwareStore.spin.tip = '正在重置生成图片数据,请稍后。。。'
|
||||
|
||||
res = await window.book.ResetGenerateImage(
|
||||
reverseManageStore.selectBookTask.id,
|
||||
OperateBookType.BOOKTASK,
|
||||
false
|
||||
)
|
||||
softwareStore.spin.spinning = false
|
||||
if (res.code == 1) {
|
||||
for (let i = 0; i < res.data.length; i++) {
|
||||
const element = res.data[i]
|
||||
let findIndex = reverseManageStore.selectBookTaskDetail.findIndex(
|
||||
(item) => item.id == element.id
|
||||
)
|
||||
if (findIndex != -1) {
|
||||
reverseManageStore.selectBookTaskDetail[findIndex].mjMessage = undefined
|
||||
reverseManageStore.selectBookTaskDetail[findIndex].outImagePath = ''
|
||||
reverseManageStore.selectBookTaskDetail[findIndex].subImagePath = []
|
||||
}
|
||||
}
|
||||
} else {
|
||||
message.error(res.message)
|
||||
return
|
||||
}
|
||||
message.success('重置生成图片数据成功')
|
||||
await TimeDelay(500)
|
||||
softwareStore.spin.spinning = false
|
||||
message.success('重置所有数据成功')
|
||||
} catch (error) {
|
||||
softwareStore.spin.spinning = false
|
||||
message.error('重置所有数据失败,' + error.message)
|
||||
} finally {
|
||||
softwareStore.spin.spinning = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 获取所有的GPT提示词
|
||||
async function GetPromptAll() {
|
||||
let da = dialog.warning({
|
||||
|
||||
@@ -1,40 +1,38 @@
|
||||
<template>
|
||||
<n-spin :show="show">
|
||||
<n-space vertical>
|
||||
<n-layout has-sider style="height: 100vh; position: relative">
|
||||
<n-layout-sider
|
||||
bordered
|
||||
collapse-mode="width"
|
||||
:collapsed-width="64"
|
||||
:width="220"
|
||||
<n-space vertical>
|
||||
<n-layout has-sider style="height: 100vh; position: relative">
|
||||
<n-layout-sider
|
||||
bordered
|
||||
collapse-mode="width"
|
||||
:collapsed-width="64"
|
||||
:width="220"
|
||||
:collapsed="collapsed"
|
||||
show-trigger
|
||||
@collapse="collapsed = true"
|
||||
@expand="collapsed = false"
|
||||
style="position: relative"
|
||||
>
|
||||
<n-menu
|
||||
:collapsed="collapsed"
|
||||
show-trigger
|
||||
@collapse="collapsed = true"
|
||||
@expand="collapsed = false"
|
||||
style="position: relative"
|
||||
:collapsed-width="64"
|
||||
:collapsed-icon-size="22"
|
||||
:options="menuOptions"
|
||||
:render-icon="renderMenuIcon"
|
||||
:expand-icon="expandIcon"
|
||||
default-value="mainHome"
|
||||
>
|
||||
<n-menu
|
||||
:collapsed="collapsed"
|
||||
:collapsed-width="64"
|
||||
:collapsed-icon-size="22"
|
||||
:options="menuOptions"
|
||||
:render-icon="renderMenuIcon"
|
||||
:expand-icon="expandIcon"
|
||||
>
|
||||
</n-menu>
|
||||
</n-layout-sider>
|
||||
<n-layout-content content-style="padding: 5px 5px 5px 10px; height:100%">
|
||||
<!-- <Setting></Setting> -->
|
||||
<router-view></router-view>
|
||||
</n-layout-content>
|
||||
</n-layout>
|
||||
</n-space>
|
||||
<template #description> 正在加载软件授权信息。。。 </template>
|
||||
</n-spin>
|
||||
</n-menu>
|
||||
</n-layout-sider>
|
||||
<n-layout-content content-style="padding: 5px 5px 5px 10px; height:100%">
|
||||
<!-- <Setting></Setting> -->
|
||||
<router-view></router-view>
|
||||
</n-layout-content>
|
||||
</n-layout>
|
||||
</n-space>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, h, onMounted, defineComponent, toRaw, computed } from 'vue'
|
||||
import { ref, h, onMounted, toRaw, computed } from 'vue'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import {
|
||||
useDialog,
|
||||
@@ -45,12 +43,12 @@ import {
|
||||
NLayoutContent,
|
||||
NIcon,
|
||||
useNotification,
|
||||
useMessage,
|
||||
NSpin
|
||||
useMessage
|
||||
} from 'naive-ui'
|
||||
|
||||
import {
|
||||
CaretDownOutline,
|
||||
HomeOutline,
|
||||
PaperPlaneOutline,
|
||||
SettingsOutline,
|
||||
DuplicateOutline,
|
||||
@@ -58,7 +56,7 @@ import {
|
||||
RadioOutline,
|
||||
BookOutline
|
||||
} from '@vicons/ionicons5'
|
||||
import CheckMachineId from '../Components/CheckMachineId.vue'
|
||||
|
||||
import { DEFINE_STRING } from '../../../../define/define_string'
|
||||
import { MD5 } from 'crypto-js'
|
||||
import InputDialogContent from '../Original/Components/InputDialogContent.vue'
|
||||
@@ -66,16 +64,11 @@ import APIIcon from '../Icon/APIIcon.vue'
|
||||
import BackTaskIcon from '../Icon/BackTaskIcon.vue'
|
||||
import BackTask from '@/renderer/src/components/BackTask/BackTask.vue'
|
||||
import { useSystemStore } from '../../../../stores/system'
|
||||
import { TimeDelay } from '../../../../define/Tools/time'
|
||||
import { BookBackTaskStatus } from '../../../../define/enum/bookEnum'
|
||||
|
||||
let collapsed = ref(false)
|
||||
let dialog = useDialog()
|
||||
let machineRef = ref()
|
||||
let message = useMessage()
|
||||
let notification = useNotification()
|
||||
let show = ref(true)
|
||||
const systemStore = useSystemStore()
|
||||
|
||||
let key_down_ref = ref(null)
|
||||
let showMenu = ref(true)
|
||||
@@ -87,6 +80,7 @@ function renderMenuIcon(option) {
|
||||
if (option.key == 'sdoriginal') return h(NIcon, null, { default: () => h(PaperPlaneOutline) })
|
||||
if (option.key == 'setting') return h(NIcon, null, { default: () => h(SettingsOutline) })
|
||||
if (option.key == 'gptCopywriting') return h(NIcon, null, { default: () => h(BookOutline) })
|
||||
if (option.key == 'mainHome') return h(NIcon, null, { default: () => h(HomeOutline) })
|
||||
if (option.key == 'book_management') return h(NIcon, null, { default: () => h(GridOutline) })
|
||||
if (option.key == 'lai_api') return h(NIcon, null, { default: () => h(APIIcon) })
|
||||
if (option.key == 'backward_matrix') return h(NIcon, null, { default: () => h(DuplicateOutline) })
|
||||
@@ -103,128 +97,7 @@ function renderMenuIcon(option) {
|
||||
if (option.key == 'TTS_Services') return h(NIcon, null, { default: () => h(RadioOutline) })
|
||||
}
|
||||
|
||||
// 启动后台任务
|
||||
async function StartBackTask(isGiveUp) {
|
||||
let startRes = await window.task.StartBackTask(isGiveUp)
|
||||
if (startRes.code == 0) {
|
||||
message.error(startRes.message)
|
||||
} else {
|
||||
message.success(startRes.message)
|
||||
}
|
||||
}
|
||||
|
||||
/** 判断是不是还是后台任务,用户确认是不是丢弃 */
|
||||
async function CheckWaitTask() {
|
||||
await TimeDelay(1000)
|
||||
let getWaitTaskCountRes = await window.task.GetAllStatusTaskCount([
|
||||
BookBackTaskStatus.WAIT,
|
||||
BookBackTaskStatus.RECONNECT
|
||||
])
|
||||
// 报错,默认丢弃
|
||||
if (getWaitTaskCountRes.code == 0) {
|
||||
message.error(getWaitTaskCountRes.message)
|
||||
await StartBackTask(true)
|
||||
return
|
||||
}
|
||||
if (getWaitTaskCountRes.data && getWaitTaskCountRes.data > 0) {
|
||||
// 这边提示用户是否丢弃
|
||||
dialog.warning({
|
||||
title: '后台任务',
|
||||
content: `检测到后台未完成的任务,任务数量为 ${getWaitTaskCountRes.data},请选择操作!`,
|
||||
positiveText: '继续执行',
|
||||
negativeText: '丢弃所有',
|
||||
onPositiveClick: async () => {
|
||||
// 启动任务
|
||||
await StartBackTask(false)
|
||||
},
|
||||
onNegativeClick: async () => {
|
||||
// 丢弃任务
|
||||
await StartBackTask(true)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// 启动任务
|
||||
await StartBackTask(true)
|
||||
}
|
||||
}
|
||||
|
||||
/** 校验机器码的逻辑 */
|
||||
async function GetMachineStatus() {
|
||||
try {
|
||||
// 获取机械码
|
||||
const machineRes = await window.system.GetMachineId()
|
||||
if (machineRes.code == 0) {
|
||||
message.error(machineRes.message)
|
||||
return
|
||||
}
|
||||
systemStore.machineId = machineRes.data
|
||||
|
||||
const checkMachineSatatusRes = await window.system.CheckMachineStatus(machineRes.data)
|
||||
if (checkMachineSatatusRes.code == 1) {
|
||||
// 自动检测成功,不同在弹窗手动进入
|
||||
message.success('自动检测机器码成功')
|
||||
// 判断是不是又后台任务
|
||||
await CheckWaitTask()
|
||||
return
|
||||
} else {
|
||||
message.error('自动检测机器码失败,请手动确认')
|
||||
}
|
||||
|
||||
// 这边是调用手动检测机器码
|
||||
// 弹窗,获取机器码
|
||||
const da = dialog.create({
|
||||
showIcon: false,
|
||||
content: () => h(CheckMachineId, { ref: machineRef }),
|
||||
style: `width : 400px; height: 300px`,
|
||||
maskClosable: false,
|
||||
positiveText: '确定',
|
||||
onClose: () => {
|
||||
// 关闭程序
|
||||
window.api.QuitApp()
|
||||
return false
|
||||
},
|
||||
onEsc: () => {
|
||||
// 关闭程序
|
||||
window.api.QuitApp()
|
||||
return false
|
||||
},
|
||||
onPositiveClick: async () => {
|
||||
const checkMachineSatatusRes = await window.system.CheckMachineStatus(machineRes.data)
|
||||
if (checkMachineSatatusRes.code == 1) {
|
||||
// 自动检测成功,不同在弹窗手动进入
|
||||
message.success('机器码校验成功')
|
||||
da.destroy()
|
||||
// 判断是不是又后台任务
|
||||
await CheckWaitTask()
|
||||
} else {
|
||||
message.error(checkMachineSatatusRes.message)
|
||||
return false
|
||||
}
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
message.error('获取机器状态码失败,请联系管理员,错误信息如下:' + error.toString())
|
||||
} finally {
|
||||
show.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 加载版本和GPU信息 */
|
||||
async function GetViosionAndGpuMessage() {
|
||||
// 加载版本
|
||||
let res = await window.system.GetViosionAndGpuMessage()
|
||||
console.log(res)
|
||||
if (res.code == 1) {
|
||||
document.title = 'LAITool ' + res.data
|
||||
} else {
|
||||
message.success(res.message)
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// 加载版本
|
||||
await GetViosionAndGpuMessage()
|
||||
|
||||
// 添加监听事件,同时按下ctrl + alt + l 打开控制台
|
||||
window.addEventListener('keydown', (e) => {
|
||||
if (e.ctrlKey && e.altKey && e.key === 'l') {
|
||||
@@ -306,7 +179,6 @@ onMounted(async () => {
|
||||
|
||||
window.api.setEventListen([DEFINE_STRING.SHOW_MAIN_MESSAGE], (value) => {
|
||||
let mess = value.message
|
||||
let type = 'success'
|
||||
if (value.code == 0) {
|
||||
message.error(mess)
|
||||
} else if (value.code == 2) {
|
||||
@@ -318,9 +190,6 @@ onMounted(async () => {
|
||||
}
|
||||
})
|
||||
|
||||
// 加载机器码状态
|
||||
await GetMachineStatus()
|
||||
|
||||
window.api.getSettingDafultData(async (value) => {
|
||||
window.config = value
|
||||
if (!(window.config && window.config.showOriginal)) {
|
||||
@@ -335,6 +204,22 @@ function expandIcon(value) {
|
||||
|
||||
const menuOptions = computed(() => {
|
||||
let me = [
|
||||
{
|
||||
label: () =>
|
||||
h(
|
||||
RouterLink,
|
||||
{
|
||||
to: {
|
||||
name: 'mainHome'
|
||||
},
|
||||
class: 'router-link-a'
|
||||
},
|
||||
{
|
||||
default: () => '首页'
|
||||
}
|
||||
),
|
||||
key: 'mainHome'
|
||||
},
|
||||
{
|
||||
label: () =>
|
||||
h(
|
||||
|
||||
@@ -0,0 +1,842 @@
|
||||
<!-- LoadingComponent.vue -->
|
||||
<template>
|
||||
<div class="loading-container" :class="{ 'full-screen': fullScreen }">
|
||||
<div class="loading-content">
|
||||
<!-- 主要加载动画 -->
|
||||
<div class="loading-spinner">
|
||||
<div class="spinner-ring">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 加载文本 -->
|
||||
<div class="loading-text">
|
||||
<h3>{{ title }}</h3>
|
||||
<p>{{ currentStepText }}</p>
|
||||
</div>
|
||||
|
||||
<!-- 进度条 -->
|
||||
<div class="loading-progress">
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill" :style="{ width: progress + '%' }"></div>
|
||||
</div>
|
||||
<span class="progress-text">{{ progress }}%</span>
|
||||
</div>
|
||||
|
||||
<!-- 加载步骤 -->
|
||||
<div class="loading-steps">
|
||||
<div
|
||||
v-for="(step, index) in loadingSteps"
|
||||
:key="index"
|
||||
class="step-item"
|
||||
:class="{
|
||||
active: index === currentStep,
|
||||
completed: index < currentStep
|
||||
}"
|
||||
>
|
||||
<div class="step-icon">
|
||||
<n-icon v-if="index < currentStep" size="14">
|
||||
<checkmark-outline />
|
||||
</n-icon>
|
||||
<div v-else-if="index === currentStep" class="step-loading"></div>
|
||||
<span v-else class="step-number">{{ index + 1 }}</span>
|
||||
</div>
|
||||
<span class="step-text">{{ step.text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 背景装饰 -->
|
||||
<div class="loading-background">
|
||||
<div class="bg-circle bg-circle-1"></div>
|
||||
<div class="bg-circle bg-circle-2"></div>
|
||||
<div class="bg-circle bg-circle-3"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, nextTick, readonly } from 'vue'
|
||||
import { NIcon, useMessage, useDialog } from 'naive-ui'
|
||||
import { CheckmarkOutline } from '@vicons/ionicons5'
|
||||
import { useSystemStore } from '@/stores/system'
|
||||
import CheckMachineId from '@/renderer/src/components/Components/CheckMachineId.vue'
|
||||
import { TimeDelay } from '@/define/Tools/time'
|
||||
import { BookBackTaskStatus } from '@/define/enum/bookEnum'
|
||||
import { define } from '@/define/define'
|
||||
import { ValidateJson } from '@/define/Tools/validate'
|
||||
|
||||
const message = useMessage()
|
||||
const dialog = useDialog()
|
||||
const systemStore = useSystemStore()
|
||||
|
||||
const props = defineProps({
|
||||
// 是否全屏显示
|
||||
fullScreen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 加载标题
|
||||
title: {
|
||||
type: String,
|
||||
default: 'LAI Tool 启动中'
|
||||
},
|
||||
// 主题色
|
||||
themeColor: {
|
||||
type: String,
|
||||
default: '#18a058'
|
||||
},
|
||||
// 自动开始加载
|
||||
autoStart: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['loading-complete'])
|
||||
|
||||
// 内部状态
|
||||
const progress = ref(0)
|
||||
const currentStep = ref(0)
|
||||
const isCompleted = ref(false)
|
||||
const isLoading = ref(false) // 添加加载状态标记
|
||||
|
||||
// 加载步骤配置
|
||||
const loadingSteps = ref([
|
||||
{
|
||||
text: '初始化系统组件',
|
||||
duration: 1000,
|
||||
action: async () => {
|
||||
// 模拟初始化系统组件
|
||||
await new Promise((resolve) => setTimeout(resolve, 800))
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
text: '获取设备硬件信息',
|
||||
duration: 900,
|
||||
action: async () => {
|
||||
// 模拟获取硬件信息
|
||||
await GetViosionAndGpuMessage()
|
||||
await new Promise((resolve) => setTimeout(resolve, 700))
|
||||
}
|
||||
},
|
||||
{
|
||||
text: '加载软件信息',
|
||||
duration: 1200,
|
||||
action: async () => {
|
||||
// 模拟加载配置
|
||||
await GetRemoteSystemInformation()
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||
}
|
||||
},
|
||||
{
|
||||
text: '检查软件授权状态',
|
||||
duration: 800,
|
||||
action: async () => {
|
||||
await GetMachineStatus()
|
||||
// 模拟检查授权
|
||||
await new Promise((resolve) => setTimeout(resolve, 600))
|
||||
}
|
||||
},
|
||||
{
|
||||
text: '准备用户界面',
|
||||
duration: 600,
|
||||
action: async () => {
|
||||
// 模拟准备界面
|
||||
await new Promise((resolve) => setTimeout(resolve, 400))
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
// 获取远程的系统信息
|
||||
async function GetRemoteSystemInformation() {
|
||||
try {
|
||||
// 获取远程版本
|
||||
let remoteVersionRes = await window.axios.get(
|
||||
define.lms + `/lms/Options/GetOptionsByKey/0/2/LaitoolVersion`
|
||||
)
|
||||
console.log('remoteVersionRes', remoteVersionRes)
|
||||
if (remoteVersionRes.success == false) {
|
||||
throw new Error('获取远程版本信息失败: ' + remoteVersionRes.message)
|
||||
}
|
||||
if (remoteVersionRes.data && remoteVersionRes.data.code == 1) {
|
||||
systemStore.remoteVersion = remoteVersionRes.data.data.value
|
||||
} else {
|
||||
throw new Error('获取远程版本信息失败: ' + remoteVersionRes.data.message)
|
||||
}
|
||||
|
||||
// 获取更新信息
|
||||
let remoteUpdateJsonContentRes = await window.axios.get(
|
||||
define.lms + `/lms/Options/GetOptionsByKey/0/2/LaitoolUpdateJsonContent`
|
||||
)
|
||||
console.log('remoteUpdateJsonContentRes', remoteUpdateJsonContentRes)
|
||||
if (remoteUpdateJsonContentRes.success == false) {
|
||||
throw new Error('获取远程更新信息失败: ' + remoteUpdateJsonContentRes.message)
|
||||
}
|
||||
if (
|
||||
remoteUpdateJsonContentRes.data &&
|
||||
remoteUpdateJsonContentRes.data.code == 1 &&
|
||||
ValidateJson(remoteUpdateJsonContentRes.data.data.value)
|
||||
) {
|
||||
systemStore.versionInfo.updateInfo = JSON.parse(remoteUpdateJsonContentRes.data.data.value)
|
||||
} else {
|
||||
throw new Error('获取远程更新信息失败: ' + remoteUpdateJsonContentRes.data.message)
|
||||
}
|
||||
|
||||
systemStore.versionInfo.currentVersion = 'v' + systemStore.version
|
||||
systemStore.versionInfo.latestVersion = 'v' + systemStore.remoteVersion
|
||||
if (systemStore.version < systemStore.remoteVersion) {
|
||||
// 如果远程版本大于本地版本,更新本地版本
|
||||
systemStore.versionInfo.canUpdate = true
|
||||
} else {
|
||||
systemStore.versionInfo.canUpdate = false
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/** 加载版本和GPU信息 */
|
||||
async function GetViosionAndGpuMessage() {
|
||||
// 加载版本
|
||||
let res = await window.system.GetViosionAndGpuMessage()
|
||||
console.log(res)
|
||||
if (res.code == 1) {
|
||||
document.title = 'LAITool v' + res.data.version
|
||||
systemStore.version = res.data.version
|
||||
systemStore.gpu = res.data.gpu
|
||||
} else {
|
||||
message.success(res.message)
|
||||
}
|
||||
}
|
||||
|
||||
const machineRef = ref(null)
|
||||
|
||||
/** 校验机器码的逻辑 */
|
||||
async function GetMachineStatus() {
|
||||
try {
|
||||
// 获取机械码
|
||||
const machineRes = await window.system.GetMachineId()
|
||||
if (machineRes.code == 0) {
|
||||
message.error(machineRes.message)
|
||||
return
|
||||
}
|
||||
systemStore.machineId = machineRes.data
|
||||
|
||||
const checkMachineSatatusRes = await window.system.CheckMachineStatus(machineRes.data)
|
||||
if (checkMachineSatatusRes.code == 1) {
|
||||
// 自动检测成功,不同在弹窗手动进入
|
||||
message.success('自动检测机器码成功')
|
||||
// 判断是不是又后台任务
|
||||
await CheckWaitTask()
|
||||
return
|
||||
} else {
|
||||
message.error('自动检测机器码失败,请手动确认')
|
||||
}
|
||||
|
||||
// 这边是调用手动检测机器码
|
||||
// 弹窗,获取机器码
|
||||
const da = dialog.create({
|
||||
showIcon: false,
|
||||
content: () => h(CheckMachineId, { ref: machineRef }),
|
||||
style: `width : 400px; height: 300px`,
|
||||
maskClosable: false,
|
||||
positiveText: '确定',
|
||||
onClose: () => {
|
||||
// 关闭程序
|
||||
window.api.QuitApp()
|
||||
return false
|
||||
},
|
||||
onEsc: () => {
|
||||
// 关闭程序
|
||||
window.api.QuitApp()
|
||||
return false
|
||||
},
|
||||
onPositiveClick: async () => {
|
||||
const checkMachineSatatusRes = await window.system.CheckMachineStatus(machineRes.data)
|
||||
if (checkMachineSatatusRes.code == 1) {
|
||||
// 自动检测成功,不同在弹窗手动进入
|
||||
message.success('机器码校验成功')
|
||||
da.destroy()
|
||||
// 继续执行后续步骤
|
||||
jumpToStep(4)
|
||||
await nextTick() // 等待DOM更新
|
||||
continue_() // 从第3步开始继续执行
|
||||
// 判断是不是又后台任务
|
||||
await CheckWaitTask()
|
||||
} else {
|
||||
message.error(checkMachineSatatusRes.message)
|
||||
return false
|
||||
}
|
||||
}
|
||||
})
|
||||
throw new Error('手动验证机器码')
|
||||
} catch (error) {
|
||||
message.error('获取机器状态码失败,请联系管理员,错误信息如下:' + error.toString())
|
||||
throw error
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
|
||||
/** 判断是不是还是后台任务,用户确认是不是丢弃 */
|
||||
async function CheckWaitTask() {
|
||||
await TimeDelay(1000)
|
||||
let getWaitTaskCountRes = await window.task.GetAllStatusTaskCount([
|
||||
BookBackTaskStatus.WAIT,
|
||||
BookBackTaskStatus.RECONNECT
|
||||
])
|
||||
// 报错,默认丢弃
|
||||
if (getWaitTaskCountRes.code == 0) {
|
||||
message.error(getWaitTaskCountRes.message)
|
||||
await StartBackTask(true)
|
||||
return
|
||||
}
|
||||
if (getWaitTaskCountRes.data && getWaitTaskCountRes.data > 0) {
|
||||
// 这边提示用户是否丢弃
|
||||
dialog.warning({
|
||||
title: '后台任务',
|
||||
content: `检测到后台未完成的任务,任务数量为 ${getWaitTaskCountRes.data},请选择操作!`,
|
||||
positiveText: '继续执行',
|
||||
negativeText: '丢弃所有',
|
||||
onPositiveClick: async () => {
|
||||
// 启动任务
|
||||
await StartBackTask(false)
|
||||
},
|
||||
onNegativeClick: async () => {
|
||||
// 丢弃任务
|
||||
await StartBackTask(true)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// 启动任务
|
||||
await StartBackTask(true)
|
||||
}
|
||||
}
|
||||
|
||||
// 启动后台任务
|
||||
async function StartBackTask(isGiveUp) {
|
||||
let startRes = await window.task.StartBackTask(isGiveUp)
|
||||
if (startRes.code == 0) {
|
||||
message.error(startRes.message)
|
||||
} else {
|
||||
message.success(startRes.message)
|
||||
}
|
||||
}
|
||||
|
||||
// 当前步骤描述文本
|
||||
const currentStepText = computed(() => {
|
||||
if (isCompleted.value) {
|
||||
return '加载完成,即将进入应用'
|
||||
}
|
||||
if (currentStep.value < loadingSteps.value.length) {
|
||||
return loadingSteps.value[currentStep.value].text
|
||||
}
|
||||
return '正在准备...'
|
||||
})
|
||||
|
||||
// 启动加载流程(从头开始)
|
||||
const startLoading = async () => {
|
||||
if (isLoading.value) return // 防止重复执行
|
||||
|
||||
isLoading.value = true
|
||||
currentStep.value = 0
|
||||
progress.value = 0
|
||||
isCompleted.value = false
|
||||
|
||||
await executeStepsFrom(0)
|
||||
}
|
||||
|
||||
// 继续加载流程(从当前步骤继续)
|
||||
const continueLoading = async () => {
|
||||
if (isLoading.value) return // 防止重复执行
|
||||
if (isCompleted.value) return // 已完成则不继续
|
||||
|
||||
isLoading.value = true
|
||||
await executeStepsFrom(currentStep.value)
|
||||
}
|
||||
|
||||
// 从指定步骤开始执行
|
||||
const executeStepsFrom = async (startStep) => {
|
||||
const totalSteps = loadingSteps.value.length
|
||||
|
||||
for (let i = startStep; i < totalSteps; i++) {
|
||||
currentStep.value = i
|
||||
const step = loadingSteps.value[i]
|
||||
|
||||
try {
|
||||
// 执行当前步骤的操作
|
||||
const startTime = Date.now()
|
||||
|
||||
// 同时进行进度条动画和实际操作
|
||||
await Promise.all([
|
||||
// 进度条动画
|
||||
animateProgress(i, totalSteps),
|
||||
// 执行步骤操作
|
||||
step.action()
|
||||
])
|
||||
|
||||
// 确保最少执行时间
|
||||
const elapsed = Date.now() - startTime
|
||||
const minDuration = step.duration || 800
|
||||
if (elapsed < minDuration) {
|
||||
await new Promise((resolve) => setTimeout(resolve, minDuration - elapsed))
|
||||
}
|
||||
} catch (error) {
|
||||
// 如果步骤执行失败,停止加载但保持当前状态
|
||||
console.error(`步骤 ${i + 1} 执行失败:`, error)
|
||||
isLoading.value = false
|
||||
return // 停止执行后续步骤
|
||||
}
|
||||
}
|
||||
|
||||
// 完成所有步骤
|
||||
currentStep.value = totalSteps
|
||||
progress.value = 100
|
||||
isCompleted.value = true
|
||||
isLoading.value = false
|
||||
|
||||
// 稍微延迟后触发完成事件
|
||||
setTimeout(() => {
|
||||
emit('loading-complete')
|
||||
}, 500)
|
||||
}
|
||||
|
||||
// 进度条动画
|
||||
const animateProgress = async (stepIndex, totalSteps) => {
|
||||
const startProgress = Math.floor((stepIndex / totalSteps) * 100)
|
||||
const endProgress = Math.floor(((stepIndex + 1) / totalSteps) * 100)
|
||||
|
||||
const duration = 300 // 动画持续时间
|
||||
const steps = 20 // 动画步数
|
||||
const stepDuration = duration / steps
|
||||
const progressStep = (endProgress - startProgress) / steps
|
||||
|
||||
for (let i = 0; i <= steps; i++) {
|
||||
progress.value = Math.min(startProgress + Math.floor(progressStep * i), endProgress)
|
||||
await new Promise((resolve) => setTimeout(resolve, stepDuration))
|
||||
}
|
||||
}
|
||||
|
||||
// 手动启动加载(从头开始)
|
||||
const start = () => {
|
||||
startLoading()
|
||||
}
|
||||
|
||||
// 继续执行剩余步骤
|
||||
const continue_ = () => {
|
||||
continueLoading()
|
||||
}
|
||||
|
||||
// 跳过当前步骤并继续
|
||||
const skipCurrentStep = () => {
|
||||
if (isLoading.value || isCompleted.value) return
|
||||
|
||||
// 标记当前步骤为完成状态
|
||||
currentStep.value += 1
|
||||
|
||||
// 继续执行后续步骤
|
||||
continueLoading()
|
||||
}
|
||||
|
||||
// 跳到指定步骤
|
||||
const jumpToStep = (stepIndex) => {
|
||||
if (isLoading.value || isCompleted.value) return
|
||||
if (stepIndex < 0 || stepIndex >= loadingSteps.value.length) return
|
||||
|
||||
currentStep.value = stepIndex
|
||||
// 更新进度条
|
||||
const totalSteps = loadingSteps.value.length
|
||||
progress.value = Math.floor((stepIndex / totalSteps) * 100)
|
||||
}
|
||||
|
||||
// 重置加载状态
|
||||
const reset = () => {
|
||||
isLoading.value = false
|
||||
progress.value = 0
|
||||
currentStep.value = 0
|
||||
isCompleted.value = false
|
||||
}
|
||||
|
||||
// 暂停加载(保持当前状态)
|
||||
const pause = () => {
|
||||
isLoading.value = false
|
||||
}
|
||||
|
||||
// 恢复加载(从当前步骤继续)
|
||||
const resume = () => {
|
||||
if (!isCompleted.value) {
|
||||
continueLoading()
|
||||
}
|
||||
}
|
||||
|
||||
// 暴露方法给父组件
|
||||
defineExpose({
|
||||
start, // 从头开始
|
||||
continue: continue_, // 继续执行
|
||||
skipCurrentStep, // 跳过当前步骤
|
||||
jumpToStep, // 跳到指定步骤
|
||||
reset, // 重置状态
|
||||
pause, // 暂停
|
||||
resume, // 恢复
|
||||
// 状态属性
|
||||
isLoading: readonly(isLoading),
|
||||
isCompleted: readonly(isCompleted),
|
||||
currentStep: readonly(currentStep),
|
||||
progress: readonly(progress)
|
||||
})
|
||||
|
||||
// 自动启动
|
||||
onMounted(() => {
|
||||
if (props.autoStart) {
|
||||
nextTick(() => {
|
||||
startLoading()
|
||||
})
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.loading-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 200px;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.loading-container.full-screen {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
min-height: 100vh;
|
||||
max-height: 100vh;
|
||||
border-radius: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.loading-content {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
max-width: 400px;
|
||||
padding: 20px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 确保全屏时内容居中 */
|
||||
.loading-container.full-screen .loading-content {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: auto;
|
||||
max-width: 500px;
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
/* 加载动画 */
|
||||
.loading-spinner {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.spinner-ring {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.spinner-ring div {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 51px;
|
||||
height: 51px;
|
||||
margin: 6px;
|
||||
border: 6px solid v-bind(themeColor);
|
||||
border-radius: 50%;
|
||||
animation: spinner-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||
border-color: v-bind(themeColor) transparent transparent transparent;
|
||||
}
|
||||
|
||||
.spinner-ring div:nth-child(1) {
|
||||
animation-delay: -0.45s;
|
||||
}
|
||||
.spinner-ring div:nth-child(2) {
|
||||
animation-delay: -0.3s;
|
||||
}
|
||||
.spinner-ring div:nth-child(3) {
|
||||
animation-delay: -0.15s;
|
||||
}
|
||||
|
||||
@keyframes spinner-ring {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* 加载文本 */
|
||||
.loading-text h3 {
|
||||
margin: 0 0 8px 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.loading-text p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
/* 进度条 */
|
||||
.loading-progress {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
background: #f0f0f0;
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, v-bind(themeColor), #40a9ff);
|
||||
border-radius: 3px;
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 加载步骤 */
|
||||
.loading-steps {
|
||||
text-align: left;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.step-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 8px 0;
|
||||
opacity: 0.5;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.step-item.active {
|
||||
opacity: 1;
|
||||
color: v-bind(themeColor);
|
||||
}
|
||||
|
||||
.step-item.completed {
|
||||
opacity: 0.8;
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.step-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #f0f0f0;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.step-item.active .step-icon {
|
||||
background: v-bind(themeColor);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.step-item.completed .step-icon {
|
||||
background: #52c41a;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.step-loading {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border: 2px solid white;
|
||||
border-top: 2px solid transparent;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
}
|
||||
|
||||
.step-item.active .step-number {
|
||||
}
|
||||
|
||||
.step-text {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
flex: 1;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* 背景装饰 */
|
||||
.loading-background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bg-circle {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(45deg, rgba(24, 160, 88, 0.1), rgba(64, 169, 255, 0.1));
|
||||
animation: float 6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.bg-circle-1 {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
top: 10%;
|
||||
left: 10%;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.bg-circle-2 {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
top: 60%;
|
||||
right: 10%;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
|
||||
.bg-circle-3 {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
bottom: 20%;
|
||||
left: 60%;
|
||||
animation-delay: 4s;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateY(0px) rotate(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-20px) rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* 深色模式 */
|
||||
.dark .loading-container {
|
||||
background: rgba(26, 26, 26, 0.95);
|
||||
}
|
||||
|
||||
.dark .loading-container.full-screen {
|
||||
background: rgba(26, 26, 26, 0.98);
|
||||
}
|
||||
|
||||
.dark .loading-text h3 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dark .loading-text p {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.dark .progress-bar {
|
||||
background: #3d3d3d;
|
||||
}
|
||||
|
||||
.dark .progress-text {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.dark .step-icon {
|
||||
background: #3d3d3d;
|
||||
}
|
||||
|
||||
.dark .step-number {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.dark .step-text {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dark .step-item {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
/* 响应式适配 */
|
||||
@media (max-width: 768px) {
|
||||
.loading-container.full-screen .loading-content {
|
||||
min-width: 300px;
|
||||
max-width: 90vw;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.loading-text h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.step-text {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 确保覆盖所有可能的父级样式 */
|
||||
.loading-container.full-screen {
|
||||
position: fixed !important;
|
||||
inset: 0 !important;
|
||||
width: 100vw !important;
|
||||
height: 100vh !important;
|
||||
min-width: 100vw !important;
|
||||
min-height: 100vh !important;
|
||||
max-width: 100vw !important;
|
||||
max-height: 100vh !important;
|
||||
left: 0 !important;
|
||||
top: 0 !important;
|
||||
right: 0 !important;
|
||||
bottom: 0 !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,238 @@
|
||||
<template>
|
||||
<div class="contact-developer">
|
||||
<!-- 头部说明 -->
|
||||
<div class="header-section">
|
||||
<div class="title">👨💻 开发者微信</div>
|
||||
<div class="description">扫描下方二维码添加开发者微信,获取专业技术支持</div>
|
||||
</div>
|
||||
|
||||
<!-- 二维码图片容器 -->
|
||||
<div class="qrcode-container">
|
||||
<img
|
||||
src="../../assets//dev-user.jpg"
|
||||
alt="开发者微信二维码"
|
||||
class="qrcode-image"
|
||||
@error="handleImageError"
|
||||
/>
|
||||
<div v-if="showPlaceholder" class="qrcode-placeholder">
|
||||
<div class="placeholder-icon">📱</div>
|
||||
<div class="placeholder-text">二维码图片</div>
|
||||
<div class="placeholder-subtext">请联系管理员获取</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 联系说明 -->
|
||||
<div class="contact-info">
|
||||
<div class="contact-title">
|
||||
<span class="contact-icon">💡</span>
|
||||
联系须知
|
||||
</div>
|
||||
<ul class="contact-list">
|
||||
<li>添加时请备注:LAITool用户</li>
|
||||
<li>工作时间:周一至周五 9:00-18:00</li>
|
||||
<li>支持技术咨询、BUG反馈、功能建议</li>
|
||||
<li>请详细描述您遇到的问题,以便快速解决</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- 底部提示 -->
|
||||
<div class="footer-info">
|
||||
<div>如无法扫码,可复制微信号:</div>
|
||||
<div class="wechat-id" @click="copyWechatId">{{ wechatId }}</div>
|
||||
<div>或发送邮件至:{{ email }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useMessage } from 'naive-ui'
|
||||
|
||||
const props = defineProps({
|
||||
wechatId: {
|
||||
type: String,
|
||||
default: 'xiangbie88'
|
||||
},
|
||||
email: {
|
||||
type: String,
|
||||
default: '2769838458@qq.com'
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['copy-success', 'copy-error'])
|
||||
|
||||
const message = useMessage()
|
||||
const showPlaceholder = ref(false)
|
||||
|
||||
const handleImageError = () => {
|
||||
showPlaceholder.value = true
|
||||
}
|
||||
|
||||
const copyWechatId = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(props.wechatId)
|
||||
message.success('微信号已复制到剪贴板')
|
||||
emit('copy-success', props.wechatId)
|
||||
} catch (error) {
|
||||
message.error(`复制失败,请手动复制:${props.wechatId}`)
|
||||
emit('copy-error', error)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.contact-developer {
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.header-section {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.qrcode-container {
|
||||
margin: 24px 0;
|
||||
padding: 20px;
|
||||
background: linear-gradient(135deg, #f0f9ff 0%, #e6f7ff 100%);
|
||||
border-radius: 12px;
|
||||
border: 2px dashed #1890ff;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.qrcode-image {
|
||||
width: 200px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.qrcode-placeholder {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: #f5f5f5;
|
||||
border: 2px dashed #d9d9d9;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #999;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.placeholder-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.placeholder-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.placeholder-subtext {
|
||||
font-size: 12px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.contact-info {
|
||||
margin-top: 24px;
|
||||
padding: 16px;
|
||||
background: #fff7e6;
|
||||
border-radius: 8px;
|
||||
border-left: 4px solid #fa8c16;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.contact-title {
|
||||
font-weight: 600;
|
||||
color: #fa8c16;
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.contact-icon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.contact-list {
|
||||
margin: 0;
|
||||
padding-left: 20px;
|
||||
color: #666;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.contact-list li {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.footer-info {
|
||||
margin-top: 16px;
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.wechat-id {
|
||||
font-weight: 600;
|
||||
color: #1890ff;
|
||||
margin-top: 4px;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
user-select: all;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
/* 深色模式适配 */
|
||||
.dark .title,
|
||||
.dark .contact-title {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dark .description {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.dark .qrcode-container {
|
||||
background: linear-gradient(135deg, #1a2332 0%, #2a3441 100%);
|
||||
border-color: #3a4a5c;
|
||||
}
|
||||
|
||||
.dark .qrcode-placeholder {
|
||||
background: #2d2d2d;
|
||||
border-color: #4a4a4a;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.dark .contact-info {
|
||||
background: #2a2418;
|
||||
border-color: #5a4a2c;
|
||||
}
|
||||
|
||||
.dark .contact-list {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.dark .footer-info {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.dark .wechat-id:hover {
|
||||
background-color: #1a2332;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,164 @@
|
||||
<template>
|
||||
<div class="wechat-group">
|
||||
<!-- 群信息卡片 -->
|
||||
<div class="group-info">
|
||||
<div class="group-title">🎯 加入VIP用户交流群</div>
|
||||
<div class="group-description">{{ groupInfo }}</div>
|
||||
</div>
|
||||
|
||||
<!-- 群内福利 -->
|
||||
<div class="benefits-section">
|
||||
<div class="benefits-title">💡 群内福利:</div>
|
||||
<ul class="benefits-list">
|
||||
<li class="benefit-item">
|
||||
<span class="benefit-icon">📢</span>
|
||||
获取最新版本信息和更新通知
|
||||
</li>
|
||||
<li class="benefit-item">
|
||||
<span class="benefit-icon">💬</span>
|
||||
与其他用户交流使用技巧和经验
|
||||
</li>
|
||||
<li class="benefit-item">
|
||||
<span class="benefit-icon">🐛</span>
|
||||
快速反馈问题和建议
|
||||
</li>
|
||||
<li class="benefit-item">
|
||||
<span class="benefit-icon">🛠️</span>
|
||||
获得开发团队的技术支持
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- 联系方式 -->
|
||||
<div class="contact-info">联系管理员邀请入群或者联系对应代理</div>
|
||||
|
||||
<!-- 群规提醒 -->
|
||||
<div class="rules-notice">注:请勿在群内发布广告或无关内容,保持良好交流氛围</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
groupInfo: {
|
||||
type: String,
|
||||
default: '仅限永久VIP用户可加入'
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.wechat-group {
|
||||
line-height: 1.6;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.group-info {
|
||||
margin-bottom: 16px;
|
||||
padding: 12px;
|
||||
background: #f0f9ff;
|
||||
border-radius: 8px;
|
||||
border-left: 4px solid #1890ff;
|
||||
}
|
||||
|
||||
.group-title {
|
||||
font-weight: 600;
|
||||
color: #1890ff;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.group-description {
|
||||
font-size: 13px;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.benefits-section {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.benefits-title {
|
||||
margin-bottom: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.benefits-list {
|
||||
margin: 0;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.benefit-item {
|
||||
margin-bottom: 8px;
|
||||
padding: 4px 0;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.benefit-icon {
|
||||
font-weight: 600;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.benefit-item:nth-child(1) .benefit-icon {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.benefit-item:nth-child(2) .benefit-icon {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.benefit-item:nth-child(3) .benefit-icon {
|
||||
color: #f0a020;
|
||||
}
|
||||
|
||||
.benefit-item:nth-child(4) .benefit-icon {
|
||||
color: #d03050;
|
||||
}
|
||||
|
||||
.contact-info {
|
||||
margin-top: 16px;
|
||||
padding: 8px;
|
||||
background: #fff7e6;
|
||||
border-radius: 6px;
|
||||
text-align: center;
|
||||
color: #fa8c16;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.rules-notice {
|
||||
margin-top: 8px;
|
||||
padding: 8px;
|
||||
background: #fff7e6;
|
||||
border-radius: 6px;
|
||||
text-align: center;
|
||||
color: #fa8c16;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* 深色模式适配 */
|
||||
.dark .group-info {
|
||||
background: #1a2332;
|
||||
border-color: #3a4a5c;
|
||||
}
|
||||
|
||||
.dark .group-title {
|
||||
color: #40a9ff;
|
||||
}
|
||||
|
||||
.dark .group-description {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.dark .benefits-title {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dark .benefits-list {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.dark .contact-info,
|
||||
.dark .rules-notice {
|
||||
background: #2a2418;
|
||||
color: #ffa940;
|
||||
}
|
||||
</style>
|
||||
@@ -13,6 +13,11 @@ const routes = [
|
||||
path: '/',
|
||||
component: () => import('./components/Home/Home.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '/mainHome',
|
||||
name: 'mainHome',
|
||||
component: () => import('./components/Home/SoftwareHome.vue')
|
||||
},
|
||||
{
|
||||
path: '/gptCopywriting',
|
||||
name: 'gptCopywriting',
|
||||
|
||||
+30
-1
@@ -6,7 +6,36 @@ export type SystemStoreModel = {
|
||||
|
||||
export const useSystemStore = defineStore('system', {
|
||||
state: () => ({
|
||||
machineId: undefined
|
||||
machineId: undefined,
|
||||
version: '1.1.1',
|
||||
remoteVersion: '1.1.1',
|
||||
versionInfo: {
|
||||
currentVersion: 'v1.0.0',
|
||||
latestVersion: 'v1.0.0',
|
||||
updateInfo: {
|
||||
latestVersion: 'v1.0.0',
|
||||
updateDate: '2023-10-01',
|
||||
updateInfo: [
|
||||
{
|
||||
version: 'v1.0.0',
|
||||
updateDate: '2023-09-01',
|
||||
changes: [
|
||||
{
|
||||
type: 'improvement',
|
||||
description: '改进了性能'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
canUpdate: false
|
||||
} as SystemConfig.VersionInfo,
|
||||
gpu: {
|
||||
name: void 0,
|
||||
type: void 0,
|
||||
vender: void 0,
|
||||
updateTime: void 0
|
||||
} as SystemConfig.GpuMessage
|
||||
} as SystemStoreModel),
|
||||
getters: {
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user