feat: add Go backend

This commit is contained in:
richjohnrambo
2026-10-10 20:56:17 +08:00
parent 50fcfd2d3d
commit f6024f0964
1040 changed files with 107169 additions and 0 deletions
@@ -0,0 +1,161 @@
-- S1 基础治理:审批、审计、幂等、Outbox 与看板汇总
-- MySQL 8.0+
CREATE TABLE IF NOT EXISTS `hg_approval_request` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`approval_no` varchar(32) NOT NULL COMMENT '审批单号',
`approval_type` varchar(32) NOT NULL COMMENT '审批类型',
`target_type` varchar(32) NOT NULL COMMENT '目标类型',
`target_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '目标ID',
`action` varchar(64) NOT NULL COMMENT '拟执行动作',
`title` varchar(200) NOT NULL COMMENT '审批标题',
`payload_json` json NOT NULL COMMENT '待执行数据快照',
`diff_json` json DEFAULT NULL COMMENT '前后差异',
`risk_level` tinyint NOT NULL DEFAULT 1 COMMENT '风险级别',
`required_approvals` int unsigned NOT NULL DEFAULT 1 COMMENT '需要通过数',
`approval_status` tinyint NOT NULL DEFAULT 1 COMMENT '审批状态',
`applicant_id` bigint unsigned NOT NULL COMMENT '申请人',
`submitted_at` datetime(3) DEFAULT NULL COMMENT '提交时间',
`decided_at` datetime(3) DEFAULT NULL COMMENT '决定时间',
`executed_at` datetime(3) DEFAULT NULL COMMENT '执行时间',
`expire_at` datetime(3) DEFAULT NULL COMMENT '超时时间',
`version` int unsigned NOT NULL DEFAULT 0 COMMENT '乐观锁',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_approval_no` (`approval_no`),
KEY `idx_approval_type_status` (`tenant_id`,`approval_type`,`approval_status`,`created_at`,`id`),
KEY `idx_approval_target` (`tenant_id`,`target_type`,`target_id`,`created_at`),
KEY `idx_approval_applicant` (`tenant_id`,`applicant_id`,`created_at`),
KEY `idx_approval_expire` (`approval_status`,`expire_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='治理_审批请求';
CREATE TABLE IF NOT EXISTS `hg_approval_action` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`approval_request_id` bigint unsigned NOT NULL COMMENT '审批请求ID',
`step_no` int unsigned NOT NULL COMMENT '节点顺序',
`actor_id` bigint unsigned NOT NULL COMMENT '操作人',
`action` tinyint NOT NULL COMMENT '审批动作',
`reason_code` varchar(64) DEFAULT NULL COMMENT '原因编码',
`comment` varchar(1000) DEFAULT NULL COMMENT '审批意见',
`snapshot_json` json NOT NULL COMMENT '操作时快照',
`actor_ip_cipher` varchar(512) DEFAULT NULL COMMENT '操作IP密文',
`mfa_verified` tinyint NOT NULL DEFAULT 0 COMMENT '是否二次认证',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_approval_step_actor` (`approval_request_id`,`step_no`,`actor_id`),
KEY `idx_approval_action_request` (`tenant_id`,`approval_request_id`,`created_at`),
KEY `idx_approval_action_actor` (`tenant_id`,`actor_id`,`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='治理_审批动作';
CREATE TABLE IF NOT EXISTS `hg_sensitive_access_log` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`access_no` varchar(32) NOT NULL COMMENT '查看流水号',
`actor_id` bigint unsigned NOT NULL COMMENT '管理员ID',
`target_type` varchar(32) NOT NULL COMMENT '目标类型',
`target_id` bigint unsigned NOT NULL COMMENT '目标ID',
`field_set` json NOT NULL COMMENT '查看字段集',
`purpose_code` varchar(64) NOT NULL COMMENT '用途编码',
`purpose_text` varchar(500) NOT NULL COMMENT '用途说明',
`authorization_no` varchar(64) DEFAULT NULL COMMENT '授权号',
`mfa_verified` tinyint NOT NULL DEFAULT 0 COMMENT '是否二次认证',
`result` tinyint NOT NULL COMMENT '查看结果',
`trace_id` varchar(64) NOT NULL COMMENT '链路ID',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_sensitive_access_no` (`access_no`),
KEY `idx_sensitive_actor` (`tenant_id`,`actor_id`,`created_at`),
KEY `idx_sensitive_target` (`tenant_id`,`target_type`,`target_id`,`created_at`),
KEY `idx_sensitive_trace` (`trace_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='治理_敏感数据查看日志';
CREATE TABLE IF NOT EXISTS `hg_biz_audit_log` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`audit_no` varchar(32) NOT NULL COMMENT '审计号',
`actor_type` tinyint NOT NULL COMMENT '操作人类型',
`actor_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '操作人ID',
`module` varchar(64) NOT NULL COMMENT '业务模块',
`action` varchar(64) NOT NULL COMMENT '操作动作',
`target_type` varchar(64) NOT NULL COMMENT '目标类型',
`target_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '目标ID',
`before_digest` char(64) DEFAULT NULL COMMENT '变更前摘要',
`after_digest` char(64) DEFAULT NULL COMMENT '变更后摘要',
`change_json` json DEFAULT NULL COMMENT '已脱敏差异',
`reason` varchar(500) DEFAULT NULL COMMENT '操作原因',
`approval_no` varchar(32) DEFAULT NULL COMMENT '审批单号',
`trace_id` varchar(64) NOT NULL COMMENT '链路ID',
`prev_hash` char(64) DEFAULT NULL COMMENT '前一条哈希',
`row_hash` char(64) NOT NULL COMMENT '当前行哈希',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_biz_audit_no` (`audit_no`),
KEY `idx_biz_audit_actor` (`tenant_id`,`actor_id`,`created_at`),
KEY `idx_biz_audit_target` (`tenant_id`,`target_type`,`target_id`,`created_at`),
KEY `idx_biz_audit_module` (`tenant_id`,`module`,`action`,`created_at`),
KEY `idx_biz_audit_trace` (`trace_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='治理_业务审计日志';
CREATE TABLE IF NOT EXISTS `hg_idempotency_record` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`scope` varchar(64) NOT NULL COMMENT '业务作用域',
`idempotency_key` varchar(128) NOT NULL COMMENT '幂等键',
`request_digest` char(64) NOT NULL COMMENT '请求摘要',
`resource_type` varchar(64) DEFAULT NULL COMMENT '资源类型',
`resource_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '资源ID',
`process_status` tinyint NOT NULL DEFAULT 1 COMMENT '处理状态',
`response_code` int DEFAULT NULL COMMENT '响应码',
`response_digest` char(64) DEFAULT NULL COMMENT '响应摘要',
`expire_at` datetime(3) NOT NULL COMMENT '过期时间',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_idempotency_scope_key` (`tenant_id`,`scope`,`idempotency_key`),
KEY `idx_idempotency_expire` (`expire_at`),
KEY `idx_idempotency_resource` (`tenant_id`,`resource_type`,`resource_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='治理_幂等记录';
CREATE TABLE IF NOT EXISTS `hg_outbox_event` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`event_no` varchar(32) NOT NULL COMMENT '事件号',
`aggregate_type` varchar(64) NOT NULL COMMENT '聚合根类型',
`aggregate_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '聚合根ID',
`event_type` varchar(128) NOT NULL COMMENT '事件类型',
`payload_json` json NOT NULL COMMENT '已脱敏事件数据',
`publish_status` tinyint NOT NULL DEFAULT 1 COMMENT '发送状态',
`retry_count` int unsigned NOT NULL DEFAULT 0 COMMENT '重试次数',
`next_retry_at` datetime(3) DEFAULT NULL COMMENT '下次重试时间',
`last_error` varchar(1000) DEFAULT NULL COMMENT '最后错误',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`published_at` datetime(3) DEFAULT NULL COMMENT '发送时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_outbox_event_no` (`event_no`),
KEY `idx_outbox_publish` (`publish_status`,`next_retry_at`,`id`),
KEY `idx_outbox_aggregate` (`tenant_id`,`aggregate_type`,`aggregate_id`,`created_at`),
KEY `idx_outbox_event_type` (`tenant_id`,`event_type`,`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='治理_事件出站箱';
CREATE TABLE IF NOT EXISTS `hg_dashboard_daily_stat` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`stat_date` date NOT NULL COMMENT '统计日期',
`dimension_type` varchar(32) NOT NULL COMMENT '维度类型',
`dimension_value` varchar(64) NOT NULL COMMENT '维度值',
`metric_code` varchar(64) NOT NULL COMMENT '指标编码',
`metric_count` bigint NOT NULL DEFAULT 0 COMMENT '指标数量',
`metric_amount` bigint NOT NULL DEFAULT 0 COMMENT '指标金额(最小货币单位)',
`calculated_at` datetime(3) NOT NULL COMMENT '计算时间',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_dashboard_metric` (`tenant_id`,`stat_date`,`dimension_type`,`dimension_value`,`metric_code`),
KEY `idx_dashboard_date_metric` (`tenant_id`,`stat_date`,`metric_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='治理_看板日汇总';
@@ -0,0 +1,50 @@
-- S1 基础治理菜单。重复执行安全;普通角色需在“角色权限”中勾选新菜单。
SET @now = NOW();
INSERT INTO `hg_admin_menu`
(`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT 0,1,'','基础治理','governance','/governance','AuditOutlined',1,'','','','LAYOUT',1,'',0,0,'',0,0,0,90,'审批、审计与安全治理',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='governance');
UPDATE `hg_admin_menu` SET `icon`='AuditOutlined', `updated_at`=@now WHERE `name`='governance';
SET @governanceId = (SELECT `id` FROM `hg_admin_menu` WHERE `name`='governance' LIMIT 1);
INSERT INTO `hg_admin_menu`
(`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @governanceId,2,CONCAT('tr_',@governanceId,' '),'审批中心','governance_approval','approval','',2,'','/approval/list','','/governance/approval/index',1,'',0,0,'',0,0,0,10,'高风险操作审批',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='governance_approval');
SET @approvalId = (SELECT `id` FROM `hg_admin_menu` WHERE `name`='governance_approval' LIMIT 1);
INSERT INTO `hg_admin_menu`
(`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @governanceId,2,CONCAT('tr_',@governanceId,' '),'业务审计','governance_biz_audit','biz-audit','',2,'','/bizAudit/list','','/governance/biz-audit/index',1,'',0,0,'',0,0,0,20,'不可变业务审计日志',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='governance_biz_audit');
SET @auditId = (SELECT `id` FROM `hg_admin_menu` WHERE `name`='governance_biz_audit' LIMIT 1);
INSERT INTO `hg_admin_menu`
(`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @approvalId,3,CONCAT('tr_',@governanceId,' tr_',@approvalId,' '),'审批详情','governance_approval_view','','',3,'','/approval/view','','',1,'',0,0,'',0,1,0,10,'',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='governance_approval_view');
INSERT INTO `hg_admin_menu`
(`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @approvalId,3,CONCAT('tr_',@governanceId,' tr_',@approvalId,' '),'创建审批','governance_approval_create','','',3,'','/approval/create','','',1,'',0,0,'',0,1,0,20,'',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='governance_approval_create');
INSERT INTO `hg_admin_menu`
(`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @approvalId,3,CONCAT('tr_',@governanceId,' tr_',@approvalId,' '),'提交审批','governance_approval_submit','','',3,'','/approval/submit','','',1,'',0,0,'',0,1,0,30,'',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='governance_approval_submit');
INSERT INTO `hg_admin_menu`
(`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @approvalId,3,CONCAT('tr_',@governanceId,' tr_',@approvalId,' '),'通过审批','governance_approval_approve','','',3,'','/approval/approve','','',1,'',0,0,'',0,1,0,40,'',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='governance_approval_approve');
INSERT INTO `hg_admin_menu`
(`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @approvalId,3,CONCAT('tr_',@governanceId,' tr_',@approvalId,' '),'驳回审批','governance_approval_reject','','',3,'','/approval/reject','','',1,'',0,0,'',0,1,0,50,'',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='governance_approval_reject');
INSERT INTO `hg_admin_menu`
(`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @approvalId,3,CONCAT('tr_',@governanceId,' tr_',@approvalId,' '),'取消审批','governance_approval_cancel','','',3,'','/approval/cancel','','',1,'',0,0,'',0,1,0,60,'',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='governance_approval_cancel');
INSERT INTO `hg_admin_menu`
(`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @auditId,3,CONCAT('tr_',@governanceId,' tr_',@auditId,' '),'审计详情','governance_biz_audit_view','','',3,'','/bizAudit/view','','',1,'',0,0,'',0,1,0,10,'',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='governance_biz_audit_view');
@@ -0,0 +1,25 @@
-- 首页业务看板接口与敏感金额权限。
SET @now = NOW();
UPDATE `hg_admin_menu`
SET `title`='主页', `icon`='HomeOutlined', `redirect`='/dashboard/console', `sort`=10, `updated_at`=@now
WHERE `name`='Dashboard';
UPDATE `hg_admin_menu`
SET `title`='首页', `icon`='DashboardOutlined', `permissions`='/console/stat,/dashboard/summary', `sort`=10, `updated_at`=@now
WHERE `name`='dashboard_console';
UPDATE `hg_admin_menu`
SET `hidden`=1, `updated_at`=@now
WHERE `name`='dashboard_workplace';
SET @dashboardId = (SELECT `id` FROM `hg_admin_menu` WHERE `name`='dashboard_console' LIMIT 1);
SET @dashboardPid = (SELECT `pid` FROM `hg_admin_menu` WHERE `id`=@dashboardId LIMIT 1);
INSERT INTO `hg_admin_menu`
(`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @dashboardId,3,CONCAT('tr_',@dashboardPid,' tr_',@dashboardId,' '),'查看看板金额','dashboard_amount_view','','',3,'','/dashboard/amount','','',1,'',0,0,'',0,1,0,10,'控制首页资金指标、趋势金额和渠道金额可见性',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='dashboard_amount_view');
SET @amountMenuId = (SELECT `id` FROM `hg_admin_menu` WHERE `name`='dashboard_amount_view' LIMIT 1);
INSERT IGNORE INTO `hg_admin_role_menu` (`role_id`,`menu_id`)
SELECT `id`, @amountMenuId FROM `hg_admin_role` WHERE `key`='finance';
@@ -0,0 +1,220 @@
-- 第五章:门户、内容、Banner 与手工商城。
-- MySQL 8.0+
CREATE TABLE IF NOT EXISTS `hg_site_config_version` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`config_no` varchar(32) NOT NULL COMMENT '配置版本号',
`config_group` varchar(64) NOT NULL COMMENT '配置组',
`schema_version` varchar(32) NOT NULL DEFAULT '1.0' COMMENT 'Schema版本',
`config_json` json NOT NULL COMMENT '完整配置快照',
`config_digest` char(64) NOT NULL COMMENT '配置摘要',
`publish_status` tinyint NOT NULL DEFAULT 1 COMMENT '发布状态',
`effective_at` datetime(3) DEFAULT NULL COMMENT '计划生效时间',
`published_at` datetime(3) DEFAULT NULL COMMENT '实际发布时间',
`approval_request_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '审批单ID',
`base_version_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '基础版本ID',
`version` int unsigned NOT NULL DEFAULT 0 COMMENT '乐观锁',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_site_config_no` (`tenant_id`,`config_no`),
KEY `idx_site_config_current` (`tenant_id`,`config_group`,`publish_status`,`effective_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='门户_站点配置版本';
CREATE TABLE IF NOT EXISTS `hg_content` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`content_key` varchar(64) NOT NULL COMMENT '稳定内容标识',
`content_type` varchar(32) NOT NULL COMMENT '内容类型',
`title` varchar(200) NOT NULL COMMENT '后台标题',
`published_version_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '当前发布版本ID',
`publish_status` tinyint NOT NULL DEFAULT 1 COMMENT '发布状态',
`published_at` datetime(3) DEFAULT NULL COMMENT '发布时间',
`sort` int NOT NULL DEFAULT 0 COMMENT '排序',
`version` int unsigned NOT NULL DEFAULT 0 COMMENT '乐观锁',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`deleted_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '删除者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
`deleted_at` datetime(3) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_content_key` (`tenant_id`,`content_key`),
KEY `idx_content_type_status` (`tenant_id`,`content_type`,`publish_status`,`sort`,`id`),
KEY `idx_content_deleted` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='门户_文本内容';
CREATE TABLE IF NOT EXISTS `hg_content_version` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`content_id` bigint unsigned NOT NULL COMMENT '内容ID',
`version_no` int unsigned NOT NULL COMMENT '版本号',
`title` varchar(200) NOT NULL COMMENT '展示标题',
`summary` varchar(500) DEFAULT NULL COMMENT '摘要',
`body_html` longtext NOT NULL COMMENT '清洗后HTML',
`body_text` longtext COMMENT '降级文本',
`cover_url` varchar(1000) DEFAULT NULL COMMENT '封面图片URL',
`asset_ids` json DEFAULT NULL COMMENT '引用附件ID',
`publish_status` tinyint NOT NULL DEFAULT 1 COMMENT '发布状态',
`effective_at` datetime(3) DEFAULT NULL COMMENT '计划生效时间',
`approval_request_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '审批单ID',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_content_version` (`content_id`,`version_no`),
KEY `idx_content_version_status` (`tenant_id`,`content_id`,`publish_status`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='门户_文本内容版本';
CREATE TABLE IF NOT EXISTS `hg_banner` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`name` varchar(100) NOT NULL COMMENT '后台名称',
`position` varchar(32) NOT NULL DEFAULT 'home_top' COMMENT '投放位置',
`image_attachment_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '图片附件ID',
`image_url` varchar(1000) NOT NULL COMMENT '图片URL',
`alt_text` varchar(200) NOT NULL COMMENT '替代文本',
`target_type` tinyint NOT NULL DEFAULT 1 COMMENT '跳转类型',
`target_value` varchar(500) DEFAULT NULL COMMENT '跳转值',
`start_at` datetime(3) DEFAULT NULL COMMENT '开始时间',
`end_at` datetime(3) DEFAULT NULL COMMENT '结束时间',
`publish_status` tinyint NOT NULL DEFAULT 1 COMMENT '发布状态',
`sort` int NOT NULL DEFAULT 0 COMMENT '排序',
`version` int unsigned NOT NULL DEFAULT 0 COMMENT '乐观锁',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`deleted_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '删除者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
`deleted_at` datetime(3) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`),
KEY `idx_banner_delivery` (`tenant_id`,`position`,`publish_status`,`start_at`,`end_at`,`sort`),
KEY `idx_banner_deleted` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='门户_Banner';
CREATE TABLE IF NOT EXISTS `hg_product` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`product_no` varchar(32) NOT NULL COMMENT '商品编号',
`category_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '分类ID',
`product_type` tinyint NOT NULL DEFAULT 2 COMMENT '商品类型',
`payment_type` varchar(32) NOT NULL DEFAULT 'balance' COMMENT '支付方式',
`name` varchar(200) NOT NULL COMMENT '商品名称',
`shop_name` varchar(100) NOT NULL DEFAULT '' COMMENT '店铺名称',
`price_amount` bigint NOT NULL DEFAULT 0 COMMENT '单价(分)',
`currency` char(3) NOT NULL DEFAULT 'CNY' COMMENT '币种',
`cover_attachment_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '封面附件ID',
`cover_url` varchar(1000) NOT NULL COMMENT '封面URL',
`detail_html` longtext COMMENT '商品详情',
`is_recommended` tinyint NOT NULL DEFAULT 2 COMMENT '是否推荐',
`publish_status` tinyint NOT NULL DEFAULT 1 COMMENT '发布状态',
`start_at` datetime(3) DEFAULT NULL COMMENT '展示开始时间',
`end_at` datetime(3) DEFAULT NULL COMMENT '展示结束时间',
`sort` int NOT NULL DEFAULT 0 COMMENT '排序',
`version` int unsigned NOT NULL DEFAULT 0 COMMENT '乐观锁',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`deleted_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '删除者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
`deleted_at` datetime(3) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_product_no` (`tenant_id`,`product_no`),
KEY `idx_product_manual` (`tenant_id`,`product_type`,`publish_status`,`sort`,`id`),
KEY `idx_product_deleted` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商城_商品';
-- 复用 HotGo 数据库字典:内容类型。
INSERT INTO `hg_sys_dict_type` (`name`,`type`,`remark`,`status`,`created_at`,`updated_at`)
SELECT '内容类型','content_type','门户文本内容分类',1,NOW(),NOW()
WHERE NOT EXISTS (SELECT 1 FROM `hg_sys_dict_type` WHERE `type`='content_type');
INSERT INTO `hg_sys_dict_data` (`type`,`label`,`value`,`value_type`,`list_class`,`sort`,`status`,`remark`,`created_at`,`updated_at`)
SELECT 'content_type',x.label,x.value,'string',x.list_class,x.sort,1,'门户内容类型',NOW(),NOW()
FROM (
SELECT '平台公告' label,'notice' value,'primary' list_class,10 sort UNION ALL
SELECT '平台简介','about','info',20 UNION ALL
SELECT '订单规则','rule','warning',30 UNION ALL
SELECT '常见问题','faq','success',40 UNION ALL
SELECT '使用指南','guide','default',50 UNION ALL
SELECT '利息宝规则','interest_rule','warning',60 UNION ALL
SELECT '首页滚动','home_ticker','primary',70 UNION ALL
SELECT '订单提示','order_tip','warning',80 UNION ALL
SELECT '活动内容','activity','success',90 UNION ALL
SELECT '首页弹窗','popup','error',100 UNION ALL
SELECT '公司资质','qualification','info',110
) x
WHERE NOT EXISTS (SELECT 1 FROM `hg_sys_dict_data` d WHERE d.`type`='content_type' AND d.`value`=x.value);
-- 菜单和接口权限。菜单由数据库驱动,重复执行不会生成重复数据。
SET @now = NOW();
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT 0,1,'','门户管理','portal','/portal','HomeOutlined',1,'','','','LAYOUT',1,'',1,0,'',0,0,0,30,'门户、文本、Banner和手工商城',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='portal');
SET @portalId=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='portal' LIMIT 1);
SET @homeId=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='Dashboard' LIMIT 1);
-- 门户能力合并到“主页”,保留原 /portal/* 地址,仅调整菜单归属。
UPDATE `hg_admin_menu` SET `hidden`=1, `status`=2, `updated_at`=@now WHERE `name`='portal';
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @homeId,2,CONCAT('tr_',@homeId,' '),'网站设置','portal_site_config','/portal/site-config','SettingOutlined',2,'','/siteConfig/current,/siteConfig/history','','/portal/site-config/index',1,'',0,0,'',1,0,0,20,'版本化站点配置',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='portal_site_config');
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @homeId,2,CONCAT('tr_',@homeId,' '),'文本管理','portal_content','/portal/content','FileTextOutlined',2,'','/portalContent/list,/portalContent/view','','/portal/content/index',1,'',0,0,'',1,0,0,30,'版本化文本内容',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='portal_content');
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @homeId,2,CONCAT('tr_',@homeId,' '),'Banner 设置','portal_banner','/portal/banner','PictureOutlined',2,'','/banner/list,/banner/view','','/portal/banner/index',1,'',0,0,'',1,0,0,40,'首页Banner',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='portal_banner');
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @homeId,2,CONCAT('tr_',@homeId,' '),'手工商城','portal_manual_product','/portal/manual-product','ShoppingOutlined',2,'','/manualProduct/list,/manualProduct/view','','/portal/manual-product/index',1,'',0,0,'',1,0,0,50,'手工商城商品',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='portal_manual_product');
UPDATE `hg_admin_menu`
SET `pid`=@homeId, `level`=2, `tree`=CONCAT('tr_',@homeId,' '),
`path`=CASE `name`
WHEN 'portal_site_config' THEN '/portal/site-config'
WHEN 'portal_content' THEN '/portal/content'
WHEN 'portal_banner' THEN '/portal/banner'
WHEN 'portal_manual_product' THEN '/portal/manual-product'
END,
`sort`=CASE `name`
WHEN 'portal_site_config' THEN 20 WHEN 'portal_content' THEN 30
WHEN 'portal_banner' THEN 40 WHEN 'portal_manual_product' THEN 50
END,
`updated_at`=@now
WHERE `name` IN ('portal_site_config','portal_content','portal_banner','portal_manual_product');
SET @siteMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='portal_site_config' LIMIT 1);
SET @contentMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='portal_content' LIMIT 1);
SET @bannerMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='portal_banner' LIMIT 1);
SET @productMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='portal_manual_product' LIMIT 1);
UPDATE `hg_admin_menu`
SET `tree`=CONCAT('tr_',@homeId,' tr_',`pid`,' '), `updated_at`=@now
WHERE `pid` IN (@siteMenu,@contentMenu,@bannerMenu,@productMenu) AND `level`=3;
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @siteMenu,3,CONCAT('tr_',@homeId,' tr_',@siteMenu,' '),x.title,x.name,'','',3,'',x.permissions,'','',1,'',0,0,'',0,1,0,x.sort,'网站设置操作权限',1,@now,@now FROM (
SELECT '保存配置草稿' title,'portal_site_save' name,'/siteConfig/save' permissions,10 sort UNION ALL SELECT '提交配置审批','portal_site_submit','/siteConfig/submit',20 UNION ALL SELECT '发布配置','portal_site_publish','/siteConfig/publish',30 UNION ALL SELECT '回滚配置','portal_site_rollback','/siteConfig/rollback',40
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` m WHERE m.`name`=x.name);
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @contentMenu,3,CONCAT('tr_',@homeId,' tr_',@contentMenu,' '),x.title,x.name,'','',3,'',x.permissions,'','',1,'',0,0,'',0,1,0,x.sort,'文本管理操作权限',1,@now,@now FROM (
SELECT '编辑文本' title,'portal_content_edit' name,'/portalContent/edit' permissions,10 sort UNION ALL SELECT '发布文本','portal_content_publish','/portalContent/publish',20 UNION ALL SELECT '下线文本','portal_content_offline','/portalContent/offline',30 UNION ALL SELECT '删除文本','portal_content_delete','/portalContent/delete',40
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` m WHERE m.`name`=x.name);
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @bannerMenu,3,CONCAT('tr_',@homeId,' tr_',@bannerMenu,' '),x.title,x.name,'','',3,'',x.permissions,'','',1,'',0,0,'',0,1,0,x.sort,'Banner操作权限',1,@now,@now FROM (
SELECT '编辑 Banner' title,'portal_banner_edit' name,'/banner/edit' permissions,10 sort UNION ALL SELECT '发布下线 Banner','portal_banner_status','/banner/status',20 UNION ALL SELECT '删除 Banner','portal_banner_delete','/banner/delete',30
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` m WHERE m.`name`=x.name);
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @productMenu,3,CONCAT('tr_',@homeId,' tr_',@productMenu,' '),x.title,x.name,'','',3,'',x.permissions,'','',1,'',0,0,'',0,1,0,x.sort,'手工商城操作权限',1,@now,@now FROM (
SELECT '编辑商品' title,'portal_product_edit' name,'/manualProduct/edit' permissions,10 sort UNION ALL SELECT '上下架商品','portal_product_status','/manualProduct/status',20 UNION ALL SELECT '删除商品','portal_product_delete','/manualProduct/delete',30
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` m WHERE m.`name`=x.name);
INSERT IGNORE INTO `hg_admin_role_menu` (`role_id`,`menu_id`)
SELECT r.id,m.id FROM `hg_admin_role` r JOIN `hg_admin_menu` m ON m.name IN ('Dashboard','dashboard_console','portal_site_config','portal_content','portal_banner','portal_manual_product','portal_site_save','portal_site_submit','portal_site_publish','portal_site_rollback','portal_content_edit','portal_content_publish','portal_content_offline','portal_content_delete','portal_banner_edit','portal_banner_status','portal_banner_delete','portal_product_edit','portal_product_status','portal_product_delete') WHERE r.`key` IN ('manage','business');
@@ -0,0 +1,281 @@
-- 第六章:会员、敏感资料、团队、钱包调账与会员通知。
-- MySQL 8.0+;金额统一使用分,敏感字段仅保存密文、检索哈希和脱敏值。
CREATE TABLE IF NOT EXISTS `hg_app_member` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`member_no` varchar(32) NOT NULL COMMENT '会员编号',
`username` varchar(64) NOT NULL COMMENT '用户名',
`mobile_cipher` text NOT NULL COMMENT '手机号密文(AES-GCM)',
`mobile_hash` char(64) NOT NULL COMMENT '手机号检索哈希(HMAC-SHA256)',
`mobile_mask` varchar(32) NOT NULL COMMENT '手机号脱敏值',
`password_hash` varchar(100) NOT NULL COMMENT '登录密码哈希(bcrypt)',
`trade_password_hash` varchar(100) NOT NULL DEFAULT '' COMMENT '交易密码哈希',
`level_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '会员等级ID',
`parent_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '上级会员ID',
`level` int NOT NULL DEFAULT 1 COMMENT '团队层级',
`tree` varchar(512) NOT NULL DEFAULT '' COMMENT '关系树',
`invite_code` varchar(32) NOT NULL COMMENT '邀请码',
`member_status` tinyint NOT NULL DEFAULT 1 COMMENT '会员状态',
`risk_status` tinyint NOT NULL DEFAULT 1 COMMENT '风控状态',
`auto_dispatch` tinyint NOT NULL DEFAULT 2 COMMENT '自动派单',
`credit_score` int NOT NULL DEFAULT 100 COMMENT '信用分',
`is_test_account` tinyint NOT NULL DEFAULT 2 COMMENT '测试账号',
`last_login_at` datetime(3) DEFAULT NULL COMMENT '最后登录时间',
`last_login_ip_cipher` text COMMENT '最后登录IP密文',
`last_login_ip_mask` varchar(64) NOT NULL DEFAULT '' COMMENT '最后登录IP脱敏值',
`last_login_region` varchar(128) NOT NULL DEFAULT '' COMMENT '最后登录地区',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`deleted_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '删除者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
`deleted_at` datetime(3) DEFAULT NULL COMMENT '注销时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_app_member_no` (`tenant_id`,`member_no`),
UNIQUE KEY `uk_app_member_username` (`tenant_id`,`username`),
UNIQUE KEY `uk_app_member_mobile_hash` (`tenant_id`,`mobile_hash`),
UNIQUE KEY `uk_app_member_invite_code` (`tenant_id`,`invite_code`),
KEY `idx_app_member_team` (`tenant_id`,`parent_id`,`level`,`created_at`),
KEY `idx_app_member_status` (`tenant_id`,`member_status`,`auto_dispatch`,`created_at`),
KEY `idx_app_member_deleted` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员_会员主档';
CREATE TABLE IF NOT EXISTS `hg_app_member_profile` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`member_id` bigint unsigned NOT NULL COMMENT '会员ID',
`real_name_cipher` text COMMENT '真实姓名密文',
`real_name_mask` varchar(64) NOT NULL DEFAULT '' COMMENT '真实姓名脱敏值',
`id_no_cipher` text COMMENT '证件号密文',
`id_no_hash` char(64) NOT NULL DEFAULT '' COMMENT '证件号检索哈希',
`id_no_mask` varchar(64) NOT NULL DEFAULT '' COMMENT '证件号脱敏值',
`avatar_attachment_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '头像附件ID',
`kyc_status` tinyint NOT NULL DEFAULT 1 COMMENT '实名状态',
`kyc_verified_at` datetime(3) DEFAULT NULL COMMENT '实名时间',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_member_profile_member` (`tenant_id`,`member_id`),
KEY `idx_member_profile_id_hash` (`tenant_id`,`id_no_hash`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员_扩展资料';
CREATE TABLE IF NOT EXISTS `hg_app_member_address` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`member_id` bigint unsigned NOT NULL COMMENT '会员ID',
`receiver_cipher` text NOT NULL COMMENT '收货人密文',
`receiver_mask` varchar(64) NOT NULL COMMENT '收货人脱敏值',
`mobile_cipher` text NOT NULL COMMENT '手机号密文',
`mobile_mask` varchar(32) NOT NULL COMMENT '手机号脱敏值',
`province` varchar(64) NOT NULL DEFAULT '' COMMENT '省',
`city` varchar(64) NOT NULL DEFAULT '' COMMENT '市',
`district` varchar(64) NOT NULL DEFAULT '' COMMENT '区县',
`address_cipher` text NOT NULL COMMENT '详细地址密文',
`address_mask` varchar(255) NOT NULL COMMENT '详细地址脱敏值',
`is_default` tinyint NOT NULL DEFAULT 2 COMMENT '默认地址',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`deleted_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '删除者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
`deleted_at` datetime(3) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`),
KEY `idx_member_address_member` (`tenant_id`,`member_id`,`is_default`,`id`),
KEY `idx_member_address_deleted` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员_收货地址';
CREATE TABLE IF NOT EXISTS `hg_app_member_payment_account` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`member_id` bigint unsigned NOT NULL COMMENT '会员ID',
`account_type` tinyint NOT NULL COMMENT '账户类型',
`bank_code` varchar(32) NOT NULL DEFAULT '' COMMENT '银行编码',
`bank_name` varchar(100) NOT NULL DEFAULT '' COMMENT '银行名称',
`holder_cipher` text NOT NULL COMMENT '持有人密文',
`holder_mask` varchar(64) NOT NULL COMMENT '持有人脱敏值',
`mobile_cipher` text COMMENT '预留手机号密文',
`mobile_mask` varchar(32) NOT NULL DEFAULT '' COMMENT '预留手机号脱敏值',
`account_no_cipher` text NOT NULL COMMENT '账号密文',
`account_no_hash` char(64) NOT NULL COMMENT '账号检索哈希',
`account_no_mask` varchar(80) NOT NULL COMMENT '账号脱敏值',
`qr_attachment_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '收款码附件ID',
`verify_status` tinyint NOT NULL DEFAULT 1 COMMENT '核验状态',
`is_default` tinyint NOT NULL DEFAULT 2 COMMENT '默认账户',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`deleted_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '删除者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
`deleted_at` datetime(3) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_member_payment_account` (`tenant_id`,`member_id`,`account_type`,`account_no_hash`),
KEY `idx_member_payment_member` (`tenant_id`,`member_id`,`is_default`,`id`),
KEY `idx_member_payment_deleted` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员_收款账户';
CREATE TABLE IF NOT EXISTS `hg_app_member_status_log` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`member_id` bigint unsigned NOT NULL COMMENT '会员ID',
`from_status` tinyint NOT NULL COMMENT '原状态',
`to_status` tinyint NOT NULL COMMENT '目标状态',
`reason_code` varchar(64) NOT NULL COMMENT '原因编码',
`reason_text` varchar(500) NOT NULL COMMENT '原因说明',
`effective_at` datetime(3) NOT NULL COMMENT '生效时间',
`expire_at` datetime(3) DEFAULT NULL COMMENT '失效时间',
`approval_request_id` bigint unsigned NOT NULL COMMENT '审批单ID',
`operator_id` bigint unsigned NOT NULL COMMENT '执行人',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `idx_member_status_log` (`tenant_id`,`member_id`,`id`),
UNIQUE KEY `uk_member_status_approval` (`tenant_id`,`approval_request_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员_状态变更日志';
CREATE TABLE IF NOT EXISTS `hg_wallet_account` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`member_id` bigint unsigned NOT NULL COMMENT '会员ID',
`currency` char(3) NOT NULL DEFAULT 'CNY' COMMENT '币种',
`available_amount` bigint NOT NULL DEFAULT 0 COMMENT '可用金额(分)',
`frozen_amount` bigint NOT NULL DEFAULT 0 COMMENT '冻结金额(分)',
`total_income` bigint NOT NULL DEFAULT 0 COMMENT '累计收入(分)',
`total_expense` bigint NOT NULL DEFAULT 0 COMMENT '累计支出(分)',
`account_status` tinyint NOT NULL DEFAULT 1 COMMENT '账户状态',
`version` int unsigned NOT NULL DEFAULT 0 COMMENT '乐观锁',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_wallet_member_currency` (`tenant_id`,`member_id`,`currency`),
CONSTRAINT `chk_wallet_available_nonnegative` CHECK (`available_amount` >= 0),
CONSTRAINT `chk_wallet_frozen_nonnegative` CHECK (`frozen_amount` >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='钱包_会员账户';
CREATE TABLE IF NOT EXISTS `hg_wallet_ledger` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`ledger_no` varchar(40) NOT NULL COMMENT '账变流水号',
`account_id` bigint unsigned NOT NULL COMMENT '钱包账户ID',
`member_id` bigint unsigned NOT NULL COMMENT '会员ID',
`biz_type` varchar(32) NOT NULL COMMENT '业务类型',
`biz_no` varchar(64) NOT NULL COMMENT '业务单号',
`entry_type` varchar(32) NOT NULL COMMENT '账变类型',
`direction` tinyint NOT NULL COMMENT '方向 1收入 2支出',
`amount` bigint NOT NULL COMMENT '发生金额(分)',
`before_amount` bigint NOT NULL COMMENT '变更前余额(分)',
`after_amount` bigint NOT NULL COMMENT '变更后余额(分)',
`currency` char(3) NOT NULL DEFAULT 'CNY' COMMENT '币种',
`reversal_of` bigint unsigned NOT NULL DEFAULT 0 COMMENT '冲正原流水ID',
`idempotency_key` varchar(80) NOT NULL COMMENT '幂等键',
`remark` varchar(500) NOT NULL DEFAULT '' COMMENT '说明',
`operator_id` bigint unsigned NOT NULL COMMENT '操作人',
`occurred_at` datetime(3) NOT NULL COMMENT '发生时间',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_wallet_ledger_no` (`tenant_id`,`ledger_no`),
UNIQUE KEY `uk_wallet_ledger_idempotency` (`tenant_id`,`account_id`,`idempotency_key`),
KEY `idx_wallet_ledger_member` (`tenant_id`,`member_id`,`occurred_at`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='钱包_不可变账变流水';
CREATE TABLE IF NOT EXISTS `hg_wallet_adjustment_request` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`request_no` varchar(40) NOT NULL COMMENT '申请单号',
`member_id` bigint unsigned NOT NULL COMMENT '会员ID',
`account_id` bigint unsigned NOT NULL COMMENT '钱包账户ID',
`adjust_type` tinyint NOT NULL COMMENT '调整类型',
`direction` tinyint NOT NULL COMMENT '方向 1收入 2支出',
`amount` bigint NOT NULL COMMENT '金额(分)',
`reason_code` varchar(64) NOT NULL COMMENT '原因编码',
`reason_text` varchar(500) NOT NULL COMMENT '原因说明',
`evidence_json` json DEFAULT NULL COMMENT '凭证附件',
`idempotency_key` varchar(80) NOT NULL COMMENT '幂等键',
`request_status` tinyint NOT NULL DEFAULT 1 COMMENT '状态 1待审批 2已通过 3已拒绝 4已执行',
`approval_request_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '审批单ID',
`ledger_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '账变流水ID',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_wallet_adjustment_no` (`tenant_id`,`request_no`),
UNIQUE KEY `uk_wallet_adjustment_idempotency` (`tenant_id`,`idempotency_key`),
KEY `idx_wallet_adjustment_member` (`tenant_id`,`member_id`,`request_status`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='钱包_调账申请';
CREATE TABLE IF NOT EXISTS `hg_app_member_notice` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`member_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '会员ID,0为全体',
`title` varchar(120) NOT NULL COMMENT '标题',
`content` varchar(500) NOT NULL COMMENT '内容',
`source_type` tinyint NOT NULL DEFAULT 1 COMMENT '来源 1真实通知 2运营模拟',
`start_at` datetime(3) NOT NULL COMMENT '开始时间',
`end_at` datetime(3) NOT NULL COMMENT '结束时间',
`notice_status` tinyint NOT NULL DEFAULT 1 COMMENT '状态 1有效 2撤回',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_member_notice_delivery` (`tenant_id`,`member_id`,`notice_status`,`start_at`,`end_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员_通知与运营弹幕';
-- 复用 HotGo 原有数据库字典。
INSERT INTO `hg_sys_dict_type` (`name`,`type`,`remark`,`status`,`created_at`,`updated_at`)
SELECT x.name,x.type,x.remark,1,NOW(),NOW() FROM (
SELECT '会员禁用原因' name,'member_disable_reason' type,'会员状态变更原因' remark UNION ALL
SELECT '钱包调账原因','wallet_adjust_reason','资金调账原因'
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_sys_dict_type` d WHERE d.`type`=x.type);
INSERT INTO `hg_sys_dict_data` (`type`,`label`,`value`,`value_type`,`list_class`,`sort`,`status`,`remark`,`created_at`,`updated_at`)
SELECT x.type,x.label,x.value,'string',x.list_class,x.sort,1,x.remark,NOW(),NOW() FROM (
SELECT 'member_disable_reason' type,'风控处置' label,'risk_control' value,'error' list_class,10 sort,'会员禁用原因' remark UNION ALL
SELECT 'member_disable_reason','用户申请','user_request','warning',20,'会员禁用原因' UNION ALL
SELECT 'member_disable_reason','违规行为','violation','error',30,'会员禁用原因' UNION ALL
SELECT 'wallet_adjust_reason','活动奖励','campaign_reward','success',10,'资金调账原因' UNION ALL
SELECT 'wallet_adjust_reason','人工补账','manual_supplement','primary',20,'资金调账原因' UNION ALL
SELECT 'wallet_adjust_reason','差错扣回','error_deduction','error',30,'资金调账原因' UNION ALL
SELECT 'wallet_adjust_reason','冲正处理','reversal','warning',40,'资金调账原因'
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_sys_dict_data` d WHERE d.`type`=x.type AND d.`value`=x.value);
-- 会员管理菜单与接口权限。
SET @now=NOW();
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT 0,1,'','会员管理','app_member','/app-member','UserOutlined',1,'','','','LAYOUT',1,'',1,0,'',0,0,0,40,'会员、团队、收款账户与钱包治理',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='app_member');
SET @memberRoot=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='app_member' LIMIT 1);
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @memberRoot,2,CONCAT('tr_',@memberRoot,' '),x.title,x.name,x.path,x.icon,2,'',x.permissions,'',x.component,1,'',0,0,'',1,0,0,x.sort,x.remark,1,@now,@now FROM (
SELECT '会员列表' title,'app_member_list' name,'list' path,'TeamOutlined' icon,'/appMember/list,/appMember/view' permissions,'/app-member/list/index' component,10 sort,'会员主档与关联资料' remark UNION ALL
SELECT '资金调账' ,'app_member_wallet','wallet','WalletOutlined','/appMember/walletList','/app-member/wallet/index',20,'审批驱动的会员钱包调账' UNION ALL
SELECT '会员通知' ,'app_member_notice','notice','NotificationOutlined','/appMember/noticeList','/app-member/notice/index',30,'真实通知与运营模拟明确标识'
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` m WHERE m.`name`=x.name);
SET @memberMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='app_member_list' LIMIT 1);
SET @walletMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='app_member_wallet' LIMIT 1);
SET @noticeMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='app_member_notice' LIMIT 1);
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT x.pid,3,x.tree,x.title,x.name,'','',3,'',x.permissions,'','',1,'',0,0,'',0,1,0,x.sort,'会员管理操作权限',1,@now,@now FROM (
SELECT @memberMenu pid,CONCAT('tr_',@memberRoot,' tr_',@memberMenu,' ') tree,'新增编辑会员' title,'app_member_edit' name,'/appMember/edit' permissions,10 sort UNION ALL
SELECT @memberMenu,CONCAT('tr_',@memberRoot,' tr_',@memberMenu,' '),'注销会员','app_member_delete','/appMember/delete',20 UNION ALL
SELECT @memberMenu,CONCAT('tr_',@memberRoot,' tr_',@memberMenu,' '),'自动派单开关','app_member_dispatch','/appMember/autoDispatch',30 UNION ALL
SELECT @memberMenu,CONCAT('tr_',@memberRoot,' tr_',@memberMenu,' '),'收款账户管理','app_member_payment','/appMember/paymentList,/appMember/paymentEdit,/appMember/paymentDelete',40 UNION ALL
SELECT @memberMenu,CONCAT('tr_',@memberRoot,' tr_',@memberMenu,' '),'地址管理','app_member_address','/appMember/addressList,/appMember/addressEdit,/appMember/addressDelete',50 UNION ALL
SELECT @memberMenu,CONCAT('tr_',@memberRoot,' tr_',@memberMenu,' '),'查看敏感信息','app_member_sensitive','/appMember/sensitive',60 UNION ALL
SELECT @memberMenu,CONCAT('tr_',@memberRoot,' tr_',@memberMenu,' '),'团队查询','app_member_team','/appMember/team',70 UNION ALL
SELECT @memberMenu,CONCAT('tr_',@memberRoot,' tr_',@memberMenu,' '),'禁用申请','app_member_status_request','/appMember/statusRequest',80 UNION ALL
SELECT @memberMenu,CONCAT('tr_',@memberRoot,' tr_',@memberMenu,' '),'执行会员状态','app_member_status_execute','/appMember/statusExecute',90 UNION ALL
SELECT @walletMenu,CONCAT('tr_',@memberRoot,' tr_',@walletMenu,' '),'发起资金调账','app_member_wallet_request','/appMember/walletRequest',10 UNION ALL
SELECT @walletMenu,CONCAT('tr_',@memberRoot,' tr_',@walletMenu,' '),'执行资金调账','app_member_wallet_execute','/appMember/walletExecute',20 UNION ALL
SELECT @noticeMenu,CONCAT('tr_',@memberRoot,' tr_',@noticeMenu,' '),'创建会员通知','app_member_notice_edit','/appMember/noticeEdit',10 UNION ALL
SELECT @noticeMenu,CONCAT('tr_',@memberRoot,' tr_',@noticeMenu,' '),'撤回会员通知','app_member_notice_revoke','/appMember/noticeRevoke',20
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` m WHERE m.`name`=x.name);
INSERT IGNORE INTO `hg_admin_role_menu` (`role_id`,`menu_id`)
SELECT r.id,m.id FROM `hg_admin_role` r JOIN `hg_admin_menu` m ON m.name IN (
'app_member','app_member_list','app_member_wallet','app_member_notice','app_member_edit','app_member_delete','app_member_dispatch','app_member_payment','app_member_address','app_member_sensitive','app_member_team','app_member_status_request','app_member_status_execute','app_member_wallet_request','app_member_wallet_execute','app_member_notice_edit','app_member_notice_revoke'
) WHERE r.`key` IN ('manage','business');
@@ -0,0 +1,119 @@
-- 第七章:会员等级与任务大厅。
-- 金额使用分,比例使用万分比;会员等级规则采用不可变版本发布。
CREATE TABLE IF NOT EXISTS `hg_app_member_level` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`level_code` varchar(32) NOT NULL COMMENT '稳定等级编码',
`name` varchar(64) NOT NULL COMMENT '等级名称',
`icon_attachment_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '图标附件ID',
`icon_url` varchar(1000) NOT NULL DEFAULT '' COMMENT '图标URL',
`current_version_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '当前发布版本ID',
`member_count` bigint unsigned NOT NULL DEFAULT 0 COMMENT '会员数(可重建)',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态 1正常 2停用',
`sort` int NOT NULL DEFAULT 0 COMMENT '排序',
`remark` varchar(500) NOT NULL DEFAULT '' COMMENT '备注',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`deleted_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '删除者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
`deleted_at` datetime(3) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_member_level_code` (`tenant_id`,`level_code`),
UNIQUE KEY `uk_member_level_name` (`tenant_id`,`name`),
KEY `idx_member_level_status` (`tenant_id`,`status`,`sort`,`id`),
KEY `idx_member_level_deleted` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员_会员等级';
CREATE TABLE IF NOT EXISTS `hg_app_member_level_version` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`level_id` bigint unsigned NOT NULL COMMENT '等级ID',
`version_no` int unsigned NOT NULL COMMENT '版本号',
`upgrade_amount` bigint NOT NULL DEFAULT 0 COMMENT '升级金额(分)',
`gift_amount` bigint NOT NULL DEFAULT 0 COMMENT '赠送金额(分)',
`daily_order_limit` int unsigned NOT NULL DEFAULT 0 COMMENT '每日接单次数',
`commission_rate` int unsigned NOT NULL DEFAULT 0 COMMENT '佣金万分比',
`daily_withdraw_limit` int unsigned NOT NULL DEFAULT 0 COMMENT '每日提现次数',
`rule_json` json DEFAULT NULL COMMENT '扩展规则快照',
`publish_status` tinyint NOT NULL DEFAULT 1 COMMENT '发布状态',
`effective_at` datetime(3) DEFAULT NULL COMMENT '计划生效时间',
`published_at` datetime(3) DEFAULT NULL COMMENT '发布时间',
`approval_request_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '审批单ID',
`base_version_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '基础版本ID',
`version` int unsigned NOT NULL DEFAULT 0 COMMENT '乐观锁',
`remark` varchar(500) NOT NULL DEFAULT '' COMMENT '变更说明',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_member_level_version` (`level_id`,`version_no`),
KEY `idx_member_level_version_status` (`tenant_id`,`level_id`,`publish_status`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员_等级规则版本';
CREATE TABLE IF NOT EXISTS `hg_task_hall` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`hall_code` varchar(32) NOT NULL COMMENT '大厅编码',
`name` varchar(100) NOT NULL COMMENT '名称',
`icon_attachment_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '图标附件ID',
`icon_url` varchar(1000) NOT NULL DEFAULT '' COMMENT '图标URL',
`summary` varchar(500) NOT NULL DEFAULT '' COMMENT '简介',
`commission_rate` int unsigned NOT NULL DEFAULT 0 COMMENT '佣金万分比',
`rate_unit` varchar(20) NOT NULL DEFAULT 'basis_point' COMMENT '比例单位',
`client_route` varchar(500) NOT NULL DEFAULT '' COMMENT 'C端跳转',
`publish_status` tinyint NOT NULL DEFAULT 1 COMMENT '发布状态',
`sort` int NOT NULL DEFAULT 0 COMMENT '排序',
`version` int unsigned NOT NULL DEFAULT 0 COMMENT '乐观锁',
`remark` varchar(500) NOT NULL DEFAULT '' COMMENT '备注',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`deleted_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '删除者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
`deleted_at` datetime(3) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_task_hall_code` (`tenant_id`,`hall_code`),
UNIQUE KEY `uk_task_hall_name` (`tenant_id`,`name`),
KEY `idx_task_hall_status` (`tenant_id`,`publish_status`,`sort`,`id`),
KEY `idx_task_hall_deleted` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='任务_任务大厅';
CREATE TABLE IF NOT EXISTS `hg_task_hall_level` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`hall_id` bigint unsigned NOT NULL COMMENT '任务大厅ID',
`level_id` bigint unsigned NOT NULL COMMENT '会员等级ID',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_task_hall_level` (`tenant_id`,`hall_id`,`level_id`),
KEY `idx_task_hall_level_level` (`tenant_id`,`level_id`,`hall_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='任务_大厅可用会员等级';
SET @now=NOW();
SET @memberRoot=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='app_member' LIMIT 1);
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @memberRoot,2,CONCAT('tr_',@memberRoot,' '),x.title,x.name,x.path,x.icon,2,'',x.permissions,'',x.component,1,'',0,0,'',1,0,0,x.sort,x.remark,1,@now,@now FROM (
SELECT '会员等级' title,'app_member_level' name,'level' path,'CrownOutlined' icon,'/memberLevel/list,/memberLevel/view,/memberLevel/history' permissions,'/app-member/level/index' component,40 sort,'版本化会员等级规则' remark UNION ALL
SELECT '任务大厅','app_task_hall','task-hall','AppstoreOutlined','/taskHall/list,/taskHall/view','/app-member/task-hall/index',50,'任务大厅及可用等级'
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` m WHERE m.`name`=x.name);
SET @levelMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='app_member_level' LIMIT 1);
SET @hallMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='app_task_hall' LIMIT 1);
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT x.pid,3,x.tree,x.title,x.name,'','',3,'',x.permissions,'','',1,'',0,0,'',0,1,0,x.sort,'第七章操作权限',1,@now,@now FROM (
SELECT @levelMenu pid,CONCAT('tr_',@memberRoot,' tr_',@levelMenu,' ') tree,'保存等级草稿' title,'member_level_save' name,'/memberLevel/save' permissions,10 sort UNION ALL
SELECT @levelMenu,CONCAT('tr_',@memberRoot,' tr_',@levelMenu,' '),'提交等级审批','member_level_submit','/memberLevel/submit',20 UNION ALL
SELECT @levelMenu,CONCAT('tr_',@memberRoot,' tr_',@levelMenu,' '),'发布等级规则','member_level_publish','/memberLevel/publish',30 UNION ALL
SELECT @levelMenu,CONCAT('tr_',@memberRoot,' tr_',@levelMenu,' '),'回滚等级规则','member_level_rollback','/memberLevel/rollback',40 UNION ALL
SELECT @levelMenu,CONCAT('tr_',@memberRoot,' tr_',@levelMenu,' '),'停用等级','member_level_status','/memberLevel/status',50 UNION ALL
SELECT @levelMenu,CONCAT('tr_',@memberRoot,' tr_',@levelMenu,' '),'删除等级','member_level_delete','/memberLevel/delete',60 UNION ALL
SELECT @hallMenu,CONCAT('tr_',@memberRoot,' tr_',@hallMenu,' '),'新增编辑大厅','task_hall_edit','/taskHall/edit',10 UNION ALL
SELECT @hallMenu,CONCAT('tr_',@memberRoot,' tr_',@hallMenu,' '),'发布下线大厅','task_hall_status','/taskHall/status',20 UNION ALL
SELECT @hallMenu,CONCAT('tr_',@memberRoot,' tr_',@hallMenu,' '),'删除大厅','task_hall_delete','/taskHall/delete',30
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` m WHERE m.`name`=x.name);
INSERT IGNORE INTO `hg_admin_role_menu` (`role_id`,`menu_id`)
SELECT r.id,m.id FROM `hg_admin_role` r JOIN `hg_admin_menu` m ON m.name IN ('app_member_level','app_task_hall','member_level_save','member_level_submit','member_level_publish','member_level_rollback','member_level_status','member_level_delete','task_hall_edit','task_hall_status','task_hall_delete') WHERE r.`key` IN ('manage','business');
@@ -0,0 +1,239 @@
-- 第八章:交易订单、充值、提现与客服管理。
-- MySQL 8.0+;金额统一使用分,资金结果通过审批与不可变台账执行。
CREATE TABLE IF NOT EXISTS `hg_trade_order` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`order_no` varchar(40) NOT NULL COMMENT '订单号',
`member_id` bigint unsigned NOT NULL COMMENT '会员ID',
`task_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '任务ID',
`product_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '商品ID',
`product_name` varchar(200) NOT NULL DEFAULT '' COMMENT '商品名称快照',
`order_type` tinyint NOT NULL COMMENT '订单类型',
`quantity` int unsigned NOT NULL DEFAULT 1 COMMENT '数量',
`unit_price_amount` bigint NOT NULL COMMENT '单价(分)',
`total_amount` bigint NOT NULL COMMENT '订单金额(分)',
`commission_amount` bigint NOT NULL DEFAULT 0 COMMENT '佣金(分)',
`currency` char(3) NOT NULL DEFAULT 'CNY' COMMENT '币种',
`member_level_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '下单等级ID',
`rule_snapshot` json DEFAULT NULL COMMENT '规则快照',
`message` varchar(500) NOT NULL DEFAULT '' COMMENT '订单消息',
`order_status` tinyint NOT NULL DEFAULT 1 COMMENT '订单状态',
`freeze_status` tinyint NOT NULL DEFAULT 1 COMMENT '冻结状态',
`approval_request_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '人工处理审批ID',
`matched_at` datetime(3) DEFAULT NULL COMMENT '匹配时间',
`completed_at` datetime(3) DEFAULT NULL COMMENT '完成时间',
`unfrozen_at` datetime(3) DEFAULT NULL COMMENT '解冻时间',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '下单时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_trade_order_no` (`tenant_id`,`order_no`),
KEY `idx_trade_order_member_time` (`tenant_id`,`member_id`,`created_at`,`id`),
KEY `idx_trade_order_status_time` (`tenant_id`,`order_status`,`created_at`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='交易_业务订单';
CREATE TABLE IF NOT EXISTS `hg_payment_channel` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`channel_code` varchar(32) NOT NULL COMMENT '渠道编码',
`name` varchar(100) NOT NULL COMMENT '渠道名称',
`channel_type` tinyint NOT NULL COMMENT '渠道类型',
`direction` tinyint NOT NULL COMMENT '支持方向',
`config_cipher` longtext COMMENT '渠道配置密文',
`min_amount` bigint NOT NULL DEFAULT 0 COMMENT '最小金额(分)',
`max_amount` bigint NOT NULL DEFAULT 0 COMMENT '最大金额(分)',
`fee_type` tinyint NOT NULL DEFAULT 1 COMMENT '手续费类型',
`fee_fixed_amount` bigint NOT NULL DEFAULT 0 COMMENT '固定手续费(分)',
`fee_rate` int unsigned NOT NULL DEFAULT 0 COMMENT '费率(万分比)',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态',
`sort` int NOT NULL DEFAULT 0 COMMENT '排序',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`deleted_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '删除者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
`deleted_at` datetime(3) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_payment_channel_code` (`tenant_id`,`channel_code`),
KEY `idx_payment_channel_status` (`tenant_id`,`status`,`sort`),
KEY `idx_payment_channel_deleted` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='交易_支付渠道';
CREATE TABLE IF NOT EXISTS `hg_recharge_order` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`recharge_no` varchar(40) NOT NULL COMMENT '充值单号',
`member_id` bigint unsigned NOT NULL COMMENT '会员ID',
`channel_id` bigint unsigned NOT NULL COMMENT '支付渠道ID',
`request_amount` bigint NOT NULL COMMENT '申请金额(分)',
`paid_amount` bigint NOT NULL DEFAULT 0 COMMENT '实付金额(分)',
`currency` char(3) NOT NULL DEFAULT 'CNY' COMMENT '币种',
`external_no` varchar(128) NOT NULL DEFAULT '' COMMENT '外部支付单号',
`voucher_attachment_ids` json DEFAULT NULL COMMENT '打款凭证附件',
`recharge_type` tinyint NOT NULL DEFAULT 1 COMMENT '充值类型',
`recharge_status` tinyint NOT NULL DEFAULT 1 COMMENT '充值状态',
`remark` varchar(500) NOT NULL DEFAULT '' COMMENT '会员备注',
`review_reason_code` varchar(64) NOT NULL DEFAULT '' COMMENT '审核原因编码',
`review_reason` varchar(500) NOT NULL DEFAULT '' COMMENT '审核意见',
`approval_request_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '审批单ID',
`ledger_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '入账台账ID',
`paid_at` datetime(3) DEFAULT NULL COMMENT '支付时间',
`reviewed_at` datetime(3) DEFAULT NULL COMMENT '审核时间',
`credited_at` datetime(3) DEFAULT NULL COMMENT '入账时间',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_recharge_no` (`tenant_id`,`recharge_no`),
KEY `idx_recharge_external` (`tenant_id`,`external_no`),
KEY `idx_recharge_member_time` (`tenant_id`,`member_id`,`created_at`,`id`),
KEY `idx_recharge_status_time` (`tenant_id`,`recharge_status`,`created_at`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='交易_充值订单';
CREATE TABLE IF NOT EXISTS `hg_withdrawal_order` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`withdrawal_no` varchar(40) NOT NULL COMMENT '提现单号',
`member_id` bigint unsigned NOT NULL COMMENT '会员ID',
`payment_account_id` bigint unsigned NOT NULL COMMENT '收款账户ID',
`channel_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '付款渠道ID',
`request_amount` bigint NOT NULL COMMENT '申请金额(分)',
`fee_amount` bigint NOT NULL DEFAULT 0 COMMENT '手续费(分)',
`actual_amount` bigint NOT NULL COMMENT '实际到账(分)',
`currency` char(3) NOT NULL DEFAULT 'CNY' COMMENT '币种',
`account_snapshot_cipher` longtext NOT NULL COMMENT '收款账户加密快照',
`account_mask` varchar(128) NOT NULL COMMENT '收款账户脱敏快照',
`bank_name` varchar(100) NOT NULL DEFAULT '' COMMENT '银行名称快照',
`holder_mask` varchar(64) NOT NULL DEFAULT '' COMMENT '开户名脱敏快照',
`risk_result` json DEFAULT NULL COMMENT '风控结果摘要',
`withdrawal_status` tinyint NOT NULL DEFAULT 1 COMMENT '提现状态',
`review_reason_code` varchar(64) NOT NULL DEFAULT '' COMMENT '审核原因编码',
`review_reason` varchar(500) NOT NULL DEFAULT '' COMMENT '审核意见',
`approval_request_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '审批单ID',
`external_no` varchar(128) NOT NULL DEFAULT '' COMMENT '外部付款单号',
`freeze_ledger_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '冻结台账ID',
`final_ledger_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '完成或解冻台账ID',
`reviewed_at` datetime(3) DEFAULT NULL COMMENT '审核时间',
`processed_at` datetime(3) DEFAULT NULL COMMENT '处理时间',
`completed_at` datetime(3) DEFAULT NULL COMMENT '完成时间',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '发起时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_withdrawal_no` (`tenant_id`,`withdrawal_no`),
KEY `idx_withdrawal_external` (`tenant_id`,`external_no`),
KEY `idx_withdrawal_member_time` (`tenant_id`,`member_id`,`created_at`,`id`),
KEY `idx_withdrawal_status_time` (`tenant_id`,`withdrawal_status`,`created_at`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='交易_提现订单';
CREATE TABLE IF NOT EXISTS `hg_finance_review` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`approval_request_id` bigint unsigned NOT NULL COMMENT '审批单ID',
`biz_type` varchar(32) NOT NULL COMMENT '业务类型',
`biz_id` bigint unsigned NOT NULL COMMENT '业务ID',
`review_stage` tinyint NOT NULL COMMENT '审核阶段',
`reviewer_id` bigint unsigned NOT NULL COMMENT '审核人',
`decision` tinyint NOT NULL COMMENT '审核结论',
`reason_code` varchar(64) NOT NULL COMMENT '原因编码',
`reason_text` varchar(500) NOT NULL COMMENT '审核说明',
`snapshot_json` json DEFAULT NULL COMMENT '审核快照',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_finance_review_actor` (`tenant_id`,`approval_request_id`,`review_stage`,`reviewer_id`),
KEY `idx_finance_review_biz` (`tenant_id`,`biz_type`,`biz_id`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='交易_财务审核记录';
CREATE TABLE IF NOT EXISTS `hg_customer_service` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`service_code` varchar(32) NOT NULL COMMENT '客服编码',
`name` varchar(100) NOT NULL COMMENT '客服名称',
`avatar_url` varchar(1000) NOT NULL DEFAULT '' COMMENT '头像地址',
`work_time` varchar(200) NOT NULL COMMENT '工作时间说明',
`online_status` tinyint NOT NULL DEFAULT 2 COMMENT '在线状态',
`service_url` varchar(1000) NOT NULL COMMENT '客服跳转URL',
`backup_contact` varchar(500) NOT NULL DEFAULT '' COMMENT '备用联系方式',
`session_mapping` json DEFAULT NULL COMMENT '第三方会话映射',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态',
`sort` int NOT NULL DEFAULT 0 COMMENT '排序',
`remark` varchar(500) NOT NULL DEFAULT '' COMMENT '备注',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`deleted_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '删除者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
`deleted_at` datetime(3) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_customer_service_code` (`tenant_id`,`service_code`),
KEY `idx_customer_service_status` (`tenant_id`,`status`,`sort`),
KEY `idx_customer_service_deleted` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='交易_客服配置';
-- 本地默认渠道仅包含展示与费率边界,不保存任何生产密钥。
INSERT INTO `hg_payment_channel` (`tenant_id`,`channel_code`,`name`,`channel_type`,`direction`,`min_amount`,`max_amount`,`fee_type`,`fee_fixed_amount`,`fee_rate`,`status`,`sort`,`created_at`,`updated_at`)
SELECT 0,x.channel_code,x.name,x.channel_type,3,0,0,1,0,0,1,x.sort,NOW(3),NOW(3) FROM (
SELECT 'wechat' channel_code,'微信' name,1 channel_type,10 sort UNION ALL
SELECT 'alipay','支付宝',2,20 UNION ALL
SELECT 'bank','银行卡',3,30 UNION ALL
SELECT 'manual','人工审核',4,40
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_payment_channel` c WHERE c.`tenant_id`=0 AND c.`channel_code`=x.channel_code);
-- 审核原因使用 HotGo 原有数据库字典。
INSERT INTO `hg_sys_dict_type` (`name`,`type`,`remark`,`status`,`created_at`,`updated_at`)
SELECT x.name,x.type,x.remark,1,NOW(),NOW() FROM (
SELECT '充值驳回原因' name,'recharge_reject_reason' type,'充值审核标准原因' remark UNION ALL
SELECT '提现驳回原因','withdrawal_reject_reason','提现审核标准原因' UNION ALL
SELECT '交易异常原因','trade_exception_reason','交易人工处理标准原因'
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_sys_dict_type` d WHERE d.`type`=x.type);
INSERT INTO `hg_sys_dict_data` (`type`,`label`,`value`,`value_type`,`list_class`,`sort`,`status`,`remark`,`created_at`,`updated_at`)
SELECT x.type,x.label,x.value,'string',x.list_class,x.sort,1,x.remark,NOW(),NOW() FROM (
SELECT 'recharge_reject_reason' type,'凭证不清晰' label,'voucher_unclear' value,'warning' list_class,10 sort,'充值审核原因' remark UNION ALL
SELECT 'recharge_reject_reason','金额不一致','amount_mismatch','error',20,'充值审核原因' UNION ALL
SELECT 'recharge_reject_reason','重复订单','duplicate_order','error',30,'充值审核原因' UNION ALL
SELECT 'withdrawal_reject_reason','账户信息异常','account_invalid','error',10,'提现审核原因' UNION ALL
SELECT 'withdrawal_reject_reason','风控拦截','risk_rejected','error',20,'提现审核原因' UNION ALL
SELECT 'withdrawal_reject_reason','余额状态异常','balance_invalid','warning',30,'提现审核原因' UNION ALL
SELECT 'trade_exception_reason','匹配超时','match_timeout','warning',10,'交易异常原因' UNION ALL
SELECT 'trade_exception_reason','风控解冻','risk_unfreeze','primary',20,'交易异常原因' UNION ALL
SELECT 'trade_exception_reason','人工重匹配','manual_rematch','primary',30,'交易异常原因'
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_sys_dict_data` d WHERE d.`type`=x.type AND d.`value`=x.value);
-- 交易管理菜单与接口权限。
SET @now=NOW();
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT 0,1,'','交易管理','trade_management','/trade','TransactionOutlined',1,'','','','LAYOUT',1,'',1,0,'',0,0,0,50,'订单、充值、提现与客服治理',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='trade_management');
SET @tradeRoot=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='trade_management' LIMIT 1);
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @tradeRoot,2,CONCAT('tr_',@tradeRoot,' '),x.title,x.name,x.path,x.icon,2,'',x.permissions,'',x.component,1,'',0,0,'',1,0,0,x.sort,x.remark,1,@now,@now FROM (
SELECT '订单列表' title,'trade_order' name,'order' path,'FileTextOutlined' icon,'/tradeOrder/list,/tradeOrder/view' permissions,'/trade/order/index' component,10 sort,'交易订单查询与异常处理' remark UNION ALL
SELECT '充值管理','trade_recharge','recharge','PayCircleOutlined','/rechargeOrder/list,/rechargeOrder/summary,/rechargeOrder/view','/trade/recharge/index',20,'充值凭证与入账审核' UNION ALL
SELECT '提现管理','trade_withdrawal','withdrawal','BankOutlined','/withdrawalOrder/list,/withdrawalOrder/view','/trade/withdrawal/index',30,'提现脱敏审核与付款结果' UNION ALL
SELECT '客服管理','trade_customer_service','customer-service','CustomerServiceOutlined','/customerService/list,/customerService/view','/trade/customer-service/index',40,'客服入口与降级联系方式'
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` m WHERE m.`name`=x.name);
SET @orderMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='trade_order' LIMIT 1);
SET @rechargeMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='trade_recharge' LIMIT 1);
SET @withdrawalMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='trade_withdrawal' LIMIT 1);
SET @serviceMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='trade_customer_service' LIMIT 1);
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT x.pid,3,x.tree,x.title,x.name,'','',3,'',x.permissions,'','',1,'',0,0,'',0,1,0,x.sort,'交易管理操作权限',1,@now,@now FROM (
SELECT @orderMenu pid,CONCAT('tr_',@tradeRoot,' tr_',@orderMenu,' ') tree,'提交订单处理' title,'trade_order_apply' name,'/tradeOrder/apply' permissions,10 sort UNION ALL
SELECT @orderMenu,CONCAT('tr_',@tradeRoot,' tr_',@orderMenu,' '),'执行订单处理','trade_order_execute','/tradeOrder/execute',20 UNION ALL
SELECT @rechargeMenu,CONCAT('tr_',@tradeRoot,' tr_',@rechargeMenu,' '),'提交充值审核','trade_recharge_review','/rechargeOrder/review',10 UNION ALL
SELECT @rechargeMenu,CONCAT('tr_',@tradeRoot,' tr_',@rechargeMenu,' '),'执行充值审核','trade_recharge_execute','/rechargeOrder/execute',20 UNION ALL
SELECT @withdrawalMenu,CONCAT('tr_',@tradeRoot,' tr_',@withdrawalMenu,' '),'提交提现审核','trade_withdrawal_review','/withdrawalOrder/review',10 UNION ALL
SELECT @withdrawalMenu,CONCAT('tr_',@tradeRoot,' tr_',@withdrawalMenu,' '),'执行提现审核','trade_withdrawal_execute','/withdrawalOrder/execute',20 UNION ALL
SELECT @withdrawalMenu,CONCAT('tr_',@tradeRoot,' tr_',@withdrawalMenu,' '),'登记付款结果','trade_withdrawal_complete','/withdrawalOrder/complete',30 UNION ALL
SELECT @serviceMenu,CONCAT('tr_',@tradeRoot,' tr_',@serviceMenu,' '),'新增编辑客服','trade_customer_service_edit','/customerService/edit',10 UNION ALL
SELECT @serviceMenu,CONCAT('tr_',@tradeRoot,' tr_',@serviceMenu,' '),'客服状态','trade_customer_service_status','/customerService/status',20 UNION ALL
SELECT @serviceMenu,CONCAT('tr_',@tradeRoot,' tr_',@serviceMenu,' '),'删除客服','trade_customer_service_delete','/customerService/delete',30
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` m WHERE m.`name`=x.name);
@@ -0,0 +1,147 @@
-- 第九章:商品、任务与会员任务审核。
-- 金额统一使用分;比例统一使用万分比;佣金结算写入不可变钱包台账。
CREATE TABLE IF NOT EXISTS `hg_product_category` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`pid` bigint unsigned NOT NULL DEFAULT 0 COMMENT '上级ID',
`level` int unsigned NOT NULL DEFAULT 1 COMMENT '树等级',
`tree` varchar(512) NOT NULL DEFAULT '' COMMENT '关系树',
`category_code` varchar(32) NOT NULL COMMENT '分类编码',
`name` varchar(100) NOT NULL COMMENT '分类名称',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态',
`sort` int NOT NULL DEFAULT 0 COMMENT '排序',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`deleted_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '删除者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
`deleted_at` datetime(3) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_product_category_code` (`tenant_id`,`category_code`),
KEY `idx_product_category_status` (`tenant_id`,`status`,`sort`,`id`),
KEY `idx_product_category_deleted` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商城_商品分类';
CREATE TABLE IF NOT EXISTS `hg_task` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`task_no` varchar(32) NOT NULL COMMENT '任务编号',
`hall_id` bigint unsigned NOT NULL COMMENT '任务大厅ID',
`title` varchar(200) NOT NULL COMMENT '标题',
`description` varchar(1000) NOT NULL DEFAULT '' COMMENT '描述',
`detail_html` longtext COMMENT '清洗后的任务详情',
`cover_attachment_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '封面附件ID',
`cover_url` varchar(1000) NOT NULL DEFAULT '' COMMENT '封面地址',
`commission_amount` bigint NOT NULL DEFAULT 0 COMMENT '固定佣金(分)',
`commission_rate` int unsigned NOT NULL DEFAULT 0 COMMENT '佣金万分比',
`daily_limit` int unsigned NOT NULL DEFAULT 0 COMMENT '每日总量',
`per_member_limit` int unsigned NOT NULL DEFAULT 1 COMMENT '单会员限制',
`start_at` datetime(3) DEFAULT NULL COMMENT '开始时间',
`end_at` datetime(3) DEFAULT NULL COMMENT '结束时间',
`publish_status` tinyint NOT NULL DEFAULT 1 COMMENT '发布状态',
`sort` int NOT NULL DEFAULT 0 COMMENT '排序',
`version` int unsigned NOT NULL DEFAULT 0 COMMENT '乐观锁',
`remark` varchar(500) NOT NULL DEFAULT '' COMMENT '备注',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`deleted_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '删除者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
`deleted_at` datetime(3) DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_task_no` (`tenant_id`,`task_no`),
KEY `idx_task_hall_status` (`tenant_id`,`hall_id`,`publish_status`,`sort`,`id`),
KEY `idx_task_period` (`tenant_id`,`start_at`,`end_at`),
KEY `idx_task_deleted` (`deleted_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='任务_任务定义';
CREATE TABLE IF NOT EXISTS `hg_task_level` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`task_id` bigint unsigned NOT NULL COMMENT '任务ID',
`level_id` bigint unsigned NOT NULL COMMENT '会员等级ID',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_task_level` (`tenant_id`,`task_id`,`level_id`),
KEY `idx_task_level_level` (`tenant_id`,`level_id`,`task_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='任务_可用会员等级';
CREATE TABLE IF NOT EXISTS `hg_task_submission` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`tenant_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '租户ID',
`submission_no` varchar(32) NOT NULL COMMENT '提交编号',
`trade_order_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '交易订单ID',
`task_id` bigint unsigned NOT NULL COMMENT '任务ID',
`member_id` bigint unsigned NOT NULL COMMENT '会员ID',
`member_level_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '提交时等级ID',
`evidence_text` varchar(2000) NOT NULL DEFAULT '' COMMENT '证据说明',
`evidence_attachment_ids` json DEFAULT NULL COMMENT '证据附件',
`submission_status` tinyint NOT NULL DEFAULT 1 COMMENT '1待审 2通过 3驳回 4已结算 5已冲正',
`commission_amount` bigint NOT NULL DEFAULT 0 COMMENT '佣金快照(分)',
`success_rate` int unsigned NOT NULL DEFAULT 0 COMMENT '成功率万分比',
`reviewed_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '审核人',
`reviewed_at` datetime(3) DEFAULT NULL COMMENT '审核时间',
`review_reason_code` varchar(64) NOT NULL DEFAULT '' COMMENT '标准原因',
`review_reason` varchar(500) NOT NULL DEFAULT '' COMMENT '审核意见',
`allow_resubmit` tinyint NOT NULL DEFAULT 2 COMMENT '是否允许重提',
`ledger_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '佣金台账ID',
`settled_at` datetime(3) DEFAULT NULL COMMENT '结算时间',
`reversal_approval_id` bigint unsigned NOT NULL DEFAULT 0 COMMENT '冲正审批ID',
`created_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '创建者',
`updated_by` bigint unsigned NOT NULL DEFAULT 0 COMMENT '更新者',
`created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`updated_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_task_submission_no` (`submission_no`),
UNIQUE KEY `uk_task_submission_order` (`trade_order_id`),
KEY `idx_task_submission_member` (`tenant_id`,`member_id`,`created_at`,`id`),
KEY `idx_task_submission_status` (`tenant_id`,`submission_status`,`created_at`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='任务_会员任务提交';
INSERT INTO `hg_product_category` (`tenant_id`,`category_code`,`name`,`status`,`sort`)
SELECT 0,'DEFAULT','默认分类',1,10
WHERE NOT EXISTS (SELECT 1 FROM `hg_product_category` WHERE `tenant_id`=0 AND `category_code`='DEFAULT');
INSERT INTO `hg_sys_dict_type` (`name`,`type`,`remark`,`status`,`created_at`,`updated_at`)
SELECT '任务审核驳回原因','task_reject_reason','第九章会员任务审核',1,NOW(),NOW()
WHERE NOT EXISTS (SELECT 1 FROM `hg_sys_dict_type` WHERE `type`='task_reject_reason');
INSERT INTO `hg_sys_dict_data` (`type`,`label`,`value`,`value_type`,`list_class`,`sort`,`status`,`remark`,`created_at`,`updated_at`)
SELECT 'task_reject_reason',x.label,x.value,'string','error',x.sort,1,'任务审核驳回原因',NOW(),NOW()
FROM (
SELECT '证据不完整' label,'evidence_incomplete' value,10 sort UNION ALL
SELECT '证据不符合要求','evidence_invalid',20 UNION ALL
SELECT '重复提交','duplicate_submission',30 UNION ALL
SELECT '任务已失效','task_expired',40 UNION ALL
SELECT '其他','other',90
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_sys_dict_data` d WHERE d.`type`='task_reject_reason' AND d.`value`=x.value);
SET @now=NOW();
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT 0,1,'', '商品与任务','product_task','/product-task','AppstoreOutlined',1,'/product-task/product','','','LAYOUT',1,'',1,0,'',0,0,0,45,'第九章商品任务管理',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='product_task');
UPDATE `hg_admin_menu` SET `component`='LAYOUT', `keep_alive`=0 WHERE `name`='product_task';
SET @root=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='product_task' LIMIT 1);
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @root,2,CONCAT('tr_',@root,' '),x.title,x.name,x.path,x.icon,2,'',x.permissions,'',x.component,1,'',0,0,'',1,0,0,x.sort,x.remark,1,@now,@now FROM (
SELECT '商品列表' title,'product_list' name,'product' path,'ShoppingOutlined' icon,'/product/list,/product/view' permissions,'/product-task/product/index' component,10 sort,'商品维护' remark UNION ALL
SELECT '任务列表','task_list','task','ProfileOutlined','/task/list,/task/view','/product-task/task/index',20,'任务维护' UNION ALL
SELECT '会员任务审核','task_submission_list','submission','AuditOutlined','/taskSubmission/list,/taskSubmission/view','/product-task/submission/index',30,'会员任务提交审核'
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` m WHERE m.`name`=x.name);
SET @productMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='product_list' LIMIT 1);
SET @taskMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='task_list' LIMIT 1);
SET @submissionMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='task_submission_list' LIMIT 1);
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT x.pid,3,x.tree,x.title,x.name,'','',3,'',x.permissions,'','',1,'',0,0,'',0,1,0,x.sort,'第九章操作权限',1,@now,@now FROM (
SELECT @productMenu pid,CONCAT('tr_',@root,' tr_',@productMenu,' ') tree,'新增编辑商品' title,'product_edit' name,'/product/edit' permissions,10 sort UNION ALL
SELECT @productMenu,CONCAT('tr_',@root,' tr_',@productMenu,' '),'商品状态','product_status','/product/status',20 UNION ALL
SELECT @productMenu,CONCAT('tr_',@root,' tr_',@productMenu,' '),'商品推荐','product_recommend','/product/recommend',30 UNION ALL
SELECT @productMenu,CONCAT('tr_',@root,' tr_',@productMenu,' '),'删除商品','product_delete','/product/delete',40 UNION ALL
SELECT @taskMenu,CONCAT('tr_',@root,' tr_',@taskMenu,' '),'新增编辑任务','task_edit','/task/edit',10 UNION ALL
SELECT @taskMenu,CONCAT('tr_',@root,' tr_',@taskMenu,' '),'任务状态','task_status','/task/status',20 UNION ALL
SELECT @taskMenu,CONCAT('tr_',@root,' tr_',@taskMenu,' '),'删除任务','task_delete','/task/delete',30 UNION ALL
SELECT @submissionMenu,CONCAT('tr_',@root,' tr_',@submissionMenu,' '),'审核任务','task_submission_review','/taskSubmission/review',10
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` m WHERE m.`name`=x.name);
INSERT IGNORE INTO `hg_admin_role_menu` (`role_id`,`menu_id`)
SELECT r.id,m.id FROM `hg_admin_role` r JOIN `hg_admin_menu` m ON m.name IN ('product_task','product_list','task_list','task_submission_list','product_edit','product_status','product_recommend','product_delete','task_edit','task_status','task_delete','task_submission_review') WHERE r.`key` IN ('manage','business');
@@ -0,0 +1,28 @@
-- 对齐原型中的会员管理菜单:一级菜单位于主页之后,原型入口优先展示。
SET @now=NOW();
SET @memberRoot=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='app_member' LIMIT 1);
UPDATE `hg_admin_menu`
SET `sort`=15, `updated_at`=@now
WHERE `id`=@memberRoot;
UPDATE `hg_admin_menu`
SET
`sort`=CASE `name`
WHEN 'app_member_list' THEN 10
WHEN 'app_member_level' THEN 20
WHEN 'app_task_hall' THEN 30
WHEN 'app_member_wallet' THEN 40
WHEN 'app_member_notice' THEN 50
ELSE `sort`
END,
`hidden`=0,
`updated_at`=@now
WHERE `pid`=@memberRoot
AND `name` IN (
'app_member_list',
'app_member_level',
'app_task_hall',
'app_member_wallet',
'app_member_notice'
);
@@ -0,0 +1,9 @@
-- 对齐原型菜单:审批和审计保留为内部能力,不在后台导航中单独展示。
SET @now = NOW();
UPDATE `hg_admin_menu`
SET `hidden` = 1,
`status` = 2,
`updated_at` = @now
WHERE `name` IN ('governance', 'governance_approval', 'governance_biz_audit')
OR `tree` LIKE CONCAT('%tr_', (SELECT `id` FROM (SELECT `id` FROM `hg_admin_menu` WHERE `name` = 'governance' LIMIT 1) AS governance_menu), ' %');
@@ -0,0 +1,12 @@
-- 原型没有独立治理菜单,移除对应菜单和角色关联;业务内部日志表继续保留。
SET @governanceId = (SELECT `id` FROM `hg_admin_menu` WHERE `name` = 'governance' LIMIT 1);
DELETE role_menu
FROM `hg_admin_role_menu` AS role_menu
INNER JOIN `hg_admin_menu` AS menu ON menu.`id` = role_menu.`menu_id`
WHERE menu.`id` = @governanceId
OR menu.`tree` LIKE CONCAT('%tr_', @governanceId, ' %');
DELETE FROM `hg_admin_menu`
WHERE `id` = @governanceId
OR `tree` LIKE CONCAT('%tr_', @governanceId, ' %');
@@ -0,0 +1,10 @@
-- 清理历史上超出直接父角色范围的菜单授权;父角色为超级管理员时不限制。
DELETE child_menu
FROM `hg_admin_role_menu` AS child_menu
INNER JOIN `hg_admin_role` AS child_role ON child_role.`id` = child_menu.`role_id`
INNER JOIN `hg_admin_role` AS parent_role ON parent_role.`id` = child_role.`pid`
LEFT JOIN `hg_admin_role_menu` AS parent_menu
ON parent_menu.`role_id` = parent_role.`id`
AND parent_menu.`menu_id` = child_menu.`menu_id`
WHERE parent_role.`key` <> 'super'
AND parent_menu.`menu_id` IS NULL;
@@ -0,0 +1,14 @@
-- 对齐会员列表操作栏:补充账变流水查询和真人/假人切换权限。
SET @now=NOW();
SET @memberRoot=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='app_member' LIMIT 1);
SET @memberMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='app_member_list' LIMIT 1);
INSERT INTO `hg_admin_menu` (`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @memberMenu,3,CONCAT('tr_',@memberRoot,' tr_',@memberMenu,' '),x.title,x.name,'','',3,'',x.permissions,'','',1,'',0,0,'',0,1,0,x.sort,'会员列表操作权限',1,@now,@now FROM (
SELECT '查看账变流水' title,'app_member_ledger' name,'/appMember/ledgerList' permissions,75 sort UNION ALL
SELECT '切换真人假人','app_member_category','/appMember/category',76
) x WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` m WHERE m.`name`=x.name);
INSERT IGNORE INTO `hg_admin_role_menu` (`role_id`,`menu_id`)
SELECT r.id,m.id FROM `hg_admin_role` r JOIN `hg_admin_menu` m ON m.name IN ('app_member_ledger','app_member_category')
WHERE r.`key` IN ('manage','business');
@@ -0,0 +1,54 @@
-- 调整业务一级菜单及商品、任务菜单归属。
-- 顺序:会员管理 -> 交易管理 -> 商品管理 -> 任务管理。
SET @now=NOW();
SET @memberRoot=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='app_member' LIMIT 1);
SET @tradeRoot=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='trade_management' LIMIT 1);
SET @productRoot=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='product_task' LIMIT 1);
SET @productMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='product_list' LIMIT 1);
SET @taskMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='task_list' LIMIT 1);
SET @submissionMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='task_submission_list' LIMIT 1);
UPDATE `hg_admin_menu` SET `sort`=15,`updated_at`=@now WHERE `id`=@memberRoot;
UPDATE `hg_admin_menu` SET `sort`=16,`updated_at`=@now WHERE `id`=@tradeRoot;
UPDATE `hg_admin_menu`
SET `title`='商品管理',`sort`=17,`redirect`='/product-task/product',`remark`='商品维护',`updated_at`=@now
WHERE `id`=@productRoot;
INSERT INTO `hg_admin_menu`
(`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT 0,1,'','任务管理','task_management','/task-management','ProfileOutlined',1,'/task-management/task','','','LAYOUT',1,'',1,0,'',0,0,0,18,'任务配置与会员任务审核',1,@now,@now
WHERE NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='task_management');
SET @taskRoot=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='task_management' LIMIT 1);
UPDATE `hg_admin_menu`
SET `title`='任务管理',`path`='/task-management',`component`='LAYOUT',`redirect`='/task-management/task',
`sort`=18,`hidden`=0,`status`=1,`updated_at`=@now
WHERE `id`=@taskRoot;
UPDATE `hg_admin_menu`
SET `pid`=@productRoot,`level`=2,`tree`=CONCAT('tr_',@productRoot,' '),`sort`=10,`hidden`=0,`updated_at`=@now
WHERE `id`=@productMenu;
UPDATE `hg_admin_menu`
SET `pid`=@taskRoot,`level`=2,`tree`=CONCAT('tr_',@taskRoot,' '),`sort`=10,`hidden`=0,`updated_at`=@now
WHERE `id`=@taskMenu;
UPDATE `hg_admin_menu`
SET `pid`=@taskRoot,`level`=2,`tree`=CONCAT('tr_',@taskRoot,' '),`sort`=20,`hidden`=0,`updated_at`=@now
WHERE `id`=@submissionMenu;
UPDATE `hg_admin_menu`
SET `level`=3,`tree`=CONCAT('tr_',@taskRoot,' tr_',@taskMenu,' '),`updated_at`=@now
WHERE `pid`=@taskMenu;
UPDATE `hg_admin_menu`
SET `level`=3,`tree`=CONCAT('tr_',@taskRoot,' tr_',@submissionMenu,' '),`updated_at`=@now
WHERE `pid`=@submissionMenu;
-- 原来拥有商品任务菜单的角色继续拥有新的任务管理一级菜单。
INSERT IGNORE INTO `hg_admin_role_menu` (`role_id`,`menu_id`)
SELECT DISTINCT rm.`role_id`,@taskRoot
FROM `hg_admin_role_menu` rm
WHERE rm.`menu_id` IN (@productRoot,@taskMenu,@submissionMenu);
@@ -0,0 +1,17 @@
-- 订单人工匹配权限,复用现有交易管理菜单。
SET @now=NOW();
SET @tradeRoot=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='trade_management' LIMIT 1);
SET @orderMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='trade_order' LIMIT 1);
INSERT INTO `hg_admin_menu`
(`pid`,`level`,`tree`,`title`,`name`,`path`,`icon`,`type`,`redirect`,`permissions`,`permission_name`,`component`,`always_show`,`active_menu`,`is_root`,`is_frame`,`frame_src`,`keep_alive`,`hidden`,`affix`,`sort`,`remark`,`status`,`created_at`,`updated_at`)
SELECT @orderMenu,3,CONCAT('tr_',@tradeRoot,' tr_',@orderMenu,' '),'匹配订单','trade_order_match','','',3,'','/tradeOrder/match,/tradeOrder/matchProducts','','',1,'',0,0,'',0,1,0,5,'订单人工选品匹配权限',1,@now,@now
WHERE @orderMenu IS NOT NULL AND NOT EXISTS (SELECT 1 FROM `hg_admin_menu` WHERE `name`='trade_order_match');
SET @matchMenu=(SELECT `id` FROM `hg_admin_menu` WHERE `name`='trade_order_match' LIMIT 1);
-- 原来拥有订单列表的角色自动继承匹配订单权限。
INSERT IGNORE INTO `hg_admin_role_menu` (`role_id`,`menu_id`)
SELECT DISTINCT rm.`role_id`,@matchMenu
FROM `hg_admin_role_menu` rm
WHERE rm.`menu_id`=@orderMenu AND @matchMenu IS NOT NULL;
@@ -0,0 +1,9 @@
-- HotGo 默认将个人中心设为隐藏路由,只能从右上角头像进入。
-- 本项目需要在「系统应用」下直接展示该菜单,因此取消隐藏;个人设置仍作为其子菜单。
UPDATE `hg_admin_menu`
SET `hidden` = 0,
`always_show` = 1,
`updated_at` = NOW()
WHERE `name` = 'home'
AND `title` = '个人中心'
AND `pid` > 0;
@@ -0,0 +1,22 @@
-- 会员管理按原型仅保留会员列表、会员等级和任务大厅。
-- 资金调账、会员通知的业务代码、数据表及按钮权限继续保留,供会员列表操作栏使用。
UPDATE `hg_admin_menu`
SET `hidden` = 1,
`status` = 2,
`updated_at` = NOW()
WHERE `name` IN (
'app_member_wallet',
'app_member_notice'
);
-- 按钮权限本身不生成菜单入口,保持启用,避免会员列表中的账变等操作被一并移除。
UPDATE `hg_admin_menu`
SET `hidden` = 1,
`status` = 1,
`updated_at` = NOW()
WHERE `name` IN (
'app_member_wallet_request',
'app_member_wallet_execute',
'app_member_notice_edit',
'app_member_notice_revoke'
);
@@ -0,0 +1,19 @@
-- 保留一条可用于验收“匹配订单”操作的演示订单。
-- 仅调整固定演示单号,不影响真实业务订单。
UPDATE `hg_trade_order`
SET
`product_id` = 0,
`product_name` = '',
`order_type` = 3,
`quantity` = 1,
`unit_price_amount` = 0,
`total_amount` = 0,
`commission_amount` = 0,
`message` = '等待后台匹配商品',
`order_status` = 1,
`freeze_status` = 1,
`approval_request_id` = 0,
`matched_at` = NULL,
`completed_at` = NULL,
`unfrozen_at` = NULL
WHERE `order_no` = 'DEMO-ORD-01';
@@ -0,0 +1,37 @@
-- 为 HotGo 原生后台的常用二级菜单补充图标。
-- 图标名称来自前端 @vicons/antd,由动态路由统一渲染。
UPDATE `hg_admin_menu`
SET `icon` = CASE `name`
WHEN 'user' THEN 'UserOutlined'
WHEN 'org_dept' THEN 'ApartmentOutlined'
WHEN 'org_post' THEN 'IdcardOutlined'
WHEN 'permission_menu' THEN 'MenuOutlined'
WHEN 'permission_role' THEN 'SafetyCertificateOutlined'
WHEN 'Logs' THEN 'FileTextOutlined'
WHEN 'asset' THEN 'AccountBookOutlined'
WHEN 'apply_provinces' THEN 'EnvironmentOutlined'
WHEN 'apply_attachment' THEN 'PaperClipOutlined'
WHEN 'apply_notice' THEN 'NotificationOutlined'
WHEN 'system_config' THEN 'SettingOutlined'
WHEN 'system_dict' THEN 'BookOutlined'
WHEN 'system_cron' THEN 'ScheduleOutlined'
WHEN 'system_blacklist' THEN 'StopOutlined'
ELSE `icon`
END,
`updated_at` = NOW()
WHERE `name` IN (
'user',
'org_dept',
'org_post',
'permission_menu',
'permission_role',
'Logs',
'asset',
'apply_provinces',
'apply_attachment',
'apply_notice',
'system_config',
'system_dict',
'system_cron',
'system_blacklist'
);
@@ -0,0 +1,34 @@
-- 商品编辑页依赖统一附件上传接口。
-- 已拥有商品编辑权限的角色,必须同时获得 /upload/file,否则新增和更换商品图片会被鉴权拦截。
INSERT IGNORE INTO `hg_admin_role_menu` (`role_id`, `menu_id`)
SELECT DISTINCT product_role.`role_id`, upload_menu.`id`
FROM `hg_admin_role_menu` AS product_role
INNER JOIN `hg_admin_menu` AS product_menu
ON product_menu.`id` = product_role.`menu_id`
INNER JOIN `hg_admin_menu` AS upload_menu
ON upload_menu.`permissions` = '/upload/file'
WHERE product_menu.`permissions` = '/product/edit'
AND product_menu.`status` = 1
AND upload_menu.`status` = 1;
-- HotGo 的 Casbin 策略持久化在独立表中,同步补齐已有角色的运行时策略。
INSERT INTO `hg_admin_role_casbin` (`p_type`, `v0`, `v1`, `v2`, `v3`, `v4`, `v5`)
SELECT 'p', role_row.`key`, '/upload/file', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''
FROM `hg_admin_role` AS role_row
WHERE role_row.`status` = 1
AND EXISTS (
SELECT 1
FROM `hg_admin_role_menu` AS role_menu
INNER JOIN `hg_admin_menu` AS menu_row ON menu_row.`id` = role_menu.`menu_id`
WHERE role_menu.`role_id` = role_row.`id`
AND menu_row.`permissions` = '/product/edit'
AND menu_row.`status` = 1
)
AND NOT EXISTS (
SELECT 1
FROM `hg_admin_role_casbin` AS policy
WHERE policy.`p_type` = 'p'
AND policy.`v0` = role_row.`key`
AND policy.`v1` = '/upload/file'
AND policy.`v2` = 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD'
);