Files
code-utils/init.sql

212 lines
13 KiB
MySQL
Raw Normal View History

2026-08-14 07:52:01 +08:00
-- ============================================================
-- 年糕崽崽项目管理PMS同步服务初始化脚本MySQL 5.7+ / 8.x
-- 用法mysql -u root -p < init.sql
2026-08-14 17:54:06 +08:00
-- 应用与前端不执行任何建表/迁移DDL使用同步功能前必须先执行本脚本
2026-08-14 07:52:01 +08:00
-- 应用连接账号只需要对 code_count 库的 SELECT/INSERT/UPDATE 权限。
-- 默认账号liqi / qiqi991012bcrypt 哈希存储,可在应用内注册新账号)
-- ============================================================
CREATE DATABASE IF NOT EXISTS code_count DEFAULT CHARSET utf8mb4;
USE code_count;
-- 应用账号(密码为 bcrypt 哈希)
CREATE TABLE IF NOT EXISTS users(
2026-08-14 17:54:06 +08:00
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID',
username VARCHAR(64) NOT NULL UNIQUE COMMENT '登录名',
password_hash VARCHAR(100) NOT NULL COMMENT 'bcrypt 密码哈希',
created_at VARCHAR(32) NOT NULL COMMENT '注册时间RFC3339'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用账号';
2026-08-14 07:52:01 +08:00
-- Todo 同步表(按 user_id 隔离LWW 以 updated_at 判定)
-- history 为生命周期轨迹 JSON[{"status":"open","at":"..."},...],记录每次进入某状态的时间
-- team_id>0 表示该条已共享给对应团队团队管理员可见0 为私密
CREATE TABLE IF NOT EXISTS sync_todos(
2026-08-14 17:54:06 +08:00
user_id BIGINT NOT NULL COMMENT '所属用户ID',
uuid CHAR(36) NOT NULL COMMENT '客户端生成的全局唯一ID',
title TEXT NOT NULL COMMENT '标题',
content MEDIUMTEXT NOT NULL COMMENT '正文Markdown可含内嵌图片',
project_name VARCHAR(255) NOT NULL DEFAULT '' COMMENT '关联项目名(展示用)',
due_at VARCHAR(32) NOT NULL DEFAULT '' COMMENT '截止时间',
priority VARCHAR(16) NOT NULL DEFAULT 'medium' COMMENT '优先级low/medium/high',
status VARCHAR(16) NOT NULL DEFAULT 'open' COMMENT '状态open/doing/done/cancelled',
history MEDIUMTEXT NOT NULL COMMENT '生命周期轨迹 JSON',
team_id BIGINT NOT NULL DEFAULT 0 COMMENT '共享团队ID0=私密',
created_at VARCHAR(32) NOT NULL DEFAULT '' COMMENT '创建时间',
updated_at VARCHAR(32) NOT NULL COMMENT '最后更新时间LWW',
deleted TINYINT NOT NULL DEFAULT 0 COMMENT '软删除标记1=已删',
2026-08-14 07:52:01 +08:00
PRIMARY KEY(user_id, uuid),
KEY idx_sync_todos_updated(user_id, updated_at),
KEY idx_sync_todos_team(team_id)
2026-08-14 17:54:06 +08:00
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='待办同步表';
2026-08-14 07:52:01 +08:00
-- 工单同步表
CREATE TABLE IF NOT EXISTS sync_tickets(
2026-08-14 17:54:06 +08:00
user_id BIGINT NOT NULL COMMENT '所属用户ID',
uuid CHAR(36) NOT NULL COMMENT '客户端生成的全局唯一ID',
title TEXT NOT NULL COMMENT '标题',
description MEDIUMTEXT NOT NULL COMMENT '描述Markdown',
type VARCHAR(16) NOT NULL DEFAULT 'task' COMMENT '类型task/bug/feature 等',
project_name VARCHAR(255) NOT NULL DEFAULT '' COMMENT '关联项目名',
start_at VARCHAR(32) NOT NULL DEFAULT '' COMMENT '开始时间',
due_at VARCHAR(32) NOT NULL DEFAULT '' COMMENT '截止时间',
status VARCHAR(16) NOT NULL DEFAULT 'open' COMMENT '状态',
priority VARCHAR(16) NOT NULL DEFAULT 'medium' COMMENT '优先级',
history MEDIUMTEXT NOT NULL COMMENT '生命周期轨迹 JSON',
team_id BIGINT NOT NULL DEFAULT 0 COMMENT '共享团队ID0=私密',
created_at VARCHAR(32) NOT NULL DEFAULT '' COMMENT '创建时间',
updated_at VARCHAR(32) NOT NULL COMMENT '最后更新时间LWW',
deleted TINYINT NOT NULL DEFAULT 0 COMMENT '软删除标记',
2026-08-14 07:52:01 +08:00
PRIMARY KEY(user_id, uuid),
KEY idx_sync_tickets_updated(user_id, updated_at),
KEY idx_sync_tickets_team(team_id)
2026-08-14 17:54:06 +08:00
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='工单同步表';
2026-08-14 07:52:01 +08:00
-- 记事本同步表
CREATE TABLE IF NOT EXISTS sync_notes(
2026-08-14 17:54:06 +08:00
user_id BIGINT NOT NULL COMMENT '所属用户ID',
uuid CHAR(36) NOT NULL COMMENT '客户端生成的全局唯一ID',
content MEDIUMTEXT NOT NULL COMMENT '记事本正文',
updated_at VARCHAR(32) NOT NULL COMMENT '最后更新时间LWW',
deleted TINYINT NOT NULL DEFAULT 0 COMMENT '软删除标记',
2026-08-14 07:52:01 +08:00
PRIMARY KEY(user_id, uuid),
KEY idx_sync_notes_updated(user_id, updated_at)
2026-08-14 17:54:06 +08:00
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='记事本同步表';
2026-08-14 07:52:01 +08:00
-- 按用户存储的同步设置(如加密盐 enc_salt、加密后的 AI API Key api_keys
-- api_keys 的值为 AES-256-GCM 密文(密钥由登录密码派生),服务器无法解密。
-- 另有全局资源行:日历节日背景图存为 fest_img:<节日名>,统一挂在管理员账号
-- id=1名下 —— 管理员在应用内上传推送,所有账号登录后拉取展示。
CREATE TABLE IF NOT EXISTS sync_settings(
2026-08-14 17:54:06 +08:00
user_id BIGINT NOT NULL COMMENT '所属用户ID全局资源挂在管理员 id=1',
name VARCHAR(64) NOT NULL COMMENT '设置键名',
value MEDIUMTEXT NOT NULL COMMENT '设置值(明文或密文)',
updated_at VARCHAR(32) NOT NULL COMMENT '最后更新时间',
2026-08-14 07:52:01 +08:00
PRIMARY KEY(user_id, name)
2026-08-14 17:54:06 +08:00
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户同步设置键值表';
2026-08-14 07:52:01 +08:00
-- 旧版本升级:早期脚本建的 content/description 为 TEXT64KB
-- 待办/工单内容支持 Markdown 内嵌图片后需要 MEDIUMTEXT重复执行无副作用。
2026-08-14 17:54:06 +08:00
ALTER TABLE sync_todos MODIFY content MEDIUMTEXT NOT NULL COMMENT '正文Markdown可含内嵌图片';
ALTER TABLE sync_tickets MODIFY description MEDIUMTEXT NOT NULL COMMENT '描述Markdown';
2026-08-14 07:52:01 +08:00
-- 旧版本升级:补 history 生命周期列(不存在时才添加,重复执行无副作用)。
SET @sql = IF((SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='code_count' AND TABLE_NAME='sync_todos' AND COLUMN_NAME='history')=0,
2026-08-14 17:54:06 +08:00
'ALTER TABLE sync_todos ADD COLUMN history MEDIUMTEXT NOT NULL COMMENT ''生命周期轨迹 JSON'' AFTER status', 'SELECT 1');
2026-08-14 07:52:01 +08:00
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;
SET @sql = IF((SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='code_count' AND TABLE_NAME='sync_tickets' AND COLUMN_NAME='history')=0,
2026-08-14 17:54:06 +08:00
'ALTER TABLE sync_tickets ADD COLUMN history MEDIUMTEXT NOT NULL COMMENT ''生命周期轨迹 JSON'' AFTER priority', 'SELECT 1');
2026-08-14 07:52:01 +08:00
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;
-- ============================================================
-- 团队协作v2.1):资料 / 团队 / 团队任务 / 日报 / 通知
-- ============================================================
-- 用户公开资料(同服务器用户互相可见:昵称/头衔/技术栈标签/头像缩略图)
CREATE TABLE IF NOT EXISTS user_profiles(
2026-08-14 17:54:06 +08:00
user_id BIGINT PRIMARY KEY COMMENT '对应用户ID',
nickname VARCHAR(64) NOT NULL DEFAULT '' COMMENT '昵称',
title VARCHAR(64) NOT NULL DEFAULT '' COMMENT '头衔/职位',
email VARCHAR(128) NOT NULL DEFAULT '' COMMENT '公开邮箱',
bio VARCHAR(500) NOT NULL DEFAULT '' COMMENT '个人简介',
tech_tags VARCHAR(1000) NOT NULL DEFAULT '[]' COMMENT '技术栈标签 JSON 数组',
avatar_thumb MEDIUMTEXT NOT NULL COMMENT '头像缩略图dataURL 或 URL',
updated_at VARCHAR(32) NOT NULL COMMENT '最后更新时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户公开资料';
2026-08-14 07:52:01 +08:00
-- 团队digest_time日报 AI 摘要自动生成时间 HH:MM
CREATE TABLE IF NOT EXISTS teams(
2026-08-14 17:54:06 +08:00
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '团队ID',
name VARCHAR(64) NOT NULL COMMENT '团队名称',
owner_id BIGINT NOT NULL COMMENT '创建者用户ID',
digest_time VARCHAR(8) NOT NULL DEFAULT '21:00' COMMENT '日报 AI 摘要自动生成时间 HH:MM',
created_at VARCHAR(32) NOT NULL COMMENT '创建时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='团队';
2026-08-14 07:52:01 +08:00
-- 团队成员role: owner | admin | member
CREATE TABLE IF NOT EXISTS team_members(
2026-08-14 17:54:06 +08:00
team_id BIGINT NOT NULL COMMENT '团队ID',
user_id BIGINT NOT NULL COMMENT '成员用户ID',
role VARCHAR(16) NOT NULL DEFAULT 'member' COMMENT '角色owner/admin/member',
joined_at VARCHAR(32) NOT NULL COMMENT '加入时间',
2026-08-14 07:52:01 +08:00
PRIMARY KEY(team_id, user_id),
KEY idx_team_members_user(user_id)
2026-08-14 17:54:06 +08:00
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='团队成员';
2026-08-14 07:52:01 +08:00
-- 团队任务/工单服务器唯一真相在线操作kind: todo | ticket
CREATE TABLE IF NOT EXISTS team_tasks(
2026-08-14 17:54:06 +08:00
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '任务ID',
team_id BIGINT NOT NULL COMMENT '所属团队ID',
kind VARCHAR(16) NOT NULL DEFAULT 'todo' COMMENT '种类todo/ticket',
title TEXT NOT NULL COMMENT '标题',
description MEDIUMTEXT NOT NULL COMMENT '描述',
priority VARCHAR(16) NOT NULL DEFAULT 'medium' COMMENT '优先级',
status VARCHAR(16) NOT NULL DEFAULT 'open' COMMENT '状态',
creator_id BIGINT NOT NULL COMMENT '创建者用户ID',
assignee_id BIGINT NOT NULL DEFAULT 0 COMMENT '指派人用户ID0=未指派',
start_at VARCHAR(32) NOT NULL DEFAULT '' COMMENT '开始时间',
due_at VARCHAR(32) NOT NULL DEFAULT '' COMMENT '截止时间',
urged_at VARCHAR(32) NOT NULL DEFAULT '' COMMENT '最近催办时间',
history MEDIUMTEXT NOT NULL COMMENT '生命周期轨迹 JSON',
updated_at VARCHAR(32) NOT NULL COMMENT '最后更新时间',
deleted TINYINT NOT NULL DEFAULT 0 COMMENT '软删除标记',
2026-08-14 07:52:01 +08:00
KEY idx_team_tasks_team(team_id, deleted),
KEY idx_team_tasks_assignee(assignee_id, deleted)
2026-08-14 17:54:06 +08:00
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='团队任务/工单';
2026-08-14 07:52:01 +08:00
-- 团队日报date 为本地日期 YYYY-MM-DD
CREATE TABLE IF NOT EXISTS team_reports(
2026-08-14 17:54:06 +08:00
team_id BIGINT NOT NULL COMMENT '团队ID',
user_id BIGINT NOT NULL COMMENT '提交人用户ID',
date CHAR(10) NOT NULL COMMENT '日报日期 YYYY-MM-DD',
content MEDIUMTEXT NOT NULL COMMENT '日报正文Markdown',
submitted_at VARCHAR(32) NOT NULL COMMENT '提交/更新时间',
2026-08-14 07:52:01 +08:00
PRIMARY KEY(team_id, user_id, date)
2026-08-14 17:54:06 +08:00
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='团队日报';
2026-08-14 07:52:01 +08:00
-- 团队日报 AI 摘要(管理员客户端生成,全员可见)
CREATE TABLE IF NOT EXISTS team_digests(
2026-08-14 17:54:06 +08:00
team_id BIGINT NOT NULL COMMENT '团队ID',
date CHAR(10) NOT NULL COMMENT '摘要对应日期 YYYY-MM-DD',
content MEDIUMTEXT NOT NULL COMMENT 'AI 摘要正文Markdown',
provider VARCHAR(32) NOT NULL DEFAULT '' COMMENT '生成所用 AI 提供商',
generated_at VARCHAR(32) NOT NULL COMMENT '生成时间',
2026-08-14 07:52:01 +08:00
PRIMARY KEY(team_id, date)
2026-08-14 17:54:06 +08:00
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='团队日报 AI 摘要';
2026-08-14 07:52:01 +08:00
-- 团队通知(指派/催办/成员变动等;客户端同步时按 to_user 增量拉取转本地消息)
CREATE TABLE IF NOT EXISTS team_notices(
2026-08-14 17:54:06 +08:00
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '通知ID',
team_id BIGINT NOT NULL COMMENT '团队ID',
to_user BIGINT NOT NULL COMMENT '接收用户ID',
from_user BIGINT NOT NULL COMMENT '发送用户ID',
kind VARCHAR(16) NOT NULL COMMENT '通知类型',
ref_id VARCHAR(64) NOT NULL DEFAULT '' COMMENT '关联对象ID',
content TEXT NOT NULL COMMENT '通知正文',
created_at VARCHAR(32) NOT NULL COMMENT '创建时间',
2026-08-14 07:52:01 +08:00
KEY idx_team_notices_to(to_user, id)
2026-08-14 17:54:06 +08:00
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='团队通知';
2026-08-14 07:52:01 +08:00
-- 旧版本升级:个人待办/工单支持按条共享到团队team_id=0 私密;重复执行无副作用)。
SET @sql = IF((SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='code_count' AND TABLE_NAME='sync_todos' AND COLUMN_NAME='team_id')=0,
2026-08-14 17:54:06 +08:00
'ALTER TABLE sync_todos ADD COLUMN team_id BIGINT NOT NULL DEFAULT 0 COMMENT ''共享团队ID0=私密'' AFTER history', 'SELECT 1');
2026-08-14 07:52:01 +08:00
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;
SET @sql = IF((SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='code_count' AND TABLE_NAME='sync_tickets' AND COLUMN_NAME='team_id')=0,
2026-08-14 17:54:06 +08:00
'ALTER TABLE sync_tickets ADD COLUMN team_id BIGINT NOT NULL DEFAULT 0 COMMENT ''共享团队ID0=私密'' AFTER history', 'SELECT 1');
2026-08-14 07:52:01 +08:00
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;
SET @sql = IF((SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA='code_count' AND TABLE_NAME='sync_todos' AND INDEX_NAME='idx_sync_todos_team')=0,
'ALTER TABLE sync_todos ADD KEY idx_sync_todos_team(team_id)', 'SELECT 1');
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;
SET @sql = IF((SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA='code_count' AND TABLE_NAME='sync_tickets' AND INDEX_NAME='idx_sync_tickets_team')=0,
'ALTER TABLE sync_tickets ADD KEY idx_sync_tickets_team(team_id)', 'SELECT 1');
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;
-- 默认账号 liqi密码 qiqi991012 的 bcrypt 哈希);已存在则跳过,不会覆盖改过的密码
INSERT IGNORE INTO users(username, password_hash, created_at)
VALUES ('liqi', '$2a$10$XWBtGPu9xYRyr8diFEfvBeEHRkO6pa3CDduE09OurJztuXVcJZOB2', '2026-08-11T13:20:00Z');