From 43bd11db0b2c3a0dfa297ef8b1fdd3a07ce11b86 Mon Sep 17 00:00:00 2001 From: qianqiuwanzi Date: Thu, 17 Sep 2026 15:30:19 +0800 Subject: [PATCH] =?UTF-8?q?v1.0.51:=20=E9=83=A8=E7=BD=B2=E9=85=8D=E5=A5=97?= =?UTF-8?q?=20-=20=E2=91=A0config/database.php=20=E6=94=AF=E6=8C=81=20env?= =?UTF-8?q?=20=E6=B3=A8=E5=85=A5(DB=5FHOST/PORT/NAME/USER/PASS/CHARSET,?= =?UTF-8?q?=E7=BC=BA=E7=9C=81=E5=9B=9E=E8=90=BD=E6=9C=AC=E5=9C=B0=E5=BC=80?= =?UTF-8?q?=E5=8F=91);=E2=91=A1=E6=96=B0=E5=A2=9Esql/schema=5Fv1.0.51=5Fba?= =?UTF-8?q?se.sql=E5=85=A8=E9=87=8F=E4=B8=9A=E5=8A=A1=E5=BA=93=E5=9F=BA?= =?UTF-8?q?=E5=87=86schema(=E4=BB=93=E5=BA=93=E5=8E=9F=E4=BB=85=E5=A2=9E?= =?UTF-8?q?=E9=87=8F=E8=BF=81=E7=A7=BB,27=E8=A1=A8=E6=8C=89=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=8F=8D=E6=8E=A8=E9=87=8D=E5=BB=BA,=E5=90=ABsource?= =?UTF-8?q?=5Fchannels=E7=A7=8D=E5=AD=90);=E2=91=A2=E6=96=B0=E5=A2=9Edeplo?= =?UTF-8?q?y/=E5=AE=B9=E5=99=A8=E5=8C=96=E7=BC=96=E6=8E=92(php8.2-fpm+ngin?= =?UTF-8?q?x+mysql8.0,web=E6=9A=B4=E9=9C=B2=E5=AE=BF=E4=B8=BB8081,DB?= =?UTF-8?q?=E4=BB=85=E5=86=85=E7=BD=91,=E5=AF=B9=E9=BD=90license=5Fserver?= =?UTF-8?q?=E6=97=A2=E6=9C=89compose=E9=A3=8E=E6=A0=BC):Dockerfile/nginx/d?= =?UTF-8?q?efault.conf/mysql=E5=88=9D=E5=A7=8B=E5=8C=96(01=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E5=9F=BA=E5=87=86+=E5=AD=97=E5=85=B8/02=E7=A7=8D?= =?UTF-8?q?=E5=AD=90=E8=B6=85=E7=AE=A1=E8=A7=92=E8=89=B2=E4=B8=8Eadmin?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E5=8F=8A12=E4=B8=AA=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E6=A0=87=E8=AE=B0)/.env.example;=E2=91=A3.gi?= =?UTF-8?q?tignore=E9=98=B2=E6=8A=A4.env=E4=B8=8E=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E4=BA=A7=E7=89=A9.=20=E5=B7=B2=E5=9C=A8=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=99=A8106.55.169.92=E7=94=A8=E4=B8=80=E6=AC=A1=E6=80=A7mysql?= =?UTF-8?q?:8.0=E5=AE=B9=E5=99=A8=E9=AA=8C=E8=AF=81:27=E8=A1=A8+=E5=AD=97?= =?UTF-8?q?=E5=85=B8(3632=E5=8C=BA=E5=9F=9F/12=E6=9D=A5=E6=BA=90=E6=B8=A0?= =?UTF-8?q?=E9=81=93)+admin/=E8=B6=85=E7=AE=A1+cert=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E6=A0=87=E8=AE=B0=E5=85=A8=E9=83=A8=E5=AF=BC=E5=85=A5=E6=88=90?= =?UTF-8?q?=E5=8A=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Code --- .gitignore | 13 + config/database.php | 30 +- deploy/.env.example | 8 + deploy/docker-compose.yml | 65 ++++ deploy/mysql/initdb/01_schema_base.sh | 11 + deploy/mysql/initdb/02_seed_admin.sql | 40 ++ deploy/nginx/default.conf | 53 +++ deploy/php/Dockerfile | 11 + sql/schema_v1.0.51_base.sql | 522 ++++++++++++++++++++++++++ 9 files changed, 744 insertions(+), 9 deletions(-) create mode 100644 .gitignore create mode 100644 deploy/.env.example create mode 100644 deploy/docker-compose.yml create mode 100644 deploy/mysql/initdb/01_schema_base.sh create mode 100644 deploy/mysql/initdb/02_seed_admin.sql create mode 100644 deploy/nginx/default.conf create mode 100644 deploy/php/Dockerfile create mode 100644 sql/schema_v1.0.51_base.sql diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d9108f4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# 本地环境变量/口令(部署时 cp .env.example .env 填写,切勿提交) +deploy/.env + +# 运行期产物 +runtime/logs/* +runtime/session/* +!runtime/logs/.gitkeep +!runtime/session/.gitkeep +static/uploads/* + +# 系统/编辑器 +Thumbs.db +.DS_Store \ No newline at end of file diff --git a/config/database.php b/config/database.php index ad08743..9738235 100644 --- a/config/database.php +++ b/config/database.php @@ -1,13 +1,25 @@ '127.0.0.1', - 'port' => 3306, - 'dbname' => 'mysuperlink', - 'username' => 'mysuperlink_root', - 'password' => '123456', - 'charset' => 'utf8mb4', -]; + 'host' => $env('DB_HOST', '127.0.0.1'), + 'port' => (int)$env('DB_PORT', 3306), + 'dbname' => $env('DB_NAME', 'mysuperlink'), + 'username' => $env('DB_USER', 'mysuperlink_root'), + 'password' => $env('DB_PASS', '123456'), + 'charset' => $env('DB_CHARSET', 'utf8mb4'), +]; \ No newline at end of file diff --git a/deploy/.env.example b/deploy/.env.example new file mode 100644 index 0000000..ba9724f --- /dev/null +++ b/deploy/.env.example @@ -0,0 +1,8 @@ +# SuperLink 部署环境变量(复制为 .env 并填写后再 docker compose up) +# 注意:.env 含口令,不要提交到 git(已加入 .gitignore) + +# 数据库 +DB_NAME=mysuperlink +DB_USER=mysuperlink_root +DB_PASS=ChangeMe_DB_Pass_2026 +DB_ROOT_PASS=ChangeMe_Root_Pass_2026 \ No newline at end of file diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml new file mode 100644 index 0000000..0763b44 --- /dev/null +++ b/deploy/docker-compose.yml @@ -0,0 +1,65 @@ +# SuperLink 部署编排(对齐服务器 license_server 既有 compose 风格) +# 服务:db(MySQL8) / app(PHP-FPM) / web(nginx) +# 使用:cp .env.example .env 并填好口令;docker compose up -d --build +# 访问:http://<服务器IP>:8081/ +name: mysuperlink + +services: + db: + image: mysql:8.0 + restart: unless-stopped + env_file: .env + environment: + MYSQL_DATABASE: ${DB_NAME} + MYSQL_USER: ${DB_USER} + MYSQL_PASSWORD: ${DB_PASS} + MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS} + command: + - --character-set-server=utf8mb4 + - --collation-server=utf8mb4_unicode_ci + - --default-authentication-plugin=mysql_native_password + volumes: + - db_data:/var/lib/mysql + - ./mysql/initdb/01_schema_base.sh:/docker-entrypoint-initdb.d/01_schema_base.sh:ro + - .:/repo # 挂载部署目录,init 脚本 source 仓库 sql + - ../../sql:/repo/sql:ro # 仓库 sql 目录(基准 + 字典 + 迁移) + - ../../config:/repo/config:ro + healthcheck: + test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -u$$MYSQL_USER -p$$MYSQL_PASSWORD --silent"] + interval: 5s + timeout: 5s + retries: 30 + start_period: 30s + + app: + build: ./php + restart: unless-stopped + env_file: .env + environment: + DB_HOST: db + DB_PORT: "3306" + DB_NAME: ${DB_NAME} + DB_USER: ${DB_USER} + DB_PASS: ${DB_PASS} + DB_CHARSET: utf8mb4 + volumes: + - ../../:/var/www/html + depends_on: + db: + condition: service_healthy + + web: + image: nginx:1.25-alpine + restart: unless-stopped + ports: + - "8081:80" + environment: + - TZ=Asia/Shanghai + volumes: + - ../../:/var/www/html:ro + - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro + depends_on: + - app + +volumes: + db_data: \ No newline at end of file diff --git a/deploy/mysql/initdb/01_schema_base.sh b/deploy/mysql/initdb/01_schema_base.sh new file mode 100644 index 0000000..5efead1 --- /dev/null +++ b/deploy/mysql/initdb/01_schema_base.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# SuperLink 首次初始化(仅空数据卷时由 mysql 镜像 entrypoint 执行): +# 1) 导入基准建库脚本(业务表全量定义) +# 2) 导入数据字典种子(官方 Excel 生成) +# 说明:大文件用 .sh 以 mysql < 方式导入;admin/角色/版本标记放 02_admin.sql。 +set -euo pipefail +echo ">> SuperLink init: import base schema (${MYSQL_DATABASE})" +mysql --user=root --password="${MYSQL_ROOT_PASSWORD}" --default-character-set=utf8mb4 "${MYSQL_DATABASE}" < /repo/sql/schema_v1.0.51_base.sql +echo ">> SuperLink init: import dict_seed.sql" +mysql --user=root --password="${MYSQL_ROOT_PASSWORD}" --default-character-set=utf8mb4 "${MYSQL_DATABASE}" < /repo/sql/dict_seed.sql +echo ">> SuperLink init: schema + dict ok" \ No newline at end of file diff --git a/deploy/mysql/initdb/02_seed_admin.sql b/deploy/mysql/initdb/02_seed_admin.sql new file mode 100644 index 0000000..58ba371 --- /dev/null +++ b/deploy/mysql/initdb/02_seed_admin.sql @@ -0,0 +1,40 @@ +-- ============================================================ +-- SuperLink 首次初始化:种子超管角色 + 管理员账号 + 迁移版本标记 +-- 由 mysql 镜像 entrypoint 在空数据卷时执行;entrypoint 已自动 USE ${MYSQL_DATABASE} +-- 说明: +-- - base schema(v1.0.51_base) 已内建 v1.0.16→v1.0.51 的全部业务表, +-- 故在此把各迁移文件标记为"已应用",避免 tools/migrate.php up 重复执行。 +-- - 管理员账号:admin / Admin@123456(bcrypt 密码,请在首次登录后立即修改) +-- ============================================================ + +-- 1) 超级管理员角色:权限 = 全部业务模块(与前端菜单标识一致) +INSERT INTO `system_roles` (`role_name`, `permissions`, `is_active`) +SELECT '超级管理员', '["dashboard","company","person","media","need","marketing","channel","document","preliminary","system","log"]', 1 +FROM DUAL +WHERE NOT EXISTS (SELECT 1 FROM `system_roles` WHERE `role_name` = '超级管理员'); + +-- 2) 管理员账号(bcrypt,Admin@123456) +INSERT INTO `system_users` (`username`, `password`, `real_name`, `role_id`, `is_active`) +SELECT 'admin', + '$2y$10$1nNvyQx/fVtrPHOkFTUwV.HNbWFkea75Cx3ICil.9BnoJpCrSAeCm', + '管理员', + (SELECT `id` FROM `system_roles` WHERE `role_name` = '超级管理员' LIMIT 1), + 1 +FROM DUAL +WHERE NOT EXISTS (SELECT 1 FROM `system_users` WHERE `username` = 'admin'); + +-- 3) 迁移版本标记(version 去掉 migration_ 前缀,checksum = 迁移文件 md5) +INSERT INTO `schema_versions` (`version`, `checksum`) VALUES +('v1.0.16','73e9594d7ab151791c4ba315e5e87156'), +('v1.0.18','cdfd4eb98e92047c2aa35325908e6f2e'), +('v1.0.20','860b09d92e810620b3bd71d126833611'), +('v1.0.25','c6b545a9dfe0bff7aad8b94849785135'), +('v1.0.27','f1db249ac23697a4981559436306f542'), +('v1.0.30','8faa7dccea9c361d0b8fe4e0c11384f3'), +('v1.0.40','70b9cedf240555bca58f46148c0d380e'), +('v1.0.41','247b6bc7718b9f1d7d5ea28ed9b8a3e2'), +('v1.0.47','10b64a2551e7eb8f1f5bdc8e87c6c06a'), +('v1.0.48','f507f2964d9bf7f8c885d69119c6d041'), +('v1.0.50','edaa2a71a4adf716591ece61ed9fc09f'), +('v1.0.51','3251bf0bca9236e201dc419770f7f5dc') +ON DUPLICATE KEY UPDATE `checksum` = VALUES(`checksum`); \ No newline at end of file diff --git a/deploy/nginx/default.conf b/deploy/nginx/default.conf new file mode 100644 index 0000000..e41c593 --- /dev/null +++ b/deploy/nginx/default.conf @@ -0,0 +1,53 @@ +server { + listen 80; + server_name _; + + root /var/www/html; + index index.html; + + charset utf-8; + sendfile on; + tcp_nopush on; + + client_max_body_size 200m; + server_tokens off; + + # 禁止点开隐藏文件/目录及运行日志 + location ~ /\. { + deny all; + } + + # 静态资源长缓存(uploads/css/js/libs) + location ~* \.(?:css|js|png|jpg|jpeg|gif|svg|ico|woff2?)$ { + expires 7d; + add_header Cache-Control "public, immutable"; + try_files $uri =404; + } + + # 上传目录允许写入(由 php-fpm 侧保证写入者权限) + location /static/uploads { + access_log off; + expires 30d; + try_files $uri =404; + } + + # PHP 交给 php-fpm + location ~ \.php$ { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_pass app:9000; + fastcgi_index index.php; + fastcgi_read_timeout 300; + fastcgi_buffers 16 16k; + fastcgi_buffer_size 32k; + } + + # 其余静态页面 + location / { + try_files $uri $uri/ =404; + } + + error_page 404 =404 /index.html; + gzip on; + gzip_types text/plain text/css application/json application/javascript image/svg+xml; +} \ No newline at end of file diff --git a/deploy/php/Dockerfile b/deploy/php/Dockerfile new file mode 100644 index 0000000..4947d21 --- /dev/null +++ b/deploy/php/Dockerfile @@ -0,0 +1,11 @@ +# SuperLink PHP-FPM 运行镜像 +# 说明:官方 php:8.2-fpm 已内置 pdo_mysql / mbstring / fileinfo 等所需扩展, +# 仅显式安装 pdo_mysql 以备未来镜像变化,并设定可写目录权限。 +FROM php:8.2-fpm + +# 显式启用 PDO MySQL(官方镜像默认已含,这里保证 manifest 一致) +RUN docker-php-ext-install pdo_mysql \ + && mkdir -p /var/www/html/runtime/logs /var/www/html/runtime/session \ + && chown -R www-data:www-data /var/www/html/runtime + +WORKDIR /var/www/html \ No newline at end of file diff --git a/sql/schema_v1.0.51_base.sql b/sql/schema_v1.0.51_base.sql new file mode 100644 index 0000000..6edb86e --- /dev/null +++ b/sql/schema_v1.0.51_base.sql @@ -0,0 +1,522 @@ +-- ============================================================ +-- SuperLink 基准建库脚本(Fresh Install Base Schema) v1.0.51 +-- 用途:全新部署时一次性建立全部业务表(当前形态,含历次迁移结果)。 +-- 由仓库"增量迁移缺失基准 schema"这一现状补建:主业务表定义从 +-- api 代码字段白名单 + INSERT/SELECT 语句反推,字典/属性/计划等表 +-- 直接采用迁移文件中的 CREATE TABLE 原文。 +-- 约定:v1.0.16 后所有业务表时间字段为 DATE;id 一律 INT UNSIGNED AUTO_INCREMENT; +-- 字符集 utf8mb4 / 排序 utf8mb4_unicode_ci。 +-- 执行顺序:本文件 → dict_seed.sql → 系统初始数据(admin)。 +-- ============================================================ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ------------------------------------------------------------ +-- 0) 数据字典(定义见 migration_v1.0.16 / v1.0.18,数据由 dict_seed.sql 注入) +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS `data_dict_country` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `code` VARCHAR(50) NOT NULL COMMENT '国家/地区编码', + `name` VARCHAR(100) NOT NULL COMMENT '国家/地区中文名', + `sort_order` INT NOT NULL DEFAULT 0 COMMENT '排序', + `is_active` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '启用状态', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_code` (`code`), + KEY `idx_name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='国家地区编码字典'; + +CREATE TABLE IF NOT EXISTS `data_dict_area` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `code` VARCHAR(50) NOT NULL COMMENT '行政区划编码', + `name` VARCHAR(100) NOT NULL COMMENT '行政区划名称', + `parent_code` VARCHAR(50) DEFAULT NULL COMMENT '上级行政区划编码', + `sort_order` INT NOT NULL DEFAULT 0 COMMENT '排序', + `is_active` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '启用状态', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_code` (`code`), + KEY `idx_parent` (`parent_code`), + KEY `idx_name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='行政区划编码字典'; + +CREATE TABLE IF NOT EXISTS `data_dict_industry` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `code` VARCHAR(50) NOT NULL COMMENT '行业编码', + `name` VARCHAR(100) NOT NULL COMMENT '行业名称', + `parent_code` VARCHAR(50) DEFAULT NULL COMMENT '上级行业编码', + `sort_order` INT NOT NULL DEFAULT 0 COMMENT '排序', + `is_active` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '启用状态', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_code` (`code`), + KEY `idx_parent` (`parent_code`), + KEY `idx_name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='招标行业分类字典'; + +CREATE TABLE IF NOT EXISTS `data_dict_certificate` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `code` VARCHAR(50) NULL DEFAULT NULL COMMENT '证书类型枚举编码', + `name` VARCHAR(100) NOT NULL COMMENT '证书类型名称', + `sort_order` INT NOT NULL DEFAULT 0 COMMENT '排序', + `is_active` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '启用状态', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_code` (`code`), + KEY `idx_name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='证书类型枚举字典'; + +CREATE TABLE IF NOT EXISTS `data_dict_company_type` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `code` VARCHAR(50) NULL DEFAULT NULL COMMENT '企业类型编码', + `name` VARCHAR(100) NOT NULL COMMENT '企业类型名称', + `sort_order` INT NOT NULL DEFAULT 0 COMMENT '排序', + `is_active` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '启用状态', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_code` (`code`), + KEY `idx_name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='企业类型字典(对应 companies.legal_form)'; + +CREATE TABLE IF NOT EXISTS `source_channels` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `name` VARCHAR(50) NOT NULL COMMENT '渠道名称', + `sort_order` INT NOT NULL DEFAULT 0 COMMENT '排序', + `is_active` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '启用状态', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='来源渠道字典'; + +-- 来源渠道默认数据 +INSERT INTO `source_channels` (`name`, `sort_order`) VALUES +('展会', 1), ('SNS/社交媒体', 2), ('竞价广告', 3), ('搜索引擎自然流量', 4), +('行业媒体/门户', 5), ('转介绍', 6), ('电话销售', 7), ('邮件营销', 8), +('地推', 9), ('代理商/渠道', 10), ('官网咨询', 11), ('其他', 99); + +-- 企业类型字典默认数据 +INSERT INTO `data_dict_company_type` (`code`, `name`, `sort_order`) VALUES +('llc', '有限责任公司', 1), ('joint_stock', '股份有限公司', 2), ('partnership', '合伙企业', 3), +('sole_proprietorship', '个人独资企业', 4), ('state_owned', '国有企业', 5), ('collective', '集体所有制企业', 6), +('foreign_invested', '外商投资企业', 7), ('joint_venture', '中外合资企业', 8), ('other', '其他', 99); + +-- ------------------------------------------------------------ +-- 1) 客户主体:企业 +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS `companies` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `display_name` VARCHAR(191) NOT NULL DEFAULT '' COMMENT '显示名称', + `name_zh` VARCHAR(191) DEFAULT NULL COMMENT '中文名', + `business_role` VARCHAR(50) DEFAULT NULL COMMENT '业务类型', + `country` VARCHAR(100) DEFAULT NULL COMMENT '国家/地区', + `registration_number` VARCHAR(100) DEFAULT NULL COMMENT '统一社会信用代码/注册号', + `address` VARCHAR(255) DEFAULT NULL COMMENT '地址', + `legal_form` VARCHAR(50) DEFAULT NULL COMMENT '企业类型(公司)', + `legal_representative` VARCHAR(100) DEFAULT NULL COMMENT '法定代表人', + `business_scope` TEXT DEFAULT NULL COMMENT '经营范围', + `established_date` DATE DEFAULT NULL COMMENT '成立日期', + `registered_capital` VARCHAR(50) DEFAULT NULL COMMENT '注册资本', + `industry` VARCHAR(100) DEFAULT NULL COMMENT '行业', + `industry_subdivision` VARCHAR(100) DEFAULT NULL COMMENT '行业细分', + `latest_employee_count` INT DEFAULT NULL COMMENT '最新员工数', + `latest_annual_revenue` VARCHAR(50) DEFAULT NULL COMMENT '年营收', + `is_listed` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否上市 0/1', + `stock_code` VARCHAR(30) DEFAULT NULL COMMENT '股票代码', + `website` VARCHAR(255) DEFAULT NULL COMMENT '官网', + `source_channel` VARCHAR(50) DEFAULT NULL COMMENT '来源渠道', + `source_detail` VARCHAR(255) DEFAULT NULL COMMENT '来源详情', + `is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '有效 0/1', + `is_incomplete` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '完整度不达标标记', + `created_at` DATE DEFAULT NULL COMMENT '创建日期', + `updated_at` DATE DEFAULT NULL COMMENT '更新日期', + PRIMARY KEY (`id`), + KEY `idx_is_active` (`is_active`), + KEY `idx_source_channel` (`source_channel`), + KEY `idx_name_zh` (`name_zh`), + KEY `idx_industry` (`industry`), + KEY `idx_created_at` (`created_at`), + KEY `idx_incomplete` (`is_incomplete`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='企业表'; + +-- ------------------------------------------------------------ +-- 2) 客户主体:人员 +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS `persons` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `union_id` VARCHAR(64) DEFAULT NULL COMMENT '外部/统一ID(去重线索)', + `full_name` VARCHAR(100) DEFAULT NULL COMMENT '姓名', + `gender` VARCHAR(20) DEFAULT NULL COMMENT '性别(男/女/未知)', + `nationality` VARCHAR(50) DEFAULT NULL COMMENT '国籍', + `id_type` VARCHAR(30) DEFAULT NULL COMMENT '证件类型', + `id_number` VARCHAR(100) DEFAULT NULL COMMENT '身份证号码', + `education` VARCHAR(30) DEFAULT NULL COMMENT '学历', + `graduated_from` VARCHAR(191) DEFAULT NULL COMMENT '毕业院校', + `hometown` VARCHAR(100) DEFAULT NULL COMMENT '家乡', + `work_location` VARCHAR(100) DEFAULT NULL COMMENT '工作所在地', + `source_channel` VARCHAR(50) DEFAULT NULL COMMENT '来源渠道', + `source_detail` VARCHAR(255) DEFAULT NULL COMMENT '来源详情', + `is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '有效 0/1', + `is_incomplete` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '完整度不达标标记', + `created_at` DATE DEFAULT NULL COMMENT '创建日期', + `updated_at` DATE DEFAULT NULL COMMENT '更新日期', + PRIMARY KEY (`id`), + KEY `idx_is_active` (`is_active`), + KEY `idx_full_name` (`full_name`), + KEY `idx_source_channel` (`source_channel`), + KEY `idx_work_location` (`work_location`), + KEY `idx_incomplete` (`is_incomplete`), + KEY `idx_created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='人员表'; + +-- ------------------------------------------------------------ +-- 3) 社媒/联系方式(多态归属:owner_type='company'|'person',platform 可为 phone/email/社媒名) +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS `social_accounts` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `owner_type` VARCHAR(20) NOT NULL COMMENT '归属类型 company/person', + `owner_id` INT UNSIGNED NOT NULL COMMENT '归属主体ID', + `platform` VARCHAR(30) NOT NULL COMMENT '平台:phone/email/wechat/weibo/douyin/...', + `account_id` VARCHAR(191) NOT NULL COMMENT '账号号/手机/邮箱', + `profile_url` VARCHAR(500) DEFAULT NULL COMMENT '主页链接', + `remark` VARCHAR(255) DEFAULT NULL COMMENT '备注', + `is_primary` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否常用 1/0', + `is_defult` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否常用(备用字段)1/0', + `is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '有效 0/1', + `is_incomplete`TINYINT(1) NOT NULL DEFAULT 0 COMMENT '完整度标记', + `created_at` DATE DEFAULT NULL COMMENT '创建日期', + PRIMARY KEY (`id`), + KEY `idx_owner` (`owner_type`, `owner_id`), + KEY `idx_platform` (`platform`), + KEY `idx_account` (`account_id`), + KEY `idx_incomplete` (`is_incomplete`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='社媒账号/联系方式表'; + +-- ------------------------------------------------------------ +-- 4) 媒体商业属性(一人/一账号的多条商业评估) +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS `media_commercial_attributes` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `social_account_id` INT UNSIGNED NOT NULL COMMENT '关联 social_accounts.id', + `account_level` VARCHAR(50) DEFAULT NULL COMMENT '账号等级', + `content_categories` VARCHAR(255) DEFAULT NULL COMMENT '内容领域', + `follower_count` INT DEFAULT NULL COMMENT '粉丝数', + `avg_read_count` INT DEFAULT NULL COMMENT '平均阅读', + `certification_type` VARCHAR(50) DEFAULT NULL COMMENT '认证类型', + `special_requirements` TEXT DEFAULT NULL COMMENT '特殊要求', + `media_remark` TEXT DEFAULT NULL COMMENT '评估备注', + `is_incomplete` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '完整度标记', + `created_at` DATE DEFAULT NULL COMMENT '创建日期', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_social_account` (`social_account_id`), + KEY `idx_incomplete` (`is_incomplete`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='媒体商业属性表'; + +-- ------------------------------------------------------------ +-- 5) 需求(企业需求线索) +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS `company_needs` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `company_id` INT UNSIGNED DEFAULT NULL COMMENT '关联企业', + `contact_person` VARCHAR(100) DEFAULT NULL COMMENT '联系人', + `contact_phone` VARCHAR(50) DEFAULT NULL COMMENT '联系电话', + `contact_email` VARCHAR(100) DEFAULT NULL COMMENT '联系邮箱', + `need_category` VARCHAR(100) DEFAULT NULL COMMENT '需求类别', + `target_product_category` VARCHAR(100) DEFAULT NULL COMMENT '目标产品品类', + `application_scenario` VARCHAR(255) DEFAULT NULL COMMENT '应用场景', + `description` TEXT DEFAULT NULL COMMENT '需求描述', + `status` VARCHAR(30) DEFAULT NULL COMMENT '状态', + `is_valid` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '有效 0/1', + `is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '启用 0/1', + `created_at` DATE DEFAULT NULL COMMENT '创建日期', + `updated_at` DATE DEFAULT NULL COMMENT '更新日期', + PRIMARY KEY (`id`), + KEY `idx_company` (`company_id`), + KEY `idx_category` (`need_category`), + KEY `idx_is_valid` (`is_valid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='需求表'; + +-- ------------------------------------------------------------ +-- 6) 人员工作履历 +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS `person_work_experiences` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `person_id` INT UNSIGNED NOT NULL COMMENT '关联人员', + `company_id` INT UNSIGNED DEFAULT NULL COMMENT '任职企业', + `position` VARCHAR(191) DEFAULT NULL COMMENT '职位', + `department` VARCHAR(100) DEFAULT NULL COMMENT '部门', + `job_level` VARCHAR(50) DEFAULT NULL COMMENT '职级', + `start_date` DATE DEFAULT NULL COMMENT '开始时间', + `end_date` DATE DEFAULT NULL COMMENT '结束时间', + `is_current` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否现任 1/0', + `created_at` DATE DEFAULT NULL COMMENT '创建日期', + PRIMARY KEY (`id`), + KEY `idx_person` (`person_id`), + KEY `idx_company` (`company_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='人员工作履历表'; + +-- ------------------------------------------------------------ +-- 7) 企业产品(类别 + 定位 + 系列) +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS `company_products` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `company_id` INT UNSIGNED NOT NULL COMMENT '关联企业', + `category_name` VARCHAR(100) NOT NULL COMMENT '产品类别名', + `category_description` VARCHAR(255) DEFAULT NULL COMMENT '类别说明', + `positioning` TEXT DEFAULT NULL COMMENT '产品基本定位(商业定位介绍)', + `series` VARCHAR(200) DEFAULT NULL COMMENT '包含系列', + `is_core` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否核心产品', + `is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '启用 0/1', + `created_at` DATE DEFAULT NULL COMMENT '创建日期', + PRIMARY KEY (`id`), + KEY `idx_company` (`company_id`), + KEY `idx_core` (`is_core`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='企业产品表'; + +-- 产品参数 EAV(定义见 migration_v1.0.18) +CREATE TABLE IF NOT EXISTS `company_products_attr` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `industry` VARCHAR(100) NOT NULL, + `attr_name` VARCHAR(50) NOT NULL, + `attr_type` ENUM('string','number','boolean','date') NOT NULL DEFAULT 'string', + `unit` VARCHAR(20) DEFAULT NULL, + `sort_order` INT NOT NULL DEFAULT 0, + `is_active` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1, + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_industry_attr` (`industry`, `attr_name`), + KEY `idx_industry` (`industry`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='产品参数属性定义表(EAV)'; + +CREATE TABLE IF NOT EXISTS `company_products_attr_value` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `product_id` INT UNSIGNED NOT NULL, + `attr_id` INT UNSIGNED NOT NULL, + `value_string` TEXT DEFAULT NULL, + `value_number` DECIMAL(20,4) DEFAULT NULL, + `value_boolean` TINYINT(1) DEFAULT NULL, + `value_date` DATE DEFAULT NULL, + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_product_attr` (`product_id`, `attr_id`), + KEY `idx_product` (`product_id`), + KEY `idx_attr` (`attr_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='产品参数值表(EAV)'; + +-- ------------------------------------------------------------ +-- 8) 企业文档 +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS `company_documents` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `company_id` INT UNSIGNED DEFAULT NULL COMMENT '关联企业', + `doc_name` VARCHAR(255) NOT NULL COMMENT '文档名称', + `storage_path` VARCHAR(500) DEFAULT NULL COMMENT '存储路径', + `file_type` VARCHAR(30) DEFAULT NULL COMMENT '文件类型(pdf/word/xlsx/图片)', + `is_current` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否现行 1/0', + `document_source` VARCHAR(100) DEFAULT NULL COMMENT '文档来源', + `tags` VARCHAR(255) DEFAULT NULL COMMENT '标签', + `publish_date` DATE DEFAULT NULL COMMENT '发布日期', + `created_at` DATE DEFAULT NULL COMMENT '创建日期', + `update_time` DATETIME DEFAULT NULL COMMENT '更新时间', + `is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '有效 0/1', + PRIMARY KEY (`id`), + KEY `idx_company` (`company_id`), + KEY `idx_file_type` (`file_type`), + KEY `idx_active` (`is_active`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='企业文档表'; + +-- ------------------------------------------------------------ +-- 9) 财务与资质 +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS `company_financials` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `company_id` INT UNSIGNED NOT NULL COMMENT '关联企业', + `fiscal_year` INT NOT NULL COMMENT '财年', + `employee_count` INT DEFAULT NULL, + `total_revenue` DECIMAL(20,2) DEFAULT NULL, + `net_profit` DECIMAL(20,2) DEFAULT NULL, + `total_assets` DECIMAL(20,2) DEFAULT NULL, + `total_liabilities` DECIMAL(20,2) DEFAULT NULL, + `owner_equity` DECIMAL(20,2) DEFAULT NULL, + `gross_margin` DECIMAL(10,4) DEFAULT NULL, + `net_margin` DECIMAL(10,4) DEFAULT NULL, + `debt_ratio` DECIMAL(10,4) DEFAULT NULL, + `financial_report_url` VARCHAR(500) DEFAULT NULL, + `data_source` VARCHAR(100) DEFAULT '手动录入', + `created_at` DATE DEFAULT NULL COMMENT '创建日期', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_company_year` (`company_id`, `fiscal_year`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='企业年度财务明细表'; + +CREATE TABLE IF NOT EXISTS `company_certifications` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `company_id` INT UNSIGNED NOT NULL COMMENT '关联企业', + `certification_type_id` INT UNSIGNED DEFAULT NULL COMMENT '证书类型(字典)', + `certificate_number` VARCHAR(100) DEFAULT NULL COMMENT '证书编号', + `level` VARCHAR(50) DEFAULT NULL COMMENT '级别', + `issuing_authority` VARCHAR(200) DEFAULT NULL COMMENT '颁证机构', + `issue_date` DATE DEFAULT NULL COMMENT '发证日期', + `expiry_date` DATE DEFAULT NULL COMMENT '有效期至', + `created_at` DATE DEFAULT NULL COMMENT '创建日期', + PRIMARY KEY (`id`), + KEY `idx_company` (`company_id`), + KEY `idx_cert_type` (`certification_type_id`), + CONSTRAINT `fk_company_cert_dict` FOREIGN KEY (`certification_type_id`) + REFERENCES `data_dict_certificate` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='企业资质认证表'; + +CREATE TABLE IF NOT EXISTS `company_relations` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `company_id` INT UNSIGNED DEFAULT NULL COMMENT '企业A', + `related_company_id` INT UNSIGNED DEFAULT NULL COMMENT '关联企业B', + `related_company_name` VARCHAR(191) DEFAULT NULL COMMENT '关联企业名称', + `relation_type` VARCHAR(50) DEFAULT NULL COMMENT '关系类型', + `established_date` DATE DEFAULT NULL COMMENT '关系建立日期', + `note` VARCHAR(255) DEFAULT NULL COMMENT '备注', + `is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '有效 0/1', + `created_at` DATE DEFAULT NULL COMMENT '创建日期', + `updated_at` DATE DEFAULT NULL COMMENT '更新日期', + PRIMARY KEY (`id`), + KEY `idx_company` (`company_id`), + KEY `idx_related` (`related_company_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='企业关联关系表'; + +-- ------------------------------------------------------------ +-- 10) 硬数据碎片(preliminary_data,v1.0.48 重构后形态) +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS `preliminary_data` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `source_type` VARCHAR(20) DEFAULT NULL COMMENT '碎片类型 company/person/product/need/mixed', + `company_name` VARCHAR(191) DEFAULT NULL COMMENT '企业名(核心)', + `person_name` VARCHAR(100) DEFAULT NULL COMMENT '联系人(核心)', + `contact_phone` VARCHAR(50) DEFAULT NULL COMMENT '联系电话(核心)', + `contact_email` VARCHAR(100) DEFAULT NULL COMMENT '联系邮箱(核心)', + `industry` VARCHAR(100) DEFAULT NULL COMMENT '行业', + `registration_number` VARCHAR(100) DEFAULT NULL COMMENT '注册号(重要)', + `business_role` VARCHAR(50) DEFAULT NULL COMMENT '业务类型(重要)', + `country` VARCHAR(100) DEFAULT NULL COMMENT '国家/地区(重要)', + `address` VARCHAR(255) DEFAULT NULL COMMENT '地址(重要)', + `work_location` VARCHAR(100) DEFAULT NULL COMMENT '工作所在地(重要)', + `id_number` VARCHAR(100) DEFAULT NULL COMMENT '身份证号码(重要)', + `platform` VARCHAR(50) DEFAULT NULL COMMENT '社媒平台(核心)', + `account_id` VARCHAR(200) DEFAULT NULL COMMENT '社媒账号ID(核心)', + `profile_url` VARCHAR(500) DEFAULT NULL COMMENT '主页链接(重要)', + `source_channel` VARCHAR(50) DEFAULT NULL COMMENT '来源渠道', + `source_detail` VARCHAR(255) DEFAULT NULL COMMENT '来源详情', + `converted_type` VARCHAR(20) DEFAULT NULL COMMENT '转换目标类型 companies/persons/...', + `converted_id` VARCHAR(64) DEFAULT NULL COMMENT '转换后目标表ID(非空=已转换/已处理)', + `recorded_by` INT UNSIGNED DEFAULT NULL COMMENT '录入用户', + `label` VARCHAR(50) DEFAULT NULL COMMENT '标签', + `remark` TEXT DEFAULT NULL COMMENT '备注', + `is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '有效 0/1', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '录入时间', + `processed_at` DATETIME DEFAULT NULL COMMENT '处理时间', + PRIMARY KEY (`id`), + KEY `idx_source_type` (`source_type`), + KEY `idx_converted` (`converted_id`), + KEY `idx_is_active` (`is_active`), + KEY `idx_channel` (`source_channel`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='硬数据碎片表'; + +-- ------------------------------------------------------------ +-- 11) 渠道新增计划(定义见 migration_v1.0.18,补 cost 列) +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS `channel_plans` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `channel_type` VARCHAR(50) NOT NULL COMMENT '渠道类别(= source_channel 枚举)', + `source_detail` VARCHAR(255) DEFAULT NULL COMMENT '来源详情', + `industry` VARCHAR(100) DEFAULT NULL COMMENT '所属行业', + `cost` DECIMAL(12,2) DEFAULT NULL COMMENT '计划成本/投入', + `start_date` DATE DEFAULT NULL COMMENT '时间窗口开始', + `end_date` DATE DEFAULT NULL COMMENT '时间窗口结束', + `remark` VARCHAR(255) DEFAULT NULL COMMENT '备注说明', + `status` ENUM('待启动','已执行','错过') NOT NULL DEFAULT '待启动' COMMENT '状态反馈', + `is_active` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '启用状态', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_channel_type` (`channel_type`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='渠道新增计划表'; + +-- ------------------------------------------------------------ +-- 12) 系统:用户 / 角色 / 日志 / 登录尝试 / 迁移版本 +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS `system_users` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `username` VARCHAR(50) NOT NULL COMMENT '登录账号', + `password` VARCHAR(190) NOT NULL COMMENT '密码(bcrypt)', + `real_name` VARCHAR(100) DEFAULT NULL COMMENT '真实姓名', + `role_id` INT UNSIGNED DEFAULT NULL COMMENT '角色', + `is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '启用 0/1', + `last_login_time` DATETIME DEFAULT NULL COMMENT '最后登录时间', + `last_login_ip` VARCHAR(45) DEFAULT NULL COMMENT '最后登录IP', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_username` (`username`), + KEY `idx_role` (`role_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统用户表'; + +CREATE TABLE IF NOT EXISTS `system_roles` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `role_name` VARCHAR(50) NOT NULL COMMENT '角色名', + `permissions` TEXT DEFAULT NULL COMMENT '权限集(JSON 数组)', + `is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '启用 0/1', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_active` (`is_active`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统角色表'; + +CREATE TABLE IF NOT EXISTS `system_logs` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `user_id` INT UNSIGNED DEFAULT NULL COMMENT '操作用户ID', + `username` VARCHAR(50) DEFAULT NULL COMMENT '操作账号', + `action` VARCHAR(50) DEFAULT NULL COMMENT '操作动作', + `module` VARCHAR(50) DEFAULT NULL COMMENT '操作模块', + `target_table` VARCHAR(50) DEFAULT NULL COMMENT '目标表', + `target_id` INT UNSIGNED DEFAULT NULL COMMENT '目标ID', + `content` TEXT DEFAULT NULL COMMENT '操作内容(JSON)', + `ip` VARCHAR(45) DEFAULT NULL COMMENT '来源IP', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `idx_user` (`user_id`), + KEY `idx_module` (`module`), + KEY `idx_created` (`created_at`), + KEY `idx_target` (`target_table`, `target_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统操作日志表'; + +CREATE TABLE IF NOT EXISTS `system_login_attempts` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `username` VARCHAR(50) NOT NULL DEFAULT '', + `ip` VARCHAR(45) NOT NULL DEFAULT '', + `success` TINYINT NOT NULL DEFAULT 0, + `attempt_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + KEY `idx_ip_user_time` (`ip`, `username`, `attempt_time`), + KEY `idx_attempt_time` (`attempt_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='登录尝试记录(限流/防爆破)'; + +CREATE TABLE IF NOT EXISTS `schema_versions` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `version` VARCHAR(64) NOT NULL, + `applied_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `checksum` CHAR(32) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_version` (`version`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据库迁移版本表'; + +-- ------------------------------------------------------------ +-- 13) 文档链接(competitor_data / 归档) +-- ------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS `document_links` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `company_id` INT UNSIGNED DEFAULT NULL COMMENT '关联企业', + `doc_name` VARCHAR(255) DEFAULT NULL COMMENT '文档名称', + `url` VARCHAR(500) DEFAULT NULL COMMENT '链接', + `file_type` VARCHAR(30) DEFAULT NULL COMMENT '类型', + `source` VARCHAR(100) DEFAULT NULL COMMENT '来源', + `publish_date` DATE DEFAULT NULL COMMENT '发布日期', + `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '有效 0/1', + PRIMARY KEY (`id`), + KEY `idx_company` (`company_id`), + KEY `idx_active` (`is_active`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='文档链接表'; + +SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file