Files
aiameiba_com_new/src/database/migrate.js
T

316 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const { getDb, closeDb } = require('../config/database');
const createTables = () => {
const db = getDb();
// Entity表 - 知识实体表(P1-01增加entity_type,P1-02增加status/public_flag)
db.exec(`
CREATE TABLE IF NOT EXISTS entities (
entity_id VARCHAR(36) PRIMARY KEY,
entity_type VARCHAR(64) DEFAULT 'concept',
name TEXT NOT NULL,
definition TEXT,
description TEXT,
status VARCHAR(32) DEFAULT 'active',
public_flag BOOLEAN DEFAULT 1,
authority_level INTEGER DEFAULT 1,
metadata TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
// DirectedRelationship表 - 有向实体关系表
db.exec(`
CREATE TABLE IF NOT EXISTS directed_relationships (
rel_id VARCHAR(36) PRIMARY KEY,
source_entity_id VARCHAR(36) NOT NULL,
relation_type VARCHAR(255) NOT NULL,
target_entity_id VARCHAR(36) NOT NULL,
rel_status VARCHAR(32) DEFAULT 'active',
authority_level INTEGER DEFAULT 1,
is_public BOOLEAN DEFAULT 0,
effective_at DATETIME,
expire_at DATETIME,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (source_entity_id) REFERENCES entities(entity_id),
FOREIGN KEY (target_entity_id) REFERENCES entities(entity_id)
)
`);
// Content基础表 - 内容基础模型
db.exec(`
CREATE TABLE IF NOT EXISTS contents (
content_id VARCHAR(36) PRIMARY KEY,
title TEXT NOT NULL,
body TEXT,
content_type VARCHAR(32) NOT NULL,
publish_status VARCHAR(32) DEFAULT 'draft',
authority_level INTEGER DEFAULT 1,
version_no INTEGER DEFAULT 1,
version_note TEXT,
metadata TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
archived_at DATETIME
)
`);
// Page表 - 页面扩展(P1-03增加summary)
db.exec(`
CREATE TABLE IF NOT EXISTS pages (
page_id VARCHAR(36) PRIMARY KEY,
slug VARCHAR(255) UNIQUE,
template VARCHAR(255),
summary TEXT,
seo_title TEXT,
seo_description TEXT,
seo_keywords TEXT,
FOREIGN KEY (page_id) REFERENCES contents(content_id)
)
`);
// Article表 - 文章扩展(P1-04增加published_at)
db.exec(`
CREATE TABLE IF NOT EXISTS articles (
article_id VARCHAR(36) PRIMARY KEY,
category VARCHAR(255),
tags TEXT,
cover_image VARCHAR(1024),
author VARCHAR(255),
published_at DATETIME,
FOREIGN KEY (article_id) REFERENCES contents(content_id)
)
`);
// Case表 - 案例扩展(P0-01扩展完整案例字段)
db.exec(`
CREATE TABLE IF NOT EXISTS cases (
case_id VARCHAR(36) PRIMARY KEY,
client_name TEXT,
industry TEXT,
challenge TEXT,
solution TEXT,
result TEXT,
background TEXT,
enterprise_stage TEXT,
original_goal TEXT,
current_state TEXT,
surface_problem TEXT,
amb_judgment TEXT,
key_obstacle TEXT,
root_cause TEXT,
evolution_path TEXT,
implementation TEXT,
case_significance TEXT,
FOREIGN KEY (case_id) REFERENCES contents(content_id)
)
`);
// FAQ表 - 常见问题扩展
db.exec(`
CREATE TABLE IF NOT EXISTS faqs (
faq_id VARCHAR(36) PRIMARY KEY,
question TEXT,
answer TEXT,
sort_order INTEGER DEFAULT 0,
FOREIGN KEY (faq_id) REFERENCES contents(content_id)
)
`);
// Capability表 - 能力扩展
db.exec(`
CREATE TABLE IF NOT EXISTS capabilities (
capability_id VARCHAR(36) PRIMARY KEY,
capability_type TEXT,
features TEXT,
use_cases TEXT,
FOREIGN KEY (capability_id) REFERENCES contents(content_id)
)
`);
// Service表 - 服务扩展
db.exec(`
CREATE TABLE IF NOT EXISTS services (
service_id VARCHAR(36) PRIMARY KEY,
service_type TEXT,
pricing_model TEXT,
delivery_method TEXT,
FOREIGN KEY (service_id) REFERENCES contents(content_id)
)
`);
// EntityContentJoin表 - 实体-内容多对多关联中间表
db.exec(`
CREATE TABLE IF NOT EXISTS entity_content_joins (
join_id VARCHAR(36) PRIMARY KEY,
entity_id VARCHAR(36) NOT NULL,
content_id VARCHAR(36) NOT NULL,
join_note TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (entity_id) REFERENCES entities(entity_id),
FOREIGN KEY (content_id) REFERENCES contents(content_id)
)
`);
// 管理员账号表
db.exec(`
CREATE TABLE IF NOT EXISTS admin_users (
user_id VARCHAR(36) PRIMARY KEY,
username VARCHAR(64) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
// 前台可编辑站点配置
db.exec(`
CREATE TABLE IF NOT EXISTS site_settings (
setting_key VARCHAR(128) PRIMARY KEY,
setting_value TEXT,
setting_group VARCHAR(64) DEFAULT 'general',
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
// 内容判断引擎发布映射:复用既有 contents/articles,而非建立第二套文章系统。
db.exec(`
CREATE TABLE IF NOT EXISTS integration_publications (
publication_id VARCHAR(36) PRIMARY KEY,
content_id VARCHAR(36) NOT NULL UNIQUE,
source_system VARCHAR(64) NOT NULL,
source_task_id VARCHAR(128) NOT NULL,
source_version_id VARCHAR(128) NOT NULL,
source_version_number INTEGER NOT NULL,
site_profile VARCHAR(16) NOT NULL,
idempotency_key VARCHAR(255) NOT NULL UNIQUE,
content_hash VARCHAR(128) NOT NULL,
revision INTEGER NOT NULL DEFAULT 1,
slug VARCHAR(180) UNIQUE,
summary TEXT,
primary_keyword VARCHAR(255),
keywords_json TEXT,
source_content_type VARCHAR(64),
direction VARCHAR(255),
target_audience VARCHAR(255),
canonical_url VARCHAR(2048),
human_confirmed BOOLEAN NOT NULL DEFAULT 0,
confirmed_at DATETIME,
knowledge_refs_json TEXT,
entities_json TEXT,
questions_json TEXT,
facts_json TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
published_at DATETIME,
UNIQUE KEY uq_integration_source_task (source_system, source_task_id, site_profile),
FOREIGN KEY (content_id) REFERENCES contents(content_id)
)
`);
console.log('数据库表创建完成');
};
const migrate = () => {
try {
createTables();
seedAdminAndSettings();
console.log('数据库迁移完成');
} catch (error) {
console.error('数据库迁移失败:', error);
throw error;
}
};
const seedAdminAndSettings = () => {
const db = getDb();
const crypto = require('crypto');
const user = db.prepare('SELECT user_id FROM admin_users WHERE username = ?').get('admin');
if (!user) {
const initialAdminPassword = process.env.ADMIN_INITIAL_PASSWORD;
if (!initialAdminPassword) {
throw new Error('首次初始化管理员账号需要配置 ADMIN_INITIAL_PASSWORD');
}
const salt = crypto.randomBytes(16).toString('hex');
const hash = crypto.scryptSync(initialAdminPassword, salt, 64).toString('hex');
db.prepare(`
INSERT INTO admin_users (user_id, username, password_hash)
VALUES (?, ?, ?)
`).run(require('uuid').v4(), 'admin', `${salt}:${hash}`);
console.log('默认管理员账号已创建: admin');
}
const defaults = {
'site.name': ['阿美巴AI', 'general'],
'site.footerCopyright': ['© 2026 阿美巴AI. All rights reserved.', 'general'],
'site.footerEmail': ['ameiba0258@gmail.com', 'general'],
'site.footerPhone': ['4009080258', 'general'],
'site.footerAddress': ['四川省成都市双流区正兴街道湖畔路北段366号1栋3楼1号', 'general'],
'site.icp': ['蜀ICP备2025143754号-7', 'general'],
'home.heroTitle': ['阿美巴(Ameiba)', 'home'],
'home.heroSubtitle': ['AI时代企业进化平台', 'home'],
'home.heroDescription': ['我们帮助企业在AI时代实现系统化进化,从战略顶层设计到组织重塑,从经营增长到AI部署,提供完整的企业进化能力与服务。', 'home'],
'contact.title': ['联系我们', 'contact'],
'contact.contactTitle': ['联系方式', 'contact'],
'contact.email': ['contact@ameiba.com', 'contact'],
'contact.phone': ['待填充', 'contact'],
'contact.address': ['待填充', 'contact'],
'contact.serviceHoursTitle': ['服务时间', 'contact'],
'contact.serviceHours': ['周一至周五:9:00 - 18:00', 'contact'],
'contact.consultationTitle': ['咨询服务', 'contact'],
'contact.consultationIntro': ['我们提供以下咨询服务:', 'contact'],
'contact.consultationItems': ['企业进化诊断\n进化路径规划\n战略咨询\n组织变革咨询\nAI部署咨询', 'contact'],
'contact.cooperationTitle': ['合作方式', 'contact'],
'contact.cooperationItems': ['顾问服务\n咨询服务\n企业陪跑\n定制化服务', 'contact'],
'contact.faqTitle': ['常见问题', 'contact'],
'contact.faqText': ['如有其他问题,请查看', 'contact'],
'contact.relatedTitle': ['相关知识', 'contact'],
};
const pageDefaults = {
about: ['阿美巴是谁', '阿美巴(Ameiba)是AI时代企业进化平台,专注于帮助企业实现系统化进化。'],
evolution: ['企业进化', '企业进化是企业围绕长期发展目标持续调整、重构与升级的过程。'],
value: ['四大价值', '价值创造、价值传递、价值交付、价值支持共同构成企业经营的价值体系。'],
amb: ['A/M/B三态模型:AI时代企业进化状态识别框架', 'A/M/B模型用于帮助企业识别自身所处的进化状态,并明确下一步行动。'],
capabilities: ['企业进化能力地图', '从战略、经营、组织到AI部署,构建企业持续进化所需要的能力地图。'],
cases: ['企业进化案例', '通过真实案例,展示企业在经营环境中的目标、障碍、进化路径与实施过程。'],
knowledge: ['知识中心', '集中展示企业进化相关的知识、方法和实践内容。'],
faq: ['常见问题', '以下是关于企业进化的常见问题解答。'],
};
Object.entries(pageDefaults).forEach(([page, [title, intro]]) => {
defaults[`${page}.title`] = [title, page];
defaults[`${page}.intro`] = [intro, page];
});
const extraDefaults = {
'amb.whatTitle': ['什么是A/M/B', 'amb'], 'amb.whatNote': ['A/M/B不是产品套餐,不是收费等级,不是强制线性路径,不是所有企业必须经历的三个固定阶段。', 'amb'], 'amb.whatPurpose': ['A/M/B的作用,是帮助企业识别自身所处状态,并进一步判断当前需要完成的关键进化动作。', 'amb'], 'amb.statesTitle': ['三种状态', 'amb'], 'amb.stateA': ['A态·入态|企业开始进入AI时代企业进化的一种状态', 'amb'], 'amb.stateM': ['M态·优态|企业进一步围绕现有经营与管理体系进行优化的一种状态', 'amb'], 'amb.stateB': ['B态·越态|企业突破原有运行边界、形成新的企业运行能力的一种状态', 'amb'], 'amb.recognitionTitle': ['状态识别', 'amb'], 'amb.recognitionText': ['企业可以根据自身情况处于不同状态,也不意味着所有企业必须从A到M再到B。\n企业需要根据自身发展阶段和实际情况,判断当前所处的状态,并确定需要完成的关键进化动作。', 'amb'],
'evolution.definitionTitle': ['什么是企业进化', 'evolution'], 'evolution.definitionMore': ['增长更多体现结果层变化。进化更强调底层能力、系统与企业状态的持续调整和升级。AI是时代变量和重要赋能工具,不是企业进化本身的终点。', 'evolution'], 'evolution.whyTitle': ['为什么需要企业进化', 'evolution'], 'evolution.whyIntro': ['在AI时代,企业面临着前所未有的挑战:', 'evolution'], 'evolution.whyItems': ['技术快速迭代,传统业务模式面临冲击\n客户需求变化,个性化、智能化要求提高\n竞争环境加剧,需要更高效的运营模式\n人才结构变化,需要新的组织能力', 'evolution'],
'value.overviewTitle': ['价值体系概述', 'value'], 'value.valuesTitle': ['四大价值', 'value'], 'value.relationTitle': ['价值体系的关系', 'value'], 'value.relationText': ['四大价值相互关联、相互支撑。价值创造是基础,价值传递是桥梁,价值交付是结果,价值支持是保障。企业需要在这四个维度上协调发展,才能实现持续增长。', 'value'],
'about.positionTitle': ['定位', 'about'], 'about.positionText': ['阿美巴(Ameiba)是AI时代企业进化平台,专注于帮助企业实现系统化进化,从战略顶层设计到组织重塑,从经营增长到AI部署,提供完整的企业进化能力与服务。', 'about'], 'about.existTitle': ['为什么存在', 'about'], 'about.existText': ['在AI时代,企业面临着前所未有的挑战与机遇。传统的企业管理方法已无法适应快速变化的环境,企业需要一套系统化的进化方法,实现从传统模式向AI时代模式的转型。\n阿美巴的存在,就是为了帮助企业完成这一进化过程,实现可持续增长与发展。', 'about'], 'about.audienceTitle': ['服务对象', 'about'], 'about.audienceText': ['我们服务的对象是那些希望在AI时代实现转型与增长的企业,无论企业当前处于哪个发展阶段,我们都能提供适合的进化路径与能力支持。', 'about'], 'about.historyTitle': ['发展历程', 'about'], 'about.historyText': ['待填充', 'about'],
'capabilities.overviewTitle': ['能力概述', 'capabilities'], 'capabilities.categoryTitle': ['能力分类', 'capabilities'], 'cases.overviewTitle': ['案例概述', 'cases'], 'cases.listTitle': ['案例列表', 'cases'], 'knowledge.systemTitle': ['知识体系', 'knowledge'], 'knowledge.categoryTitle': ['知识分类', 'knowledge'], 'knowledge.articleTitle': ['最新文章', 'knowledge'], 'faq.overviewTitle': ['FAQ概述', 'faq'], 'faq.listTitle': ['问题列表', 'faq'],
};
Object.entries(extraDefaults).forEach(([key, [value, group]]) => {
defaults[key] = [value, group];
});
Object.entries(defaults).forEach(([key, [value, group]]) => {
const existing = db.prepare('SELECT setting_key FROM site_settings WHERE setting_key = ?').get(key);
if (!existing) {
db.prepare('INSERT INTO site_settings (setting_key, setting_value, setting_group) VALUES (?, ?, ?)').run(key, value, group);
}
});
// 修正早期版本中误写的 A/M-B 文案;保留管理员已编辑的其他内容。
db.prepare(`
UPDATE site_settings
SET setting_value = REPLACE(setting_value, 'A/M-B', 'A/M/B'),
updated_at = CURRENT_TIMESTAMP
WHERE setting_value LIKE '%A/M-B%'
`).run();
};
if (require.main === module) {
migrate();
}
module.exports = { migrate, createTables, seedAdminAndSettings };