init: 初始化 dpb 桃育种系统代码库

前后端 + 后端 FastAPI 全量源码、部署脚本与文档。
This commit is contained in:
34047007@qq.com
2026-08-06 00:17:49 +08:00
commit b95053c52c
1469 changed files with 322298 additions and 0 deletions
+712
View File
@@ -0,0 +1,712 @@
// scripts/clean-dev.ts
import fs from "fs/promises";
import path from "path";
// 现代化颜色主题
const theme = {
// 基础颜色
reset: "\x1b[0m",
bold: "\x1b[1m",
dim: "\x1b[2m",
// 前景色
primary: "\x1b[38;5;75m", // 亮蓝色
success: "\x1b[38;5;82m", // 亮绿色
warning: "\x1b[38;5;220m", // 亮黄色
error: "\x1b[38;5;196m", // 亮红色
info: "\x1b[38;5;159m", // 青色
purple: "\x1b[38;5;141m", // 紫色
orange: "\x1b[38;5;208m", // 橙色
gray: "\x1b[38;5;245m", // 灰色
white: "\x1b[38;5;255m", // 白色
// 背景色
bgDark: "\x1b[48;5;235m", // 深灰背景
bgBlue: "\x1b[48;5;24m", // 蓝色背景
bgGreen: "\x1b[48;5;22m", // 绿色背景
bgRed: "\x1b[48;5;52m", // 红色背景
};
// 现代化图标集
const icons = {
rocket: "🚀",
fire: "🔥",
star: "⭐",
gem: "💎",
crown: "👑",
magic: "✨",
warning: "⚠️",
success: "✅",
error: "❌",
info: "️",
folder: "📁",
file: "📄",
image: "🖼️",
code: "💻",
data: "📊",
globe: "🌐",
map: "🗺️",
chat: "💬",
bolt: "⚡",
shield: "🛡️",
key: "🔑",
link: "🔗",
clean: "🧹",
trash: "🗑️",
check: "✓",
cross: "✗",
arrow: "→",
loading: "⏳",
};
// 格式化工具
const fmt = {
title: (text: string) => `${theme.bold}${theme.primary}${text}${theme.reset}`,
subtitle: (text: string) => `${theme.purple}${text}${theme.reset}`,
success: (text: string) => `${theme.success}${text}${theme.reset}`,
error: (text: string) => `${theme.error}${text}${theme.reset}`,
warning: (text: string) => `${theme.warning}${text}${theme.reset}`,
info: (text: string) => `${theme.info}${text}${theme.reset}`,
highlight: (text: string) => `${theme.bold}${theme.white}${text}${theme.reset}`,
dim: (text: string) => `${theme.dim}${theme.gray}${text}${theme.reset}`,
orange: (text: string) => `${theme.orange}${text}${theme.reset}`,
// 带背景的文本
badge: (text: string, bg: string = theme.bgBlue) =>
`${bg}${theme.white}${theme.bold} ${text} ${theme.reset}`,
// 渐变效果模拟
gradient: (text: string) => {
const colors = ["\x1b[38;5;75m", "\x1b[38;5;81m", "\x1b[38;5;87m", "\x1b[38;5;159m"];
const chars = text.split("");
return chars.map((char, i) => `${colors[i % colors.length]}${char}`).join("") + theme.reset;
},
};
// 创建现代化标题横幅
function createModernBanner() {
console.log();
console.log(
fmt.gradient(" ╔══════════════════════════════════════════════════════════════════╗")
);
console.log(
fmt.gradient(" ║ ║")
);
console.log(
`${icons.rocket} ${fmt.title("ART DESIGN PRO")} ${fmt.subtitle("· 代码精简程序")} ${icons.magic}`
);
console.log(
`${fmt.dim("为项目移除演示数据,快速切换至开发模式")}`
);
console.log(
fmt.gradient(" ║ ║")
);
console.log(
fmt.gradient(" ╚══════════════════════════════════════════════════════════════════╝")
);
console.log();
}
// 创建分割线
function createDivider(char = "─", color = theme.primary) {
console.log(`${color}${" " + char.repeat(66)}${theme.reset}`);
}
// 创建卡片样式容器
function createCard(title: string, content: string[]) {
console.log(` ${fmt.badge("", theme.bgBlue)} ${fmt.title(title)}`);
console.log();
content.forEach((line) => {
console.log(` ${line}`);
});
console.log();
}
// 进度条动画
function createProgressBar(current: number, total: number, text: string, width = 40) {
const percentage = Math.round((current / total) * 100);
const filled = Math.round((current / total) * width);
const empty = width - filled;
const filledBar = "█".repeat(filled);
const emptyBar = "░".repeat(empty);
process.stdout.write(
`\r ${fmt.info("进度")} [${theme.success}${filledBar}${theme.gray}${emptyBar}${theme.reset}] ${fmt.highlight(percentage + "%")})}`
);
if (current === total) {
console.log();
}
}
// 统计信息
const stats = {
deletedFiles: 0,
deletedPaths: 0,
failedPaths: 0,
startTime: Date.now(),
totalFiles: 0,
};
// 清理目标
const targets = [
"README.md",
"README.zh-CN.md",
"CHANGELOG.md",
"CHANGELOG.zh-CN.md",
"src/views/safeguard",
"src/views/dashboard/analysis",
"src/views/dashboard/ecommerce",
"src/mock/json",
"src/mock/temp/articleList.ts",
"src/mock/temp/commentDetail.ts",
"src/mock/temp/commentList.ts",
"src/assets/images/cover",
"src/assets/images/safeguard",
"src/assets/images/3d",
"src/components/charts/art-map-chart",
"src/components/business/comment-widget",
];
// 递归统计文件数量
async function countFiles(targetPath: string): Promise<number> {
const fullPath = path.resolve(process.cwd(), targetPath);
try {
const stat = await fs.stat(fullPath);
if (stat.isFile()) {
return 1;
} else if (stat.isDirectory()) {
const entries = await fs.readdir(fullPath);
let count = 0;
for (const entry of entries) {
const entryPath = path.join(targetPath, entry);
count += await countFiles(entryPath);
}
return count;
}
} catch {
return 0;
}
return 0;
}
// 统计所有目标的文件数量
async function countAllFiles(): Promise<number> {
let totalCount = 0;
for (const target of targets) {
const count = await countFiles(target);
totalCount += count;
}
return totalCount;
}
// 删除文件和目录
async function remove(targetPath: string, index: number) {
const fullPath = path.resolve(process.cwd(), targetPath);
createProgressBar(index + 1, targets.length, targetPath);
try {
const fileCount = await countFiles(targetPath);
await fs.rm(fullPath, { recursive: true, force: true });
stats.deletedFiles += fileCount;
stats.deletedPaths++;
await new Promise((resolve) => setTimeout(resolve, 50));
} catch (err) {
stats.failedPaths++;
console.log();
console.log(` ${icons.error} ${fmt.error("删除失败")}: ${fmt.highlight(targetPath)}`);
console.log(` ${fmt.dim("错误详情: " + err)}`);
}
}
// 重置前端内置动态路由为空(`MenuProcessor.ts` 内 `builtinFrontendRoutes`;异常页在 staticRoutes
async function cleanRouteModules() {
const routesPath = path.resolve(process.cwd(), "src/router");
try {
try {
await fs.rm(path.join(routesPath, "dashboard.ts"), { force: true });
} catch {
// 忽略
}
try {
await fs.rm(path.join(routesPath, "builtinFrontendRoutes.ts"), { force: true });
} catch {
// 忽略(旧独立文件可能已不存在)
}
const menuProcessorPath = path.join(routesPath, "MenuProcessor.ts");
const mp = await fs.readFile(menuProcessorPath, "utf-8");
const reset = mp.replace(
/export const builtinFrontendRoutes: AppRouteRecord\[\] = \[[\s\S]*?\];/,
"export const builtinFrontendRoutes: AppRouteRecord[] = [];"
);
if (reset === mp) {
console.log(
` ${icons.warning} ${fmt.dim("MenuProcessor.ts 中未找到 builtinFrontendRoutes,跳过重置")}`
);
} else {
await fs.writeFile(menuProcessorPath, reset, "utf-8");
}
console.log(` ${icons.success} ${fmt.success("清理路由演示模块完成")}`);
} catch (err) {
console.log(` ${icons.error} ${fmt.error("清理路由演示模块失败")}`);
console.log(` ${fmt.dim("错误详情: " + err)}`);
}
}
// 路由占位常量已写在 src/router/staticRoutes.ts 顶部,清理脚本不再单独重写
async function cleanRouterConstants() {
console.log(
` ${icons.info} ${fmt.dim("路由常量(ROUTE_*)位于 staticRoutes.ts 顶部,请按需手动修改")}`
);
}
// 清理变更日志
async function cleanChangeLog() {
const changeLogPath = path.resolve(process.cwd(), "src/mock/upgrade/changeLog.ts");
try {
const cleanedChangeLog = `import { ref } from 'vue'
interface UpgradeLog {
version: string // 版本号
title: string // 更新标题
date: string // 更新日期
detail?: string[] // 更新内容
requireReLogin?: boolean // 是否需要重新登录
remark?: string // 备注
}
export const upgradeLogList = ref<UpgradeLog[]>([])
`;
await fs.writeFile(changeLogPath, cleanedChangeLog, "utf-8");
console.log(` ${icons.success} ${fmt.success("清空变更日志数据完成")}`);
} catch (err) {
console.log(` ${icons.error} ${fmt.error("清理变更日志失败")}`);
console.log(` ${fmt.dim("错误详情: " + err)}`);
}
}
// 清理语言文件
async function cleanLanguageFiles() {
const languageFiles = [
{ path: "src/locales/langs/zh.json", name: "中文语言文件" },
{ path: "src/locales/langs/en.json", name: "英文语言文件" },
];
for (const { path: langPath, name } of languageFiles) {
try {
const fullPath = path.resolve(process.cwd(), langPath);
const content = await fs.readFile(fullPath, "utf-8");
const langData = JSON.parse(content);
const menusToRemove = [
"widgets",
"template",
"article",
"examples",
"safeguard",
"plan",
"help",
];
if (langData.menus) {
menusToRemove.forEach((menuKey) => {
if (langData.menus[menuKey]) {
delete langData.menus[menuKey];
}
});
if (langData.menus.dashboard) {
if (langData.menus.dashboard.analysis) {
delete langData.menus.dashboard.analysis;
}
if (langData.menus.dashboard.ecommerce) {
delete langData.menus.dashboard.ecommerce;
}
}
if (langData.menus.system) {
const systemKeysToRemove = [
"nested",
"menu1",
"menu2",
"menu21",
"menu3",
"menu31",
"menu32",
"menu321",
];
systemKeysToRemove.forEach((key) => {
if (langData.menus.system[key]) {
delete langData.menus.system[key];
}
});
}
}
await fs.writeFile(fullPath, JSON.stringify(langData, null, 2), "utf-8");
console.log(` ${icons.success} ${fmt.success(`清理${name}完成`)}`);
} catch (err) {
console.log(` ${icons.error} ${fmt.error(`清理${name}失败`)}`);
console.log(` ${fmt.dim("错误详情: " + err)}`);
}
}
}
// 清理快速入口组件
async function cleanFastEnterComponent() {
const fastEnterPath = path.resolve(process.cwd(), "src/config/fastEnter.ts");
try {
const cleanedFastEnter = `/**
* 快速入口配置
* 包含:应用列表、快速链接等配置
*/
import { WEB_LINKS } from "@utils/constants";
import type { FastEnterConfig } from '@/types/config'
const fastEnterConfig: FastEnterConfig = {
// 显示条件(屏幕宽度)
minWidth: 1200,
// 应用列表
applications: [
{
name: '工作台',
description: '系统概览与数据统计',
icon: 'ri:pie-chart-line',
iconColor: '#377dff',
enabled: true,
order: 1,
routeName: 'Console'
},
{
name: '官方文档',
description: '使用指南与开发文档',
icon: 'ri:bill-line',
iconColor: '#ffb100',
enabled: true,
order: 2,
link: WEB_LINKS.DOCS
},
{
name: '技术支持',
description: '技术支持与问题反馈',
icon: 'ri:user-location-line',
iconColor: '#ff6b6b',
enabled: true,
order: 3,
link: WEB_LINKS.COMMUNITY
},
{
name: '哔哩哔哩',
description: '技术分享与交流',
icon: 'ri:bilibili-line',
iconColor: '#FB7299',
enabled: true,
order: 4,
link: WEB_LINKS.BILIBILI
}
],
// 快速链接
quickLinks: [
{
name: '登录',
enabled: true,
order: 1,
routeName: 'Login'
},
{
name: '注册',
enabled: true,
order: 2,
routeName: 'Login'
},
{
name: '忘记密码',
enabled: true,
order: 3,
routeName: 'Login'
},
{
name: '个人中心',
enabled: true,
order: 4,
routeName: 'Profile'
}
]
}
export default Object.freeze(fastEnterConfig)
`;
await fs.writeFile(fastEnterPath, cleanedFastEnter, "utf-8");
console.log(` ${icons.success} ${fmt.success("清理快速入口配置完成")}`);
} catch (err) {
console.log(` ${icons.error} ${fmt.error("清理快速入口配置失败")}`);
console.log(` ${fmt.dim("错误详情: " + err)}`);
}
}
// 更新菜单接口
async function updateMenuApi() {
const apiPath = path.resolve(process.cwd(), "src/api/system-manage.ts");
try {
const content = await fs.readFile(apiPath, "utf-8");
const updatedContent = content.replace(
"url: '/api/v3/system/menus'",
"url: '/api/v3/system/menus/simple'"
);
await fs.writeFile(apiPath, updatedContent, "utf-8");
console.log(` ${icons.success} ${fmt.success("更新菜单接口完成")}`);
} catch (err) {
console.log(` ${icons.error} ${fmt.error("更新菜单接口失败")}`);
console.log(` ${fmt.dim("错误详情: " + err)}`);
}
}
// 用户确认函数
async function getUserConfirmation(): Promise<boolean> {
const { createInterface } = await import("readline");
return new Promise((resolve) => {
const rl = createInterface({
input: process.stdin,
output: process.stdout,
});
console.log(
` ${fmt.highlight("请输入")} ${fmt.success("yes")} ${fmt.highlight("确认执行清理操作,或按 Enter 取消")}`
);
console.log();
process.stdout.write(` ${icons.arrow} `);
rl.question("", (answer: string) => {
rl.close();
resolve(answer.toLowerCase().trim() === "yes");
});
});
}
// 显示清理警告
async function showCleanupWarning() {
createCard("安全警告", [
`${fmt.warning("此操作将永久删除以下演示内容,且无法恢复!")}`,
`${fmt.dim("请仔细阅读清理列表,确认后再继续操作")}`,
]);
const cleanupItems = [
{
icon: icons.image,
name: "图片资源",
desc: "演示用的封面图片、3D图片、运维图片等",
color: theme.orange,
},
{
icon: icons.file,
name: "演示页面",
desc: "widgets、article、examples、safeguard 等页面",
color: theme.purple,
},
{
icon: icons.code,
name: "路由模块文件",
desc: "删除演示路由模块,只保留核心模块(dashboard、system、result、exception",
color: theme.primary,
},
{
icon: icons.link,
name: "路由常量",
desc: "占位路径见 staticRoutes.ts 顶部(脚本不自动覆盖)",
color: theme.info,
},
{
icon: icons.data,
name: "Mock数据",
desc: "演示用的JSON数据、文章列表、评论数据等",
color: theme.success,
},
{
icon: icons.globe,
name: "多语言文件",
desc: "清理中英文语言包中的演示菜单项",
color: theme.warning,
},
{ icon: icons.map, name: "地图组件", desc: "移除art-map-chart地图组件", color: theme.error },
{ icon: icons.chat, name: "评论组件", desc: "移除comment-widget评论组件", color: theme.orange },
{
icon: icons.bolt,
name: "快速入口",
desc: "移除分析页、礼花效果、聊天、更新日志、定价、留言管理等无效项目",
color: theme.purple,
},
];
console.log(` ${fmt.badge("", theme.bgRed)} ${fmt.title("将要清理的内容")}`);
console.log();
cleanupItems.forEach((item, index) => {
console.log(` ${item.color}${theme.reset} ${fmt.highlight(`${index + 1}. ${item.name}`)}`);
console.log(` ${fmt.dim(item.desc)}`);
});
console.log();
console.log(` ${fmt.badge("", theme.bgGreen)} ${fmt.title("保留的功能模块")}`);
console.log();
const preservedModules = [
{ name: "Dashboard", desc: "工作台页面" },
{ name: "System", desc: "系统管理模块" },
{ name: "Result", desc: "结果页面" },
{ name: "Exception", desc: "异常页面" },
{ name: "Auth", desc: "登录注册功能" },
{ name: "Core Components", desc: "核心组件库" },
];
preservedModules.forEach((module) => {
console.log(` ${icons.check} ${fmt.success(module.name)} ${fmt.dim(`- ${module.desc}`)}`);
});
console.log();
createDivider();
console.log();
}
// 显示统计信息
async function showStats() {
const duration = Date.now() - stats.startTime;
const seconds = (duration / 1000).toFixed(2);
console.log();
createCard("清理统计", [
`${fmt.success("成功删除")}: ${fmt.highlight(stats.deletedFiles.toString())} 个文件`,
`${fmt.info("涉及路径")}: ${fmt.highlight(stats.deletedPaths.toString())} 个目录/文件`,
...(stats.failedPaths > 0
? [
`${icons.error} ${fmt.error("删除失败")}: ${fmt.highlight(stats.failedPaths.toString())} 个路径`,
]
: []),
`${fmt.info("耗时")}: ${fmt.highlight(seconds)}`,
]);
}
// 创建成功横幅
function createSuccessBanner() {
console.log();
console.log(
fmt.gradient(" ╔══════════════════════════════════════════════════════════════════╗")
);
console.log(
fmt.gradient(" ║ ║")
);
console.log(
`${icons.star} ${fmt.success("清理完成!项目已准备就绪")} ${icons.rocket}`
);
console.log(
`${fmt.dim("现在可以开始您的开发之旅了!")}`
);
console.log(
fmt.gradient(" ║ ║")
);
console.log(
fmt.gradient(" ╚══════════════════════════════════════════════════════════════════╝")
);
console.log();
}
// 主函数
async function main() {
// 清屏并显示横幅
console.clear();
createModernBanner();
// 显示清理警告
await showCleanupWarning();
// 统计文件数量
console.log(` ${fmt.info("正在统计文件数量...")}`);
stats.totalFiles = await countAllFiles();
console.log(` ${fmt.info("即将清理")}: ${fmt.highlight(stats.totalFiles.toString())} 个文件`);
console.log(` ${fmt.dim(`涉及 ${targets.length} 个目录/文件路径`)}`);
console.log();
// 用户确认
const confirmed = await getUserConfirmation();
if (!confirmed) {
console.log(` ${fmt.warning("操作已取消,清理中止")}`);
console.log();
return;
}
console.log();
console.log(` ${icons.check} ${fmt.success("确认成功,开始清理...")}`);
console.log();
// 开始清理过程
console.log(` ${fmt.badge("步骤 1/6", theme.bgBlue)} ${fmt.title("删除演示文件")}`);
console.log();
for (let i = 0; i < targets.length; i++) {
await remove(targets[i], i);
}
console.log();
console.log(` ${fmt.badge("步骤 2/6", theme.bgBlue)} ${fmt.title("清理路由模块")}`);
console.log();
await cleanRouteModules();
console.log();
console.log(` ${fmt.badge("步骤 3/6", theme.bgBlue)} ${fmt.title("重写路由常量")}`);
console.log();
await cleanRouterConstants();
console.log();
console.log(` ${fmt.badge("步骤 4/6", theme.bgBlue)} ${fmt.title("清空变更日志")}`);
console.log();
await cleanChangeLog();
console.log();
console.log(` ${fmt.badge("步骤 5/6", theme.bgBlue)} ${fmt.title("清理语言文件")}`);
console.log();
await cleanLanguageFiles();
console.log();
console.log(` ${fmt.badge("步骤 6/7", theme.bgBlue)} ${fmt.title("清理快速入口")}`);
console.log();
await cleanFastEnterComponent();
console.log();
console.log(` ${fmt.badge("步骤 7/7", theme.bgBlue)} ${fmt.title("更新菜单接口")}`);
console.log();
await updateMenuApi();
// 显示统计信息
await showStats();
// 显示成功横幅
createSuccessBanner();
}
main().catch((err) => {
console.log();
console.log(` ${icons.error} ${fmt.error("清理脚本执行出错")}`);
console.log(` ${fmt.dim("错误详情: " + err)}`);
console.log();
process.exit(1);
});