-- 科技成果转化系统 数据库设计 (PostgreSQL) - 完整版 -- 1. 部门表 CREATE TABLE IF NOT EXISTS departments ( id SERIAL PRIMARY KEY, name VARCHAR(100) UNIQUE NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- 2. 用户表 CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, username VARCHAR(50) UNIQUE NOT NULL, -- 手机号 password_hash VARCHAR(255) NOT NULL, role VARCHAR(20) NOT NULL CHECK (role IN ('super_admin', 'admin', 'user', 'maintainer', 'senior_user', 'intermediate_user')), real_name VARCHAR(100), department VARCHAR(100), -- 所属部门名称 dept_status VARCHAR(20) DEFAULT 'verified', -- 部门审核状态 token_version INTEGER DEFAULT 0, -- Token 版本号 (用于单点登录) created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- 3. 成果基础信息表 (所有类型共用) CREATE TABLE IF NOT EXISTS achievements ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id) ON DELETE SET NULL, type VARCHAR(50) NOT NULL, -- 'paper', 'project', 'award', 'standard', 'monograph', 'report', 'plan', 'patent', 'transformation', 'software' name TEXT NOT NULL, -- 成果名称 main_contributors TEXT, -- 主要完成人 (字符串格式,兼容旧数据) all_contributors TEXT, -- 完成人 (字符串格式,兼容旧数据) contributor_phones TEXT, -- 完成人手机号 (字符串格式) contributors JSONB DEFAULT '[]', -- 结构化完成人列表 [{name, phone, isMain}] assigned_departments TEXT[] DEFAULT '{}', -- 归属部门数组 (自动计算) achievement_date DATE, -- 时间 remarks TEXT, -- 备注 status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'rejected')), audit_comment TEXT, -- 审核意见 created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- 4. 论文详情表 CREATE TABLE IF NOT EXISTS achievement_paper ( id SERIAL PRIMARY KEY, achievement_id INTEGER REFERENCES achievements(id) ON DELETE CASCADE, paper_type TEXT, first_unit TEXT, journal_name TEXT, publish_date DATE, doi VARCHAR(100) ); -- 5. 项目详情表 CREATE TABLE IF NOT EXISTS achievement_project ( id SERIAL PRIMARY KEY, achievement_id INTEGER REFERENCES achievements(id) ON DELETE CASCADE, project_category TEXT, source TEXT ); -- 6. 奖励详情表 CREATE TABLE IF NOT EXISTS achievement_award ( id SERIAL PRIMARY KEY, achievement_id INTEGER REFERENCES achievements(id) ON DELETE CASCADE, award_type TEXT, award_level TEXT, award_unit TEXT ); -- 7. 标准详情表 CREATE TABLE IF NOT EXISTS achievement_standard ( id SERIAL PRIMARY KEY, achievement_id INTEGER REFERENCES achievements(id) ON DELETE CASCADE, standard_type TEXT, standard_no VARCHAR(100) NOT NULL, implement_date DATE ); -- 8. 专著详情表 CREATE TABLE IF NOT EXISTS achievement_monograph ( id SERIAL PRIMARY KEY, achievement_id INTEGER REFERENCES achievements(id) ON DELETE CASCADE, publisher TEXT, isbn VARCHAR(50) ); -- 9. 技术报告详情表 CREATE TABLE IF NOT EXISTS achievement_report ( id SERIAL PRIMARY KEY, achievement_id INTEGER REFERENCES achievements(id) ON DELETE CASCADE, report_type TEXT, recipient TEXT, approver_id INTEGER REFERENCES users(id), -- 签批院领导ID approver_name VARCHAR(100) -- 签批院领导姓名 (冗余存储,方便显示) ); -- 10. 规划详情表 CREATE TABLE IF NOT EXISTS achievement_plan ( id SERIAL PRIMARY KEY, achievement_id INTEGER REFERENCES achievements(id) ON DELETE CASCADE ); -- 11. 专利详情表 CREATE TABLE IF NOT EXISTS achievement_patent ( id SERIAL PRIMARY KEY, achievement_id INTEGER REFERENCES achievements(id) ON DELETE CASCADE, patent_no VARCHAR(100), patent_type TEXT, assignee TEXT ); -- 12. 成果转化详情表 CREATE TABLE IF NOT EXISTS achievement_transformation ( id SERIAL PRIMARY KEY, achievement_id INTEGER REFERENCES achievements(id) ON DELETE CASCADE, trans_method TEXT, trans_amount NUMERIC(15, 2), project_category TEXT ); -- 13. 软著详情表 CREATE TABLE IF NOT EXISTS achievement_software ( id SERIAL PRIMARY KEY, achievement_id INTEGER REFERENCES achievements(id) ON DELETE CASCADE, reg_no VARCHAR(100), acquisition_method TEXT, scope TEXT, owner_unit TEXT ); -- 14. 附件表 CREATE TABLE IF NOT EXISTS achievement_attachments ( id SERIAL PRIMARY KEY, achievement_id INTEGER REFERENCES achievements(id) ON DELETE CASCADE, file_name TEXT NOT NULL, file_path TEXT NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- 15. 字典表 (由超级管理员管理) -- 单位名称表 CREATE TABLE IF NOT EXISTS dict_organizations ( id SERIAL PRIMARY KEY, name VARCHAR(100) UNIQUE NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- 奖励种类表 CREATE TABLE IF NOT EXISTS dict_award_types ( id SERIAL PRIMARY KEY, name VARCHAR(100) UNIQUE NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- 奖励等级表 CREATE TABLE IF NOT EXISTS dict_award_levels ( id SERIAL PRIMARY KEY, name VARCHAR(100) UNIQUE NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- 论文种类表 CREATE TABLE IF NOT EXISTS dict_paper_types ( id SERIAL PRIMARY KEY, name VARCHAR(100) UNIQUE NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- 标准种类表 CREATE TABLE IF NOT EXISTS dict_standard_types ( id SERIAL PRIMARY KEY, name VARCHAR(100) UNIQUE NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- 项目分类表 CREATE TABLE IF NOT EXISTS dict_project_categories ( id SERIAL PRIMARY KEY, name VARCHAR(100) UNIQUE NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- 领导层部门表 (用于筛选签批领导) CREATE TABLE IF NOT EXISTS dict_leader_departments ( id SERIAL PRIMARY KEY, name VARCHAR(100) UNIQUE NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- 16. 审计日志表 CREATE TABLE IF NOT EXISTS audit_logs ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id), username VARCHAR(50), real_name VARCHAR(50), ip_address VARCHAR(50), method VARCHAR(10), url TEXT, description VARCHAR(255), status INTEGER, duration INTEGER, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 17. 系统公告表 CREATE TABLE IF NOT EXISTS notifications ( id SERIAL PRIMARY KEY, title VARCHAR(255) NOT NULL, content TEXT NOT NULL, publisher_id INTEGER REFERENCES users(id), publisher_name VARCHAR(100), created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, is_top BOOLEAN DEFAULT FALSE, status VARCHAR(20) DEFAULT 'published' -- published, draft, archived ); -- 18. 系统公告附件表 CREATE TABLE IF NOT EXISTS notification_attachments ( id SERIAL PRIMARY KEY, notification_id INTEGER REFERENCES notifications(id) ON DELETE CASCADE, file_name VARCHAR(255) NOT NULL, file_path VARCHAR(255) NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- 索引优化 CREATE INDEX IF NOT EXISTS idx_achievements_user ON achievements(user_id); CREATE INDEX IF NOT EXISTS idx_achievements_type ON achievements(type); CREATE INDEX IF NOT EXISTS idx_achievements_status ON achievements(status); CREATE INDEX IF NOT EXISTS idx_achievements_assigned_depts ON achievements USING GIN (assigned_departments); CREATE INDEX IF NOT EXISTS idx_audit_logs_created_at ON audit_logs(created_at DESC); CREATE INDEX IF NOT EXISTS idx_audit_logs_username ON audit_logs(username); CREATE INDEX IF NOT EXISTS idx_notifications_created_at ON notifications(created_at DESC);