Files
ylhp-ai-project-manager/docs/dev-ops/pgsql/sql/weform_run.sql
JiaoTianBo 88c9fe5e06 feat(open-api): 新增对外开放接口及项目日报同步功能
- 新增项目日报表及其防重唯一索引,支持外部系统同步日报数据
- 添加项目日报实体类及对应 Mapper 和 XML 配置
- 新增对外开放接口控制器 OpenApiController,实现项目列表查询及日报同步接口
- 实现 OpenApiService 服务及其实现类,包含用户项目查询和日报防重同步逻辑
- 扩展 ProjectMapper,支持根据用户名查询用户关联项目列表
- 配置 SaToken 过滤白名单,放行 /api/open/** 路径无登录验证
- 引入 spring-boot-starter-validation 依赖,支持请求参数校验
- 创建数据传输对象 DailyReportSyncDTO,带参数校验注解
- 日志记录和异常处理增强,保证数据同步和查询的健壮性
2026-03-31 15:45:36 +08:00

1367 lines
71 KiB
SQL
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.
-- =====================================================
-- AI项目进度与风险管控平台 - 通用版数据库设计 (PostgreSQL + pgvector)
-- 适用于各类项目的管理与追踪分析
-- 支持AI原生特性向量存储、语义搜索、RAG
-- =====================================================
-- 启用pgvector扩展
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- =====================================================
-- Spring AI PgVectorStore 向量存储表
-- 用于RAG文档向量存储和相似度搜索
-- 兼容PgVectorStore默认结构同时支持完整文档管理
-- =====================================================
DROP TABLE IF EXISTS vector_store CASCADE;
CREATE TABLE vector_store (
-- PgVectorStore 核心字段
id VARCHAR(255) PRIMARY KEY,
content TEXT,
metadata JSONB,
embedding vector(1024),
-- 关联关系
project_id BIGINT,
timeline_node_id BIGINT,
kb_id BIGINT,
-- 文档来源
source_type VARCHAR(50),
source_id BIGINT,
-- 文档扩展信息
title VARCHAR(500),
content_raw TEXT,
summary TEXT,
-- 文档元数据
doc_type VARCHAR(50),
language VARCHAR(10) DEFAULT 'zh',
file_type VARCHAR(50),
file_size BIGINT,
file_path VARCHAR(500),
file_url VARCHAR(500),
-- 时间信息 (用于时间维度检索)
doc_date DATE,
doc_datetime TIMESTAMP,
-- 分块信息(大文档分块存储)
chunk_index INT DEFAULT 0,
chunk_total INT DEFAULT 1,
chunk_parent_id VARCHAR(255),
-- 标签和分类
tags JSONB,
category VARCHAR(100),
-- 使用统计
view_count INT DEFAULT 0,
query_count INT DEFAULT 0,
last_queried_at TIMESTAMP,
-- 状态
status VARCHAR(20) DEFAULT 'active',
error_message TEXT,
-- 创建信息
create_by BIGINT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_by BIGINT,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
-- 外键约束
CONSTRAINT fk_vs_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE SET NULL,
CONSTRAINT fk_vs_timeline FOREIGN KEY (timeline_node_id) REFERENCES project_timeline(id) ON DELETE SET NULL,
CONSTRAINT fk_vs_kb FOREIGN KEY (kb_id) REFERENCES ai_knowledge_base(id) ON DELETE SET NULL,
CONSTRAINT fk_vs_create_by FOREIGN KEY (create_by) REFERENCES sys_user(id) ON DELETE SET NULL
);
-- 创建向量索引使用IVFFlat算法适合中等数据量
CREATE INDEX idx_vector_store_embedding ON vector_store
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
-- 创建其他常用索引
CREATE INDEX idx_vs_project ON vector_store(project_id) WHERE deleted = 0;
CREATE INDEX idx_vs_timeline ON vector_store(timeline_node_id) WHERE deleted = 0;
CREATE INDEX idx_vs_kb ON vector_store(kb_id) WHERE deleted = 0;
CREATE INDEX idx_vs_source ON vector_store(source_type, source_id) WHERE deleted = 0;
CREATE INDEX idx_vs_status ON vector_store(status);
CREATE INDEX idx_vs_type ON vector_store(doc_type);
CREATE INDEX idx_vs_tags ON vector_store USING GIN(tags);
CREATE INDEX idx_vs_chunk_parent ON vector_store(chunk_parent_id) WHERE chunk_parent_id IS NOT NULL;
COMMENT ON TABLE vector_store IS '向量存储表 - 用于RAG文档检索和知识库管理';
COMMENT ON COLUMN vector_store.id IS '文档ID字符串类型兼容PgVectorStore';
COMMENT ON COLUMN vector_store.content IS '文档内容文本';
COMMENT ON COLUMN vector_store.metadata IS '文档元数据JSONB格式兼容PgVectorStore';
COMMENT ON COLUMN vector_store.embedding IS '向量嵌入1024维阿里云text-embedding-v4';
COMMENT ON COLUMN vector_store.project_id IS '关联项目ID';
COMMENT ON COLUMN vector_store.timeline_node_id IS '关联时间节点ID';
COMMENT ON COLUMN vector_store.kb_id IS '关联知识库ID';
COMMENT ON COLUMN vector_store.source_type IS '来源类型: project-项目文档, risk-风险文档, ticket-工单, report-日报, upload-上传文件, knowledge-知识库, chat-对话记录';
COMMENT ON COLUMN vector_store.source_id IS '来源记录ID';
COMMENT ON COLUMN vector_store.title IS '文档标题';
COMMENT ON COLUMN vector_store.content_raw IS '原始内容(带格式)';
COMMENT ON COLUMN vector_store.summary IS 'AI生成的摘要';
COMMENT ON COLUMN vector_store.doc_type IS '文档类型: requirement-需求, design-设计, plan-计划, report-报告, contract-合同, photo-照片, other-其他';
COMMENT ON COLUMN vector_store.language IS '语言: zh-中文, en-英文';
COMMENT ON COLUMN vector_store.file_type IS '文件类型: pdf, doc, txt, md, jpg, png等';
COMMENT ON COLUMN vector_store.file_size IS '文件大小(字节)';
COMMENT ON COLUMN vector_store.file_path IS '文件存储路径';
COMMENT ON COLUMN vector_store.doc_date IS '文档日期(如日报日期、照片拍摄日期)';
COMMENT ON COLUMN vector_store.doc_datetime IS '文档时间戳';
COMMENT ON COLUMN vector_store.chunk_index IS '分块序号';
COMMENT ON COLUMN vector_store.chunk_total IS '总分块数';
COMMENT ON COLUMN vector_store.chunk_parent_id IS '父文档ID(分块时使用)';
COMMENT ON COLUMN vector_store.tags IS '标签数组';
COMMENT ON COLUMN vector_store.category IS '分类';
COMMENT ON COLUMN vector_store.view_count IS '查看次数';
COMMENT ON COLUMN vector_store.query_count IS '被检索次数';
COMMENT ON COLUMN vector_store.last_queried_at IS '最后被检索时间';
COMMENT ON COLUMN vector_store.status IS '状态: active-可用, processing-处理中, error-错误, archived-归档';
COMMENT ON COLUMN vector_store.error_message IS '错误信息';
-- 设置时区
SET timezone = 'Asia/Shanghai';
-- =====================================================
-- 1. 部门与用户相关表 (简化版:单部门,无多租户)
-- =====================================================
-- 部门表 (单部门架构,简化设计)
DROP TABLE IF EXISTS sys_department CASCADE;
CREATE TABLE sys_department (
id BIGSERIAL PRIMARY KEY,
dept_code VARCHAR(50) NOT NULL UNIQUE,
dept_name VARCHAR(100) NOT NULL,
parent_id BIGINT DEFAULT NULL,
leader_id BIGINT,
description TEXT,
sort_order INT DEFAULT 0,
status SMALLINT DEFAULT 1,
create_by BIGINT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_by BIGINT,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
CONSTRAINT fk_dept_parent FOREIGN KEY (parent_id) REFERENCES sys_department(id) ON DELETE SET NULL
);
CREATE INDEX idx_dept_parent ON sys_department(parent_id);
CREATE INDEX idx_dept_status ON sys_department(status);
COMMENT ON TABLE sys_department IS '部门表 - 单部门架构';
COMMENT ON COLUMN sys_department.dept_code IS '部门编码';
COMMENT ON COLUMN sys_department.dept_name IS '部门名称';
COMMENT ON COLUMN sys_department.parent_id IS '父级部门ID';
COMMENT ON COLUMN sys_department.leader_id IS '部门负责人ID';
COMMENT ON COLUMN sys_department.description IS '部门描述';
COMMENT ON COLUMN sys_department.sort_order IS '排序';
COMMENT ON COLUMN sys_department.status IS '状态: 1-正常, 0-禁用';
COMMENT ON COLUMN sys_department.create_by IS '创建人';
COMMENT ON COLUMN sys_department.create_time IS '创建时间';
COMMENT ON COLUMN sys_department.update_by IS '更新人';
COMMENT ON COLUMN sys_department.update_time IS '更新时间';
COMMENT ON COLUMN sys_department.deleted IS '删除标记';
-- =====================================================
-- 2. 用户与权限相关表
-- =====================================================
-- 用户表
DROP TABLE IF EXISTS sys_user CASCADE;
CREATE TABLE sys_user (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(200) NOT NULL,
real_name VARCHAR(50),
nickname VARCHAR(50),
avatar VARCHAR(500),
gender SMALLINT DEFAULT 0,
phone VARCHAR(20),
email VARCHAR(100),
dept_id BIGINT,
position VARCHAR(50),
employee_no VARCHAR(50),
entry_date DATE,
status SMALLINT DEFAULT 1,
last_login_time TIMESTAMP,
last_login_ip VARCHAR(50),
preferences JSONB,
extra_data JSONB,
create_by BIGINT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_by BIGINT,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
CONSTRAINT fk_user_dept FOREIGN KEY (dept_id) REFERENCES sys_department(id) ON DELETE SET NULL
);
CREATE INDEX idx_user_dept ON sys_user(dept_id);
CREATE INDEX idx_user_phone ON sys_user(phone);
CREATE INDEX idx_user_status ON sys_user(status);
COMMENT ON TABLE sys_user IS '用户表';
COMMENT ON COLUMN sys_user.username IS '用户名';
COMMENT ON COLUMN sys_user.password IS '密码(加密)';
COMMENT ON COLUMN sys_user.real_name IS '真实姓名';
COMMENT ON COLUMN sys_user.nickname IS '昵称';
COMMENT ON COLUMN sys_user.avatar IS '头像URL';
COMMENT ON COLUMN sys_user.gender IS '性别: 0-未知, 1-男, 2-女';
COMMENT ON COLUMN sys_user.phone IS '手机号';
COMMENT ON COLUMN sys_user.email IS '邮箱';
COMMENT ON COLUMN sys_user.dept_id IS '所属部门ID';
COMMENT ON COLUMN sys_user.position IS '职位';
COMMENT ON COLUMN sys_user.employee_no IS '工号';
COMMENT ON COLUMN sys_user.entry_date IS '入职日期';
COMMENT ON COLUMN sys_user.status IS '状态: 1-正常, 0-禁用, 2-锁定';
COMMENT ON COLUMN sys_user.last_login_time IS '最后登录时间';
COMMENT ON COLUMN sys_user.last_login_ip IS '最后登录IP';
COMMENT ON COLUMN sys_user.preferences IS '用户偏好设置';
COMMENT ON COLUMN sys_user.extra_data IS '扩展数据';
-- 角色表
DROP TABLE IF EXISTS sys_role CASCADE;
CREATE TABLE sys_role (
id BIGSERIAL PRIMARY KEY,
role_code VARCHAR(50) NOT NULL UNIQUE,
role_name VARCHAR(50) NOT NULL,
role_type VARCHAR(20) DEFAULT 'custom',
description TEXT,
data_scope SMALLINT DEFAULT 1,
sort_order INT DEFAULT 0,
status SMALLINT DEFAULT 1,
create_by BIGINT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_by BIGINT,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0
);
COMMENT ON TABLE sys_role IS '角色表';
COMMENT ON COLUMN sys_role.role_code IS '角色编码';
COMMENT ON COLUMN sys_role.role_name IS '角色名称';
COMMENT ON COLUMN sys_role.role_type IS '角色类型: system-系统角色, custom-自定义角色';
COMMENT ON COLUMN sys_role.description IS '角色描述';
COMMENT ON COLUMN sys_role.data_scope IS '数据权限: 1-全部, 2-本部门, 3-本人';
COMMENT ON COLUMN sys_role.sort_order IS '排序';
COMMENT ON COLUMN sys_role.status IS '状态: 1-正常, 0-禁用';
-- 用户角色关联表
DROP TABLE IF EXISTS sys_user_role CASCADE;
CREATE TABLE sys_user_role (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
role_id BIGINT NOT NULL,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(user_id, role_id),
CONSTRAINT fk_ur_user FOREIGN KEY (user_id) REFERENCES sys_user(id) ON DELETE CASCADE,
CONSTRAINT fk_ur_role FOREIGN KEY (role_id) REFERENCES sys_role(id) ON DELETE CASCADE
);
CREATE INDEX idx_ur_role ON sys_user_role(role_id);
COMMENT ON TABLE sys_user_role IS '用户角色关联表';
COMMENT ON COLUMN sys_user_role.user_id IS '用户ID';
COMMENT ON COLUMN sys_user_role.role_id IS '角色ID';
-- 权限表(菜单/功能权限)
DROP TABLE IF EXISTS sys_permission CASCADE;
CREATE TABLE sys_permission (
id BIGSERIAL PRIMARY KEY,
parent_id BIGINT DEFAULT NULL,
permission_code VARCHAR(100) NOT NULL UNIQUE,
permission_name VARCHAR(50) NOT NULL,
permission_type SMALLINT DEFAULT 1,
path VARCHAR(200),
component VARCHAR(200),
icon VARCHAR(50),
api_url VARCHAR(200),
api_method VARCHAR(10),
sort_order INT DEFAULT 0,
visible SMALLINT DEFAULT 1,
status SMALLINT DEFAULT 1,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
CONSTRAINT fk_perm_parent FOREIGN KEY (parent_id) REFERENCES sys_permission(id) ON DELETE SET NULL
);
CREATE INDEX idx_perm_parent ON sys_permission(parent_id);
COMMENT ON TABLE sys_permission IS '权限表';
COMMENT ON COLUMN sys_permission.parent_id IS '父级权限ID';
COMMENT ON COLUMN sys_permission.permission_code IS '权限编码';
COMMENT ON COLUMN sys_permission.permission_name IS '权限名称';
COMMENT ON COLUMN sys_permission.permission_type IS '权限类型: 1-菜单, 2-按钮, 3-接口';
COMMENT ON COLUMN sys_permission.path IS '路由路径';
COMMENT ON COLUMN sys_permission.component IS '组件路径';
COMMENT ON COLUMN sys_permission.icon IS '图标';
COMMENT ON COLUMN sys_permission.api_url IS '接口URL';
COMMENT ON COLUMN sys_permission.api_method IS '接口方法';
COMMENT ON COLUMN sys_permission.sort_order IS '排序';
COMMENT ON COLUMN sys_permission.visible IS '是否可见: 1-是, 0-否';
COMMENT ON COLUMN sys_permission.status IS '状态: 1-正常, 0-禁用';
-- 角色权限关联表
DROP TABLE IF EXISTS sys_role_permission CASCADE;
CREATE TABLE sys_role_permission (
id BIGSERIAL PRIMARY KEY,
role_id BIGINT NOT NULL,
permission_id BIGINT NOT NULL,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(role_id, permission_id),
CONSTRAINT fk_rp_role FOREIGN KEY (role_id) REFERENCES sys_role(id) ON DELETE CASCADE,
CONSTRAINT fk_rp_perm FOREIGN KEY (permission_id) REFERENCES sys_permission(id) ON DELETE CASCADE
);
COMMENT ON TABLE sys_role_permission IS '角色权限关联表';
COMMENT ON COLUMN sys_role_permission.role_id IS '角色ID';
COMMENT ON COLUMN sys_role_permission.permission_id IS '权限ID';
-- =====================================================
-- 3. 项目管理核心表
-- =====================================================
-- 项目表
DROP TABLE IF EXISTS project CASCADE;
CREATE TABLE project (
id BIGSERIAL PRIMARY KEY,
project_code VARCHAR(50) NOT NULL UNIQUE,
project_name VARCHAR(200) NOT NULL,
project_type VARCHAR(50),
description TEXT,
objectives TEXT,
manager_id BIGINT,
sponsor_id BIGINT,
plan_start_date DATE,
plan_end_date DATE,
actual_start_date DATE,
actual_end_date DATE,
budget DECIMAL(18,2) DEFAULT 0,
cost DECIMAL(18,2) DEFAULT 0,
currency VARCHAR(10) DEFAULT 'CNY',
progress INT DEFAULT 0,
status VARCHAR(20) DEFAULT 'draft',
priority VARCHAR(20) DEFAULT 'medium',
risk_level VARCHAR(20) DEFAULT 'low',
visibility SMALLINT DEFAULT 1,
tags JSONB,
extra_data JSONB,
create_by BIGINT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_by BIGINT,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
CONSTRAINT fk_project_manager FOREIGN KEY (manager_id) REFERENCES sys_user(id) ON DELETE SET NULL
);
CREATE INDEX idx_project_manager ON project(manager_id);
CREATE INDEX idx_project_status ON project(status);
CREATE INDEX idx_project_risk_level ON project(risk_level);
COMMENT ON TABLE project IS '项目表';
COMMENT ON COLUMN project.project_code IS '项目编号';
COMMENT ON COLUMN project.project_name IS '项目名称';
COMMENT ON COLUMN project.project_type IS '项目类型(如: 研发项目, 工程项目, 运营项目)';
COMMENT ON COLUMN project.description IS '项目描述';
COMMENT ON COLUMN project.objectives IS '项目目标';
COMMENT ON COLUMN project.manager_id IS '项目经理ID';
COMMENT ON COLUMN project.sponsor_id IS '项目发起人ID';
COMMENT ON COLUMN project.plan_start_date IS '计划开始日期';
COMMENT ON COLUMN project.plan_end_date IS '计划结束日期';
COMMENT ON COLUMN project.actual_start_date IS '实际开始日期';
COMMENT ON COLUMN project.actual_end_date IS '实际结束日期';
COMMENT ON COLUMN project.budget IS '项目预算';
COMMENT ON COLUMN project.cost IS '已花费金额';
COMMENT ON COLUMN project.currency IS '币种';
COMMENT ON COLUMN project.progress IS '进度百分比';
COMMENT ON COLUMN project.status IS '状态: draft-草稿, planning-规划中, ongoing-进行中, paused-暂停, completed-已完成, cancelled-已取消';
COMMENT ON COLUMN project.priority IS '优先级: critical-关键, high-高, medium-中, low-低';
COMMENT ON COLUMN project.risk_level IS '风险等级: high-高, medium-中, low-低';
COMMENT ON COLUMN project.visibility IS '可见性: 1-公开, 2-部门内, 3-项目成员';
COMMENT ON COLUMN project.tags IS '标签列表';
COMMENT ON COLUMN project.extra_data IS '扩展数据(用于存储行业特定字段)';
-- 项目初始化记录表 (记录AI解析项目文档的过程)
DROP TABLE IF EXISTS project_init_record CASCADE;
CREATE TABLE project_init_record (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL,
-- 输入信息
input_files JSONB,
input_text TEXT,
-- 解析结果
parse_status VARCHAR(20) DEFAULT 'pending',
parse_result JSONB,
-- 生成的数据统计
generated_milestones INT DEFAULT 0,
generated_tasks INT DEFAULT 0,
generated_members INT DEFAULT 0,
generated_resources INT DEFAULT 0,
-- AI信息
model VARCHAR(50),
tokens_used INT,
-- 错误信息
error_message TEXT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_init_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE CASCADE
);
CREATE INDEX idx_init_project ON project_init_record(project_id);
COMMENT ON TABLE project_init_record IS '项目初始化记录表 - 记录AI解析项目文档生成项目结构的过程';
COMMENT ON COLUMN project_init_record.project_id IS '项目ID';
COMMENT ON COLUMN project_init_record.input_files IS '上传的文件列表[{name, path, type, size}]';
COMMENT ON COLUMN project_init_record.input_text IS '用户输入的项目描述';
COMMENT ON COLUMN project_init_record.parse_status IS '状态: pending-待解析, processing-解析中, completed-已完成, failed-失败';
COMMENT ON COLUMN project_init_record.parse_result IS '解析结果(结构化数据)';
COMMENT ON COLUMN project_init_record.generated_milestones IS '生成的里程碑数量';
COMMENT ON COLUMN project_init_record.generated_tasks IS '生成的任务数量';
COMMENT ON COLUMN project_init_record.generated_members IS '生成的成员数量';
COMMENT ON COLUMN project_init_record.generated_resources IS '生成的资源数量';
-- 项目成员表
DROP TABLE IF EXISTS project_member CASCADE;
CREATE TABLE project_member (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
role_code VARCHAR(50) DEFAULT 'member',
join_date DATE,
leave_date DATE,
responsibility TEXT,
weekly_hours DECIMAL(5,1),
status SMALLINT DEFAULT 1,
create_by BIGINT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
UNIQUE(project_id, user_id),
CONSTRAINT fk_pm_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE CASCADE,
CONSTRAINT fk_pm_user FOREIGN KEY (user_id) REFERENCES sys_user(id) ON DELETE CASCADE
);
CREATE INDEX idx_pm_user ON project_member(user_id);
COMMENT ON TABLE project_member IS '项目成员表';
COMMENT ON COLUMN project_member.project_id IS '项目ID';
COMMENT ON COLUMN project_member.user_id IS '用户ID';
COMMENT ON COLUMN project_member.role_code IS '项目角色: manager-项目经理, leader-负责人, member-成员, observer-观察者';
COMMENT ON COLUMN project_member.join_date IS '加入日期';
COMMENT ON COLUMN project_member.leave_date IS '离开日期';
COMMENT ON COLUMN project_member.responsibility IS '职责描述';
COMMENT ON COLUMN project_member.weekly_hours IS '每周投入小时数';
COMMENT ON COLUMN project_member.status IS '状态: 1-正常, 0-已移除';
-- 项目阶段/里程碑表
DROP TABLE IF EXISTS project_milestone CASCADE;
CREATE TABLE project_milestone (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL,
milestone_name VARCHAR(200) NOT NULL,
description TEXT,
plan_date DATE,
actual_date DATE,
status VARCHAR(20) DEFAULT 'pending',
progress INT DEFAULT 0,
sort_order INT DEFAULT 0,
is_key SMALLINT DEFAULT 0,
deliverables JSONB,
extra_data JSONB,
create_by BIGINT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_by BIGINT,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
CONSTRAINT fk_milestone_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE CASCADE
);
CREATE INDEX idx_milestone_project ON project_milestone(project_id);
CREATE INDEX idx_milestone_status ON project_milestone(status);
COMMENT ON TABLE project_milestone IS '项目里程碑表';
COMMENT ON COLUMN project_milestone.project_id IS '项目ID';
COMMENT ON COLUMN project_milestone.milestone_name IS '里程碑名称';
COMMENT ON COLUMN project_milestone.description IS '描述';
COMMENT ON COLUMN project_milestone.plan_date IS '计划日期';
COMMENT ON COLUMN project_milestone.actual_date IS '实际日期';
COMMENT ON COLUMN project_milestone.status IS '状态: pending-待开始, in_progress-进行中, completed-已完成, delayed-延期';
COMMENT ON COLUMN project_milestone.progress IS '完成进度';
COMMENT ON COLUMN project_milestone.sort_order IS '排序';
COMMENT ON COLUMN project_milestone.is_key IS '是否关键里程碑: 1-是, 0-否';
COMMENT ON COLUMN project_milestone.deliverables IS '交付物列表';
COMMENT ON COLUMN project_milestone.extra_data IS '扩展数据';
-- =====================================================
-- 4. 任务管理表
-- =====================================================
-- 任务表
DROP TABLE IF EXISTS task CASCADE;
CREATE TABLE task (
id BIGSERIAL PRIMARY KEY,
task_code VARCHAR(50),
project_id BIGINT NOT NULL,
milestone_id BIGINT,
task_name VARCHAR(200) NOT NULL,
description TEXT,
task_type VARCHAR(50),
assignee_id BIGINT,
plan_start_date DATE,
plan_end_date DATE,
actual_start_date DATE,
actual_end_date DATE,
plan_hours DECIMAL(8,2),
actual_hours DECIMAL(8,2),
progress INT DEFAULT 0,
priority VARCHAR(20) DEFAULT 'medium',
status VARCHAR(20) DEFAULT 'pending',
sort_order INT DEFAULT 0,
tags JSONB,
attachments JSONB,
extra_data JSONB,
create_by BIGINT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_by BIGINT,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
CONSTRAINT fk_task_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE CASCADE,
CONSTRAINT fk_task_milestone FOREIGN KEY (milestone_id) REFERENCES project_milestone(id) ON DELETE SET NULL,
CONSTRAINT fk_task_assignee FOREIGN KEY (assignee_id) REFERENCES sys_user(id) ON DELETE SET NULL
);
CREATE INDEX idx_task_project ON task(project_id);
CREATE INDEX idx_task_milestone ON task(milestone_id);
CREATE INDEX idx_task_assignee ON task(assignee_id);
CREATE INDEX idx_task_status ON task(status);
COMMENT ON TABLE task IS '任务表';
COMMENT ON COLUMN task.task_code IS '任务编号';
COMMENT ON COLUMN task.project_id IS '项目ID';
COMMENT ON COLUMN task.milestone_id IS '所属里程碑ID';
COMMENT ON COLUMN task.task_name IS '任务名称';
COMMENT ON COLUMN task.description IS '任务描述';
COMMENT ON COLUMN task.task_type IS '任务类型';
COMMENT ON COLUMN task.assignee_id IS '执行人ID';
COMMENT ON COLUMN task.plan_start_date IS '计划开始日期';
COMMENT ON COLUMN task.plan_end_date IS '计划结束日期';
COMMENT ON COLUMN task.actual_start_date IS '实际开始日期';
COMMENT ON COLUMN task.actual_end_date IS '实际结束日期';
COMMENT ON COLUMN task.plan_hours IS '计划工时(小时)';
COMMENT ON COLUMN task.actual_hours IS '实际工时(小时)';
COMMENT ON COLUMN task.progress IS '进度百分比';
COMMENT ON COLUMN task.priority IS '优先级: critical-关键, high-高, medium-中, low-低';
COMMENT ON COLUMN task.status IS '状态: pending-待开始, in_progress-进行中, completed-已完成, cancelled-已取消';
COMMENT ON COLUMN task.sort_order IS '排序';
COMMENT ON COLUMN task.tags IS '标签';
COMMENT ON COLUMN task.attachments IS '附件列表';
COMMENT ON COLUMN task.extra_data IS '扩展数据';
-- 任务依赖关系表
DROP TABLE IF EXISTS task_dependency CASCADE;
CREATE TABLE task_dependency (
id BIGSERIAL PRIMARY KEY,
task_id BIGINT NOT NULL,
depends_on_task_id BIGINT NOT NULL,
dependency_type VARCHAR(20) DEFAULT 'finish_to_start',
lag_days INT DEFAULT 0,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(task_id, depends_on_task_id),
-- 修正了下面的 fk_td_depends 约束
CONSTRAINT fk_td_task FOREIGN KEY (task_id) REFERENCES task(id) ON DELETE CASCADE,
CONSTRAINT fk_td_depends FOREIGN KEY (depends_on_task_id) REFERENCES task(id) ON DELETE CASCADE
);
CREATE INDEX idx_td_depends ON task_dependency(depends_on_task_id);
COMMENT ON TABLE task_dependency IS '任务依赖关系表';
COMMENT ON COLUMN task_dependency.task_id IS '任务ID';
COMMENT ON COLUMN task_dependency.depends_on_task_id IS '依赖的任务ID';
COMMENT ON COLUMN task_dependency.dependency_type IS '依赖类型: finish_to_start-完成-开始, start_to_start-开始-开始, finish_to_finish-完成-完成, start_to_finish-开始-完成';
COMMENT ON COLUMN task_dependency.lag_days IS '滞后天数';
-- =====================================================
-- 5. 工单管理表
-- =====================================================
-- 工单表 (移除order_type_id外键使用type字段替代)
-- 工单可关联风险,用于风险处理
DROP TABLE IF EXISTS work_order CASCADE;
CREATE TABLE work_order (
id BIGSERIAL PRIMARY KEY,
order_code VARCHAR(50) NOT NULL UNIQUE,
order_type VARCHAR(50),
project_id BIGINT,
risk_id BIGINT,
title VARCHAR(200) NOT NULL,
description TEXT,
creator_id BIGINT NOT NULL,
handler_id BIGINT,
handler_group_id BIGINT,
priority VARCHAR(20) DEFAULT 'medium',
status VARCHAR(20) DEFAULT 'pending',
source VARCHAR(50),
deadline TIMESTAMP,
assigned_time TIMESTAMP,
first_response_time TIMESTAMP,
resolved_time TIMESTAMP,
closed_time TIMESTAMP,
satisfaction_score INT,
tags JSONB,
attachments JSONB,
extra_data JSONB,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
CONSTRAINT fk_wo_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE SET NULL
);
CREATE INDEX idx_wo_project ON work_order(project_id);
CREATE INDEX idx_wo_creator ON work_order(creator_id);
CREATE INDEX idx_wo_handler ON work_order(handler_id);
CREATE INDEX idx_wo_status ON work_order(status);
CREATE INDEX idx_wo_priority ON work_order(priority);
CREATE INDEX idx_wo_type ON work_order(order_type);
COMMENT ON TABLE work_order IS '工单表';
COMMENT ON COLUMN work_order.order_code IS '工单编号';
COMMENT ON COLUMN work_order.order_type IS '工单类型: bug-缺陷, feature-需求, task-任务, incident-事件, risk_handle-风险处理, other-其他';
COMMENT ON COLUMN work_order.project_id IS '关联项目ID';
COMMENT ON COLUMN work_order.risk_id IS '关联风险ID(用于风险处理工单)';
COMMENT ON COLUMN work_order.title IS '工单标题';
COMMENT ON COLUMN work_order.description IS '工单描述';
COMMENT ON COLUMN work_order.creator_id IS '创建人ID';
COMMENT ON COLUMN work_order.handler_id IS '处理人ID';
COMMENT ON COLUMN work_order.handler_group_id IS '处理组ID';
COMMENT ON COLUMN work_order.priority IS '优先级: critical-紧急, high-高, medium-中, low-低';
COMMENT ON COLUMN work_order.status IS '状态: pending-待处理, assigned-已分派, processing-处理中, resolved-已解决, closed-已关闭, reopened-已重开';
COMMENT ON COLUMN work_order.source IS '来源: web-网页, mobile-移动端, api-接口, system-系统生成, risk-风险分派';
COMMENT ON COLUMN work_order.deadline IS '截止时间';
COMMENT ON COLUMN work_order.assigned_time IS '分派时间';
COMMENT ON COLUMN work_order.first_response_time IS '首次响应时间';
COMMENT ON COLUMN work_order.resolved_time IS '解决时间';
COMMENT ON COLUMN work_order.closed_time IS '关闭时间';
COMMENT ON COLUMN work_order.satisfaction_score IS '满意度评分(1-5)';
COMMENT ON COLUMN work_order.tags IS '标签';
COMMENT ON COLUMN work_order.attachments IS '附件列表';
COMMENT ON COLUMN work_order.extra_data IS '扩展数据';
-- 工单流转记录表
DROP TABLE IF EXISTS work_order_log CASCADE;
CREATE TABLE work_order_log (
id BIGSERIAL PRIMARY KEY,
order_id BIGINT NOT NULL,
action_type VARCHAR(50) NOT NULL,
from_status VARCHAR(20),
to_status VARCHAR(20),
operator_id BIGINT,
content TEXT,
attachments JSONB,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_wol_order FOREIGN KEY (order_id) REFERENCES work_order(id) ON DELETE CASCADE
);
CREATE INDEX idx_wol_order ON work_order_log(order_id);
CREATE INDEX idx_wol_operator ON work_order_log(operator_id);
COMMENT ON TABLE work_order_log IS '工单流转记录表';
COMMENT ON COLUMN work_order_log.order_id IS '工单ID';
COMMENT ON COLUMN work_order_log.action_type IS '操作类型: create-创建, assign-分派, accept-接受, process-处理, resolve-解决, close-关闭, reopen-重开, comment-备注';
COMMENT ON COLUMN work_order_log.from_status IS '原状态';
COMMENT ON COLUMN work_order_log.to_status IS '新状态';
COMMENT ON COLUMN work_order_log.operator_id IS '操作人ID';
COMMENT ON COLUMN work_order_log.content IS '操作内容';
COMMENT ON COLUMN work_order_log.attachments IS '附件列表';
-- =====================================================
-- 6. 风险管理表
-- =====================================================
-- 风险表 (移除category_id外键使用category字符串字段)
-- 风险通过分派工单处理,工单完成后同步更新风险状态
DROP TABLE IF EXISTS risk CASCADE;
CREATE TABLE risk (
id BIGSERIAL PRIMARY KEY,
risk_code VARCHAR(50),
project_id BIGINT NOT NULL,
category VARCHAR(50),
risk_name VARCHAR(200) NOT NULL,
description TEXT,
risk_source VARCHAR(50),
risk_type VARCHAR(50),
probability DECIMAL(5,2),
impact DECIMAL(5,2),
risk_score DECIMAL(5,2),
risk_level VARCHAR(20) DEFAULT 'low',
status VARCHAR(20) DEFAULT 'identified',
owner_id BIGINT,
-- 工单关联(风险分派的工单ID列表)
work_order_ids BIGINT[],
mitigation_plan TEXT,
contingency_plan TEXT,
trigger_condition TEXT,
discover_time TIMESTAMP,
due_date DATE,
resolved_time TIMESTAMP,
ai_analysis JSONB,
tags JSONB,
extra_data JSONB,
create_by BIGINT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_by BIGINT,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
CONSTRAINT fk_risk_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE CASCADE,
CONSTRAINT fk_risk_owner FOREIGN KEY (owner_id) REFERENCES sys_user(id) ON DELETE SET NULL
);
-- 添加工单外键约束 (需要先创建risk表)
ALTER TABLE work_order ADD CONSTRAINT fk_wo_risk FOREIGN KEY (risk_id) REFERENCES risk(id) ON DELETE SET NULL;
CREATE INDEX idx_wo_risk ON work_order(risk_id);
CREATE INDEX idx_risk_project ON risk(project_id);
CREATE INDEX idx_risk_category ON risk(category);
CREATE INDEX idx_risk_owner ON risk(owner_id);
CREATE INDEX idx_risk_level ON risk(risk_level);
CREATE INDEX idx_risk_status ON risk(status);
COMMENT ON TABLE risk IS '风险表';
COMMENT ON COLUMN risk.risk_code IS '风险编号';
COMMENT ON COLUMN risk.project_id IS '项目ID';
COMMENT ON COLUMN risk.category IS '风险分类: technical-技术风险, schedule-进度风险, cost-成本风险, quality-质量风险, resource-资源风险, external-外部风险, other-其他';
COMMENT ON COLUMN risk.risk_name IS '风险名称';
COMMENT ON COLUMN risk.description IS '风险描述';
COMMENT ON COLUMN risk.risk_source IS '风险来源: internal-内部, external-外部, ai_detection-AI检测';
COMMENT ON COLUMN risk.risk_type IS '风险类型';
COMMENT ON COLUMN risk.probability IS '发生概率(0-100%)';
COMMENT ON COLUMN risk.impact IS '影响程度(1-5)';
COMMENT ON COLUMN risk.risk_score IS '风险得分(概率*影响)';
COMMENT ON COLUMN risk.risk_level IS '风险等级: critical-严重, high-高, medium-中, low-低';
COMMENT ON COLUMN risk.status IS '状态: identified-已识别, assigned-已分派工单, mitigating-缓解中, resolved-已解决, closed-已关闭';
COMMENT ON COLUMN risk.owner_id IS '负责人ID';
COMMENT ON COLUMN risk.work_order_ids IS '关联的工单ID数组';
COMMENT ON COLUMN risk.mitigation_plan IS '缓解措施';
COMMENT ON COLUMN risk.contingency_plan IS '应急计划';
COMMENT ON COLUMN risk.trigger_condition IS '触发条件';
COMMENT ON COLUMN risk.discover_time IS '发现时间';
COMMENT ON COLUMN risk.due_date IS '预期解决日期';
COMMENT ON COLUMN risk.resolved_time IS '解决时间';
COMMENT ON COLUMN risk.ai_analysis IS 'AI分析结果';
COMMENT ON COLUMN risk.tags IS '标签';
COMMENT ON COLUMN risk.extra_data IS '扩展数据';
-- 注:风险通过分派工单进行处理,工单处理完成后同步更新风险状态
-- 因此不需要单独的风险处理记录表,处理历史在工单流转记录中查看
-- =====================================================
-- 7. 数据录入与报告表
-- =====================================================
-- 日报/数据录入表
DROP TABLE IF EXISTS daily_report CASCADE;
CREATE TABLE daily_report (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL,
creator_id BIGINT NOT NULL,
report_date DATE,
report_type VARCHAR(50) DEFAULT 'daily',
title VARCHAR(200),
content TEXT,
work_content TEXT,
issues TEXT,
next_plan TEXT,
location VARCHAR(200),
latitude DECIMAL(10,7),
longitude DECIMAL(10,7),
weather VARCHAR(50),
temperature DECIMAL(5,2),
status VARCHAR(20) DEFAULT 'draft',
ai_analysis JSONB,
tags JSONB,
extra_data JSONB,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
CONSTRAINT fk_dr_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE CASCADE,
CONSTRAINT fk_dr_creator FOREIGN KEY (creator_id) REFERENCES sys_user(id) ON DELETE CASCADE
);
CREATE INDEX idx_dr_project ON daily_report(project_id);
CREATE INDEX idx_dr_creator ON daily_report(creator_id);
CREATE INDEX idx_dr_report_date ON daily_report(report_date);
CREATE INDEX idx_dr_report_type ON daily_report(report_type);
COMMENT ON TABLE daily_report IS '日报/数据录入表';
COMMENT ON COLUMN daily_report.project_id IS '项目ID';
COMMENT ON COLUMN daily_report.creator_id IS '创建人ID';
COMMENT ON COLUMN daily_report.report_date IS '报告日期';
COMMENT ON COLUMN daily_report.report_type IS '报告类型: daily-日报, weekly-周报, monthly-月报, milestone-里程碑报告, photo-照片记录';
COMMENT ON COLUMN daily_report.title IS '标题';
COMMENT ON COLUMN daily_report.content IS '内容';
COMMENT ON COLUMN daily_report.work_content IS '工作内容';
COMMENT ON COLUMN daily_report.issues IS '问题与风险';
COMMENT ON COLUMN daily_report.next_plan IS '下一步计划';
COMMENT ON COLUMN daily_report.location IS '位置';
COMMENT ON COLUMN daily_report.latitude IS '纬度';
COMMENT ON COLUMN daily_report.longitude IS '经度';
COMMENT ON COLUMN daily_report.weather IS '天气';
COMMENT ON COLUMN daily_report.temperature IS '温度';
COMMENT ON COLUMN daily_report.status IS '状态: draft-草稿, submitted-已提交, approved-已审批';
COMMENT ON COLUMN daily_report.ai_analysis IS 'AI分析结果';
COMMENT ON COLUMN daily_report.tags IS '标签';
COMMENT ON COLUMN daily_report.extra_data IS '扩展数据';
-- 文件附件表
DROP TABLE IF EXISTS file_attachment CASCADE;
CREATE TABLE file_attachment (
id BIGSERIAL PRIMARY KEY,
file_name VARCHAR(200) NOT NULL,
original_name VARCHAR(200),
file_path VARCHAR(500) NOT NULL,
file_url VARCHAR(500),
file_type VARCHAR(50),
file_size BIGINT,
storage_type VARCHAR(20) DEFAULT 'local',
related_type VARCHAR(50),
related_id BIGINT,
uploader_id BIGINT,
exif_data JSONB,
ai_analysis JSONB,
extra_data JSONB,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
CONSTRAINT fk_fa_uploader FOREIGN KEY (uploader_id) REFERENCES sys_user(id) ON DELETE SET NULL
);
CREATE INDEX idx_fa_related ON file_attachment(related_type, related_id);
CREATE INDEX idx_fa_uploader ON file_attachment(uploader_id);
COMMENT ON TABLE file_attachment IS '文件附件表';
COMMENT ON COLUMN file_attachment.file_name IS '文件名称';
COMMENT ON COLUMN file_attachment.original_name IS '原始文件名';
COMMENT ON COLUMN file_attachment.file_path IS '文件路径';
COMMENT ON COLUMN file_attachment.file_url IS '文件URL';
COMMENT ON COLUMN file_attachment.file_type IS '文件类型(MIME)';
COMMENT ON COLUMN file_attachment.file_size IS '文件大小(字节)';
COMMENT ON COLUMN file_attachment.storage_type IS '存储类型: local-本地, oss-对象存储, minio-MinIO';
COMMENT ON COLUMN file_attachment.related_type IS '关联类型: project, task, work_order, risk, report';
COMMENT ON COLUMN file_attachment.related_id IS '关联ID';
COMMENT ON COLUMN file_attachment.uploader_id IS '上传人ID';
COMMENT ON COLUMN file_attachment.exif_data IS 'EXIF信息(照片专用)';
COMMENT ON COLUMN file_attachment.ai_analysis IS 'AI分析结果';
COMMENT ON COLUMN file_attachment.extra_data IS '扩展数据';
-- =====================================================
-- 8. 资源管理表
-- =====================================================
-- 资源表(项目资源抽象: 人力、物料、设备、资金等)
-- 简化设计移除resource_type表使用resource_type字符串字段
DROP TABLE IF EXISTS resource CASCADE;
CREATE TABLE resource (
id BIGSERIAL PRIMARY KEY,
resource_code VARCHAR(50),
project_id BIGINT NOT NULL,
resource_type VARCHAR(50),
resource_name VARCHAR(200) NOT NULL,
description TEXT,
specification VARCHAR(200),
unit VARCHAR(20),
plan_quantity DECIMAL(12,2),
actual_quantity DECIMAL(12,2),
unit_price DECIMAL(12,2),
currency VARCHAR(10) DEFAULT 'CNY',
supplier VARCHAR(200),
status VARCHAR(20) DEFAULT 'planned',
plan_arrive_date DATE,
actual_arrive_date DATE,
responsible_id BIGINT,
location VARCHAR(200),
tags JSONB,
extra_data JSONB,
create_by BIGINT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_by BIGINT,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
CONSTRAINT fk_resource_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE CASCADE,
CONSTRAINT fk_resource_responsible FOREIGN KEY (responsible_id) REFERENCES sys_user(id) ON DELETE SET NULL
);
CREATE INDEX idx_resource_project ON resource(project_id);
CREATE INDEX idx_resource_type ON resource(resource_type);
CREATE INDEX idx_resource_status ON resource(status);
COMMENT ON TABLE resource IS '资源表 - 项目资源统一管理(人力、物料、设备、资金等)';
COMMENT ON COLUMN resource.resource_code IS '资源编号';
COMMENT ON COLUMN resource.project_id IS '项目ID';
COMMENT ON COLUMN resource.resource_type IS '资源类型: human-人力, material-物料, equipment-设备, software-软件, finance-资金, other-其他';
COMMENT ON COLUMN resource.resource_name IS '资源名称';
COMMENT ON COLUMN resource.description IS '资源描述';
COMMENT ON COLUMN resource.specification IS '规格型号';
COMMENT ON COLUMN resource.unit IS '单位';
COMMENT ON COLUMN resource.plan_quantity IS '计划数量';
COMMENT ON COLUMN resource.actual_quantity IS '实际数量';
COMMENT ON COLUMN resource.unit_price IS '单价';
COMMENT ON COLUMN resource.currency IS '币种';
COMMENT ON COLUMN resource.supplier IS '供应商/来源';
COMMENT ON COLUMN resource.status IS '状态: planned-计划中, requested-已申请, approved-已批准, procuring-采购中, arrived-已到货, in_use-使用中, completed-已完成';
COMMENT ON COLUMN resource.plan_arrive_date IS '计划到位日期';
COMMENT ON COLUMN resource.actual_arrive_date IS '实际到位日期';
COMMENT ON COLUMN resource.responsible_id IS '负责人ID';
COMMENT ON COLUMN resource.location IS '存放位置';
COMMENT ON COLUMN resource.tags IS '标签';
COMMENT ON COLUMN resource.extra_data IS '扩展数据';
-- =====================================================
-- 9. 流程卡点分析表
-- =====================================================
-- 流程卡点记录表
DROP TABLE IF EXISTS bottleneck_record CASCADE;
CREATE TABLE bottleneck_record (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
bottleneck_type VARCHAR(50) NOT NULL,
related_type VARCHAR(50),
related_id BIGINT,
description TEXT,
impact_level VARCHAR(20) DEFAULT 'medium',
status VARCHAR(20) DEFAULT 'pending',
start_time TIMESTAMP,
resolved_time TIMESTAMP,
duration_hours DECIMAL(8,2),
solution TEXT,
extra_data JSONB,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_br_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE CASCADE,
CONSTRAINT fk_br_user FOREIGN KEY (user_id) REFERENCES sys_user(id) ON DELETE CASCADE
);
CREATE INDEX idx_br_project ON bottleneck_record(project_id);
CREATE INDEX idx_br_user ON bottleneck_record(user_id);
CREATE INDEX idx_br_type ON bottleneck_record(bottleneck_type);
COMMENT ON TABLE bottleneck_record IS '流程卡点记录表';
COMMENT ON COLUMN bottleneck_record.project_id IS '项目ID';
COMMENT ON COLUMN bottleneck_record.user_id IS '用户ID';
COMMENT ON COLUMN bottleneck_record.bottleneck_type IS '卡点类型: resource-资源不足, approval-审批延迟, dependency-依赖阻塞, skill-技能不足, external-外部因素, other-其他';
COMMENT ON COLUMN bottleneck_record.related_type IS '关联类型: task, work_order, risk';
COMMENT ON COLUMN bottleneck_record.related_id IS '关联ID';
COMMENT ON COLUMN bottleneck_record.description IS '卡点描述';
COMMENT ON COLUMN bottleneck_record.impact_level IS '影响程度: critical-严重, high-高, medium-中, low-低';
COMMENT ON COLUMN bottleneck_record.status IS '状态: pending-待处理, resolving-解决中, resolved-已解决';
COMMENT ON COLUMN bottleneck_record.start_time IS '卡点开始时间';
COMMENT ON COLUMN bottleneck_record.resolved_time IS '解决时间';
COMMENT ON COLUMN bottleneck_record.duration_hours IS '持续时长(小时)';
COMMENT ON COLUMN bottleneck_record.solution IS '解决方案';
COMMENT ON COLUMN bottleneck_record.extra_data IS '扩展数据';
-- =====================================================
-- 10. 时间节点知识库表
-- =====================================================
-- 项目时间节点表
DROP TABLE IF EXISTS project_timeline CASCADE;
CREATE TABLE project_timeline (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL,
node_name VARCHAR(200) NOT NULL,
node_type VARCHAR(50) DEFAULT 'phase',
parent_id BIGINT,
plan_date DATE,
actual_date DATE,
description TEXT,
status VARCHAR(20) DEFAULT 'pending',
sort_order INT DEFAULT 0,
-- 知识库范围配置
kb_scope JSONB,
extra_data JSONB,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
CONSTRAINT fk_timeline_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE CASCADE,
CONSTRAINT fk_timeline_parent FOREIGN KEY (parent_id) REFERENCES project_timeline(id) ON DELETE SET NULL
);
CREATE INDEX idx_timeline_project ON project_timeline(project_id);
CREATE INDEX idx_timeline_parent ON project_timeline(parent_id);
CREATE INDEX idx_timeline_type ON project_timeline(node_type);
COMMENT ON TABLE project_timeline IS '项目时间节点表 - 用于构建时间维度知识库';
COMMENT ON COLUMN project_timeline.project_id IS '项目ID';
COMMENT ON COLUMN project_timeline.node_name IS '节点名称';
COMMENT ON COLUMN project_timeline.node_type IS '节点类型: phase-阶段, milestone-里程碑, event-事件, checkpoint-检查点';
COMMENT ON COLUMN project_timeline.parent_id IS '父节点ID';
COMMENT ON COLUMN project_timeline.plan_date IS '计划日期';
COMMENT ON COLUMN project_timeline.actual_date IS '实际日期';
COMMENT ON COLUMN project_timeline.description IS '描述';
COMMENT ON COLUMN project_timeline.status IS '状态: pending-待开始, in_progress-进行中, completed-已完成, delayed-延期';
COMMENT ON COLUMN project_timeline.sort_order IS '排序';
COMMENT ON COLUMN project_timeline.kb_scope IS '知识库范围配置["report","file","risk","ticket"]';
-- 知识库表
DROP TABLE IF EXISTS ai_knowledge_base CASCADE;
CREATE TABLE ai_knowledge_base (
id BIGSERIAL PRIMARY KEY,
kb_name VARCHAR(200) NOT NULL,
kb_type VARCHAR(50) DEFAULT 'project',
project_id BIGINT,
timeline_node_id BIGINT,
description TEXT,
-- 向量化配置
embedding_model VARCHAR(100) DEFAULT 'text-embedding-3-small',
chunk_size INT DEFAULT 500,
chunk_overlap INT DEFAULT 50,
-- 统计
doc_count INT DEFAULT 0,
total_chunks INT DEFAULT 0,
status VARCHAR(20) DEFAULT 'active',
create_by BIGINT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0,
CONSTRAINT fk_kb_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE CASCADE,
CONSTRAINT fk_kb_timeline FOREIGN KEY (timeline_node_id) REFERENCES project_timeline(id) ON DELETE SET NULL
);
CREATE INDEX idx_kb_project ON ai_knowledge_base(project_id);
CREATE INDEX idx_kb_timeline ON ai_knowledge_base(timeline_node_id);
CREATE INDEX idx_kb_type ON ai_knowledge_base(kb_type);
COMMENT ON TABLE ai_knowledge_base IS '知识库表';
COMMENT ON COLUMN ai_knowledge_base.kb_name IS '知识库名称';
COMMENT ON COLUMN ai_knowledge_base.kb_type IS '知识库类型: project-项目知识库, timeline-时间节点知识库, global-全局知识库';
COMMENT ON COLUMN ai_knowledge_base.project_id IS '关联项目ID';
COMMENT ON COLUMN ai_knowledge_base.timeline_node_id IS '关联时间节点ID';
COMMENT ON COLUMN ai_knowledge_base.description IS '描述';
COMMENT ON COLUMN ai_knowledge_base.embedding_model IS '向量模型';
COMMENT ON COLUMN ai_knowledge_base.chunk_size IS '分块大小';
COMMENT ON COLUMN ai_knowledge_base.chunk_overlap IS '分块重叠';
COMMENT ON COLUMN ai_knowledge_base.doc_count IS '文档数量';
COMMENT ON COLUMN ai_knowledge_base.total_chunks IS '总分块数';
COMMENT ON COLUMN ai_knowledge_base.status IS '状态: active-可用, archived-归档';
-- =====================================================
-- 11. AI服务相关表
-- =====================================================
-- AI对话记录表 (合并会话管理功能无需单独的session表)
-- 注ai_document表已合并到vector_store表中
DROP TABLE IF EXISTS ai_chat_history CASCADE;
CREATE TABLE ai_chat_history (
id BIGSERIAL PRIMARY KEY,
-- 会话标识 (使用UUID标识一个会话无需单独的session表)
session_id UUID NOT NULL,
session_title VARCHAR(200),
user_id BIGINT NOT NULL,
project_id BIGINT,
timeline_node_id BIGINT,
-- 消息内容
role VARCHAR(20) NOT NULL,
content TEXT NOT NULL,
content_embedding vector(1024),
-- 引用的知识库文档
referenced_doc_ids VARCHAR(255)[],
-- 上下文配置
system_prompt TEXT,
context_window INT DEFAULT 10,
kb_ids JSONB,
-- 模型信息
model VARCHAR(50),
tokens_used INT,
response_time INT,
-- 用户反馈
feedback_score INT,
feedback_content TEXT,
-- 统计
message_index INT DEFAULT 0,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_chat_project FOREIGN KEY (project_id) REFERENCES project(id) ON DELETE SET NULL,
CONSTRAINT fk_chat_timeline FOREIGN KEY (timeline_node_id) REFERENCES project_timeline(id) ON DELETE SET NULL,
CONSTRAINT fk_chat_user FOREIGN KEY (user_id) REFERENCES sys_user(id) ON DELETE CASCADE
);
-- 索引
CREATE INDEX idx_chat_session ON ai_chat_history(session_id);
CREATE INDEX idx_chat_user ON ai_chat_history(user_id);
CREATE INDEX idx_chat_project ON ai_chat_history(project_id);
CREATE INDEX idx_chat_timeline ON ai_chat_history(timeline_node_id);
CREATE INDEX idx_chat_time ON ai_chat_history(create_time);
CREATE INDEX idx_chat_role ON ai_chat_history(session_id, role);
COMMENT ON TABLE ai_chat_history IS 'AI对话记录表 - 包含会话管理功能';
COMMENT ON COLUMN ai_chat_history.session_id IS '会话ID(同一session_id的消息属于同一会话)';
COMMENT ON COLUMN ai_chat_history.session_title IS '会话标题(首条消息自动生成)';
COMMENT ON COLUMN ai_chat_history.user_id IS '用户ID';
COMMENT ON COLUMN ai_chat_history.project_id IS '关联项目ID';
COMMENT ON COLUMN ai_chat_history.timeline_node_id IS '关联时间节点ID';
COMMENT ON COLUMN ai_chat_history.role IS '角色: user-用户, assistant-助手, system-系统';
COMMENT ON COLUMN ai_chat_history.content IS '对话内容';
COMMENT ON COLUMN ai_chat_history.content_embedding IS '对话内容的向量表示(用于语义检索历史对话)';
COMMENT ON COLUMN ai_chat_history.referenced_doc_ids IS '引用的文档ID列表';
COMMENT ON COLUMN ai_chat_history.system_prompt IS '系统提示词(仅role=system时有值)';
COMMENT ON COLUMN ai_chat_history.context_window IS '该会话的上下文窗口大小';
COMMENT ON COLUMN ai_chat_history.kb_ids IS '关联的知识库ID列表';
COMMENT ON COLUMN ai_chat_history.model IS '使用的模型';
COMMENT ON COLUMN ai_chat_history.tokens_used IS '消耗Token数';
COMMENT ON COLUMN ai_chat_history.response_time IS '响应时间(ms)';
COMMENT ON COLUMN ai_chat_history.feedback_score IS '反馈评分(1-5)';
COMMENT ON COLUMN ai_chat_history.feedback_content IS '反馈内容';
COMMENT ON COLUMN ai_chat_history.message_index IS '消息在会话中的序号';
-- AI分析结果表
DROP TABLE IF EXISTS ai_analysis_result CASCADE;
CREATE TABLE ai_analysis_result (
id BIGSERIAL PRIMARY KEY,
analysis_type VARCHAR(50) NOT NULL,
related_type VARCHAR(50),
related_id BIGINT,
-- 输入输出
input_data JSONB,
result_data JSONB,
result_embedding vector(1024),
-- 模型信息
confidence DECIMAL(5,2),
model_name VARCHAR(100),
model_version VARCHAR(50),
processing_time INT,
-- 成本和Token
input_tokens INT,
output_tokens INT,
cost DECIMAL(10,6),
status VARCHAR(20) DEFAULT 'completed',
error_message TEXT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_analysis_type ON ai_analysis_result(analysis_type);
CREATE INDEX idx_analysis_related ON ai_analysis_result(related_type, related_id);
CREATE INDEX idx_analysis_time ON ai_analysis_result(create_time);
COMMENT ON TABLE ai_analysis_result IS 'AI分析结果表';
COMMENT ON COLUMN ai_analysis_result.analysis_type IS '分析类型: photo_analysis-照片分析, risk_prediction-风险预测, progress_analysis-进度分析, text_extraction-文本提取, embedding-向量生成';
COMMENT ON COLUMN ai_analysis_result.related_type IS '关联类型';
COMMENT ON COLUMN ai_analysis_result.related_id IS '关联ID';
COMMENT ON COLUMN ai_analysis_result.input_data IS '输入数据';
COMMENT ON COLUMN ai_analysis_result.result_data IS '分析结果';
COMMENT ON COLUMN ai_analysis_result.result_embedding IS '分析结果的向量表示';
COMMENT ON COLUMN ai_analysis_result.confidence IS '置信度(0-100%)';
COMMENT ON COLUMN ai_analysis_result.model_name IS '模型名称';
COMMENT ON COLUMN ai_analysis_result.model_version IS '模型版本';
COMMENT ON COLUMN ai_analysis_result.processing_time IS '处理时间(ms)';
COMMENT ON COLUMN ai_analysis_result.input_tokens IS '输入token数';
COMMENT ON COLUMN ai_analysis_result.output_tokens IS '输出token数';
COMMENT ON COLUMN ai_analysis_result.cost IS '成本(美元)';
COMMENT ON COLUMN ai_analysis_result.status IS '状态: processing-处理中, completed-已完成, failed-失败';
COMMENT ON COLUMN ai_analysis_result.error_message IS '错误信息';
-- =====================================================
-- 12. 系统配置与日志表
-- =====================================================
-- 系统配置表
DROP TABLE IF EXISTS sys_config CASCADE;
CREATE TABLE sys_config (
id BIGSERIAL PRIMARY KEY,
config_key VARCHAR(100) NOT NULL UNIQUE,
config_value TEXT,
config_type VARCHAR(50) DEFAULT 'system',
description TEXT,
status SMALLINT DEFAULT 1,
create_by BIGINT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_by BIGINT,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted SMALLINT DEFAULT 0
);
COMMENT ON TABLE sys_config IS '系统配置表';
COMMENT ON COLUMN sys_config.config_key IS '配置键';
COMMENT ON COLUMN sys_config.config_value IS '配置值';
COMMENT ON COLUMN sys_config.config_type IS '配置类型: system-系统, business-业务, ai-AI配置';
COMMENT ON COLUMN sys_config.description IS '配置描述';
COMMENT ON COLUMN sys_config.status IS '状态';
-- 操作日志表
DROP TABLE IF EXISTS sys_operation_log CASCADE;
CREATE TABLE sys_operation_log (
id BIGSERIAL PRIMARY KEY,
trace_id VARCHAR(100),
user_id BIGINT,
module VARCHAR(50),
operation VARCHAR(100),
method VARCHAR(200),
request_url VARCHAR(500),
request_method VARCHAR(10),
request_params TEXT,
response_data TEXT,
ip VARCHAR(50),
user_agent VARCHAR(500),
execute_time INT,
status SMALLINT DEFAULT 1,
error_msg TEXT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_log_user FOREIGN KEY (user_id) REFERENCES sys_user(id) ON DELETE SET NULL
);
CREATE INDEX idx_log_trace ON sys_operation_log(trace_id);
CREATE INDEX idx_log_user ON sys_operation_log(user_id);
CREATE INDEX idx_log_module ON sys_operation_log(module);
CREATE INDEX idx_log_time ON sys_operation_log(create_time);
COMMENT ON TABLE sys_operation_log IS '操作日志表';
COMMENT ON COLUMN sys_operation_log.trace_id IS '追踪ID';
COMMENT ON COLUMN sys_operation_log.user_id IS '用户ID';
COMMENT ON COLUMN sys_operation_log.module IS '模块';
COMMENT ON COLUMN sys_operation_log.operation IS '操作';
COMMENT ON COLUMN sys_operation_log.method IS '方法';
COMMENT ON COLUMN sys_operation_log.request_url IS '请求URL';
COMMENT ON COLUMN sys_operation_log.request_method IS '请求方法';
COMMENT ON COLUMN sys_operation_log.request_params IS '请求参数';
COMMENT ON COLUMN sys_operation_log.response_data IS '响应数据';
COMMENT ON COLUMN sys_operation_log.ip IS 'IP地址';
COMMENT ON COLUMN sys_operation_log.user_agent IS '用户代理';
COMMENT ON COLUMN sys_operation_log.execute_time IS '执行时长(ms)';
COMMENT ON COLUMN sys_operation_log.status IS '状态: 1-成功, 0-失败';
COMMENT ON COLUMN sys_operation_log.error_msg IS '错误信息';
-- 通知消息表
DROP TABLE IF EXISTS sys_notification CASCADE;
CREATE TABLE sys_notification (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
title VARCHAR(200) NOT NULL,
content TEXT,
notification_type VARCHAR(50),
related_type VARCHAR(50),
related_id BIGINT,
priority VARCHAR(20) DEFAULT 'normal',
is_read SMALLINT DEFAULT 0,
read_time TIMESTAMP,
sender_id BIGINT,
extra_data JSONB,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_notif_user FOREIGN KEY (user_id) REFERENCES sys_user(id) ON DELETE CASCADE,
CONSTRAINT fk_notif_sender FOREIGN KEY (sender_id) REFERENCES sys_user(id) ON DELETE SET NULL
);
CREATE INDEX idx_notif_user ON sys_notification(user_id);
CREATE INDEX idx_notif_read ON sys_notification(is_read);
CREATE INDEX idx_notif_time ON sys_notification(create_time);
COMMENT ON TABLE sys_notification IS '通知消息表';
COMMENT ON COLUMN sys_notification.user_id IS '接收用户ID';
COMMENT ON COLUMN sys_notification.title IS '标题';
COMMENT ON COLUMN sys_notification.content IS '内容';
COMMENT ON COLUMN sys_notification.notification_type IS '通知类型: system-系统, task-任务, risk-风险, work_order-工单';
COMMENT ON COLUMN sys_notification.related_type IS '关联类型';
COMMENT ON COLUMN sys_notification.related_id IS '关联ID';
COMMENT ON COLUMN sys_notification.priority IS '优先级: urgent-紧急, high-高, normal-普通, low-低';
COMMENT ON COLUMN sys_notification.is_read IS '是否已读: 1-是, 0-否';
COMMENT ON COLUMN sys_notification.read_time IS '阅读时间';
COMMENT ON COLUMN sys_notification.sender_id IS '发送人ID';
COMMENT ON COLUMN sys_notification.extra_data IS '扩展数据';
-- =====================================================
-- 初始化数据
-- =====================================================
-- 初始化系统角色
INSERT INTO sys_role (role_code, role_name, role_type, description, data_scope, sort_order, status) VALUES
('admin', '系统管理员', 'system', '拥有系统全部权限', 1, 1, 1),
('project_manager', '项目经理', 'system', '项目管理权限', 2, 2, 1),
('team_leader', '团队负责人', 'system', '团队管理权限', 2, 3, 1),
('member', '普通成员', 'system', '基本操作权限', 3, 4, 1);
-- 初始化系统配置
INSERT INTO sys_config (config_key, config_value, config_type, description) VALUES
('ai.model.default', 'gpt-4o', 'ai', '默认AI模型'),
('ai.embedding.model', 'text-embedding-v4', 'ai', '向量嵌入模型'),
('ai.embedding.dimension', '1024', 'ai', '向量维度'),
('ai.rag.top_k', '5', 'ai', 'RAG检索返回数量'),
('ai.rag.similarity_threshold', '0.7', 'ai', 'RAG相似度阈値');
-- =====================================================
-- 项目日报表(供外部系统同步日报数据)
-- 防重键: (project_id, report_date, submitter_username)
-- =====================================================
CREATE TABLE IF NOT EXISTS project_daily_report (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL,
submitter_username VARCHAR(100) NOT NULL,
submitter_id BIGINT,
report_date DATE NOT NULL,
work_content TEXT,
tomorrow_plan TEXT,
work_intensity INTEGER CHECK (work_intensity BETWEEN 1 AND 5),
need_help BOOLEAN DEFAULT FALSE,
help_content TEXT,
create_time TIMESTAMP DEFAULT NOW(),
update_time TIMESTAMP DEFAULT NOW(),
deleted INTEGER DEFAULT 0,
CONSTRAINT uq_daily_report UNIQUE (project_id, report_date, submitter_username)
);
COMMENT ON TABLE project_daily_report IS '项目日报(外部同步)';
COMMENT ON COLUMN project_daily_report.submitter_username IS '提交人用户名 (对应 sys_user.username)';
COMMENT ON COLUMN project_daily_report.work_intensity IS '工作强度: 1-轻松 2-较轻 3-适中 4-繁忙 5-非常繁忙';