-- Lingyue Zhibao Database Schema -- PostgreSQL -- ============================================= -- Graph Core Tables -- ============================================= -- Node Types CREATE TABLE IF NOT EXISTS node_types ( id SERIAL PRIMARY KEY, type_code VARCHAR(50) NOT NULL UNIQUE, type_name VARCHAR(100) NOT NULL, description TEXT, icon VARCHAR(50), color VARCHAR(20), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Edge Types CREATE TABLE IF NOT EXISTS edge_types ( id SERIAL PRIMARY KEY, type_code VARCHAR(50) NOT NULL UNIQUE, type_name VARCHAR(100) NOT NULL, from_node_type VARCHAR(50), to_node_type VARCHAR(50), description TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Nodes CREATE TABLE IF NOT EXISTS nodes ( id BIGSERIAL PRIMARY KEY, node_type VARCHAR(50) NOT NULL, node_key VARCHAR(255), name VARCHAR(255), status VARCHAR(20) DEFAULT 'active', created_by BIGINT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_nodes_type ON nodes(node_type); CREATE INDEX idx_nodes_key ON nodes(node_key); -- Edges CREATE TABLE IF NOT EXISTS edges ( id BIGSERIAL PRIMARY KEY, edge_type VARCHAR(50) NOT NULL, from_node_id BIGINT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE, to_node_id BIGINT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE, sort_order INTEGER DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_edges_from ON edges(from_node_id); CREATE INDEX idx_edges_to ON edges(to_node_id); CREATE INDEX idx_edges_type ON edges(edge_type); -- Node Properties CREATE TABLE IF NOT EXISTS node_properties ( id BIGSERIAL PRIMARY KEY, node_id BIGINT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE, prop_key VARCHAR(100) NOT NULL, prop_value TEXT, prop_json JSONB, prop_number NUMERIC(20, 6), prop_date TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(node_id, prop_key) ); CREATE INDEX idx_node_props_node ON node_properties(node_id); CREATE INDEX idx_node_props_key ON node_properties(prop_key); -- Edge Properties CREATE TABLE IF NOT EXISTS edge_properties ( id BIGSERIAL PRIMARY KEY, edge_id BIGINT NOT NULL REFERENCES edges(id) ON DELETE CASCADE, prop_key VARCHAR(100) NOT NULL, prop_value TEXT, prop_json JSONB, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(edge_id, prop_key) ); CREATE INDEX idx_edge_props_edge ON edge_properties(edge_id); -- ============================================= -- Auth Tables -- ============================================= -- Users CREATE TABLE IF NOT EXISTS sys_users ( id BIGSERIAL PRIMARY KEY, node_id BIGINT REFERENCES nodes(id), username VARCHAR(50) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, salt VARCHAR(50), email VARCHAR(100), phone VARCHAR(20), avatar VARCHAR(255), real_name VARCHAR(50), department VARCHAR(100), position VARCHAR(100), status VARCHAR(20) DEFAULT 'active', last_login_at TIMESTAMP, last_login_ip VARCHAR(50), login_count INTEGER DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Roles CREATE TABLE IF NOT EXISTS sys_roles ( id SERIAL PRIMARY KEY, role_code VARCHAR(50) NOT NULL UNIQUE, role_name VARCHAR(100) NOT NULL, description TEXT, sort_order INTEGER DEFAULT 0, status VARCHAR(20) DEFAULT 'active', created_by BIGINT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Permissions CREATE TABLE IF NOT EXISTS sys_permissions ( id SERIAL PRIMARY KEY, perm_code VARCHAR(100) NOT NULL UNIQUE, perm_name VARCHAR(100) NOT NULL, perm_type VARCHAR(20), parent_id INTEGER, path VARCHAR(255), icon VARCHAR(50), component VARCHAR(255), sort_order INTEGER DEFAULT 0, status VARCHAR(20) DEFAULT 'active', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- User Roles CREATE TABLE IF NOT EXISTS sys_user_roles ( id SERIAL PRIMARY KEY, user_id BIGINT NOT NULL REFERENCES sys_users(id) ON DELETE CASCADE, role_id INTEGER NOT NULL REFERENCES sys_roles(id) ON DELETE CASCADE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(user_id, role_id) ); -- Role Permissions CREATE TABLE IF NOT EXISTS sys_role_permissions ( id SERIAL PRIMARY KEY, role_id INTEGER NOT NULL REFERENCES sys_roles(id) ON DELETE CASCADE, permission_id INTEGER NOT NULL REFERENCES sys_permissions(id) ON DELETE CASCADE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(role_id, permission_id) ); -- Sessions CREATE TABLE IF NOT EXISTS sys_sessions ( id BIGSERIAL PRIMARY KEY, user_id BIGINT NOT NULL REFERENCES sys_users(id) ON DELETE CASCADE, session_token VARCHAR(255) NOT NULL UNIQUE, refresh_token VARCHAR(255), device_type VARCHAR(50), device_info VARCHAR(255), ip_address VARCHAR(50), user_agent TEXT, expires_at TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_sessions_user ON sys_sessions(user_id); CREATE INDEX idx_sessions_token ON sys_sessions(session_token); -- Config CREATE TABLE IF NOT EXISTS sys_configs ( id SERIAL PRIMARY KEY, config_key VARCHAR(100) NOT NULL UNIQUE, config_value TEXT, config_type VARCHAR(20), description TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Dict Types CREATE TABLE IF NOT EXISTS sys_dict_types ( id SERIAL PRIMARY KEY, dict_code VARCHAR(50) NOT NULL UNIQUE, dict_name VARCHAR(100) NOT NULL, description TEXT, status VARCHAR(20) DEFAULT 'active', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Dict Items CREATE TABLE IF NOT EXISTS sys_dict_items ( id SERIAL PRIMARY KEY, dict_type_id INTEGER NOT NULL REFERENCES sys_dict_types(id) ON DELETE CASCADE, item_value VARCHAR(100) NOT NULL, item_label VARCHAR(100) NOT NULL, sort_order INTEGER DEFAULT 0, status VARCHAR(20) DEFAULT 'active', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Login Logs CREATE TABLE IF NOT EXISTS sys_login_logs ( id BIGSERIAL PRIMARY KEY, user_id BIGINT, username VARCHAR(50), login_type VARCHAR(20), ip_address VARCHAR(50), user_agent TEXT, status VARCHAR(20), message TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Operation Logs CREATE TABLE IF NOT EXISTS sys_operation_logs ( id BIGSERIAL PRIMARY KEY, user_id BIGINT, username VARCHAR(50), operation VARCHAR(100), method VARCHAR(200), params TEXT, result TEXT, ip_address VARCHAR(50), duration INTEGER, status VARCHAR(20), error_msg TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- ============================================= -- File Tables -- ============================================= CREATE TABLE IF NOT EXISTS sys_files ( id BIGSERIAL PRIMARY KEY, file_key VARCHAR(100) NOT NULL UNIQUE, original_name VARCHAR(255) NOT NULL, storage_name VARCHAR(255), storage_path VARCHAR(500), file_type VARCHAR(50), file_size BIGINT, md5_hash VARCHAR(32), storage_type VARCHAR(20) DEFAULT 'local', bucket VARCHAR(100), url VARCHAR(500), thumbnail_url VARCHAR(500), uploaded_by BIGINT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_files_key ON sys_files(file_key); -- ============================================= -- Task Tables -- ============================================= CREATE TABLE IF NOT EXISTS sys_tasks ( id BIGSERIAL PRIMARY KEY, task_type VARCHAR(50) NOT NULL, task_key VARCHAR(100), payload TEXT, status VARCHAR(20) DEFAULT 'pending', priority INTEGER DEFAULT 0, retry_count INTEGER DEFAULT 0, max_retries INTEGER DEFAULT 3, result TEXT, error_msg TEXT, started_at TIMESTAMP, finished_at TIMESTAMP, created_by BIGINT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_tasks_status ON sys_tasks(status); CREATE INDEX idx_tasks_type ON sys_tasks(task_type); -- ============================================= -- Initial Data -- ============================================= -- Node Types INSERT INTO node_types (type_code, type_name, description) VALUES ('project', '项目', '评审项目'), ('element', '要素', '报告要素'), ('value', '值', '要素值'), ('attachment', '附件', '项目附件'), ('rule', '规则', '自动化规则'), ('user', '用户', '系统用户') ON CONFLICT (type_code) DO NOTHING; -- Edge Types INSERT INTO edge_types (type_code, type_name, from_node_type, to_node_type) VALUES ('has_element', '包含要素', 'project', 'element'), ('has_value', '包含值', 'project', 'value'), ('has_attachment', '包含附件', 'project', 'attachment'), ('has_rule', '包含规则', 'project', 'rule'), ('element_value', '要素值', 'element', 'value'), ('rule_input', '规则输入', 'rule', 'attachment'), ('rule_output', '规则输出', 'rule', 'element') ON CONFLICT (type_code) DO NOTHING; -- Default Admin User (password: admin123) INSERT INTO sys_users (username, password_hash, salt, real_name, status) VALUES ('admin', '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', '', '管理员', 'active') ON CONFLICT (username) DO NOTHING; -- Default Roles INSERT INTO sys_roles (role_code, role_name, description) VALUES ('admin', '管理员', '系统管理员'), ('user', '普通用户', '普通用户') ON CONFLICT (role_code) DO NOTHING;