😎1、增加清理相关js脚本 2、调整翻译模式及增加Deepseek翻译

This commit is contained in:
zuohuaijun 2025-08-12 14:15:56 +08:00
parent 6e9780c507
commit b9265c4fd9
10 changed files with 5829 additions and 5536 deletions

View File

@ -12,3 +12,6 @@ VITE_PUBLIC_PATH =
# 国密SM公钥保持空即可自动从后台获取
VITE_SM_PUBLIC_KEY =
# 翻译 DeepSeek API key https://platform.deepseek.com/api_keys
DEEPSEEK_API_KEY = "你的 DeepSeek API key"

View File

@ -3,7 +3,7 @@ CHCP 65001
set dir=%~dp0
set moduleName=apiServices
set moduleName=system
set apiServicesPath=%dir%..\src\api-services\system\
set apiUrl=http://localhost:5005/swagger/Default/swagger.json

View File

@ -12,7 +12,7 @@
## 脚本一键生成
Swagger Codegen 读取 swagger.json 生成 typescript-axios 客户端后,直接拷贝到 src/api-services/system 子文件夹中
Swagger Codegen 读取 swagger.json 生成 typescript-axios 客户端后,直接拷贝到 src/api-services/system 子文件夹中(建议每个应用层创建一个独立的文件夹单独放置,和框架接口分开)
> Swagger Codegen 可以通过为任何 API 生成服务端代码和客户端代码的方式来简化 OpenAPI 的构建过程,因此,项目开发团队可以更好地关注 API 的实现和应用
> Githubhttps://github.com/swagger-api/swagger-codegen

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,8 @@
"build-api": "cd api_build/ && build.bat",
"build-approvalFlow-api": "cd api_build/ && build.bat approvalFlow",
"build-dingTalk-api": "cd api_build/ && build.bat dingTalk",
"build-goView-api": "cd api_build/ && build.bat goView"
"build-goView-api": "cd api_build/ && build.bat goView",
"translate": "node script/translate.cjs"
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.2",
@ -95,7 +96,10 @@
"@vitejs/plugin-vue": "^6.0.1",
"@vitejs/plugin-vue-jsx": "^5.0.1",
"@vue/compiler-sfc": "^3.5.18",
"cli-progress": "^3.12.0",
"code-inspector-plugin": "^1.0.5",
"colors": "^1.4.0",
"dotenv": "^17.2.1",
"eslint": "^9.33.0",
"eslint-plugin-vue": "^10.4.0",
"globals": "^16.3.0",

16
Web/script/clean-dist.js Normal file
View File

@ -0,0 +1,16 @@
// 清理dist文件夹
import fs from 'fs';
import path from 'path';
const directoriesToDelete = ['dist'];
// 删除文件夹
directoriesToDelete.forEach((dir) => {
const dirPath = path.join(process.cwd(), dir);
if (fs.existsSync(dirPath)) {
fs.rmSync(dirPath, { recursive: true, force: true });
console.log(`Deleted directory: ${dirPath}`);
} else {
console.log(`Directory not found: ${dirPath}`);
}
});

16
Web/script/clean-lock.js Normal file
View File

@ -0,0 +1,16 @@
// 清理lock文件
import fs from 'fs';
import path from 'path';
const filesToDelete = ['pnpm-lock.yaml', 'package-lock.json'];
// 删除文件
filesToDelete.forEach((file) => {
const filePath = path.join(process.cwd(), file);
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
console.log(`Deleted file: ${filePath}`);
} else {
console.log(`File not found: ${filePath}`);
}
});

View File

@ -0,0 +1,16 @@
// 清理modules文件夹
import fs from 'fs';
import path from 'path';
const directoriesToDelete = ['node_modules'];
// 删除文件夹
directoriesToDelete.forEach((dir) => {
const dirPath = path.join(process.cwd(), dir);
if (fs.existsSync(dirPath)) {
fs.rmSync(dirPath, { recursive: true, force: true });
console.log(`Deleted directory: ${dirPath}`);
} else {
console.log(`Directory not found: ${dirPath}`);
}
});

238
Web/script/translate.cjs Normal file
View File

@ -0,0 +1,238 @@
// DeepSeek 翻译
require('dotenv').config();
const fs = require('fs');
const path = require('path');
const API_URL = 'https://api.deepseek.com/v1/chat/completions';
const API_KEY = process.env.DEEPSEEK_API_KEY;
const SOURCE_LANG = 'zh-cn';
const LOCALE_FILE = path.resolve(__dirname, '../lang/index.json');
// 引入进度条库
const cliProgress = require('cli-progress');
const colors = require('colors');
async function translateBatch(texts, targetLang) {
// 构建批量内容:每行以[index]开头
const batchContent = texts.map((text, index) => `[${index}] ${text}`).join('\n');
const response = await fetch(API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${API_KEY}`,
},
body: JSON.stringify({
model: 'deepseek-chat',
messages: [
{
role: 'system',
content: `作为企业软件系统专业翻译,严格遵守以下铁律:
核心原则
1. 严格逐符号翻译${SOURCE_LANG}${targetLang}
2. 禁止添加/删除/改写任何内容
3. 保持批量翻译的编号格式
符号保留规则
! 所有符号必须原样保留
编程符号\${ } <% %> @ # & |
UI占位符{0} %s [ ]
货币单位¥100.00 kg cm²
中文符号
中文符号位置规范
# 三级处理机制
1. 成对符号必须保持完整结构
正确WarningText
禁止Warning Text
2. 独立符号位置
优先句尾 Text?
次选句首 Text?
禁止句中 TextText?
3. 跨字符串符号处理
前段含 保留在段尾"Synchronize【"
后段含 保留在段首"】authorization data?"
符号后接字母时添加空格 Authorization
语法规范
外文 被动语态"Item was created"
中文 主动语态"已创建项目"
禁止推测上下文只翻译当前字符串内容
错误预防绝对禁止
将中文符号改为西式符号]
移动非中文符号位置
添加原文不存在的内容
合并/拆分原始字符串
批量处理
严格保持原始JSON结构
语言键名精确匹配zh-cn/en/it等`,
},
{
role: 'user',
content: batchContent,
},
],
temperature: 0.3,
max_tokens: 4000,
}),
});
const data = await response.json();
if (!response.ok || !data.choices || !data.choices[0]?.message?.content) {
const errorMsg = data.error?.message || `HTTP ${response.status}: ${response.statusText}`;
throw new Error(`翻译API返回错误${errorMsg}`);
}
// 解析批量响应
const batchResult = data.choices[0].message.content.trim();
const translations = {};
// 按行分割结果
const lines = batchResult.split('\n');
for (const line of lines) {
// 使用更精确的匹配模式
const match = line.match(/^\[(\d+)\]\s*(.+)/);
if (match) {
const index = parseInt(match[1]);
translations[index] = match[2].trim();
}
}
return translations;
}
function extractTargetLangs(localeData) {
const allLangs = new Set();
for (const translations of Object.values(localeData)) {
for (const lang of Object.keys(translations)) {
if (lang !== SOURCE_LANG) {
allLangs.add(lang);
}
}
}
return [...allLangs];
}
function groupTasksByLang(localeData, targetLangs) {
const tasks = {};
for (const lang of targetLangs) {
tasks[lang] = {
keys: [],
texts: [],
};
}
for (const [key, translations] of Object.entries(localeData)) {
const sourceText = translations[SOURCE_LANG];
if (!sourceText) {
console.warn(`⚠️ 缺少源语言(${SOURCE_LANG})文本: ${key}`);
continue;
}
for (const lang of targetLangs) {
if (!translations[lang] || translations[lang].trim() === '') {
tasks[lang].keys.push(key);
tasks[lang].texts.push(sourceText);
}
}
}
return tasks;
}
async function main() {
// 读取语言文件
const rawData = fs.readFileSync(LOCALE_FILE);
const localeData = JSON.parse(rawData);
const TARGET_LANGS = extractTargetLangs(localeData);
const langTasks = groupTasksByLang(localeData, TARGET_LANGS);
let totalUpdated = 0;
const BATCH_SIZE = 10;
// 创建多进度条容器
const multibar = new cliProgress.MultiBar(
{
format: '{lang} |' + colors.cyan('{bar}') + '| {percentage}% | {value}/{total} 条',
barCompleteChar: '\u2588',
barIncompleteChar: '\u2591',
hideCursor: true,
clearOnComplete: true,
stopOnComplete: true,
},
cliProgress.Presets.shades_grey
);
// 为每个语言创建进度条
const progressBars = {};
for (const lang of TARGET_LANGS) {
if (langTasks[lang].texts.length > 0) {
progressBars[lang] = multibar.create(langTasks[lang].texts.length, 0, {
lang: lang.padEnd(6, ' '),
});
}
}
// 并行处理所有语言
await Promise.all(
Object.entries(langTasks).map(async ([lang, task]) => {
if (task.texts.length === 0) return;
// 分批处理
for (let i = 0; i < task.texts.length; i += BATCH_SIZE) {
const batchKeys = task.keys.slice(i, i + BATCH_SIZE);
const batchTexts = task.texts.slice(i, i + BATCH_SIZE);
try {
const batchResults = await translateBatch(batchTexts, lang);
// 更新翻译结果
batchKeys.forEach((key, index) => {
if (batchResults[index] !== undefined) {
localeData[key][lang] = batchResults[index];
totalUpdated++;
} else {
console.error(`❌ 缺失翻译结果 [${key}@${lang}]`);
localeData[key][lang] = `[BATCH_ERROR] ${localeData[key][SOURCE_LANG]}`;
}
});
// 更新进度条
progressBars[lang].increment(batchTexts.length);
// 每批处理后保存进度
fs.writeFileSync(LOCALE_FILE, JSON.stringify(localeData, null, 2));
// 添加请求间隔避免速率限制
await new Promise((resolve) => setTimeout(resolve, 300));
} catch (error) {
console.error(`\n❌ 批次翻译失败 [${lang}]:`, error.message);
// 标记失败条目
batchKeys.forEach((key) => {
localeData[key][lang] = `[TRANSLATION_FAILED] ${localeData[key][SOURCE_LANG]}`;
});
// 跳过当前批次继续处理
progressBars[lang].increment(batchTexts.length);
}
}
})
);
// 停止所有进度条
multibar.stop();
// 最终保存
fs.writeFileSync(LOCALE_FILE, JSON.stringify(localeData, null, 2));
// 显示最终结果
if (totalUpdated > 0) {
console.log(`\n✅ 翻译完成! 共更新 ${totalUpdated} 处翻译`);
} else {
console.log('\n 没有需要更新的翻译');
}
}
main().catch(console.error);

View File

@ -76,7 +76,8 @@ const viteConfig = defineConfig((mode: ConfigEnv) => {
translateKey: '$tr',
// 是否清除已经不在上下文中的内容(清除项目中不再使用到的源语言键值对)
isClear: true,
// 翻译器(支持 doubao 或 deepseek
// 翻译器
translator: new EmptyTranslator(),
// translator: new VolcengineTranslator({
// apiKey: '',
// model: '',
@ -85,16 +86,15 @@ const viteConfig = defineConfig((mode: ConfigEnv) => {
// appId: '',
// appKey: '',
// }),
// translator: new EmptyTranslator(),
translator: new GoogleTranslator({
proxyOption: {
host: '127.0.0.1',
port: 7890,
headers: {
'User-Agent': 'Node',
},
},
}),
// translator: new GoogleTranslator({
// proxyOption: {
// host: '127.0.0.1',
// port: 7890,
// headers: {
// 'User-Agent': 'Node',
// },
// },
// }),
}),
],
root: process.cwd(),