150ae3dcfd
- Prisma 新增 Skill 模型 (id/name/description/icon/category/difficulty/systemPrompt/starters/tasks/tags/prerequisiteIds) - SkillsService 从 DB 读取替代硬编码常量 - seed.ts 新增 seedSkills() 写入 8 个技能 - SkillsController 保持不变,API 返回 JSON 解析后的 starters/tasks
262 lines
19 KiB
JavaScript
262 lines
19 KiB
JavaScript
"use strict";
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
function step(op) {
|
|
if (f) throw new TypeError("Generator is already executing.");
|
|
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
switch (op[0]) {
|
|
case 0: case 1: t = op; break;
|
|
case 4: _.label++; return { value: op[1], done: false };
|
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
default:
|
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
if (t[2]) _.ops.pop();
|
|
_.trys.pop(); continue;
|
|
}
|
|
op = body.call(thisArg, _);
|
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
}
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
var client_1 = require("@prisma/client");
|
|
var bcrypt = __importStar(require("bcryptjs"));
|
|
var prisma = new client_1.PrismaClient();
|
|
function main() {
|
|
return __awaiter(this, void 0, void 0, function () {
|
|
var adminPassword, categories, _i, categories_1, cat, basicsCategory, promptCategory, course, prompts, _a, prompts_1, prompt_1, toolsCategory, tools, _b, tools_1, tool;
|
|
return __generator(this, function (_c) {
|
|
switch (_c.label) {
|
|
case 0: return [4 /*yield*/, bcrypt.hash('admin123456', 10)];
|
|
case 1:
|
|
adminPassword = _c.sent();
|
|
return [4 /*yield*/, prisma.adminUser.upsert({
|
|
where: { username: 'admin' },
|
|
update: {},
|
|
create: {
|
|
username: 'admin',
|
|
passwordHash: adminPassword,
|
|
nickname: '超级管理员',
|
|
role: 'superadmin',
|
|
},
|
|
})];
|
|
case 2:
|
|
_c.sent();
|
|
categories = [
|
|
{ name: 'AI 入门', slug: 'ai-basics', description: 'AI 基础知识与入门指南' },
|
|
{ name: '办公效率', slug: 'office-productivity', description: '用 AI 提升办公效率' },
|
|
{ name: '创意设计', slug: 'creative-design', description: 'AI 辅助创意与设计' },
|
|
{ name: '编程开发', slug: 'programming', description: 'AI 辅助编程开发' },
|
|
{ name: '教育学习', slug: 'education', description: 'AI 在教育中的应用' },
|
|
{ name: '提示词技巧', slug: 'prompt-engineering', description: '提示词工程与技巧' },
|
|
{ name: 'AI 工具', slug: 'ai-tools', description: 'AI 工具收录与评测' },
|
|
{ name: '模型百科', slug: 'model-encyclopedia', description: '大模型介绍与对比' },
|
|
];
|
|
_i = 0, categories_1 = categories;
|
|
_c.label = 3;
|
|
case 3:
|
|
if (!(_i < categories_1.length)) return [3 /*break*/, 6];
|
|
cat = categories_1[_i];
|
|
return [4 /*yield*/, prisma.category.upsert({
|
|
where: { slug: cat.slug },
|
|
update: {},
|
|
create: cat,
|
|
})];
|
|
case 4:
|
|
_c.sent();
|
|
_c.label = 5;
|
|
case 5:
|
|
_i++;
|
|
return [3 /*break*/, 3];
|
|
case 6: return [4 /*yield*/, prisma.category.findUnique({ where: { slug: 'ai-basics' } })];
|
|
case 7:
|
|
basicsCategory = _c.sent();
|
|
return [4 /*yield*/, prisma.category.findUnique({ where: { slug: 'prompt-engineering' } })];
|
|
case 8:
|
|
promptCategory = _c.sent();
|
|
if (!basicsCategory) return [3 /*break*/, 10];
|
|
return [4 /*yield*/, prisma.course.upsert({
|
|
where: { id: 1 },
|
|
update: {},
|
|
create: {
|
|
title: 'AI 通识课:零基础入门人工智能',
|
|
description: '面向零基础用户的 AI 入门课程,带你了解 AI 的基本概念、发展历程和实际应用。',
|
|
categoryId: basicsCategory.id,
|
|
isFree: true,
|
|
status: 'PUBLISHED',
|
|
sortOrder: 1,
|
|
chapters: {
|
|
create: [
|
|
{
|
|
title: '第一章:什么是人工智能',
|
|
sortOrder: 1,
|
|
lessons: {
|
|
create: [
|
|
{ title: 'AI 的定义与发展简史', content: '# AI 的定义\n\n人工智能...', sortOrder: 1, status: 'PUBLISHED' },
|
|
{ title: '机器学习 vs 深度学习', content: '# 机器学习\n\n...', sortOrder: 2, status: 'PUBLISHED' },
|
|
{ title: '大语言模型(LLM)是什么', content: '# 大语言模型\n\n...', sortOrder: 3, status: 'PUBLISHED' },
|
|
],
|
|
},
|
|
},
|
|
{
|
|
title: '第二章:主流 AI 工具介绍',
|
|
sortOrder: 2,
|
|
lessons: {
|
|
create: [
|
|
{ title: 'ChatGPT 与 GPT 系列', content: '# ChatGPT\n\n...', sortOrder: 1, status: 'PUBLISHED' },
|
|
{ title: 'Claude 系列模型', content: '# Claude\n\n...', sortOrder: 2, status: 'PUBLISHED' },
|
|
{ title: '国内大模型:通义千问、文心一言、GLM', content: '# 国内大模型\n\n...', sortOrder: 3, status: 'PUBLISHED' },
|
|
],
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
})];
|
|
case 9:
|
|
course = _c.sent();
|
|
_c.label = 10;
|
|
case 10:
|
|
if (!promptCategory) return [3 /*break*/, 14];
|
|
prompts = [
|
|
{ title: '写周报助手', content: '请帮我写一份本周工作总结,我的工作是:[描述你的工作内容]。\n\n要求:\n1. 按重点项目分类\n2. 包含数据成果\n3. 列出下周计划\n4. 语言简洁专业', description: '帮你快速生成高质量周报', categoryId: promptCategory.id, tags: '办公,周报', model: '通用', status: 'PUBLISHED' },
|
|
{ title: '会议纪要生成', content: '请根据以下会议内容生成会议纪要:\n[粘贴会议内容]\n\n格式要求:\n- 时间\n- 参会人\n- 会议议题\n- 讨论要点\n- 待办事项及负责人', description: '快速整理会议内容为结构化纪要', categoryId: promptCategory.id, tags: '办公,会议', model: '通用', status: 'PUBLISHED' },
|
|
];
|
|
_a = 0, prompts_1 = prompts;
|
|
_c.label = 11;
|
|
case 11:
|
|
if (!(_a < prompts_1.length)) return [3 /*break*/, 14];
|
|
prompt_1 = prompts_1[_a];
|
|
return [4 /*yield*/, prisma.prompt.create({ data: prompt_1 })];
|
|
case 12:
|
|
_c.sent();
|
|
_c.label = 13;
|
|
case 13:
|
|
_a++;
|
|
return [3 /*break*/, 11];
|
|
case 14: return [4 /*yield*/, prisma.category.findUnique({ where: { slug: 'ai-tools' } })];
|
|
case 15:
|
|
toolsCategory = _c.sent();
|
|
if (!toolsCategory) return [3 /*break*/, 19];
|
|
tools = [
|
|
{ name: 'ChatGPT', description: 'OpenAI 开发的对话式 AI 助手,支持文本生成、代码编写、分析等', url: 'https://chat.openai.com', categoryId: toolsCategory.id, tags: '对话,文本生成,代码', isFeatured: true, status: 'PUBLISHED' },
|
|
{ name: 'Claude', description: 'Anthropic 开发的 AI 助手,擅长深度分析、长文本处理', url: 'https://claude.ai', categoryId: toolsCategory.id, tags: '对话,分析,长文本', isFeatured: true, status: 'PUBLISHED' },
|
|
{ name: '通义千问', description: '阿里云开发的 AI 大模型,支持文本、图像、代码等多种任务', url: 'https://tongyi.aliyun.com', categoryId: toolsCategory.id, tags: '对话,文本,国内', isFeatured: true, status: 'PUBLISHED' },
|
|
{ name: '文心一言', description: '百度开发的 AI 对话产品,基于文心大模型', url: 'https://yiyan.baidu.com', categoryId: toolsCategory.id, tags: '对话,文本,国内', isFeatured: true, status: 'PUBLISHED' },
|
|
];
|
|
_b = 0, tools_1 = tools;
|
|
_c.label = 16;
|
|
case 16:
|
|
if (!(_b < tools_1.length)) return [3 /*break*/, 19];
|
|
tool = tools_1[_b];
|
|
return [4 /*yield*/, prisma.tool.create({ data: tool })];
|
|
case 17:
|
|
_c.sent();
|
|
_c.label = 18;
|
|
case 18:
|
|
_b++;
|
|
return [3 /*break*/, 16];
|
|
case 19: return [4 /*yield*/, seedSkills()];
|
|
case 20:
|
|
_c.sent();
|
|
console.log('Seed data created successfully!');
|
|
return [2 /*return*/];
|
|
}
|
|
});
|
|
});
|
|
}
|
|
function seedSkills() {
|
|
return __awaiter(this, void 0, void 0, function () {
|
|
var skills, _i, skills_1, skill;
|
|
return __generator(this, function (_a) {
|
|
switch (_a.label) {
|
|
case 0:
|
|
skills = [
|
|
{ id: 'general-chat', name: '通用对话', description: '日常问答,无所不谈', icon: '💬', category: 'basic', difficulty: 'beginner', systemPrompt: '你是一个智能 AI 助手,请友好、准确地回答用户的问题。', starters: JSON.stringify(['介绍一下你自己', '今天天气怎么样', '讲个笑话']), tasks: JSON.stringify([{ label: '发起一次对话', prompt: '你好' }]), tags: '入门,通用', prerequisiteIds: null, sortOrder: 1 },
|
|
{ id: 'coding', name: '编程助手', description: '写代码、Debug、学编程', icon: '💻', category: 'technical', difficulty: 'intermediate', systemPrompt: '你是一名资深软件工程师,擅长编程教学。请用清晰的代码示例和通俗的语言解释技术概念。回答时优先提供可运行的代码。', starters: JSON.stringify(['用 Python 写一个二分查找', 'React 和 Vue 有什么区别', '帮我 Debug 这段代码']), tasks: JSON.stringify([{ label: '要求代码示例', prompt: '用 Python 写一个二分查找' }]), tags: '编程,Python,Debug', prerequisiteIds: null, sortOrder: 2 },
|
|
{ id: 'writing', name: '写作助手', description: '文章、文案、报告润色', icon: '✍️', category: 'creative', difficulty: 'beginner', systemPrompt: '你是一名专业的写作顾问,擅长各类文体写作。请根据用户需求提供高质量的文字内容,注意逻辑清晰、表达准确。', starters: JSON.stringify(['帮我写一篇产品介绍', '润色这段文字', '写一封工作邮件']), tasks: JSON.stringify([{ label: '练习写作', prompt: '帮我写一篇产品介绍' }]), tags: '写作,文案,润色', prerequisiteIds: null, sortOrder: 3 },
|
|
{ id: 'study', name: '学习辅导', description: '概念讲解、知识总结', icon: '📚', category: 'education', difficulty: 'beginner', systemPrompt: '你是一名耐心且知识渊博的老师。请用通俗易懂的方式解释复杂概念,善用类比和例子,鼓励用户深入提问。', starters: JSON.stringify(['解释什么是机器学习', '讲一下 TCP/IP 协议', '怎么理解量子计算']), tasks: JSON.stringify([{ label: '学习概念', prompt: '用简单的类比解释什么是机器学习' }]), tags: '学习,概念讲解', prerequisiteIds: null, sortOrder: 4 },
|
|
{ id: 'english', name: '英语学习', description: '翻译、语法、口语练习', icon: '🌍', category: 'education', difficulty: 'intermediate', systemPrompt: 'You are an English tutor. Help users improve their English.', starters: JSON.stringify(['"However" 和 "Although" 的区别', '帮我翻译这段话', '检查语法错误']), tasks: JSON.stringify([{ label: '语法练习', prompt: '"I have went to school" 有什么语法错误' }]), tags: '英语,翻译,语法', prerequisiteIds: null, sortOrder: 5 },
|
|
{ id: 'prompt-engineering', name: '提示词工程', description: '学习编写高质量提示词', icon: '🎯', category: 'advanced', difficulty: 'advanced', systemPrompt: '你是一名提示词工程专家。帮助用户理解如何构建有效的提示词。', starters: JSON.stringify(['如何写好一个提示词', '什么是 Chain-of-Thought']), tasks: JSON.stringify([{ label: '学习提示词结构', prompt: '一个好的提示词应该包含哪些要素' }]), tags: '提示词,Prompt,进阶', prerequisiteIds: 'general-chat', sortOrder: 6 },
|
|
{ id: 'data-analysis', name: '数据分析', description: '数据处理、可视化、报表', icon: '📊', category: 'technical', difficulty: 'intermediate', systemPrompt: '你是一名数据分析师。擅长使用 Python、SQL 等工具进行数据分析和可视化。', starters: JSON.stringify(['用 Python 分析这份数据', '这个 SQL 查询怎么优化']), tasks: JSON.stringify([{ label: '数据分析入门', prompt: '用 Python pandas 读取 CSV 文件并做基本统计' }]), tags: '数据分析,Python,SQL', prerequisiteIds: null, sortOrder: 7 },
|
|
{ id: 'career', name: '职业发展', description: '简历优化、面试准备', icon: '🚀', category: 'career', difficulty: 'beginner', systemPrompt: '你是一名职业发展顾问。帮助用户优化简历、准备面试。', starters: JSON.stringify(['帮我优化简历', '面试注意事项']), tasks: JSON.stringify([{ label: '简历优化', prompt: '帮我优化这段工作经历描述' }]), tags: '职业,简历,面试', prerequisiteIds: null, sortOrder: 8 },
|
|
];
|
|
_i = 0, skills_1 = skills;
|
|
_a.label = 1;
|
|
case 1:
|
|
if (!(_i < skills_1.length)) return [3 /*break*/, 4];
|
|
skill = skills_1[_i];
|
|
return [4 /*yield*/, prisma.skill.upsert({
|
|
where: { id: skill.id },
|
|
create: skill,
|
|
update: skill,
|
|
})];
|
|
case 2:
|
|
_a.sent();
|
|
_a.label = 3;
|
|
case 3:
|
|
_i++;
|
|
return [3 /*break*/, 1];
|
|
case 4:
|
|
console.log("".concat(skills.length, " skills seeded"));
|
|
return [2 /*return*/];
|
|
}
|
|
});
|
|
});
|
|
}
|
|
main()
|
|
.catch(function (e) {
|
|
console.error(e);
|
|
process.exit(1);
|
|
})
|
|
.finally(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
return __generator(this, function (_a) {
|
|
switch (_a.label) {
|
|
case 0: return [4 /*yield*/, prisma.$disconnect()];
|
|
case 1:
|
|
_a.sent();
|
|
return [2 /*return*/];
|
|
}
|
|
});
|
|
}); });
|