temp
This commit is contained in:
270
urbanLifelineServ/.bin/database/postgres/bin.sh
Normal file
270
urbanLifelineServ/.bin/database/postgres/bin.sh
Normal file
@@ -0,0 +1,270 @@
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
# 定义颜色输出
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 设置脚本所在目录为工作目录
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
SQL_DIR="${SCRIPT_DIR}/sql"
|
||||
|
||||
# 打印带时间戳的日志
|
||||
log() {
|
||||
local level=$1
|
||||
local message=$2
|
||||
local color=$NC
|
||||
|
||||
case $level in
|
||||
"INFO") color=$BLUE;;
|
||||
"SUCCESS") color=$GREEN;;
|
||||
"WARN") color=$YELLOW;;
|
||||
"ERROR") color=$RED;;
|
||||
esac
|
||||
|
||||
echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] ${color}${level}${NC}: ${message}"
|
||||
}
|
||||
|
||||
# 数据库连接信息(可通过环境变量覆盖)
|
||||
DB_HOST=${POSTGRES_HOST:-"localhost"}
|
||||
DB_PORT=${POSTGRES_PORT:-"5432"}
|
||||
DB_NAME=${POSTGRES_DB:-"urban-lifeline"}
|
||||
DB_USER=${POSTGRES_USER:-"postgres"}
|
||||
DB_PASSWORD=${POSTGRES_PASSWORD:-"postgres"}
|
||||
|
||||
# 设置 PSQL 环境变量以支持中文
|
||||
export PGCLIENTENCODING=UTF8
|
||||
|
||||
# 检查psql命令是否可用
|
||||
check_psql() {
|
||||
if ! command -v psql &> /dev/null; then
|
||||
echo -e "${RED}Error: psql command not found. Please install PostgreSQL client.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 检查并创建数据库用户
|
||||
check_and_create_user() {
|
||||
local new_user=$1
|
||||
local new_password=$2
|
||||
|
||||
# 使用 postgres 用户执行
|
||||
if sudo -u postgres psql -c "SELECT 1 FROM pg_roles WHERE rolname = '$new_user'" | grep -q 1; then
|
||||
echo -e "${GREEN}User $new_user already exists${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}Creating user $new_user...${NC}"
|
||||
sudo -u postgres psql -c "CREATE USER $new_user WITH PASSWORD '$new_password' CREATEDB;"
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "${GREEN}User $new_user created successfully${NC}"
|
||||
else
|
||||
echo -e "${RED}Failed to create user $new_user${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 检查数据库连接
|
||||
check_db_connection() {
|
||||
# 首先尝试以当前用户身份连接
|
||||
if ! psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "postgres" -c '\q' &> /dev/null; then
|
||||
echo -e "${YELLOW}Could not connect with current settings, attempting to create user...${NC}"
|
||||
# 创建用户并设置权限
|
||||
check_and_create_user "$DB_USER" "$DB_PASSWORD"
|
||||
|
||||
# 再次检查连接
|
||||
if ! psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "postgres" -c '\q' &> /dev/null; then
|
||||
echo -e "${RED}Error: Could not connect to PostgreSQL server.${NC}"
|
||||
echo "Please check your connection settings:"
|
||||
echo "Host: $DB_HOST"
|
||||
echo "Port: $DB_PORT"
|
||||
echo "User: $DB_USER"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 执行SQL文件
|
||||
execute_sql_file() {
|
||||
local sql_file=$1
|
||||
if [ ! -f "$sql_file" ]; then
|
||||
echo -e "${RED}Error: SQL file not found: $sql_file${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Executing SQL file: $sql_file${NC}"
|
||||
PGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -f "$sql_file"
|
||||
local status=$?
|
||||
if [ $status -eq 0 ]; then
|
||||
echo -e "${GREEN}Successfully executed: $sql_file${NC}"
|
||||
else
|
||||
echo -e "${RED}Failed to execute: $sql_file${NC}"
|
||||
return $status
|
||||
fi
|
||||
}
|
||||
|
||||
# 初始化数据库
|
||||
init() {
|
||||
echo -e "${YELLOW}Initializing database...${NC}"
|
||||
|
||||
# 执行完整的初始化脚本
|
||||
log "INFO" "Executing initialization script..."
|
||||
# Run from inside the SQL_DIR so relative \i includes in initAll.sql (like createDB.sql)
|
||||
# resolve relative to the SQL directory.
|
||||
(
|
||||
if [ ! -d "$SQL_DIR" ]; then
|
||||
echo -e "${RED}Error: SQL directory not found: $SQL_DIR${NC}"
|
||||
exit 1
|
||||
fi
|
||||
cd "$SQL_DIR" || exit 1
|
||||
PGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "postgres" -v ON_ERROR_STOP=1 -f "initAll.sql"
|
||||
)
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
log "SUCCESS" "Database initialization completed successfully"
|
||||
else
|
||||
log "ERROR" "Database initialization failed"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}Failed to create database.${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 2. 创建扩展和设置搜索路径
|
||||
echo -e "${YELLOW}Creating extensions...${NC}"
|
||||
check_extensions_availability() {
|
||||
# 检查服务器上是否存在需创建的扩展
|
||||
local missing=()
|
||||
local exts=("uuid-ossp" "pg_trgm" "btree_gist")
|
||||
for ext in "${exts[@]}"; do
|
||||
# 查询 pg_available_extensions 来判断扩展是否已安装到服务器目录
|
||||
if ! PGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -tAc "SELECT 1 FROM pg_available_extensions WHERE name = '$ext';" | grep -q 1; then
|
||||
missing+=("$ext")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#missing[@]} -ne 0 ]; then
|
||||
echo -e "${RED}Error: The following server-side extensions are not available: ${missing[*]}${NC}"
|
||||
echo "If you compiled PostgreSQL from source, you need to build and install the contrib modules into the server's installation prefix. Example steps:"
|
||||
echo " # 在 PostgreSQL 源码目录下运行:"
|
||||
echo " cd /path/to/postgresql-source/contrib"
|
||||
echo " make"
|
||||
echo " sudo make install"
|
||||
echo "或者只安装缺失的模块(例如 uuid-ossp):"
|
||||
echo " cd /path/to/postgresql-source/contrib/uuid-ossp"
|
||||
echo " make"
|
||||
echo " sudo make install"
|
||||
echo "安装完成后,重启 PostgreSQL 服务并重新运行此脚本:"
|
||||
echo " sudo systemctl restart postgresql"
|
||||
echo "如果你使用的是容器或自定义路径,请确保将编译安装的扩展安装到 PostgreSQL 的 \$(pg_config --sharedir)/extension 目录下。"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# 检查扩展可用性,若缺失则给出建议并退出
|
||||
if ! check_extensions_availability; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
PGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
|
||||
CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";
|
||||
CREATE EXTENSION IF NOT EXISTS \"pg_trgm\";
|
||||
CREATE EXTENSION IF NOT EXISTS \"btree_gist\";"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}Failed to create extensions.${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 3. 逐个执行初始化SQL文件
|
||||
echo -e "${YELLOW}Initializing tables...${NC}"
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
# 跳过注释和空行
|
||||
[[ $line =~ ^--.*$ ]] && continue
|
||||
[[ -z "${line// }" ]] && continue
|
||||
|
||||
# 从 \i 命令中提取文件名
|
||||
if [[ $line =~ \\i[[:space:]]+([^[:space:]]+) ]]; then
|
||||
sql_file="${SQL_DIR}/${BASH_REMATCH[1]}"
|
||||
if [[ $sql_file != *"createDB.sql"* ]]; then # 跳过createDB.sql
|
||||
echo -e "${YELLOW}Executing: $sql_file${NC}"
|
||||
PGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -f "$sql_file"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED}Failed to execute: $sql_file${NC}"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done < "${SQL_DIR}/initAll.sql"
|
||||
|
||||
# 4. 设置搜索路径
|
||||
echo -e "${YELLOW}Setting search path...${NC}"
|
||||
PGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
|
||||
ALTER DATABASE $DB_NAME SET search_path TO sys, public;"
|
||||
|
||||
echo -e "${GREEN}Database initialization completed successfully.${NC}"
|
||||
return 0
|
||||
}
|
||||
|
||||
# 重新初始化数据库
|
||||
reinit() {
|
||||
echo -e "${YELLOW}Reinitializing database...${NC}"
|
||||
delete
|
||||
init
|
||||
}
|
||||
|
||||
# 删除数据库
|
||||
delete() {
|
||||
echo -e "${YELLOW}Deleting database...${NC}"
|
||||
|
||||
# 确保没有活动连接
|
||||
PGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "postgres" -c "
|
||||
SELECT pg_terminate_backend(pg_stat_activity.pid)
|
||||
FROM pg_stat_activity
|
||||
WHERE pg_stat_activity.datname = '$DB_NAME'
|
||||
AND pid <> pg_backend_pid();"
|
||||
|
||||
# 删除数据库
|
||||
PGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "postgres" -c "DROP DATABASE IF EXISTS $DB_NAME;"
|
||||
|
||||
echo -e "${GREEN}Database deleted.${NC}"
|
||||
}
|
||||
|
||||
# 显示帮助信息
|
||||
show_help() {
|
||||
echo "Usage: $0 {init|reinit|delete}"
|
||||
echo "Commands:"
|
||||
echo " init Initialize the database"
|
||||
echo " reinit Reinitialize the database (delete and create)"
|
||||
echo " delete Delete the database"
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
check_psql
|
||||
check_db_connection
|
||||
|
||||
case "$1" in
|
||||
"init")
|
||||
init
|
||||
;;
|
||||
"reinit")
|
||||
reinit
|
||||
;;
|
||||
"delete")
|
||||
delete
|
||||
;;
|
||||
*)
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Call main with all passed arguments so the script runs when invoked
|
||||
main "$@"
|
||||
27
urbanLifelineServ/.bin/database/postgres/sql/createDB.sql
Normal file
27
urbanLifelineServ/.bin/database/postgres/sql/createDB.sql
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
-- 删除已存在的数据库(如果存在)
|
||||
DROP DATABASE IF EXISTS urban-lifeline;
|
||||
|
||||
-- 创建新数据库,使用 UTF8 编码,并设置适合中文的排序规则
|
||||
-- 使用 template0 确保干净的数据库模板
|
||||
-- zh_CN.UTF-8 支持中文字符排序和比较
|
||||
CREATE DATABASE urban-lifeline
|
||||
ENCODING 'UTF8'
|
||||
TEMPLATE template0
|
||||
LC_COLLATE 'zh_CN.UTF-8'
|
||||
LC_CTYPE 'zh_CN.UTF-8';
|
||||
|
||||
-- 连接到新创建的数据库
|
||||
\c urban-lifeline;
|
||||
|
||||
-- -- 创建扩展(如果需要)
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- UUID 支持
|
||||
CREATE EXTENSION IF NOT EXISTS "pg_trgm"; -- 文本搜索支持
|
||||
CREATE EXTENSION IF NOT EXISTS "btree_gist"; -- GiST 索引支持
|
||||
|
||||
-- 设置搜索路径(可选,但建议设置)
|
||||
-- ALTER DATABASE urban-lifeline SET search_path TO sys, public;
|
||||
|
||||
-- sudo ./configure --prefix=/opt/postgres/postgres-17.6
|
||||
-- --with-uuid=ossp --with-openssl --with-libxml --with-pam
|
||||
-- && sudo make && sudo make install
|
||||
@@ -0,0 +1,308 @@
|
||||
-- =============================
|
||||
-- 智能体管理和平台基础设施模块
|
||||
-- 支持:智能体广场、API集成管理、智能体运维监控
|
||||
-- =============================
|
||||
CREATE SCHEMA IF NOT EXISTS agent;
|
||||
|
||||
-- 智能体定义表
|
||||
DROP TABLE IF EXISTS agent.tb_agent CASCADE;
|
||||
CREATE TABLE agent.tb_agent (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
agent_id VARCHAR(50) NOT NULL, -- 智能体ID
|
||||
agent_code VARCHAR(100) NOT NULL, -- 智能体编码(唯一标识)
|
||||
agent_name VARCHAR(255) NOT NULL, -- 智能体名称
|
||||
agent_type VARCHAR(50) NOT NULL, -- 智能体类型:bidding-招投标/customer_service-客服/knowledge_assistant-知识助手/custom-自定义
|
||||
display_name VARCHAR(255) NOT NULL, -- 展示名称
|
||||
description TEXT, -- 智能体描述
|
||||
icon VARCHAR(500), -- 图标URL
|
||||
banner VARCHAR(500), -- Banner图URL
|
||||
version VARCHAR(20) DEFAULT '1.0.0', -- 版本号
|
||||
model_provider VARCHAR(50), -- 模型提供商:openai/anthropic/baidu/aliyun/custom
|
||||
model_name VARCHAR(100), -- 模型名称
|
||||
model_config JSONB, -- 模型配置(温度、最大tokens等)
|
||||
prompt_template TEXT, -- 提示词模板
|
||||
system_prompt TEXT, -- 系统提示词
|
||||
kb_ids VARCHAR(50)[], -- 关联知识库ID数组
|
||||
tool_ids VARCHAR(50)[], -- 关联工具ID数组
|
||||
capabilities TEXT[], -- 能力列表
|
||||
access_level VARCHAR(20) DEFAULT 'private', -- 访问级别:public-公开/private-私有/internal-内部
|
||||
is_published BOOLEAN DEFAULT false, -- 是否发布到智能体广场
|
||||
usage_count INTEGER DEFAULT 0, -- 使用次数
|
||||
rating DECIMAL(3,2) DEFAULT 0, -- 评分(0-5)
|
||||
rating_count INTEGER DEFAULT 0, -- 评分人数
|
||||
tags TEXT[], -- 标签数组
|
||||
category VARCHAR(100), -- 分类
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
owner_user_id VARCHAR(50), -- 所有者用户ID
|
||||
status VARCHAR(20) DEFAULT 'active', -- 状态:active-激活/inactive-停用/under_maintenance-维护中
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (agent_id),
|
||||
UNIQUE (optsn),
|
||||
UNIQUE (agent_code)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_agent_type ON agent.tb_agent(agent_type) WHERE deleted = false;
|
||||
CREATE INDEX idx_agent_published ON agent.tb_agent(is_published) WHERE deleted = false AND is_published = true;
|
||||
CREATE INDEX idx_agent_category ON agent.tb_agent(category) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE agent.tb_agent IS '智能体定义表';
|
||||
COMMENT ON COLUMN agent.tb_agent.agent_type IS '智能体类型:bidding/customer_service/knowledge_assistant/custom';
|
||||
|
||||
-- 智能体会话表
|
||||
DROP TABLE IF EXISTS agent.tb_agent_session CASCADE;
|
||||
CREATE TABLE agent.tb_agent_session (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
session_id VARCHAR(50) NOT NULL, -- 会话ID
|
||||
agent_id VARCHAR(50) NOT NULL, -- 智能体ID
|
||||
user_id VARCHAR(50) NOT NULL, -- 用户ID
|
||||
session_type VARCHAR(30) DEFAULT 'chat', -- 会话类型:chat-对话/task-任务/workflow-工作流
|
||||
session_name VARCHAR(255), -- 会话名称
|
||||
context JSONB, -- 会话上下文
|
||||
session_status VARCHAR(20) DEFAULT 'active', -- 会话状态:active-活跃/paused-暂停/ended-结束
|
||||
start_time timestamptz DEFAULT now(), -- 开始时间
|
||||
end_time timestamptz, -- 结束时间
|
||||
message_count INTEGER DEFAULT 0, -- 消息数量
|
||||
token_usage INTEGER DEFAULT 0, -- Token使用量
|
||||
cost DECIMAL(10,4) DEFAULT 0, -- 成本
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (session_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (agent_id) REFERENCES agent.tb_agent(agent_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_session_agent ON agent.tb_agent_session(agent_id) WHERE deleted = false;
|
||||
CREATE INDEX idx_session_user ON agent.tb_agent_session(user_id) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE agent.tb_agent_session IS '智能体会话表';
|
||||
|
||||
-- 智能体消息表
|
||||
DROP TABLE IF EXISTS agent.tb_agent_message CASCADE;
|
||||
CREATE TABLE agent.tb_agent_message (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
message_id VARCHAR(50) NOT NULL, -- 消息ID
|
||||
session_id VARCHAR(50) NOT NULL, -- 会话ID
|
||||
agent_id VARCHAR(50) NOT NULL, -- 智能体ID
|
||||
role VARCHAR(20) NOT NULL, -- 角色:user-用户/assistant-助手/system-系统/function-函数
|
||||
content TEXT, -- 消息内容
|
||||
content_type VARCHAR(30) DEFAULT 'text', -- 内容类型:text-文本/image-图片/file-文件/structured-结构化数据
|
||||
function_call JSONB, -- 函数调用(JSON格式)
|
||||
function_response JSONB, -- 函数响应
|
||||
token_count INTEGER, -- Token数量
|
||||
model_name VARCHAR(100), -- 使用的模型
|
||||
kb_references JSONB, -- 知识库引用(JSON数组)
|
||||
metadata JSONB, -- 消息元数据
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (message_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (session_id) REFERENCES agent.tb_agent_session(session_id),
|
||||
FOREIGN KEY (agent_id) REFERENCES agent.tb_agent(agent_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_msg_session ON agent.tb_agent_message(session_id, create_time) WHERE deleted = false;
|
||||
CREATE INDEX idx_msg_agent ON agent.tb_agent_message(agent_id) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE agent.tb_agent_message IS '智能体消息表';
|
||||
|
||||
-- 智能体工具表
|
||||
DROP TABLE IF EXISTS agent.tb_agent_tool CASCADE;
|
||||
CREATE TABLE agent.tb_agent_tool (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
tool_id VARCHAR(50) NOT NULL, -- 工具ID
|
||||
tool_code VARCHAR(100) NOT NULL, -- 工具编码
|
||||
tool_name VARCHAR(255) NOT NULL, -- 工具名称
|
||||
tool_type VARCHAR(50) NOT NULL, -- 工具类型:api-API调用/function-函数/plugin-插件/integration-集成
|
||||
description TEXT, -- 工具描述
|
||||
function_schema JSONB, -- 函数Schema(OpenAI function calling格式)
|
||||
api_endpoint VARCHAR(500), -- API端点
|
||||
api_method VARCHAR(10), -- API方法:GET/POST/PUT/DELETE
|
||||
api_headers JSONB, -- API请求头
|
||||
auth_type VARCHAR(30), -- 认证类型:none/api_key/oauth2/bearer
|
||||
auth_config JSONB, -- 认证配置(加密存储)
|
||||
request_template TEXT, -- 请求模板
|
||||
response_template TEXT, -- 响应模板
|
||||
timeout_seconds INTEGER DEFAULT 30, -- 超时时间(秒)
|
||||
retry_count INTEGER DEFAULT 3, -- 重试次数
|
||||
is_enabled BOOLEAN DEFAULT true, -- 是否启用
|
||||
usage_count INTEGER DEFAULT 0, -- 使用次数
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (tool_id),
|
||||
UNIQUE (optsn),
|
||||
UNIQUE (tool_code)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_tool_type ON agent.tb_agent_tool(tool_type) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE agent.tb_agent_tool IS '智能体工具表';
|
||||
|
||||
-- API集成注册表
|
||||
DROP TABLE IF EXISTS agent.tb_api_integration CASCADE;
|
||||
CREATE TABLE agent.tb_api_integration (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
integration_id VARCHAR(50) NOT NULL, -- 集成ID
|
||||
integration_name VARCHAR(255) NOT NULL, -- 集成名称
|
||||
integration_type VARCHAR(50) NOT NULL, -- 集成类型:rest_api/soap/graphql/webhook/mq
|
||||
provider VARCHAR(100), -- 提供商
|
||||
base_url VARCHAR(500), -- 基础URL
|
||||
version VARCHAR(20), -- API版本
|
||||
auth_type VARCHAR(30) DEFAULT 'none', -- 认证类型
|
||||
auth_config JSONB, -- 认证配置(加密存储)
|
||||
endpoints JSONB, -- 端点列表(JSON数组)
|
||||
rate_limit INTEGER, -- 速率限制(请求/秒)
|
||||
timeout_seconds INTEGER DEFAULT 30, -- 超时时间
|
||||
retry_config JSONB, -- 重试配置
|
||||
health_check_url VARCHAR(500), -- 健康检查URL
|
||||
health_status VARCHAR(20) DEFAULT 'unknown', -- 健康状态:healthy-健康/unhealthy-不健康/unknown-未知
|
||||
last_health_check timestamptz, -- 最后健康检查时间
|
||||
documentation_url VARCHAR(500), -- 文档URL
|
||||
is_enabled BOOLEAN DEFAULT true, -- 是否启用
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (integration_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_integration_type ON agent.tb_api_integration(integration_type) WHERE deleted = false;
|
||||
CREATE INDEX idx_integration_health ON agent.tb_api_integration(health_status) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE agent.tb_api_integration IS 'API集成注册表';
|
||||
|
||||
-- API调用日志表
|
||||
DROP TABLE IF EXISTS agent.tb_api_call_log CASCADE;
|
||||
CREATE TABLE agent.tb_api_call_log (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
log_id VARCHAR(50) NOT NULL, -- 日志ID
|
||||
integration_id VARCHAR(50), -- 集成ID
|
||||
tool_id VARCHAR(50), -- 工具ID
|
||||
agent_id VARCHAR(50), -- 智能体ID
|
||||
session_id VARCHAR(50), -- 会话ID
|
||||
user_id VARCHAR(50), -- 用户ID
|
||||
endpoint VARCHAR(500) NOT NULL, -- 请求端点
|
||||
method VARCHAR(10) NOT NULL, -- 请求方法
|
||||
request_headers JSONB, -- 请求头
|
||||
request_body TEXT, -- 请求体
|
||||
response_status INTEGER, -- 响应状态码
|
||||
response_headers JSONB, -- 响应头
|
||||
response_body TEXT, -- 响应体
|
||||
duration_ms INTEGER, -- 请求耗时(毫秒)
|
||||
is_success BOOLEAN, -- 是否成功
|
||||
error_message TEXT, -- 错误信息
|
||||
retry_count INTEGER DEFAULT 0, -- 重试次数
|
||||
ip_address VARCHAR(45), -- IP地址
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
PRIMARY KEY (log_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_api_log_integration ON agent.tb_api_call_log(integration_id, create_time DESC);
|
||||
CREATE INDEX idx_api_log_agent ON agent.tb_api_call_log(agent_id, create_time DESC);
|
||||
CREATE INDEX idx_api_log_status ON agent.tb_api_call_log(is_success, create_time DESC);
|
||||
|
||||
COMMENT ON TABLE agent.tb_api_call_log IS 'API调用日志表';
|
||||
|
||||
-- 智能体监控指标表
|
||||
DROP TABLE IF EXISTS agent.tb_agent_metrics CASCADE;
|
||||
CREATE TABLE agent.tb_agent_metrics (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
metric_id VARCHAR(50) NOT NULL, -- 指标ID
|
||||
agent_id VARCHAR(50) NOT NULL, -- 智能体ID
|
||||
metric_date DATE NOT NULL, -- 指标日期
|
||||
metric_hour INTEGER, -- 指标小时(0-23)
|
||||
total_sessions INTEGER DEFAULT 0, -- 总会话数
|
||||
active_sessions INTEGER DEFAULT 0, -- 活跃会话数
|
||||
total_messages INTEGER DEFAULT 0, -- 总消息数
|
||||
total_tokens BIGINT DEFAULT 0, -- 总Token数
|
||||
total_cost DECIMAL(10,4) DEFAULT 0, -- 总成本
|
||||
avg_response_time INTEGER, -- 平均响应时间(毫秒)
|
||||
success_rate DECIMAL(5,4), -- 成功率
|
||||
error_count INTEGER DEFAULT 0, -- 错误次数
|
||||
api_call_count INTEGER DEFAULT 0, -- API调用次数
|
||||
avg_rating DECIMAL(3,2), -- 平均评分
|
||||
rating_count INTEGER DEFAULT 0, -- 评分数量
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
PRIMARY KEY (metric_id),
|
||||
UNIQUE (optsn),
|
||||
UNIQUE (agent_id, metric_date, metric_hour),
|
||||
FOREIGN KEY (agent_id) REFERENCES agent.tb_agent(agent_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_metrics_agent_date ON agent.tb_agent_metrics(agent_id, metric_date DESC);
|
||||
|
||||
COMMENT ON TABLE agent.tb_agent_metrics IS '智能体监控指标表';
|
||||
|
||||
-- 智能体异常日志表
|
||||
DROP TABLE IF EXISTS agent.tb_agent_error_log CASCADE;
|
||||
CREATE TABLE agent.tb_agent_error_log (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
log_id VARCHAR(50) NOT NULL, -- 日志ID
|
||||
agent_id VARCHAR(50) NOT NULL, -- 智能体ID
|
||||
session_id VARCHAR(50), -- 会话ID
|
||||
error_type VARCHAR(50) NOT NULL, -- 错误类型:model_error-模型错误/api_error-API错误/timeout-超时/rate_limit-限流/other-其他
|
||||
error_code VARCHAR(50), -- 错误代码
|
||||
error_message TEXT NOT NULL, -- 错误信息
|
||||
stack_trace TEXT, -- 堆栈跟踪
|
||||
request_context JSONB, -- 请求上下文
|
||||
severity VARCHAR(20) DEFAULT 'error', -- 严重级别:critical-致命/error-错误/warning-警告
|
||||
is_resolved BOOLEAN DEFAULT false, -- 是否已解决
|
||||
resolution_notes TEXT, -- 解决方案备注
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
resolve_time timestamptz, -- 解决时间
|
||||
PRIMARY KEY (log_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (agent_id) REFERENCES agent.tb_agent(agent_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_error_agent ON agent.tb_agent_error_log(agent_id, create_time DESC);
|
||||
CREATE INDEX idx_error_severity ON agent.tb_agent_error_log(severity) WHERE is_resolved = false;
|
||||
|
||||
COMMENT ON TABLE agent.tb_agent_error_log IS '智能体异常日志表';
|
||||
|
||||
-- 智能体评价表
|
||||
DROP TABLE IF EXISTS agent.tb_agent_rating CASCADE;
|
||||
CREATE TABLE agent.tb_agent_rating (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
rating_id VARCHAR(50) NOT NULL, -- 评价ID
|
||||
agent_id VARCHAR(50) NOT NULL, -- 智能体ID
|
||||
session_id VARCHAR(50), -- 会话ID
|
||||
user_id VARCHAR(50) NOT NULL, -- 用户ID
|
||||
rating INTEGER NOT NULL, -- 评分(1-5星)
|
||||
dimensions JSONB, -- 分维度评分(准确性、速度、友好度等)
|
||||
feedback TEXT, -- 评价反馈
|
||||
tags TEXT[], -- 标签
|
||||
is_anonymous BOOLEAN DEFAULT false, -- 是否匿名
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (rating_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (agent_id) REFERENCES agent.tb_agent(agent_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_rating_agent ON agent.tb_agent_rating(agent_id) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE agent.tb_agent_rating IS '智能体评价表';
|
||||
209
urbanLifelineServ/.bin/database/postgres/sql/createTableAll.sql
Normal file
209
urbanLifelineServ/.bin/database/postgres/sql/createTableAll.sql
Normal file
@@ -0,0 +1,209 @@
|
||||
-- =============================
|
||||
-- 泰豪电源AI数智化平台 - 完整数据库初始化脚本
|
||||
-- 包含所有业务模块的表结构
|
||||
-- =============================
|
||||
|
||||
-- 安装必要的扩展
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- UUID生成
|
||||
CREATE EXTENSION IF NOT EXISTS "pg_trgm"; -- 全文搜索
|
||||
CREATE EXTENSION IF NOT EXISTS "btree_gin"; -- GIN索引支持
|
||||
-- CREATE EXTENSION IF NOT EXISTS "vector"; -- pgvector向量检索(需要单独安装)
|
||||
|
||||
-- =============================
|
||||
-- 1. 系统基础模块(权限、用户、部门、角色)
|
||||
-- =============================
|
||||
\i createTablePermission.sql
|
||||
\i createTableUser.sql
|
||||
|
||||
-- =============================
|
||||
-- 2. 文件管理模块
|
||||
-- =============================
|
||||
\i createTableFile.sql
|
||||
|
||||
-- =============================
|
||||
-- 3. 消息通知模块
|
||||
-- =============================
|
||||
\i createTableMessage.sql
|
||||
|
||||
-- =============================
|
||||
-- 4. 日志模块
|
||||
-- =============================
|
||||
\i createTableLog.sql
|
||||
|
||||
-- =============================
|
||||
-- 5. 配置管理模块
|
||||
-- =============================
|
||||
\i createTableConfig.sql
|
||||
|
||||
-- =============================
|
||||
-- 6. 知识库管理模块
|
||||
-- =============================
|
||||
\i createTableKnowledge.sql
|
||||
|
||||
-- =============================
|
||||
-- 7. 招投标智能体业务模块
|
||||
-- =============================
|
||||
\i createTableBidding.sql
|
||||
|
||||
-- =============================
|
||||
-- 8. 智能客服系统业务模块
|
||||
-- =============================
|
||||
\i createTableCustomerService.sql
|
||||
|
||||
-- =============================
|
||||
-- 9. 智能体管理和平台基础设施模块
|
||||
-- =============================
|
||||
\i createTableAgent.sql
|
||||
|
||||
-- =============================
|
||||
-- 创建通用触发器函数
|
||||
-- =============================
|
||||
|
||||
-- 自动更新update_time的触发器函数
|
||||
CREATE OR REPLACE FUNCTION public.update_modified_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.update_time = now();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- 为所有表添加update_time触发器的辅助函数
|
||||
CREATE OR REPLACE FUNCTION public.create_update_triggers()
|
||||
RETURNS void AS $$
|
||||
DECLARE
|
||||
r RECORD;
|
||||
BEGIN
|
||||
FOR r IN
|
||||
SELECT schemaname, tablename
|
||||
FROM pg_tables
|
||||
WHERE schemaname IN ('sys', 'file', 'message', 'log', 'config', 'knowledge', 'bidding', 'customer_service', 'agent')
|
||||
AND tablename LIKE 'tb_%'
|
||||
LOOP
|
||||
-- 检查表是否有update_time列
|
||||
IF EXISTS (
|
||||
SELECT 1
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = r.schemaname
|
||||
AND table_name = r.tablename
|
||||
AND column_name = 'update_time'
|
||||
) THEN
|
||||
-- 删除已存在的触发器
|
||||
EXECUTE format('DROP TRIGGER IF EXISTS trg_%s_update_time ON %I.%I',
|
||||
r.tablename, r.schemaname, r.tablename);
|
||||
|
||||
-- 创建新触发器
|
||||
EXECUTE format('CREATE TRIGGER trg_%s_update_time
|
||||
BEFORE UPDATE ON %I.%I
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.update_modified_column()',
|
||||
r.tablename, r.schemaname, r.tablename);
|
||||
|
||||
RAISE NOTICE 'Created trigger for %.%', r.schemaname, r.tablename;
|
||||
END IF;
|
||||
END LOOP;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- 执行触发器创建
|
||||
SELECT public.create_update_triggers();
|
||||
|
||||
-- =============================
|
||||
-- 创建视图
|
||||
-- =============================
|
||||
|
||||
-- 用户完整信息视图
|
||||
CREATE OR REPLACE VIEW sys.v_user_full_info AS
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.email,
|
||||
u.phone,
|
||||
u.wechat_id,
|
||||
u.status,
|
||||
ui.avatar,
|
||||
ui.full_name,
|
||||
ui.gender,
|
||||
ui.level,
|
||||
u.create_time,
|
||||
u.update_time
|
||||
FROM sys.tb_sys_user u
|
||||
LEFT JOIN sys.tb_sys_user_info ui ON u.user_id = ui.user_id
|
||||
WHERE u.deleted = false AND (ui.deleted = false OR ui.deleted IS NULL);
|
||||
|
||||
-- 用户角色权限视图
|
||||
CREATE OR REPLACE VIEW sys.v_user_role_permission AS
|
||||
SELECT DISTINCT
|
||||
ur.user_id,
|
||||
r.role_id,
|
||||
r.name AS role_name,
|
||||
p.permission_id,
|
||||
p.code AS permission_code,
|
||||
p.name AS permission_name,
|
||||
m.module_id,
|
||||
m.name AS module_name
|
||||
FROM sys.tb_sys_user_role ur
|
||||
JOIN sys.tb_sys_role r ON ur.role_id = r.role_id
|
||||
JOIN sys.tb_sys_role_permission rp ON r.role_id = rp.role_id
|
||||
JOIN sys.tb_sys_permission p ON rp.permission_id = p.permission_id
|
||||
LEFT JOIN sys.tb_sys_module m ON p.module_id = m.module_id
|
||||
WHERE ur.deleted = false
|
||||
AND r.deleted = false
|
||||
AND rp.deleted = false
|
||||
AND p.deleted = false;
|
||||
|
||||
-- 智能体使用统计视图
|
||||
CREATE OR REPLACE VIEW agent.v_agent_usage_stats AS
|
||||
SELECT
|
||||
a.agent_id,
|
||||
a.agent_name,
|
||||
a.agent_type,
|
||||
COUNT(DISTINCT s.session_id) AS total_sessions,
|
||||
COUNT(DISTINCT s.user_id) AS unique_users,
|
||||
SUM(s.message_count) AS total_messages,
|
||||
AVG(s.token_usage) AS avg_token_usage,
|
||||
AVG(r.rating) AS avg_rating,
|
||||
COUNT(r.rating_id) AS rating_count,
|
||||
MAX(s.start_time) AS last_used_time
|
||||
FROM agent.tb_agent a
|
||||
LEFT JOIN agent.tb_agent_session s ON a.agent_id = s.agent_id AND s.deleted = false
|
||||
LEFT JOIN agent.tb_agent_rating r ON a.agent_id = r.agent_id AND r.deleted = false
|
||||
WHERE a.deleted = false
|
||||
GROUP BY a.agent_id, a.agent_name, a.agent_type;
|
||||
|
||||
-- 客服工单统计视图
|
||||
CREATE OR REPLACE VIEW customer_service.v_ticket_stats AS
|
||||
SELECT
|
||||
t.ticket_status,
|
||||
t.priority,
|
||||
t.ticket_type,
|
||||
COUNT(*) AS ticket_count,
|
||||
AVG(EXTRACT(EPOCH FROM (t.resolution_time - t.create_time))/3600) AS avg_resolution_hours,
|
||||
AVG(t.customer_rating) AS avg_rating,
|
||||
COUNT(CASE WHEN t.is_overdue THEN 1 END) AS overdue_count
|
||||
FROM customer_service.tb_ticket t
|
||||
WHERE t.deleted = false
|
||||
GROUP BY t.ticket_status, t.priority, t.ticket_type;
|
||||
|
||||
-- 招投标项目统计视图
|
||||
CREATE OR REPLACE VIEW bidding.v_project_stats AS
|
||||
SELECT
|
||||
p.project_status,
|
||||
p.project_type,
|
||||
COUNT(*) AS project_count,
|
||||
SUM(p.budget_amount) AS total_budget,
|
||||
SUM(CASE WHEN p.winning_status = 'won' THEN 1 ELSE 0 END) AS won_count,
|
||||
SUM(CASE WHEN p.winning_status = 'won' THEN p.winning_amount ELSE 0 END) AS total_won_amount,
|
||||
AVG(CASE WHEN p.winning_status = 'won' THEN p.winning_amount / NULLIF(p.budget_amount, 0) ELSE NULL END) AS avg_win_rate
|
||||
FROM bidding.tb_bidding_project p
|
||||
WHERE p.deleted = false
|
||||
GROUP BY p.project_status, p.project_type;
|
||||
|
||||
COMMENT ON VIEW sys.v_user_full_info IS '用户完整信息视图';
|
||||
COMMENT ON VIEW sys.v_user_role_permission IS '用户角色权限视图';
|
||||
COMMENT ON VIEW agent.v_agent_usage_stats IS '智能体使用统计视图';
|
||||
COMMENT ON VIEW customer_service.v_ticket_stats IS '客服工单统计视图';
|
||||
COMMENT ON VIEW bidding.v_project_stats IS '招投标项目统计视图';
|
||||
|
||||
-- =============================
|
||||
-- 数据库初始化完成
|
||||
-- =============================
|
||||
@@ -0,0 +1,264 @@
|
||||
-- =============================
|
||||
-- 招投标智能体业务模块
|
||||
-- 支持:招标文件管理、投标文件生成、评分分析、流程跟踪
|
||||
-- =============================
|
||||
CREATE SCHEMA IF NOT EXISTS bidding;
|
||||
|
||||
-- 招标项目表
|
||||
DROP TABLE IF EXISTS bidding.tb_bidding_project CASCADE;
|
||||
CREATE TABLE bidding.tb_bidding_project (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
project_id VARCHAR(50) NOT NULL, -- 项目ID
|
||||
project_no VARCHAR(100) NOT NULL, -- 项目编号
|
||||
project_name VARCHAR(500) NOT NULL, -- 项目名称
|
||||
project_type VARCHAR(50) NOT NULL, -- 项目类型:public-公开招标/invitation-邀请招标/competitive_negotiation-竞争性谈判
|
||||
industry VARCHAR(100), -- 所属行业
|
||||
source_platform VARCHAR(100), -- 来源平台(如:政府采购网、企业官网等)
|
||||
source_url VARCHAR(500), -- 来源URL
|
||||
publish_date timestamptz, -- 发布日期
|
||||
deadline timestamptz, -- 投标截止日期
|
||||
opening_date timestamptz, -- 开标日期
|
||||
budget_amount DECIMAL(18,2), -- 预算金额
|
||||
currency VARCHAR(10) DEFAULT 'CNY', -- 货币单位
|
||||
project_status VARCHAR(30) NOT NULL DEFAULT 'collecting', -- 项目状态:collecting-收集中/analyzing-分析中/preparing-准备投标/submitted-已提交/opened-已开标/won-中标/lost-未中标/abandoned-放弃
|
||||
winning_status VARCHAR(30), -- 中标状态:pending-待定/won-中标/lost-未中标
|
||||
winning_amount DECIMAL(18,2), -- 中标金额
|
||||
client_name VARCHAR(255), -- 客户名称
|
||||
client_contact VARCHAR(100), -- 客户联系方式
|
||||
contact_person VARCHAR(100), -- 联系人
|
||||
project_location VARCHAR(500), -- 项目地点
|
||||
description TEXT, -- 项目描述
|
||||
keywords TEXT[], -- 关键词数组
|
||||
metadata JSONB DEFAULT NULL, -- 项目元数据
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
responsible_user VARCHAR(50), -- 负责人
|
||||
team_members VARCHAR(50)[], -- 团队成员数组
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (project_id),
|
||||
UNIQUE (optsn),
|
||||
UNIQUE (project_no)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_project_status ON bidding.tb_bidding_project(project_status) WHERE deleted = false;
|
||||
CREATE INDEX idx_project_deadline ON bidding.tb_bidding_project(deadline) WHERE deleted = false;
|
||||
CREATE INDEX idx_project_dept ON bidding.tb_bidding_project(dept_path) WHERE deleted = false;
|
||||
CREATE INDEX idx_project_responsible ON bidding.tb_bidding_project(responsible_user) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE bidding.tb_bidding_project IS '招标项目表';
|
||||
COMMENT ON COLUMN bidding.tb_bidding_project.project_status IS '项目状态:collecting/analyzing/preparing/submitted/opened/won/lost/abandoned';
|
||||
|
||||
-- 招标文件表
|
||||
DROP TABLE IF EXISTS bidding.tb_bidding_document CASCADE;
|
||||
CREATE TABLE bidding.tb_bidding_document (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
doc_id VARCHAR(50) NOT NULL, -- 文档ID
|
||||
project_id VARCHAR(50) NOT NULL, -- 所属项目ID
|
||||
doc_type VARCHAR(50) NOT NULL, -- 文档类型:tender-招标文件/technical-技术标/commercial-商务标/clarification-澄清文件/other-其他
|
||||
doc_name VARCHAR(500) NOT NULL, -- 文档名称
|
||||
file_id VARCHAR(50), -- 关联文件表ID
|
||||
file_path VARCHAR(500), -- 文件路径
|
||||
file_size BIGINT, -- 文件大小
|
||||
mime_type VARCHAR(100), -- MIME类型
|
||||
version VARCHAR(20) DEFAULT '1.0', -- 版本号
|
||||
language VARCHAR(20) DEFAULT 'zh-CN', -- 语言
|
||||
page_count INTEGER, -- 页数
|
||||
parse_status VARCHAR(30) DEFAULT 'pending', -- 解析状态:pending-待解析/parsing-解析中/completed-已完成/failed-失败
|
||||
parse_result JSONB, -- 解析结果(JSON格式:提取的要素、表格、图纸等)
|
||||
extraction_data JSONB, -- 提取的结构化数据
|
||||
ai_analysis TEXT, -- AI分析结果
|
||||
upload_date timestamptz DEFAULT now(), -- 上传日期
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (doc_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (project_id) REFERENCES bidding.tb_bidding_project(project_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_doc_project ON bidding.tb_bidding_document(project_id) WHERE deleted = false;
|
||||
CREATE INDEX idx_doc_type ON bidding.tb_bidding_document(doc_type) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE bidding.tb_bidding_document IS '招标文件表';
|
||||
COMMENT ON COLUMN bidding.tb_bidding_document.parse_status IS '解析状态:pending/parsing/completed/failed';
|
||||
|
||||
-- 招标要素提取表
|
||||
DROP TABLE IF EXISTS bidding.tb_bidding_requirement CASCADE;
|
||||
CREATE TABLE bidding.tb_bidding_requirement (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
req_id VARCHAR(50) NOT NULL, -- 要素ID
|
||||
project_id VARCHAR(50) NOT NULL, -- 所属项目ID
|
||||
doc_id VARCHAR(50), -- 来源文档ID
|
||||
req_category VARCHAR(50) NOT NULL, -- 要素类别:commercial-商务要素/technical-技术参数/veto-否决项/qualification-资质要求/delivery-交付要求/payment-付款条件/scoring-评分标准
|
||||
req_name VARCHAR(255) NOT NULL, -- 要素名称
|
||||
req_content TEXT NOT NULL, -- 要素内容
|
||||
req_value VARCHAR(500), -- 要素值
|
||||
is_mandatory BOOLEAN DEFAULT false, -- 是否必填
|
||||
is_veto BOOLEAN DEFAULT false, -- 是否为否决项
|
||||
priority INTEGER DEFAULT 0, -- 优先级
|
||||
extraction_method VARCHAR(30) DEFAULT 'ai', -- 提取方式:ai-AI提取/manual-人工录入
|
||||
confidence_score DECIMAL(5,4), -- 置信度分数(0-1)
|
||||
source_location JSONB, -- 来源位置(页码、段落等)
|
||||
compliance_status VARCHAR(30), -- 合规状态:compliant-符合/non_compliant-不符合/pending-待确认
|
||||
response_content TEXT, -- 响应内容(我方的应答)
|
||||
notes TEXT, -- 备注
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (req_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (project_id) REFERENCES bidding.tb_bidding_project(project_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_req_project ON bidding.tb_bidding_requirement(project_id) WHERE deleted = false;
|
||||
CREATE INDEX idx_req_category ON bidding.tb_bidding_requirement(req_category) WHERE deleted = false;
|
||||
CREATE INDEX idx_req_veto ON bidding.tb_bidding_requirement(is_veto) WHERE deleted = false AND is_veto = true;
|
||||
|
||||
COMMENT ON TABLE bidding.tb_bidding_requirement IS '招标要素提取表';
|
||||
COMMENT ON COLUMN bidding.tb_bidding_requirement.req_category IS '要素类别:commercial/technical/veto/qualification/delivery/payment/scoring';
|
||||
|
||||
-- 投标文件生成表
|
||||
DROP TABLE IF EXISTS bidding.tb_bid_response CASCADE;
|
||||
CREATE TABLE bidding.tb_bid_response (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
response_id VARCHAR(50) NOT NULL, -- 响应文件ID
|
||||
project_id VARCHAR(50) NOT NULL, -- 所属项目ID
|
||||
response_type VARCHAR(50) NOT NULL, -- 响应类型:technical-技术标/commercial-商务标/comprehensive-综合标
|
||||
doc_name VARCHAR(500) NOT NULL, -- 文档名称
|
||||
outline TEXT, -- 文档大纲(JSON格式)
|
||||
content TEXT, -- 文档内容
|
||||
generation_method VARCHAR(30) DEFAULT 'ai', -- 生成方式:ai-AI生成/template-模板生成/manual-人工编写
|
||||
template_id VARCHAR(50), -- 使用的模板ID
|
||||
ai_model VARCHAR(100), -- 使用的AI模型
|
||||
generation_status VARCHAR(30) DEFAULT 'draft', -- 生成状态:draft-草稿/reviewing-审核中/approved-已批准/rejected-已拒绝/submitted-已提交
|
||||
file_id VARCHAR(50), -- 生成的文件ID
|
||||
file_path VARCHAR(500), -- 文件路径
|
||||
version VARCHAR(20) DEFAULT '1.0', -- 版本号
|
||||
parent_version_id VARCHAR(50), -- 父版本ID
|
||||
review_comments TEXT, -- 审核意见
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (response_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (project_id) REFERENCES bidding.tb_bidding_project(project_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_response_project ON bidding.tb_bid_response(project_id) WHERE deleted = false;
|
||||
CREATE INDEX idx_response_status ON bidding.tb_bid_response(generation_status) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE bidding.tb_bid_response IS '投标文件生成表';
|
||||
COMMENT ON COLUMN bidding.tb_bid_response.generation_status IS '生成状态:draft/reviewing/approved/rejected/submitted';
|
||||
|
||||
-- 评分规则表
|
||||
DROP TABLE IF EXISTS bidding.tb_bidding_scoring_rule CASCADE;
|
||||
CREATE TABLE bidding.tb_bidding_scoring_rule (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
rule_id VARCHAR(50) NOT NULL, -- 规则ID
|
||||
project_id VARCHAR(50) NOT NULL, -- 所属项目ID
|
||||
rule_category VARCHAR(50) NOT NULL, -- 规则类别:technical-技术分/commercial-商务分/price-价格分/credit-信誉分
|
||||
rule_name VARCHAR(255) NOT NULL, -- 规则名称
|
||||
rule_description TEXT, -- 规则描述
|
||||
max_score DECIMAL(10,2) NOT NULL, -- 最高分值
|
||||
weight DECIMAL(5,4), -- 权重(0-1)
|
||||
scoring_method VARCHAR(50), -- 评分方法:fixed-固定分值/range-区间评分/formula-公式计算
|
||||
calculation_formula TEXT, -- 计算公式
|
||||
evaluation_criteria TEXT, -- 评分标准
|
||||
our_score DECIMAL(10,2), -- 我方得分(预估)
|
||||
score_analysis TEXT, -- 得分分析
|
||||
optimization_advice TEXT, -- 优化建议
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (rule_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (project_id) REFERENCES bidding.tb_bidding_project(project_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_rule_project ON bidding.tb_bidding_scoring_rule(project_id) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE bidding.tb_bidding_scoring_rule IS '评分规则表';
|
||||
|
||||
-- 项目流程节点表
|
||||
DROP TABLE IF EXISTS bidding.tb_bidding_process CASCADE;
|
||||
CREATE TABLE bidding.tb_bidding_process (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
process_id VARCHAR(50) NOT NULL, -- 流程节点ID
|
||||
project_id VARCHAR(50) NOT NULL, -- 所属项目ID
|
||||
node_name VARCHAR(255) NOT NULL, -- 节点名称
|
||||
node_type VARCHAR(50) NOT NULL, -- 节点类型:collection-文件收集/analysis-需求分析/preparation-文件准备/review-内部审核/submission-投标提交/opening-开标/result-结果通知
|
||||
node_order INTEGER NOT NULL, -- 节点顺序
|
||||
node_status VARCHAR(30) DEFAULT 'pending', -- 节点状态:pending-待处理/in_progress-进行中/completed-已完成/skipped-已跳过
|
||||
planned_start_time timestamptz, -- 计划开始时间
|
||||
planned_end_time timestamptz, -- 计划结束时间
|
||||
actual_start_time timestamptz, -- 实际开始时间
|
||||
actual_end_time timestamptz, -- 实际结束时间
|
||||
responsible_user VARCHAR(50), -- 负责人
|
||||
participants VARCHAR(50)[], -- 参与人员数组
|
||||
notes TEXT, -- 节点备注
|
||||
attachments VARCHAR(50)[], -- 附件ID数组
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (process_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (project_id) REFERENCES bidding.tb_bidding_project(project_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_process_project ON bidding.tb_bidding_process(project_id, node_order) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE bidding.tb_bidding_process IS '项目流程节点表';
|
||||
COMMENT ON COLUMN bidding.tb_bidding_process.node_type IS '节点类型:collection/analysis/preparation/review/submission/opening/result';
|
||||
|
||||
-- 投标模板表
|
||||
DROP TABLE IF EXISTS bidding.tb_bid_template CASCADE;
|
||||
CREATE TABLE bidding.tb_bid_template (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
template_id VARCHAR(50) NOT NULL, -- 模板ID
|
||||
template_name VARCHAR(255) NOT NULL, -- 模板名称
|
||||
template_type VARCHAR(50) NOT NULL, -- 模板类型:technical-技术标/commercial-商务标/comprehensive-综合标
|
||||
industry VARCHAR(100), -- 适用行业
|
||||
template_content TEXT, -- 模板内容
|
||||
outline_structure JSONB, -- 大纲结构(JSON格式)
|
||||
file_id VARCHAR(50), -- 模板文件ID
|
||||
usage_count INTEGER DEFAULT 0, -- 使用次数
|
||||
is_default BOOLEAN DEFAULT false, -- 是否默认模板
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
status VARCHAR(20) DEFAULT 'active', -- 状态:active-激活/inactive-停用
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (template_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_template_type ON bidding.tb_bid_template(template_type) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE bidding.tb_bid_template IS '投标模板表';
|
||||
@@ -0,0 +1,51 @@
|
||||
CREATE SCHEMA IF NOT EXISTS config;
|
||||
DROP TABLE IF EXISTS config.tb_sys_config CASCADE;
|
||||
CREATE TABLE config.tb_sys_config (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
config_id VARCHAR(50) NOT NULL, -- 配置ID
|
||||
key VARCHAR(255) NOT NULL, -- 配置键
|
||||
name VARCHAR(255) NOT NULL, -- 配置名称
|
||||
value VARCHAR(255) NOT NULL, -- 配置值
|
||||
config_type VARCHAR(50) NOT NULL, -- 数据类型(String, Integer, Boolean, Float, Double)
|
||||
render_type VARCHAR(50) NOT NULL, -- 配置渲染类型(select, input, textarea, checkbox, radio, switch)
|
||||
description VARCHAR(255) NOT NULL, -- 配置描述
|
||||
re JSON DEFAULT NULL, -- 正则表达式校验规则
|
||||
options JSON DEFAULT NULL, -- 可选项,render_type为select、checkbox、radio时使用
|
||||
group VARCHAR(255) NOT NULL, -- 配置组
|
||||
module_id VARCHAR(255) NOT NULL, -- 模块id
|
||||
order_num INT NOT NULL, -- 配置顺序
|
||||
status INT NOT NULL DEFAULT 0, -- 配置状态 0:启用 1:禁用
|
||||
remark VARCHAR(255) NOT NULL, -- 配置备注
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径,支持like递归(如/1/2/3/)
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 配置创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 配置更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 配置删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (config_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
COMMENT ON TABLE config.tb_sys_config IS '系统配置表';
|
||||
COMMENT ON COLUMN config.tb_sys_config.optsn IS '流水号';
|
||||
COMMENT ON COLUMN config.tb_sys_config.config_id IS '配置ID';
|
||||
COMMENT ON COLUMN config.tb_sys_config.key IS '配置键';
|
||||
COMMENT ON COLUMN config.tb_sys_config.name IS '配置名称';
|
||||
COMMENT ON COLUMN config.tb_sys_config.value IS '配置值';
|
||||
COMMENT ON COLUMN config.tb_sys_config.config_type IS '数据类型';
|
||||
COMMENT ON COLUMN config.tb_sys_config.render_type IS '数据渲染类型';
|
||||
COMMENT ON COLUMN config.tb_sys_config.description IS '配置描述';
|
||||
COMMENT ON COLUMN config.tb_sys_config.re IS '正则表达式校验规则';
|
||||
COMMENT ON COLUMN config.tb_sys_config.options IS '可选项';
|
||||
COMMENT ON COLUMN config.tb_sys_config.group IS'配置组名称';
|
||||
COMMENT ON COLUMN config.tb_sys_config.module_id IS '模块id';
|
||||
COMMENT ON COLUMN config.tb_sys_config.order_num IS '配置顺序';
|
||||
COMMENT ON COLUMN config.tb_sys_config.status IS '配置状态';
|
||||
COMMENT ON COLUMN config.tb_sys_config.remark IS '配置备注';
|
||||
COMMENT ON COLUMN config.tb_sys_config.creator IS '创建者';
|
||||
COMMENT ON COLUMN config.tb_sys_config.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN config.tb_sys_config.updater IS '更新者';
|
||||
COMMENT ON COLUMN config.tb_sys_config.create_time IS '配置创建时间';
|
||||
COMMENT ON COLUMN config.tb_sys_config.update_time IS '配置更新时间';
|
||||
COMMENT ON COLUMN config.tb_sys_config.delete_time IS '配置删除时间';
|
||||
COMMENT ON COLUMN config.tb_sys_config.deleted IS '是否删除';
|
||||
@@ -0,0 +1,289 @@
|
||||
-- =============================
|
||||
-- 智能客服系统业务模块
|
||||
-- 支持:微信小程序客户咨询、智能问答、工单管理、CRM集成
|
||||
-- =============================
|
||||
CREATE SCHEMA IF NOT EXISTS customer_service;
|
||||
|
||||
-- 客户信息表
|
||||
DROP TABLE IF EXISTS customer_service.tb_customer CASCADE;
|
||||
CREATE TABLE customer_service.tb_customer (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
customer_id VARCHAR(50) NOT NULL, -- 客户ID
|
||||
customer_no VARCHAR(100), -- 客户编号
|
||||
customer_name VARCHAR(255), -- 客户姓名
|
||||
customer_type VARCHAR(30) DEFAULT 'individual', -- 客户类型:individual-个人/enterprise-企业
|
||||
company_name VARCHAR(255), -- 公司名称
|
||||
phone VARCHAR(20), -- 电话
|
||||
email VARCHAR(100), -- 邮箱
|
||||
wechat_openid VARCHAR(100), -- 微信OpenID
|
||||
wechat_unionid VARCHAR(100), -- 微信UnionID
|
||||
avatar VARCHAR(500), -- 头像URL
|
||||
gender INTEGER DEFAULT 0, -- 性别:0-未知/1-男/2-女
|
||||
address VARCHAR(500), -- 地址
|
||||
customer_level VARCHAR(20) DEFAULT 'normal', -- 客户等级:vip/important/normal/potential
|
||||
customer_source VARCHAR(50), -- 客户来源:wechat-微信/web-网站/phone-电话/referral-推荐
|
||||
tags TEXT[], -- 客户标签数组
|
||||
notes TEXT, -- 备注
|
||||
crm_customer_id VARCHAR(50), -- CRM系统客户ID(外部系统)
|
||||
last_contact_time timestamptz, -- 最后联系时间
|
||||
total_consultations INTEGER DEFAULT 0, -- 咨询总次数
|
||||
total_orders INTEGER DEFAULT 0, -- 订单总数
|
||||
total_amount DECIMAL(18,2) DEFAULT 0, -- 总消费金额
|
||||
satisfaction_score DECIMAL(3,2), -- 满意度评分(1-5)
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
status VARCHAR(20) DEFAULT 'active', -- 状态:active-活跃/inactive-非活跃/blacklist-黑名单
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (customer_id),
|
||||
UNIQUE (optsn),
|
||||
UNIQUE (wechat_openid),
|
||||
UNIQUE (phone),
|
||||
UNIQUE (email)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_customer_type ON customer_service.tb_customer(customer_type) WHERE deleted = false;
|
||||
CREATE INDEX idx_customer_level ON customer_service.tb_customer(customer_level) WHERE deleted = false;
|
||||
CREATE INDEX idx_customer_wechat ON customer_service.tb_customer(wechat_openid) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE customer_service.tb_customer IS '客户信息表';
|
||||
COMMENT ON COLUMN customer_service.tb_customer.customer_level IS '客户等级:vip/important/normal/potential';
|
||||
|
||||
-- 会话表
|
||||
DROP TABLE IF EXISTS customer_service.tb_conversation CASCADE;
|
||||
CREATE TABLE customer_service.tb_conversation (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
conversation_id VARCHAR(50) NOT NULL, -- 会话ID
|
||||
customer_id VARCHAR(50) NOT NULL, -- 客户ID
|
||||
conversation_type VARCHAR(30) DEFAULT 'ai', -- 会话类型:ai-AI客服/human-人工客服/transfer-转接
|
||||
channel VARCHAR(20) DEFAULT 'wechat', -- 渠道:wechat-微信/web-网页/app-应用/phone-电话
|
||||
agent_id VARCHAR(50), -- 智能体ID或客服人员ID
|
||||
agent_type VARCHAR(20) DEFAULT 'ai', -- 座席类型:ai-AI/human-人工
|
||||
session_start_time timestamptz DEFAULT now(), -- 会话开始时间
|
||||
session_end_time timestamptz, -- 会话结束时间
|
||||
duration_seconds INTEGER, -- 会话时长(秒)
|
||||
message_count INTEGER DEFAULT 0, -- 消息数量
|
||||
conversation_status VARCHAR(20) DEFAULT 'active', -- 会话状态:active-进行中/closed-已结束/transferred-已转接/timeout-超时
|
||||
satisfaction_rating INTEGER, -- 满意度评分(1-5星)
|
||||
satisfaction_feedback TEXT, -- 满意度反馈
|
||||
summary TEXT, -- 会话摘要(AI生成)
|
||||
tags TEXT[], -- 会话标签
|
||||
metadata JSONB, -- 会话元数据
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (conversation_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (customer_id) REFERENCES customer_service.tb_customer(customer_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_conv_customer ON customer_service.tb_conversation(customer_id, session_start_time DESC) WHERE deleted = false;
|
||||
CREATE INDEX idx_conv_status ON customer_service.tb_conversation(conversation_status) WHERE deleted = false;
|
||||
CREATE INDEX idx_conv_agent ON customer_service.tb_conversation(agent_id) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE customer_service.tb_conversation IS '会话表';
|
||||
COMMENT ON COLUMN customer_service.tb_conversation.conversation_type IS '会话类型:ai/human/transfer';
|
||||
|
||||
-- 会话消息表
|
||||
DROP TABLE IF EXISTS customer_service.tb_conversation_message CASCADE;
|
||||
CREATE TABLE customer_service.tb_conversation_message (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
message_id VARCHAR(50) NOT NULL, -- 消息ID
|
||||
conversation_id VARCHAR(50) NOT NULL, -- 所属会话ID
|
||||
sender_type VARCHAR(20) NOT NULL, -- 发送者类型:customer-客户/agent-座席/system-系统
|
||||
sender_id VARCHAR(50), -- 发送者ID
|
||||
message_type VARCHAR(30) NOT NULL DEFAULT 'text',-- 消息类型:text-文本/image-图片/voice-语音/video-视频/file-文件/card-卡片
|
||||
content TEXT, -- 消息内容
|
||||
content_url VARCHAR(500), -- 内容URL(图片、文件等)
|
||||
is_ai_generated BOOLEAN DEFAULT false, -- 是否AI生成
|
||||
ai_model VARCHAR(100), -- 使用的AI模型
|
||||
kb_references VARCHAR(50)[], -- 引用的知识库文档ID数组
|
||||
confidence_score DECIMAL(5,4), -- AI回答置信度
|
||||
sentiment VARCHAR(20), -- 情感分析:positive-正面/neutral-中性/negative-负面
|
||||
intent VARCHAR(100), -- 意图识别结果
|
||||
is_sensitive BOOLEAN DEFAULT false, -- 是否敏感信息
|
||||
read_status BOOLEAN DEFAULT false, -- 已读状态
|
||||
read_time timestamptz, -- 阅读时间
|
||||
metadata JSONB, -- 消息元数据
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间(发送时间)
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (message_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (conversation_id) REFERENCES customer_service.tb_conversation(conversation_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_msg_conversation ON customer_service.tb_conversation_message(conversation_id, create_time) WHERE deleted = false;
|
||||
CREATE INDEX idx_msg_sender ON customer_service.tb_conversation_message(sender_id) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE customer_service.tb_conversation_message IS '会话消息表';
|
||||
COMMENT ON COLUMN customer_service.tb_conversation_message.sentiment IS '情感分析:positive/neutral/negative';
|
||||
|
||||
-- 工单表
|
||||
DROP TABLE IF EXISTS customer_service.tb_ticket CASCADE;
|
||||
CREATE TABLE customer_service.tb_ticket (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
ticket_id VARCHAR(50) NOT NULL, -- 工单ID
|
||||
ticket_no VARCHAR(100) NOT NULL, -- 工单编号
|
||||
customer_id VARCHAR(50) NOT NULL, -- 客户ID
|
||||
conversation_id VARCHAR(50), -- 关联会话ID
|
||||
ticket_type VARCHAR(50) NOT NULL, -- 工单类型:consultation-咨询/complaint-投诉/suggestion-建议/repair-维修/installation-安装/other-其他
|
||||
ticket_category VARCHAR(100), -- 工单分类(具体业务分类)
|
||||
priority VARCHAR(20) DEFAULT 'normal', -- 优先级:urgent-紧急/high-高/normal-普通/low-低
|
||||
title VARCHAR(500) NOT NULL, -- 工单标题
|
||||
description TEXT NOT NULL, -- 问题描述
|
||||
attachments VARCHAR(50)[], -- 附件ID数组
|
||||
ticket_source VARCHAR(30) DEFAULT 'ai', -- 工单来源:ai-AI生成/manual-人工创建/system-系统自动
|
||||
assigned_to VARCHAR(50), -- 分配给(处理人)
|
||||
assigned_dept VARCHAR(50), -- 分配部门
|
||||
ticket_status VARCHAR(30) DEFAULT 'pending', -- 工单状态:pending-待处理/processing-处理中/resolved-已解决/closed-已关闭/cancelled-已取消
|
||||
resolution TEXT, -- 解决方案
|
||||
resolution_time timestamptz, -- 解决时间
|
||||
close_time timestamptz, -- 关闭时间
|
||||
response_time timestamptz, -- 首次响应时间
|
||||
sla_deadline timestamptz, -- SLA截止时间
|
||||
is_overdue BOOLEAN DEFAULT false, -- 是否逾期
|
||||
customer_rating INTEGER, -- 客户评分(1-5星)
|
||||
customer_feedback TEXT, -- 客户反馈
|
||||
crm_ticket_id VARCHAR(50), -- CRM系统工单ID(外部系统)
|
||||
sync_status VARCHAR(20) DEFAULT 'pending', -- 同步状态:pending-待同步/synced-已同步/failed-失败
|
||||
tags TEXT[], -- 工单标签
|
||||
metadata JSONB, -- 工单元数据
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (ticket_id),
|
||||
UNIQUE (optsn),
|
||||
UNIQUE (ticket_no),
|
||||
FOREIGN KEY (customer_id) REFERENCES customer_service.tb_customer(customer_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_ticket_customer ON customer_service.tb_ticket(customer_id) WHERE deleted = false;
|
||||
CREATE INDEX idx_ticket_status ON customer_service.tb_ticket(ticket_status) WHERE deleted = false;
|
||||
CREATE INDEX idx_ticket_assigned ON customer_service.tb_ticket(assigned_to) WHERE deleted = false;
|
||||
CREATE INDEX idx_ticket_priority ON customer_service.tb_ticket(priority) WHERE deleted = false;
|
||||
CREATE INDEX idx_ticket_sla ON customer_service.tb_ticket(sla_deadline) WHERE deleted = false AND is_overdue = false;
|
||||
|
||||
COMMENT ON TABLE customer_service.tb_ticket IS '工单表';
|
||||
COMMENT ON COLUMN customer_service.tb_ticket.ticket_type IS '工单类型:consultation/complaint/suggestion/repair/installation/other';
|
||||
|
||||
-- 工单处理记录表
|
||||
DROP TABLE IF EXISTS customer_service.tb_ticket_log CASCADE;
|
||||
CREATE TABLE customer_service.tb_ticket_log (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
log_id VARCHAR(50) NOT NULL, -- 日志ID
|
||||
ticket_id VARCHAR(50) NOT NULL, -- 工单ID
|
||||
action_type VARCHAR(50) NOT NULL, -- 操作类型:create-创建/assign-分配/update-更新/comment-评论/resolve-解决/close-关闭/reopen-重开
|
||||
action_content TEXT, -- 操作内容
|
||||
old_value TEXT, -- 旧值
|
||||
new_value TEXT, -- 新值
|
||||
operator_id VARCHAR(50), -- 操作人ID
|
||||
operator_name VARCHAR(100), -- 操作人姓名
|
||||
attachments VARCHAR(50)[], -- 附件ID数组
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
PRIMARY KEY (log_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (ticket_id) REFERENCES customer_service.tb_ticket(ticket_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_ticket_log_ticket ON customer_service.tb_ticket_log(ticket_id, create_time DESC);
|
||||
|
||||
COMMENT ON TABLE customer_service.tb_ticket_log IS '工单处理记录表';
|
||||
|
||||
-- FAQ表(常见问题)
|
||||
DROP TABLE IF EXISTS customer_service.tb_faq CASCADE;
|
||||
CREATE TABLE customer_service.tb_faq (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
faq_id VARCHAR(50) NOT NULL, -- FAQ ID
|
||||
kb_id VARCHAR(50), -- 关联知识库ID
|
||||
category VARCHAR(100) NOT NULL, -- 分类
|
||||
question TEXT NOT NULL, -- 问题
|
||||
answer TEXT NOT NULL, -- 答案
|
||||
similar_questions TEXT[], -- 相似问题数组
|
||||
keywords TEXT[], -- 关键词数组
|
||||
hit_count INTEGER DEFAULT 0, -- 命中次数
|
||||
helpful_count INTEGER DEFAULT 0, -- 有帮助次数
|
||||
unhelpful_count INTEGER DEFAULT 0, -- 无帮助次数
|
||||
is_published BOOLEAN DEFAULT false, -- 是否发布
|
||||
priority INTEGER DEFAULT 0, -- 优先级
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (faq_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_faq_category ON customer_service.tb_faq(category) WHERE deleted = false;
|
||||
CREATE INDEX idx_faq_published ON customer_service.tb_faq(is_published) WHERE deleted = false AND is_published = true;
|
||||
|
||||
COMMENT ON TABLE customer_service.tb_faq IS 'FAQ常见问题表';
|
||||
|
||||
-- 客服评价表
|
||||
DROP TABLE IF EXISTS customer_service.tb_service_evaluation CASCADE;
|
||||
CREATE TABLE customer_service.tb_service_evaluation (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
evaluation_id VARCHAR(50) NOT NULL, -- 评价ID
|
||||
customer_id VARCHAR(50) NOT NULL, -- 客户ID
|
||||
conversation_id VARCHAR(50), -- 会话ID
|
||||
ticket_id VARCHAR(50), -- 工单ID
|
||||
evaluation_type VARCHAR(30) NOT NULL, -- 评价类型:conversation-会话/ticket-工单/overall-整体服务
|
||||
rating INTEGER NOT NULL, -- 评分(1-5星)
|
||||
dimensions JSONB, -- 分维度评分(JSON格式:响应速度、专业性、态度等)
|
||||
feedback TEXT, -- 评价反馈
|
||||
tags TEXT[], -- 评价标签
|
||||
is_anonymous BOOLEAN DEFAULT false, -- 是否匿名
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (evaluation_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (customer_id) REFERENCES customer_service.tb_customer(customer_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_eval_customer ON customer_service.tb_service_evaluation(customer_id) WHERE deleted = false;
|
||||
CREATE INDEX idx_eval_rating ON customer_service.tb_service_evaluation(rating) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE customer_service.tb_service_evaluation IS '客服评价表';
|
||||
|
||||
-- CRM集成配置表
|
||||
DROP TABLE IF EXISTS customer_service.tb_crm_config CASCADE;
|
||||
CREATE TABLE customer_service.tb_crm_config (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
config_id VARCHAR(50) NOT NULL, -- 配置ID
|
||||
crm_system VARCHAR(50) NOT NULL, -- CRM系统名称
|
||||
api_endpoint VARCHAR(500) NOT NULL, -- API端点
|
||||
api_key VARCHAR(500), -- API密钥(加密存储)
|
||||
auth_type VARCHAR(30) DEFAULT 'api_key', -- 认证类型:api_key/oauth2/basic_auth
|
||||
sync_interval INTEGER DEFAULT 3600, -- 同步间隔(秒)
|
||||
sync_direction VARCHAR(30) DEFAULT 'bidirectional',-- 同步方向:to_crm-单向到CRM/from_crm-单向从CRM/bidirectional-双向
|
||||
field_mapping JSONB, -- 字段映射配置
|
||||
sync_enabled BOOLEAN DEFAULT false, -- 是否启用同步
|
||||
last_sync_time timestamptz, -- 最后同步时间
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (config_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE customer_service.tb_crm_config IS 'CRM集成配置表';
|
||||
@@ -0,0 +1,42 @@
|
||||
CREATE SCHEMA IF NOT EXISTS file;
|
||||
|
||||
DROP TABLE IF EXISTS file.tb_sys_file CASCADE;
|
||||
CREATE TABLE file.tb_sys_file (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
file_id VARCHAR(50) NOT NULL, -- 文件ID
|
||||
name VARCHAR(255) NOT NULL, -- 文件名
|
||||
path VARCHAR(255) NOT NULL, -- 文件路径
|
||||
size BIGINT NOT NULL, -- 文件大小
|
||||
type VARCHAR(50) NOT NULL, -- 文件类型
|
||||
storage_type VARCHAR(50) NOT NULL, -- 存储类型
|
||||
mime_type VARCHAR(255) NOT NULL, -- 文件MIME类型
|
||||
url VARCHAR(255) NOT NULL, -- 文件URL
|
||||
status VARCHAR(50) NOT NULL, -- 文件状态
|
||||
dept_path VARCHAR(255) NOT NULL, -- 当前部门路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间(由触发器维护)
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted boolean NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (file_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
COMMENT ON TABLE file.tb_sys_file IS '文件表';
|
||||
COMMENT ON COLUMN file.tb_sys_file.optsn IS '流水号';
|
||||
COMMENT ON COLUMN file.tb_sys_file.file_id IS '文件ID';
|
||||
COMMENT ON COLUMN file.tb_sys_file.name IS '文件名';
|
||||
COMMENT ON COLUMN file.tb_sys_file.path IS '文件路径';
|
||||
COMMENT ON COLUMN file.tb_sys_file.size IS '文件大小';
|
||||
COMMENT ON COLUMN file.tb_sys_file.type IS '文件类型';
|
||||
COMMENT ON COLUMN file.tb_sys_file.storage_type IS '存储类型';
|
||||
COMMENT ON COLUMN file.tb_sys_file.mime_type IS '文件MIME类型';
|
||||
COMMENT ON COLUMN file.tb_sys_file.url IS '文件URL';
|
||||
COMMENT ON COLUMN file.tb_sys_file.status IS '文件状态';
|
||||
COMMENT ON COLUMN file.tb_sys_file.dept_path IS '当前部门路径';
|
||||
COMMENT ON COLUMN file.tb_sys_file.creator IS '创建者';
|
||||
COMMENT ON COLUMN file.tb_sys_file.updater IS '更新者';
|
||||
COMMENT ON COLUMN file.tb_sys_file.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN file.tb_sys_file.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN file.tb_sys_file.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN file.tb_sys_file.deleted IS '是否删除';
|
||||
@@ -0,0 +1,138 @@
|
||||
-- =============================
|
||||
-- 知识库管理模块
|
||||
-- 支持:招投标知识库、客服知识库、企业内部知识库
|
||||
-- =============================
|
||||
CREATE SCHEMA IF NOT EXISTS knowledge;
|
||||
|
||||
-- 知识库表(多租户知识库定义)
|
||||
DROP TABLE IF EXISTS knowledge.tb_knowledge_base CASCADE;
|
||||
CREATE TABLE knowledge.tb_knowledge_base (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
kb_id VARCHAR(50) NOT NULL, -- 知识库ID
|
||||
name VARCHAR(255) NOT NULL, -- 知识库名称
|
||||
kb_type VARCHAR(50) NOT NULL, -- 知识库类型:bidding-招投标/customer_service-客服/internal-内部协同
|
||||
access_level VARCHAR(20) NOT NULL DEFAULT 'private', -- 访问级别:public-公开/private-私有/internal-内部
|
||||
description TEXT, -- 知识库描述
|
||||
storage_path VARCHAR(500), -- 存储路径
|
||||
version VARCHAR(20) DEFAULT '1.0', -- 当前版本号
|
||||
config JSONB DEFAULT NULL, -- 知识库配置(JSON格式:索引配置、检索参数等)
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active', -- 状态:active-激活/inactive-停用/archived-归档
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (kb_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_kb_type ON knowledge.tb_knowledge_base(kb_type) WHERE deleted = false;
|
||||
CREATE INDEX idx_kb_dept_path ON knowledge.tb_knowledge_base(dept_path) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE knowledge.tb_knowledge_base IS '知识库表';
|
||||
COMMENT ON COLUMN knowledge.tb_knowledge_base.kb_type IS '知识库类型:bidding-招投标/customer_service-客服/internal-内部协同';
|
||||
COMMENT ON COLUMN knowledge.tb_knowledge_base.access_level IS '访问级别:public-公开/private-私有/internal-内部';
|
||||
|
||||
-- 知识文档表
|
||||
DROP TABLE IF EXISTS knowledge.tb_knowledge_document CASCADE;
|
||||
CREATE TABLE knowledge.tb_knowledge_document (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
doc_id VARCHAR(50) NOT NULL, -- 文档ID
|
||||
kb_id VARCHAR(50) NOT NULL, -- 所属知识库ID
|
||||
title VARCHAR(500) NOT NULL, -- 文档标题
|
||||
doc_type VARCHAR(50) NOT NULL, -- 文档类型:text-文本/pdf/word/excel/image/video
|
||||
category VARCHAR(100), -- 文档分类(自动或手动分类)
|
||||
content TEXT, -- 文档内容(文本类型)
|
||||
content_summary TEXT, -- 内容摘要(AI生成)
|
||||
file_id VARCHAR(50), -- 关联文件表ID
|
||||
file_path VARCHAR(500), -- 文件路径
|
||||
file_size BIGINT, -- 文件大小(字节)
|
||||
mime_type VARCHAR(100), -- MIME类型
|
||||
version VARCHAR(20) DEFAULT '1.0', -- 文档版本号
|
||||
parent_doc_id VARCHAR(50), -- 父文档ID(用于版本管理)
|
||||
tags TEXT[], -- 文档标签数组
|
||||
keywords TEXT[], -- 关键词数组(AI提取)
|
||||
embedding_status VARCHAR(20) DEFAULT 'pending', -- 向量化状态:pending-待处理/processing-处理中/completed-完成/failed-失败
|
||||
embedding_model VARCHAR(100), -- 使用的向量化模型
|
||||
chunk_count INTEGER DEFAULT 0, -- 切片数量
|
||||
metadata JSONB DEFAULT NULL, -- 文档元数据(JSON格式)
|
||||
source_url VARCHAR(500), -- 来源URL
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active', -- 状态:active-激活/inactive-停用/archived-归档
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (doc_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (kb_id) REFERENCES knowledge.tb_knowledge_base(kb_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_doc_kb ON knowledge.tb_knowledge_document(kb_id) WHERE deleted = false;
|
||||
CREATE INDEX idx_doc_category ON knowledge.tb_knowledge_document(category) WHERE deleted = false;
|
||||
CREATE INDEX idx_doc_embedding_status ON knowledge.tb_knowledge_document(embedding_status) WHERE deleted = false;
|
||||
CREATE INDEX idx_doc_tags ON knowledge.tb_knowledge_document USING GIN(tags) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE knowledge.tb_knowledge_document IS '知识文档表';
|
||||
COMMENT ON COLUMN knowledge.tb_knowledge_document.embedding_status IS '向量化状态:pending/processing/completed/failed';
|
||||
|
||||
-- 知识文档片段表(用于RAG检索)
|
||||
DROP TABLE IF EXISTS knowledge.tb_knowledge_chunk CASCADE;
|
||||
CREATE TABLE knowledge.tb_knowledge_chunk (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
chunk_id VARCHAR(50) NOT NULL, -- 片段ID
|
||||
doc_id VARCHAR(50) NOT NULL, -- 所属文档ID
|
||||
kb_id VARCHAR(50) NOT NULL, -- 所属知识库ID
|
||||
chunk_index INTEGER NOT NULL, -- 片段索引(在文档中的顺序)
|
||||
content TEXT NOT NULL, -- 片段内容
|
||||
content_length INTEGER, -- 内容长度
|
||||
embedding vector(1536), -- 向量嵌入(假设使用OpenAI 1536维)
|
||||
chunk_type VARCHAR(20) DEFAULT 'text', -- 片段类型:text-文本/table-表格/image-图片
|
||||
position_info JSONB, -- 位置信息(页码、坐标等)
|
||||
metadata JSONB, -- 片段元数据
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (chunk_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (doc_id) REFERENCES knowledge.tb_knowledge_document(doc_id),
|
||||
FOREIGN KEY (kb_id) REFERENCES knowledge.tb_knowledge_base(kb_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_chunk_doc ON knowledge.tb_knowledge_chunk(doc_id) WHERE deleted = false;
|
||||
CREATE INDEX idx_chunk_kb ON knowledge.tb_knowledge_chunk(kb_id) WHERE deleted = false;
|
||||
-- 向量检索索引(需要安装pgvector扩展)
|
||||
-- CREATE INDEX idx_chunk_embedding ON knowledge.tb_knowledge_chunk USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
|
||||
|
||||
COMMENT ON TABLE knowledge.tb_knowledge_chunk IS '知识文档片段表(RAG检索)';
|
||||
COMMENT ON COLUMN knowledge.tb_knowledge_chunk.embedding IS '向量嵌入(需要pgvector扩展)';
|
||||
|
||||
-- 知识访问日志表
|
||||
DROP TABLE IF EXISTS knowledge.tb_knowledge_access_log CASCADE;
|
||||
CREATE TABLE knowledge.tb_knowledge_access_log (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
log_id VARCHAR(50) NOT NULL, -- 日志ID
|
||||
kb_id VARCHAR(50), -- 知识库ID
|
||||
doc_id VARCHAR(50), -- 文档ID
|
||||
user_id VARCHAR(50) NOT NULL, -- 用户ID
|
||||
access_type VARCHAR(20) NOT NULL, -- 访问类型:view-查看/download-下载/search-搜索/edit-编辑
|
||||
query_text TEXT, -- 搜索查询文本
|
||||
result_count INTEGER, -- 搜索结果数量
|
||||
ip_address VARCHAR(45), -- IP地址
|
||||
user_agent TEXT, -- 用户代理
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
PRIMARY KEY (log_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_access_log_user ON knowledge.tb_knowledge_access_log(user_id, create_time DESC);
|
||||
CREATE INDEX idx_access_log_kb ON knowledge.tb_knowledge_access_log(kb_id, create_time DESC);
|
||||
|
||||
COMMENT ON TABLE knowledge.tb_knowledge_access_log IS '知识访问日志表';
|
||||
@@ -0,0 +1,39 @@
|
||||
CREATE SCHEMA IF NOT EXISTS log;
|
||||
DROP TABLE IF EXISTS log.tb_sys_log CASCADE;
|
||||
CREATE TABLE log.tb_sys_log (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
log_id VARCHAR(50) NOT NULL, -- 日志ID
|
||||
type VARCHAR(50) NOT NULL, -- 日志类型
|
||||
level VARCHAR(50) NOT NULL, -- 日志级别
|
||||
module VARCHAR(50) NOT NULL, -- 日志模块
|
||||
ip_address varchar(45), -- IP地址
|
||||
ip_source varchar(100), -- IP来源
|
||||
browser varchar(100), -- 浏览器
|
||||
os varchar(100), -- 操作系统
|
||||
message VARCHAR(255) NOT NULL, -- 日志消息
|
||||
data JSONB DEFAULT NULL, -- 日志数据
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 日志创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 日志更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 日志删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (log_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
COMMENT ON TABLE log.tb_sys_log IS '系统日志表';
|
||||
COMMENT ON COLUMN log.tb_sys_log.optsn IS '流水号';
|
||||
COMMENT ON COLUMN log.tb_sys_log.log_id IS '日志ID';
|
||||
COMMENT ON COLUMN log.tb_sys_log.type IS '日志类型';
|
||||
COMMENT ON COLUMN log.tb_sys_log.level IS '日志级别';
|
||||
COMMENT ON COLUMN log.tb_sys_log.module IS '日志模块';
|
||||
COMMENT ON COLUMN log.tb_sys_log.message IS '日志消息';
|
||||
COMMENT ON COLUMN log.tb_sys_log.data IS '日志数据';
|
||||
COMMENT ON COLUMN log.tb_sys_log.creator IS '创建者';
|
||||
COMMENT ON COLUMN log.tb_sys_log.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN log.tb_sys_log.updater IS '更新者';
|
||||
COMMENT ON COLUMN log.tb_sys_log.create_time IS '日志创建时间';
|
||||
COMMENT ON COLUMN log.tb_sys_log.update_time IS '日志更新时间';
|
||||
COMMENT ON COLUMN log.tb_sys_log.delete_time IS '日志删除时间';
|
||||
COMMENT ON COLUMN log.tb_sys_log.deleted IS '是否删除';
|
||||
@@ -0,0 +1,161 @@
|
||||
CREATE SCHEMA IF NOT EXISTS message;
|
||||
|
||||
DROP TABLE IF EXISTS message.tb_message CASCADE;
|
||||
CREATE TABLE message.tb_message (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
message_id VARCHAR(50) NOT NULL, -- 消息ID
|
||||
title VARCHAR(255) NOT NULL, -- 消息标题
|
||||
content VARCHAR(255) NOT NULL, -- 消息内容
|
||||
type VARCHAR(50) NOT NULL, -- 消息类型
|
||||
status VARCHAR(50) NOT NULL, -- 消息状态
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径(隔离)
|
||||
creator VARCHAR(50) NOT NULL DEFAULT 'system',-- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL,
|
||||
delete_time timestamptz DEFAULT NULL,
|
||||
deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
PRIMARY KEY (message_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE message.tb_message IS '消息表';
|
||||
COMMENT ON COLUMN message.tb_message.optsn IS '流水号';
|
||||
COMMENT ON COLUMN message.tb_message.message_id IS '消息ID';
|
||||
COMMENT ON COLUMN message.tb_message.title IS '消息标题';
|
||||
COMMENT ON COLUMN message.tb_message.content IS '消息内容';
|
||||
COMMENT ON COLUMN message.tb_message.type IS '消息类型';
|
||||
COMMENT ON COLUMN message.tb_message.status IS '消息状态';
|
||||
COMMENT ON COLUMN message.tb_message.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN message.tb_message.creator IS '创建者';
|
||||
COMMENT ON COLUMN message.tb_message.updater IS '更新者';
|
||||
COMMENT ON COLUMN message.tb_message.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN message.tb_message.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN message.tb_message.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN message.tb_message.deleted IS '是否删除';
|
||||
|
||||
|
||||
-- 消息发送范围定义表(定义消息要发送给哪些对象,通过什么渠道)
|
||||
DROP TABLE IF EXISTS message.tb_message_range CASCADE;
|
||||
CREATE TABLE message.tb_message_range (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
message_id VARCHAR(50) NOT NULL, -- 消息ID
|
||||
target_type VARCHAR(20) NOT NULL, -- 目标类型:user/dept/role/all
|
||||
target_id VARCHAR(50) DEFAULT NULL, -- 目标ID(用户、部门、角色ID等,all类型时为空)
|
||||
channel VARCHAR(20) NOT NULL DEFAULT 'app', -- 发送渠道:app/sms/email/wechat等
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径,支持like递归(如/1/2/3/)
|
||||
creator VARCHAR(50) NOT NULL DEFAULT 'system',-- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (optsn),
|
||||
UNIQUE (message_id, target_type, target_id, channel)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE message.tb_message_range IS '消息发送范围定义表';
|
||||
COMMENT ON COLUMN message.tb_message_range.optsn IS '流水号';
|
||||
COMMENT ON COLUMN message.tb_message_range.message_id IS '消息ID';
|
||||
COMMENT ON COLUMN message.tb_message_range.target_type IS '目标类型:user-指定用户/dept-部门/role-角色/all-全员';
|
||||
COMMENT ON COLUMN message.tb_message_range.target_id IS '目标ID(用户、部门、角色ID等,all类型时为空)';
|
||||
COMMENT ON COLUMN message.tb_message_range.channel IS '发送渠道:app/sms/email/wechat等';
|
||||
COMMENT ON COLUMN message.tb_message_range.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN message.tb_message_range.creator IS '创建者';
|
||||
COMMENT ON COLUMN message.tb_message_range.updater IS '更新者';
|
||||
COMMENT ON COLUMN message.tb_message_range.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN message.tb_message_range.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN message.tb_message_range.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN message.tb_message_range.deleted IS '是否删除';
|
||||
|
||||
|
||||
-- 用户消息接收记录表(记录每个用户实际收到的消息及处理状态)
|
||||
DROP TABLE IF EXISTS message.tb_message_receiver CASCADE;
|
||||
CREATE TABLE message.tb_message_receiver (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
message_id VARCHAR(50) NOT NULL, -- 消息ID
|
||||
user_id VARCHAR(50) NOT NULL, -- 用户ID
|
||||
channel VARCHAR(20) DEFAULT 'app', -- 接收渠道:app/sms/email/wechat等
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'unread', -- 消息状态:unread-未读/read-已读/handled-已处理/deleted-已删除
|
||||
read_time timestamptz DEFAULT NULL, -- 阅读时间
|
||||
handle_time timestamptz DEFAULT NULL, -- 处理时间
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径(数据隔离)
|
||||
creator VARCHAR(50) NOT NULL DEFAULT 'system',-- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间(接收时间)
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (optsn),
|
||||
UNIQUE (message_id, user_id, channel)
|
||||
);
|
||||
|
||||
-- 创建索引以提高查询效率
|
||||
CREATE INDEX idx_message_user_user_status ON message.tb_message_receiver(user_id, status, create_time DESC) WHERE deleted = false;
|
||||
CREATE INDEX idx_message_user_message ON message.tb_message_receiver(message_id) WHERE deleted = false;
|
||||
|
||||
COMMENT ON TABLE message.tb_message_receiver IS '用户消息接收记录表';
|
||||
COMMENT ON COLUMN message.tb_message_receiver.optsn IS '流水号';
|
||||
COMMENT ON COLUMN message.tb_message_receiver.message_id IS '消息ID';
|
||||
COMMENT ON COLUMN message.tb_message_receiver.user_id IS '用户ID';
|
||||
COMMENT ON COLUMN message.tb_message_receiver.channel IS '接收渠道:app/sms/email/wechat等';
|
||||
COMMENT ON COLUMN message.tb_message_receiver.status IS '消息状态:unread-未读/read-已读/handled-已处理/deleted-已删除';
|
||||
COMMENT ON COLUMN message.tb_message_receiver.read_time IS '阅读时间';
|
||||
COMMENT ON COLUMN message.tb_message_receiver.handle_time IS '处理时间';
|
||||
COMMENT ON COLUMN message.tb_message_receiver.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN message.tb_message_receiver.creator IS '创建者';
|
||||
COMMENT ON COLUMN message.tb_message_receiver.updater IS '更新者';
|
||||
COMMENT ON COLUMN message.tb_message_receiver.create_time IS '创建时间(接收时间)';
|
||||
COMMENT ON COLUMN message.tb_message_receiver.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN message.tb_message_receiver.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN message.tb_message_receiver.deleted IS '是否删除';
|
||||
|
||||
|
||||
-- 消息渠道配置表(管理各种消息发送渠道的配置)
|
||||
DROP TABLE IF EXISTS message.tb_message_channel CASCADE;
|
||||
CREATE TABLE message.tb_message_channel (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
channel_id VARCHAR(50) NOT NULL, -- 渠道ID
|
||||
channel_code VARCHAR(20) NOT NULL, -- 渠道编码:app/sms/email/wechat/dingtalk等
|
||||
channel_name VARCHAR(100) NOT NULL, -- 渠道名称
|
||||
channel_desc VARCHAR(255) DEFAULT NULL, -- 渠道描述
|
||||
config TEXT DEFAULT NULL, -- 渠道配置(JSON格式,如API密钥、服务器地址等)
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'enabled', -- 渠道状态:enabled-启用/disabled-禁用/maintenance-维护中
|
||||
priority INTEGER DEFAULT 0, -- 优先级(数字越大优先级越高)
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径(数据隔离)
|
||||
creator VARCHAR(50) NOT NULL DEFAULT 'system',-- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (channel_id),
|
||||
UNIQUE (optsn),
|
||||
UNIQUE (channel_code)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE message.tb_message_channel IS '消息渠道配置表';
|
||||
COMMENT ON COLUMN message.tb_message_channel.optsn IS '流水号';
|
||||
COMMENT ON COLUMN message.tb_message_channel.channel_id IS '渠道ID';
|
||||
COMMENT ON COLUMN message.tb_message_channel.channel_code IS '渠道编码:app/sms/email/wechat/dingtalk等';
|
||||
COMMENT ON COLUMN message.tb_message_channel.channel_name IS '渠道名称';
|
||||
COMMENT ON COLUMN message.tb_message_channel.channel_desc IS '渠道描述';
|
||||
COMMENT ON COLUMN message.tb_message_channel.config IS '渠道配置(JSON格式)';
|
||||
COMMENT ON COLUMN message.tb_message_channel.status IS '渠道状态:enabled-启用/disabled-禁用/maintenance-维护中';
|
||||
COMMENT ON COLUMN message.tb_message_channel.priority IS '优先级(数字越大优先级越高)';
|
||||
COMMENT ON COLUMN message.tb_message_channel.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN message.tb_message_channel.creator IS '创建者';
|
||||
COMMENT ON COLUMN message.tb_message_channel.updater IS '更新者';
|
||||
COMMENT ON COLUMN message.tb_message_channel.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN message.tb_message_channel.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN message.tb_message_channel.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN message.tb_message_channel.deleted IS '是否删除';
|
||||
|
||||
-- 插入默认渠道配置
|
||||
INSERT INTO message.tb_message_channel (optsn, channel_id, channel_code, channel_name, channel_desc, status, priority)
|
||||
VALUES
|
||||
('CHANNEL_APP_001', 'CH_APP', 'app', '应用内消息', '系统内部消息推送', 'enabled', 100),
|
||||
('CHANNEL_SMS_001', 'CH_SMS', 'sms', '短信通知', '手机短信推送', 'disabled', 80),
|
||||
('CHANNEL_EMAIL_001', 'CH_EMAIL', 'email', '邮件通知', '电子邮件推送', 'disabled', 60),
|
||||
('CHANNEL_WECHAT_001', 'CH_WECHAT', 'wechat', '微信通知', '微信公众号/企业微信推送', 'disabled', 70),
|
||||
('CHANNEL_DINGTALK_001', 'CH_DINGTALK', 'dingtalk', '钉钉通知', '钉钉工作通知推送', 'disabled', 70);
|
||||
@@ -0,0 +1,461 @@
|
||||
CREATE SCHEMA IF NOT EXISTS sys;
|
||||
|
||||
-- 通用更新时间触发函数(用于模拟 MySQL 的 ON UPDATE CURRENT_TIMESTAMP)
|
||||
-- CREATE OR REPLACE FUNCTION sys.set_update_time()
|
||||
-- RETURNS trigger AS $$
|
||||
-- BEGIN
|
||||
-- NEW.update_time := CURRENT_TIMESTAMP;
|
||||
-- RETURN NEW;
|
||||
-- END;
|
||||
-- $$ LANGUAGE plpgsql;
|
||||
|
||||
-- 部门表
|
||||
DROP TABLE IF EXISTS sys.tb_sys_dept CASCADE;
|
||||
CREATE TABLE sys.tb_sys_dept (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
dept_id VARCHAR(50) NOT NULL, -- 部门ID
|
||||
name VARCHAR(100) NOT NULL, -- 部门名称
|
||||
parent_id VARCHAR(50) DEFAULT NULL, -- 父部门ID
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
description VARCHAR(255) DEFAULT NULL, -- 部门描述
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间(由触发器维护)
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted boolean NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (dept_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
-- 创建索引
|
||||
CREATE INDEX idx_sys_dept_parent ON sys.tb_sys_dept USING btree (parent_id);
|
||||
COMMENT ON TABLE sys.tb_sys_dept IS '部门表';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept.optsn IS '流水号';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept.dept_id IS '部门ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept.name IS '部门名称';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept.parent_id IS '父部门ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept.description IS '部门描述';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept.creator IS '创建者';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept.updater IS '更新者';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept.deleted IS '是否删除';
|
||||
|
||||
-- 角色表
|
||||
DROP TABLE IF EXISTS sys.tb_sys_role CASCADE;
|
||||
CREATE TABLE sys.tb_sys_role (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
role_id VARCHAR(50) NOT NULL, -- 角色ID
|
||||
name VARCHAR(100) NOT NULL,
|
||||
description VARCHAR(200) DEFAULT NULL, -- 角色名称
|
||||
scope VARCHAR(20) NOT NULL DEFAULT 'dept', -- 角色作用域:global/dept
|
||||
owner_dept_id VARCHAR(50) DEFAULT NULL, -- 当scope=dept时,所属部门ID
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
dept_path VARCHAR(255) DEFAULT NULL,
|
||||
status boolean NOT NULL DEFAULT false, -- 部门全路径
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间(由触发器维护)
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted boolean NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (role_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
COMMENT ON TABLE sys.tb_sys_role IS '角色表';
|
||||
COMMENT ON COLUMN sys.tb_sys_role.optsn IS '流水号';
|
||||
COMMENT ON COLUMN sys.tb_sys_role.role_id IS '角色ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_role.name IS '角色名称';
|
||||
COMMENT ON COLUMN sys.tb_sys_role.description IS '角色名称';
|
||||
COMMENT ON COLUMN sys.tb_sys_role.scope IS '角色作用域:global=通用,dept=部门私有';
|
||||
COMMENT ON COLUMN sys.tb_sys_role.owner_dept_id IS '部门私有角色的所属部门ID(scope=dept 时必填)';
|
||||
COMMENT ON COLUMN sys.tb_sys_role.status IS '角色状态';
|
||||
COMMENT ON COLUMN sys.tb_sys_role.creator IS '创建者';
|
||||
COMMENT ON COLUMN sys.tb_sys_role.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN sys.tb_sys_role.updater IS '更新者';
|
||||
COMMENT ON COLUMN sys.tb_sys_role.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_role.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_role.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_role.deleted IS '是否删除';
|
||||
|
||||
-- 唯一性:
|
||||
-- 全局角色:name 在未删除且 scope=global 下唯一
|
||||
-- 部门私有角色:同一部门下 name 唯一(scope=dept)
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uq_sys_role_global_name
|
||||
ON sys.tb_sys_role USING btree (name)
|
||||
WHERE deleted = false AND scope = 'global';
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uq_sys_role_dept_name
|
||||
ON sys.tb_sys_role USING btree (owner_dept_id, name)
|
||||
WHERE deleted = false AND scope = 'dept';
|
||||
CREATE INDEX IF NOT EXISTS idx_sys_role_owner_dept ON sys.tb_sys_role USING btree (owner_dept_id) WHERE deleted = false;
|
||||
|
||||
-- 部门角色关联表
|
||||
DROP TABLE IF EXISTS sys.tb_sys_dept_role CASCADE;
|
||||
CREATE TABLE sys.tb_sys_dept_role (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
dept_id VARCHAR(50) NOT NULL, -- 部门ID
|
||||
role_id VARCHAR(50) NOT NULL, -- 角色ID
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间(由触发器维护)
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted boolean NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (dept_id, role_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
COMMENT ON TABLE sys.tb_sys_dept_role IS '部门角色关联表';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept_role.optsn IS '流水号';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept_role.dept_id IS '部门ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept_role.role_id IS '角色ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept_role.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept_role.creator IS '创建者';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept_role.updater IS '更新者';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept_role.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept_role.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept_role.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_dept_role.deleted IS '是否删除';
|
||||
|
||||
-- 用户角色关联表
|
||||
DROP TABLE IF EXISTS sys.tb_sys_user_role CASCADE;
|
||||
CREATE TABLE sys.tb_sys_user_role (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
user_id VARCHAR(50) NOT NULL, -- 用户ID
|
||||
role_id VARCHAR(50) NOT NULL, -- 角色ID
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间(由触发器维护)
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted boolean NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (user_id, role_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
COMMENT ON TABLE sys.tb_sys_user_role IS '用户角色关联表';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_role.optsn IS '流水号';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_role.user_id IS '用户ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_role.role_id IS '角色ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_role.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_role.creator IS '创建者';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_role.updater IS '更新者';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_role.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_role.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_role.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_role.deleted IS '是否删除';
|
||||
|
||||
-- 视图表
|
||||
DROP TABLE IF EXISTS sys.tb_sys_view CASCADE;
|
||||
CREATE TABLE sys.tb_sys_view (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
view_id VARCHAR(50) NOT NULL, -- 视图ID
|
||||
name VARCHAR(100) NOT NULL, -- 视图名称
|
||||
parent_id VARCHAR(50) DEFAULT NULL, -- 父视图ID
|
||||
url VARCHAR(255) DEFAULT NULL, -- 视图URL
|
||||
component VARCHAR(255) DEFAULT NULL, -- 视图组件
|
||||
icon VARCHAR(100) DEFAULT NULL, -- 视图图标
|
||||
type integer DEFAULT 0, -- 视图类型
|
||||
layout VARCHAR(100) DEFAULT NULL, -- 布局组件路径名称
|
||||
order_num integer DEFAULT 0, -- 视图排序号
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
description VARCHAR(255) DEFAULT NULL, -- 视图描述
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间(由触发器维护)
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted boolean NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (view_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
COMMENT ON TABLE sys.tb_sys_view IS '视图表';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.optsn IS '流水号';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.view_id IS '视图ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.name IS '视图名称';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.parent_id IS '父视图ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.url IS '视图URL';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.component IS '视图组件';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.icon IS '视图图标';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.type IS '视图类型';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.layout IS '布局组件路径名称';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.order_num IS '视图排序号';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.description IS '视图描述';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.creator IS '创建者';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.updater IS '更新者';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_view.deleted IS '是否删除';
|
||||
|
||||
|
||||
-- 模块表
|
||||
DROP TABLE IF EXISTS sys.tb_sys_module CASCADE;
|
||||
CREATE TABLE sys.tb_sys_module (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
module_id VARCHAR(50) NOT NULL, -- 模块ID
|
||||
name VARCHAR(100) NOT NULL, -- 模块名称
|
||||
description VARCHAR(255) DEFAULT NULL, -- 模块描述
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间(由触发器维护)
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted boolean NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (module_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
COMMENT ON TABLE sys.tb_sys_module IS '模块表';
|
||||
COMMENT ON COLUMN sys.tb_sys_module.optsn IS '流水号';
|
||||
COMMENT ON COLUMN sys.tb_sys_module.module_id IS '模块ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_module.name IS '模块名称';
|
||||
COMMENT ON COLUMN sys.tb_sys_module.description IS '模块描述';
|
||||
COMMENT ON COLUMN sys.tb_sys_module.creator IS '创建者';
|
||||
COMMENT ON COLUMN sys.tb_sys_module.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN sys.tb_sys_module.updater IS '更新者';
|
||||
COMMENT ON COLUMN sys.tb_sys_module.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_module.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_module.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_module.deleted IS '是否删除';
|
||||
|
||||
-- 权限表
|
||||
DROP TABLE IF EXISTS sys.tb_sys_permission CASCADE;
|
||||
CREATE TABLE sys.tb_sys_permission (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
permission_id VARCHAR(50) NOT NULL, -- 权限ID
|
||||
name VARCHAR(100) NOT NULL, -- 权限名称
|
||||
code VARCHAR(100) NOT NULL, -- 权限代码
|
||||
description VARCHAR(255) DEFAULT NULL, -- 权限描述
|
||||
module_id VARCHAR(50) DEFAULT NULL, -- 所属模块ID
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
dept_path VARCHAR(255) DEFAULT NULL,
|
||||
status boolean NOT NULL DEFAULT false, -- 部门全路径
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间(由触发器维护)
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted boolean NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (permission_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
COMMENT ON TABLE sys.tb_sys_permission IS '权限表';
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.optsn IS '流水号';
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.permission_id IS '权限ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.name IS '权限名称';
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.code IS '权限代码';
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.description IS '权限描述' ;
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.module_id IS '所属模块ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.creator IS '创建者';
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.status IS '角色状态';
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.updater IS '更新者';
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.deleted IS '是否删除';
|
||||
|
||||
-- 角色权限
|
||||
DROP TABLE IF EXISTS sys.tb_sys_role_permission CASCADE;
|
||||
CREATE TABLE sys.tb_sys_role_permission (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
role_id VARCHAR(50) NOT NULL, -- 角色ID
|
||||
permission_id VARCHAR(50) NOT NULL, -- 权限ID
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间(由触发器维护)
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted boolean NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (role_id, permission_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
COMMENT ON TABLE sys.tb_sys_role_permission IS '角色权限表';
|
||||
COMMENT ON COLUMN sys.tb_sys_role_permission.optsn IS '流水号';
|
||||
COMMENT ON COLUMN sys.tb_sys_role_permission.role_id IS '角色ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_role_permission.permission_id IS '权限ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_role_permission.creator IS '创建者';
|
||||
COMMENT ON COLUMN sys.tb_sys_role_permission.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN sys.tb_sys_role_permission.updater IS '更新者';
|
||||
COMMENT ON COLUMN sys.tb_sys_role_permission.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_role_permission.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_role_permission.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_role_permission.deleted IS '是否删除';
|
||||
|
||||
-- 视图权限
|
||||
DROP TABLE IF EXISTS sys.tb_sys_view_permission CASCADE;
|
||||
CREATE TABLE sys.tb_sys_view_permission (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
view_id VARCHAR(50) NOT NULL, -- 视图ID
|
||||
permission_id VARCHAR(50) NOT NULL, -- 权限ID
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间(由触发器维护)
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted boolean NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (view_id, permission_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
COMMENT ON TABLE sys.tb_sys_view_permission IS '视图权限表';
|
||||
COMMENT ON COLUMN sys.tb_sys_view_permission.optsn IS '流水号';
|
||||
COMMENT ON COLUMN sys.tb_sys_view_permission.view_id IS '视图ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_view_permission.permission_id IS '权限ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_view_permission.creator IS '创建者';
|
||||
COMMENT ON COLUMN sys.tb_sys_view_permission.dept_path IS '部门全路径';
|
||||
COMMENT ON COLUMN sys.tb_sys_view_permission.updater IS '更新者';
|
||||
COMMENT ON COLUMN sys.tb_sys_view_permission.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_view_permission.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_view_permission.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_view_permission.deleted IS '是否删除';
|
||||
|
||||
-- 为所有表创建更新时间触发器
|
||||
-- DROP TRIGGER IF EXISTS trg_tb_sys_dept_update_time ON sys.tb_sys_dept;
|
||||
-- CREATE TRIGGER trg_tb_sys_dept_update_time
|
||||
-- BEFORE UPDATE ON sys.tb_sys_dept
|
||||
-- FOR EACH ROW
|
||||
-- EXECUTE FUNCTION sys.set_update_time();
|
||||
|
||||
-- DROP TRIGGER IF EXISTS trg_tb_sys_role_update_time ON sys.tb_sys_role;
|
||||
-- CREATE TRIGGER trg_tb_sys_role_update_time
|
||||
-- BEFORE UPDATE ON sys.tb_sys_role
|
||||
-- FOR EACH ROW
|
||||
-- EXECUTE FUNCTION sys.set_update_time();
|
||||
|
||||
-- DROP TRIGGER IF EXISTS trg_tb_sys_dept_role_update_time ON sys.tb_sys_dept_role;
|
||||
-- CREATE TRIGGER trg_tb_sys_dept_role_update_time
|
||||
-- BEFORE UPDATE ON sys.tb_sys_dept_role
|
||||
-- FOR EACH ROW
|
||||
-- EXECUTE FUNCTION sys.set_update_time();
|
||||
|
||||
-- DROP TRIGGER IF EXISTS trg_tb_sys_user_role_update_time ON sys.tb_sys_user_role;
|
||||
-- CREATE TRIGGER trg_tb_sys_user_role_update_time
|
||||
-- BEFORE UPDATE ON sys.tb_sys_user_role
|
||||
-- FOR EACH ROW
|
||||
-- EXECUTE FUNCTION sys.set_update_time();
|
||||
|
||||
-- DROP TRIGGER IF EXISTS trg_tb_sys_view_update_time ON sys.tb_sys_view;
|
||||
-- CREATE TRIGGER trg_tb_sys_view_update_time
|
||||
-- BEFORE UPDATE ON sys.tb_sys_view
|
||||
-- FOR EACH ROW
|
||||
-- EXECUTE FUNCTION sys.set_update_time();
|
||||
|
||||
-- DROP TRIGGER IF EXISTS trg_tb_sys_module_update_time ON sys.tb_sys_module;
|
||||
-- CREATE TRIGGER trg_tb_sys_module_update_time
|
||||
-- BEFORE UPDATE ON sys.tb_sys_module
|
||||
-- FOR EACH ROW
|
||||
-- EXECUTE FUNCTION sys.set_update_time();
|
||||
|
||||
-- DROP TRIGGER IF EXISTS trg_tb_sys_permission_update_time ON sys.tb_sys_permission;
|
||||
-- CREATE TRIGGER trg_tb_sys_permission_update_time
|
||||
-- BEFORE UPDATE ON sys.tb_sys_permission
|
||||
-- FOR EACH ROW
|
||||
-- EXECUTE FUNCTION sys.set_update_time();
|
||||
|
||||
-- DROP TRIGGER IF EXISTS trg_tb_sys_role_permission_update_time ON sys.tb_sys_role_permission;
|
||||
-- CREATE TRIGGER trg_tb_sys_role_permission_update_time
|
||||
-- BEFORE UPDATE ON sys.tb_sys_role_permission
|
||||
-- FOR EACH ROW
|
||||
-- EXECUTE FUNCTION sys.set_update_time();
|
||||
|
||||
-- DROP TRIGGER IF EXISTS trg_tb_sys_view_permission_update_time ON sys.tb_sys_view_permission;
|
||||
-- CREATE TRIGGER trg_tb_sys_view_permission_update_time
|
||||
-- BEFORE UPDATE ON sys.tb_sys_view_permission
|
||||
-- FOR EACH ROW
|
||||
-- EXECUTE FUNCTION sys.set_update_time();
|
||||
|
||||
-- =============================
|
||||
-- 通用对象级权限(ACL)
|
||||
-- 支持对象类型:任意(如 article/file/course/...)
|
||||
-- 支持主体:user/dept/role
|
||||
-- 权限位:1=读(read),2=写(write),4=执行(exec),可相加
|
||||
-- include_descendants:当主体为 dept/role 时,是否包含其子级(便于“所有子级可查看”场景)
|
||||
-- allow:true=允许;false=显式拒绝(拒绝优先生效)
|
||||
-- dept_path:用于数据范围隔离(与现有规则一致)
|
||||
-- =============================
|
||||
|
||||
DROP TABLE IF EXISTS sys.tb_sys_acl CASCADE;
|
||||
CREATE TABLE sys.tb_sys_acl (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
acl_id VARCHAR(50) NOT NULL, -- ACL主键
|
||||
object_type VARCHAR(50) NOT NULL, -- 对象类型:article/file/course/...
|
||||
object_id VARCHAR(50) NOT NULL, -- 对象ID
|
||||
principal_type VARCHAR(20) NOT NULL, -- 主体类型:user/dept/role
|
||||
principal_id VARCHAR(50) NOT NULL, -- 主体ID
|
||||
principal_dept_id VARCHAR(50) DEFAULT NULL, -- 当主体为role且限定到某部门时的部门ID(支持“某部门的某角色”)
|
||||
permission SMALLINT NOT NULL, -- 权限位:1读 2写 4执行
|
||||
allow BOOLEAN NOT NULL DEFAULT true, -- 允许或显式拒绝
|
||||
include_descendants BOOLEAN NOT NULL DEFAULT false, -- 是否包含子级(对dept/role生效)
|
||||
dept_path VARCHAR(255) DEFAULT NULL, -- 部门全路径(数据隔离)
|
||||
creator VARCHAR(50) DEFAULT NULL, -- 创建者
|
||||
updater VARCHAR(50) DEFAULT NULL, -- 更新者
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted boolean NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (acl_id),
|
||||
UNIQUE (object_type, object_id, principal_type, principal_id, principal_dept_id, deleted),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE sys.tb_sys_acl IS '通用对象级权限表(ACL)';
|
||||
COMMENT ON COLUMN sys.tb_sys_acl.object_type IS '对象类型:article/file/course/...';
|
||||
COMMENT ON COLUMN sys.tb_sys_acl.object_id IS '对象ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_acl.principal_type IS '主体类型:user/dept/role';
|
||||
COMMENT ON COLUMN sys.tb_sys_acl.principal_id IS '主体ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_acl.principal_dept_id IS '当主体为角色时,可选的限定部门ID(某部门的某角色)';
|
||||
COMMENT ON COLUMN sys.tb_sys_acl.permission IS '权限位:1读 2写 4执行,可相加';
|
||||
COMMENT ON COLUMN sys.tb_sys_acl.allow IS '是否允许(false=显式拒绝)';
|
||||
COMMENT ON COLUMN sys.tb_sys_acl.include_descendants IS '是否包含子级(dept/role时启用)';
|
||||
COMMENT ON COLUMN sys.tb_sys_acl.dept_path IS '部门全路径(用于数据范围隔离)';
|
||||
|
||||
CREATE INDEX idx_sys_acl_object ON sys.tb_sys_acl USING btree (object_type, object_id) WHERE deleted = false;
|
||||
CREATE INDEX idx_sys_acl_principal ON sys.tb_sys_acl USING btree (principal_type, principal_id) WHERE deleted = false;
|
||||
CREATE INDEX idx_sys_acl_dept_path ON sys.tb_sys_acl USING btree (dept_path) WHERE deleted = false;
|
||||
-- 针对“某部门的某角色”的检索优化
|
||||
CREATE INDEX idx_sys_acl_role_scoped ON sys.tb_sys_acl USING btree (principal_id, principal_dept_id)
|
||||
WHERE deleted = false AND principal_type = 'role';
|
||||
|
||||
-- =============================
|
||||
-- ACL 策略表:定义对象类型的层级可见/可编辑规则
|
||||
-- 例如:
|
||||
-- - 同级与父级管理员可修改(edit_hierarchy_rule = 'parent_or_same_admin')
|
||||
-- - 子级全部可查看(view_hierarchy_rule = 'children_all')
|
||||
-- - 课程:下级只有指定部门/角色可查看(view_hierarchy_rule = 'children_specified')
|
||||
-- 说明:业务侧需结合“管理员”的判定(通常由角色判定)在应用层实现;本表做规则声明
|
||||
-- =============================
|
||||
|
||||
DROP TABLE IF EXISTS sys.tb_sys_acl_policy CASCADE;
|
||||
CREATE TABLE sys.tb_sys_acl_policy (
|
||||
optsn VARCHAR(50) NOT NULL, -- 流水号
|
||||
policy_id VARCHAR(50) NOT NULL, -- 策略ID
|
||||
name VARCHAR(255) NOT NULL, -- 策略名称
|
||||
object_type VARCHAR(50) NOT NULL, -- 目标对象类型
|
||||
edit_hierarchy_rule VARCHAR(50) DEFAULT NULL, -- 编辑层级规则:parent_only/parent_or_same_admin/owner_only/none
|
||||
view_hierarchy_rule VARCHAR(50) DEFAULT NULL, -- 查看层级规则:children_all/children_specified/none
|
||||
default_permission SMALLINT DEFAULT 0, -- 默认权限位(无显式ACL时应用)
|
||||
default_allow BOOLEAN DEFAULT true, -- 默认是否允许
|
||||
apply_to_children BOOLEAN DEFAULT true, -- 是否默认应用到子级
|
||||
creator VARCHAR(50) DEFAULT NULL,
|
||||
updater VARCHAR(50) DEFAULT NULL,
|
||||
create_time timestamptz NOT NULL DEFAULT now(),
|
||||
update_time timestamptz DEFAULT NULL,
|
||||
delete_time timestamptz DEFAULT NULL,
|
||||
deleted boolean NOT NULL DEFAULT false,
|
||||
PRIMARY KEY (policy_id),
|
||||
UNIQUE (object_type, deleted),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE sys.tb_sys_acl_policy IS 'ACL对象类型策略表(层级可见/可编辑规则)';
|
||||
COMMENT ON COLUMN sys.tb_sys_acl_policy.object_type IS '对象类型:article/file/course/...';
|
||||
COMMENT ON COLUMN sys.tb_sys_acl_policy.edit_hierarchy_rule IS '编辑层级规则:parent_only/parent_or_same_admin/owner_only/none';
|
||||
COMMENT ON COLUMN sys.tb_sys_acl_policy.view_hierarchy_rule IS '查看层级规则:children_all/children_specified/none';
|
||||
COMMENT ON COLUMN sys.tb_sys_acl_policy.default_permission IS '默认权限位(无显式ACL时兜底)';
|
||||
COMMENT ON COLUMN sys.tb_sys_acl_policy.apply_to_children IS '默认是否应用到子级';
|
||||
|
||||
CREATE INDEX idx_sys_acl_policy_object ON sys.tb_sys_acl_policy USING btree (object_type) WHERE deleted = false;
|
||||
120
urbanLifelineServ/.bin/database/postgres/sql/createTableUser.sql
Normal file
120
urbanLifelineServ/.bin/database/postgres/sql/createTableUser.sql
Normal file
@@ -0,0 +1,120 @@
|
||||
|
||||
-- 创建 sys schema(如果不存在)
|
||||
CREATE SCHEMA IF NOT EXISTS sys;
|
||||
|
||||
-- 用户表
|
||||
DROP TABLE IF EXISTS sys.tb_sys_user CASCADE;
|
||||
CREATE TABLE sys.tb_sys_user (
|
||||
optsn varchar(50) NOT NULL, -- 流水号
|
||||
user_id varchar(50) NOT NULL, -- 用户ID
|
||||
password varchar(128) NOT NULL, -- 密码(建议存储 bcrypt/argon2 哈希)
|
||||
email varchar(100), -- 电子邮件
|
||||
phone varchar(20), -- 电话号码
|
||||
wechat_id varchar(50), -- 微信ID
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间(使用带时区时间)
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间(由触发器维护)
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted boolean NOT NULL DEFAULT false, -- 是否删除(使用 boolean)
|
||||
status integer NOT NULL DEFAULT 1, -- 状态
|
||||
PRIMARY KEY (user_id),
|
||||
UNIQUE (optsn),
|
||||
UNIQUE (email),
|
||||
UNIQUE (phone),
|
||||
UNIQUE (wechat_id)
|
||||
);
|
||||
CREATE INDEX idx_tb_sys_user_phone ON sys.tb_sys_user USING btree (phone);
|
||||
|
||||
-- 按 email 域名建立表达式索引(对域名小写处理以实现不区分大小写的域名查询)
|
||||
-- 使用 split_part(email, '@', 2) 提取 @ 之后的域名部分,再做 lower() 归一化
|
||||
-- WHERE email IS NOT NULL 可以避免索引包含大量 NULL
|
||||
CREATE INDEX idx_tb_sys_user_email_domain ON sys.tb_sys_user USING btree (lower(split_part(email, '@', 2)))
|
||||
WHERE email IS NOT NULL;
|
||||
CREATE INDEX idx_tb_sys_user_wechat_id ON sys.tb_sys_user USING btree (wechat_id);
|
||||
|
||||
-- 可选:保留列注释(如果你想把 MySQL 的 COMMENT 同步到 Postgres)
|
||||
COMMENT ON TABLE sys.tb_sys_user IS '用户表';
|
||||
COMMENT ON COLUMN sys.tb_sys_user.optsn IS '流水号';
|
||||
COMMENT ON COLUMN sys.tb_sys_user.user_id IS '用户ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_user.password IS '密码(建议存储 bcrypt/argon2 哈希)';
|
||||
COMMENT ON COLUMN sys.tb_sys_user.email IS '电子邮件';
|
||||
COMMENT ON COLUMN sys.tb_sys_user.phone IS '电话号码';
|
||||
COMMENT ON COLUMN sys.tb_sys_user.wechat_id IS '微信ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_user.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_user.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_user.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_user.deleted IS '是否删除';
|
||||
COMMENT ON COLUMN sys.tb_sys_user.status IS '状态';
|
||||
|
||||
-- 用户信息表
|
||||
DROP TABLE IF EXISTS sys.tb_sys_user_info CASCADE;
|
||||
CREATE TABLE sys.tb_sys_user_info (
|
||||
optsn varchar(50) NOT NULL, -- 流水号
|
||||
user_id varchar(50) NOT NULL, -- 用户ID
|
||||
avatar varchar(255), -- 头像
|
||||
gender integer DEFAULT 0, -- 性别
|
||||
family_name varchar(50), -- 姓
|
||||
given_name varchar(50), -- 名
|
||||
full_name varchar(100), -- 全名
|
||||
level integer DEFAULT 1, -- 等级
|
||||
id_card varchar(50), -- 身份证号
|
||||
address varchar(255), -- 地址
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
update_time timestamptz DEFAULT NULL, -- 更新时间(触发器维护)
|
||||
delete_time timestamptz DEFAULT NULL, -- 删除时间
|
||||
deleted boolean NOT NULL DEFAULT false, -- 是否删除
|
||||
PRIMARY KEY (user_id),
|
||||
UNIQUE (optsn)
|
||||
);
|
||||
COMMENT ON TABLE sys.tb_sys_user_info IS '用户信息表';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_info.optsn IS '流水号';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_info.user_id IS '用户ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_info.avatar IS '头像';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_info.gender IS '性别';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_info.family_name IS '姓';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_info.given_name IS '名';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_info.full_name IS '全名';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_info.level IS '等级';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_info.id_card IS '身份证号';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_info.address IS '地址';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_info.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_info.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_info.delete_time IS '删除时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_info.deleted IS '是否删除';
|
||||
|
||||
-- 登录日志表
|
||||
DROP TABLE IF EXISTS sys.tb_sys_login_log CASCADE;
|
||||
CREATE TABLE sys.tb_sys_login_log (
|
||||
optsn varchar(50) NOT NULL, -- 流水号(作为主键)
|
||||
user_id varchar(50) NOT NULL, -- 用户ID
|
||||
username varchar(50) NOT NULL, -- 用户名
|
||||
ip_address varchar(45), -- IP地址
|
||||
ip_source varchar(100), -- IP来源
|
||||
browser varchar(100), -- 浏览器
|
||||
os varchar(100), -- 操作系统
|
||||
password varchar(128), -- 密码(建议存储 bcrypt/argon2 哈希)
|
||||
login_time timestamptz DEFAULT now(), -- 登录时间
|
||||
status integer DEFAULT 1, -- 登录状态(0失败 1成功)
|
||||
error_count integer DEFAULT 0, -- 错误次数
|
||||
message varchar(255), -- 登录消息
|
||||
create_time timestamptz NOT NULL DEFAULT now(), -- 创建时间
|
||||
PRIMARY KEY (optsn)
|
||||
);
|
||||
-- B-tree 索引(显式指定 USING btree,Postgres 默认即为 btree)
|
||||
CREATE INDEX idx_tb_sys_login_log_user_id ON sys.tb_sys_login_log USING btree (user_id);
|
||||
CREATE INDEX idx_tb_sys_login_log_login_time ON sys.tb_sys_login_log USING btree (login_time);
|
||||
|
||||
-- 可选:保留列注释
|
||||
COMMENT ON TABLE sys.tb_sys_login_log IS '登录日志表';
|
||||
COMMENT ON COLUMN sys.tb_sys_login_log.optsn IS '流水号';
|
||||
COMMENT ON COLUMN sys.tb_sys_login_log.user_id IS '用户ID';
|
||||
COMMENT ON COLUMN sys.tb_sys_login_log.username IS '用户名';
|
||||
COMMENT ON COLUMN sys.tb_sys_login_log.ip_address IS 'IP地址';
|
||||
COMMENT ON COLUMN sys.tb_sys_login_log.ip_source IS 'IP来源';
|
||||
COMMENT ON COLUMN sys.tb_sys_login_log.browser IS '浏览器';
|
||||
COMMENT ON COLUMN sys.tb_sys_login_log.os IS '操作系统';
|
||||
COMMENT ON COLUMN sys.tb_sys_login_log.password IS '密码(建议存储 bcrypt/argon2 哈希)';
|
||||
COMMENT ON COLUMN sys.tb_sys_login_log.login_time IS '登录时间';
|
||||
COMMENT ON COLUMN sys.tb_sys_login_log.status IS '登录状态(0失败 1成功)';
|
||||
COMMENT ON COLUMN sys.tb_sys_login_log.error_count IS '错误次数';
|
||||
COMMENT ON COLUMN sys.tb_sys_login_log.message IS '登录消息';
|
||||
COMMENT ON COLUMN sys.tb_sys_login_log.create_time IS '创建时间';
|
||||
11
urbanLifelineServ/.bin/database/postgres/sql/initAll.sql
Normal file
11
urbanLifelineServ/.bin/database/postgres/sql/initAll.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
-- 按顺序执行初始化
|
||||
\i createDB.sql -- 创建数据库和基础扩展
|
||||
\i createTableUser.sql -- 用户表相关(核心表)
|
||||
\i createTablePermission.sql -- 权限相关(核心表)
|
||||
\i createTableFile.sql -- 文件管理
|
||||
\i createTableMessage.sql -- 消息管理
|
||||
\i createTableConfig.sql -- 配置管理
|
||||
\i createTableLog.sql -- 日志管理
|
||||
|
||||
-- 初始化基础数据(如果有)
|
||||
-- \i initBaseData.sql -- 取消注释如果需要初始化基础数据
|
||||
@@ -0,0 +1,43 @@
|
||||
-- 初始化系统常用配置(与 config.tb_sys_config 对应)
|
||||
-- 仅插入常用示例,可按需调整 value/remark
|
||||
|
||||
INSERT INTO config.tb_sys_config (
|
||||
optsn, config_id, key, value, type, description, "group", "order", status, remark,
|
||||
creator, dept_path, updater, create_time, update_time, delete_time, deleted
|
||||
) VALUES
|
||||
|
||||
-- 站点与品牌
|
||||
('CFG-0001', 'cfg_site_name', 'site.name', 'urban-lifeline 平台', 'string', '站点名称', 'site', 10, 'enabled', '展示在标题/登录/页脚', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
('CFG-0002', 'cfg_site_logo', 'site.logo', '/static/logo.png', 'string', '站点Logo地址', 'site', 20, 'enabled', '相对或绝对URL', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
('CFG-0003', 'cfg_site_icp', 'site.icp', '', 'string', 'ICP备案号', 'site', 30, 'enabled', '页脚展示', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
|
||||
-- 国际化与时区
|
||||
('CFG-0101', 'cfg_i18n_locale', 'i18n.defaultLocale', 'zh-CN', 'string', '默认语言', 'i18n', 10, 'enabled', '如 zh-CN/en-US', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
('CFG-0102', 'cfg_timezone', 'system.timezone', 'Asia/Shanghai', 'string', '系统默认时区', 'i18n', 20, 'enabled', 'IANA时区名', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
|
||||
-- 安全与认证
|
||||
('CFG-0201', 'cfg_pwd_policy', 'security.passwordPolicy','{"minLen":8,"upper":1,"lower":1,"digit":1,"special":0}', 'json', '密码策略', 'security', 10, 'enabled', 'JSON结构', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
('CFG-0202', 'cfg_jwt_exp', 'security.jwt.expireSeconds','86400', 'number', 'JWT过期秒数', 'security', 20, 'enabled', '默认24小时', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
('CFG-0203', 'cfg_session_timeout', 'security.session.timeoutMinutes','30', 'number', '会话超时(分钟)', 'security', 30, 'enabled', '空闲登出', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
('CFG-0204', 'cfg_signup_enabled', 'security.signup.enabled','false', 'bool', '是否开放注册', 'security', 40, 'enabled', '生产建议关闭', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
|
||||
-- 存储与上传
|
||||
('CFG-0301', 'cfg_upload_max', 'upload.maxSizeMB', '50', 'number', '单文件最大上传(MB)', 'storage', 10, 'enabled', '前后端需一致校验', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
('CFG-0302', 'cfg_storage_backend', 'storage.backend', 'local', 'string', '存储后端(local/minio/s3)', 'storage', 20, 'enabled', '本地/MinIO/S3等', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
('CFG-0303', 'cfg_storage_base', 'storage.basePath', '/data/urban-lifeline', 'string', '本地存储基路径', 'storage', 30, 'enabled', '当 backend=local', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
|
||||
-- 通知(邮件/SMS)
|
||||
('CFG-0401', 'cfg_mail_host', 'mail.smtp.host', '', 'string', 'SMTP主机', 'notify', 10, 'disabled','留空为未配置', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
('CFG-0402', 'cfg_mail_port', 'mail.smtp.port', '465', 'number', 'SMTP端口', 'notify', 20, 'disabled','SSL常用465', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
('CFG-0403', 'cfg_mail_from', 'mail.from', '', 'string', '发件人邮箱', 'notify', 30, 'disabled','如 no-reply@x.com', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
('CFG-0411', 'cfg_sms_provider', 'sms.provider', '', 'string', '短信服务商', 'notify', 40, 'disabled','如 aliyun/tencent', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
|
||||
-- 日志与审计
|
||||
('CFG-0501', 'cfg_log_level', 'log.level', 'INFO', 'string', '系统日志级别', 'log', 10, 'enabled', 'DEBUG/INFO/WARN/ERROR', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
('CFG-0502', 'cfg_audit_retention', 'audit.retentionDays', '90', 'number', '审计日志保留天数', 'log', 20, 'enabled', '合规按需调整', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
|
||||
-- 平台特性
|
||||
('CFG-0601', 'cfg_maintenance', 'platform.maintenance', 'false', 'bool', '维护模式开关', 'platform', 10, 'enabled', 'true时仅管理员可用', 'system', NULL, NULL, now(), NULL, NULL, false),
|
||||
('CFG-0602', 'cfg_feature_acl_policy', 'feature.acl.policy', 'enabled', 'string', 'ACL策略开关', 'platform', 20, 'enabled', 'enabled/disabled', 'system', NULL, NULL, now(), NULL, NULL, false);
|
||||
|
||||
|
||||
549
urbanLifelineServ/.bin/database/postgres/sql/optimizations.sql
Normal file
549
urbanLifelineServ/.bin/database/postgres/sql/optimizations.sql
Normal file
@@ -0,0 +1,549 @@
|
||||
-- =============================
|
||||
-- 数据库优化补丁脚本
|
||||
-- 基于现有表结构的增强和修改
|
||||
-- =============================
|
||||
|
||||
-- =============================
|
||||
-- 1. 用户模块优化
|
||||
-- =============================
|
||||
|
||||
-- 1.1 移除登录日志表中的敏感密码字段
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'sys'
|
||||
AND table_name = 'tb_sys_login_log'
|
||||
AND column_name = 'password'
|
||||
) THEN
|
||||
ALTER TABLE sys.tb_sys_login_log DROP COLUMN password;
|
||||
RAISE NOTICE '已移除登录日志表的密码字段';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 1.2 创建用户部门关联表
|
||||
CREATE TABLE IF NOT EXISTS sys.tb_sys_user_dept (
|
||||
optsn VARCHAR(50) NOT NULL,
|
||||
user_id VARCHAR(50) NOT NULL,
|
||||
dept_id VARCHAR(50) NOT NULL,
|
||||
is_primary BOOLEAN DEFAULT false,
|
||||
position VARCHAR(100),
|
||||
creator VARCHAR(50) DEFAULT NULL,
|
||||
updater VARCHAR(50) DEFAULT NULL,
|
||||
create_time timestamptz NOT NULL DEFAULT now(),
|
||||
update_time timestamptz DEFAULT NULL,
|
||||
delete_time timestamptz DEFAULT NULL,
|
||||
deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
PRIMARY KEY (user_id, dept_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (user_id) REFERENCES sys.tb_sys_user(user_id),
|
||||
FOREIGN KEY (dept_id) REFERENCES sys.tb_sys_dept(dept_id)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE sys.tb_sys_user_dept IS '用户部门关联表';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_dept.is_primary IS '是否主部门';
|
||||
COMMENT ON COLUMN sys.tb_sys_user_dept.position IS '职位';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_user_dept_user ON sys.tb_sys_user_dept(user_id) WHERE deleted = false;
|
||||
CREATE INDEX IF NOT EXISTS idx_user_dept_dept ON sys.tb_sys_user_dept(dept_id) WHERE deleted = false;
|
||||
|
||||
-- 1.3 用户表添加主部门字段
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'sys'
|
||||
AND table_name = 'tb_sys_user'
|
||||
AND column_name = 'primary_dept_id'
|
||||
) THEN
|
||||
ALTER TABLE sys.tb_sys_user ADD COLUMN primary_dept_id VARCHAR(50);
|
||||
COMMENT ON COLUMN sys.tb_sys_user.primary_dept_id IS '主部门ID';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- =============================
|
||||
-- 2. 权限模块优化
|
||||
-- =============================
|
||||
|
||||
-- 2.1 角色表添加排序字段
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'sys'
|
||||
AND table_name = 'tb_sys_role'
|
||||
AND column_name = 'order_num'
|
||||
) THEN
|
||||
ALTER TABLE sys.tb_sys_role ADD COLUMN order_num INTEGER DEFAULT 0;
|
||||
COMMENT ON COLUMN sys.tb_sys_role.order_num IS '排序号';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 2.2 权限表添加权限类型字段
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'sys'
|
||||
AND table_name = 'tb_sys_permission'
|
||||
AND column_name = 'permission_type'
|
||||
) THEN
|
||||
ALTER TABLE sys.tb_sys_permission ADD COLUMN permission_type VARCHAR(20) DEFAULT 'action';
|
||||
COMMENT ON COLUMN sys.tb_sys_permission.permission_type IS '权限类型:action-操作权限/data-数据权限/menu-菜单权限';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- =============================
|
||||
-- 3. 文件模块扩展
|
||||
-- =============================
|
||||
|
||||
-- 3.1 文件表添加版本管理字段
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'file'
|
||||
AND table_name = 'tb_sys_file'
|
||||
AND column_name = 'version'
|
||||
) THEN
|
||||
ALTER TABLE file.tb_sys_file
|
||||
ADD COLUMN version VARCHAR(20) DEFAULT '1.0',
|
||||
ADD COLUMN parent_file_id VARCHAR(50),
|
||||
ADD COLUMN is_latest BOOLEAN DEFAULT true;
|
||||
|
||||
COMMENT ON COLUMN file.tb_sys_file.version IS '文件版本号';
|
||||
COMMENT ON COLUMN file.tb_sys_file.parent_file_id IS '父文件ID(版本链)';
|
||||
COMMENT ON COLUMN file.tb_sys_file.is_latest IS '是否最新版本';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 3.2 文件表添加分类和标签
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'file'
|
||||
AND table_name = 'tb_sys_file'
|
||||
AND column_name = 'category'
|
||||
) THEN
|
||||
ALTER TABLE file.tb_sys_file
|
||||
ADD COLUMN category VARCHAR(100),
|
||||
ADD COLUMN tags TEXT[],
|
||||
ADD COLUMN metadata JSONB;
|
||||
|
||||
COMMENT ON COLUMN file.tb_sys_file.category IS '文件分类';
|
||||
COMMENT ON COLUMN file.tb_sys_file.tags IS '文件标签数组';
|
||||
COMMENT ON COLUMN file.tb_sys_file.metadata IS '文件元数据';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 3.3 创建文件关联表
|
||||
CREATE TABLE IF NOT EXISTS file.tb_file_relation (
|
||||
optsn VARCHAR(50) NOT NULL,
|
||||
relation_id VARCHAR(50) NOT NULL,
|
||||
file_id VARCHAR(50) NOT NULL,
|
||||
object_type VARCHAR(50) NOT NULL,
|
||||
object_id VARCHAR(50) NOT NULL,
|
||||
relation_type VARCHAR(30) DEFAULT 'attachment',
|
||||
order_num INTEGER DEFAULT 0,
|
||||
creator VARCHAR(50) DEFAULT NULL,
|
||||
updater VARCHAR(50) DEFAULT NULL,
|
||||
create_time timestamptz NOT NULL DEFAULT now(),
|
||||
update_time timestamptz DEFAULT NULL,
|
||||
delete_time timestamptz DEFAULT NULL,
|
||||
deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
PRIMARY KEY (relation_id),
|
||||
UNIQUE (optsn),
|
||||
FOREIGN KEY (file_id) REFERENCES file.tb_sys_file(file_id)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE file.tb_file_relation IS '文件关联表';
|
||||
COMMENT ON COLUMN file.tb_file_relation.object_type IS '对象类型:bidding_project/ticket/document等';
|
||||
COMMENT ON COLUMN file.tb_file_relation.object_id IS '对象ID';
|
||||
COMMENT ON COLUMN file.tb_file_relation.relation_type IS '关联类型:attachment-附件/avatar-头像/banner-横幅';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_file_relation_object
|
||||
ON file.tb_file_relation(object_type, object_id) WHERE deleted = false;
|
||||
CREATE INDEX IF NOT EXISTS idx_file_relation_file
|
||||
ON file.tb_file_relation(file_id) WHERE deleted = false;
|
||||
|
||||
-- =============================
|
||||
-- 4. 消息模块增强
|
||||
-- =============================
|
||||
|
||||
-- 4.1 创建消息模板表
|
||||
CREATE TABLE IF NOT EXISTS message.tb_message_template (
|
||||
optsn VARCHAR(50) NOT NULL,
|
||||
template_id VARCHAR(50) NOT NULL,
|
||||
template_code VARCHAR(100) NOT NULL,
|
||||
template_name VARCHAR(255) NOT NULL,
|
||||
template_type VARCHAR(30) NOT NULL,
|
||||
title_template TEXT,
|
||||
content_template TEXT NOT NULL,
|
||||
variables JSONB,
|
||||
dept_path VARCHAR(255) DEFAULT NULL,
|
||||
creator VARCHAR(50) DEFAULT NULL,
|
||||
updater VARCHAR(50) DEFAULT NULL,
|
||||
create_time timestamptz NOT NULL DEFAULT now(),
|
||||
update_time timestamptz DEFAULT NULL,
|
||||
delete_time timestamptz DEFAULT NULL,
|
||||
deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
PRIMARY KEY (template_id),
|
||||
UNIQUE (optsn),
|
||||
UNIQUE (template_code)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE message.tb_message_template IS '消息模板表';
|
||||
COMMENT ON COLUMN message.tb_message_template.template_type IS '模板类型:system-系统/business-业务';
|
||||
COMMENT ON COLUMN message.tb_message_template.variables IS '模板变量定义';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_template_type
|
||||
ON message.tb_message_template(template_type) WHERE deleted = false;
|
||||
|
||||
-- =============================
|
||||
-- 5. 日志模块优化
|
||||
-- =============================
|
||||
|
||||
-- 5.1 日志表添加trace_id用于链路追踪
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = 'log'
|
||||
AND table_name = 'tb_sys_log'
|
||||
AND column_name = 'trace_id'
|
||||
) THEN
|
||||
ALTER TABLE log.tb_sys_log
|
||||
ADD COLUMN trace_id VARCHAR(50),
|
||||
ADD COLUMN span_id VARCHAR(50),
|
||||
ADD COLUMN parent_span_id VARCHAR(50);
|
||||
|
||||
COMMENT ON COLUMN log.tb_sys_log.trace_id IS '追踪ID(用于分布式追踪)';
|
||||
COMMENT ON COLUMN log.tb_sys_log.span_id IS '跨度ID';
|
||||
COMMENT ON COLUMN log.tb_sys_log.parent_span_id IS '父跨度ID';
|
||||
|
||||
CREATE INDEX idx_log_trace ON log.tb_sys_log(trace_id) WHERE trace_id IS NOT NULL;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- =============================
|
||||
-- 6. 全文搜索索引
|
||||
-- =============================
|
||||
|
||||
-- 6.1 为知识文档标题创建全文搜索索引
|
||||
CREATE INDEX IF NOT EXISTS idx_knowledge_doc_title_trgm
|
||||
ON knowledge.tb_knowledge_document USING gin(title gin_trgm_ops)
|
||||
WHERE deleted = false;
|
||||
|
||||
-- 6.2 为招标项目名称创建全文搜索索引
|
||||
CREATE INDEX IF NOT EXISTS idx_project_name_trgm
|
||||
ON bidding.tb_bidding_project USING gin(project_name gin_trgm_ops)
|
||||
WHERE deleted = false;
|
||||
|
||||
-- 6.3 为客户姓名创建全文搜索索引
|
||||
CREATE INDEX IF NOT EXISTS idx_customer_name_trgm
|
||||
ON customer_service.tb_customer USING gin(customer_name gin_trgm_ops)
|
||||
WHERE deleted = false;
|
||||
|
||||
-- =============================
|
||||
-- 7. JSONB字段优化索引
|
||||
-- =============================
|
||||
|
||||
-- 7.1 智能体配置JSONB索引
|
||||
CREATE INDEX IF NOT EXISTS idx_agent_model_config_gin
|
||||
ON agent.tb_agent USING gin(model_config)
|
||||
WHERE deleted = false;
|
||||
|
||||
-- 7.2 工单元数据JSONB索引
|
||||
CREATE INDEX IF NOT EXISTS idx_ticket_metadata_gin
|
||||
ON customer_service.tb_ticket USING gin(metadata)
|
||||
WHERE deleted = false;
|
||||
|
||||
-- =============================
|
||||
-- 8. 性能优化视图
|
||||
-- =============================
|
||||
|
||||
-- 8.1 用户完整权限视图(包含ACL)
|
||||
CREATE OR REPLACE VIEW sys.v_user_full_permissions AS
|
||||
WITH user_roles AS (
|
||||
-- 用户直接拥有的角色权限
|
||||
SELECT DISTINCT
|
||||
ur.user_id,
|
||||
p.permission_id,
|
||||
p.code AS permission_code,
|
||||
p.name AS permission_name,
|
||||
'role' AS source_type,
|
||||
r.role_id AS source_id
|
||||
FROM sys.tb_sys_user_role ur
|
||||
JOIN sys.tb_sys_role r ON ur.role_id = r.role_id
|
||||
JOIN sys.tb_sys_role_permission rp ON r.role_id = rp.role_id
|
||||
JOIN sys.tb_sys_permission p ON rp.permission_id = p.permission_id
|
||||
WHERE ur.deleted = false
|
||||
AND r.deleted = false
|
||||
AND rp.deleted = false
|
||||
AND p.deleted = false
|
||||
),
|
||||
user_acls AS (
|
||||
-- 用户的ACL权限
|
||||
SELECT DISTINCT
|
||||
principal_id AS user_id,
|
||||
object_type || ':' || object_id AS permission_id,
|
||||
object_type || '_' ||
|
||||
CASE
|
||||
WHEN (permission & 1) = 1 THEN 'read'
|
||||
WHEN (permission & 2) = 2 THEN 'write'
|
||||
WHEN (permission & 4) = 4 THEN 'exec'
|
||||
END AS permission_code,
|
||||
'ACL permission on ' || object_type AS permission_name,
|
||||
'acl' AS source_type,
|
||||
acl_id AS source_id
|
||||
FROM sys.tb_sys_acl
|
||||
WHERE principal_type = 'user'
|
||||
AND allow = true
|
||||
AND deleted = false
|
||||
)
|
||||
SELECT * FROM user_roles
|
||||
UNION ALL
|
||||
SELECT * FROM user_acls;
|
||||
|
||||
COMMENT ON VIEW sys.v_user_full_permissions IS '用户完整权限视图(包含角色权限和ACL权限)';
|
||||
|
||||
-- 8.2 智能体实时状态视图
|
||||
CREATE OR REPLACE VIEW agent.v_agent_realtime_status AS
|
||||
SELECT
|
||||
a.agent_id,
|
||||
a.agent_name,
|
||||
a.agent_type,
|
||||
a.status,
|
||||
COUNT(DISTINCT s.session_id) FILTER (WHERE s.session_status = 'active') AS active_sessions,
|
||||
COUNT(DISTINCT s.user_id) FILTER (WHERE s.start_time > now() - interval '24 hours') AS daily_users,
|
||||
COALESCE(SUM(s.message_count) FILTER (WHERE s.start_time > now() - interval '1 hour'), 0) AS hourly_messages,
|
||||
COALESCE(AVG(r.rating) FILTER (WHERE r.create_time > now() - interval '7 days'), 0) AS weekly_avg_rating
|
||||
FROM agent.tb_agent a
|
||||
LEFT JOIN agent.tb_agent_session s ON a.agent_id = s.agent_id AND s.deleted = false
|
||||
LEFT JOIN agent.tb_agent_rating r ON a.agent_id = r.agent_id AND r.deleted = false
|
||||
WHERE a.deleted = false
|
||||
GROUP BY a.agent_id, a.agent_name, a.agent_type, a.status;
|
||||
|
||||
COMMENT ON VIEW agent.v_agent_realtime_status IS '智能体实时状态视图';
|
||||
|
||||
-- 8.3 工单处理效率视图
|
||||
CREATE OR REPLACE VIEW customer_service.v_ticket_efficiency AS
|
||||
SELECT
|
||||
DATE(t.create_time) AS stat_date,
|
||||
t.ticket_type,
|
||||
t.priority,
|
||||
COUNT(*) AS total_tickets,
|
||||
COUNT(*) FILTER (WHERE t.ticket_status = 'resolved') AS resolved_tickets,
|
||||
COUNT(*) FILTER (WHERE t.is_overdue) AS overdue_tickets,
|
||||
AVG(EXTRACT(EPOCH FROM (t.response_time - t.create_time))/60) AS avg_response_minutes,
|
||||
AVG(EXTRACT(EPOCH FROM (t.resolution_time - t.create_time))/3600) FILTER (WHERE t.resolution_time IS NOT NULL) AS avg_resolution_hours,
|
||||
AVG(t.customer_rating) FILTER (WHERE t.customer_rating IS NOT NULL) AS avg_rating
|
||||
FROM customer_service.tb_ticket t
|
||||
WHERE t.deleted = false
|
||||
AND t.create_time > now() - interval '90 days'
|
||||
GROUP BY DATE(t.create_time), t.ticket_type, t.priority;
|
||||
|
||||
COMMENT ON VIEW customer_service.v_ticket_efficiency IS '工单处理效率统计视图';
|
||||
|
||||
-- =============================
|
||||
-- 9. 审计触发器增强
|
||||
-- =============================
|
||||
|
||||
-- 9.1 创建审计日志函数
|
||||
CREATE OR REPLACE FUNCTION public.audit_trigger_func()
|
||||
RETURNS TRIGGER AS $$
|
||||
DECLARE
|
||||
audit_data JSONB;
|
||||
BEGIN
|
||||
IF (TG_OP = 'DELETE') THEN
|
||||
audit_data := jsonb_build_object(
|
||||
'operation', 'DELETE',
|
||||
'table', TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME,
|
||||
'old_data', row_to_json(OLD)
|
||||
);
|
||||
|
||||
INSERT INTO log.tb_sys_log (
|
||||
optsn, log_id, type, level, module, message, data, creator
|
||||
) VALUES (
|
||||
'AUDIT_' || gen_random_uuid()::text,
|
||||
gen_random_uuid()::text,
|
||||
'audit',
|
||||
'info',
|
||||
TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME,
|
||||
'Record deleted',
|
||||
audit_data,
|
||||
COALESCE(current_setting('app.current_user_id', true), 'system')
|
||||
);
|
||||
RETURN OLD;
|
||||
|
||||
ELSIF (TG_OP = 'UPDATE') THEN
|
||||
audit_data := jsonb_build_object(
|
||||
'operation', 'UPDATE',
|
||||
'table', TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME,
|
||||
'old_data', row_to_json(OLD),
|
||||
'new_data', row_to_json(NEW)
|
||||
);
|
||||
|
||||
INSERT INTO log.tb_sys_log (
|
||||
optsn, log_id, type, level, module, message, data, creator
|
||||
) VALUES (
|
||||
'AUDIT_' || gen_random_uuid()::text,
|
||||
gen_random_uuid()::text,
|
||||
'audit',
|
||||
'info',
|
||||
TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME,
|
||||
'Record updated',
|
||||
audit_data,
|
||||
COALESCE(current_setting('app.current_user_id', true), 'system')
|
||||
);
|
||||
RETURN NEW;
|
||||
|
||||
ELSIF (TG_OP = 'INSERT') THEN
|
||||
audit_data := jsonb_build_object(
|
||||
'operation', 'INSERT',
|
||||
'table', TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME,
|
||||
'new_data', row_to_json(NEW)
|
||||
);
|
||||
|
||||
INSERT INTO log.tb_sys_log (
|
||||
optsn, log_id, type, level, module, message, data, creator
|
||||
) VALUES (
|
||||
'AUDIT_' || gen_random_uuid()::text,
|
||||
gen_random_uuid()::text,
|
||||
'audit',
|
||||
'info',
|
||||
TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME,
|
||||
'Record created',
|
||||
audit_data,
|
||||
COALESCE(current_setting('app.current_user_id', true), 'system')
|
||||
);
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
COMMENT ON FUNCTION public.audit_trigger_func() IS '审计日志触发器函数';
|
||||
|
||||
-- =============================
|
||||
-- 10. 数据归档函数
|
||||
-- =============================
|
||||
|
||||
-- 10.1 创建日志归档函数
|
||||
CREATE OR REPLACE FUNCTION public.archive_old_logs(
|
||||
p_months_to_keep INTEGER DEFAULT 6
|
||||
)
|
||||
RETURNS TABLE(
|
||||
archived_count INTEGER,
|
||||
deleted_count INTEGER
|
||||
) AS $$
|
||||
DECLARE
|
||||
v_cutoff_date TIMESTAMPTZ;
|
||||
v_archived INTEGER := 0;
|
||||
v_deleted INTEGER := 0;
|
||||
BEGIN
|
||||
v_cutoff_date := now() - (p_months_to_keep || ' months')::INTERVAL;
|
||||
|
||||
-- 归档系统日志
|
||||
CREATE TABLE IF NOT EXISTS log.tb_sys_log_archived (LIKE log.tb_sys_log INCLUDING ALL);
|
||||
|
||||
WITH moved_rows AS (
|
||||
INSERT INTO log.tb_sys_log_archived
|
||||
SELECT * FROM log.tb_sys_log
|
||||
WHERE create_time < v_cutoff_date
|
||||
RETURNING *
|
||||
)
|
||||
SELECT COUNT(*) INTO v_archived FROM moved_rows;
|
||||
|
||||
DELETE FROM log.tb_sys_log
|
||||
WHERE create_time < v_cutoff_date;
|
||||
|
||||
GET DIAGNOSTICS v_deleted = ROW_COUNT;
|
||||
|
||||
RETURN QUERY SELECT v_archived, v_deleted;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
COMMENT ON FUNCTION public.archive_old_logs IS '归档旧日志数据';
|
||||
|
||||
-- 10.2 创建API调用日志归档函数
|
||||
CREATE OR REPLACE FUNCTION agent.archive_api_logs(
|
||||
p_months_to_keep INTEGER DEFAULT 3
|
||||
)
|
||||
RETURNS INTEGER AS $$
|
||||
DECLARE
|
||||
v_cutoff_date TIMESTAMPTZ;
|
||||
v_archived INTEGER;
|
||||
BEGIN
|
||||
v_cutoff_date := now() - (p_months_to_keep || ' months')::INTERVAL;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS agent.tb_api_call_log_archived (LIKE agent.tb_api_call_log INCLUDING ALL);
|
||||
|
||||
WITH moved_rows AS (
|
||||
INSERT INTO agent.tb_api_call_log_archived
|
||||
SELECT * FROM agent.tb_api_call_log
|
||||
WHERE create_time < v_cutoff_date
|
||||
RETURNING *
|
||||
)
|
||||
SELECT COUNT(*) INTO v_archived FROM moved_rows;
|
||||
|
||||
DELETE FROM agent.tb_api_call_log
|
||||
WHERE create_time < v_cutoff_date;
|
||||
|
||||
RETURN v_archived;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
COMMENT ON FUNCTION agent.archive_api_logs IS '归档旧API调用日志';
|
||||
|
||||
-- =============================
|
||||
-- 11. 性能监控函数
|
||||
-- =============================
|
||||
|
||||
-- 11.1 表膨胀检查函数
|
||||
CREATE OR REPLACE FUNCTION public.check_table_bloat()
|
||||
RETURNS TABLE(
|
||||
schemaname TEXT,
|
||||
tablename TEXT,
|
||||
table_size_mb NUMERIC,
|
||||
bloat_size_mb NUMERIC,
|
||||
bloat_ratio NUMERIC
|
||||
) AS $$
|
||||
BEGIN
|
||||
RETURN QUERY
|
||||
SELECT
|
||||
s.schemaname::TEXT,
|
||||
s.tablename::TEXT,
|
||||
ROUND(pg_total_relation_size(s.schemaname || '.' || s.tablename)::NUMERIC / 1024 / 1024, 2) AS table_size_mb,
|
||||
ROUND((pg_total_relation_size(s.schemaname || '.' || s.tablename) - pg_relation_size(s.schemaname || '.' || s.tablename))::NUMERIC / 1024 / 1024, 2) AS bloat_size_mb,
|
||||
ROUND(((pg_total_relation_size(s.schemaname || '.' || s.tablename) - pg_relation_size(s.schemaname || '.' || s.tablename))::NUMERIC / NULLIF(pg_total_relation_size(s.schemaname || '.' || s.tablename), 0) * 100), 2) AS bloat_ratio
|
||||
FROM pg_tables s
|
||||
WHERE s.schemaname IN ('sys', 'file', 'message', 'log', 'config', 'knowledge', 'bidding', 'customer_service', 'agent')
|
||||
ORDER BY pg_total_relation_size(s.schemaname || '.' || s.tablename) DESC;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
COMMENT ON FUNCTION public.check_table_bloat IS '检查表膨胀情况';
|
||||
|
||||
-- =============================
|
||||
-- 执行完成提示
|
||||
-- =============================
|
||||
DO $$
|
||||
BEGIN
|
||||
RAISE NOTICE '==============================';
|
||||
RAISE NOTICE '数据库优化补丁执行完成!';
|
||||
RAISE NOTICE '==============================';
|
||||
RAISE NOTICE '已完成以下优化:';
|
||||
RAISE NOTICE '1. 用户模块:移除敏感字段、添加部门关联';
|
||||
RAISE NOTICE '2. 权限模块:添加排序和类型字段';
|
||||
RAISE NOTICE '3. 文件模块:版本管理、分类标签、关联表';
|
||||
RAISE NOTICE '4. 消息模块:消息模板表';
|
||||
RAISE NOTICE '5. 日志模块:链路追踪支持';
|
||||
RAISE NOTICE '6. 全文搜索:添加GIN索引';
|
||||
RAISE NOTICE '7. JSONB优化:添加GIN索引';
|
||||
RAISE NOTICE '8. 性能视图:用户权限、智能体状态、工单效率';
|
||||
RAISE NOTICE '9. 审计增强:完整审计触发器';
|
||||
RAISE NOTICE '10. 数据归档:日志和API调用归档函数';
|
||||
RAISE NOTICE '11. 监控工具:表膨胀检查函数';
|
||||
RAISE NOTICE '==============================';
|
||||
END $$;
|
||||
137
urbanLifelineServ/.bin/database/redis/redis.yaml
Normal file
137
urbanLifelineServ/.bin/database/redis/redis.yaml
Normal file
@@ -0,0 +1,137 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: redis-config
|
||||
namespace: urban-lifeline
|
||||
data:
|
||||
redis.conf: |
|
||||
bind 0.0.0.0
|
||||
protected-mode no
|
||||
port 6379
|
||||
tcp-backlog 511
|
||||
timeout 0
|
||||
tcp-keepalive 300
|
||||
daemonize no
|
||||
supervised no
|
||||
pidfile /var/run/redis_6379.pid
|
||||
loglevel notice
|
||||
logfile ""
|
||||
databases 16
|
||||
always-show-logo yes
|
||||
save 900 1
|
||||
save 300 10
|
||||
save 60 10000
|
||||
stop-writes-on-bgsave-error yes
|
||||
rdbcompression yes
|
||||
rdbchecksum yes
|
||||
dbfilename dump.rdb
|
||||
dir /data
|
||||
maxmemory 512mb
|
||||
maxmemory-policy allkeys-lru
|
||||
appendonly yes
|
||||
appendfilename "appendonly.aof"
|
||||
appendfsync everysec
|
||||
no-appendfsync-on-rewrite no
|
||||
auto-aof-rewrite-percentage 100
|
||||
auto-aof-rewrite-min-size 64mb
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: redis
|
||||
namespace: urban-lifeline
|
||||
labels:
|
||||
app: redis
|
||||
spec:
|
||||
selector:
|
||||
app: redis
|
||||
ports:
|
||||
- name: redis
|
||||
port: 6379
|
||||
targetPort: 6379
|
||||
type: ClusterIP
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: redis-nodeport
|
||||
namespace: urban-lifeline
|
||||
labels:
|
||||
app: redis
|
||||
spec:
|
||||
selector:
|
||||
app: redis
|
||||
type: NodePort
|
||||
ports:
|
||||
- name: redis
|
||||
port: 6379
|
||||
targetPort: 6379
|
||||
nodePort: 30379
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: redis
|
||||
namespace: urban-lifeline
|
||||
labels:
|
||||
app: redis
|
||||
spec:
|
||||
serviceName: redis
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: redis
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: redis
|
||||
spec:
|
||||
containers:
|
||||
- name: redis
|
||||
image: redis:7-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- redis-server
|
||||
- /usr/local/etc/redis/redis.conf
|
||||
ports:
|
||||
- containerPort: 6379
|
||||
name: redis
|
||||
env:
|
||||
- name: TZ
|
||||
value: "Asia/Shanghai"
|
||||
volumeMounts:
|
||||
- name: redis-data
|
||||
mountPath: /data
|
||||
- name: redis-config
|
||||
mountPath: /usr/local/etc/redis
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- redis-cli
|
||||
- ping
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 5
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- redis-cli
|
||||
- ping
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
resources:
|
||||
requests:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
volumes:
|
||||
- name: redis-data
|
||||
hostPath:
|
||||
path: /data/k8s/redis/data
|
||||
type: DirectoryOrCreate
|
||||
- name: redis-config
|
||||
configMap:
|
||||
name: redis-config
|
||||
62
urbanLifelineServ/.bin/docker/docker-compose.yml
Normal file
62
urbanLifelineServ/.bin/docker/docker-compose.yml
Normal file
@@ -0,0 +1,62 @@
|
||||
version: '3.8'
|
||||
|
||||
# urban-lifeline 开发环境 Docker Compose 配置
|
||||
# 使用主机的 MySQL 数据库
|
||||
|
||||
networks:
|
||||
urban-lifeline:
|
||||
driver: bridge
|
||||
name: urban-lifeline
|
||||
|
||||
services:
|
||||
nacos:
|
||||
image: nacos/nacos-server:v3.1.0
|
||||
container_name: urban-lifeline-nacos
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- urban-lifeline
|
||||
ports:
|
||||
- "8081:8080" # Nacos Console (Web UI) - 映射到主机 8081
|
||||
- "8848:8848" # Nacos HTTP API
|
||||
- "9848:9848" # Nacos gRPC 客户端请求
|
||||
- "9849:9849" # Nacos gRPC 服务间同步
|
||||
environment:
|
||||
# 运行模式
|
||||
MODE: standalone
|
||||
|
||||
# 数据库配置 - 使用主机 MySQL
|
||||
SPRING_DATASOURCE_PLATFORM: mysql
|
||||
MYSQL_SERVICE_HOST: host.docker.internal # Docker Desktop
|
||||
# MYSQL_SERVICE_HOST: 172.17.0.1 # Linux 使用此行,注释上一行
|
||||
MYSQL_SERVICE_PORT: 3306
|
||||
MYSQL_SERVICE_DB_NAME: nacos_config
|
||||
MYSQL_SERVICE_USER: root
|
||||
MYSQL_SERVICE_PASSWORD: "123456"
|
||||
MYSQL_SERVICE_DB_PARAM: allowPublicKeyRetrieval=true&useSSL=false
|
||||
|
||||
# JVM 配置
|
||||
JVM_XMS: 512m
|
||||
JVM_XMX: 512m
|
||||
JVM_XMN: 256m
|
||||
|
||||
# 认证配置(开发环境关闭)
|
||||
NACOS_AUTH_ENABLE: "false"
|
||||
NACOS_AUTH_TOKEN: ZlRkR2ZxR3BvZ1F0a3JxY2V6RUx2cUh1Rkx6V1ZQbE9kUVd1R1VOcWFFS2t3dG5hS0E9PQ==
|
||||
NACOS_AUTH_IDENTITY_KEY: ZlRkR2ZxR3BvZ1F0a3JxY2V6RUx2cUh1Rkx6V1ZQbE9kUVd1R1VOcWFFS2t3dG5hS0E9PQ==
|
||||
NACOS_AUTH_IDENTITY_VALUE: ZlRkR2ZxR3BvZ1F0a3JxY2V6RUx2cUh1Rkx6V1ZQbE9kUVd1R1VOcWFFS2t3dG5hS0E9PQ==
|
||||
|
||||
volumes:
|
||||
# 数据持久化到主机目录
|
||||
- ../../.data/docker/nacos/data:/home/nacos/data
|
||||
- ../../.data/docker/nacos/logs:/home/nacos/logs
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8848/nacos/"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
start_period: 60s
|
||||
|
||||
# Linux 需要添加 extra_hosts 来访问主机服务
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
3
urbanLifelineServ/.bin/docker/readme.md
Normal file
3
urbanLifelineServ/.bin/docker/readme.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# 注意点
|
||||
1. mysql 开发 bind-address 必须是 0.0.0.0 否则无法连接
|
||||
2. root % 密码必须是 123456
|
||||
210
urbanLifelineServ/.bin/docker/start.sh
Normal file
210
urbanLifelineServ/.bin/docker/start.sh
Normal file
@@ -0,0 +1,210 @@
|
||||
#!/bin/bash
|
||||
|
||||
# urban-lifeline Docker Compose 启动脚本
|
||||
|
||||
set -e
|
||||
|
||||
# If the user invoked this script with `sh start.sh` (which may be dash),
|
||||
# some Bash-specific features (like ${BASH_SOURCE[0]} and [[ .. ]]) will
|
||||
# fail with "Bad substitution". If we're not running under Bash, try to
|
||||
# re-exec the script using `bash` if available.
|
||||
if [ -z "$BASH_VERSION" ]; then
|
||||
if command -v bash >/dev/null 2>&1; then
|
||||
echo "脚本需要 Bash,正在重新以 Bash 执行..."
|
||||
exec bash "$0" "$@"
|
||||
else
|
||||
echo "错误: 需要 Bash 运行此脚本,但系统未安装 Bash。"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
DATA_DIR="$PROJECT_ROOT/.data/docker"
|
||||
|
||||
echo "=========================================="
|
||||
echo "urban-lifeline Docker 开发环境启动"
|
||||
echo "=========================================="
|
||||
echo "项目目录: $PROJECT_ROOT"
|
||||
echo "数据目录: $DATA_DIR"
|
||||
echo ""
|
||||
|
||||
# 1. 检查 Docker
|
||||
echo "1. 检查 Docker..."
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo "❌ 错误: 未找到 Docker"
|
||||
echo "请先安装 Docker: https://docs.docker.com/get-docker/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker info &> /dev/null; then
|
||||
echo "❌ 错误: Docker 未运行"
|
||||
echo "请启动 Docker 服务"
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ Docker 检查完成"
|
||||
echo ""
|
||||
|
||||
# 2. 检查 Docker Compose
|
||||
echo "2. 检查 Docker Compose..."
|
||||
if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
|
||||
echo "❌ 错误: 未找到 Docker Compose"
|
||||
echo "请先安装 Docker Compose: https://docs.docker.com/compose/install/"
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ Docker Compose 检查完成"
|
||||
echo ""
|
||||
|
||||
# 3. 检查主机 MySQL
|
||||
echo "3. 检查主机 MySQL..."
|
||||
if command -v mysql &> /dev/null; then
|
||||
echo "请输入 MySQL 连接信息 (按 Enter 使用默认值):"
|
||||
read -p " 主机 [127.0.0.1]: " MYSQL_HOST
|
||||
MYSQL_HOST=${MYSQL_HOST:-127.0.0.1}
|
||||
|
||||
read -p " 端口 [3306]: " MYSQL_PORT
|
||||
MYSQL_PORT=${MYSQL_PORT:-3306}
|
||||
|
||||
read -p " 用户名 [root]: " MYSQL_USER
|
||||
MYSQL_USER=${MYSQL_USER:-root}
|
||||
|
||||
read -s -p " 密码 [123456]: " MYSQL_PASSWORD
|
||||
echo
|
||||
MYSQL_PASSWORD=${MYSQL_PASSWORD:-123456}
|
||||
|
||||
read -p " 数据库名 [nacos_config]: " MYSQL_DB
|
||||
MYSQL_DB=${MYSQL_DB:-nacos_config}
|
||||
|
||||
echo ""
|
||||
echo "测试 MySQL 连接..."
|
||||
if mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" -e "USE $MYSQL_DB;" 2>/dev/null; then
|
||||
echo "✓ MySQL 连接成功"
|
||||
else
|
||||
echo "⚠️ 警告: MySQL 连接失败"
|
||||
echo ""
|
||||
echo "请确保:"
|
||||
echo " 1. MySQL 服务正在运行"
|
||||
echo " 2. 数据库 '$MYSQL_DB' 已创建"
|
||||
echo " 3. 用户 '$MYSQL_USER' 有权限访问该数据库"
|
||||
echo ""
|
||||
read -p "是否继续启动? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "⚠️ 警告: 未找到 mysql 客户端,无法验证数据库连接"
|
||||
echo "将使用默认配置: root:123456@localhost:3306/nacos_config"
|
||||
MYSQL_USER=root
|
||||
MYSQL_PASSWORD=123456
|
||||
MYSQL_DB=nacos_config
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 4. 创建数据目录
|
||||
echo "4. 创建数据目录..."
|
||||
mkdir -p "$DATA_DIR"/nacos/{data,logs}
|
||||
echo "✓ 数据目录创建完成"
|
||||
echo ""
|
||||
|
||||
# 5. 更新 docker-compose.yml 配置
|
||||
if [ -n "$MYSQL_USER" ] && [ "$MYSQL_USER" != "root" ]; then
|
||||
echo "5. 更新 Docker Compose 配置..."
|
||||
|
||||
# 创建临时 .env 文件
|
||||
cat > "$SCRIPT_DIR/.env" <<EOF
|
||||
MYSQL_SERVICE_USER=$MYSQL_USER
|
||||
MYSQL_SERVICE_PASSWORD=$MYSQL_PASSWORD
|
||||
MYSQL_SERVICE_DB_NAME=$MYSQL_DB
|
||||
EOF
|
||||
|
||||
echo "✓ 配置更新完成"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# 6. 拉取镜像
|
||||
echo "6. 拉取 Nacos 镜像..."
|
||||
cd "$SCRIPT_DIR"
|
||||
if command -v docker-compose &> /dev/null; then
|
||||
docker-compose pull
|
||||
else
|
||||
docker compose pull
|
||||
fi
|
||||
echo "✓ 镜像拉取完成"
|
||||
echo ""
|
||||
|
||||
# 7. 启动服务
|
||||
echo "7. 启动服务..."
|
||||
if command -v docker-compose &> /dev/null; then
|
||||
docker-compose up -d
|
||||
else
|
||||
docker compose up -d
|
||||
fi
|
||||
echo "✓ 服务启动完成"
|
||||
echo ""
|
||||
|
||||
# 8. 等待 Nacos 启动
|
||||
echo "8. 等待 Nacos 启动..."
|
||||
echo " 这可能需要 30-60 秒..."
|
||||
|
||||
MAX_WAIT=60
|
||||
WAITED=0
|
||||
while [ $WAITED -lt $MAX_WAIT ]; do
|
||||
if curl -s http://localhost:8848/nacos/ > /dev/null 2>&1; then
|
||||
echo "✓ Nacos 启动成功"
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
WAITED=$((WAITED + 2))
|
||||
echo -n "."
|
||||
done
|
||||
echo ""
|
||||
|
||||
if [ $WAITED -ge $MAX_WAIT ]; then
|
||||
echo "⚠️ 警告: Nacos 启动超时"
|
||||
echo ""
|
||||
echo "查看日志:"
|
||||
if command -v docker-compose &> /dev/null; then
|
||||
docker-compose logs nacos
|
||||
else
|
||||
docker compose logs nacos
|
||||
fi
|
||||
echo ""
|
||||
echo "请检查 MySQL 连接配置是否正确"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 9. 显示服务信息
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "✅ urban-lifeline 开发环境启动完成!"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "服务访问地址:"
|
||||
echo " - Nacos 控制台: http://localhost:8848/nacos/"
|
||||
echo " - Nacos 默认账号: nacos / nacos"
|
||||
echo ""
|
||||
echo "数据库连接信息:"
|
||||
echo " - 数据库: ${MYSQL_DB:-nacos_config}"
|
||||
echo " - 用户: ${MYSQL_USER:-root}"
|
||||
echo ""
|
||||
echo "数据持久化目录:"
|
||||
echo " - $DATA_DIR/nacos/data"
|
||||
echo " - $DATA_DIR/nacos/logs"
|
||||
echo ""
|
||||
echo "常用命令:"
|
||||
echo " 查看运行状态:"
|
||||
echo " docker ps"
|
||||
echo ""
|
||||
echo " 查看 Nacos 日志:"
|
||||
echo " docker logs -f urban-lifeline-nacos"
|
||||
echo ""
|
||||
echo " 停止服务:"
|
||||
echo " cd $SCRIPT_DIR && docker-compose down"
|
||||
echo ""
|
||||
echo " 重启服务:"
|
||||
echo " cd $SCRIPT_DIR && docker-compose restart"
|
||||
echo ""
|
||||
echo " 完全清理(删除容器和网络):"
|
||||
echo " cd $SCRIPT_DIR && docker-compose down -v"
|
||||
echo ""
|
||||
27
urbanLifelineServ/.bin/docker/stop.sh
Normal file
27
urbanLifelineServ/.bin/docker/stop.sh
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
# urban-lifeline Docker Compose 停止脚本
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
echo "=========================================="
|
||||
echo "停止 urban-lifeline 开发环境"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
if command -v docker-compose &> /dev/null; then
|
||||
docker-compose down
|
||||
else
|
||||
docker compose down
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✅ 服务已停止"
|
||||
echo ""
|
||||
echo "数据已保留在: ../../.data/docker/nacos/"
|
||||
echo ""
|
||||
echo "如需重新启动,请运行: ./start.sh"
|
||||
echo "如需完全清理,请运行: docker-compose down -v"
|
||||
echo ""
|
||||
182
urbanLifelineServ/.bin/sql/nacos/nacos-mysql-schema.sql
Normal file
182
urbanLifelineServ/.bin/sql/nacos/nacos-mysql-schema.sql
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
DROP DATABASE IF EXISTS `nacos_config`;
|
||||
CREATE DATABASE IF NOT EXISTS `nacos_config` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
|
||||
USE `nacos_config`;
|
||||
|
||||
/******************************************/
|
||||
/* 表名称 = config_info */
|
||||
/******************************************/
|
||||
CREATE TABLE `config_info` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
|
||||
`group_id` varchar(128) DEFAULT NULL COMMENT 'group_id',
|
||||
`content` longtext NOT NULL COMMENT 'content',
|
||||
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
|
||||
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
|
||||
`src_user` text COMMENT 'source user',
|
||||
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
|
||||
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
|
||||
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
|
||||
`c_desc` varchar(256) DEFAULT NULL COMMENT 'configuration description',
|
||||
`c_use` varchar(64) DEFAULT NULL COMMENT 'configuration usage',
|
||||
`effect` varchar(64) DEFAULT NULL COMMENT '配置生效的描述',
|
||||
`type` varchar(64) DEFAULT NULL COMMENT '配置的类型',
|
||||
`c_schema` text COMMENT '配置的模式',
|
||||
`encrypted_data_key` varchar(1024) NOT NULL DEFAULT '' COMMENT '密钥',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';
|
||||
|
||||
/******************************************/
|
||||
/* 表名称 = config_info since 2.5.0 */
|
||||
/******************************************/
|
||||
CREATE TABLE `config_info_gray` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
|
||||
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
|
||||
`content` longtext NOT NULL COMMENT 'content',
|
||||
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
|
||||
`src_user` text COMMENT 'src_user',
|
||||
`src_ip` varchar(100) DEFAULT NULL COMMENT 'src_ip',
|
||||
`gmt_create` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'gmt_create',
|
||||
`gmt_modified` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'gmt_modified',
|
||||
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
|
||||
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
|
||||
`gray_name` varchar(128) NOT NULL COMMENT 'gray_name',
|
||||
`gray_rule` text NOT NULL COMMENT 'gray_rule',
|
||||
`encrypted_data_key` varchar(256) NOT NULL DEFAULT '' COMMENT 'encrypted_data_key',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_configinfogray_datagrouptenantgray` (`data_id`,`group_id`,`tenant_id`,`gray_name`),
|
||||
KEY `idx_dataid_gmt_modified` (`data_id`,`gmt_modified`),
|
||||
KEY `idx_gmt_modified` (`gmt_modified`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='config_info_gray';
|
||||
|
||||
/******************************************/
|
||||
/* 表名称 = config_tags_relation */
|
||||
/******************************************/
|
||||
CREATE TABLE `config_tags_relation` (
|
||||
`id` bigint(20) NOT NULL COMMENT 'id',
|
||||
`tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
|
||||
`tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
|
||||
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
|
||||
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
|
||||
`tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
|
||||
`nid` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'nid, 自增长标识',
|
||||
PRIMARY KEY (`nid`),
|
||||
UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
|
||||
KEY `idx_tenant_id` (`tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';
|
||||
|
||||
/******************************************/
|
||||
/* 表名称 = group_capacity */
|
||||
/******************************************/
|
||||
CREATE TABLE `group_capacity` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
|
||||
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
|
||||
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
|
||||
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
|
||||
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
|
||||
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
|
||||
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
|
||||
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_group_id` (`group_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';
|
||||
|
||||
/******************************************/
|
||||
/* 表名称 = his_config_info */
|
||||
/******************************************/
|
||||
CREATE TABLE `his_config_info` (
|
||||
`id` bigint(20) unsigned NOT NULL COMMENT 'id',
|
||||
`nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'nid, 自增标识',
|
||||
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
|
||||
`group_id` varchar(128) NOT NULL COMMENT 'group_id',
|
||||
`app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
|
||||
`content` longtext NOT NULL COMMENT 'content',
|
||||
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
|
||||
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
|
||||
`src_user` text COMMENT 'source user',
|
||||
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
|
||||
`op_type` char(10) DEFAULT NULL COMMENT 'operation type',
|
||||
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
|
||||
`encrypted_data_key` varchar(1024) NOT NULL DEFAULT '' COMMENT '密钥',
|
||||
`publish_type` varchar(50) DEFAULT 'formal' COMMENT 'publish type gray or formal',
|
||||
`gray_name` varchar(50) DEFAULT NULL COMMENT 'gray name',
|
||||
`ext_info` longtext DEFAULT NULL COMMENT 'ext info',
|
||||
PRIMARY KEY (`nid`),
|
||||
KEY `idx_gmt_create` (`gmt_create`),
|
||||
KEY `idx_gmt_modified` (`gmt_modified`),
|
||||
KEY `idx_did` (`data_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';
|
||||
|
||||
|
||||
/******************************************/
|
||||
/* 表名称 = tenant_capacity */
|
||||
/******************************************/
|
||||
CREATE TABLE `tenant_capacity` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
|
||||
`quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
|
||||
`usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
|
||||
`max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
|
||||
`max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
|
||||
`max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
|
||||
`max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
|
||||
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_tenant_id` (`tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';
|
||||
|
||||
|
||||
CREATE TABLE `tenant_info` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`kp` varchar(128) NOT NULL COMMENT 'kp',
|
||||
`tenant_id` varchar(128) default '' COMMENT 'tenant_id',
|
||||
`tenant_name` varchar(128) default '' COMMENT 'tenant_name',
|
||||
`tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
|
||||
`create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
|
||||
`gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
|
||||
`gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
|
||||
KEY `idx_tenant_id` (`tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
|
||||
|
||||
CREATE TABLE `users` (
|
||||
`username` varchar(50) NOT NULL PRIMARY KEY COMMENT 'username',
|
||||
`password` varchar(500) NOT NULL COMMENT 'password',
|
||||
`enabled` boolean NOT NULL COMMENT 'enabled'
|
||||
);
|
||||
|
||||
CREATE TABLE `roles` (
|
||||
`username` varchar(50) NOT NULL COMMENT 'username',
|
||||
`role` varchar(50) NOT NULL COMMENT 'role',
|
||||
UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
|
||||
);
|
||||
|
||||
CREATE TABLE `permissions` (
|
||||
`role` varchar(50) NOT NULL COMMENT 'role',
|
||||
`resource` varchar(128) NOT NULL COMMENT 'resource',
|
||||
`action` varchar(8) NOT NULL COMMENT 'action',
|
||||
UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user