diff --git a/.github/workflows/docker_publish.yml b/.github/workflows/docker_publish.yml index 361795c..d2df9c4 100644 --- a/.github/workflows/docker_publish.yml +++ b/.github/workflows/docker_publish.yml @@ -33,6 +33,12 @@ jobs: - name: Checkout Code uses: actions/checkout@v7.0.1 + - name: Checkout OpenSabre Framework + uses: actions/checkout@v7.0.1 + with: + repository: opensabre/opensabre-framework + path: opensabre-framework + - name: Set up JDK uses: actions/setup-java@v5.6.0 with: @@ -40,6 +46,9 @@ jobs: distribution: 'temurin' cache: maven + - name: Install OpenSabre Framework Snapshot + run: mvn --batch-mode --no-transfer-progress -f opensabre-framework/pom.xml -DskipTests install + - name: Run Tests run: mvn --batch-mode --no-transfer-progress verify @@ -66,6 +75,12 @@ jobs: - name: Checkout Code uses: actions/checkout@v7.0.1 + - name: Checkout OpenSabre Framework + uses: actions/checkout@v7.0.1 + with: + repository: opensabre/opensabre-framework + path: opensabre-framework + - name: Set up JDK uses: actions/setup-java@v5.6.0 with: @@ -73,6 +88,9 @@ jobs: distribution: 'temurin' cache: maven + - name: Install OpenSabre Framework Snapshot + run: mvn --batch-mode --no-transfer-progress -f opensabre-framework/pom.xml -DskipTests install + - name: Resolve image tags id: image shell: bash diff --git a/docs/development.md b/docs/development.md index 4fb1600..b2b89dd 100644 --- a/docs/development.md +++ b/docs/development.md @@ -1,6 +1,6 @@ # 开发与运行 -1. 基于 `resources/db/` 初始化数据库;已有环境按版本顺序评估并执行 `migrations/`。 +1. 数据库变更写入 `resources/db/migration/mysql/`,由发布阶段的独立 Flyway 进程执行;应用 Pod 启动时不执行迁移。 2. 配置注册中心、数据库、缓存和通知渠道等依赖,再通过 Maven 启动。 3. 变更后按模块验证 API、数据持久化、权限和异常路径。 diff --git a/pom.xml b/pom.xml index c2e52cb..84ee1e5 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ opensabre-base-dependencies io.github.opensabre - 1.1.2 + 1.1.3-SNAPSHOT base-sysadmin @@ -45,6 +45,10 @@ + + io.github.opensabre + opensabre-starter-migration + io.github.opensabre opensabre-starter-register diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8e19a7f..ef6b56e 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,6 +1,9 @@ server: port: ${SERVER_PORT:8020} spring: + # Database changes are executed by the dedicated release migration process, never by app pods. + flyway: + enabled: false application: name: base-sysadmin cloud: diff --git a/src/main/resources/db/migration/mysql/V20260701_00__baseline.sql b/src/main/resources/db/migration/mysql/V20260701_00__baseline.sql new file mode 100644 index 0000000..9e6f5dd --- /dev/null +++ b/src/main/resources/db/migration/mysql/V20260701_00__baseline.sql @@ -0,0 +1,164 @@ +SET NAMES utf8; +-- 审计日志表 +DROP TABLE IF EXISTS base_sys_audit_log; +CREATE TABLE IF NOT EXISTS `base_sys_audit_log` ( + `id` varchar(32) NOT NULL COMMENT '主键ID', + `operation_type` varchar(50) NOT NULL COMMENT '操作类型', + `operation_time` datetime NOT NULL COMMENT '操作时间', + `operator_username` varchar(100) NOT NULL COMMENT '操作人用户名', + `module` varchar(100) NOT NULL COMMENT '操作模块', + `description` varchar(500) COMMENT '操作描述', + `client_ip` varchar(50) COMMENT '操作IP地址', + `target_key` varchar(50) COMMENT '操作目标关键key', + `user_agent` varchar(500) COMMENT '用户代理', + `request_method` varchar(10) COMMENT '请求方法', + `request_url` varchar(500) COMMENT '请求URL', + `request` text COMMENT '请求参数', + `response` text COMMENT '操作结果', + `error_message` text COMMENT '错误信息', + `execution_time` bigint COMMENT '执行时间(毫秒)', + `created_by` varchar(100) NOT NULL COMMENT '创建人', + `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_by` varchar(100) NOT NULL COMMENT '更新人', + `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_operator_username` (`operator_username`), + KEY `idx_operation_time` (`operation_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='审计日志表'; + +DROP TABLE IF EXISTS base_sys_captcha_scene; +CREATE TABLE IF NOT EXISTS `base_sys_captcha_scene` ( + `id` varchar(32) NOT NULL COMMENT '主键ID', + `scene_code` varchar(64) NOT NULL COMMENT '场景编码', + `scene_name` varchar(128) NOT NULL COMMENT '场景名称', + `captcha_type` varchar(32) NOT NULL COMMENT '验证码类型', + `template_code` varchar(64) DEFAULT NULL COMMENT '消息模板编码', + `notification_template_id` varchar(64) DEFAULT NULL COMMENT '通知模板ID', + `description` varchar(255) DEFAULT NULL COMMENT '描述', + `captcha_length` int NOT NULL DEFAULT 4 COMMENT '验证码长度', + `captcha_expire_time` int NOT NULL DEFAULT 300 COMMENT '过期时间(秒)', + `captcha_attempts` int NOT NULL DEFAULT 3 COMMENT '最大尝试次数', + `min_interval` int NOT NULL DEFAULT 60 COMMENT '最小间隔(秒)', + `max_limit_count` int NOT NULL DEFAULT 100 COMMENT '单用户生成限制次数', + `enabled` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否启用', + `created_by` varchar(100) NOT NULL COMMENT '创建人', + `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_by` varchar(100) NOT NULL COMMENT '更新人', + `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_scene_code` (`scene_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='验证码场景表'; + +DROP TABLE IF EXISTS base_sys_ratelimit_scene; +CREATE TABLE IF NOT EXISTS `base_sys_ratelimit_scene` ( + `id` varchar(32) NOT NULL COMMENT '主键ID', + `scene_code` varchar(64) NOT NULL COMMENT '场景编码', + `scene_name` varchar(128) NOT NULL COMMENT '场景名称', + `algorithm` varchar(32) NOT NULL COMMENT '限次算法', + `dimensions` varchar(255) DEFAULT NULL COMMENT '维度代码,逗号分隔', + `key_prefix` varchar(100) DEFAULT NULL COMMENT '业务前缀', + `max_count` int NOT NULL DEFAULT 5 COMMENT '最大次数', + `period` int NOT NULL DEFAULT 60 COMMENT '时间窗口(秒)', + `enabled` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否启用', + `description` varchar(255) DEFAULT NULL COMMENT '描述', + `created_by` varchar(100) NOT NULL COMMENT '创建人', + `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_by` varchar(100) NOT NULL COMMENT '更新人', + `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_scene_code` (`scene_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='限次场景表'; + +DROP TABLE IF EXISTS base_sys_notification_record; +DROP TABLE IF EXISTS base_sys_notification_template; +DROP TABLE IF EXISTS base_sys_notification_scene; +CREATE TABLE IF NOT EXISTS `base_sys_notification_scene` ( + `id` varchar(32) NOT NULL COMMENT '主键ID', + `scene_code` varchar(64) NOT NULL COMMENT '场景编码', + `scene_name` varchar(128) NOT NULL COMMENT '场景名称', + `description` varchar(255) DEFAULT NULL COMMENT '描述', + `enabled` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否启用', + `created_by` varchar(100) NOT NULL COMMENT '创建人', + `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_by` varchar(100) NOT NULL COMMENT '更新人', + `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_scene_code` (`scene_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='通知场景表'; + +CREATE TABLE IF NOT EXISTS `base_sys_notification_template` ( + `id` varchar(32) NOT NULL COMMENT '主键ID', + `scene_code` varchar(64) NOT NULL COMMENT '场景编码', + `channel` varchar(32) NOT NULL COMMENT '发送渠道', + `template_name` varchar(128) NOT NULL COMMENT '模板名称', + `title` varchar(255) DEFAULT NULL COMMENT '标题', + `content` text NOT NULL COMMENT '模板内容', + `param_schema` varchar(1000) DEFAULT NULL COMMENT '参数说明', + `sort` int NOT NULL DEFAULT 1 COMMENT '排序', + `enabled` tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否启用', + `created_by` varchar(100) NOT NULL COMMENT '创建人', + `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_by` varchar(100) NOT NULL COMMENT '更新人', + `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_scene_channel` (`scene_code`, `channel`), + KEY `idx_scene_enabled_sort` (`scene_code`, `enabled`, `sort`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='通知渠道模板表'; + +CREATE TABLE IF NOT EXISTS `base_sys_notification_record` ( + `id` varchar(32) NOT NULL COMMENT '主键ID', + `scene_code` varchar(64) NOT NULL COMMENT '场景编码', + `channel` varchar(32) NOT NULL COMMENT '发送渠道', + `target` varchar(255) NOT NULL COMMENT '发送目标', + `template_id` varchar(32) DEFAULT NULL COMMENT '模板ID', + `template_title` varchar(255) DEFAULT NULL COMMENT '标题快照', + `template_content` text COMMENT '内容快照', + `args_json` text COMMENT '参数JSON', + `status` varchar(32) NOT NULL COMMENT '发送状态', + `message_id` varchar(128) DEFAULT NULL COMMENT '消息ID', + `failure_reason` text COMMENT '失败原因', + `retry_count` int NOT NULL DEFAULT 0 COMMENT '重试次数', + `next_retry_time` datetime DEFAULT NULL COMMENT '下次重试时间', + `sent_time` datetime DEFAULT NULL COMMENT '发送时间', + `created_by` varchar(100) NOT NULL COMMENT '创建人', + `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_by` varchar(100) NOT NULL COMMENT '更新人', + `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_scene_channel_status` (`scene_code`, `channel`, `status`), + KEY `idx_created_time` (`created_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='通知发送记录表'; + +DROP TABLE IF EXISTS base_sys_dict_item; +DROP TABLE IF EXISTS base_sys_dict_type; +CREATE TABLE IF NOT EXISTS `base_sys_dict_type` ( + `id` varchar(32) NOT NULL COMMENT '主键ID', + `name` varchar(128) NOT NULL COMMENT '字典名称', + `dict_code` varchar(64) NOT NULL COMMENT '字典编码', + `status` tinyint NOT NULL DEFAULT 1 COMMENT '状态(1:启用;0:禁用)', + `remark` varchar(255) DEFAULT NULL COMMENT '备注', + `created_by` varchar(100) NOT NULL COMMENT '创建人', + `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_by` varchar(100) NOT NULL COMMENT '更新人', + `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_dict_code` (`dict_code`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='字典类型表'; + +CREATE TABLE IF NOT EXISTS `base_sys_dict_item` ( + `id` varchar(32) NOT NULL COMMENT '主键ID', + `dict_code` varchar(64) NOT NULL COMMENT '字典编码', + `label` varchar(128) NOT NULL COMMENT '字典项标签', + `value` varchar(128) NOT NULL COMMENT '字典项值', + `status` tinyint NOT NULL DEFAULT 1 COMMENT '状态(1:启用;0:禁用)', + `sort` int NOT NULL DEFAULT 1 COMMENT '排序', + `tag_type` varchar(16) NOT NULL DEFAULT 'N' COMMENT '标签类型(N/P/S/W/I/D)', + `created_by` varchar(100) NOT NULL COMMENT '创建人', + `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_by` varchar(100) NOT NULL COMMENT '更新人', + `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_dict_value` (`dict_code`, `value`), + KEY `idx_dict_status_sort` (`dict_code`, `status`, `sort`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='字典项表'; diff --git a/src/main/resources/db/migrations/V20260714_01__create_rate_limit_scene_table.sql b/src/main/resources/db/migration/mysql/V20260714_01__create_rate_limit_scene_table.sql similarity index 98% rename from src/main/resources/db/migrations/V20260714_01__create_rate_limit_scene_table.sql rename to src/main/resources/db/migration/mysql/V20260714_01__create_rate_limit_scene_table.sql index 4dc2145..c8732d9 100644 --- a/src/main/resources/db/migrations/V20260714_01__create_rate_limit_scene_table.sql +++ b/src/main/resources/db/migration/mysql/V20260714_01__create_rate_limit_scene_table.sql @@ -1,4 +1,3 @@ -USE os_base_sysadmin; SET NAMES utf8mb4; CREATE TABLE IF NOT EXISTS `base_sys_ratelimit_scene` ( diff --git a/src/main/resources/db/migrations/V20260714_02__seed_captcha_rate_limit_scenes.sql b/src/main/resources/db/migration/mysql/V20260714_02__seed_captcha_rate_limit_scenes.sql similarity index 98% rename from src/main/resources/db/migrations/V20260714_02__seed_captcha_rate_limit_scenes.sql rename to src/main/resources/db/migration/mysql/V20260714_02__seed_captcha_rate_limit_scenes.sql index a0066d2..c3623aa 100644 --- a/src/main/resources/db/migrations/V20260714_02__seed_captcha_rate_limit_scenes.sql +++ b/src/main/resources/db/migration/mysql/V20260714_02__seed_captcha_rate_limit_scenes.sql @@ -1,4 +1,3 @@ -USE os_base_sysadmin; SET NAMES utf8mb4; INSERT INTO base_sys_ratelimit_scene diff --git a/src/main/resources/db/migration/mysql/V20260715_01__create_internal_message_tables.sql b/src/main/resources/db/migration/mysql/V20260715_01__create_internal_message_tables.sql new file mode 100644 index 0000000..b4a37f3 --- /dev/null +++ b/src/main/resources/db/migration/mysql/V20260715_01__create_internal_message_tables.sql @@ -0,0 +1,36 @@ +SET NAMES utf8mb4; + +-- 站内信:消息主体与收件人快照。发布时由应用将目标用户名固化为收件人记录。 +CREATE TABLE IF NOT EXISTS `base_sys_internal_message` ( + `id` varchar(32) NOT NULL COMMENT '主键ID', + `kind` varchar(32) NOT NULL COMMENT '消息类型:ANNOUNCEMENT/NOTIFICATION', + `title` varchar(255) NOT NULL COMMENT '标题', + `content` text NOT NULL COMMENT '富文本内容', + `level` varchar(16) NOT NULL DEFAULT 'L' COMMENT '消息等级', + `target_scope` varchar(32) NOT NULL COMMENT '目标范围', + `target_usernames` text NOT NULL COMMENT '草稿目标用户名快照,逗号分隔', + `target_url` varchar(500) DEFAULT NULL COMMENT '站内跳转地址', + `status` varchar(32) NOT NULL COMMENT '状态:DRAFT/PUBLISHED/REVOKED', + `publish_time` datetime DEFAULT NULL COMMENT '发布时间', + `expire_time` datetime DEFAULT NULL COMMENT '到期时间', + `created_by` varchar(100) NOT NULL COMMENT '创建人', + `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_by` varchar(100) NOT NULL COMMENT '更新人', + `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_status_publish_time` (`status`, `publish_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='站内信主体表'; + +CREATE TABLE IF NOT EXISTS `base_sys_internal_message_recipient` ( + `id` varchar(32) NOT NULL COMMENT '主键ID', + `message_id` varchar(32) NOT NULL COMMENT '站内信ID', + `username` varchar(100) NOT NULL COMMENT '接收用户名', + `read_time` datetime DEFAULT NULL COMMENT '阅读时间', + `created_by` varchar(100) NOT NULL COMMENT '创建人', + `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_by` varchar(100) NOT NULL COMMENT '更新人', + `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_message_username` (`message_id`, `username`), + KEY `idx_username_read_time` (`username`, `read_time`, `created_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='站内信收件人表'; diff --git a/src/main/resources/db/migrations/V20260715_03__create_usage_counter_minute_table.sql b/src/main/resources/db/migration/mysql/V20260715_03__create_usage_counter_minute_table.sql similarity index 100% rename from src/main/resources/db/migrations/V20260715_03__create_usage_counter_minute_table.sql rename to src/main/resources/db/migration/mysql/V20260715_03__create_usage_counter_minute_table.sql diff --git a/src/main/resources/db/migrations/V20260720_01__create_usage_scene_table.sql b/src/main/resources/db/migration/mysql/V20260720_01__create_usage_scene_table.sql similarity index 100% rename from src/main/resources/db/migrations/V20260720_01__create_usage_scene_table.sql rename to src/main/resources/db/migration/mysql/V20260720_01__create_usage_scene_table.sql diff --git a/src/main/resources/db/migrations/V20260720_02__repair_usage_scene_name_encoding.sql b/src/main/resources/db/migration/mysql/V20260720_02__repair_usage_scene_name_encoding.sql similarity index 100% rename from src/main/resources/db/migrations/V20260720_02__repair_usage_scene_name_encoding.sql rename to src/main/resources/db/migration/mysql/V20260720_02__repair_usage_scene_name_encoding.sql diff --git a/src/main/resources/db/migrations/V20260720_03__create_error_catalog_table.sql b/src/main/resources/db/migration/mysql/V20260720_03__create_error_catalog_table.sql similarity index 100% rename from src/main/resources/db/migrations/V20260720_03__create_error_catalog_table.sql rename to src/main/resources/db/migration/mysql/V20260720_03__create_error_catalog_table.sql diff --git a/src/main/resources/db/migrations/V20260726_01__add_error_catalog_ownership.sql b/src/main/resources/db/migration/mysql/V20260726_01__add_error_catalog_ownership.sql similarity index 100% rename from src/main/resources/db/migrations/V20260726_01__add_error_catalog_ownership.sql rename to src/main/resources/db/migration/mysql/V20260726_01__add_error_catalog_ownership.sql diff --git a/src/main/resources/db/migrations/V20260729_01__add_dictionary_ownership.sql b/src/main/resources/db/migration/mysql/V20260729_01__add_dictionary_ownership.sql similarity index 100% rename from src/main/resources/db/migrations/V20260729_01__add_dictionary_ownership.sql rename to src/main/resources/db/migration/mysql/V20260729_01__add_dictionary_ownership.sql diff --git a/src/main/resources/db/migrations/V20260818_01__use_millisecond_precision_for_audit_timestamps.sql b/src/main/resources/db/migration/mysql/V20260818_01__use_millisecond_precision_for_audit_timestamps.sql similarity index 99% rename from src/main/resources/db/migrations/V20260818_01__use_millisecond_precision_for_audit_timestamps.sql rename to src/main/resources/db/migration/mysql/V20260818_01__use_millisecond_precision_for_audit_timestamps.sql index 2c58722..6215092 100644 --- a/src/main/resources/db/migrations/V20260818_01__use_millisecond_precision_for_audit_timestamps.sql +++ b/src/main/resources/db/migration/mysql/V20260818_01__use_millisecond_precision_for_audit_timestamps.sql @@ -1,4 +1,3 @@ -USE os_base_sysadmin; SET NAMES utf8mb4; -- 此版本迁移仅执行一次。DATETIME 不进行时区转换;历史记录已截断的毫秒无法恢复。 diff --git a/src/main/resources/db/migrations/V20260829_01__seed_iqc_rule_category_dictionary.sql b/src/main/resources/db/migration/mysql/V20260829_01__seed_iqc_rule_category_dictionary.sql similarity index 51% rename from src/main/resources/db/migrations/V20260829_01__seed_iqc_rule_category_dictionary.sql rename to src/main/resources/db/migration/mysql/V20260829_01__seed_iqc_rule_category_dictionary.sql index 9c29fb6..33b754f 100644 --- a/src/main/resources/db/migrations/V20260829_01__seed_iqc_rule_category_dictionary.sql +++ b/src/main/resources/db/migration/mysql/V20260829_01__seed_iqc_rule_category_dictionary.sql @@ -33,3 +33,25 @@ ON DUPLICATE KEY UPDATE `sort` = VALUES(`sort`), `tag_type` = VALUES(`tag_type`), `updated_by` = 'system'; + +INSERT INTO `base_sys_dict_type` + (`id`, `name`, `dict_code`, `source_application`, `status`, `remark`, `created_by`, `updated_by`) +VALUES + ('DICT_IQC_CONVERSATION_CHANNEL', '会话渠道', 'iqc_conversation_channel', 'iqc-platform', 1, 'IQC 会话来源渠道(系统枚举)', 'system', 'system'), + ('DICT_IQC_BUSINESS_TYPE', '业务类型', 'iqc_business_type', NULL, 1, 'IQC 业务类型(管理员可维护)', 'system', 'system') +ON DUPLICATE KEY UPDATE + `name` = VALUES(`name`), `status` = 1, `remark` = VALUES(`remark`), `updated_by` = 'system'; + +INSERT INTO `base_sys_dict_item` + (`id`, `dict_code`, `label`, `value`, `status`, `sort`, `tag_type`, `created_by`, `updated_by`) +VALUES + ('DICT_IQC_CHANNEL_WEB', 'iqc_conversation_channel', '网页', 'WEB', 1, 10, 'P', 'system', 'system'), + ('DICT_IQC_CHANNEL_PHONE', 'iqc_conversation_channel', '电话', 'PHONE', 1, 20, 'S', 'system', 'system'), + ('DICT_IQC_CHANNEL_WECHAT', 'iqc_conversation_channel', '微信', 'WECHAT', 1, 30, 'P', 'system', 'system'), + ('DICT_IQC_CHANNEL_APP', 'iqc_conversation_channel', 'App', 'APP', 1, 40, 'S', 'system', 'system'), + ('DICT_IQC_CHANNEL_OTHER', 'iqc_conversation_channel', '其他', 'OTHER', 1, 99, 'N', 'system', 'system'), + ('DICT_IQC_BUSINESS_ORDER', 'iqc_business_type', '订单', 'ORDER', 1, 10, 'P', 'system', 'system'), + ('DICT_IQC_BUSINESS_TICKET', 'iqc_business_type', '工单', 'TICKET', 1, 20, 'W', 'system', 'system'), + ('DICT_IQC_BUSINESS_COMPLAINT', 'iqc_business_type', '投诉', 'COMPLAINT', 1, 30, 'D', 'system', 'system') +ON DUPLICATE KEY UPDATE + `label` = VALUES(`label`), `status` = 1, `sort` = VALUES(`sort`), `tag_type` = VALUES(`tag_type`), `updated_by` = 'system'; diff --git a/src/main/resources/db/migration/mysql/V20260829_02__seed_iqc_rate_limit_scenes.sql b/src/main/resources/db/migration/mysql/V20260829_02__seed_iqc_rate_limit_scenes.sql new file mode 100644 index 0000000..37f3838 --- /dev/null +++ b/src/main/resources/db/migration/mysql/V20260829_02__seed_iqc_rate_limit_scenes.sql @@ -0,0 +1,51 @@ +SET NAMES utf8mb4; + +-- IQC controllers declare named rate-limit scenes. Sysadmin requires every named scene +-- to exist and deliberately does not fall back to annotation values for unknown names. +INSERT INTO base_sys_ratelimit_scene + (id, scene_code, scene_name, algorithm, dimensions, key_prefix, max_count, period, enabled, description, created_by, updated_by) +VALUES + ('RL_IQC_CONV_IMPORT', 'iqc-conversation-import', 'IQC 单文件会话导入', 'COUNTER', 'IP', 'iqc-conversation-import', 30, 60, 1, '单文件 TXT 会话导入限次', 'system', 'system'), + ('RL_IQC_CONV_BATCH_IMPORT', 'iqc-conversation-batch-import', 'IQC 批量会话导入', 'COUNTER', 'IP', 'iqc-conversation-batch-import', 10, 60, 1, '批量 TXT 会话导入限次', 'system', 'system'), + ('RL_IQC_CONV_ZIP_IMPORT', 'iqc-conversation-zip-import', 'IQC ZIP 会话导入', 'COUNTER', 'IP', 'iqc-conversation-zip-import', 10, 60, 1, 'ZIP 会话导入限次', 'system', 'system'), + ('RL_IQC_CONV_INGEST', 'iqc-conversation-ingest', 'IQC 单会话接口接入', 'COUNTER', 'IP', 'iqc-conversation-ingest', 120, 60, 1, '单会话接口接入限次', 'system', 'system'), + ('RL_IQC_CONV_INGEST_BATCH', 'iqc-conversation-ingest-batch', 'IQC 批量会话接口接入', 'COUNTER', 'IP', 'iqc-conversation-ingest-batch', 30, 60, 1, '批量会话接口接入限次', 'system', 'system'), + ('RL_IQC_CONV_QUERY', 'iqc-conversation-query', 'IQC 会话查询', 'COUNTER', 'IP', 'iqc-conversation-query', 60, 60, 1, '会话列表和详情查询限次', 'system', 'system'), + ('RL_IQC_TASK_QUERY', 'iqc-task-query', 'IQC 任务查询', 'COUNTER', 'IP', 'iqc-task-query', 60, 60, 1, '质检任务查询限次', 'system', 'system'), + ('RL_IQC_TASK_CREATE', 'iqc-task-create', 'IQC 任务创建', 'COUNTER', 'IP', 'iqc-task-create', 20, 60, 1, '质检任务创建限次', 'system', 'system'), + ('RL_IQC_TASK_RUN', 'iqc-task-run', 'IQC 任务执行', 'COUNTER', 'IP', 'iqc-task-run', 10, 60, 1, '质检任务执行限次', 'system', 'system'), + ('RL_IQC_RESULT_QUERY', 'iqc-result-query', 'IQC 结果查询', 'COUNTER', 'IP', 'iqc-result-query', 60, 60, 1, '质检结果查询限次', 'system', 'system'), + ('RL_IQC_RESULT_EXPORT', 'iqc-result-export', 'IQC 结果导出', 'COUNTER', 'IP', 'iqc-result-export', 10, 60, 1, '质检结果导出限次', 'system', 'system'), + ('RL_IQC_RESULT_FEEDBACK', 'iqc-result-feedback', 'IQC 结果反馈', 'COUNTER', 'IP', 'iqc-result-feedback', 60, 60, 1, '质检结果人工标注限次', 'system', 'system'), + ('RL_IQC_BOOTSTRAP', 'iqc-bootstrap', 'IQC 基础状态查询', 'COUNTER', 'IP', 'iqc-bootstrap', 60, 60, 1, 'IQC 基础状态查询限次', 'system', 'system'), + ('RL_IQC_DASHBOARD_QUERY', 'iqc-dashboard-query', 'IQC 总览查询', 'COUNTER', 'IP', 'iqc-dashboard-query', 30, 60, 1, '质检总览查询限次', 'system', 'system'), + ('RL_IQC_TEMPLATE_QUERY', 'iqc-template-query', 'IQC 模板查询', 'COUNTER', 'IP', 'iqc-template-query', 60, 60, 1, '质检模板查询限次', 'system', 'system'), + ('RL_IQC_TEMPLATE_MATERIALIZE', 'iqc-template-materialize', 'IQC 模板实例化', 'COUNTER', 'IP', 'iqc-template-materialize', 10, 60, 1, '从模板创建规则限次', 'system', 'system'), + ('RL_IQC_SETTINGS_QUERY', 'iqc-settings-query', 'IQC 设置查询', 'COUNTER', 'IP', 'iqc-settings-query', 60, 60, 1, 'IQC 设置查询限次', 'system', 'system'), + ('RL_IQC_DICTIONARY_QUERY', 'iqc-dictionary-query', 'IQC 字典查询', 'COUNTER', 'IP', 'iqc-dictionary-query', 60, 60, 1, 'IQC 字典选项查询限次', 'system', 'system'), + ('RL_IQC_AGENT_CREATE', 'iqc-agent-create', 'IQC Agent 创建', 'COUNTER', 'IP', 'iqc-agent-create', 20, 60, 1, 'IQC Agent 创建限次', 'system', 'system'), + ('RL_IQC_RULE_CREATE', 'iqc-rule-create', 'IQC 规则创建', 'COUNTER', 'IP', 'iqc-rule-create', 30, 60, 1, 'IQC 规则创建限次', 'system', 'system'), + ('RL_IQC_RULE_TEST', 'iqc-rule-test', 'IQC 规则测试', 'COUNTER', 'IP', 'iqc-rule-test', 60, 60, 1, 'IQC 规则测试限次', 'system', 'system'), + ('RL_IQC_SKILL_CREATE', 'iqc-skill-create', 'IQC Skill 创建', 'COUNTER', 'IP', 'iqc-skill-create', 20, 60, 1, 'IQC Skill 创建限次', 'system', 'system') +ON DUPLICATE KEY UPDATE scene_name = VALUES(scene_name), + algorithm = VALUES(algorithm), + dimensions = VALUES(dimensions), + key_prefix = VALUES(key_prefix), + max_count = VALUES(max_count), + period = VALUES(period), + enabled = VALUES(enabled), + description = VALUES(description), + updated_time = CURRENT_TIMESTAMP(3), + updated_by = VALUES(updated_by); +INSERT INTO base_sys_usage_scene + (id, object_type, object_id, usage_event, scene_name, source_app, enabled, description, created_by, updated_by) +SELECT REPLACE(UUID(), '-', ''), 'RATE_LIMIT_SCENE', scene_code, 'RATE_LIMIT_CHECK', + CONCAT(scene_name, '限次检查'), 'iqc-platform', enabled, description, 'system', 'system' +FROM base_sys_ratelimit_scene +WHERE scene_code LIKE 'iqc-%' +ON DUPLICATE KEY UPDATE scene_name = VALUES(scene_name), + source_app = VALUES(source_app), + enabled = VALUES(enabled), + description = VALUES(description), + updated_time = CURRENT_TIMESTAMP(3), + updated_by = VALUES(updated_by);