import 'dotenv/config'; import { PrismaClient } from '../src/generated/prisma/client'; import { hashPassword } from '../src/lib/auth'; import { CONTENT_TYPE_CONFIGS } from '../src/lib/cms/content-types'; import { PRIVACY_POLICY_HTML, TERMS_OF_SERVICE_HTML } from './seeds/legal-pages'; import { CASE_STUDIES } from './seeds/case-studies'; import { NEWS } from '../src/lib/constants/news'; import { SERVICES } from './seeds/services'; import { PRODUCTS } from './seeds/products'; import { STANDALONE_PRODUCTS } from './seeds/standalone-products'; import { SOLUTIONS } from './seeds/solutions'; import { STATS } from '../src/lib/constants/stats'; import { COMPANY_INFO } from '../src/lib/constants/company'; import { NAVIGATION_V2, MEGA_DROPDOWN_DATA } from '../src/lib/constants/navigation'; const prisma = new PrismaClient(); async function getModelId(code: string): Promise { const model = await prisma.contentModel.findUnique({ where: { code } }); if (!model) throw new Error(`模型 ${code} 未找到`); return model.id; } async function seedItems( modelCode: string, items: Record[], options: { slugField?: string; titleField?: string } = {}, ) { const modelId = await getModelId(modelCode); const slugField = options.slugField || 'slug'; const titleField = options.titleField || 'title'; for (let i = 0; i < items.length; i++) { const item = items[i]!; const slug = String(item[slugField] || item.id || `${modelCode}-${i}`); const title = String(item[titleField] || `未命名 ${i + 1}`); const data = item as Record; await prisma.contentItem.upsert({ where: { modelCode_slug_locale: { modelCode, slug, locale: 'zh-CN' } }, update: { title, data: JSON.stringify(data), sortOrder: i, status: 'published', publishedAt: new Date(), }, create: { modelId, modelCode, title, slug, data: JSON.stringify(data), sortOrder: i, status: 'published', publishedAt: new Date(), createdBy: 'system', updatedBy: 'system', }, }); } } async function seedHomeZones() { const heroItem = await prisma.contentItem.findFirst({ where: { modelCode: 'hero-banner', status: 'published' }, orderBy: { sortOrder: 'asc' }, }); const statItems = await prisma.contentItem.findMany({ where: { modelCode: 'stat-item', status: 'published' }, orderBy: { sortOrder: 'asc' }, take: 4, }); const serviceItems = await prisma.contentItem.findMany({ where: { modelCode: 'service', status: 'published' }, orderBy: { sortOrder: 'asc' }, take: 6, }); const solutionItems = await prisma.contentItem.findMany({ where: { modelCode: 'solution', status: 'published' }, orderBy: { sortOrder: 'asc' }, take: 6, }); const caseItems = await prisma.contentItem.findMany({ where: { modelCode: 'case-study', status: 'published' }, orderBy: { sortOrder: 'asc' }, }); const featuredCaseItems = caseItems .filter((item) => { try { const data = JSON.parse(item.data) as Record; return data.featured === true; } catch { return false; } }) .slice(0, 3); const newsItems = await prisma.contentItem.findMany({ where: { modelCode: 'news', status: 'published' }, orderBy: { sortOrder: 'asc' }, take: 3, }); const zones = [ { code: 'home-hero', name: '首页 - Hero Banner', pageCode: 'home', zoneKey: 'hero', allowedModels: ['hero-banner'], items: heroItem ? [{ itemId: heroItem.id, sortOrder: 0, variant: 'default' }] : [], }, { code: 'home-stats', name: '首页 - 数据指标', pageCode: 'home', zoneKey: 'stats', allowedModels: ['stat-item'], items: statItems.map((item, i) => ({ itemId: item.id, sortOrder: i, variant: 'default' })), }, { code: 'home-services', name: '首页 - 服务展示', pageCode: 'home', zoneKey: 'services', allowedModels: ['service'], items: serviceItems.map((item, i) => ({ itemId: item.id, sortOrder: i, variant: 'default' })), }, { code: 'home-solutions', name: '首页 - 解决方案', pageCode: 'home', zoneKey: 'solutions', allowedModels: ['solution'], items: solutionItems.map((item, i) => ({ itemId: item.id, sortOrder: i, variant: 'default' })), }, { code: 'home-cases', name: '首页 - 精选案例', pageCode: 'home', zoneKey: 'cases', allowedModels: ['case-study'], items: featuredCaseItems.map((item, i) => ({ itemId: item.id, sortOrder: i, variant: 'default' })), }, { code: 'home-news', name: '首页 - 新闻动态', pageCode: 'home', zoneKey: 'news', allowedModels: ['news'], items: newsItems.map((item, i) => ({ itemId: item.id, sortOrder: i, variant: 'default' })), }, ]; for (const zone of zones) { await prisma.contentZone.upsert({ where: { code: zone.code }, update: { name: zone.name, pageCode: zone.pageCode, zoneKey: zone.zoneKey, allowedModels: JSON.stringify(zone.allowedModels), items: JSON.stringify(zone.items), }, create: { code: zone.code, name: zone.name, pageCode: zone.pageCode, zoneKey: zone.zoneKey, allowedModels: JSON.stringify(zone.allowedModels), items: JSON.stringify(zone.items), }, }); console.log(` ✅ 区域: ${zone.name}`); } } async function main() { console.log('🌱 开始数据库初始化...'); // ============ 1. 创建管理员用户 ============ console.log('📝 创建管理员用户...'); const adminPassword = await hashPassword('admin123'); const adminUser = await prisma.user.upsert({ where: { username: 'admin' }, update: {}, create: { username: 'admin', password: adminPassword, nickname: '管理员', role: 'admin', status: 1, }, }); console.log(' ✅ 管理员: admin / admin123'); // ============ 1.5 创建 RBAC 角色与权限 ============ console.log('📝 创建 RBAC 角色与权限...'); const roleCodes = ['super_admin', 'content_admin', 'content_editor', 'reviewer', 'readonly']; for (const code of roleCodes) { const nameMap: Record = { super_admin: '超级管理员', content_admin: '内容管理员', content_editor: '内容编辑', reviewer: '审核员', readonly: '只读用户', }; await prisma.role.upsert({ where: { code }, update: {}, create: { code, name: nameMap[code] || code }, }); } const contentModels = [ 'news', 'product', 'solution', 'service', 'case-study', 'team', 'legal', 'about-page', 'hero-banner', 'stat-item', 'standalone-product', 'media', ]; // 为 super_admin 之外的角色创建权限 const permissionMatrix: Array<{ roleCode: string; actions: string[]; models?: string[] }> = [ { roleCode: 'content_admin', actions: ['create', 'read', 'update', 'delete', 'publish'], models: contentModels, }, { roleCode: 'content_editor', actions: ['create', 'read', 'update'], models: contentModels, }, { roleCode: 'reviewer', actions: ['read', 'publish'], models: contentModels, }, { roleCode: 'readonly', actions: ['read'], models: contentModels, }, ]; for (const { roleCode, actions, models } of permissionMatrix) { if (!models) continue; for (const modelCode of models) { for (const action of actions) { await prisma.permission.upsert({ where: { roleCode_modelCode_action: { roleCode, modelCode, action, }, }, update: {}, create: { roleCode, modelCode, action, }, }); } } } // 为 admin 用户分配 super_admin 角色 await prisma.userRole.upsert({ where: { userId_roleCode: { userId: adminUser.id, roleCode: 'super_admin', }, }, update: {}, create: { userId: adminUser.id, roleCode: 'super_admin', }, }); // 为 E2E 测试创建固定角色账号 console.log('📝 创建 E2E 测试用户...'); const editorPassword = await hashPassword('editor123'); const reviewerPassword = await hashPassword('reviewer123'); const e2eEditor = await prisma.user.upsert({ where: { username: 'e2e_editor' }, update: {}, create: { username: 'e2e_editor', password: editorPassword, nickname: 'E2E 编辑', role: 'content_editor', status: 1, }, }); const e2eReviewer = await prisma.user.upsert({ where: { username: 'e2e_reviewer' }, update: {}, create: { username: 'e2e_reviewer', password: reviewerPassword, nickname: 'E2E 审核', role: 'reviewer', status: 1, }, }); await prisma.userRole.upsert({ where: { userId_roleCode: { userId: e2eEditor.id, roleCode: 'content_editor' } }, update: {}, create: { userId: e2eEditor.id, roleCode: 'content_editor' }, }); await prisma.userRole.upsert({ where: { userId_roleCode: { userId: e2eReviewer.id, roleCode: 'reviewer' } }, update: {}, create: { userId: e2eReviewer.id, roleCode: 'reviewer' }, }); console.log(' ✅ E2E 测试用户: e2e_editor / editor123, e2e_reviewer / reviewer123'); console.log(' ✅ RBAC 角色与权限初始化完成'); // ============ 2. 创建内容模型 ============ console.log('📝 创建内容模型...'); const modelConfigs = [ ...Object.values(CONTENT_TYPE_CONFIGS), // === about-page === { model: { code: 'about-page', name: '关于我们', description: '公司介绍、核心价值、发展历程与资质认证信息', isPageType: true, urlPattern: '/about', hasVersions: true, hasDraft: true, icon: 'building2', fields: [ { name: 'heroSubtitle', type: 'text', label: 'Hero 标签', required: true }, { name: 'heroTitle', type: 'text', label: 'Hero 主标题', required: true }, { name: 'heroDescription', type: 'textarea', label: 'Hero 描述', required: true }, { name: 'whoWeAreTitle', type: 'text', label: '"我们是谁"标题' }, { name: 'whoWeAreDescription', type: 'textarea', label: '"我们是谁"描述' }, { name: 'promise', type: 'textarea', label: '承诺标语', required: true }, { name: 'coreValues', type: 'array', label: '核心价值观', fields: [ { name: 'number', type: 'text', label: '编号' }, { name: 'title', type: 'text', label: '标题' }, { name: 'description', type: 'textarea', label: '描述' }, ]}, { name: 'milestones', type: 'array', label: '发展历程', fields: [ { name: 'year', type: 'text', label: '年份' }, { name: 'title', type: 'text', label: '标题' }, { name: 'description', type: 'textarea', label: '描述' }, { name: 'highlight', type: 'text', label: '亮点' }, ]}, { name: 'keyMetrics', type: 'array', label: '关键指标', fields: [ { name: 'value', type: 'text', label: '数值' }, { name: 'label', type: 'text', label: '标签' }, { name: 'sub', type: 'text', label: '副文本' }, ]}, { name: 'certifications', type: 'array', label: '资质认证', fields: [ { name: 'name', type: 'text', label: '名称' }, { name: 'desc', type: 'text', label: '描述' }, { name: 'icon', type: 'text', label: '图标名称' }, ]}, { name: 'partners', type: 'array', label: '合作伙伴', fields: [ { name: 'name', type: 'text', label: '名称' }, ]}, { name: 'ctaTitle', type: 'text', label: 'CTA 标题' }, { name: 'ctaDescription', type: 'textarea', label: 'CTA 描述' }, ], }, }, // === team-page === { model: { code: 'team-page', name: '团队介绍', description: '团队实力、文化氛围、数据指标', isPageType: true, urlPattern: '/team', hasVersions: true, hasDraft: true, icon: 'users', fields: [ { name: 'heroSubtitle', type: 'text', label: 'Hero 标签', required: true }, { name: 'heroTitle', type: 'textarea', label: 'Hero 主标题', required: true }, { name: 'heroDescription', type: 'textarea', label: 'Hero 描述', required: true }, { name: 'stats', type: 'array', label: '统计指标', fields: [ { name: 'value', type: 'number', label: '数值' }, { name: 'suffix', type: 'text', label: '后缀' }, { name: 'label', type: 'text', label: '标签' }, ]}, { name: 'strengths', type: 'array', label: '团队优势', fields: [ { name: 'icon', type: 'text', label: '图标名称' }, { name: 'number', type: 'text', label: '编号' }, { name: 'title', type: 'text', label: '标题' }, { name: 'description', type: 'textarea', label: '描述' }, ]}, { name: 'culture', type: 'array', label: '团队文化', fields: [ { name: 'icon', type: 'text', label: '图标名称' }, { name: 'number', type: 'text', label: '编号' }, { name: 'title', type: 'text', label: '标题' }, { name: 'description', type: 'textarea', label: '描述' }, ]}, { name: 'teamAboutTitle', type: 'text', label: '团队介绍标题' }, { name: 'ctaTitle', type: 'text', label: 'CTA 标题' }, { name: 'ctaDescription', type: 'textarea', label: 'CTA 描述' }, ], }, }, // === contact-page === { model: { code: 'contact-page', name: '联系我们', description: '联系信息、工作时间与服务承诺', isPageType: true, urlPattern: '/contact', hasVersions: true, hasDraft: true, icon: 'phone', fields: [ { name: 'heroSubtitle', type: 'text', label: 'Hero 标签', required: true }, { name: 'heroTitle', type: 'textarea', label: 'Hero 主标题', required: true }, { name: 'heroDescription', type: 'textarea', label: 'Hero 描述', required: true }, { name: 'companyName', type: 'text', label: '公司名称', required: true }, { name: 'companyEmail', type: 'text', label: '联系邮箱', required: true }, { name: 'companyAddress', type: 'text', label: '公司地址', required: true }, { name: 'workHoursWeekday', type: 'text', label: '工作日描述' }, { name: 'workHoursTime', type: 'text', label: '工作时间段' }, { name: 'promises', type: 'array', label: '服务承诺', fields: [ { name: 'text', type: 'textarea', label: '承诺内容' }, ]}, { name: 'ctaTitle', type: 'text', label: 'CTA 标题' }, { name: 'ctaDescription', type: 'textarea', label: 'CTA 描述' }, ], }, }, // === site-config === { model: { code: 'site-config', name: '站点配置', description: '公司基本信息、SEO 元数据等全局配置', isPageType: false, urlPattern: '', hasVersions: false, hasDraft: true, icon: 'settings', fields: [ { name: 'name', type: 'text', label: '公司全称', required: true }, { name: 'shortName', type: 'text', label: '公司简称', required: true }, { name: 'displayName', type: 'text', label: '展示名称', required: true }, { name: 'slogan', type: 'text', label: '品牌标语', required: true }, { name: 'description', type: 'textarea', label: '公司简介', required: true }, { name: 'founded', type: 'text', label: '成立年份' }, { name: 'location', type: 'text', label: '所在地' }, { name: 'email', type: 'text', label: '联系邮箱', required: true }, { name: 'address', type: 'text', label: '办公地址', required: true }, { name: 'icp', type: 'text', label: 'ICP 备案号' }, { name: 'police', type: 'text', label: '公安备案号' }, ], }, }, // === navigation === { model: { code: 'navigation', name: '导航菜单', description: '主导航项和下拉菜单内容', isPageType: false, urlPattern: '', hasVersions: false, hasDraft: true, icon: 'menu', fields: [ { name: 'mainNav', type: 'json', label: '主导航项', required: true }, { name: 'megaDropdown', type: 'json', label: '下拉菜单数据', required: true }, ], }, }, // === legal-page === { model: { code: 'legal-page', name: '法律页面', description: '隐私政策/服务条款页面内容配置', isPageType: false, urlPattern: '', hasVersions: false, hasDraft: true, icon: 'file-text', fields: [ { name: 'pageType', type: 'text', label: '页面类型', required: true, options: [ { label: '隐私政策', value: 'privacy' }, { label: '服务条款', value: 'terms' }, ]}, { name: 'heroTitle', type: 'text', label: '页面标题', required: true }, { name: 'heroDescription', type: 'textarea', label: '页面描述' }, { name: 'lastUpdated', type: 'text', label: '最后更新日期', required: true }, { name: 'content', type: 'richtext', label: '页面正文(HTML)', required: true, description: '隐私政策/服务条款完整正文,支持 HTML 标签' }, ], }, }, ]; for (let i = 0; i < modelConfigs.length; i++) { const config = modelConfigs[i]!; await prisma.contentModel.upsert({ where: { code: config.model.code }, update: { name: config.model.name, description: config.model.description, fields: JSON.stringify(config.model.fields), isPageType: config.model.isPageType, urlPattern: config.model.urlPattern || '', hasVersions: config.model.hasVersions, hasDraft: config.model.hasDraft, icon: config.model.icon || '', sortOrder: i, }, create: { code: config.model.code, name: config.model.name, description: config.model.description, fields: JSON.stringify(config.model.fields), isPageType: config.model.isPageType, urlPattern: config.model.urlPattern || '', hasVersions: config.model.hasVersions, hasDraft: config.model.hasDraft, icon: config.model.icon || '', sortOrder: i, }, }); console.log(` ✅ 模型: ${config.model.name} (${config.model.code})`); } // ============ 3. 导入内容数据 ============ console.log('📝 导入首页 Hero Banner...'); await seedItems('hero-banner', [ { slug: 'home', title: '首页 Hero Banner', eyebrow: '企业数字化转型', heading: '让每一家企业都拥有数据驱动的决策能力', subheading: '12 年深耕,从战略规划到系统落地,陪伴制造、零售、医疗、金融、教育、物流六大行业客户实现可衡量的业务改善。', headingTop: '四川睿新致远科技有限公司', headingBottom: '让技术成为业务增长引擎', ctaLabel: '预约咨询', ctaHref: '/contact', secondaryCtaLabel: '了解我们的方法论', secondaryCtaHref: '/services/consulting', statValue: '500+', statSubtext: '企业数字化转型实践', ctaTitleLine1: '每一次合作,', ctaTitleLine2: '真正转化为业务增长', }, ]); console.log(' ✅ 首页 Hero Banner'); console.log('📝 导入案例研究...'); await seedItems('case-study', CASE_STUDIES as unknown as Record[]); console.log(` ✅ ${CASE_STUDIES.length} 个案例`); console.log('📝 导入新闻...'); await seedItems('news', NEWS as unknown as Record[]); console.log(` ✅ ${NEWS.length} 条新闻`); console.log('📝 导入服务...'); const homeServiceFields: Record = { consulting: { subtitle: '战略咨询', desc: '数字化转型战略规划与落地路径设计,让技术投资真正驱动业务增长。从愿景制定到执行落地,陪伴企业穿越转型周期。', highlights: ['数字化成熟度评估', '转型路线图设计', '技术选型评估', '组织变革管理'], metrics: [ { value: '50+', label: '咨询项目' }, { value: '90%+', label: '方案落地率' }, ], href: '/services/consulting', }, software: { subtitle: '企业软件', desc: 'ERP、CRM、BI 等核心系统的评估、实施与定制化开发,基于行业最佳实践打造适配企业实际的数字化底座。', highlights: ['ERP 实施优化', 'CRM 客户管理', 'BI 商业智能', '系统集成'], metrics: [ { value: '95%+', label: '准时交付率' }, { value: '<4h', label: '平均响应' }, ], href: '/services/software', }, data: { subtitle: '技术服务', desc: '系统集成、数据中台、云原生架构设计与技术外包服务,以工程化能力保障系统的稳定性、可扩展性与持续迭代。', highlights: ['数据中台建设', '云原生迁移', '研发效能提升', '7x24 运维'], metrics: [ { value: '20+', label: '数据源对接' }, { value: '99.9%', label: '系统可用率' }, ], href: '/services/data', }, solutions: { subtitle: 'AI 赋能', desc: 'AI 成熟度评估、场景落地与大模型应用开发,帮助企业找到 AI 与业务的最佳结合点,实现智能化升级。', highlights: ['AI 战略规划', '大模型应用开发', '智能流程自动化', 'AI 模型训练'], metrics: [ { value: '30+', label: 'AI 场景落地' }, { value: '85%', label: '平均效率提升' }, ], href: '/services/solutions', }, }; const servicesForSeed = SERVICES.map((s) => ({ ...s, ...homeServiceFields[s.id], })); await seedItems('service', servicesForSeed as unknown as Record[]); console.log(` ✅ ${SERVICES.length} 个服务`); console.log('📝 导入产品...'); await seedItems('product', PRODUCTS as unknown as Record[]); console.log(` ✅ ${PRODUCTS.length} 个产品`); console.log('📝 导入独立产品...'); await seedItems('standalone-product', STANDALONE_PRODUCTS as unknown as Record[]); console.log(` ✅ ${STANDALONE_PRODUCTS.length} 个独立产品`); console.log('📝 导入解决方案...'); await seedItems('solution', SOLUTIONS as unknown as Record[]); console.log(` ✅ ${SOLUTIONS.length} 个解决方案`); // 数据指标需要特殊处理 console.log('📝 导入数据指标...'); const statList = Array.isArray(STATS) ? STATS : (STATS as { stats?: unknown[] }).stats || []; const statModelId = await getModelId('stat-item'); for (let i = 0; i < statList.length; i++) { const s = statList[i] as Record; const slug = `stat-${i}`; const title = String(s.label || `指标 ${i + 1}`); const { id: _id, ...data } = s; await prisma.contentItem.upsert({ where: { modelCode_slug_locale: { modelCode: 'stat-item', slug, locale: 'zh-CN' } }, update: { title, data: JSON.stringify({ ...data, accentColor: s.color }), sortOrder: i, status: 'published', publishedAt: new Date(), }, create: { modelId: statModelId, modelCode: 'stat-item', title, slug, data: JSON.stringify({ ...data, accentColor: s.color }), sortOrder: i, status: 'published', publishedAt: new Date(), createdBy: 'system', updatedBy: 'system', }, }); } console.log(` ✅ ${statList.length} 个数据指标`); // ============ 4. 导入页面内容 ============ console.log('📝 导入关于页面...'); await seedItems('about-page', [ { slug: 'default', title: '关于我们', heroSubtitle: '关于我们', heroTitle: '12 年深耕\n500+ 企业\n的转型伙伴', heroDescription: '我们不把项目完成当作终点。您的业务增长了吗?您的团队能力提升了吗?\n这才是我们真正在意的事。', heroCtaText: '预约咨询', heroCtaLink: '/contact', heroSecondaryCtaText: '了解服务', heroSecondaryCtaLink: '/services', whoWeAreTitle: '我们是谁', whoWeAreDescription: '我们坚持对行业趋势的深度研究,不追逐昙花一现的概念。每一次方案,都源于对您业务场景的洞察;每一次连接,都为了让技术真正服务于您的未来。', promise: '不卖您用不上的技术,不说不懂业务的术语,不做路过就忘的一锤子买卖。', coreValues: [ { number: '01', title: '结果导向', description: '不以「项目上线」为终点,以「客户业务是否真正改善」为衡量标准。每一次交付,都追求可量化的价值。' }, { number: '02', title: '长期主义', description: '不追逐风口,只做真正为客户创造价值的事。您的下一次难题,还愿意第一个想到我们——这才是我们追求的成功。' }, { number: '03', title: '技术驱动', description: '用扎实的工程能力和行业经验赢得信任。技术不是炫技的工具,而是解决真实问题的手段。' }, ], milestones: [ { year: '2014', title: '团队启航', description: '核心团队始于大型企业数字化转型项目,深耕 ERP、CRM 实施与定制开发。', highlight: '服务首批 20+ 企业客户' }, { year: '2018', title: '业务扩展', description: '从单一实施服务向全链路咨询转型,建立战略咨询 + 技术落地的双轮驱动模式。', highlight: '客户突破 100 家' }, { year: '2021', title: '产品化起步', description: '开始自研产品矩阵,从项目制向「产品+服务」双模式升级。', highlight: '3 款自研产品上线' }, { year: '2023', title: '行业深耕', description: '聚焦制造、零售、医疗三大核心行业,建立行业解决方案库与最佳实践沉淀。', highlight: '客户续约率 95%+' }, { year: '2026', title: '睿新致远成立', description: '四川睿新致远科技有限公司在成都正式成立,以全新品牌开启下一段征程。', highlight: '全新启航,步履不停' }, ], keyMetrics: [ { value: '500+', label: '服务企业', sub: '六大行业覆盖' }, { value: '200+', label: '专业顾问', sub: '平均行业经验 8 年' }, { value: '98%', label: '客户满意度', sub: '97% 续约率' }, { value: '12年', label: '行业深耕', sub: 'since 2014' }, ], certifications: [ { name: 'ISO 27001', description: '信息安全管理体系认证', icon: 'Shield' }, { name: 'ISO 9001', description: '质量管理体系认证', icon: 'Award' }, { name: 'CMMI 3级', description: '软件能力成熟度认证', icon: 'Zap' }, { name: '高新技术企业', description: '国家高新技术企业认定', icon: 'Trophy' }, ], partners: [ 'SAP', 'Oracle', 'Salesforce', 'Microsoft', '阿里云', '腾讯云', '华为云', '金蝶', ], ctaTitle: '准备好开始了吗?', ctaDescription: '无论您是想了解合作机会,还是希望深入探讨具体方案,都欢迎随时联系。', }, ]); console.log(' ✅ 关于页面'); console.log('📝 导入团队页面...'); await seedItems('team-page', [ { slug: 'default', title: '团队介绍', heroSubtitle: '核心团队', heroTitle: '既懂技术又懂业务的\n复合型团队', heroDescription: '我们的成员不只是写代码的工程师——我们是能理解您业务场景、能和您一起想清楚问题的合作伙伴。', heroPrimaryCtaLabel: '加入我们', heroPrimaryCtaHref: '/contact', heroSecondaryCtaLabel: '了解公司', heroSecondaryCtaHref: '/about', stats: [ { value: 12, suffix: '+', label: '年行业经验' }, { value: 10, suffix: '+', label: '核心成员' }, { value: 5, suffix: '+', label: '行业覆盖' }, ], strengths: [ { iconName: 'Shield', number: '01', title: '12 年+ 行业深耕', description: '核心团队长期从事技术咨询、企业数字化等领域,服务覆盖金融、制造、零售、政务、农业等多个行业。' }, { iconName: 'Building2', number: '02', title: '大型 IT 企业背景', description: '开发团队成员来自多个大型传统 IT 企业,具备扎实的工程能力、规范化的交付流程和严格的质量意识。' }, { iconName: 'Users', number: '03', title: '复合型技术团队', description: '既懂技术又懂业务,能够深入理解客户的真实场景和痛点,提供真正可落地的解决方案。' }, { iconName: 'Code', number: '04', title: '全栈技术能力', description: '从前端到后端、从云原生到数据智能、从移动端到物联网——应对各种复杂技术挑战。' }, { iconName: 'Target', number: '05', title: '结果导向交付', description: '不以"项目上线"为终点,以"客户业务是否真正改善"为衡量标准。每一个交付成果都追求可量化的业务价值。' }, ], culture: [ { iconName: 'Layers', number: '01', title: '扁平化协作', description: '没有冗长的汇报链条,每个人都有机会直接参与决策。信息透明,沟通高效。' }, { iconName: 'BookOpen', number: '02', title: '持续学习', description: '技术日新月异,我们保持对新技术的好奇。内部分享、技术沙龙、外部培训——学习是日常的一部分。' }, { iconName: 'Sparkles', number: '03', title: '客户成功', description: '我们的成就感来自客户的成功。客户的业务增长,就是我们最好的成绩单。' }, ], aboutTitle: '关于我们的团队', aboutParagraphs: [ { text: '我们的核心团队长期从事技术咨询、企业数字化等行业,拥有 12 年以上的深厚积累。' }, { text: '开发团队成员来自于多个大型传统 IT 企业,具备扎实的工程能力和规范化的交付经验。' }, { text: '我们相信,优秀的技术咨询不仅需要过硬的技术能力,更需要深入理解客户的业务场景和真实需求。每一位成员都是既懂技术又懂业务的复合型人才。' }, ], ctaTitle: '想成为我们的一员?', ctaDescription: '我们始终在寻找既懂技术又热爱业务的伙伴。如果您认同我们的理念,欢迎聊聊。', ctaPrimaryLabel: '联系我们', ctaPrimaryHref: '/contact', ctaSecondaryLabel: '了解公司', ctaSecondaryHref: '/about', }, ]); console.log(' ✅ 团队页面'); console.log('📝 导入联系页面...'); await seedItems('contact-page', [ { slug: 'default', title: '联系我们', heroSubtitle: '联系我们', heroTitle: '随时欢迎\n聊一聊', heroDescription: '工作日 2 小时内快速响应,首次咨询免费。\n没有销售压力,只是坐下来把问题理清楚。', email: 'contact@novalon.cn', address: '中国四川省成都市龙泉驿区幸福路12号', commitmentItems: [ '工作日 2 小时内快速响应您的咨询', '提供免费的业务咨询和方案评估服务', '根据您的需求量身定制最优解决方案', ], contactTitle: '联系方式', emailLabel: '邮箱', addressLabel: '地址', workHoursTitle: '工作时间', dayLabel: '周一至周五', hours: '9:00 - 18:00', commitmentTitle: '服务承诺', formTitle: '发送消息', submitLabel: '发送消息', submittingLabel: '发送中…', successTitle: '消息已发送', successMessage: '感谢您的留言,我们会尽快与您联系。', ctaSubtitle: '更直接的方式', ctaTitle: '还是想直接聊?', ctaDescription: '表单填起来太麻烦?直接发邮件到 contact@novalon.cn,我们同样会快速回复。', ctaPrimaryLabel: '发送邮件', ctaPrimaryHref: 'mailto:contact@novalon.cn', ctaSecondaryLabel: '返回首页', ctaSecondaryHref: '/', }, ]); console.log(' ✅ 联系页面'); console.log('📝 导入法律页面...'); await seedItems('legal-page', [ { slug: 'privacy', title: '隐私政策', pageType: 'privacy', heroTitle: '隐私政策', heroDescription: '我们重视您的隐私,致力于保护您的个人信息安全', lastUpdated: '2026-02-26', content: PRIVACY_POLICY_HTML, }, { slug: 'terms', title: '服务条款', pageType: 'terms', heroTitle: '服务条款', heroDescription: '请仔细阅读以下服务条款,使用我们的服务即表示您同意这些条款', lastUpdated: '2026-02-26', content: TERMS_OF_SERVICE_HTML, }, ]); console.log(' ✅ 法律页面'); console.log('📝 导入站点配置...'); await seedItems('site-config', [ { slug: 'default', title: '站点配置', name: COMPANY_INFO.name, shortName: COMPANY_INFO.shortName, displayName: COMPANY_INFO.displayName, slogan: COMPANY_INFO.slogan, description: COMPANY_INFO.description, founded: COMPANY_INFO.founded, location: COMPANY_INFO.location, email: COMPANY_INFO.email, address: COMPANY_INFO.address, icp: COMPANY_INFO.icp, police: COMPANY_INFO.police, }, ]); console.log(' ✅ 站点配置'); console.log('📝 导入导航菜单...'); await seedItems('navigation', [ { slug: 'default', title: '导航菜单', mainNav: NAVIGATION_V2, megaDropdown: MEGA_DROPDOWN_DATA, }, ]); console.log(' ✅ 导航菜单'); // ============ 5. 创建默认内容区域 ============ console.log('📝 创建默认内容区域...'); await seedHomeZones(); console.log(' ✅ 首页内容区域创建完成'); // ============ 统计 ============ const itemCount = await prisma.contentItem.count(); const modelCount = await prisma.contentModel.count(); const zoneCount = await prisma.contentZone.count(); console.log('\n🎉 数据库初始化完成!'); console.log(` 📊 内容模型: ${modelCount}`); console.log(` 📄 内容条目: ${itemCount}`); console.log(` 🗂️ 内容区域: ${zoneCount}`); console.log(` 👤 管理员: admin / admin123`); } main() .catch((e) => { console.error('❌ 种子数据初始化失败:', e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });