From f866cac768d675947589240af526a9816fe68f8c Mon Sep 17 00:00:00 2001 From: Yvan <8574526@qq,com> Date: Wed, 4 Nov 2026 18:13:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8C=89=E5=8E=9F=E5=9E=8B=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=95=86=E5=8A=A1=E6=98=8E=E7=BB=86=E4=B8=8E=E6=B8=B8?= =?UTF-8?q?=E6=88=8F=E5=88=86=E6=9E=90=E5=B9=B6=E6=B8=85=E7=90=86=E4=B8=B4?= =?UTF-8?q?=E6=97=B6=E8=B5=84=E6=96=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 7 + AGENTS.md | 4 + cmd/analytics_http_test.go | 2 + cmd/ledger_http_test.go | 9 +- cmd/server_analysis_http_test.go | 2 + docs/API_REVIEW.md | 55 - docs/README.md | 5 +- docs/sw6-to-kra/README.md | 28 - docs/sw6-to-kra/alert-attachment-migration.md | 15 - docs/sw6-to-kra/analytics-source-notes.md | 31 - .../channel-portrait-source-notes.md | 31 - docs/sw6-to-kra/channel-source-notes.md | 55 - docs/sw6-to-kra/ledger-source-notes.md | 36 - docs/sw6-to-kra/portrait-source-notes.md | 43 - docs/sw6-to-kra/ranking-source-notes.md | 16 - docs/sw6-to-kra/report-build-source-notes.md | 64 - .../server-analysis-source-notes.md | 16 - .../sw8-sw9-recheck-summary-2026-11-04.json | 558 ------ docs/sw6-to-kra/sw_to_kra_migrate.sql | 1768 ----------------- docs/sw6-to-kra/system-api-audit.md | 50 - docs/sw6-to-kra/validation.md | 91 - docs/sw6-to-kra/workbench-source-notes.md | 26 - internal/biz/business/analytics.go | 9 + internal/biz/business/analytics_test.go | 19 + internal/biz/business/ledger.go | 13 +- internal/biz/business/ledger_test.go | 9 +- internal/biz/business/server_analysis.go | 22 +- internal/biz/business/server_analysis_test.go | 20 +- internal/data/business/analytics.go | 13 + internal/data/business/analytics_test.go | 1 + internal/data/business/approved_games.go | 28 + internal/data/business/approved_games_test.go | 62 + internal/data/business/ledger.go | 60 +- internal/data/business/ledger_test.go | 36 +- internal/data/business/server_analysis.go | 9 +- .../data/business/server_analysis_test.go | 25 +- web/src/view/sw/ServerAnalysis.vue | 21 +- web/src/view/sw/analysis-game-selection.js | 5 + web/src/view/sw/components/LedgerDetails.vue | 21 +- .../view/sw/components/ReportAnalytics.vue | 38 +- web/src/view/sw/table-display.js | 24 + 41 files changed, 392 insertions(+), 2955 deletions(-) delete mode 100644 docs/API_REVIEW.md delete mode 100644 docs/sw6-to-kra/README.md delete mode 100644 docs/sw6-to-kra/alert-attachment-migration.md delete mode 100644 docs/sw6-to-kra/analytics-source-notes.md delete mode 100644 docs/sw6-to-kra/channel-portrait-source-notes.md delete mode 100644 docs/sw6-to-kra/channel-source-notes.md delete mode 100644 docs/sw6-to-kra/ledger-source-notes.md delete mode 100644 docs/sw6-to-kra/portrait-source-notes.md delete mode 100644 docs/sw6-to-kra/ranking-source-notes.md delete mode 100644 docs/sw6-to-kra/report-build-source-notes.md delete mode 100644 docs/sw6-to-kra/server-analysis-source-notes.md delete mode 100644 docs/sw6-to-kra/sw8-sw9-recheck-summary-2026-11-04.json delete mode 100644 docs/sw6-to-kra/sw_to_kra_migrate.sql delete mode 100644 docs/sw6-to-kra/system-api-audit.md delete mode 100644 docs/sw6-to-kra/validation.md delete mode 100644 docs/sw6-to-kra/workbench-source-notes.md create mode 100644 internal/data/business/approved_games.go create mode 100644 internal/data/business/approved_games_test.go create mode 100644 web/src/view/sw/analysis-game-selection.js create mode 100644 web/src/view/sw/table-display.js diff --git a/.gitignore b/.gitignore index ecd1080..5725b71 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,10 @@ __pycache__/ # Local reference sources and desktop-only tooling state /gva/ /.claude/settings.local.json + +# One-off migration notes, verification scripts, and generated reports +/docs/sw6-to-kra/ +/docs/sw6tokra/ +/scripts/ +/test-results/ +/playwright-report/ diff --git a/AGENTS.md b/AGENTS.md index cd8d7bf..89aaa1a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -149,3 +149,7 @@ Regenerate via `make generate` or `make all`; never hand-edit `wire_gen.go`. `docs:`, `test:`. Regenerated files belong in the same commit as their source. - Never commit real credentials in `configs/config.yaml`. +- Do not commit one-off scripts, migration scratch notes, test reports, or + screenshots. Keep temporary work outside the repository and delete it after + use. Do not recreate `docs/sw6-to-kra/`, `docs/sw6tokra/`, or `scripts/`. + Permanent regression tests belong beside the source they cover. diff --git a/cmd/analytics_http_test.go b/cmd/analytics_http_test.go index a5f58c0..bc3e3fa 100644 --- a/cmd/analytics_http_test.go +++ b/cmd/analytics_http_test.go @@ -36,6 +36,8 @@ func TestChannelAndGameAnalyticsHTTP(t *testing.T) { "INSERT INTO sys_user_bind_platform(user_id,source_db,platform_busier_id,platform_busier_account,status) VALUES(9,'lx',14,'SDK账号','0'),(99,'hw',20,'其他账号','0')", "CREATE TABLE tab_promote(id INTEGER,source_db TEXT,account TEXT,promote_level INTEGER,top_promote_id INTEGER,busier_id INTEGER,register_type INTEGER)", "INSERT INTO tab_promote VALUES(100,'lx','root-channel',1,0,14,0),(101,'lx','child-channel',2,100,14,0),(200,'lx','guild-channel',1,0,14,1),(100,'hw','other-platform',1,0,20,0)", + "CREATE TABLE tab_promote_apply(source_db TEXT,promote_id INTEGER,game_id INTEGER,status INTEGER)", + "INSERT INTO tab_promote_apply VALUES('lx',100,1,1),('hw',100,1,1),('lx',200,2,1)", "CREATE TABLE tab_game(id INTEGER,source_db TEXT,game_name TEXT)", "INSERT INTO tab_game VALUES(1,'lx','当前游戏'),(2,'lx','公会游戏'),(1,'hw','外服游戏')", "CREATE TABLE tab_sw_report_day(source_db TEXT,promote_id INTEGER,game_id INTEGER,game_name TEXT,dedup_mode INTEGER,stat_date DATE,total_pay DECIMAL(20,2))", diff --git a/cmd/ledger_http_test.go b/cmd/ledger_http_test.go index ad4ac13..0fc1b15 100644 --- a/cmd/ledger_http_test.go +++ b/cmd/ledger_http_test.go @@ -43,6 +43,9 @@ func TestLedgerHTTPQueriesAndExcelExports(t *testing.T) { "INSERT INTO sys_user_bind_platform(user_id,source_db,platform_busier_id,platform_busier_account,status) VALUES(9,'lx',14,'sdk','0'),(99,'hw',20,'other','0')", "CREATE TABLE tab_promote(id INTEGER,source_db TEXT,account TEXT,promote_level INTEGER,top_promote_id INTEGER,busier_id INTEGER)", "INSERT INTO tab_promote VALUES(100,'lx','root-channel',1,0,14),(101,'lx','child-channel',2,100,14),(100,'hw','outside',1,0,20)", + "CREATE TABLE tab_promote_apply(source_db TEXT,promote_id INTEGER,game_id INTEGER,status INTEGER)", + "INSERT INTO tab_promote_apply VALUES('lx',100,1,1),('hw',100,1,1)", + "ALTER TABLE tab_promote ADD COLUMN nickname TEXT", "CREATE TABLE tab_game(id INTEGER,source_db TEXT,game_name TEXT)", "INSERT INTO tab_game VALUES(1,'lx','当前游戏'),(1,'hw','同号其他游戏')", "CREATE TABLE tab_user(id INTEGER,source_db TEXT,register_time TEXT,fgame_id INTEGER,fgame_name TEXT,register_ip TEXT,device_name TEXT,promote_id INTEGER,puid INTEGER)", @@ -107,7 +110,7 @@ func TestLedgerHTTPQueriesAndExcelExports(t *testing.T) { data := call(7, "GET", "/sw/register/list?sourceDb=lx&sortField=totalPayAmount", "", 0).(map[string]any) rows := data["rows"].([]any) first := rows[0].(map[string]any) - if data["total"] != float64(2) || first["userId"] != float64(1) || first["totalPayAmount"] != "1012.34" || first["fgameName"] != "历史游戏" || first["busierName"] != "sdk(leaf)" { + if data["total"] != float64(2) || first["userId"] != float64(1) || first["totalPayAmount"] != "1012.34" || first["fgameName"] != "历史游戏" || first["busierName"] != "owner→leaf" { t.Fatalf("注册明细口径或字段错误: %+v", data) } games := call(7, "GET", "/sw/serverAnalysis/games?sourceDb=lx&limit=50", "", 0).([]any) @@ -119,8 +122,8 @@ func TestLedgerHTTPQueriesAndExcelExports(t *testing.T) { t.Fatal("游戏筛选跨平台串号") } data = call(7, "GET", "/sw/spend/list?sourceDb=lx&payStatus=0", "", 0).(map[string]any) - if data["total"] != float64(1) || data["totalPayAmount"] != "15.34" { - t.Fatal("失败列表的合计仍须取对应成功订单") + if data["total"] != float64(1) || data["totalPayAmount"] != "0.00" { + t.Fatal("合计不得包含筛选条件外的成功订单") } data = call(1, "GET", "/sw/spend/list?sourceDb=lx", "", 0).(map[string]any) if data["total"] != float64(4) || data["totalPayAmount"] != "20.34" { diff --git a/cmd/server_analysis_http_test.go b/cmd/server_analysis_http_test.go index f8fd53b..c989508 100644 --- a/cmd/server_analysis_http_test.go +++ b/cmd/server_analysis_http_test.go @@ -37,6 +37,8 @@ func TestServerAnalysisHTTP(t *testing.T) { "INSERT INTO sys_user_bind_platform(user_id,source_db,platform_busier_id,status) VALUES(9,'lx',14,'0'),(99,'hw',20,'0')", "CREATE TABLE tab_promote(id INTEGER,source_db TEXT,promote_level INTEGER,busier_id INTEGER)", "INSERT INTO tab_promote VALUES(100,'lx',1,14),(101,'lx',2,14),(100,'hw',1,20)", + "CREATE TABLE tab_promote_apply(source_db TEXT,promote_id INTEGER,game_id INTEGER,status INTEGER)", + "INSERT INTO tab_promote_apply VALUES('lx',100,1,1),('hw',100,1,1)", "CREATE TABLE tab_game(id INTEGER,source_db TEXT,game_name TEXT)", "INSERT INTO tab_game VALUES(1,'lx','游戏'),(1,'hw','其他游戏')", "CREATE TABLE tab_game_server(id INTEGER,source_db TEXT,game_id INTEGER,server_num TEXT,server_name TEXT,start_time INTEGER)", diff --git a/docs/API_REVIEW.md b/docs/API_REVIEW.md deleted file mode 100644 index 10cfdd9..0000000 --- a/docs/API_REVIEW.md +++ /dev/null @@ -1,55 +0,0 @@ -# 当前接口审查(2026-11-04) - -## 范围 - -以 `internal/routecatalog/catalog.go` 与实际 Gin 注册为基线:共 **252** 个接口,其中商务 **55** 个(包括 4 个找回密码接口),原生框架 **197** 个。公开接口 15 个,其余 237 个均检查认证入口;分别在空前缀和 `/api` 前缀下执行未登录请求,共 **474** 项认证回归。 - -路由完整性与鉴权检查覆盖全部入口。按领域审查商务查询、权限范围、输入/排序/分页、写入事务、导出和定时任务,以及原生认证、权限、上传、支付、集成配置和审计的公共处理。真实外部支付、短信发送、OA 审批和所有原生管理写操作未在共享测试数据上逐一执行,不能将路由覆盖等同于这些外部流程全量验收。 - -## 本轮修复 - -| 问题 | 修改与回归 | -|---|---| -| 渠道激活只按商务账号名授权,跨平台同名可能串数据 | 列表和流水明细均按已通过绑定的“平台+账号”匹配;测试同名异平台、无绑定、管理员及状态范围 | -| 日期只传一端时被忽略,统计结果悄悄回到默认区间 | 商务列表、注册/充值、渠道/游戏统计、区服分析及排行榜统一拒绝不完整/非法/倒置范围;合法默认与单日保留 | -| 审计写入无 deadline,数据库异常可能拖住退出 | 每批写入限时 2 秒,Close 最多等 5 秒;关闭后拒绝入队,测试阻塞写入被取消 | -| 证书的 content/path/file 别名未脱敏 | 配置读回、掩码提交合并与审计共享识别;覆盖内联证书、密钥、PKCS12、嵌套字段和普通 content 字段 | -| 支付测试的结构化步骤消息透传适配器原始错误 | HTTP 返回安全错误和步骤信息,服务端保留诊断;避免 URL、凭据、SQL 经 data 字段泄露 | -| 已有错误弹窗时 401 回调被丢弃 | 会话失效立即清理并跳转,不依赖弹窗确认;旧请求不覆盖新令牌或注销新会话;真实 Chrome 验证 | -| Swagger 的环境判定与启动日志不同,空环境默认开放 | 配置统一判定,仅显式 dev/development/test/local 开放;启动地址和路由一致,包含缺省及 qa/uat 测试 | -| 媒体分类保存原名会把自身当重复记录 | 重名检查排除当前 ID,仍拒绝其他同名分类;媒体重命名缺失记录映射领域 NotFound | -| 偏好对比脚本在 HTTP 恢复失败时跳过数据库恢复 | 双层 finally 确保尝试恢复原行和更新时间 | - -本次提交也包含此前完成但尚未提交的迁移任务、SQL 修正、查询索引、性能优化及页面修复。性能和统计口径见 [商务验收](sw6-to-kra/validation.md)。 - -## 验证结果与数据漂移 - -- `make generate`、`go test ./...`、`go vet ./...`、服务构建通过;Wire 由工具重新生成。 -- 独立 MySQL 5.7 的 5 组测试通过:预警并发去重、渠道并发创建、注册 CAST 索引、区服时间索引、查询索引幂等及冲突拒绝。 -- 前端完整 ESLint 和生产构建通过;构建仍提示大分块及第三方 BigInt 目标兼容告警,没有把告警视为旧浏览器兼容验证。Chrome 实测覆盖另一个错误弹窗已打开时的 401 清理和跳转。 -- 新旧真实读取共 75 组:管理员 36,绑定三级 21,专用一级/二级/三级各 6。**73 组相等,2 组预警列表因数据快照不同而不等**,失败原始报告已保留。 -- 漂移核实:sw8 的预警在 **2026-11-04 14:00** 被更新,当前 480 条;sw9 为原快照 478 条,其中 55 个同 ID 记录的时间已不同。本机旧服务配置仍关闭调度,未从其日志确认更新来源;没有覆盖、删除或回写 sw8 的新记录。 -- 使用之前保存的同参数 sw8 快照重新核对当前 sw9 的完整预警列表,通过;报告明确 `source_capture_reused=true`。这证明当前列表符合该快照,不代表两库当前内容相等。 -- 新版已启动在日常 8000;8 组工作台、排行榜、激活第二页、偏好和任务注册结果与验证实例一致。 - -本轮原始报告位于仓库外 `D:/Users/Yvan/backups/sw9/20261104_rehearsal/review_20261104/`。此前完整写入/导出/重建及恢复证据见 [历史综合索引](sw6-to-kra/sw8-sw9-recheck-summary-2026-11-04.json)。本机无可用 CGO 编译环境,未运行 `-race`,不宣称竞态检测通过。 - -## 保留的框架风险与验证边界 - -旧审查材料中尚未消除的内容移到这里,避免删除历史文档时丢失问题。它们不属于“已修复”清单: - -| 范围 | 当前边界 | -|---|---| -| 媒体并发 | 删除只有进程内互斥,秒传复用创建与删除缺少统一的跨实例引用锁;长时间合并仍受陈旧会话清理宽限影响,需要独立并发/故障方案 | -| 配置保存 | storage、email 和配置文件分步持久化,中途失败可能形成部分成功;尚无跨存储的原子提交/补偿流程 | -| 历史支付订单 | 请求指纹严格匹配;缺少旧指纹样本的幂等重放验证,不直接放宽金额、业务身份的冲突检查 | -| 错误协议 | 框架仍有裸错误与字符串拼接、响应净化规则;此次堵住支付测试 data 泄露,但未统一全框架 typed error 协议 | -| 认证与前端路由 | token 仍由既有 localStorage 方案保存,登录与守卫仍各有动态路由注册;改成仅 HttpOnly cookie 或统一注册需要独立兼容设计 | -| 调度启动 | 永久非法 cron 会保持旧计划并继续启动重试;数据库读失败不清空既有计划,但固定重试间隔仍可改成有界退避 | -| 审计可读性 | 一些通用 key/序列号字段仍被旧脱敏策略掩盖;未为恢复可读性而放宽密钥保护 | - -## 文档与脚本清理 - -首次清理将 104 份阶段报告、重复 JSON、旧目录审查和独立菜单 SQL,以及 26 个旧脚本移出项目。用户追加要求后,剩余 14 个验证工具、脚本说明和 Python 缓存也全部移出,`scripts` 目录已删除。所有移除文件均在仓库外归档并校验 SHA-256;统一迁移 SQL、业务口径与综合验收索引保留。 - -真实本地配置 `configs/config.yaml`、私有运行数据,以及其他会话的 V2 估算和 outputs 成果不纳入本次提交。未推送远端。 diff --git a/docs/README.md b/docs/README.md index 4d6b49a..06daff1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,9 +1,6 @@ # 文档入口 -- [商务迁移](sw6-to-kra/README.md):统一 SQL、业务口径、接口与任务验收。 -- [当前接口审查](API_REVIEW.md):此次修复、验证范围及保留的技术风险。 - [后台说明](ADMIN_BACKEND.md)、[支付接入](PAYMENT.md)、[短信接入](SMS_INTEGRATION.md)。 - [OA 迁移计划](OA_MIGRATION_PLAN.md):独立 OA 工作的设计材料,不是当前商务迁移的完成证明。 -- [汇总任务说明](sw6-to-kra/report-build-source-notes.md):任务读写表及接口依赖;临时验证脚本已移出项目。 -历史阶段记录已归档到仓库外;后续将最新结果更新到对应维护文档,不再每个接口生成一份日期报告。其他会话生成的商务 V2 估算及表格保持原状,本次清理和提交不包含这些文件。 +此目录仅保留持续维护的文档。临时迁移笔记、验证报告和脚本用完即删,不纳入版本控制。 diff --git a/docs/sw6-to-kra/README.md b/docs/sw6-to-kra/README.md deleted file mode 100644 index 0bc8d9e..0000000 --- a/docs/sw6-to-kra/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# 商务迁移维护入口 - -旧 Java 商务使用测试库 **sw8**,当前 Go 商务使用 **sw9**。两库来自相同线上副本;未执行正式库 sw6 迁移。 - -## 执行顺序 - -1. 准备完整业务副本及 SQL 要求的 26 张框架源表,保存数据库备份。 -2. 在 [统一迁移 SQL](sw_to_kra_migrate.sql) 开头修改 `USE`,当前为 `USE sw9`。用支持 `DELIMITER` 的客户端在同一连接执行,遇错停止。 -3. 启动当前 Go 版本,执行版本迁移,补齐业务锁、密码重置表、附件引用和查询索引。大表首次建索引需要等待完成。 -4. 配置主库和 `lx`、`hw`、`yq`、`oa` 数据源。配置和凭据保存在仓库外;数据库连接信息不写入本目录。 -5. 对照 [验收记录](validation.md) 与 [汇总任务说明](report-build-source-notes.md) 复核接口和任务。迁入计划默认停用,启用前应确认业务所需运行时段。 - -SQL 自动区分首次迁移、已完成迁移的菜单调整和异常中间状态;不会对完成迁移的库重新导入账号。重复执行及旧表已归档/清理的路径均有演练记录。 - -当前 SQL v5 按 LF 规范化 SHA-256: -`07e2c8395b6f43f064fe973407f374a962b39d07474bfba68aeb2b3c5ffe8bf2`。 - -## 维护材料 - -- [验收与性能记录](validation.md):数据、任务、已知契约差异和性能基线。 -- [历史逐接口验收索引](sw8-sw9-recheck-summary-2026-11-04.json):63 项旧契约及 230 项检查;时间点为最近一次完整写入演练,不代表以后每轮都重跑写操作。 -- [原生系统接口与旧别名](system-api-audit.md)、[附件引用转换](alert-attachment-migration.md)。 -- 各域 `*-source-notes.md`:长期保留的查询、权限和统计口径。 -- [当前接口审查](../API_REVIEW.md):此次修复、测试范围与需继续验证的框架边界。 - -SQL 生成器位于旧仓库 `script/sql/sw6_to_kra/build_sw7_migration.py`。修改生成器后同步本目录统一 SQL,并重新核对散列及迁移结果;不要恢复分阶段 SQL 补丁。 - -阶段报告、重复 JSON、全部临时验证脚本已归档到本机仓库外 `D:/Users/Yvan/backups/sw9/20261104_rehearsal/cleanup-archive/`,最后保留的工具位于其中的 `scripts-final/`。项目不再保留 `scripts` 目录,Go 任务运行不依赖这些脚本。归档及相邻的运行配置、原始响应、分区备份不纳入 Git。历史索引中 `reports` 项的文件名可在归档内查找。 diff --git a/docs/sw6-to-kra/alert-attachment-migration.md b/docs/sw6-to-kra/alert-attachment-migration.md deleted file mode 100644 index 63207fd..0000000 --- a/docs/sw6-to-kra/alert-attachment-migration.md +++ /dev/null @@ -1,15 +0,0 @@ -# 预警日志附件的文件 ID 迁移补充 - -现有 `sw_to_kra_migrate.sql` 为 `sys_oss.oss_id` 建立 `entity='file'` 映射并导入 `media_file_upload_and_downloads`,同时只更新预警操作日志的操作人 ID,没有转换 `attachment_ids` 中的文件 ID。日志数字数组仍引用旧文件,不能直接当成 Kra 文件 ID 查询。 - -代码迁移步骤 `202611030007_business_alert_attachments` 在服务启动的迁移流程中执行,不修改用户提供的 SQL。最终数据库复制验收时,先完成原 SQL,再启动包含本步骤的新服务。 - -处理规则: - -1. 新库没有旧日志备份和映射表时不执行转换。 -2. 按日志 ID 与 `bak_sw2kra_20261103_sys_alert_operation_log` 关联,只处理当前附件与旧备份一致的纯数字数组,兼容 JSON 数字和数字字符串。 -3. 根据文件映射写入新文件 ID,保留原数组顺序。没有旧文件映射的引用原本无法展示,转换后不指向任何同号新文件;原始引用仍在备份中保留。 -4. URL 数组、混合 URL 数组、新日志、已改动的旧日志均不转换。分批查询和事务写入,重复执行不会二次映射。 -5. 运行时附件解析支持数字 ID 与 URL;文件查询分批执行,已删除或不存在文件不展示。大数字 ID 在解析及返回过程中不经过浮点数。 - -隔离测试覆盖超出 JavaScript 精确整数范围的旧 ID、失效引用、新旧文件同号、URL、新日志、已转换日志及重复执行。最终实库验收应以旧、新附件解析出的 URL 对比,而不是要求转换后的 JSON 字节仍与旧 ID 数组一致。 diff --git a/docs/sw6-to-kra/analytics-source-notes.md b/docs/sw6-to-kra/analytics-source-notes.md deleted file mode 100644 index 228e70a..0000000 --- a/docs/sw6-to-kra/analytics-source-notes.md +++ /dev/null @@ -1,31 +0,0 @@ -# 渠道统计与游戏分析核对 - -核对基线至旧后端 main 最终代码中的 `ChannelDataServiceImpl`、`GameDataServiceImpl`、`BusinessBindScopeServiceImpl`、`ReportQueryScopes` 及日汇总/身份键 Mapper;页面直接核对旧 `ChannelDataStatistics.vue` 与 `GameAnalytics.vue`。 - -## 数据与范围 - -- 数据来自 `tab_sw_report_day` 和 `tab_sw_report_day_key`,金额固定 `dedup_mode=0`,人数按查看者的身份证偏好。金额用精确十进制处理,保留两位。 -- 渠道查询保留本人/下级绑定范围和“包含下级渠道”开关;模糊查询匹配账号,不匹配昵称。开启下级时,命中的下级扩展到同根渠道树,再与原权限范围、类型筛选取交集。 -- 金额根渠道:一级用自身,否则正 top ID,再否则自身。人数根渠道沿用旧 SQL 的 `COALESCE(NULLIF(top_promote_id,0),promote_id)`;两者在异常历史层级数据上可能不同,不能擅自统一。 -- 超管全平台、包含下级且无渠道筛选时包含官方 0 号和已无渠道资料的历史行;普通商务只返回允许展示的根渠道。 -- 游戏分组按平台+游戏 ID,过滤 `game_id > 0`。游戏名称筛选使用报表中的历史名,展示使用 `tab_game` 当前名。 -- 渠道商务名称先用平台商务账号,否则 SW 用户名;此处不追加画像/明细页面使用的括号用户名。 - -## 汇总与计算 - -- 游戏 summary 累加全部筛选后游戏行,与当前页无关。相同身份出现在不同游戏时分别计数,不做全局去重。 -- 普通商务渠道 summary 累加可见行。超管渠道 summary 使用筛选范围内全局去重;模式 0 按平台前缀区分身份,模式 1 跨平台去重。 -- 付费率=充值人数÷活跃人数×100,ARPU=充值金额÷活跃人数,ARPPU=充值金额÷充值人数。分母为零时为零。 -- 保留原逐行人数的 Java int 上限,游戏汇总改用 int64 避免相加溢出。相同排序值使用平台、ID 稳定排序。 -- 后端不传日期时周期为上海当天,只传一端会拒绝;前端默认近 30 天含今天。后端页长缺失、非正或超过上限时为 500,页面显式传 10。 -- 缺少必要数据表时 `available=false`、`summary=null`,顶部指标为 null,不把缺表当成零。 - -## 验证与优化 - -- 使用聚合查询和批量资料查询代替逐行查询,不改变业务口径。日期非法或倒置返回明确错误。 -- 数字指标先按全部统计行计算汇总、排序和分页,再补当前页的渠道/游戏名称及商务资料;按渠道名称或渠道类型排序时仍先补全体资料。空页不读取资料,官方及未知渠道标签保持原规则。 -- 需要渠道权限或渠道筛选时,报表通过平台+渠道 ID 的 IN 子查询匹配可见渠道,保留原绑定、层级、名称和类型条件,使 MySQL 5.7 能使用半连接处理。 -- 隔离 TCP HTTP 和仓储测试覆盖全量汇总与分页、跨平台同号、官方/孤立渠道、根渠道树去重、类型交集、历史游戏名过滤、当前资料展示、偏好切换及空范围。 -- 领域测试覆盖大金额精确排序、分母和人数上限。前端检查筛选回第一页、30 天默认值、汇总不随分页变化、缺数据提示、没有额外导出入口。 - -当前验证状态统一见 [验收与性能记录](validation.md),不再维护阶段性运行报告。 diff --git a/docs/sw6-to-kra/channel-portrait-source-notes.md b/docs/sw6-to-kra/channel-portrait-source-notes.md deleted file mode 100644 index 690bb89..0000000 --- a/docs/sw6-to-kra/channel-portrait-source-notes.md +++ /dev/null @@ -1,31 +0,0 @@ -# 渠道画像迁移核对 - - -## 数据范围与基本资料 - -- 先按当前商务本人/下级的正常绑定校验渠道可见性,平台与渠道 ID 组合定位;超管不限。 -- 统计树与原渠道画像 helper 一致:关闭下级只看自身;二级看自身及直属三级;一级看自身及同平台 top/parent 对应的渠道。 -- 基本信息包含昵称、账号、负责人、级别、审批状态、注册类型、注册/登录时间、归属商务、上级渠道与已通过推广游戏数。一级渠道不显示父级;其他渠道的父级账号从同平台记录重新读取。 -- 画像状态取 status,与列表锁定状态不同:0 待审核、1 正常、-2 驳回、-3 商务新增。第四张指标卡是活跃人数,不能套用商务画像的人均充值。 - -## 时间与累计 - -- 支持 today、yesterday、last7、last30、total;累计起点取当前人数去重模式的最早日汇总,缺省上海当天。 -- 累计模式无对照期,compareValue/changeRate/changeDiff/compareLabel 均为空;其他周期保持原对比规则。 -- 游戏分布和付费分层始终按累计身份范围,与顶部指标周期独立。 -- 今日/昨日趋势读取原始主账号和成功支付;其余按日汇总。金额固定模式 0,人数遵守全局去重偏好。 - -## 付费分层 - -- 参与者是累计注册身份键集合,重复键只计一次;无键时保留原注册人数回退规则。 -- 分层金额来自统计渠道树内的所有历史成功支付,没有支付时间过滤。因此历史或未来时间戳的支付仍可能影响已注册身份的分层,不擅自改成顶部日期范围。 -- 模式 1 按付款用户的原始 idcard 汇总,再按旧 trim/末尾 X 规则归一并合并;不擅自加主账号过滤或把子账号付款并到父账号。模式 0 按原始付款 user_id 汇总,并使用平台前缀与注册身份对应。 -- 大R ≥10000,中R ≥1000 且 <10000,小R >0 且 <1000,其余免费。先按旧金额规则保留两位再归档,比例独立保留一位,不强制凑成 100%。未出现在注册集合中的付款人不增加分层人数。 - -## 修复的旧页面参数错误 - -- 旧“近7天/近30天”发送 7d/30d,而旧后台只识别 last7/last30,导致回退今日;新页面发送后台正式参数。 -- 旧关联预警误将渠道 ID 传入 businessId;新页面使用 targetPromoteId 与 platformCodes,并继续由预警接口执行查看者数据范围隔离。 -- 小R/免费区间文案按实际后端 >0 / ≤0 调整,避免把小于一元的付费玩家误解为免费。 - -当前验证状态统一见 [验收与性能记录](validation.md),不再维护阶段性运行报告。 diff --git a/docs/sw6-to-kra/channel-source-notes.md b/docs/sw6-to-kra/channel-source-notes.md deleted file mode 100644 index f7ea6e7..0000000 --- a/docs/sw6-to-kra/channel-source-notes.md +++ /dev/null @@ -1,55 +0,0 @@ -# 渠道列表与新增渠道:源码核对记录 - - -## 页面 - -来源 `sw/web/src/views/BusMgmt/ChannelList.vue`、`components/AddChannelDrawer.vue`、`components/ChannelGameDrawer.vue`。 - -- 筛选:平台默认全选、商务账号、关键词、渠道层级、注册类型、锁定状态。实际关键词后端只查询渠道账号;旧占位文案“渠道账号 / 负责人姓名”与实现不一致。 -- 列:平台、ID、渠道账号、渠道层级、归属商务、上级渠道、负责人、渠道类型、推广游戏、玩家数量、累计充值、锁定状态、画像。没有编辑入口。 -- 列表的注册类型选项只有“个人 0 / 公会 1”,其余选项被注释;新增抽屉则是“个人 0 / 企业 1”,不能擅自根据其中一处统一名称。 -- 状态筛选及列使用 `lockStatus`:0 正常、-1 已锁定、-2 解除合作,与渠道审批字段 `status` 不同。 -- “添加渠道”只按按钮权限判断,旧代码没有额外要求三级商务。游戏商务下拉随平台变化加载,选项取平台商务 ID 并去重。 -- 新增字段:平台、游戏商务、推广类型、渠道账号、密码。账号为 `[\u4e00-\u9fa5a-zA-Z0-9]{4,30}`,提交前 trim;密码原值保留,按 Java UTF-16 长度 6–15 校验。 -- 推广游戏与画像均是右侧抽屉,必须同时传 `sourceDb` 与渠道 ID。游戏抽屉调用 `/system/promote/game-distribution`,累计口径,列为游戏、玩家数量、充值金额。画像已迁移。 - -## 列表权限和查询 - -来源 `PromoteServiceImpl`、`BusinessBindScopeServiceImpl`、`BusierAccountFilters`。 - -- 非超管查询本人及全部下级的已通过平台绑定,三级仅本人。列表自身并不会因全局“包含下级渠道”关闭而只列一级;该偏好用于指标聚合。 -- 超管默认不限绑定;一旦指定 `busierUserId` 或商务账号关键词,必须按匹配绑定收窄。 -- `busierUserId` 是指定用户本人绑定,不能套用预警筛选“该商务及全部下级”的语义。 -- 商务账号关键词在 Java 中按忽略大小写的文字子串匹配平台商务账号或 SW 用户名。`%`、`_` 在这里是普通字符,不能随意变成 SQL 通配符。 -- 平台商务与渠道以 `(source_db, busier_id)` 关联,跨平台同号不得混用。用户名展示为 `平台账号(SW用户名)`;两者相同或其中为空时不重复拼接。 -- 支持平台、层级、注册类型、审批状态、锁定状态、渠道账号关键词。默认按创建时间、ID 倒序;新增稳定的平台排序可用于跨平台同号并列。 - -## 列表指标 - -来源 `PromoteListMetricsSupport`、`PromotePortraitScopeHelper` 和三个 Mapper。 - -- `gameCount`:`tab_promote_apply.status=1`,按该行渠道自身去重 `game_id`;不随包含下级扩展。 -- `playerCount`:`tab_user` 主账号(`puid=0 OR puid IS NULL`)。不去重时累计行数;身份证去重时在整棵统计树内去重,空证件不计入。 -- 身份证规范化仅 trim,并将末尾大写 X 改为小写 x,不能做额外证件合法性校验或把无证件用户按 ID 计入。 -- `totalPayAmount`:`tab_spend.pay_status=1` 累计 `pay_amount`,不按身份证去重,也没有日期上限。 -- 关闭包含下级、层级为空或 >=3:只统计当前渠道。二级:本级与 `parent_id=当前ID AND promote_level=3`。一级:本级与同平台 `top_promote_id=当前ID OR parent_id=当前ID`。 -- 注意一级旧加载函数还会加载第二跳子渠道,但最终 `PromotePortraitScopeHelper` 再按 top/parent 条件过滤;不能仅看加载函数就扩大最终统计集合。 - -## 源平台创建事务 - -来源 `PlatformPromoteWriteServiceImpl`、`PlatformTabPromote`、`TabPromoteSettlementTime`、`TabPromoteBusinessMapper`。 - -1. 先验证当前用户可用的已通过绑定与目标平台商务匹配,再进入对应 `lx/hw/yq` 源库写入事务。 -2. 源库 `tab_promote` 账号不得重复。密码为 `XiguPasswordUtils.cmfPassword` 格式,需要复用已有环境盐适配器,不能用 Kra 登录密码算法替换。 -3. 新渠道 `status=-3`、`promote_level=1`、`parent_id=0`、`top_promote_id=0`、`game_ids2=''`,注册类型默认 0;时间为 Unix 秒。 -4. 同事务创建 `tab_promote_settlement_time`:`time_type=0`、`day_period=7`,下一次结算为当前秒数加 7 天。 -5. 游戏商务必须存在,原子追加新渠道 ID 到 `tab_promote_business.promote_ids`,避免并发覆盖;任一步失败整体回滚。 -6. 返回新 ID 与 `sourceDb`,原成功文案提示“添加成功,数据同步到列表可能有延迟”。不直接制造主库同步副本,不在真实平台库创建测试渠道。 - -## 游戏分布的已核对依赖 - -游戏分布依赖 `PromotePortraitServiceImpl.buildGameDistribution`、`SwReportDayQueryServiceImpl` 和日汇总/身份键 Mapper。当前实现只列根渠道已通过的游戏,用同渠道统计树读取日汇总:人数对 metric=1 的 identity_key 去重,dedup_mode 随偏好;金额固定 dedup_mode=0。累计起点从当前人数模式的最早日汇总取得,缺失则使用上海当天,即使模式 0 有更早数据也不改写该起点。截止上海当天,排除未来日期。先将金额保留两位再按金额降序、游戏 ID 升序排列。 - -完整渠道画像已接入,规则及验证见 `channel-portrait-source-notes.md`。报表汇总任务、预警生成任务和最终实库验收仍属于后续范围。 - -当前验证状态统一见 [验收与性能记录](validation.md),不再维护阶段性运行报告。 diff --git a/docs/sw6-to-kra/ledger-source-notes.md b/docs/sw6-to-kra/ledger-source-notes.md deleted file mode 100644 index a95896a..0000000 --- a/docs/sw6-to-kra/ledger-source-notes.md +++ /dev/null @@ -1,36 +0,0 @@ -# 注册与充值明细迁移核对 - -已接入注册/充值列表、对应 XLSX 导出,以及页面依赖的游戏下拉接口。来源为旧 `RegisterServiceImpl`、`SpendServiceImpl`、`BusinessBindScopeServiceImpl`、`ReportQueryScopes` 和实际明细 Vue 页面。 - -## 查询口径 - -- 注册列表严格 `puid=0`,不包含 NULL,也不受身份证去重开关影响。注册时间使用 Unix 秒;未传完整日期时默认截至昨日的七天,页面主动传入的默认范围则是含今日的近30天。 -- 注册累计充值按同平台+玩家 ID 汇总全部历史成功支付,不受本次注册日期和渠道过滤影响,也不归并子账号。 -- 充值列表按选定状态过滤;成功支付合计强制 pay_status=1,忽略选定状态,保留其余过滤。因此筛选失败订单时合计仍可非零。 -- 充值保留历史游戏名和渠道账号,注册保留首登游戏名快照。渠道资料缺失时依次保留历史账号、显示官方渠道(ID=0)或未知渠道及 ID。 -- 游戏选项来自平台游戏表,列表按游戏名称传参;注册游戏筛选通过同平台游戏 ID 关联,充值直接筛订单的游戏名快照。 - -## 可见范围 - -- 普通商务只用本人和下级正常绑定;三级只用本人。指定商务账号按平台账号或 SW 登录名的文字子串收窄。 -- 渠道账号为区分大小写的精确匹配。包含下级时,先解析命中渠道所属一级树,再与原可见渠道范围取交集;不包含下级时只保留一级。 -- 超管未按商务/渠道收窄且包含下级时,可以看到官方和已无当前渠道资料的历史数据;其他情况必须命中真实可见渠道。 -- 所有平台实体关联均带 source_db,不将同号玩家、渠道或游戏混为同一条。 - -## 修复与优化 - -- 修复旧注册游戏 EXISTS 内未限定外层 source_db 导致跨平台串号。 -- 保留旧累计充值排序已修复的外层用户关联,并按数值注册时间排序。 -- 移除“命中超过200个渠道后退回全平台”的筛选失效行为;用相关 EXISTS 表达渠道树,不需要把大量 ID 拼进请求。 -- 只读取当前页/导出范围所需的渠道与绑定资料,累计充值按玩家组合键分批查询。 -- 注册导出按钮使用正确的注册导出权限,不再误用充值导出权限;充值 ID 列不显示后台不支持的排序箭头。 - -## 导出与页面 - -- 超过10000条在读取完整结果和生成工作簿前拒绝;缺业务表不导出假空数据,确定无匹配绑定可导出只有表头的工作簿。 -- 保留原 VO 导出字段顺序,包括没有中文 ExcelProperty 的辅助字段;时间保留 Unix 秒,状态/方式保留原代码。 -- 数值直接写入数值 XML,不先转 float64;账号、订单号等强制文本,保留前导零并避免当作公式。 -- 页面按旧模板提供筛选、游戏远程下拉、日期快捷项、排序、分页、导出;充值金额≥5000的行高亮。查询失败会清除旧行和旧合计。 -- 游戏下拉的默认/批量 limit 行为沿用旧接口;区服分析的 servers/list 现已完成迁移。 - -当前验证状态统一见 [验收与性能记录](validation.md),不再维护阶段性运行报告。 diff --git a/docs/sw6-to-kra/portrait-source-notes.md b/docs/sw6-to-kra/portrait-source-notes.md deleted file mode 100644 index 25d2215..0000000 --- a/docs/sw6-to-kra/portrait-source-notes.md +++ /dev/null @@ -1,43 +0,0 @@ -# 商务与 SDK 商务画像源码核对 - -两种画像接口、三个页面入口及报表读取已实现。接口、平台数据源及账号状态验证统一见 `validation.md`。 - -## 范围与入口 - -- `GET /sw/business/:userId/portrait`:普通商务画像。旧 `BusinessPortraitQueryBo` 取 `sourceDbList`,必须选择平台;不是渠道接口的 `sourceDb` 参数。通过目标商务本人及下级的正常绑定解析渠道范围。 -- `GET /sw/business/bindPlatform/portrait`:指定 `sourceDb` 与 `platformBusierId` 的正常绑定,校验当前登录人的可见范围。基本资料读取对应平台 `tab_promote_business`,不能用 SW 用户资料冒充。 -- 两种画像共用旧 `BusinessProfileDrawer.vue`。商务列表“画像”、绑定正常行“画像”、只读 SDK 绑定详情的平台入口都需要接上;此前移除的“编辑”不能恢复。 -- SDK 基本信息中 `userId` 实际是平台商务 ID。关联预警及旗下渠道的查询仍应使用打开抽屉时的 SW 用户 ID 和绑定参数,不能误用这个平台 ID。 - -## 基本信息 - -- 普通商务:账号、姓名、级别、父商务账号/姓名、创建时间、审核状态;渠道数只数所选范围内一级渠道,本月新增判断渠道创建 Unix 秒位于上海本月首日(含)至明天零点(不含)。 -- SDK 商务:账号、姓名、级别、创建 Unix 秒。二级的父商务是 `commerce1`,三级是 `commerce2`,一级没有父级;父记录不存在时不填父资料。 -- SDK 状态与 SW 不同:SDK 的 1 为正常、0 为待审核、其余为停用;不能把 SDK 字符串 `"0"` 套用成 SW 正常。 -- 普通商务画像的渠道数包含目标商务的下级绑定;旧“旗下渠道”抽屉接口仍是直属口径,需要保留并记录两者差异。 - -## 时间、卡片与趋势 - -来源:`BusinessPortraitServiceImpl`、`BusinessPortraitSupport`。 - -- 画像服务支持 today、yesterday、last7、last30、thismonth,大小写归一,空/未知回退 today。公共 helper 另外支持 total,但普通商务画像服务不接受 total;渠道画像才使用累计模式。 -- today 对比昨日;yesterday 对比前日;last7/last30 包含今天并对比前一完整同长周期;thismonth 对比上月首日至相同日号,上月不足该日时截到月末。 -- 注册玩家来自日汇总身份键的 REGISTER=1;付费率为 PAY=3 人数 / ACTIVE=2 人数 ×100,保留 1 位;人均充值为金额 / 注册人数,保留 2 位。 -- 当前活跃为零时付费率为 0.0;对照期活跃为零时 compareValue 为 null,百分点差也为 null。 -- 注册、金额、ARPU 的相对变化率为 `(current-previous)*100/previous`,保留 1 位;对照为零/null 时 changeRate 为 null。付费率用 changeDiff 百分点差。 -- today/yesterday 的趋势读取原始主账号注册与成功支付,补齐 24 个小时;小时注册趋势不做身份证去重。MySQL 与原 Mapper 一致使用 `HOUR(FROM_UNIXTIME(...))`,原服务与新服务的数据库会话时区在最终实库验收时核对;SQLite 测试按传入上海日边界计算小时。 -- 其他周期趋势来自日汇总/身份键,按天补零。金额查询固定 dedup_mode=0;人数随当前登录人的偏好。 -- 跨平台不去重人数需要给身份键加 source_db 前缀;身份证去重模式按身份键跨平台去重。具体 SQL 在 `TabSwReportDayKeyMapper.xml` 的 summary / summaryByDate 中。 - -## 排行和关联预警 - -- 注册 TOP 5 经 `ChannelTreeMetricsSupport.countRegisterByDisplayChannel` 汇总:含下级时按源平台和一级渠道树 COUNT DISTINCT;一级取自身 ID,其他渠道 top_promote_id>0 时取 top,否则取自身 ID。不能把子渠道人数简单求和。人数先按旧 int 上限归一,再排序和截取 TOP 5。 -- 充值 TOP 5 先按渠道取金额,再按 `resolveRootPromoteId` 归根;同平台分组,过滤 <=0,只取前五。按值降序、渠道 ID 升序,返回 rank、平台、渠道 ID/账号、value(保留两位)。 -- 关联预警不在画像 DTO 中,由前端独立请求 `/sw/alertRecord/list`,参数为 `platformCodes`、SW `businessId`、分页。 -- 旧 SDK 画像的预警仍按 SW 商务及平台筛选,没有单独按 platformBusierId 收窄;需按实际模板核对,不从基本资料 ID 推断范围。 - -## 验证与实现要求 - -沿用 DTO → service → biz → data,金额用精确计算,页面采用 Kra 图表/表格风格。不要在 stats 缺表时伪造零;没有任何绑定是已知空范围,可返回真实零和零趋势,有绑定但渠道/汇总未接入时保留可读取基本信息并明确未知指标。 - -当前验证状态统一见 [验收与性能记录](validation.md),不再维护阶段性运行报告。 diff --git a/docs/sw6-to-kra/ranking-source-notes.md b/docs/sw6-to-kra/ranking-source-notes.md deleted file mode 100644 index 305c437..0000000 --- a/docs/sw6-to-kra/ranking-source-notes.md +++ /dev/null @@ -1,16 +0,0 @@ -# 独立排行榜迁移核对 - -来源为旧 main `RankServiceImpl`、`RankController`、日汇总和身份键 Mapper,以及 dev/dev1.0 `RankingAnalysis.vue`。 - -- `/sw/rank/channel`、`business`、`game` 各返回注册、充值、付费率、活跃四组 TOP20。日期缺一项时默认上海当天,前端默认近 7 天。上期为当前开始日之前的等长连续区间。 -- 渠道榜金额和人数均使用旧 `COALESCE(NULLIF(top_promote_id,0),promote_id)` 分组,即使不包含下级也保留根算法。不能复用工作台的 CASE 根算法或注册榜 INNER JOIN;真实历史异常 top ID 已有测试覆盖。 -- 游戏榜按平台+游戏 ID,展示当前游戏名,缺名为“游戏ID”。objectId 保留 `source|id`;渠道 objectId 为 ID 字符串。旧 query 的 gameId 实际没有用于筛选,新接口保留其无筛选行为,页面不添加旧模板不存在的游戏选择器。 -- 商务榜超管列出一/二/三级商务,普通商务看直属下级,三级空榜。每个被展示商务的数据来自本人及全部下级的正常绑定渠道。一次关系查询展开目标、下级、绑定、渠道,代替旧每个目标单独查询下级的 N+1;查询条件保持各目标自己的祖先路径范围。 -- 商务人数累加各渠道人数,不做跨渠道全局去重;金额累加同一组渠道。逐渠道保留 Java int 上限,商务总数采用 int64 避免旧 int 溢出。祖先与下级可以分别上榜;不是互斥分区。 -- 注册、充值、活跃只展示正值;付费率只要求活跃大于 0,保留 0% 行。金额固定模式 0,人数取当前偏好。 -- 2026-11-04 按用户要求,四榜环比统一为 `(本期值 - 上期值) / 上期值 × 100%`。上期没有有效数据或为零时为 null;本期付费率降到零且上期为正时为 -100%。付费率原来的百分点差已改为相对增幅,这是迁移后明确采用的新口径。金额展示先保留两位,金额环比用未舍入汇总,与旧服务一致。 -- 环比保留两位,绝对值小于 0.01 为持平。数值排序用精确有理数,同值追加平台/ID 稳定排序,截取后连续编号。 -- 源码还核对了空平台含义:独立排行榜空选表示全部,区别于工作台必须选平台。非法/倒置日期明确拒绝。缺报表时 available=false 和空数组,不伪造零指标或空查询成功。 -- 当前菜单名称、父级和路径已通过实际菜单接口核实,仍为 `sw_DataAnalysis` 下 `sw_RankingAnalysis` / `RankingAnalysis`。 - -当前验证状态统一见 [验收与性能记录](validation.md),不再维护阶段性运行报告。 diff --git a/docs/sw6-to-kra/report-build-source-notes.md b/docs/sw6-to-kra/report-build-source-notes.md deleted file mode 100644 index e57dfe0..0000000 --- a/docs/sw6-to-kra/report-build-source-notes.md +++ /dev/null @@ -1,64 +0,0 @@ -# 日汇总和区服汇总任务迁移 - -核对旧 main 的两个 `SwReport*BuildServiceImpl`、两个 SnailJob 执行器、`ReportIdentityHelper` 和 `ReportBuildRangeSupport`。 - -## 原始数据口径 - -- 日汇总注册只取 `tab_user.puid=0`,注册时间按原 `CAST(register_time AS UNSIGNED)` 语义。按平台、渠道、首次游戏分组。 -- 日汇总活跃来自 `tab_user_day_login`,必须能找到同平台主账号。记录无平台时,仅当全库同 ID 恰好一个主账号时才接受;跨平台存在多个主账号时跳过。缺渠道回退账号的渠道。 -- 日汇总充值取当天成功支付,金额不限制主账号;付款用户不存在时模式 0 仍计账号,模式 1 因无身份证不计身份。没有付款用户 ID 的成功单仍计金额。 -- 新增付费先取同一分组内“当日注册账号 ∩ 当日付费账号”,再转身份证;不能直接用身份证交集,否则会把同证件的其他账号误认成新增付费。 -- 区服注册取 `tab_user_play_info.create_time` 的创角,活跃取 `play_time`,不套用日注册/登录的主账号限制。区服编号去首尾空白,保留前导零;创角/活跃缺游戏 ID 时忽略,充值缺游戏 ID 沿用 0。区服汇总没有新增付费指标。 -- 两类报表均按日、平台、渠道、游戏(区服额外编号)生成模式 0/1 两行及对应身份键。模式 1 去首尾空格、仅将末尾 X 转 x,空身份证丢弃。金额两种模式相同,查询层仍固定读取模式 0。 -- 游戏名作为当前游戏资料的快照写入。已知平台的用户按平台分组、ID 排序后分批加载;缺平台的事件仍读取全部同号用户以判断唯一主账号。平台作为字典键的一部分,不混淆跨平台同号。 - -## 原子替换与任务 - -- 所有原始数据读取、计算和两张报表替换在同一事务。按报表类型+日期的锁表串行同分区重建,避免不同任务同时回跑同一天。读不到必要源表/目标表时拒绝重建,不清空既有数据。 -- 汇总、身份键按批写入,失败或取消回滚原有分区;其他日期不变。输出日期固定 `yyyy-MM-dd`,不采用驱动返回的时间格式作为写入日期。 -- 任务方法保留 `swReportDayTodayTask` / `YesterdayTask` / `BackfillTask` 和对应 `swReportServerDay*` 六个名字。已有迁移 SQL 保留旧执行器名和 `_execution` 参数,可直接绑定 Kra 方法执行器。 -- 回跑参数为 startDate/endDate;每个缺省日期独立取昨日,闭区间逐日重建、日间暂停一秒,最后一天不暂停。支持上下文取消,非法/倒置日期报错。 -- 迁移本身不新建默认商务计划、不启用旧导入计划;实际运行状态由管理员单独配置。原始同步表和四张业务报表表沿用旧库结构,不在系统库中伪造完整业务数据源。 - -## 验证边界 - -领域与存储测试覆盖身份/账号规则、重复构建、自然日筛选和身份明细写失败后的原子回滚。真实 TCP HTTP 使用隔离数据库和 Kra 原生任务创建、手动触发、执行日志,核对两种报表实际落库且任务仍为禁用。 - -当前验证状态统一见 [验收与性能记录](validation.md),不再维护阶段性运行报告。 - -## 任务、表与接口的对应关系 - -这些任务是 Go 内部注册的方法,与已删除的临时验证脚本无关。它们从当前主库读取已同步的原始数据,再生成统计结果;不负责将 SDK 平台数据同步进主库。当前运行服务主库为 sw9。 - -| 任务方法 | 日期范围 | 写入的统计表 | -|---|---|---| -| swReportDayTodayTask | 上海时区今天 | tab_sw_report_day、tab_sw_report_day_key | -| swReportDayYesterdayTask | 上海时区昨天 | 同上 | -| swReportDayBackfillTask | startDate 至 endDate,含两端 | 同上 | -| swReportServerDayTodayTask | 上海时区今天 | tab_sw_report_server_day、tab_sw_report_server_day_key | -| swReportServerDayYesterdayTask | 上海时区昨天 | 同上 | -| swReportServerDayBackfillTask | startDate 至 endDate,含两端 | 同上 | - -商务日报读取 `tab_user`(主账号注册及身份资料)、`tab_user_day_login`(登录)、`tab_spend`(成功充值)、`tab_game`(游戏名)。区服日报读取 `tab_user_play_info`(创角 create_time、活跃 play_time)、`tab_spend`、`tab_user`、`tab_game`。 - -`tab_sw_report_day` 按日期、平台、渠道、游戏、去重模式保存注册数、活跃人数、付费人数、新增付费人数和充值金额。`tab_sw_report_server_day` 在相同维度上增加区服,注册数代表创角玩家数,不包含新增付费人数。 - -两个 `_key` 表保存参与统计的身份键,供跨日期、渠道或游戏聚合时重新 `COUNT(DISTINCT identity_key)`。例如同一玩家连续两天活跃,查询这两天的独立活跃人数应为 1,不能直接将两个日活人数相加。`dedup_mode=0` 使用账号 ID,`dedup_mode=1` 使用规范化身份证;空身份证不计入模式 1。`metric` 为注册 1、活跃 2、付费 3,商务日报另有新增付费 4;金额查询只读模式 0,避免两种模式重复累加。 - -每次重建会在一个事务内锁定“报表类型+日期”,读取原始数据,删除统计表及对应 key 表该 `stat_date` 的旧行,批量写入新结果。读取或写入失败、取消时回滚;每个日期单独提交,回跑中途失败不会撤销此前已完成日期。除统计表外,会使用 `sys_business_report_build_locks` 保存互斥锁键,任务执行框架将结果记入 `sys_timed_task_logs`。原始用户、充值和登录记录不会被这些任务改写。 - -| 使用方 | 接口 | 依赖 | -|---|---|---| -| 渠道数据统计 | GET /sw/channelData/list | 商务日报两表 | -| 游戏数据 | GET /sw/gameData/list | 商务日报两表 | -| 三类排行榜 | GET /sw/rank/channel、/business、/game | 商务日报两表 | -| 仪表盘/工作台 | GET /sw/workbench/summary、/registerTop、/payRank | 商务日报两表;汇总中的新增渠道另查渠道表 | -| 商务画像 | GET /sw/business/:userId/portrait、/sw/business/bindPlatform/portrait | 商务日报两表 | -| 渠道画像及游戏分布 | GET /sw/promote/portrait、/sw/promote/game-distribution | 商务日报两表;付费分层还会读取原始充值 | -| 区服分析 | GET /sw/serverAnalysis/list | 区服日报两表 | - -普通渠道列表、注册明细、充值明细、渠道激活、工作台未登录榜,以及游戏/区服下拉选项不直接使用这四张汇总表。预警检测 `alertTriggerTask` 另行读取原始注册/充值数据,不由这些汇总任务生成预警。 - -今天任务用于当天持续刷新,昨天任务用于补算昨日完整数据,backfill 用于补历史或纠正迟到数据。2026-11-04 按用户要求与旧计划同步:四条今天/昨天汇总计划和预警计划启用;两个 backfill 保持停用,需要时手动运行。周期、时区和超时/重试参数保持原配置,详见 [验收记录](validation.md)。 - -报表输入索引由版本 `202611040014_business_report_build_indexes` 增量添加:`tab_user.idx_sw_user_report_identity` 覆盖用户身份及渠道字段,`tab_user_play_info.idx_sw_play_report_active` 覆盖活跃时间查询的全部读取字段。迁移跳过未接入的业务表,重复执行不重建已有同列索引,同名异列索引报错。MySQL 使用 `ALGORITHM=INPLACE, LOCK=NONE`,不改写原始业务字段。 diff --git a/docs/sw6-to-kra/server-analysis-source-notes.md b/docs/sw6-to-kra/server-analysis-source-notes.md deleted file mode 100644 index f72345a..0000000 --- a/docs/sw6-to-kra/server-analysis-source-notes.md +++ /dev/null @@ -1,16 +0,0 @@ -# 区服分析迁移核对 - -核对旧 main 的 `ServerAnalysisServiceImpl`、`SwReportServerDayQueryServiceImpl`、两个区服日汇总 Mapper,以及 dev/dev1.0 的 `ServerAnalysis.vue`。 - -- `/sw/serverAnalysis/games` 复用已迁移游戏选项;新增 `/servers`、`/list`。两者均要求游戏名称;来源支持逗号分隔或重复参数。 -- 选项通过当前 `tab_game.game_name` 确定平台+游戏,匹配区服名称;保留区服编号的字符串及前导零。原接口不按商务绑定裁剪资料选项,统计查询独立按可见范围隔离。 -- 选项默认 50,超过 100 时允许 100000,沿用旧批量选项请求。使用 `(source_db,game_id) IN (SELECT source_db,id FROM tab_game …)` 保持成对关联并避免重复行;MySQL 5.7 可先按游戏名索引定位,再使用区服的 game_id 索引,避免相关 EXISTS 扫描全部区服。 -- 统计读取 `tab_sw_report_server_day` 和身份键表,按平台+游戏+区服编号分组;空白编号不展示。不额外加日游戏报表的 `game_id > 0` 限制。 -- 人数在每个区服内 COUNT DISTINCT,金额固定模式 0;筛选历史报表游戏名。展示优先金额汇总的历史游戏名,无金额行时回退当前游戏名,保留旧行为。 -- 区服名称/开服日期按三元组批量补充;重复资料固定取最小 ID,提高原不确定顺序的稳定性。相同主排序后保留区服编号顺序,再按平台、游戏 ID 稳定排列。 -- 未指定区服时忽略新增/活跃/付费人数和四舍五入金额均为零的行;指定区服保留报表已有零行,不凭资料表制造新行。 -- 汇总是全部筛选后展示行之和,不随分页变化;ARPU 的分母是活跃人数。逐行人数保留 Java int 上限,summary 改用 int64 避免原累加溢出;金额与比率精确处理。 -- 缺任一必要业务表时明确未接入,summary 为 null;不能混用不存在区服和缺表错误。未知开服时间保持 null。 -- 后端默认上海当天,前端默认近 30 天;非法日期/倒置周期明确拒绝。页长沿用最大 500。 - -当前验证状态统一见 [验收与性能记录](validation.md),不再维护阶段性运行报告。 diff --git a/docs/sw6-to-kra/sw8-sw9-recheck-summary-2026-11-04.json b/docs/sw6-to-kra/sw8-sw9-recheck-summary-2026-11-04.json deleted file mode 100644 index 4eb9269..0000000 --- a/docs/sw6-to-kra/sw8-sw9-recheck-summary-2026-11-04.json +++ /dev/null @@ -1,558 +0,0 @@ -{ - "date": "2026-11-04", - "sourceDatabase": "sw8", - "targetDatabase": "sw9", - "ports": { - "legacy": 18080, - "newRecheck": 19002, - "newDevelopment": 8000 - }, - "businessContractsVerified": 51, - "legacyFrameworkAliasesReplaced": 12, - "readComparisonCases": 104, - "businessTasksMigrated": 7, - "businessTasksEnabled": 0, - "checks": 230, - "reports": [ - { - "file": "sw8-sw9-recheck-account-create-2026-11-04.json", - "checks": 10, - "passed": true - }, - { - "file": "sw8-sw9-recheck-account-write-2026-11-04.json", - "checks": 21, - "passed": true - }, - { - "file": "sw8-sw9-recheck-admin-2026-11-04.json", - "checks": 36, - "passed": true - }, - { - "file": "sw8-sw9-recheck-exports-2026-11-04.json", - "checks": 2, - "passed": true - }, - { - "file": "sw8-sw9-recheck-level3-2026-11-04.json", - "checks": 15, - "passed": true - }, - { - "file": "sw8-sw9-recheck-pagination-2026-11-04.json", - "checks": 19, - "passed": true - }, - { - "file": "sw8-sw9-recheck-preference-matrix-2026-11-04-sub0-dedup0.json", - "checks": 4, - "passed": true - }, - { - "file": "sw8-sw9-recheck-preference-matrix-2026-11-04-sub0-dedup1.json", - "checks": 4, - "passed": true - }, - { - "file": "sw8-sw9-recheck-preference-matrix-2026-11-04-sub1-dedup0.json", - "checks": 4, - "passed": true - }, - { - "file": "sw8-sw9-recheck-preference-matrix-2026-11-04-sub1-dedup1.json", - "checks": 4, - "passed": true - }, - { - "file": "sw8-sw9-recheck-preference-matrix-2026-11-04.json", - "checks": 14, - "passed": true - }, - { - "file": "sw8-sw9-recheck-sdk-write-2026-11-04.json", - "checks": 35, - "passed": true - }, - { - "file": "sw8-sw9-recheck-task-validation-2026-11-04.json", - "checks": 8, - "passed": true - }, - { - "file": "sw8-sw9-recheck-tasks-2026-11-04.json", - "checks": 7, - "passed": true - }, - { - "file": "sw8-sw9-recheck-testlevel1-2026-11-04.json", - "checks": 6, - "passed": true - }, - { - "file": "sw8-sw9-recheck-testlevel2-2026-11-04.json", - "checks": 6, - "passed": true - }, - { - "file": "sw8-sw9-recheck-testlevel3-2026-11-04.json", - "checks": 6, - "passed": true - }, - { - "file": "sw8-sw9-recheck-write-2026-11-04.json", - "checks": 29, - "passed": true - } - ], - "coverage": [ - { - "method": "GET", - "source_path": "/system/user/preference", - "target_path": "/sw/user/preference", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "PUT", - "source_path": "/system/user/preference", - "target_path": "/sw/user/preference", - "status": "verified", - "evidence": "sw8-sw9-recheck-preference-matrix-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/promote/list", - "target_path": "/sw/promote/list", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/promote/portrait", - "target_path": "/sw/promote/portrait", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/promote/game-distribution", - "target_path": "/sw/promote/game-distribution", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/promote/bindOptions", - "target_path": "/sw/promote/bindOptions", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "POST", - "source_path": "/system/promote", - "target_path": "/sw/promote", - "status": "verified", - "evidence": "sw8-sw9-recheck-sdk-write-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/promoteActivePool/bindList", - "target_path": "/sw/promoteActivePool/bindList", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/promoteActivePool/bindSpendDetail", - "target_path": "/sw/promoteActivePool/bindSpendDetail", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/workbench/summary", - "target_path": "/sw/workbench/summary", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/workbench/registerTop", - "target_path": "/sw/workbench/registerTop", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/workbench/payRank", - "target_path": "/sw/workbench/payRank", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/workbench/unloginTop", - "target_path": "/sw/workbench/unloginTop", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/rank/channel", - "target_path": "/sw/rank/channel", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/rank/business", - "target_path": "/sw/rank/business", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/rank/game", - "target_path": "/sw/rank/game", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/gameData/list", - "target_path": "/sw/gameData/list", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/channelData/list", - "target_path": "/sw/channelData/list", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/register/list", - "target_path": "/sw/register/list", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "POST", - "source_path": "/system/register/export", - "target_path": "/sw/register/export", - "status": "verified", - "evidence": "sw8-sw9-recheck-exports-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/spend/list", - "target_path": "/sw/spend/list", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "POST", - "source_path": "/system/spend/export", - "target_path": "/sw/spend/export", - "status": "verified", - "evidence": "sw8-sw9-recheck-exports-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/serverAnalysis/games", - "target_path": "/sw/serverAnalysis/games", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/serverAnalysis/servers", - "target_path": "/sw/serverAnalysis/servers", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/serverAnalysis/list", - "target_path": "/sw/serverAnalysis/list", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/alertRule/list", - "target_path": "/sw/alertRule/list", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/alertRule/ruleTypes", - "target_path": "/sw/alertRule/ruleTypes", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/alertRule/{id}", - "target_path": "/sw/alertRule/:id", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "POST", - "source_path": "/system/alertRule/add", - "target_path": "/sw/alertRule/add", - "status": "verified", - "evidence": "sw8-sw9-recheck-write-2026-11-04.json" - }, - { - "method": "PUT", - "source_path": "/system/alertRule/edit", - "target_path": "/sw/alertRule/edit", - "status": "verified", - "evidence": "sw8-sw9-recheck-write-2026-11-04.json" - }, - { - "method": "DELETE", - "source_path": "/system/alertRule/{id}", - "target_path": "/sw/alertRule/:id", - "status": "verified", - "evidence": "sw8-sw9-recheck-write-2026-11-04.json" - }, - { - "method": "PUT", - "source_path": "/system/alertRule/toggle/{id}", - "target_path": "/sw/alertRule/toggle/:id", - "status": "verified", - "evidence": "sw8-sw9-recheck-write-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/alertRecord/list", - "target_path": "/sw/alertRecord/list", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/alertRecord/detail/{id}", - "target_path": "/sw/alertRecord/detail/:id", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "POST", - "source_path": "/system/alertRecord/startProcess", - "target_path": "/sw/alertRecord/startProcess", - "status": "verified", - "evidence": "sw8-sw9-recheck-write-2026-11-04.json" - }, - { - "method": "POST", - "source_path": "/system/alertRecord/submitAudit", - "target_path": "/sw/alertRecord/submitAudit", - "status": "verified", - "evidence": "sw8-sw9-recheck-write-2026-11-04.json" - }, - { - "method": "POST", - "source_path": "/system/alertRecord/approve", - "target_path": "/sw/alertRecord/approve", - "status": "verified", - "evidence": "sw8-sw9-recheck-write-2026-11-04.json" - }, - { - "method": "POST", - "source_path": "/system/alertRecord/reject", - "target_path": "/sw/alertRecord/reject", - "status": "verified", - "evidence": "sw8-sw9-recheck-write-2026-11-04.json" - }, - { - "method": "POST", - "source_path": "/system/alertRecord/reProcess", - "target_path": "/sw/alertRecord/reProcess", - "status": "verified", - "evidence": "sw8-sw9-recheck-write-2026-11-04.json" - }, - { - "method": "POST", - "source_path": "/system/alertRecord/addNote", - "target_path": "/sw/alertRecord/addNote", - "status": "verified", - "evidence": "sw8-sw9-recheck-write-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/user/list", - "target_path": "/sw/business/list", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/user/{userId}/promotes", - "target_path": "/sw/business/:userId/promotes", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/user/{userId}/portrait", - "target_path": "/sw/business/:userId/portrait", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/user/{userId}/bindPlatform", - "target_path": "/sw/business/:userId/bindPlatform", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "POST", - "source_path": "/system/user/bindPlatform", - "target_path": "/sw/business/bindPlatform", - "status": "verified", - "evidence": "sw8-sw9-recheck-sdk-write-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/user/bindPlatform", - "target_path": "/sw/business/bindPlatform", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "GET", - "source_path": "/system/user/bindPlatform/portrait", - "target_path": "/sw/business/bindPlatform/portrait", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "DELETE", - "source_path": "/system/user/bindPlatform", - "target_path": "/sw/business/bindPlatform", - "status": "verified", - "evidence": "sw8-sw9-recheck-sdk-write-2026-11-04.json" - }, - { - "method": "POST", - "source_path": "/system/user/export", - "target_path": "/sw/business/export", - "status": "native_framework_replacement", - "note": "not a legacy wire-protocol alias" - }, - { - "method": "POST", - "source_path": "/system/user/importData", - "target_path": "/sw/business/importData", - "status": "native_framework_replacement", - "note": "not a legacy wire-protocol alias" - }, - { - "method": "GET", - "source_path": "/system/user/", - "target_path": "/sw/business", - "status": "native_framework_replacement", - "note": "not a legacy wire-protocol alias" - }, - { - "method": "GET", - "source_path": "/system/user/{userId}", - "target_path": "/sw/business/:userId", - "status": "verified", - "evidence": "sw8-sw9-recheck-admin-2026-11-04.json" - }, - { - "method": "POST", - "source_path": "/system/user", - "target_path": "/sw/business", - "status": "verified", - "evidence": "sw8-sw9-recheck-account-create-2026-11-04.json" - }, - { - "method": "PUT", - "source_path": "/system/user", - "target_path": "/sw/business", - "status": "verified", - "evidence": "sw8-sw9-recheck-account-write-2026-11-04.json" - }, - { - "method": "DELETE", - "source_path": "/system/user/{userIds}", - "target_path": "/sw/business/:userIds", - "status": "native_framework_replacement", - "note": "not a legacy wire-protocol alias" - }, - { - "method": "GET", - "source_path": "/system/user/optionselect", - "target_path": "/sw/business/optionselect", - "status": "native_framework_replacement", - "note": "not a legacy wire-protocol alias" - }, - { - "method": "PUT", - "source_path": "/system/user/resetPwd", - "target_path": "/sw/business/resetPwd", - "status": "native_framework_replacement", - "note": "not a legacy wire-protocol alias" - }, - { - "method": "PUT", - "source_path": "/system/user/changeStatus", - "target_path": "/sw/business/changeStatus", - "status": "native_framework_replacement", - "note": "not a legacy wire-protocol alias" - }, - { - "method": "GET", - "source_path": "/system/user/unlock/{userId}", - "target_path": "/sw/business/unlock/:userId", - "status": "native_framework_replacement", - "note": "not a legacy wire-protocol alias" - }, - { - "method": "GET", - "source_path": "/system/user/authRole/{userId}", - "target_path": "/sw/business/authRole/:userId", - "status": "native_framework_replacement", - "note": "not a legacy wire-protocol alias" - }, - { - "method": "PUT", - "source_path": "/system/user/authRole", - "target_path": "/sw/business/authRole", - "status": "native_framework_replacement", - "note": "not a legacy wire-protocol alias" - }, - { - "method": "GET", - "source_path": "/system/user/deptTree", - "target_path": "/sw/business/deptTree", - "status": "native_framework_replacement", - "note": "not a legacy wire-protocol alias" - }, - { - "method": "GET", - "source_path": "/system/user/list/dept/{deptId}", - "target_path": "/sw/business/list/dept/:deptId", - "status": "native_framework_replacement", - "note": "not a legacy wire-protocol alias" - } - ], - "explicitDifferences": [ - "Pay-rate ranking uses user-requested relative percentage growth instead of percentage-point change.", - "Only the creation times of three explicitly identified HTTP-created test users are excluded; original migrated users remain strict.", - "Legacy MyBatis returns page one on an out-of-range page; new service returns an empty page. Valid pages match.", - "Disabled/pending/rejected users cannot use existing sessions in the new service; old service permits this." - ], - "passed": true -} diff --git a/docs/sw6-to-kra/sw_to_kra_migrate.sql b/docs/sw6-to-kra/sw_to_kra_migrate.sql deleted file mode 100644 index b5640b8..0000000 --- a/docs/sw6-to-kra/sw_to_kra_migrate.sql +++ /dev/null @@ -1,1768 +0,0 @@ --- SW → Kra 系统框架迁移统一入口,目标库由下方 USE 配置。 --- 新副本:备份源表、创建 Kra 表、转换框架数据及关联,并归档旧表。 --- 已迁移副本:自动执行菜单调整,不重新导入账号,不重建已存在的表。 --- 检测到部分迁移状态时立即停止,防止覆盖未完成的数据。 --- 首次迁移要求 26 张源表已存在;支持包含真实规则、预警和日志的完整业务副本。 --- 本脚本不包含账号明文、密码哈希或连接凭据;原始业务大表保留在目标副本中。 --- 请使用支持 DELIMITER 的 MySQL 客户端,在同一连接执行,遇错停止,不使用 --force。 --- 工作台复用仪表盘;商务管理、数据分析、预警中心依次排在仪表盘下方。 --- 与当前 Go 版本配套使用;启动时追加业务锁表等增量迁移,导入的全部任务保持停用。 --- 已迁移分支不依赖已清理的旧源表或备份表;执行前请备份当前菜单及角色元数据。 --- 唯一的库名配置:当前测试库填 sw9,正式库填 sw6;连接地址由数据库客户端选择。 --- MySQL 5.7 不支持 USE @变量,因此只修改下一行,正文自动使用当前数据库。 -USE `sw9`; -SET @sw_kra_target_db = DATABASE(); -SET NAMES utf8mb4; -SET SESSION time_zone='+08:00'; -DELIMITER $$ -DROP PROCEDURE IF EXISTS sw_kra_migrate_20261103$$ -CREATE PROCEDURE sw_kra_migrate_20261103() -migration_run: BEGIN -DECLARE v_actual BIGINT DEFAULT 0; -DECLARE v_expected BIGINT DEFAULT 0; -DECLARE v_iter INT DEFAULT 0; -DECLARE v_lock INT DEFAULT 0; -DECLARE v_lock_name VARCHAR(64); -DECLARE v_dashboard BIGINT UNSIGNED DEFAULT NULL; -DECLARE v_workbench BIGINT UNSIGNED DEFAULT NULL; -DECLARE EXIT HANDLER FOR SQLEXCEPTION -BEGIN - ROLLBACK; - IF v_lock=1 THEN DO RELEASE_LOCK(v_lock_name); END IF; - RESIGNAL; -END; -IF DATABASE() IS NULL OR @sw_kra_target_db IS NULL OR NOT (BINARY DATABASE() <=> BINARY @sw_kra_target_db) THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='当前数据库与配置不一致'; -END IF; --- 按目标库生成迁移锁,避免不同数据库互相阻塞,名称不超过 MySQL 的 64 字符限制。 -SET v_lock_name=CONCAT('sw_to_kra:',MD5(DATABASE())); -SELECT GET_LOCK(v_lock_name,10) INTO v_lock; -IF COALESCE(v_lock,0)<>1 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Migration lock unavailable'; END IF; --- 一、已迁移库:确认目标表完整、迁移账本已完成,再调整菜单。 -IF EXISTS(SELECT 1 FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name='sys_users') THEN - IF (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=DATABASE() - AND table_name IN ('sys_schema_migrations','sys_users','sys_authorities','sys_base_menus','sys_user_authority','sys_authority_menus','sys_base_menu_parameters','sys_apis','sys_ignore_apis','sys_authority_apis','casbin_rule','sys_base_menu_btns','sys_authority_btns','sys_departments','sys_positions','sys_user_departments','sys_user_positions','sys_authority_departments','sys_dictionaries','sys_dictionary_details','sys_params','sys_api_tokens','jwt_blacklists','sys_security_config','sys_versions','sys_export_templates','sys_export_template_condition','sys_export_template_join','sys_operation_records','sys_login_logs','sys_data_access_logs','sys_error','media_file_upload_and_downloads','media_attachment_category','media_uploads','media_upload_chunks','sys_announcements','sys_integration_configs','sys_timed_tasks','sys_timed_task_logs','pay_orders','pay_events','sys_user_bind_platform','sys_user_preference','sys_alert_rule','sys_alert_record','sys_alert_operation_log','sys_message','sw_kra_id_map') AND engine='InnoDB')<>49 THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Kra target tables incomplete; refusing partial migration'; - END IF; - IF EXISTS(SELECT 1 FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name='sw_kra_state') THEN - IF NOT EXISTS(SELECT 1 FROM sw_kra_state WHERE id=1 AND phase='completed') THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Previous migration not completed'; - END IF; - ELSEIF EXISTS(SELECT 1 FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name='sys_user') THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Legacy users remain without completed migration state'; - END IF; - START TRANSACTION; - IF (SELECT COUNT(*) FROM sys_base_menus WHERE name='dashboard' AND parent_id=0 AND deleted_at IS NULL)<>1 - OR (SELECT COUNT(*) FROM sys_base_menus WHERE name='sw_workbench')>1 - OR (SELECT COUNT(DISTINCT name) FROM sys_base_menus WHERE parent_id=0 AND deleted_at IS NULL - AND name IN ('sw_BusMgmt','sw_DataAnalysis','sw_AlertCenter'))<>3 THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Required menu identities differ'; - END IF; - SELECT id INTO v_dashboard FROM sys_base_menus WHERE name='dashboard' AND parent_id=0 AND deleted_at IS NULL FOR UPDATE; - SET v_workbench=(SELECT id FROM sys_base_menus WHERE name='sw_workbench'); - IF EXISTS(SELECT 1 FROM sys_base_menus WHERE parent_id=v_workbench) - OR EXISTS(SELECT 1 FROM sys_base_menu_btns WHERE sys_base_menu_id=v_workbench AND name<>'sw:workbench:query') THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Workbench has unexpected children/buttons'; - END IF; - - -- 先补齐仪表盘授权,再移除重复工作台;已有授权不重复插入。 - INSERT INTO sys_authority_menus(sys_authority_authority_id,sys_base_menu_id) - SELECT a.authority_id,v_dashboard FROM sys_authorities a - WHERE (a.default_router IN ('sw_workbench','dashboard') OR EXISTS( - SELECT 1 FROM sys_authority_menus x WHERE x.sys_authority_authority_id=a.authority_id AND x.sys_base_menu_id=v_workbench)) - AND NOT EXISTS(SELECT 1 FROM sys_authority_menus x WHERE x.sys_authority_authority_id=a.authority_id AND x.sys_base_menu_id=v_dashboard); - UPDATE sys_authorities SET default_router='dashboard' WHERE default_router='sw_workbench'; - - -- 删除工作台页面、查询按钮及其关联,保留业务接口和查询权限。 - DELETE x FROM sys_authority_btns x LEFT JOIN sys_base_menu_btns b ON b.id=x.sys_base_menu_btn_id - WHERE x.sys_menu_id=v_workbench OR b.sys_base_menu_id=v_workbench; - DELETE FROM sys_authority_menus WHERE sys_base_menu_id=v_workbench; - DELETE FROM sys_base_menu_parameters WHERE sys_base_menu_id=v_workbench; - DELETE m FROM sw_kra_id_map m LEFT JOIN sys_base_menu_btns b ON b.id=m.new_id - WHERE m.entity='menu' AND (m.new_id=v_workbench OR b.sys_base_menu_id=v_workbench); - DELETE FROM sys_base_menu_btns WHERE sys_base_menu_id=v_workbench; - DELETE FROM sys_base_menus WHERE id=v_workbench; - - -- 使用固定排序值,确保重复执行结果一致;不调整子菜单排序。 - UPDATE sys_base_menus SET sort=CASE name - WHEN 'dashboard' THEN 1 - WHEN 'sw_BusMgmt' THEN 2 - WHEN 'sw_DataAnalysis' THEN 3 - WHEN 'sw_AlertCenter' THEN 4 - WHEN 'permission' THEN 5 - WHEN 'org' THEN 6 - WHEN 'systemConfig' THEN 7 - WHEN 'monitor' THEN 8 - WHEN 'media' THEN 9 - WHEN 'extensions' THEN 13 - WHEN 'person' THEN 16 - ELSE sort END WHERE parent_id=0; - - -- RuoYi SVG 名称转换为 Kra 已注册图标;只修复旧值,保留后续自定义选择。 - UPDATE sys_base_menus SET icon=CASE name - WHEN 'sw_BusMgmt' THEN 'Briefcase' - WHEN 'sw_BusinessList' THEN 'UserFilled' - WHEN 'sw_ChannelList' THEN 'Connection' - WHEN 'sw_ChannelActivationList' THEN 'CircleCheck' - WHEN 'sw_DataAnalysis' THEN 'DataAnalysis' - WHEN 'sw_ChannelDataStatistics' THEN 'Histogram' - WHEN 'sw_RechargeDetails' THEN 'Money' - WHEN 'sw_RegistrationDetails' THEN 'User' - WHEN 'sw_GameAnalytics' THEN 'TrendCharts' - WHEN 'sw_ServerAnalysis' THEN 'Monitor' - WHEN 'sw_RankingAnalysis' THEN 'Star' - WHEN 'sw_AlertCenter' THEN 'Bell' - WHEN 'sw_AlertList' THEN 'Warning' - WHEN 'sw_AlertRules' THEN 'Setting' - ELSE icon END - WHERE name IN ('sw_BusMgmt','sw_BusinessList','sw_ChannelList','sw_ChannelActivationList','sw_DataAnalysis','sw_ChannelDataStatistics','sw_RechargeDetails','sw_RegistrationDetails','sw_GameAnalytics','sw_ServerAnalysis','sw_RankingAnalysis','sw_AlertCenter','sw_AlertList','sw_AlertRules') - AND (icon IS NULL OR icon IN ('', 'category', 'email', 'chart', 'company', 'international', 'color', 'dict', 'cascader', 'education', 'excel', 'star', 'process-definition', 'documentation', 'example', 'data-analysis', 'user', 'money', 'warn')); - - IF EXISTS(SELECT 1 FROM sys_base_menus WHERE name='sw_workbench' OR path='sw-index') - OR EXISTS(SELECT 1 FROM sys_base_menu_btns WHERE name='sw:workbench:query') THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Duplicate workbench remains'; - END IF; - IF EXISTS(SELECT 1 FROM sys_authorities a WHERE NOT EXISTS( - SELECT 1 FROM sys_base_menus m JOIN sys_authority_menus x ON x.sys_base_menu_id=m.id - WHERE x.sys_authority_authority_id=a.authority_id AND m.name=a.default_router AND m.deleted_at IS NULL)) THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Role default router not accessible'; - END IF; - IF EXISTS(SELECT 1 FROM sys_authority_menus x LEFT JOIN sys_base_menus m ON m.id=x.sys_base_menu_id WHERE m.id IS NULL) - OR EXISTS(SELECT 1 FROM sys_authority_btns x LEFT JOIN sys_base_menu_btns b ON b.id=x.sys_base_menu_btn_id - LEFT JOIN sys_base_menus m ON m.id=x.sys_menu_id WHERE b.id IS NULL OR m.id IS NULL OR b.sys_base_menu_id<>x.sys_menu_id) - OR EXISTS(SELECT 1 FROM sys_base_menu_parameters x LEFT JOIN sys_base_menus m ON m.id=x.sys_base_menu_id WHERE m.id IS NULL) THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Dangling menu relationship'; - END IF; - COMMIT; - DO RELEASE_LOCK(v_lock_name); SET v_lock=0; - SELECT '菜单调整完成,原有框架和业务数据已保留' AS result; - LEAVE migration_run; -END IF; - --- 二、未迁移的新副本:核查源表及迁移状态,再执行完整迁移。 -IF EXISTS(SELECT 1 FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name IN ('sw_kra_state','sys_users','sys_schema_migrations','bak_sw2kra_20261103_sys_user')) THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Target already migrated or partially prepared; do not overwrite'; -END IF; -SELECT COUNT(*) INTO v_actual FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name IN ('sys_social','sys_dept','sys_user','sys_post','sys_role','sys_menu','sys_user_role','sys_role_menu','sys_role_dept','sys_user_post','sys_oper_log','sys_dict_type','sys_dict_data','sys_config','sys_login_info','sys_notice','sys_message','sys_oss','sys_oss_config','sys_client','sys_user_bind_platform','sys_user_preference','sj_job','sys_alert_rule','sys_alert_record','sys_alert_operation_log') AND engine='InnoDB'; - -IF v_actual<>26 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Source table set/engine differs'; END IF; - -IF EXISTS(SELECT 1 FROM sys_user WHERE del_flag='0' AND LEFT(password,4) NOT IN ('$2a$','$2b$','$2y$')) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Unsupported source password format'; END IF; - -IF EXISTS(SELECT user_name FROM sys_user WHERE del_flag='0' GROUP BY user_name HAVING COUNT(*)>1) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Duplicate source username'; END IF; - -IF EXISTS(SELECT u.user_id FROM sys_user u LEFT JOIN sys_user_role ur ON ur.user_id=u.user_id LEFT JOIN sys_role r ON r.role_id=ur.role_id AND r.del_flag='0' WHERE u.del_flag='0' GROUP BY u.user_id HAVING COUNT(DISTINCT r.role_id)<>1) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Source user needs exactly one active role'; END IF; - -IF EXISTS(SELECT 1 FROM sys_role WHERE del_flag='0' AND data_scope NOT IN ('1','2','3','4','5')) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Unsupported source data scope'; END IF; - -IF EXISTS(SELECT 1 FROM sys_user u LEFT JOIN sys_user p ON p.user_id=u.parent_id WHERE u.del_flag='0' AND u.parent_id>0 AND (p.user_id IS NULL OR p.del_flag<>'0' OR p.level>=u.level)) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Invalid source business ancestry'; END IF; - --- 三、创建迁移账本和批次备份,逐表核对行数与字段内容。 - -CREATE TABLE sw_kra_state (id INT PRIMARY KEY, version VARCHAR(80) NOT NULL, phase VARCHAR(40) NOT NULL, started_at DATETIME(3), completed_at DATETIME(3)) ENGINE=InnoDB; - -INSERT INTO sw_kra_state VALUES(1,'20261103_framework_migration_v5','backup',NOW(3),NULL); - -CREATE TABLE sw_kra_checks (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,stage VARCHAR(32),check_name VARCHAR(160),expected_value BIGINT,actual_value BIGINT,passed TINYINT NOT NULL) ENGINE=InnoDB; - -CREATE TABLE `bak_sw2kra_20261103_sys_social` LIKE `sys_social`; - -CREATE TABLE `bak_sw2kra_20261103_sys_dept` LIKE `sys_dept`; - -CREATE TABLE `bak_sw2kra_20261103_sys_user` LIKE `sys_user`; - -CREATE TABLE `bak_sw2kra_20261103_sys_post` LIKE `sys_post`; - -CREATE TABLE `bak_sw2kra_20261103_sys_role` LIKE `sys_role`; - -CREATE TABLE `bak_sw2kra_20261103_sys_menu` LIKE `sys_menu`; - -CREATE TABLE `bak_sw2kra_20261103_sys_user_role` LIKE `sys_user_role`; - -CREATE TABLE `bak_sw2kra_20261103_sys_role_menu` LIKE `sys_role_menu`; - -CREATE TABLE `bak_sw2kra_20261103_sys_role_dept` LIKE `sys_role_dept`; - -CREATE TABLE `bak_sw2kra_20261103_sys_user_post` LIKE `sys_user_post`; - -CREATE TABLE `bak_sw2kra_20261103_sys_oper_log` LIKE `sys_oper_log`; - -CREATE TABLE `bak_sw2kra_20261103_sys_dict_type` LIKE `sys_dict_type`; - -CREATE TABLE `bak_sw2kra_20261103_sys_dict_data` LIKE `sys_dict_data`; - -CREATE TABLE `bak_sw2kra_20261103_sys_config` LIKE `sys_config`; - -CREATE TABLE `bak_sw2kra_20261103_sys_login_info` LIKE `sys_login_info`; - -CREATE TABLE `bak_sw2kra_20261103_sys_notice` LIKE `sys_notice`; - -CREATE TABLE `bak_sw2kra_20261103_sys_message` LIKE `sys_message`; - -CREATE TABLE `bak_sw2kra_20261103_sys_oss` LIKE `sys_oss`; - -CREATE TABLE `bak_sw2kra_20261103_sys_oss_config` LIKE `sys_oss_config`; - -CREATE TABLE `bak_sw2kra_20261103_sys_client` LIKE `sys_client`; - -CREATE TABLE `bak_sw2kra_20261103_sys_user_bind_platform` LIKE `sys_user_bind_platform`; - -CREATE TABLE `bak_sw2kra_20261103_sys_user_preference` LIKE `sys_user_preference`; - -CREATE TABLE `bak_sw2kra_20261103_sj_job` LIKE `sj_job`; - -CREATE TABLE `bak_sw2kra_20261103_sys_alert_rule` LIKE `sys_alert_rule`; - -CREATE TABLE `bak_sw2kra_20261103_sys_alert_record` LIKE `sys_alert_record`; - -CREATE TABLE `bak_sw2kra_20261103_sys_alert_operation_log` LIKE `sys_alert_operation_log`; - -START TRANSACTION; - -INSERT INTO `bak_sw2kra_20261103_sys_social` (`id`,`user_id`,`auth_id`,`source`,`open_id`,`user_name`,`nick_name`,`email`,`avatar`,`access_token`,`expire_in`,`refresh_token`,`access_code`,`union_id`,`scope`,`token_type`,`id_token`,`mac_algorithm`,`mac_key`,`code`,`oauth_token`,`oauth_token_secret`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`del_flag`) SELECT `id`,`user_id`,`auth_id`,`source`,`open_id`,`user_name`,`nick_name`,`email`,`avatar`,`access_token`,`expire_in`,`refresh_token`,`access_code`,`union_id`,`scope`,`token_type`,`id_token`,`mac_algorithm`,`mac_key`,`code`,`oauth_token`,`oauth_token_secret`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`del_flag` FROM `sys_social`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_social`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_social`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_social backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_social backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_social` s LEFT JOIN `bak_sw2kra_20261103_sys_social` b ON s.`id`=b.`id` WHERE b.`id` IS NULL OR NOT((BINARY s.`id` <=> BINARY b.`id`) AND (BINARY s.`user_id` <=> BINARY b.`user_id`) AND (BINARY s.`auth_id` <=> BINARY b.`auth_id`) AND (BINARY s.`source` <=> BINARY b.`source`) AND (BINARY s.`open_id` <=> BINARY b.`open_id`) AND (BINARY s.`user_name` <=> BINARY b.`user_name`) AND (BINARY s.`nick_name` <=> BINARY b.`nick_name`) AND (BINARY s.`email` <=> BINARY b.`email`) AND (BINARY s.`avatar` <=> BINARY b.`avatar`) AND (BINARY s.`access_token` <=> BINARY b.`access_token`) AND (BINARY s.`expire_in` <=> BINARY b.`expire_in`) AND (BINARY s.`refresh_token` <=> BINARY b.`refresh_token`) AND (BINARY s.`access_code` <=> BINARY b.`access_code`) AND (BINARY s.`union_id` <=> BINARY b.`union_id`) AND (BINARY s.`scope` <=> BINARY b.`scope`) AND (BINARY s.`token_type` <=> BINARY b.`token_type`) AND (BINARY s.`id_token` <=> BINARY b.`id_token`) AND (BINARY s.`mac_algorithm` <=> BINARY b.`mac_algorithm`) AND (BINARY s.`mac_key` <=> BINARY b.`mac_key`) AND (BINARY s.`code` <=> BINARY b.`code`) AND (BINARY s.`oauth_token` <=> BINARY b.`oauth_token`) AND (BINARY s.`oauth_token_secret` <=> BINARY b.`oauth_token_secret`) AND (BINARY s.`create_dept` <=> BINARY b.`create_dept`) AND (BINARY s.`create_by` <=> BINARY b.`create_by`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`update_by` <=> BINARY b.`update_by`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`) AND (BINARY s.`del_flag` <=> BINARY b.`del_flag`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_social backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_social backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_dept` (`dept_id`,`parent_id`,`ancestors`,`dept_name`,`dept_category`,`order_num`,`leader`,`phone`,`email`,`status`,`del_flag`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`) SELECT `dept_id`,`parent_id`,`ancestors`,`dept_name`,`dept_category`,`order_num`,`leader`,`phone`,`email`,`status`,`del_flag`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time` FROM `sys_dept`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_dept`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_dept`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_dept backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_dept backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_dept` s LEFT JOIN `bak_sw2kra_20261103_sys_dept` b ON s.`dept_id`=b.`dept_id` WHERE b.`dept_id` IS NULL OR NOT((BINARY s.`dept_id` <=> BINARY b.`dept_id`) AND (BINARY s.`parent_id` <=> BINARY b.`parent_id`) AND (BINARY s.`ancestors` <=> BINARY b.`ancestors`) AND (BINARY s.`dept_name` <=> BINARY b.`dept_name`) AND (BINARY s.`dept_category` <=> BINARY b.`dept_category`) AND (BINARY s.`order_num` <=> BINARY b.`order_num`) AND (BINARY s.`leader` <=> BINARY b.`leader`) AND (BINARY s.`phone` <=> BINARY b.`phone`) AND (BINARY s.`email` <=> BINARY b.`email`) AND (BINARY s.`status` <=> BINARY b.`status`) AND (BINARY s.`del_flag` <=> BINARY b.`del_flag`) AND (BINARY s.`create_dept` <=> BINARY b.`create_dept`) AND (BINARY s.`create_by` <=> BINARY b.`create_by`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`update_by` <=> BINARY b.`update_by`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_dept backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_dept backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_user` (`user_id`,`dept_id`,`user_name`,`nick_name`,`user_type`,`email`,`phone_number`,`gender`,`avatar`,`password`,`status`,`del_flag`,`login_ip`,`login_date`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark`,`level`,`parent_id`,`id_path`,`real_name`,`qq_number`,`reject_reason`) SELECT `user_id`,`dept_id`,`user_name`,`nick_name`,`user_type`,`email`,`phone_number`,`gender`,`avatar`,`password`,`status`,`del_flag`,`login_ip`,`login_date`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark`,`level`,`parent_id`,`id_path`,`real_name`,`qq_number`,`reject_reason` FROM `sys_user`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_user`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_user`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_user backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_user backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_user` s LEFT JOIN `bak_sw2kra_20261103_sys_user` b ON s.`user_id`=b.`user_id` WHERE b.`user_id` IS NULL OR NOT((BINARY s.`user_id` <=> BINARY b.`user_id`) AND (BINARY s.`dept_id` <=> BINARY b.`dept_id`) AND (BINARY s.`user_name` <=> BINARY b.`user_name`) AND (BINARY s.`nick_name` <=> BINARY b.`nick_name`) AND (BINARY s.`user_type` <=> BINARY b.`user_type`) AND (BINARY s.`email` <=> BINARY b.`email`) AND (BINARY s.`phone_number` <=> BINARY b.`phone_number`) AND (BINARY s.`gender` <=> BINARY b.`gender`) AND (BINARY s.`avatar` <=> BINARY b.`avatar`) AND (BINARY s.`password` <=> BINARY b.`password`) AND (BINARY s.`status` <=> BINARY b.`status`) AND (BINARY s.`del_flag` <=> BINARY b.`del_flag`) AND (BINARY s.`login_ip` <=> BINARY b.`login_ip`) AND (BINARY s.`login_date` <=> BINARY b.`login_date`) AND (BINARY s.`create_dept` <=> BINARY b.`create_dept`) AND (BINARY s.`create_by` <=> BINARY b.`create_by`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`update_by` <=> BINARY b.`update_by`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`) AND (BINARY s.`remark` <=> BINARY b.`remark`) AND (BINARY s.`level` <=> BINARY b.`level`) AND (BINARY s.`parent_id` <=> BINARY b.`parent_id`) AND (BINARY s.`id_path` <=> BINARY b.`id_path`) AND (BINARY s.`real_name` <=> BINARY b.`real_name`) AND (BINARY s.`qq_number` <=> BINARY b.`qq_number`) AND (BINARY s.`reject_reason` <=> BINARY b.`reject_reason`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_user backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_user backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_post` (`post_id`,`dept_id`,`post_code`,`post_category`,`post_name`,`post_sort`,`status`,`del_flag`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark`) SELECT `post_id`,`dept_id`,`post_code`,`post_category`,`post_name`,`post_sort`,`status`,`del_flag`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark` FROM `sys_post`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_post`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_post`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_post backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_post backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_post` s LEFT JOIN `bak_sw2kra_20261103_sys_post` b ON s.`post_id`=b.`post_id` WHERE b.`post_id` IS NULL OR NOT((BINARY s.`post_id` <=> BINARY b.`post_id`) AND (BINARY s.`dept_id` <=> BINARY b.`dept_id`) AND (BINARY s.`post_code` <=> BINARY b.`post_code`) AND (BINARY s.`post_category` <=> BINARY b.`post_category`) AND (BINARY s.`post_name` <=> BINARY b.`post_name`) AND (BINARY s.`post_sort` <=> BINARY b.`post_sort`) AND (BINARY s.`status` <=> BINARY b.`status`) AND (BINARY s.`del_flag` <=> BINARY b.`del_flag`) AND (BINARY s.`create_dept` <=> BINARY b.`create_dept`) AND (BINARY s.`create_by` <=> BINARY b.`create_by`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`update_by` <=> BINARY b.`update_by`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`) AND (BINARY s.`remark` <=> BINARY b.`remark`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_post backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_post backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_role` (`role_id`,`role_name`,`role_key`,`role_sort`,`data_scope`,`menu_check_strictly`,`dept_check_strictly`,`status`,`del_flag`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark`) SELECT `role_id`,`role_name`,`role_key`,`role_sort`,`data_scope`,`menu_check_strictly`,`dept_check_strictly`,`status`,`del_flag`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark` FROM `sys_role`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_role`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_role`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_role backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_role backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_role` s LEFT JOIN `bak_sw2kra_20261103_sys_role` b ON s.`role_id`=b.`role_id` WHERE b.`role_id` IS NULL OR NOT((BINARY s.`role_id` <=> BINARY b.`role_id`) AND (BINARY s.`role_name` <=> BINARY b.`role_name`) AND (BINARY s.`role_key` <=> BINARY b.`role_key`) AND (BINARY s.`role_sort` <=> BINARY b.`role_sort`) AND (BINARY s.`data_scope` <=> BINARY b.`data_scope`) AND (BINARY s.`menu_check_strictly` <=> BINARY b.`menu_check_strictly`) AND (BINARY s.`dept_check_strictly` <=> BINARY b.`dept_check_strictly`) AND (BINARY s.`status` <=> BINARY b.`status`) AND (BINARY s.`del_flag` <=> BINARY b.`del_flag`) AND (BINARY s.`create_dept` <=> BINARY b.`create_dept`) AND (BINARY s.`create_by` <=> BINARY b.`create_by`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`update_by` <=> BINARY b.`update_by`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`) AND (BINARY s.`remark` <=> BINARY b.`remark`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_role backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_role backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_menu` (`menu_id`,`menu_name`,`parent_id`,`order_num`,`path`,`component`,`query_param`,`is_frame`,`is_cache`,`menu_type`,`visible`,`status`,`perms`,`icon`,`active_menu`,`ext`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark`) SELECT `menu_id`,`menu_name`,`parent_id`,`order_num`,`path`,`component`,`query_param`,`is_frame`,`is_cache`,`menu_type`,`visible`,`status`,`perms`,`icon`,`active_menu`,`ext`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark` FROM `sys_menu`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_menu`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_menu`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_menu backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_menu backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_menu` s LEFT JOIN `bak_sw2kra_20261103_sys_menu` b ON s.`menu_id`=b.`menu_id` WHERE b.`menu_id` IS NULL OR NOT((BINARY s.`menu_id` <=> BINARY b.`menu_id`) AND (BINARY s.`menu_name` <=> BINARY b.`menu_name`) AND (BINARY s.`parent_id` <=> BINARY b.`parent_id`) AND (BINARY s.`order_num` <=> BINARY b.`order_num`) AND (BINARY s.`path` <=> BINARY b.`path`) AND (BINARY s.`component` <=> BINARY b.`component`) AND (BINARY s.`query_param` <=> BINARY b.`query_param`) AND (BINARY s.`is_frame` <=> BINARY b.`is_frame`) AND (BINARY s.`is_cache` <=> BINARY b.`is_cache`) AND (BINARY s.`menu_type` <=> BINARY b.`menu_type`) AND (BINARY s.`visible` <=> BINARY b.`visible`) AND (BINARY s.`status` <=> BINARY b.`status`) AND (BINARY s.`perms` <=> BINARY b.`perms`) AND (BINARY s.`icon` <=> BINARY b.`icon`) AND (BINARY s.`active_menu` <=> BINARY b.`active_menu`) AND (BINARY s.`ext` <=> BINARY b.`ext`) AND (BINARY s.`create_dept` <=> BINARY b.`create_dept`) AND (BINARY s.`create_by` <=> BINARY b.`create_by`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`update_by` <=> BINARY b.`update_by`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`) AND (BINARY s.`remark` <=> BINARY b.`remark`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_menu backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_menu backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_user_role` (`user_id`,`role_id`) SELECT `user_id`,`role_id` FROM `sys_user_role`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_user_role`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_user_role`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_user_role backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_user_role backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_user_role` s LEFT JOIN `bak_sw2kra_20261103_sys_user_role` b ON s.`user_id`=b.`user_id` AND s.`role_id`=b.`role_id` WHERE b.`user_id` IS NULL OR NOT((BINARY s.`user_id` <=> BINARY b.`user_id`) AND (BINARY s.`role_id` <=> BINARY b.`role_id`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_user_role backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_user_role backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_role_menu` (`role_id`,`menu_id`) SELECT `role_id`,`menu_id` FROM `sys_role_menu`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_role_menu`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_role_menu`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_role_menu backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_role_menu backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_role_menu` s LEFT JOIN `bak_sw2kra_20261103_sys_role_menu` b ON s.`role_id`=b.`role_id` AND s.`menu_id`=b.`menu_id` WHERE b.`role_id` IS NULL OR NOT((BINARY s.`role_id` <=> BINARY b.`role_id`) AND (BINARY s.`menu_id` <=> BINARY b.`menu_id`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_role_menu backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_role_menu backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_role_dept` (`role_id`,`dept_id`) SELECT `role_id`,`dept_id` FROM `sys_role_dept`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_role_dept`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_role_dept`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_role_dept backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_role_dept backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_role_dept` s LEFT JOIN `bak_sw2kra_20261103_sys_role_dept` b ON s.`role_id`=b.`role_id` AND s.`dept_id`=b.`dept_id` WHERE b.`role_id` IS NULL OR NOT((BINARY s.`role_id` <=> BINARY b.`role_id`) AND (BINARY s.`dept_id` <=> BINARY b.`dept_id`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_role_dept backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_role_dept backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_user_post` (`user_id`,`post_id`) SELECT `user_id`,`post_id` FROM `sys_user_post`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_user_post`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_user_post`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_user_post backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_user_post backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_user_post` s LEFT JOIN `bak_sw2kra_20261103_sys_user_post` b ON s.`user_id`=b.`user_id` AND s.`post_id`=b.`post_id` WHERE b.`user_id` IS NULL OR NOT((BINARY s.`user_id` <=> BINARY b.`user_id`) AND (BINARY s.`post_id` <=> BINARY b.`post_id`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_user_post backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_user_post backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_oper_log` (`oper_id`,`title`,`business_type`,`method`,`request_method`,`operator_type`,`oper_name`,`user_id`,`dept_id`,`dept_name`,`client_key`,`device_type`,`browser`,`os`,`oper_url`,`oper_ip`,`oper_location`,`oper_param`,`json_result`,`status`,`error_msg`,`oper_time`,`cost_time`) SELECT `oper_id`,`title`,`business_type`,`method`,`request_method`,`operator_type`,`oper_name`,`user_id`,`dept_id`,`dept_name`,`client_key`,`device_type`,`browser`,`os`,`oper_url`,`oper_ip`,`oper_location`,`oper_param`,`json_result`,`status`,`error_msg`,`oper_time`,`cost_time` FROM `sys_oper_log`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_oper_log`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_oper_log`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_oper_log backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_oper_log backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_oper_log` s LEFT JOIN `bak_sw2kra_20261103_sys_oper_log` b ON s.`oper_id`=b.`oper_id` WHERE b.`oper_id` IS NULL OR NOT((BINARY s.`oper_id` <=> BINARY b.`oper_id`) AND (BINARY s.`title` <=> BINARY b.`title`) AND (BINARY s.`business_type` <=> BINARY b.`business_type`) AND (BINARY s.`method` <=> BINARY b.`method`) AND (BINARY s.`request_method` <=> BINARY b.`request_method`) AND (BINARY s.`operator_type` <=> BINARY b.`operator_type`) AND (BINARY s.`oper_name` <=> BINARY b.`oper_name`) AND (BINARY s.`user_id` <=> BINARY b.`user_id`) AND (BINARY s.`dept_id` <=> BINARY b.`dept_id`) AND (BINARY s.`dept_name` <=> BINARY b.`dept_name`) AND (BINARY s.`client_key` <=> BINARY b.`client_key`) AND (BINARY s.`device_type` <=> BINARY b.`device_type`) AND (BINARY s.`browser` <=> BINARY b.`browser`) AND (BINARY s.`os` <=> BINARY b.`os`) AND (BINARY s.`oper_url` <=> BINARY b.`oper_url`) AND (BINARY s.`oper_ip` <=> BINARY b.`oper_ip`) AND (BINARY s.`oper_location` <=> BINARY b.`oper_location`) AND (BINARY s.`oper_param` <=> BINARY b.`oper_param`) AND (BINARY s.`json_result` <=> BINARY b.`json_result`) AND (BINARY s.`status` <=> BINARY b.`status`) AND (BINARY s.`error_msg` <=> BINARY b.`error_msg`) AND (BINARY s.`oper_time` <=> BINARY b.`oper_time`) AND (BINARY s.`cost_time` <=> BINARY b.`cost_time`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_oper_log backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_oper_log backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_dict_type` (`dict_id`,`dict_name`,`dict_type`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark`) SELECT `dict_id`,`dict_name`,`dict_type`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark` FROM `sys_dict_type`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_dict_type`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_dict_type`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_dict_type backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_dict_type backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_dict_type` s LEFT JOIN `bak_sw2kra_20261103_sys_dict_type` b ON s.`dict_id`=b.`dict_id` WHERE b.`dict_id` IS NULL OR NOT((BINARY s.`dict_id` <=> BINARY b.`dict_id`) AND (BINARY s.`dict_name` <=> BINARY b.`dict_name`) AND (BINARY s.`dict_type` <=> BINARY b.`dict_type`) AND (BINARY s.`create_dept` <=> BINARY b.`create_dept`) AND (BINARY s.`create_by` <=> BINARY b.`create_by`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`update_by` <=> BINARY b.`update_by`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`) AND (BINARY s.`remark` <=> BINARY b.`remark`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_dict_type backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_dict_type backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_dict_data` (`dict_code`,`dict_sort`,`dict_label`,`dict_value`,`dict_type`,`css_class`,`list_class`,`is_default`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark`) SELECT `dict_code`,`dict_sort`,`dict_label`,`dict_value`,`dict_type`,`css_class`,`list_class`,`is_default`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark` FROM `sys_dict_data`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_dict_data`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_dict_data`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_dict_data backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_dict_data backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_dict_data` s LEFT JOIN `bak_sw2kra_20261103_sys_dict_data` b ON s.`dict_code`=b.`dict_code` WHERE b.`dict_code` IS NULL OR NOT((BINARY s.`dict_code` <=> BINARY b.`dict_code`) AND (BINARY s.`dict_sort` <=> BINARY b.`dict_sort`) AND (BINARY s.`dict_label` <=> BINARY b.`dict_label`) AND (BINARY s.`dict_value` <=> BINARY b.`dict_value`) AND (BINARY s.`dict_type` <=> BINARY b.`dict_type`) AND (BINARY s.`css_class` <=> BINARY b.`css_class`) AND (BINARY s.`list_class` <=> BINARY b.`list_class`) AND (BINARY s.`is_default` <=> BINARY b.`is_default`) AND (BINARY s.`create_dept` <=> BINARY b.`create_dept`) AND (BINARY s.`create_by` <=> BINARY b.`create_by`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`update_by` <=> BINARY b.`update_by`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`) AND (BINARY s.`remark` <=> BINARY b.`remark`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_dict_data backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_dict_data backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_config` (`config_id`,`config_name`,`config_key`,`config_value`,`config_type`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark`) SELECT `config_id`,`config_name`,`config_key`,`config_value`,`config_type`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark` FROM `sys_config`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_config`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_config`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_config backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_config backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_config` s LEFT JOIN `bak_sw2kra_20261103_sys_config` b ON s.`config_id`=b.`config_id` WHERE b.`config_id` IS NULL OR NOT((BINARY s.`config_id` <=> BINARY b.`config_id`) AND (BINARY s.`config_name` <=> BINARY b.`config_name`) AND (BINARY s.`config_key` <=> BINARY b.`config_key`) AND (BINARY s.`config_value` <=> BINARY b.`config_value`) AND (BINARY s.`config_type` <=> BINARY b.`config_type`) AND (BINARY s.`create_dept` <=> BINARY b.`create_dept`) AND (BINARY s.`create_by` <=> BINARY b.`create_by`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`update_by` <=> BINARY b.`update_by`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`) AND (BINARY s.`remark` <=> BINARY b.`remark`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_config backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_config backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_login_info` (`info_id`,`user_name`,`client_key`,`device_type`,`ipaddr`,`login_location`,`browser`,`os`,`status`,`msg`,`login_time`) SELECT `info_id`,`user_name`,`client_key`,`device_type`,`ipaddr`,`login_location`,`browser`,`os`,`status`,`msg`,`login_time` FROM `sys_login_info`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_login_info`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_login_info`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_login_info backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_login_info backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_login_info` s LEFT JOIN `bak_sw2kra_20261103_sys_login_info` b ON s.`info_id`=b.`info_id` WHERE b.`info_id` IS NULL OR NOT((BINARY s.`info_id` <=> BINARY b.`info_id`) AND (BINARY s.`user_name` <=> BINARY b.`user_name`) AND (BINARY s.`client_key` <=> BINARY b.`client_key`) AND (BINARY s.`device_type` <=> BINARY b.`device_type`) AND (BINARY s.`ipaddr` <=> BINARY b.`ipaddr`) AND (BINARY s.`login_location` <=> BINARY b.`login_location`) AND (BINARY s.`browser` <=> BINARY b.`browser`) AND (BINARY s.`os` <=> BINARY b.`os`) AND (BINARY s.`status` <=> BINARY b.`status`) AND (BINARY s.`msg` <=> BINARY b.`msg`) AND (BINARY s.`login_time` <=> BINARY b.`login_time`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_login_info backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_login_info backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_notice` (`notice_id`,`notice_title`,`notice_type`,`notice_content`,`status`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark`) SELECT `notice_id`,`notice_title`,`notice_type`,`notice_content`,`status`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark` FROM `sys_notice`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_notice`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_notice`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_notice backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_notice backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_notice` s LEFT JOIN `bak_sw2kra_20261103_sys_notice` b ON s.`notice_id`=b.`notice_id` WHERE b.`notice_id` IS NULL OR NOT((BINARY s.`notice_id` <=> BINARY b.`notice_id`) AND (BINARY s.`notice_title` <=> BINARY b.`notice_title`) AND (BINARY s.`notice_type` <=> BINARY b.`notice_type`) AND (BINARY s.`notice_content` <=> BINARY b.`notice_content`) AND (BINARY s.`status` <=> BINARY b.`status`) AND (BINARY s.`create_dept` <=> BINARY b.`create_dept`) AND (BINARY s.`create_by` <=> BINARY b.`create_by`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`update_by` <=> BINARY b.`update_by`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`) AND (BINARY s.`remark` <=> BINARY b.`remark`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_notice backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_notice backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_message` (`message_id`,`category`,`type`,`source`,`title`,`message`,`content`,`data_json`,`path`,`send_user_ids`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`) SELECT `message_id`,`category`,`type`,`source`,`title`,`message`,`content`,`data_json`,`path`,`send_user_ids`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time` FROM `sys_message`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_message`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_message`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_message backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_message backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_message` s LEFT JOIN `bak_sw2kra_20261103_sys_message` b ON s.`message_id`=b.`message_id` WHERE b.`message_id` IS NULL OR NOT((BINARY s.`message_id` <=> BINARY b.`message_id`) AND (BINARY s.`category` <=> BINARY b.`category`) AND (BINARY s.`type` <=> BINARY b.`type`) AND (BINARY s.`source` <=> BINARY b.`source`) AND (BINARY s.`title` <=> BINARY b.`title`) AND (BINARY s.`message` <=> BINARY b.`message`) AND (BINARY s.`content` <=> BINARY b.`content`) AND (BINARY s.`data_json` <=> BINARY b.`data_json`) AND (BINARY s.`path` <=> BINARY b.`path`) AND (BINARY s.`send_user_ids` <=> BINARY b.`send_user_ids`) AND (BINARY s.`create_dept` <=> BINARY b.`create_dept`) AND (BINARY s.`create_by` <=> BINARY b.`create_by`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`update_by` <=> BINARY b.`update_by`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_message backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_message backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_oss` (`oss_id`,`file_name`,`original_name`,`file_suffix`,`url`,`ext1`,`create_dept`,`create_time`,`create_by`,`update_time`,`update_by`,`service`) SELECT `oss_id`,`file_name`,`original_name`,`file_suffix`,`url`,`ext1`,`create_dept`,`create_time`,`create_by`,`update_time`,`update_by`,`service` FROM `sys_oss`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_oss`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_oss`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_oss backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_oss backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_oss` s LEFT JOIN `bak_sw2kra_20261103_sys_oss` b ON s.`oss_id`=b.`oss_id` WHERE b.`oss_id` IS NULL OR NOT((BINARY s.`oss_id` <=> BINARY b.`oss_id`) AND (BINARY s.`file_name` <=> BINARY b.`file_name`) AND (BINARY s.`original_name` <=> BINARY b.`original_name`) AND (BINARY s.`file_suffix` <=> BINARY b.`file_suffix`) AND (BINARY s.`url` <=> BINARY b.`url`) AND (BINARY s.`ext1` <=> BINARY b.`ext1`) AND (BINARY s.`create_dept` <=> BINARY b.`create_dept`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`create_by` <=> BINARY b.`create_by`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`) AND (BINARY s.`update_by` <=> BINARY b.`update_by`) AND (BINARY s.`service` <=> BINARY b.`service`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_oss backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_oss backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_oss_config` (`oss_config_id`,`config_key`,`access_key`,`secret_key`,`bucket_name`,`prefix`,`endpoint`,`domain_url`,`is_https`,`region`,`access_policy`,`status`,`ext1`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark`) SELECT `oss_config_id`,`config_key`,`access_key`,`secret_key`,`bucket_name`,`prefix`,`endpoint`,`domain_url`,`is_https`,`region`,`access_policy`,`status`,`ext1`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`,`remark` FROM `sys_oss_config`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_oss_config`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_oss_config`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_oss_config backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_oss_config backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_oss_config` s LEFT JOIN `bak_sw2kra_20261103_sys_oss_config` b ON s.`oss_config_id`=b.`oss_config_id` WHERE b.`oss_config_id` IS NULL OR NOT((BINARY s.`oss_config_id` <=> BINARY b.`oss_config_id`) AND (BINARY s.`config_key` <=> BINARY b.`config_key`) AND (BINARY s.`access_key` <=> BINARY b.`access_key`) AND (BINARY s.`secret_key` <=> BINARY b.`secret_key`) AND (BINARY s.`bucket_name` <=> BINARY b.`bucket_name`) AND (BINARY s.`prefix` <=> BINARY b.`prefix`) AND (BINARY s.`endpoint` <=> BINARY b.`endpoint`) AND (BINARY s.`domain_url` <=> BINARY b.`domain_url`) AND (BINARY s.`is_https` <=> BINARY b.`is_https`) AND (BINARY s.`region` <=> BINARY b.`region`) AND (BINARY s.`access_policy` <=> BINARY b.`access_policy`) AND (BINARY s.`status` <=> BINARY b.`status`) AND (BINARY s.`ext1` <=> BINARY b.`ext1`) AND (BINARY s.`create_dept` <=> BINARY b.`create_dept`) AND (BINARY s.`create_by` <=> BINARY b.`create_by`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`update_by` <=> BINARY b.`update_by`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`) AND (BINARY s.`remark` <=> BINARY b.`remark`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_oss_config backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_oss_config backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_client` (`id`,`client_id`,`client_key`,`client_secret`,`grant_type`,`device_type`,`access_path`,`ip_whitelist`,`active_timeout`,`timeout`,`status`,`del_flag`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time`) SELECT `id`,`client_id`,`client_key`,`client_secret`,`grant_type`,`device_type`,`access_path`,`ip_whitelist`,`active_timeout`,`timeout`,`status`,`del_flag`,`create_dept`,`create_by`,`create_time`,`update_by`,`update_time` FROM `sys_client`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_client`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_client`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_client backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_client backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_client` s LEFT JOIN `bak_sw2kra_20261103_sys_client` b ON s.`id`=b.`id` WHERE b.`id` IS NULL OR NOT((BINARY s.`id` <=> BINARY b.`id`) AND (BINARY s.`client_id` <=> BINARY b.`client_id`) AND (BINARY s.`client_key` <=> BINARY b.`client_key`) AND (BINARY s.`client_secret` <=> BINARY b.`client_secret`) AND (BINARY s.`grant_type` <=> BINARY b.`grant_type`) AND (BINARY s.`device_type` <=> BINARY b.`device_type`) AND (BINARY s.`access_path` <=> BINARY b.`access_path`) AND (BINARY s.`ip_whitelist` <=> BINARY b.`ip_whitelist`) AND (BINARY s.`active_timeout` <=> BINARY b.`active_timeout`) AND (BINARY s.`timeout` <=> BINARY b.`timeout`) AND (BINARY s.`status` <=> BINARY b.`status`) AND (BINARY s.`del_flag` <=> BINARY b.`del_flag`) AND (BINARY s.`create_dept` <=> BINARY b.`create_dept`) AND (BINARY s.`create_by` <=> BINARY b.`create_by`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`update_by` <=> BINARY b.`update_by`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_client backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_client backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_user_bind_platform` (`user_id`,`source_db`,`platform_busier_id`,`platform_busier_account`,`status`,`reject_reason`,`create_time`,`review_time`,`review_account`) SELECT `user_id`,`source_db`,`platform_busier_id`,`platform_busier_account`,`status`,`reject_reason`,`create_time`,`review_time`,`review_account` FROM `sys_user_bind_platform`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_user_bind_platform`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_user_bind_platform`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_user_bind_platform backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_user_bind_platform backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_user_bind_platform` s LEFT JOIN `bak_sw2kra_20261103_sys_user_bind_platform` b ON s.`user_id`=b.`user_id` AND s.`source_db`=b.`source_db` AND s.`platform_busier_id`=b.`platform_busier_id` WHERE b.`user_id` IS NULL OR NOT((BINARY s.`user_id` <=> BINARY b.`user_id`) AND (BINARY s.`source_db` <=> BINARY b.`source_db`) AND (BINARY s.`platform_busier_id` <=> BINARY b.`platform_busier_id`) AND (BINARY s.`platform_busier_account` <=> BINARY b.`platform_busier_account`) AND (BINARY s.`status` <=> BINARY b.`status`) AND (BINARY s.`reject_reason` <=> BINARY b.`reject_reason`) AND (BINARY s.`create_time` <=> BINARY b.`create_time`) AND (BINARY s.`review_time` <=> BINARY b.`review_time`) AND (BINARY s.`review_account` <=> BINARY b.`review_account`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_user_bind_platform backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_user_bind_platform backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_user_preference` (`user_id`,`include_sub_promote`,`idcard_dedup`,`update_time`) SELECT `user_id`,`include_sub_promote`,`idcard_dedup`,`update_time` FROM `sys_user_preference`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_user_preference`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_user_preference`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_user_preference backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_user_preference backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_user_preference` s LEFT JOIN `bak_sw2kra_20261103_sys_user_preference` b ON s.`user_id`=b.`user_id` WHERE b.`user_id` IS NULL OR NOT((BINARY s.`user_id` <=> BINARY b.`user_id`) AND (BINARY s.`include_sub_promote` <=> BINARY b.`include_sub_promote`) AND (BINARY s.`idcard_dedup` <=> BINARY b.`idcard_dedup`) AND (BINARY s.`update_time` <=> BINARY b.`update_time`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_user_preference backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_user_preference backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sj_job` (`id`,`namespace_id`,`biz_id`,`group_name`,`job_name`,`args_str`,`args_type`,`next_trigger_at`,`job_status`,`task_type`,`route_key`,`executor_type`,`executor_info`,`trigger_type`,`trigger_interval`,`block_strategy`,`executor_timeout`,`max_retry_times`,`parallel_num`,`retry_interval`,`bucket_index`,`resident`,`notify_ids`,`owner_id`,`labels`,`description`,`ext_attrs`,`deleted`,`create_dt`,`update_dt`) SELECT `id`,`namespace_id`,`biz_id`,`group_name`,`job_name`,`args_str`,`args_type`,`next_trigger_at`,`job_status`,`task_type`,`route_key`,`executor_type`,`executor_info`,`trigger_type`,`trigger_interval`,`block_strategy`,`executor_timeout`,`max_retry_times`,`parallel_num`,`retry_interval`,`bucket_index`,`resident`,`notify_ids`,`owner_id`,`labels`,`description`,`ext_attrs`,`deleted`,`create_dt`,`update_dt` FROM `sj_job`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sj_job`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sj_job`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sj_job backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sj_job backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sj_job` s LEFT JOIN `bak_sw2kra_20261103_sj_job` b ON s.`id`=b.`id` WHERE b.`id` IS NULL OR NOT((BINARY s.`id` <=> BINARY b.`id`) AND (BINARY s.`namespace_id` <=> BINARY b.`namespace_id`) AND (BINARY s.`biz_id` <=> BINARY b.`biz_id`) AND (BINARY s.`group_name` <=> BINARY b.`group_name`) AND (BINARY s.`job_name` <=> BINARY b.`job_name`) AND (BINARY s.`args_str` <=> BINARY b.`args_str`) AND (BINARY s.`args_type` <=> BINARY b.`args_type`) AND (BINARY s.`next_trigger_at` <=> BINARY b.`next_trigger_at`) AND (BINARY s.`job_status` <=> BINARY b.`job_status`) AND (BINARY s.`task_type` <=> BINARY b.`task_type`) AND (BINARY s.`route_key` <=> BINARY b.`route_key`) AND (BINARY s.`executor_type` <=> BINARY b.`executor_type`) AND (BINARY s.`executor_info` <=> BINARY b.`executor_info`) AND (BINARY s.`trigger_type` <=> BINARY b.`trigger_type`) AND (BINARY s.`trigger_interval` <=> BINARY b.`trigger_interval`) AND (BINARY s.`block_strategy` <=> BINARY b.`block_strategy`) AND (BINARY s.`executor_timeout` <=> BINARY b.`executor_timeout`) AND (BINARY s.`max_retry_times` <=> BINARY b.`max_retry_times`) AND (BINARY s.`parallel_num` <=> BINARY b.`parallel_num`) AND (BINARY s.`retry_interval` <=> BINARY b.`retry_interval`) AND (BINARY s.`bucket_index` <=> BINARY b.`bucket_index`) AND (BINARY s.`resident` <=> BINARY b.`resident`) AND (BINARY s.`notify_ids` <=> BINARY b.`notify_ids`) AND (BINARY s.`owner_id` <=> BINARY b.`owner_id`) AND (BINARY s.`labels` <=> BINARY b.`labels`) AND (BINARY s.`description` <=> BINARY b.`description`) AND (BINARY s.`ext_attrs` <=> BINARY b.`ext_attrs`) AND (BINARY s.`deleted` <=> BINARY b.`deleted`) AND (BINARY s.`create_dt` <=> BINARY b.`create_dt`) AND (BINARY s.`update_dt` <=> BINARY b.`update_dt`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sj_job backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sj_job backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_alert_rule` (`id`,`rule_name`,`rule_type`,`monitor_metric`,`stat_period_days`,`mom_direction`,`mom_threshold`,`unlogin_days`,`monitor_scope`,`warning_color`,`creator_id`,`enabled`,`is_deleted`,`created_at`,`updated_at`) SELECT `id`,`rule_name`,`rule_type`,`monitor_metric`,`stat_period_days`,`mom_direction`,`mom_threshold`,`unlogin_days`,`monitor_scope`,`warning_color`,`creator_id`,`enabled`,`is_deleted`,`created_at`,`updated_at` FROM `sys_alert_rule`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_alert_rule`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_alert_rule`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_alert_rule backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_alert_rule backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_alert_rule` s LEFT JOIN `bak_sw2kra_20261103_sys_alert_rule` b ON s.`id`=b.`id` WHERE b.`id` IS NULL OR NOT((BINARY s.`id` <=> BINARY b.`id`) AND (BINARY s.`rule_name` <=> BINARY b.`rule_name`) AND (BINARY s.`rule_type` <=> BINARY b.`rule_type`) AND (BINARY s.`monitor_metric` <=> BINARY b.`monitor_metric`) AND (BINARY s.`stat_period_days` <=> BINARY b.`stat_period_days`) AND (BINARY s.`mom_direction` <=> BINARY b.`mom_direction`) AND (BINARY s.`mom_threshold` <=> BINARY b.`mom_threshold`) AND (BINARY s.`unlogin_days` <=> BINARY b.`unlogin_days`) AND (BINARY s.`monitor_scope` <=> BINARY b.`monitor_scope`) AND (BINARY s.`warning_color` <=> BINARY b.`warning_color`) AND (BINARY s.`creator_id` <=> BINARY b.`creator_id`) AND (BINARY s.`enabled` <=> BINARY b.`enabled`) AND (BINARY s.`is_deleted` <=> BINARY b.`is_deleted`) AND (BINARY s.`created_at` <=> BINARY b.`created_at`) AND (BINARY s.`updated_at` <=> BINARY b.`updated_at`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_alert_rule backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_alert_rule backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_alert_record` (`id`,`platform_code`,`platform_name`,`rule_id`,`rule_name`,`rule_type`,`monitor_metric`,`target_promote_id`,`target_promote_name`,`business_id`,`business_name`,`alert_content`,`status`,`alert_date`,`created_at`,`updated_at`) SELECT `id`,`platform_code`,`platform_name`,`rule_id`,`rule_name`,`rule_type`,`monitor_metric`,`target_promote_id`,`target_promote_name`,`business_id`,`business_name`,`alert_content`,`status`,`alert_date`,`created_at`,`updated_at` FROM `sys_alert_record`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_alert_record`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_alert_record`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_alert_record backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_alert_record backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_alert_record` s LEFT JOIN `bak_sw2kra_20261103_sys_alert_record` b ON s.`id`=b.`id` WHERE b.`id` IS NULL OR NOT((BINARY s.`id` <=> BINARY b.`id`) AND (BINARY s.`platform_code` <=> BINARY b.`platform_code`) AND (BINARY s.`platform_name` <=> BINARY b.`platform_name`) AND (BINARY s.`rule_id` <=> BINARY b.`rule_id`) AND (BINARY s.`rule_name` <=> BINARY b.`rule_name`) AND (BINARY s.`rule_type` <=> BINARY b.`rule_type`) AND (BINARY s.`monitor_metric` <=> BINARY b.`monitor_metric`) AND (BINARY s.`target_promote_id` <=> BINARY b.`target_promote_id`) AND (BINARY s.`target_promote_name` <=> BINARY b.`target_promote_name`) AND (BINARY s.`business_id` <=> BINARY b.`business_id`) AND (BINARY s.`business_name` <=> BINARY b.`business_name`) AND (BINARY s.`alert_content` <=> BINARY b.`alert_content`) AND (BINARY s.`status` <=> BINARY b.`status`) AND (BINARY s.`alert_date` <=> BINARY b.`alert_date`) AND (BINARY s.`created_at` <=> BINARY b.`created_at`) AND (BINARY s.`updated_at` <=> BINARY b.`updated_at`) AND (BINARY s.`unclosed_flag` <=> BINARY b.`unclosed_flag`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_alert_record backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_alert_record backup bytes'; END IF; - -INSERT INTO `bak_sw2kra_20261103_sys_alert_operation_log` (`id`,`alert_id`,`operator_id`,`operator_name`,`log_type`,`action_detail`,`note_content`,`attachment_ids`,`created_at`) SELECT `id`,`alert_id`,`operator_id`,`operator_name`,`log_type`,`action_detail`,`note_content`,`attachment_ids`,`created_at` FROM `sys_alert_operation_log`; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_alert_operation_log`) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `sys_alert_operation_log`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_alert_operation_log backup rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_alert_operation_log backup rows'; END IF; - -SELECT (SELECT COUNT(*) FROM `sys_alert_operation_log` s LEFT JOIN `bak_sw2kra_20261103_sys_alert_operation_log` b ON s.`id`=b.`id` WHERE b.`id` IS NULL OR NOT((BINARY s.`id` <=> BINARY b.`id`) AND (BINARY s.`alert_id` <=> BINARY b.`alert_id`) AND (BINARY s.`operator_id` <=> BINARY b.`operator_id`) AND (BINARY s.`operator_name` <=> BINARY b.`operator_name`) AND (BINARY s.`log_type` <=> BINARY b.`log_type`) AND (BINARY s.`action_detail` <=> BINARY b.`action_detail`) AND (BINARY s.`note_content` <=> BINARY b.`note_content`) AND (BINARY s.`attachment_ids` <=> BINARY b.`attachment_ids`) AND (BINARY s.`created_at` <=> BINARY b.`created_at`))) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('backup','sys_alert_operation_log backup bytes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='sys_alert_operation_log backup bytes'; END IF; - -COMMIT; - --- 四、按 Kra 当前定义创建目标表,并增加商务账号和岗位扩展字段。 - -CREATE TABLE `sys_schema_migrations` (`id` varchar(255),PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_users` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`uuid` char(36),`username` varchar(191),`password` longtext,`nick_name` longtext,`header_img` longtext,`authority_id` bigint unsigned,`dept_id` bigint unsigned,`phone` longtext,`email` longtext,`enable` bigint DEFAULT 1,`origin_setting` text,`password_updated_at` datetime(3) NULL,`must_change_password` boolean,PRIMARY KEY (`id`),INDEX `idx_sys_users_deleted_at` (`deleted_at`),INDEX `idx_sys_users_uuid` (`uuid`),INDEX `idx_sys_users_username` (`username`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_authorities` (`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`authority_id` bigint unsigned AUTO_INCREMENT,`authority_name` longtext,`parent_id` bigint unsigned,`data_scope` bigint DEFAULT 1,`default_router` varchar(191) DEFAULT 'dashboard',PRIMARY KEY (`authority_id`),INDEX `idx_sys_authorities_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_base_menus` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`menu_level` bigint unsigned,`parent_id` bigint unsigned,`path` longtext,`name` longtext,`hidden` boolean,`component` longtext,`sort` bigint,`active_name` longtext,`keep_alive` boolean,`default_menu` boolean,`title` longtext,`icon` longtext,`close_tab` boolean,`transition_type` longtext,PRIMARY KEY (`id`),INDEX `idx_sys_base_menus_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_user_authority` (`sys_user_id` bigint unsigned,`sys_authority_authority_id` bigint unsigned) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_authority_menus` (`sys_authority_authority_id` bigint unsigned,`sys_base_menu_id` bigint unsigned) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_base_menu_parameters` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`sys_base_menu_id` bigint unsigned,`type` longtext,`key` longtext,`value` longtext,PRIMARY KEY (`id`),INDEX `idx_sys_base_menu_parameters_deleted_at` (`deleted_at`),INDEX `idx_sys_base_menu_parameters_menu_id` (`sys_base_menu_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_apis` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`path` longtext,`description` longtext,`api_group` longtext,`method` longtext,PRIMARY KEY (`id`),INDEX `idx_sys_apis_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_ignore_apis` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`path` longtext,`method` varchar(191) DEFAULT 'POST',PRIMARY KEY (`id`),INDEX `idx_sys_ignore_apis_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_authority_apis` (`authority_id` bigint unsigned,`api_id` bigint unsigned,PRIMARY KEY (`authority_id`,`api_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `casbin_rule` (`id` bigint unsigned AUTO_INCREMENT,`ptype` varchar(100),`v0` varchar(100),`v1` varchar(100),`v2` varchar(100),`v3` varchar(100),`v4` varchar(100),`v5` varchar(100),PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_base_menu_btns` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`name` longtext,`desc` longtext,`sys_base_menu_id` bigint unsigned,PRIMARY KEY (`id`),INDEX `idx_sys_base_menu_btns_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_authority_btns` (`authority_id` bigint unsigned,`sys_menu_id` bigint unsigned,`sys_base_menu_btn_id` bigint unsigned) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_departments` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`name` varchar(191),`parent_id` bigint unsigned,`ancestors` longtext,`sort` bigint,`leader_id` bigint unsigned,`status` boolean DEFAULT true,PRIMARY KEY (`id`),INDEX `idx_sys_departments_deleted_at` (`deleted_at`),INDEX `idx_sys_departments_name` (`name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_positions` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`name` varchar(191),`code` longtext,`sort` bigint,`status` boolean DEFAULT true,`remark` longtext,PRIMARY KEY (`id`),INDEX `idx_sys_positions_deleted_at` (`deleted_at`),INDEX `idx_sys_positions_name` (`name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_user_departments` (`sys_user_id` bigint unsigned,`sys_department_id` bigint unsigned) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_user_positions` (`sys_user_id` bigint unsigned,`sys_position_id` bigint unsigned) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_authority_departments` (`sys_authority_authority_id` bigint unsigned,`sys_department_id` bigint unsigned,INDEX `idx_sys_authority_departments_authority_id` (`sys_authority_authority_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_dictionaries` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`name` longtext,`type` longtext,`status` boolean,`desc` longtext,`parent_id` bigint unsigned,PRIMARY KEY (`id`),INDEX `idx_sys_dictionaries_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_dictionary_details` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`label` longtext,`value` longtext,`extend` longtext,`status` boolean,`sort` bigint,`sys_dictionary_id` bigint unsigned,`parent_id` bigint unsigned,`level` bigint,`path` longtext,PRIMARY KEY (`id`),INDEX `idx_sys_dictionary_details_deleted_at` (`deleted_at`),INDEX `idx_sys_dictionary_details_dictionary_id` (`sys_dictionary_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_params` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`name` longtext,`key` longtext,`value` longtext,`desc` longtext,PRIMARY KEY (`id`),INDEX `idx_sys_params_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_api_tokens` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`user_id` bigint unsigned,`authority_id` bigint unsigned,`token` text,`status` boolean,`expires_at` datetime(3) NULL,`remark` longtext,PRIMARY KEY (`id`),INDEX `idx_sys_api_tokens_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `jwt_blacklists` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`jwt` text,PRIMARY KEY (`id`),INDEX `idx_jwt_blacklists_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_security_config` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`captcha_open` bigint DEFAULT 0,`captcha_timeout` bigint DEFAULT 3600,`key_long` bigint DEFAULT 6,`img_width` bigint DEFAULT 240,`img_height` bigint DEFAULT 80,`pwd_min_length` bigint DEFAULT 8,`pwd_require_upper` boolean DEFAULT false,`pwd_require_lower` boolean DEFAULT false,`pwd_require_digit` boolean DEFAULT false,`pwd_require_special` boolean DEFAULT false,`limit_enable` boolean DEFAULT false,`limit_window` bigint DEFAULT 60,`limit_count` bigint DEFAULT 30,`lock_enable` boolean DEFAULT false,`lock_threshold` bigint DEFAULT 5,`lock_duration` bigint DEFAULT 30,`pwd_expire_enable` boolean DEFAULT false,`pwd_expire_days` bigint DEFAULT 90,`force_new_user_change_password` boolean DEFAULT false,PRIMARY KEY (`id`),INDEX `idx_sys_security_config_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_versions` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`version_name` longtext,`version_code` longtext,`description` longtext,`version_data` text,PRIMARY KEY (`id`),INDEX `idx_sys_versions_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_export_templates` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`db_name` longtext,`name` longtext,`table_name` longtext,`template_id` longtext,`template_info` text,`sql` text,`import_sql` text,`limit` bigint,`order` longtext,PRIMARY KEY (`id`),INDEX `idx_sys_export_templates_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_export_template_condition` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`template_id` varchar(191),`from` longtext,`column` longtext,`operator` longtext,PRIMARY KEY (`id`),INDEX `idx_sys_export_template_condition_deleted_at` (`deleted_at`),INDEX `idx_sys_export_template_condition_template_id` (`template_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_export_template_join` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`template_id` varchar(191),`joins` longtext,`table` longtext,`on` longtext,PRIMARY KEY (`id`),INDEX `idx_sys_export_template_join_deleted_at` (`deleted_at`),INDEX `idx_sys_export_template_join_template_id` (`template_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_operation_records` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`ip` longtext,`method` longtext,`path` longtext,`status` bigint,`latency_ms` bigint,`agent` text,`error_message` longtext,`body` text,`resp` text,`user_id` bigint unsigned,`request_id` varchar(191),`trace_id` varchar(191),`device_id` longtext,PRIMARY KEY (`id`),INDEX `idx_sys_operation_records_deleted_at` (`deleted_at`),INDEX `idx_sys_operation_records_request_id` (`request_id`),INDEX `idx_sys_operation_records_trace_id` (`trace_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_login_logs` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`username` longtext,`ip` longtext,`status` boolean,`error_message` longtext,`agent` longtext,`user_id` bigint unsigned,PRIMARY KEY (`id`),INDEX `idx_sys_login_logs_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_data_access_logs` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`event_type` longtext,`target_table` longtext,`operation` longtext,`user_id` bigint unsigned,`authority_id` bigint unsigned,`scope` bigint,`request_id` longtext,`method` longtext,`path` longtext,`detail` longtext,PRIMARY KEY (`id`),INDEX `idx_sys_data_access_logs_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_error` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`form` text,`info` text,`level` longtext,`request_id` varchar(191),`trace_id` varchar(191),`solution` text,`status` varchar(191) DEFAULT '未处理',PRIMARY KEY (`id`),INDEX `idx_sys_error_deleted_at` (`deleted_at`),INDEX `idx_sys_error_request_id` (`request_id`),INDEX `idx_sys_error_trace_id` (`trace_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `media_file_upload_and_downloads` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`name` longtext,`class_id` bigint,`url` longtext,`tag` longtext,`key` varchar(191),`size` bigint,`mime` longtext,`md5` varchar(191),`user_id` bigint unsigned,PRIMARY KEY (`id`),INDEX `idx_media_file_upload_and_downloads_deleted_at` (`deleted_at`),INDEX `idx_media_file_upload_and_downloads_key` (`key`),INDEX `idx_media_file_upload_and_downloads_md5` (`md5`),INDEX `idx_media_file_upload_and_downloads_user_id` (`user_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `media_attachment_category` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`name` longtext,`pid` bigint unsigned,PRIMARY KEY (`id`),INDEX `idx_media_attachment_category_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `media_uploads` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`user_id` bigint unsigned,`file_name` longtext,`file_hash` varchar(191),`file_size` bigint,`chunk_size` bigint,`chunk_total` bigint,`status` longtext,`storage_key` longtext,`media_id` bigint unsigned,PRIMARY KEY (`id`),INDEX `idx_media_uploads_deleted_at` (`deleted_at`),INDEX `idx_media_uploads_user_id` (`user_id`),INDEX `idx_media_uploads_file_hash` (`file_hash`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `media_upload_chunks` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`upload_id` bigint unsigned,`chunk_index` bigint,`chunk_hash` longtext,`size` bigint,PRIMARY KEY (`id`),INDEX `idx_media_upload_chunks_deleted_at` (`deleted_at`),UNIQUE INDEX `idx_upload_chunk` (`upload_id`,`chunk_index`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_announcements` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`title` longtext,`content` text,`user_id` bigint,`attachments` JSON,PRIMARY KEY (`id`),INDEX `idx_sys_announcements_deleted_at` (`deleted_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_integration_configs` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`kind` varchar(32) NOT NULL,`provider` varchar(64) NOT NULL,`enabled` boolean,`config` text NOT NULL,PRIMARY KEY (`id`),UNIQUE INDEX `idx_integration_kind_provider` (`kind`,`provider`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_timed_tasks` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`name` varchar(191),`description` longtext,`spec` longtext,`with_seconds` boolean,`executor_type` longtext,`method_name` longtext,`params` JSON,`http_url` longtext,`http_method` longtext,`http_header` JSON,`http_body` text,`http_allow_private` boolean,`enabled` boolean,PRIMARY KEY (`id`),INDEX `idx_sys_timed_tasks_deleted_at` (`deleted_at`),INDEX `idx_sys_timed_tasks_name` (`name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `sys_timed_task_logs` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`task_id` bigint unsigned,`task_name` longtext,`trigger_type` longtext,`started_at` datetime(3) NULL,`finished_at` datetime(3) NULL,`duration_ms` bigint,`status` longtext,`error_msg` text,`output` text,PRIMARY KEY (`id`),INDEX `idx_sys_timed_task_logs_deleted_at` (`deleted_at`),INDEX `idx_sys_timed_task_logs_task_id` (`task_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `pay_orders` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`trade_no` varchar(128) NOT NULL,`provider` varchar(64) NOT NULL,`provider_trade_no` varchar(128),`query_id` varchar(128),`business_type` varchar(64) NOT NULL,`business_id` varchar(128) NOT NULL,`subject` varchar(256) NOT NULL,`payment_mode` varchar(32) NOT NULL DEFAULT 'external',`original_amount` bigint NOT NULL DEFAULT 0,`amount` bigint NOT NULL,`paid_amount` bigint NOT NULL DEFAULT 0,`payer_paid_amount` bigint NOT NULL DEFAULT 0,`cash_paid_amount` bigint NOT NULL DEFAULT 0,`point_paid_amount` bigint NOT NULL DEFAULT 0,`discount_amount` bigint NOT NULL DEFAULT 0,`provider_discount_amount` bigint NOT NULL DEFAULT 0,`merchant_discount_amount` bigint NOT NULL DEFAULT 0,`settlement_amount` bigint NOT NULL DEFAULT 0,`currency` varchar(16) NOT NULL,`payer_currency` varchar(16),`amount_breakdown_known` boolean NOT NULL DEFAULT false,`payment_status` varchar(32) NOT NULL,`provider_status` varchar(64),`fulfillment_status` varchar(32) NOT NULL,`refund_status` varchar(32) NOT NULL,`refunded_amount` bigint NOT NULL DEFAULT 0,`refund_requested_amount` bigint NOT NULL DEFAULT 0,`refund_no` varchar(128),`confirmation_id` varchar(36) NOT NULL,`request_fingerprint` varchar(64) NOT NULL,`create_payload` text,`extra` text,`last_event_id` varchar(128),`last_payload_hash` varchar(64),`last_error` varchar(512),`fulfillment_token` varchar(36),`refund_token` varchar(36),`version` bigint unsigned NOT NULL DEFAULT 1,`paid_at` datetime(3) NULL,`fulfilled_at` datetime(3) NULL,`refunded_at` datetime(3) NULL,`fulfillment_lease_until` datetime(3) NULL,`refund_lease_until` datetime(3) NULL,PRIMARY KEY (`id`),UNIQUE INDEX `idx_pay_orders_provider_trade` (`trade_no`,`provider`),UNIQUE INDEX `idx_pay_orders_provider_provider_trade` (`provider`,`provider_trade_no`),INDEX `idx_pay_orders_provider` (`provider`),INDEX `idx_pay_orders_business` (`business_type`,`business_id`),INDEX `idx_pay_orders_payment_mode` (`payment_mode`),INDEX `idx_pay_orders_payment_status` (`payment_status`),INDEX `idx_pay_orders_fulfillment_status` (`fulfillment_status`),INDEX `idx_pay_orders_refund_status` (`refund_status`),INDEX `idx_pay_orders_refund_no` (`refund_no`),UNIQUE INDEX `idx_pay_orders_confirmation_id` (`confirmation_id`),INDEX `idx_pay_orders_request_fingerprint` (`request_fingerprint`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -CREATE TABLE `pay_events` (`id` bigint unsigned AUTO_INCREMENT,`provider` varchar(64) NOT NULL,`trade_no` varchar(128) NOT NULL,`type` varchar(64) NOT NULL,`source` varchar(64) NOT NULL,`status` varchar(64),`provider_status` varchar(64),`message` varchar(512),`event_id` varchar(128),`payload_hash` varchar(64),`amount` bigint NOT NULL DEFAULT 0,`currency` varchar(16),`operator_id` bigint unsigned,`operator_name` varchar(128),`client_ip` varchar(64),`user_agent` varchar(512),`device_id` varchar(128),`created_at` datetime(3) NULL,PRIMARY KEY (`id`),INDEX `idx_pay_events_order` (`provider`,`trade_no`),INDEX `idx_pay_events_type` (`type`),INDEX `idx_pay_events_source` (`source`),INDEX `idx_pay_events_event_id` (`event_id`),INDEX `idx_pay_events_operator_id` (`operator_id`),INDEX `idx_pay_events_created_at` (`created_at`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; - -ALTER TABLE sys_users ADD COLUMN level TINYINT UNSIGNED NOT NULL DEFAULT 0,ADD COLUMN parent_id BIGINT UNSIGNED NOT NULL DEFAULT 0,ADD COLUMN id_path VARCHAR(255) NOT NULL DEFAULT '0',ADD COLUMN real_name VARCHAR(30) NOT NULL DEFAULT '',ADD COLUMN qq_number VARCHAR(20) NOT NULL DEFAULT '',ADD COLUMN business_status TINYINT UNSIGNED NOT NULL DEFAULT 0,ADD COLUMN reject_reason VARCHAR(200) NOT NULL DEFAULT '',ADD INDEX idx_sys_users_business_parent(parent_id); - -ALTER TABLE sys_positions ADD COLUMN dept_id BIGINT UNSIGNED NULL,ADD INDEX idx_sys_positions_department(dept_id); - -CREATE TABLE sw_kra_id_map (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,entity VARCHAR(32) NOT NULL,old_id VARCHAR(64) NOT NULL,new_id BIGINT UNSIGNED NULL,UNIQUE KEY uk_source(entity,old_id),UNIQUE KEY uk_target(entity,new_id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; - -CREATE TABLE sw_kra_menu_permissions (source_menu_id BIGINT UNSIGNED PRIMARY KEY,source_permission VARCHAR(160),button_key VARCHAR(160)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -CREATE TABLE sw_kra_api_contract (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,method VARCHAR(12),source_path VARCHAR(255),target_path VARCHAR(255),source_permission VARCHAR(160),controller VARCHAR(80),implementation_status VARCHAR(32) NOT NULL DEFAULT 'pending_go_handler') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -START TRANSACTION; - --- 五、写入 Kra 必需初始数据,并按 ID 映射转换用户、角色、部门及其他框架数据。 - -INSERT INTO `casbin_rule` (`id`,`ptype`,`v0`,`v1`,`v2`,`v3`,`v4`,`v5`) VALUES -(1,'p','888','/integration/configs/:kind','GET','','',''), -(2,'p','888','/integration/configs/:kind/:provider','DELETE','','',''), -(3,'p','888','/integration/configs/:kind/:provider','GET','','',''), -(4,'p','888','/integration/configs/:kind/:provider','PUT','','',''), -(5,'p','888','/integration/configs/:kind/:provider/test','POST','','',''), -(6,'p','888','/integration/sms/:provider/send','POST','','',''), -(7,'p','888','/payment/create','POST','','',''), -(8,'p','888','/payment/fulfill','POST','','',''), -(9,'p','888','/payment/order','POST','','',''), -(10,'p','888','/payment/orders','GET','','',''), -(11,'p','888','/payment/orders/:provider/:tradeNo','GET','','',''), -(12,'p','888','/payment/orders/:provider/:tradeNo/events','GET','','',''), -(13,'p','888','/payment/orders/:provider/:tradeNo/fulfill','POST','','',''), -(14,'p','888','/payment/orders/:provider/:tradeNo/refund','POST','','',''), -(15,'p','888','/payment/orders/summary','GET','','',''), -(16,'p','888','/payment/providers/:provider/test','POST','','',''), -(17,'p','888','/payment/query','POST','','',''), -(18,'p','888','/payment/refund','POST','','',''), -(19,'p','888','/api/createApi','POST','','',''), -(20,'p','888','/api/deleteApi','POST','','',''), -(21,'p','888','/api/deleteApisByIds','DELETE','','',''), -(22,'p','888','/api/enterSyncApi','POST','','',''), -(23,'p','888','/api/getAllApis','POST','','',''), -(24,'p','888','/api/getApiById','POST','','',''), -(25,'p','888','/api/getApiGroups','GET','','',''), -(26,'p','888','/api/getApiList','POST','','',''), -(27,'p','888','/api/getApiRoles','GET','','',''), -(28,'p','888','/api/ignoreApi','POST','','',''), -(29,'p','888','/api/setApiRoles','POST','','',''), -(30,'p','888','/api/syncApi','GET','','',''), -(31,'p','888','/api/updateApi','POST','','',''), -(32,'p','888','/attachmentCategory/addCategory','POST','','',''), -(33,'p','888','/attachmentCategory/deleteCategory','POST','','',''), -(34,'p','888','/attachmentCategory/getCategoryList','GET','','',''), -(35,'p','888','/authority/copyAuthority','POST','','',''), -(36,'p','888','/authority/createAuthority','POST','','',''), -(37,'p','888','/authority/deleteAuthority','POST','','',''), -(38,'p','888','/authority/getAuthorityList','POST','','',''), -(39,'p','888','/authority/getDataScopeDepts','GET','','',''), -(40,'p','888','/authority/getUsersByAuthority','GET','','',''), -(41,'p','888','/authority/setDataScope','POST','','',''), -(42,'p','888','/authority/setRoleUsers','POST','','',''), -(43,'p','888','/authority/updateAuthority','PUT','','',''), -(44,'p','888','/authorityBtn/canRemoveAuthorityBtn','POST','','',''), -(45,'p','888','/authorityBtn/getAuthorityBtn','POST','','',''), -(46,'p','888','/authorityBtn/setAuthorityBtn','POST','','',''), -(47,'p','888','/casbin/getPolicyPathByAuthorityId','POST','','',''), -(48,'p','888','/casbin/updateCasbin','POST','','',''), -(49,'p','888','/dataAccessLog/deleteDataAccessLogByIds','DELETE','','',''), -(50,'p','888','/dataAccessLog/getDataAccessLogList','POST','','',''), -(51,'p','888','/department/createDepartment','POST','','',''), -(52,'p','888','/department/deleteDepartment','DELETE','','',''), -(53,'p','888','/department/findDepartment','GET','','',''), -(54,'p','888','/department/getDepartmentList','POST','','',''), -(55,'p','888','/department/getDepartmentUsers','GET','','',''), -(56,'p','888','/department/setDepartmentUsers','POST','','',''), -(57,'p','888','/department/updateDepartment','PUT','','',''), -(58,'p','888','/email/emailTest','POST','','',''), -(59,'p','888','/email/sendEmail','POST','','',''), -(60,'p','888','/fileUploadAndDownload/deleteFile','POST','','',''), -(61,'p','888','/fileUploadAndDownload/deleteFiles','POST','','',''), -(62,'p','888','/fileUploadAndDownload/editFileName','POST','','',''), -(63,'p','888','/fileUploadAndDownload/findFile','GET','','',''), -(64,'p','888','/fileUploadAndDownload/getFileList','POST','','',''), -(65,'p','888','/fileUploadAndDownload/importURL','POST','','',''), -(66,'p','888','/fileUploadAndDownload/listOssFiles','POST','','',''), -(67,'p','888','/fileUploadAndDownload/upload','POST','','',''), -(68,'p','888','/info/createInfo','POST','','',''), -(69,'p','888','/info/deleteInfo','DELETE','','',''), -(70,'p','888','/info/deleteInfoByIds','DELETE','','',''), -(71,'p','888','/info/findInfo','GET','','',''), -(72,'p','888','/info/getInfoDataSource','GET','','',''), -(73,'p','888','/info/getInfoList','GET','','',''), -(74,'p','888','/info/updateInfo','PUT','','',''), -(75,'p','888','/jwt/jsonInBlacklist','POST','','',''), -(76,'p','888','/logViewer/content','GET','','',''), -(77,'p','888','/logViewer/dates','GET','','',''), -(78,'p','888','/logViewer/files','GET','','',''), -(79,'p','888','/mediaUpload/:uploadId','DELETE','','',''), -(80,'p','888','/mediaUpload/chunk','POST','','',''), -(81,'p','888','/mediaUpload/complete','POST','','',''), -(82,'p','888','/mediaUpload/init','POST','','',''), -(83,'p','888','/menu/addBaseMenu','POST','','',''), -(84,'p','888','/menu/addMenuAuthority','POST','','',''), -(85,'p','888','/menu/deleteBaseMenu','POST','','',''), -(86,'p','888','/menu/getBaseMenuById','POST','','',''), -(87,'p','888','/menu/getBaseMenuTree','POST','','',''), -(88,'p','888','/menu/getMenu','POST','','',''), -(89,'p','888','/menu/getMenuAuthority','POST','','',''), -(90,'p','888','/menu/getMenuList','POST','','',''), -(91,'p','888','/menu/getMenuRoles','GET','','',''), -(92,'p','888','/menu/setMenuRoles','POST','','',''), -(93,'p','888','/menu/updateBaseMenu','POST','','',''), -(94,'p','888','/payment/callback/:provider','POST','','',''), -(95,'p','888','/position/createPosition','POST','','',''), -(96,'p','888','/position/deletePosition','DELETE','','',''), -(97,'p','888','/position/findPosition','GET','','',''), -(98,'p','888','/position/getPositionList','POST','','',''), -(99,'p','888','/position/getPositionUsers','GET','','',''), -(100,'p','888','/position/setPositionUsers','POST','','',''), -(101,'p','888','/position/updatePosition','PUT','','',''), -(102,'p','888','/securityConfig/getSecurityConfig','GET','','',''), -(103,'p','888','/securityConfig/setSecurityConfig','POST','','',''), -(104,'p','888','/sysApiToken/createApiToken','POST','','',''), -(105,'p','888','/sysApiToken/deleteApiToken','POST','','',''), -(106,'p','888','/sysApiToken/getApiTokenList','POST','','',''), -(107,'p','888','/sysDictionary/createSysDictionary','POST','','',''), -(108,'p','888','/sysDictionary/deleteSysDictionary','DELETE','','',''), -(109,'p','888','/sysDictionary/exportSysDictionary','GET','','',''), -(110,'p','888','/sysDictionary/findSysDictionary','GET','','',''), -(111,'p','888','/sysDictionary/getSysDictionaryList','GET','','',''), -(112,'p','888','/sysDictionary/getSysDictionaryListWithDetails','GET','','',''), -(113,'p','888','/sysDictionary/importSysDictionary','POST','','',''), -(114,'p','888','/sysDictionary/updateSysDictionary','PUT','','',''), -(115,'p','888','/sysDictionaryDetail/createSysDictionaryDetail','POST','','',''), -(116,'p','888','/sysDictionaryDetail/deleteSysDictionaryDetail','DELETE','','',''), -(117,'p','888','/sysDictionaryDetail/findSysDictionaryDetail','GET','','',''), -(118,'p','888','/sysDictionaryDetail/getDictionaryDetailsByParent','GET','','',''), -(119,'p','888','/sysDictionaryDetail/getDictionaryPath','GET','','',''), -(120,'p','888','/sysDictionaryDetail/getDictionaryTreeList','GET','','',''), -(121,'p','888','/sysDictionaryDetail/getDictionaryTreeListByType','GET','','',''), -(122,'p','888','/sysDictionaryDetail/getSysDictionaryDetailList','GET','','',''), -(123,'p','888','/sysDictionaryDetail/updateSysDictionaryDetail','PUT','','',''), -(124,'p','888','/sysError/createSysError','POST','','',''), -(125,'p','888','/sysError/deleteSysError','DELETE','','',''), -(126,'p','888','/sysError/deleteSysErrorByIds','DELETE','','',''), -(127,'p','888','/sysError/findSysError','GET','','',''), -(128,'p','888','/sysError/getSysErrorList','GET','','',''), -(129,'p','888','/sysError/updateSysError','PUT','','',''), -(130,'p','888','/sysExportTemplate/createSysExportTemplate','POST','','',''), -(131,'p','888','/sysExportTemplate/deleteSysExportTemplate','DELETE','','',''), -(132,'p','888','/sysExportTemplate/deleteSysExportTemplateByIds','DELETE','','',''), -(133,'p','888','/sysExportTemplate/exportExcel','GET','','',''), -(134,'p','888','/sysExportTemplate/exportExcelByToken','GET','','',''), -(135,'p','888','/sysExportTemplate/exportTemplate','GET','','',''), -(136,'p','888','/sysExportTemplate/exportTemplateByToken','GET','','',''), -(137,'p','888','/sysExportTemplate/findSysExportTemplate','GET','','',''), -(138,'p','888','/sysExportTemplate/getSysExportTemplateList','GET','','',''), -(139,'p','888','/sysExportTemplate/importExcel','POST','','',''), -(140,'p','888','/sysExportTemplate/previewSQL','GET','','',''), -(141,'p','888','/sysExportTemplate/updateSysExportTemplate','PUT','','',''), -(142,'p','888','/sysLoginLog/deleteLoginLog','DELETE','','',''), -(143,'p','888','/sysLoginLog/deleteLoginLogByIds','DELETE','','',''), -(144,'p','888','/sysLoginLog/findLoginLog','GET','','',''), -(145,'p','888','/sysLoginLog/getLoginLogList','GET','','',''), -(146,'p','888','/sysOperationRecord/deleteSysOperationRecord','DELETE','','',''), -(147,'p','888','/sysOperationRecord/deleteSysOperationRecordByIds','DELETE','','',''), -(148,'p','888','/sysOperationRecord/findSysOperationRecord','GET','','',''), -(149,'p','888','/sysOperationRecord/getSysOperationRecordList','GET','','',''), -(150,'p','888','/sysParams/createSysParams','POST','','',''), -(151,'p','888','/sysParams/deleteSysParams','DELETE','','',''), -(152,'p','888','/sysParams/deleteSysParamsByIds','DELETE','','',''), -(153,'p','888','/sysParams/findSysParams','GET','','',''), -(154,'p','888','/sysParams/getSysParam','GET','','',''), -(155,'p','888','/sysParams/getSysParamsList','GET','','',''), -(156,'p','888','/sysParams/updateSysParams','PUT','','',''), -(157,'p','888','/sysVersion/deleteSysVersion','DELETE','','',''), -(158,'p','888','/sysVersion/deleteSysVersionByIds','DELETE','','',''), -(159,'p','888','/sysVersion/downloadVersionJson','GET','','',''), -(160,'p','888','/sysVersion/exportVersion','POST','','',''), -(161,'p','888','/sysVersion/findSysVersion','GET','','',''), -(162,'p','888','/sysVersion/getSysVersionList','GET','','',''), -(163,'p','888','/sysVersion/importVersion','POST','','',''), -(164,'p','888','/system/getServerInfo','POST','','',''), -(165,'p','888','/system/getSystemConfig','POST','','',''), -(166,'p','888','/system/setSystemConfig','POST','','',''), -(167,'p','888','/timedTask/alertStream','GET','','',''), -(168,'p','888','/timedTask/createTimedTask','POST','','',''), -(169,'p','888','/timedTask/deleteTimedTask','DELETE','','',''), -(170,'p','888','/timedTask/getRegisteredMethods','GET','','',''), -(171,'p','888','/timedTask/getTimedTaskList','GET','','',''), -(172,'p','888','/timedTask/getTimedTaskLogList','GET','','',''), -(173,'p','888','/timedTask/toggleTimedTask','POST','','',''), -(174,'p','888','/timedTask/triggerTimedTask','POST','','',''), -(175,'p','888','/timedTask/updateTimedTask','PUT','','',''), -(176,'p','888','/user/admin_register','POST','','',''), -(177,'p','888','/user/changePassword','POST','','',''), -(178,'p','888','/user/deleteUser','DELETE','','',''), -(179,'p','888','/user/getUserInfo','GET','','',''), -(180,'p','888','/user/getUserList','POST','','',''), -(181,'p','888','/user/resetPassword','POST','','',''), -(182,'p','888','/user/setSelfInfo','PUT','','',''), -(183,'p','888','/user/setSelfSetting','PUT','','',''), -(184,'p','888','/user/setUserAuthorities','POST','','',''), -(185,'p','888','/user/setUserAuthority','POST','','',''), -(186,'p','888','/user/setUserDepartments','POST','','',''), -(187,'p','888','/user/setUserInfo','PUT','','',''), -(188,'p','888','/user/setUserPositions','POST','','',''); - -INSERT INTO `sys_apis` (`api_group`,`created_at`,`deleted_at`,`description`,`id`,`method`,`path`,`updated_at`) VALUES -('集成配置',NOW(3),NULL,'按类型获取集成配置',1,'GET','/integration/configs/:kind',NOW(3)), -('集成配置',NOW(3),NULL,'删除集成配置',2,'DELETE','/integration/configs/:kind/:provider',NOW(3)), -('集成配置',NOW(3),NULL,'获取指定集成配置',3,'GET','/integration/configs/:kind/:provider',NOW(3)), -('集成配置',NOW(3),NULL,'保存集成配置',4,'PUT','/integration/configs/:kind/:provider',NOW(3)), -('集成配置',NOW(3),NULL,'测试通信集成连接',5,'POST','/integration/configs/:kind/:provider/test',NOW(3)), -('短信服务',NOW(3),NULL,'发送单条模板短信',6,'POST','/integration/sms/:provider/send',NOW(3)), -('支付',NOW(3),NULL,'创建支付订单',7,'POST','/payment/create',NOW(3)), -('支付',NOW(3),NULL,'重试支付订单发货',8,'POST','/payment/fulfill',NOW(3)), -('支付',NOW(3),NULL,'查询支付订单',9,'POST','/payment/order',NOW(3)), -('支付',NOW(3),NULL,'分页查询支付订单',10,'GET','/payment/orders',NOW(3)), -('支付',NOW(3),NULL,'按路径查询支付订单',11,'GET','/payment/orders/:provider/:tradeNo',NOW(3)), -('支付',NOW(3),NULL,'查询支付订单事件流水',12,'GET','/payment/orders/:provider/:tradeNo/events',NOW(3)), -('支付',NOW(3),NULL,'按路径重试支付订单发货',13,'POST','/payment/orders/:provider/:tradeNo/fulfill',NOW(3)), -('支付',NOW(3),NULL,'按路径申请支付订单退款',14,'POST','/payment/orders/:provider/:tradeNo/refund',NOW(3)), -('支付',NOW(3),NULL,'汇总支付订单运营指标',15,'GET','/payment/orders/summary',NOW(3)), -('支付',NOW(3),NULL,'测试支付渠道配置与沙箱交易链路',16,'POST','/payment/providers/:provider/test',NOW(3)), -('支付',NOW(3),NULL,'同步支付订单状态',17,'POST','/payment/query',NOW(3)), -('支付',NOW(3),NULL,'申请支付订单退款',18,'POST','/payment/refund',NOW(3)), -('api',NOW(3),NULL,'创建api',19,'POST','/api/createApi',NOW(3)), -('api',NOW(3),NULL,'删除Api',20,'POST','/api/deleteApi',NOW(3)), -('api',NOW(3),NULL,'批量删除api',21,'DELETE','/api/deleteApisByIds',NOW(3)), -('api',NOW(3),NULL,'确认同步API',22,'POST','/api/enterSyncApi',NOW(3)), -('api',NOW(3),NULL,'刷新 Casbin 缓存',23,'GET','/api/freshCasbin',NOW(3)), -('api',NOW(3),NULL,'获取所有api',24,'POST','/api/getAllApis',NOW(3)), -('api',NOW(3),NULL,'获取api详细信息',25,'POST','/api/getApiById',NOW(3)), -('api',NOW(3),NULL,'获取路由组',26,'GET','/api/getApiGroups',NOW(3)), -('api',NOW(3),NULL,'获取api列表',27,'POST','/api/getApiList',NOW(3)), -('api',NOW(3),NULL,'获取指定API关联角色列表',28,'GET','/api/getApiRoles',NOW(3)), -('api',NOW(3),NULL,'忽略API',29,'POST','/api/ignoreApi',NOW(3)), -('api',NOW(3),NULL,'全量覆盖API关联角色列表',30,'POST','/api/setApiRoles',NOW(3)), -('api',NOW(3),NULL,'获取待同步API',31,'GET','/api/syncApi',NOW(3)), -('api',NOW(3),NULL,'更新Api',32,'POST','/api/updateApi',NOW(3)), -('媒体库分类',NOW(3),NULL,'添加/编辑分类',33,'POST','/attachmentCategory/addCategory',NOW(3)), -('媒体库分类',NOW(3),NULL,'删除分类',34,'POST','/attachmentCategory/deleteCategory',NOW(3)), -('媒体库分类',NOW(3),NULL,'分类列表',35,'GET','/attachmentCategory/getCategoryList',NOW(3)), -('角色',NOW(3),NULL,'拷贝角色',36,'POST','/authority/copyAuthority',NOW(3)), -('角色',NOW(3),NULL,'创建角色',37,'POST','/authority/createAuthority',NOW(3)), -('角色',NOW(3),NULL,'删除角色',38,'POST','/authority/deleteAuthority',NOW(3)), -('角色',NOW(3),NULL,'获取角色列表',39,'POST','/authority/getAuthorityList',NOW(3)), -('角色',NOW(3),NULL,'获取角色自定义部门集',40,'GET','/authority/getDataScopeDepts',NOW(3)), -('角色',NOW(3),NULL,'获取角色关联用户ID列表',41,'GET','/authority/getUsersByAuthority',NOW(3)), -('角色',NOW(3),NULL,'设置角色数据权限',42,'POST','/authority/setDataScope',NOW(3)), -('角色',NOW(3),NULL,'全量覆盖角色关联用户',43,'POST','/authority/setRoleUsers',NOW(3)), -('角色',NOW(3),NULL,'更新角色信息',44,'PUT','/authority/updateAuthority',NOW(3)), -('按钮权限',NOW(3),NULL,'删除按钮',45,'POST','/authorityBtn/canRemoveAuthorityBtn',NOW(3)), -('按钮权限',NOW(3),NULL,'获取已有按钮权限',46,'POST','/authorityBtn/getAuthorityBtn',NOW(3)), -('按钮权限',NOW(3),NULL,'设置按钮权限',47,'POST','/authorityBtn/setAuthorityBtn',NOW(3)), -('base',NOW(3),NULL,'获取验证码',48,'POST','/base/captcha',NOW(3)), -('base',NOW(3),NULL,'登录',49,'POST','/base/login',NOW(3)), -('casbin',NOW(3),NULL,'获取权限列表',50,'POST','/casbin/getPolicyPathByAuthorityId',NOW(3)), -('casbin',NOW(3),NULL,'更改角色api权限',51,'POST','/casbin/updateCasbin',NOW(3)), -('数据权限审计',NOW(3),NULL,'批量删除数据权限审计日志',52,'DELETE','/dataAccessLog/deleteDataAccessLogByIds',NOW(3)), -('数据权限审计',NOW(3),NULL,'获取数据权限审计日志',53,'POST','/dataAccessLog/getDataAccessLogList',NOW(3)), -('部门',NOW(3),NULL,'创建部门',54,'POST','/department/createDepartment',NOW(3)), -('部门',NOW(3),NULL,'删除部门',55,'DELETE','/department/deleteDepartment',NOW(3)), -('部门',NOW(3),NULL,'根据ID获取部门',56,'GET','/department/findDepartment',NOW(3)), -('部门',NOW(3),NULL,'获取部门树',57,'POST','/department/getDepartmentList',NOW(3)), -('部门',NOW(3),NULL,'获取部门成员ID列表',58,'GET','/department/getDepartmentUsers',NOW(3)), -('部门',NOW(3),NULL,'设置部门成员(反向分配)',59,'POST','/department/setDepartmentUsers',NOW(3)), -('部门',NOW(3),NULL,'更新部门',60,'PUT','/department/updateDepartment',NOW(3)), -('email',NOW(3),NULL,'发送测试邮件',61,'POST','/email/emailTest',NOW(3)), -('email',NOW(3),NULL,'发送邮件',62,'POST','/email/sendEmail',NOW(3)), -('文件上传与下载',NOW(3),NULL,'删除文件',63,'POST','/fileUploadAndDownload/deleteFile',NOW(3)), -('文件上传与下载',NOW(3),NULL,'批量删除文件',64,'POST','/fileUploadAndDownload/deleteFiles',NOW(3)), -('文件上传与下载',NOW(3),NULL,'文件名或者备注编辑',65,'POST','/fileUploadAndDownload/editFileName',NOW(3)), -('文件上传与下载',NOW(3),NULL,'获取文件详情',66,'GET','/fileUploadAndDownload/findFile',NOW(3)), -('文件上传与下载',NOW(3),NULL,'获取上传文件列表',67,'POST','/fileUploadAndDownload/getFileList',NOW(3)), -('文件上传与下载',NOW(3),NULL,'导入URL',68,'POST','/fileUploadAndDownload/importURL',NOW(3)), -('文件上传与下载',NOW(3),NULL,'获取对象存储文件列表',69,'POST','/fileUploadAndDownload/listOssFiles',NOW(3)), -('文件上传与下载',NOW(3),NULL,'文件上传(建议选择)',70,'POST','/fileUploadAndDownload/upload',NOW(3)), -('base',NOW(3),NULL,'健康检查',71,'GET','/health',NOW(3)), -('公告',NOW(3),NULL,'新建公告',72,'POST','/info/createInfo',NOW(3)), -('公告',NOW(3),NULL,'删除公告',73,'DELETE','/info/deleteInfo',NOW(3)), -('公告',NOW(3),NULL,'批量删除公告',74,'DELETE','/info/deleteInfoByIds',NOW(3)), -('公告',NOW(3),NULL,'根据ID获取公告',75,'GET','/info/findInfo',NOW(3)), -('公告',NOW(3),NULL,'获取公告数据源',76,'GET','/info/getInfoDataSource',NOW(3)), -('公告',NOW(3),NULL,'获取公告列表',77,'GET','/info/getInfoList',NOW(3)), -('公告',NOW(3),NULL,'获取公开公告',78,'GET','/info/getInfoPublic',NOW(3)), -('公告',NOW(3),NULL,'更新公告',79,'PUT','/info/updateInfo',NOW(3)), -('初始化',NOW(3),NULL,'检查数据库',80,'POST','/init/checkdb',NOW(3)), -('初始化',NOW(3),NULL,'初始化数据库',81,'POST','/init/initdb',NOW(3)), -('jwt',NOW(3),NULL,'jwt加入黑名单(退出,必选)',82,'POST','/jwt/jsonInBlacklist',NOW(3)), -('文件日志',NOW(3),NULL,'分块读取日志文件内容',83,'GET','/logViewer/content',NOW(3)), -('文件日志',NOW(3),NULL,'获取存在日志的日期',84,'GET','/logViewer/dates',NOW(3)), -('文件日志',NOW(3),NULL,'获取日期下的日志文件',85,'GET','/logViewer/files',NOW(3)), -('媒体上传',NOW(3),NULL,'取消大文件上传',86,'DELETE','/mediaUpload/:uploadId',NOW(3)), -('媒体上传',NOW(3),NULL,'上传分片',87,'POST','/mediaUpload/chunk',NOW(3)), -('媒体上传',NOW(3),NULL,'完成大文件上传',88,'POST','/mediaUpload/complete',NOW(3)), -('媒体上传',NOW(3),NULL,'初始化大文件上传',89,'POST','/mediaUpload/init',NOW(3)), -('菜单',NOW(3),NULL,'新增菜单',90,'POST','/menu/addBaseMenu',NOW(3)), -('菜单',NOW(3),NULL,'增加menu和角色关联关系',91,'POST','/menu/addMenuAuthority',NOW(3)), -('菜单',NOW(3),NULL,'删除菜单',92,'POST','/menu/deleteBaseMenu',NOW(3)), -('菜单',NOW(3),NULL,'根据id获取菜单',93,'POST','/menu/getBaseMenuById',NOW(3)), -('菜单',NOW(3),NULL,'获取用户动态路由',94,'POST','/menu/getBaseMenuTree',NOW(3)), -('菜单',NOW(3),NULL,'获取菜单树(必选)',95,'POST','/menu/getMenu',NOW(3)), -('菜单',NOW(3),NULL,'获取指定角色menu',96,'POST','/menu/getMenuAuthority',NOW(3)), -('菜单',NOW(3),NULL,'分页获取基础menu列表',97,'POST','/menu/getMenuList',NOW(3)), -('菜单',NOW(3),NULL,'获取菜单关联角色列表',98,'GET','/menu/getMenuRoles',NOW(3)), -('菜单',NOW(3),NULL,'全量覆盖菜单关联角色列表',99,'POST','/menu/setMenuRoles',NOW(3)), -('菜单',NOW(3),NULL,'更新菜单',100,'POST','/menu/updateBaseMenu',NOW(3)), -('支付',NOW(3),NULL,'处理支付回调',101,'POST','/payment/callback/:provider',NOW(3)), -('岗位',NOW(3),NULL,'创建岗位',102,'POST','/position/createPosition',NOW(3)), -('岗位',NOW(3),NULL,'删除岗位',103,'DELETE','/position/deletePosition',NOW(3)), -('岗位',NOW(3),NULL,'根据ID获取岗位',104,'GET','/position/findPosition',NOW(3)), -('岗位',NOW(3),NULL,'获取岗位列表',105,'POST','/position/getPositionList',NOW(3)), -('岗位',NOW(3),NULL,'获取岗位成员ID列表',106,'GET','/position/getPositionUsers',NOW(3)), -('岗位',NOW(3),NULL,'设置岗位成员(反向分配)',107,'POST','/position/setPositionUsers',NOW(3)), -('岗位',NOW(3),NULL,'更新岗位',108,'PUT','/position/updatePosition',NOW(3)), -('安全配置',NOW(3),NULL,'获取安全配置',109,'GET','/securityConfig/getSecurityConfig',NOW(3)), -('安全配置',NOW(3),NULL,'设置安全配置',110,'POST','/securityConfig/setSecurityConfig',NOW(3)), -('base',NOW(3),NULL,'Swagger 文档',111,'GET','/swagger/*any',NOW(3)), -('API Token',NOW(3),NULL,'签发API Token',112,'POST','/sysApiToken/createApiToken',NOW(3)), -('API Token',NOW(3),NULL,'作废API Token',113,'POST','/sysApiToken/deleteApiToken',NOW(3)), -('API Token',NOW(3),NULL,'获取API Token列表',114,'POST','/sysApiToken/getApiTokenList',NOW(3)), -('系统字典',NOW(3),NULL,'新增字典',115,'POST','/sysDictionary/createSysDictionary',NOW(3)), -('系统字典',NOW(3),NULL,'删除字典',116,'DELETE','/sysDictionary/deleteSysDictionary',NOW(3)), -('系统字典',NOW(3),NULL,'导出字典JSON',117,'GET','/sysDictionary/exportSysDictionary',NOW(3)), -('系统字典',NOW(3),NULL,'根据ID获取字典(建议选择)',118,'GET','/sysDictionary/findSysDictionary',NOW(3)), -('系统字典',NOW(3),NULL,'获取字典列表',119,'GET','/sysDictionary/getSysDictionaryList',NOW(3)), -('系统字典',NOW(3),NULL,'获取字典列表(含明细)',120,'GET','/sysDictionary/getSysDictionaryListWithDetails',NOW(3)), -('系统字典',NOW(3),NULL,'导入字典JSON',121,'POST','/sysDictionary/importSysDictionary',NOW(3)), -('系统字典',NOW(3),NULL,'更新字典',122,'PUT','/sysDictionary/updateSysDictionary',NOW(3)), -('系统字典详情',NOW(3),NULL,'新增字典内容',123,'POST','/sysDictionaryDetail/createSysDictionaryDetail',NOW(3)), -('系统字典详情',NOW(3),NULL,'删除字典内容',124,'DELETE','/sysDictionaryDetail/deleteSysDictionaryDetail',NOW(3)), -('系统字典详情',NOW(3),NULL,'根据ID获取字典内容',125,'GET','/sysDictionaryDetail/findSysDictionaryDetail',NOW(3)), -('系统字典详情',NOW(3),NULL,'根据父级ID获取字典详情',126,'GET','/sysDictionaryDetail/getDictionaryDetailsByParent',NOW(3)), -('系统字典详情',NOW(3),NULL,'获取字典详情的完整路径',127,'GET','/sysDictionaryDetail/getDictionaryPath',NOW(3)), -('系统字典详情',NOW(3),NULL,'获取字典数列表',128,'GET','/sysDictionaryDetail/getDictionaryTreeList',NOW(3)), -('系统字典详情',NOW(3),NULL,'根据分类获取字典数列表',129,'GET','/sysDictionaryDetail/getDictionaryTreeListByType',NOW(3)), -('系统字典详情',NOW(3),NULL,'获取字典内容列表',130,'GET','/sysDictionaryDetail/getSysDictionaryDetailList',NOW(3)), -('系统字典详情',NOW(3),NULL,'更新字典内容',131,'PUT','/sysDictionaryDetail/updateSysDictionaryDetail',NOW(3)), -('错误日志',NOW(3),NULL,'新建错误日志',132,'POST','/sysError/createSysError',NOW(3)), -('错误日志',NOW(3),NULL,'删除错误日志',133,'DELETE','/sysError/deleteSysError',NOW(3)), -('错误日志',NOW(3),NULL,'批量删除错误日志',134,'DELETE','/sysError/deleteSysErrorByIds',NOW(3)), -('错误日志',NOW(3),NULL,'根据ID获取错误日志',135,'GET','/sysError/findSysError',NOW(3)), -('错误日志',NOW(3),NULL,'获取错误日志列表',136,'GET','/sysError/getSysErrorList',NOW(3)), -('错误日志',NOW(3),NULL,'更新错误日志',137,'PUT','/sysError/updateSysError',NOW(3)), -('导出模板',NOW(3),NULL,'新增导出模板',138,'POST','/sysExportTemplate/createSysExportTemplate',NOW(3)), -('导出模板',NOW(3),NULL,'删除导出模板',139,'DELETE','/sysExportTemplate/deleteSysExportTemplate',NOW(3)), -('导出模板',NOW(3),NULL,'批量删除导出模板',140,'DELETE','/sysExportTemplate/deleteSysExportTemplateByIds',NOW(3)), -('导出模板',NOW(3),NULL,'导出Excel',141,'GET','/sysExportTemplate/exportExcel',NOW(3)), -('导出模板',NOW(3),NULL,'按令牌导出Excel',142,'GET','/sysExportTemplate/exportExcelByToken',NOW(3)), -('导出模板',NOW(3),NULL,'下载模板',143,'GET','/sysExportTemplate/exportTemplate',NOW(3)), -('导出模板',NOW(3),NULL,'按令牌下载模板',144,'GET','/sysExportTemplate/exportTemplateByToken',NOW(3)), -('导出模板',NOW(3),NULL,'根据ID获取导出模板',145,'GET','/sysExportTemplate/findSysExportTemplate',NOW(3)), -('导出模板',NOW(3),NULL,'获取导出模板列表',146,'GET','/sysExportTemplate/getSysExportTemplateList',NOW(3)), -('导出模板',NOW(3),NULL,'导入Excel',147,'POST','/sysExportTemplate/importExcel',NOW(3)), -('导出模板',NOW(3),NULL,'预览SQL',148,'GET','/sysExportTemplate/previewSQL',NOW(3)), -('导出模板',NOW(3),NULL,'更新导出模板',149,'PUT','/sysExportTemplate/updateSysExportTemplate',NOW(3)), -('登录日志',NOW(3),NULL,'删除登录日志',150,'DELETE','/sysLoginLog/deleteLoginLog',NOW(3)), -('登录日志',NOW(3),NULL,'批量删除登录日志',151,'DELETE','/sysLoginLog/deleteLoginLogByIds',NOW(3)), -('登录日志',NOW(3),NULL,'根据ID获取登录日志',152,'GET','/sysLoginLog/findLoginLog',NOW(3)), -('登录日志',NOW(3),NULL,'获取登录日志列表',153,'GET','/sysLoginLog/getLoginLogList',NOW(3)), -('操作记录',NOW(3),NULL,'删除操作记录',154,'DELETE','/sysOperationRecord/deleteSysOperationRecord',NOW(3)), -('操作记录',NOW(3),NULL,'批量删除操作历史',155,'DELETE','/sysOperationRecord/deleteSysOperationRecordByIds',NOW(3)), -('操作记录',NOW(3),NULL,'根据ID获取操作记录',156,'GET','/sysOperationRecord/findSysOperationRecord',NOW(3)), -('操作记录',NOW(3),NULL,'获取操作记录列表',157,'GET','/sysOperationRecord/getSysOperationRecordList',NOW(3)), -('参数管理',NOW(3),NULL,'新建参数',158,'POST','/sysParams/createSysParams',NOW(3)), -('参数管理',NOW(3),NULL,'删除参数',159,'DELETE','/sysParams/deleteSysParams',NOW(3)), -('参数管理',NOW(3),NULL,'批量删除参数',160,'DELETE','/sysParams/deleteSysParamsByIds',NOW(3)), -('参数管理',NOW(3),NULL,'根据ID获取参数',161,'GET','/sysParams/findSysParams',NOW(3)), -('参数管理',NOW(3),NULL,'按键获取参数',162,'GET','/sysParams/getSysParam',NOW(3)), -('参数管理',NOW(3),NULL,'获取参数列表',163,'GET','/sysParams/getSysParamsList',NOW(3)), -('参数管理',NOW(3),NULL,'更新参数',164,'PUT','/sysParams/updateSysParams',NOW(3)), -('版本控制',NOW(3),NULL,'删除版本',165,'DELETE','/sysVersion/deleteSysVersion',NOW(3)), -('版本控制',NOW(3),NULL,'批量删除版本',166,'DELETE','/sysVersion/deleteSysVersionByIds',NOW(3)), -('版本控制',NOW(3),NULL,'下载版本json',167,'GET','/sysVersion/downloadVersionJson',NOW(3)), -('版本控制',NOW(3),NULL,'创建版本',168,'POST','/sysVersion/exportVersion',NOW(3)), -('版本控制',NOW(3),NULL,'获取单一版本',169,'GET','/sysVersion/findSysVersion',NOW(3)), -('版本控制',NOW(3),NULL,'获取版本列表',170,'GET','/sysVersion/getSysVersionList',NOW(3)), -('版本控制',NOW(3),NULL,'同步版本',171,'POST','/sysVersion/importVersion',NOW(3)), -('系统服务',NOW(3),NULL,'获取服务器信息',172,'POST','/system/getServerInfo',NOW(3)), -('系统服务',NOW(3),NULL,'获取配置文件内容',173,'POST','/system/getSystemConfig',NOW(3)), -('系统服务',NOW(3),NULL,'重载系统配置',174,'POST','/system/reloadSystem',NOW(3)), -('系统服务',NOW(3),NULL,'设置配置文件内容',175,'POST','/system/setSystemConfig',NOW(3)), -('定时任务',NOW(3),NULL,'订阅定时任务失败告警(SSE)',176,'GET','/timedTask/alertStream',NOW(3)), -('定时任务',NOW(3),NULL,'创建定时任务',177,'POST','/timedTask/createTimedTask',NOW(3)), -('定时任务',NOW(3),NULL,'删除定时任务',178,'DELETE','/timedTask/deleteTimedTask',NOW(3)), -('定时任务',NOW(3),NULL,'获取已注册方法列表',179,'GET','/timedTask/getRegisteredMethods',NOW(3)), -('定时任务',NOW(3),NULL,'获取定时任务列表',180,'GET','/timedTask/getTimedTaskList',NOW(3)), -('定时任务',NOW(3),NULL,'获取定时任务执行日志',181,'GET','/timedTask/getTimedTaskLogList',NOW(3)), -('定时任务',NOW(3),NULL,'启用/停用定时任务',182,'POST','/timedTask/toggleTimedTask',NOW(3)), -('定时任务',NOW(3),NULL,'手动触发定时任务',183,'POST','/timedTask/triggerTimedTask',NOW(3)), -('定时任务',NOW(3),NULL,'更新定时任务',184,'PUT','/timedTask/updateTimedTask',NOW(3)), -('系统用户',NOW(3),NULL,'用户注册',185,'POST','/user/admin_register',NOW(3)), -('系统用户',NOW(3),NULL,'修改密码(建议选择)',186,'POST','/user/changePassword',NOW(3)), -('系统用户',NOW(3),NULL,'删除用户',187,'DELETE','/user/deleteUser',NOW(3)), -('系统用户',NOW(3),NULL,'获取自身信息(必选)',188,'GET','/user/getUserInfo',NOW(3)), -('系统用户',NOW(3),NULL,'获取用户列表',189,'POST','/user/getUserList',NOW(3)), -('系统用户',NOW(3),NULL,'重置用户密码',190,'POST','/user/resetPassword',NOW(3)), -('系统用户',NOW(3),NULL,'设置自身信息(必选)',191,'PUT','/user/setSelfInfo',NOW(3)), -('系统用户',NOW(3),NULL,'用户界面配置',192,'PUT','/user/setSelfSetting',NOW(3)), -('系统用户',NOW(3),NULL,'设置权限组',193,'POST','/user/setUserAuthorities',NOW(3)), -('系统用户',NOW(3),NULL,'修改用户角色(必选)',194,'POST','/user/setUserAuthority',NOW(3)), -('系统用户',NOW(3),NULL,'设置用户归属部门',195,'POST','/user/setUserDepartments',NOW(3)), -('系统用户',NOW(3),NULL,'设置用户信息',196,'PUT','/user/setUserInfo',NOW(3)), -('系统用户',NOW(3),NULL,'设置用户岗位',197,'POST','/user/setUserPositions',NOW(3)); - -INSERT INTO `sys_authorities` (`authority_id`,`authority_name`,`created_at`,`data_scope`,`default_router`,`deleted_at`,`parent_id`,`updated_at`) VALUES -(888,'超级管理员',NOW(3),1,'dashboard',NULL,0,NOW(3)); - -INSERT INTO `sys_authority_menus` (`sys_authority_authority_id`,`sys_base_menu_id`) VALUES -(888,1), -(888,9), -(888,13), -(888,16), -(888,20), -(888,28), -(888,2), -(888,10), -(888,14), -(888,17), -(888,21), -(888,29), -(888,3), -(888,11), -(888,15), -(888,18), -(888,22), -(888,4), -(888,12), -(888,19), -(888,23), -(888,30), -(888,5), -(888,24), -(888,31), -(888,6), -(888,25), -(888,34), -(888,26), -(888,35), -(888,27), -(888,32), -(888,33), -(888,7), -(888,8); - -INSERT INTO `sys_base_menus` (`active_name`,`close_tab`,`component`,`created_at`,`default_menu`,`deleted_at`,`hidden`,`icon`,`id`,`keep_alive`,`menu_level`,`name`,`parent_id`,`path`,`sort`,`title`,`transition_type`,`updated_at`) VALUES -('',0,'view/dashboard/index.vue',NOW(3),0,NULL,0,'odometer',1,0,0,'dashboard',0,'dashboard',1,'仪表盘','',NOW(3)), -('',0,'view/routerHolder.vue',NOW(3),0,NULL,0,'perm-kra',2,0,0,'permission',0,'permission',2,'权限管理','',NOW(3)), -('',0,'view/routerHolder.vue',NOW(3),0,NULL,0,'share',3,0,0,'org',0,'org',3,'组织管理','',NOW(3)), -('',0,'view/routerHolder.vue',NOW(3),0,NULL,0,'config-kra',4,0,0,'systemConfig',0,'systemConfig',4,'系统设置','',NOW(3)), -('',0,'view/routerHolder.vue',NOW(3),0,NULL,0,'monitor-kra',5,0,0,'monitor',0,'monitor',5,'运维监控','',NOW(3)), -('',0,'view/routerHolder.vue',NOW(3),0,NULL,0,'folder-opened',6,0,0,'media',0,'media',6,'媒体管理','',NOW(3)), -('',0,'view/routerHolder.vue',NOW(3),0,NULL,0,'cherry',7,0,0,'extensions',0,'extensions',10,'扩展功能','',NOW(3)), -('',0,'view/person/person.vue',NOW(3),0,NULL,1,'postcard',8,0,0,'person',0,'person',13,'个人信息','',NOW(3)), -('',0,'view/superAdmin/authority/authority.vue',NOW(3),0,NULL,0,'role-kra',9,0,1,'authority',2,'authority',1,'角色管理','',NOW(3)), -('',0,'view/superAdmin/menu/menu.vue',NOW(3),0,NULL,0,'tickets',10,1,1,'menu',2,'menu',2,'菜单管理','',NOW(3)), -('',0,'view/superAdmin/api/api.vue',NOW(3),0,NULL,0,'api-kra',11,1,1,'api',2,'api',3,'api管理','',NOW(3)), -('',0,'view/systemTools/apiToken/index.vue',NOW(3),0,NULL,0,'key',12,0,1,'apiToken',2,'apiToken',4,'API Token','',NOW(3)), -('',0,'view/superAdmin/user/user.vue',NOW(3),0,NULL,0,'user',13,0,1,'user',3,'user',1,'用户管理','',NOW(3)), -('',0,'view/superAdmin/department/department.vue',NOW(3),0,NULL,0,'office-building',14,0,1,'department',3,'department',2,'部门管理','',NOW(3)), -('',0,'view/superAdmin/position/position.vue',NOW(3),0,NULL,0,'postcard',15,0,1,'position',3,'position',3,'岗位管理','',NOW(3)), -('',0,'view/systemTools/system/system.vue',NOW(3),0,NULL,0,'config-file-kra',16,0,1,'system',4,'system',1,'配置文件','',NOW(3)), -('',0,'view/superAdmin/dictionary/sysDictionary.vue',NOW(3),0,NULL,0,'notebook',17,0,1,'dictionary',4,'dictionary',2,'字典管理','',NOW(3)), -('',0,'view/superAdmin/params/sysParams.vue',NOW(3),0,NULL,0,'set-up',18,0,1,'sysParams',4,'sysParams',3,'参数管理','',NOW(3)), -('',0,'view/system/security/index.vue',NOW(3),0,NULL,0,'security-kra',19,0,1,'security',4,'security',4,'安全配置','',NOW(3)), -('',0,'view/superAdmin/operation/sysOperationRecord.vue',NOW(3),0,NULL,0,'document',20,0,1,'operation',5,'operation',1,'操作历史','',NOW(3)), -('',0,'view/systemTools/loginLog/index.vue',NOW(3),0,NULL,0,'clock',21,0,1,'loginLog',5,'loginLog',2,'登录日志','',NOW(3)), -('',0,'view/systemTools/sysError/sysError.vue',NOW(3),0,NULL,0,'error-kra',22,0,1,'sysError',5,'sysError',3,'错误日志','',NOW(3)), -('',0,'view/systemTools/version/version.vue',NOW(3),0,NULL,0,'version-kra',23,0,1,'sysVersion',5,'sysVersion',4,'版本管理','',NOW(3)), -('',0,'view/system/state.vue',NOW(3),0,NULL,0,'server',24,0,1,'state',5,'state',5,'服务器状态','',NOW(3)), -('',0,'view/superAdmin/dataAccessLog/dataAccessLog.vue',NOW(3),0,NULL,0,'warning',25,0,1,'dataAccessLog',5,'dataAccessLog',6,'数据权限审计','',NOW(3)), -('',0,'view/systemTools/timedTask/index.vue',NOW(3),0,NULL,0,'timer',26,0,1,'timedTask',5,'timedTask',7,'定时任务','',NOW(3)), -('',0,'view/systemTools/logViewer/index.vue',NOW(3),0,NULL,0,'document',27,0,1,'logViewer',5,'logViewer',8,'文件日志','',NOW(3)), -('',0,'view/media/upload.vue',NOW(3),0,NULL,0,'upload',28,0,1,'upload',6,'upload',1,'媒体库(上传下载)','',NOW(3)), -('',0,'view/media/chunkUpload.vue',NOW(3),0,NULL,0,'folder-add',29,0,1,'chunkUpload',6,'chunkUpload',2,'大文件上传','',NOW(3)), -('',0,'modules/email/view/index.vue',NOW(3),0,NULL,0,'message',30,0,1,'email',7,'email',4,'邮件发送','',NOW(3)), -('',0,'modules/announcement/view/info.vue',NOW(3),0,NULL,0,'bell',31,0,1,'anInfo',7,'anInfo',5,'公告管理','',NOW(3)), -('',0,'view/systemTools/integration/config.vue',NOW(3),0,NULL,0,'connection',32,0,1,'integrationConfig',7,'integrationConfig',8,'通信集成','',NOW(3)), -('',0,'view/systemTools/sms/index.vue',NOW(3),0,NULL,0,'message',33,0,1,'sms',7,'sms',9,'短信服务','',NOW(3)), -('',0,'view/systemTools/payment/orders.vue',NOW(3),0,NULL,0,'wallet',34,0,1,'paymentOrders',7,'paymentOrders',6,'支付订单','',NOW(3)), -('',0,'view/systemTools/payment/config.vue',NOW(3),0,NULL,0,'credit-card',35,0,1,'paymentConfig',7,'paymentConfig',7,'支付配置','',NOW(3)); - -INSERT INTO `sys_export_templates` (`created_at`,`db_name`,`deleted_at`,`id`,`import_sql`,`limit`,`name`,`order`,`sql`,`table_name`,`template_id`,`template_info`,`updated_at`) VALUES -(NOW(3),'',NULL,1,'',NULL,'api','','','sys_apis','api','{ -"path":"路径", -"method":"方法(大写)", -"description":"方法介绍", -"api_group":"方法分组" -}',NOW(3)); - -INSERT INTO `sys_ignore_apis` (`created_at`,`deleted_at`,`id`,`method`,`path`,`updated_at`) VALUES -(NOW(3),NULL,1,'GET','/api/freshCasbin',NOW(3)), -(NOW(3),NULL,2,'GET','/health',NOW(3)), -(NOW(3),NULL,3,'GET','/swagger/*any',NOW(3)), -(NOW(3),NULL,4,'GET','/uploads/file/*filepath',NOW(3)), -(NOW(3),NULL,5,'HEAD','/uploads/file/*filepath',NOW(3)), -(NOW(3),NULL,6,'POST','/system/reloadSystem',NOW(3)), -(NOW(3),NULL,7,'POST','/base/login',NOW(3)), -(NOW(3),NULL,8,'POST','/base/captcha',NOW(3)), -(NOW(3),NULL,9,'POST','/init/initdb',NOW(3)), -(NOW(3),NULL,10,'POST','/init/checkdb',NOW(3)), -(NOW(3),NULL,11,'GET','/info/getInfoPublic',NOW(3)); - -INSERT INTO `sys_integration_configs` (`config`,`created_at`,`enabled`,`id`,`kind`,`provider`,`updated_at`) VALUES -('{"broker":"tcp://127.0.0.1:1883","clean_session":true,"client_id":"kra","connect_timeout":10,"keep_alive":30,"password":"","reconnect_interval":5,"username":""}',NOW(3),0,1,'mq','emqx',NOW(3)), -('{"allow_auto_topic_creation":false,"brokers":["127.0.0.1:9092"],"client_id":"kra","connect_timeout":10,"group_id":"kra","max_bytes":10485760,"max_wait":1,"min_bytes":1,"password":"","reconnect_interval":5,"start_offset":"earliest","tls":false,"tls_skip_verify":false,"username":""}',NOW(3),0,2,'mq','kafka',NOW(3)), -('{"auto_delete":false,"connect_timeout":10,"durable":true,"exchange":"kra","exchange_type":"topic","heartbeat":10,"host":"127.0.0.1","password":"guest","port":5672,"prefetch_count":10,"queue":"kra","reconnect_interval":5,"routing_key":"#","tls":false,"username":"guest","vhost":"/"}',NOW(3),0,3,'mq','rabbitmq',NOW(3)), -('{"allow_origins":[],"concurrent_message_handling":false,"max_message_size":0,"message_buffer_size":0,"path":"/ws","ping_period":"54s","pong_wait":"60s","write_wait":"10s"}',NOW(3),0,4,'websocket','melody',NOW(3)), -('{"app_id":"","environment":"production","gateway_url":"https://openapi.alipay.com/gateway.do","method":"alipay.trade.create","notify_url":"","private_key":"","public_key":"","return_url":"","sign_type":"RSA2","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false}',NOW(3),0,5,'payment','alipay',NOW(3)), -('{"api_base_url":"https://openapi.alipay.com","app_cert":"","app_id":"","environment":"production","gateway_url":"https://openapi.alipay.com/gateway.do","method":"alipay.trade.create","notify_url":"","private_key":"","public_cert":"","return_url":"","root_cert":"","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false}',NOW(3),0,6,'payment','alipay-v3',NOW(3)), -('{"app_id":"","currency":"CNY","cus_id":"","environment":"production","notify_url":"","org_id":"","pay_type":"W02","private_key":"","public_key":"","query_order_type":"reqsn","return_url":"","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false}',NOW(3),0,7,'payment','allinpay',NOW(3)), -('{"bundle_id":"","environment":"production","issuer_id":"","key_id":"","notify_url":"","price_divisor":10,"private_key":"","return_url":"","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false,"test_product_id":"","test_transaction_id":""}',NOW(3),0,8,'payment','apple-iap',NOW(3)), -('{"app_id":"","app_key":"","callback_provider_trade_no_field":"","callback_status_field":"","callback_success_values":"","callback_trade_no_field":"","create_url":"","merchant_id":"","notify_url":"","protocol_version":"v1","query_amount_field":"","query_amount_scale":1,"query_currency_field":"","query_provider_trade_no_field":"","query_status_field":"","query_success_values":"","query_trade_no_field":"","query_url":"","refund_failure_values":"","refund_status_field":"","refund_success_values":"","refund_url":"","return_url":"","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false}',NOW(3),0,9,'payment','chinaums',NOW(3)), -('{"api_key":"","app_id":"","environment":"production","merchant_id":"","notify_url":"","platform_cert":"","platform_serial_no":"","private_key":"","return_url":"","serial_no":"","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false,"trade_type":"jsapi"}',NOW(3),0,10,'payment','douyin',NOW(3)), -('{"app_id":"","app_key":"","callback_provider_trade_no_field":"","callback_status_field":"","callback_success_values":"","callback_trade_no_field":"","create_url":"","merchant_id":"","notify_url":"","protocol_version":"v1","query_amount_field":"","query_amount_scale":1,"query_currency_field":"","query_provider_trade_no_field":"","query_status_field":"","query_success_values":"","query_trade_no_field":"","query_url":"","refund_failure_values":"","refund_status_field":"","refund_success_values":"","refund_url":"","return_url":"","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false}',NOW(3),0,11,'payment','douyin-game-pay',NOW(3)), -('{"channel":"Wechat","credential_code":"","currency":"CNY","environment":"production","method":"jsapi","notify_url":"","partner_code":"","return_url":"","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false}',NOW(3),0,12,'payment','lakala',NOW(3)), -('{"auto_capture":true,"cancel_url":"","client_id":"","client_secret":"","environment":"sandbox","notify_url":"","return_url":"","test_amount":1,"test_currency":"USD","test_extra":"{}","test_mode":false,"webhook_id":""}',NOW(3),0,13,'payment','paypal',NOW(3)), -('{"api_key":"","cert_file":"","environment":"production","key_file":"","mch_id":"","notify_url":"","return_url":"","sign_type":"MD5","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false,"trade_type":"NATIVE"}',NOW(3),0,14,'payment','qq',NOW(3)), -('{"access_token":"","currency":"CNY","environment":"production","inst_no":"","key":"","merchant_no":"","notify_url":"","pay_type":"010","return_url":"","terminal_id":"","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false}',NOW(3),0,15,'payment','saobei',NOW(3)), -('{"app_id":"","app_key":"","callback_provider_trade_no_field":"","callback_status_field":"","callback_success_values":"","callback_trade_no_field":"","create_url":"","merchant_id":"","notify_url":"","protocol_version":"v1","query_amount_field":"","query_amount_scale":1,"query_currency_field":"","query_provider_trade_no_field":"","query_status_field":"","query_success_values":"","query_trade_no_field":"","query_url":"","refund_failure_values":"","refund_status_field":"","refund_success_values":"","refund_url":"","return_url":"","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false}',NOW(3),0,16,'payment','sft',NOW(3)), -('{"app_id":"","app_key":"","callback_provider_trade_no_field":"","callback_status_field":"","callback_success_values":"","callback_trade_no_field":"","create_url":"","merchant_id":"","notify_url":"","protocol_version":"v1","query_amount_field":"","query_amount_scale":1,"query_currency_field":"","query_provider_trade_no_field":"","query_status_field":"","query_success_values":"","query_trade_no_field":"","query_url":"","refund_failure_values":"","refund_status_field":"","refund_success_values":"","refund_url":"","return_url":"","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false}',NOW(3),0,17,'payment','supper-pay',NOW(3)), -('{"app_id":"","app_key":"","callback_provider_trade_no_field":"","callback_status_field":"","callback_success_values":"","callback_trade_no_field":"","create_url":"","merchant_id":"","notify_url":"","protocol_version":"v1","query_amount_field":"","query_amount_scale":1,"query_currency_field":"","query_provider_trade_no_field":"","query_status_field":"","query_success_values":"","query_trade_no_field":"","query_url":"","refund_failure_values":"","refund_status_field":"","refund_success_values":"","refund_url":"","return_url":"","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false}',NOW(3),0,18,'payment','wechat-game-pay',NOW(3)), -('{"app_id":"","client_cert":"","client_key":"","mch_key":"","merchant_id":"","notify_url":"","return_url":"","sign_type":"MD5","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false,"trade_type":"NATIVE"}',NOW(3),0,19,'payment','wechat-v2',NOW(3)), -('{"api_v3_key":"","app_id":"","merchant_id":"","notify_url":"","platform_cert":"","platform_serial_no":"","private_key":"","return_url":"","serial_no":"","test_amount":1,"test_currency":"CNY","test_extra":"{}","test_mode":false,"trade_type":"jsapi"}',NOW(3),0,20,'payment','wechat-v3',NOW(3)); - -INSERT INTO `sys_schema_migrations` (`id`) VALUES -('202608200002_system_schema'), -('202608210002_communication_surface'), -('202608210003_communication_test_surface'), -('202608200001_data_infrastructure'), -('202608210001_communication_integration_defaults'), -('202608200004_payment_defaults'), -('202608290004_kafka_integration_default'), -('202608290005_communication_integration_default_upgrade'), -('202609290001_sms_admin_surface'), -('202608220001_task_schema'), -('202608200003_payment_schema'), -('202608290001_payment_event_schema'), -('202608290002_payment_admin_surface'), -('202608290003_payment_order_read_permissions'); - -INSERT INTO `sys_security_config` (`captcha_open`,`captcha_timeout`,`created_at`,`deleted_at`,`force_new_user_change_password`,`id`,`img_height`,`img_width`,`key_long`,`limit_count`,`limit_enable`,`limit_window`,`lock_duration`,`lock_enable`,`lock_threshold`,`pwd_expire_days`,`pwd_expire_enable`,`pwd_min_length`,`pwd_require_digit`,`pwd_require_lower`,`pwd_require_special`,`pwd_require_upper`,`updated_at`) VALUES -(0,3600,NOW(3),NULL,0,1,80,240,6,30,0,60,30,0,5,90,0,8,0,0,0,0,NOW(3)); - -INSERT INTO `sys_timed_tasks` (`created_at`,`deleted_at`,`description`,`enabled`,`executor_type`,`http_allow_private`,`http_body`,`http_header`,`http_method`,`http_url`,`id`,`method_name`,`name`,`params`,`spec`,`updated_at`,`with_seconds`) VALUES -(NOW(3),NULL,'定时清理数据库过期日志(操作记录/JWT黑名单/定时任务执行日志)',0,'method',0,'',NULL,'','',1,'ClearDB','ClearDB',NULL,'@daily',NOW(3),0), -(NOW(3),NULL,'定时清理过期大文件上传会话',0,'method',0,'',NULL,'','',2,'CleanStaleUploads','CleanStaleUploads',NULL,'@hourly',NOW(3),0); - -INSERT INTO sw_kra_id_map(entity,old_id) SELECT 'user',CAST(`user_id` AS CHAR) FROM `sys_user` WHERE del_flag='0' ORDER BY `user_id`; - -INSERT INTO sw_kra_id_map(entity,old_id) SELECT 'role',CAST(`role_id` AS CHAR) FROM `sys_role` WHERE del_flag='0' ORDER BY `role_id`; - -INSERT INTO sw_kra_id_map(entity,old_id) SELECT 'dept',CAST(`dept_id` AS CHAR) FROM `sys_dept` WHERE del_flag='0' ORDER BY `dept_id`; - -INSERT INTO sw_kra_id_map(entity,old_id) SELECT 'post',CAST(`post_id` AS CHAR) FROM `sys_post` WHERE del_flag='0' ORDER BY `post_id`; - -INSERT INTO sw_kra_id_map(entity,old_id) SELECT 'file',CAST(`oss_id` AS CHAR) FROM `sys_oss` WHERE 1=1 ORDER BY `oss_id`; - -INSERT INTO sw_kra_id_map(entity,old_id) SELECT 'menu',CAST(`menu_id` AS CHAR) FROM `sys_menu` WHERE menu_id IN ('2084194096229949441','2084194830778408961','2084202636386541569','2084224284976246785','2084224583841378306','2084449385185308674','2084453258847350785','2084458436631752706','2084466605093318657','2084475309624684546','2084478005203202049','2084480429515108353','2084480593562726401','2086033702105710593','2086034409621880833','2086621845875916801','2086623544338350082','2086643768701812738','2086643813702500354','2086643981961199618','2086644092393029633','2087069357514440706','2087385085920727041','2087385679095975937','2087385949666332673','2087386325354336258','2087444380922167298','2087447465111326721','2087831493110956033','2095702540414996481','2095702652168032258') ORDER BY `menu_id`; - -INSERT INTO sw_kra_id_map(entity,old_id) SELECT 'dict',CAST(`dict_id` AS CHAR) FROM `sys_dict_type` WHERE 1=1 ORDER BY `dict_id`; - -INSERT INTO sw_kra_id_map(entity,old_id) SELECT 'dict_item',CAST(`dict_code` AS CHAR) FROM `sys_dict_data` WHERE 1=1 ORDER BY `dict_code`; - -INSERT INTO sw_kra_id_map(entity,old_id) SELECT 'notice',CAST(`notice_id` AS CHAR) FROM `sys_notice` WHERE 1=1 ORDER BY `notice_id`; - -INSERT INTO sw_kra_id_map(entity,old_id) SELECT 'task',CAST(`id` AS CHAR) FROM `sj_job` WHERE deleted=0 ORDER BY `id`; - -UPDATE sw_kra_id_map SET new_id=10000+id; - -UPDATE sw_kra_id_map m JOIN sys_role r ON m.entity='role' AND m.old_id=CAST(r.role_id AS CHAR) SET m.new_id=888 WHERE r.role_key='superadmin'; - -INSERT INTO sys_authorities(authority_id,created_at,updated_at,authority_name,parent_id,data_scope,default_router) SELECT m.new_id,r.create_time,r.update_time,r.role_name,888,CASE r.data_scope WHEN '1' THEN 1 WHEN '2' THEN 5 WHEN '3' THEN 3 WHEN '4' THEN 2 WHEN '5' THEN 4 END,'dashboard' FROM sys_role r JOIN sw_kra_id_map m ON m.entity='role' AND m.old_id=CAST(r.role_id AS CHAR) WHERE r.del_flag='0' AND r.role_key<>'superadmin'; - -INSERT INTO sys_departments(id,created_at,updated_at,name,parent_id,ancestors,sort,leader_id,status) SELECT m.new_id,d.create_time,d.update_time,d.dept_name,COALESCE(p.new_id,0),'0',d.order_num,COALESCE(u.new_id,0),d.status='0' FROM sys_dept d JOIN sw_kra_id_map m ON m.entity='dept' AND m.old_id=CAST(d.dept_id AS CHAR) LEFT JOIN sw_kra_id_map p ON p.entity='dept' AND p.old_id=CAST(d.parent_id AS CHAR) LEFT JOIN sw_kra_id_map u ON u.entity='user' AND u.old_id=CAST(d.leader AS CHAR) WHERE d.del_flag='0'; - -SET v_iter=0; WHILE v_iter<16 DO UPDATE sys_departments d JOIN sys_departments p ON p.id=d.parent_id SET d.ancestors=CONCAT(p.ancestors,',',p.id); SET v_iter=v_iter+1; END WHILE; - -INSERT INTO sys_positions(id,created_at,updated_at,name,code,sort,status,remark,dept_id) SELECT m.new_id,p.create_time,p.update_time,p.post_name,p.post_code,p.post_sort,p.status='0',p.remark,d.new_id FROM sys_post p JOIN sw_kra_id_map m ON m.entity='post' AND m.old_id=CAST(p.post_id AS CHAR) LEFT JOIN sw_kra_id_map d ON d.entity='dept' AND d.old_id=CAST(p.dept_id AS CHAR) WHERE p.del_flag='0'; - -INSERT INTO sys_users(id,created_at,updated_at,uuid,username,password,nick_name,header_img,authority_id,dept_id,phone,email,enable,origin_setting,password_updated_at,must_change_password,level,parent_id,id_path,real_name,qq_number,business_status,reject_reason) SELECT m.new_id,u.create_time,u.update_time,UUID(),u.user_name,u.password,u.nick_name,COALESCE(o.url,''),rm.new_id,COALESCE(dm.new_id,0),u.phone_number,u.email,u.status='0','{}',COALESCE(u.update_time,u.create_time,NOW(3)),0,u.level,COALESCE(pm.new_id,0),'0',COALESCE(u.real_name,''),COALESCE(u.qq_number,''),CAST(u.status AS UNSIGNED),COALESCE(u.reject_reason,'') FROM sys_user u JOIN sw_kra_id_map m ON m.entity='user' AND m.old_id=CAST(u.user_id AS CHAR) JOIN sys_user_role ur ON ur.user_id=u.user_id JOIN sw_kra_id_map rm ON rm.entity='role' AND rm.old_id=CAST(ur.role_id AS CHAR) LEFT JOIN sw_kra_id_map dm ON dm.entity='dept' AND dm.old_id=CAST(u.dept_id AS CHAR) LEFT JOIN sw_kra_id_map pm ON pm.entity='user' AND pm.old_id=CAST(u.parent_id AS CHAR) LEFT JOIN sys_oss o ON o.oss_id=u.avatar WHERE u.del_flag='0'; - -SET v_iter=0; WHILE v_iter<4 DO UPDATE sys_users u JOIN sys_users p ON p.id=u.parent_id SET u.id_path=CONCAT(p.id_path,',',p.id); SET v_iter=v_iter+1; END WHILE; - -INSERT INTO sys_user_authority(sys_user_id,sys_authority_authority_id) SELECT um.new_id,rm.new_id FROM sys_user_role x JOIN sw_kra_id_map um ON um.entity='user' AND um.old_id=CAST(x.user_id AS CHAR) JOIN sw_kra_id_map rm ON rm.entity='role' AND rm.old_id=CAST(x.role_id AS CHAR); - -INSERT INTO sys_user_departments(sys_user_id,sys_department_id) SELECT id,dept_id FROM sys_users WHERE dept_id<>0; - -INSERT INTO sys_user_positions(sys_user_id,sys_position_id) SELECT um.new_id,pm.new_id FROM sys_user_post x JOIN sw_kra_id_map um ON um.entity='user' AND um.old_id=CAST(x.user_id AS CHAR) JOIN sw_kra_id_map pm ON pm.entity='post' AND pm.old_id=CAST(x.post_id AS CHAR); - -INSERT INTO media_file_upload_and_downloads(id,created_at,updated_at,name,class_id,url,tag,`key`,size,mime,md5,user_id) SELECT m.new_id,o.create_time,o.update_time,o.original_name,0,o.url,o.file_suffix,o.file_name,COALESCE(CAST(JSON_UNQUOTE(JSON_EXTRACT(IF(JSON_VALID(o.ext1),o.ext1,JSON_OBJECT()),'$.fileSize')) AS UNSIGNED),0),COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(IF(JSON_VALID(o.ext1),o.ext1,JSON_OBJECT()),'$.contentType')),'null'),''),COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(IF(JSON_VALID(o.ext1),o.ext1,JSON_OBJECT()),'$.md5')),'null'),''),COALESCE(um.new_id,0) FROM sys_oss o JOIN sw_kra_id_map m ON m.entity='file' AND m.old_id=CAST(o.oss_id AS CHAR) LEFT JOIN sw_kra_id_map um ON um.entity='user' AND um.old_id=CAST(o.create_by AS CHAR); - -INSERT INTO sys_dictionaries(id,created_at,updated_at,name,type,status,`desc`,parent_id) SELECT m.new_id,d.create_time,d.update_time,d.dict_name,d.dict_type,1,d.remark,0 FROM sys_dict_type d JOIN sw_kra_id_map m ON m.entity='dict' AND m.old_id=CAST(d.dict_id AS CHAR); - -INSERT INTO sys_dictionary_details(id,created_at,updated_at,label,value,extend,status,sort,sys_dictionary_id,parent_id,level,path) SELECT m.new_id,d.create_time,d.update_time,d.dict_label,d.dict_value,JSON_OBJECT('cssClass',d.css_class,'listClass',d.list_class,'isDefault',d.is_default),1,d.dict_sort,tm.new_id,0,0,'0' FROM sys_dict_data d JOIN sw_kra_id_map m ON m.entity='dict_item' AND m.old_id=CAST(d.dict_code AS CHAR) JOIN sys_dict_type t ON t.dict_type=d.dict_type JOIN sw_kra_id_map tm ON tm.entity='dict' AND tm.old_id=CAST(t.dict_id AS CHAR); - -INSERT INTO sys_announcements(id,created_at,updated_at,title,content,user_id,attachments) SELECT m.new_id,n.create_time,n.update_time,n.notice_title,CONVERT(n.notice_content USING utf8mb4),um.new_id,JSON_ARRAY() FROM sys_notice n JOIN sw_kra_id_map m ON m.entity='notice' AND m.old_id=CAST(n.notice_id AS CHAR) LEFT JOIN sw_kra_id_map um ON um.entity='user' AND um.old_id=CAST(n.create_by AS CHAR) WHERE n.status='0'; - -INSERT INTO sys_params(created_at,updated_at,name,`key`,value,`desc`) SELECT NOW(3),NOW(3),config_name,CONCAT('sw.legacy.',config_key),config_value,'Legacy non-secret setting; application adapter must consume it explicitly' FROM sys_config WHERE config_key IN('sys.account.registerUser','sys.oss.previewListResource'); - --- 六、导入新增业务菜单及授权;原工作台页面和查询按钮不再导入。 - -INSERT INTO sw_kra_menu_permissions(source_menu_id,source_permission,button_key) VALUES -('2084194096229949441','',''), -('2084194830778408961','system:user:list','sw:business:list'), -('2084202636386541569','system:promote:list','sw:promote:list'), -('2084224284976246785','',''), -('2084224583841378306','system:channelData:list','sw:channelData:list'), -('2084449385185308674','system:spend:list','sw:spend:list'), -('2084453258847350785','system:register:list','sw:register:list'), -('2084458436631752706','system:gameData:list','sw:gameData:list'), -('2084466605093318657','system:serverAnalysis:list','sw:serverAnalysis:list'), -('2084475309624684546','system:rank:channel','sw:rank:channel'), -('2084478005203202049','',''), -('2084480429515108353','system:alertRecord:list','sw:alertRecord:list'), -('2084480593562726401','system:alertRule:list','sw:alertRule:list'), -('2086033702105710593','system:alertRecord:audit','sw:alertRecord:audit'), -('2086034409621880833','system:alertRecord:query','sw:alertRecord:query'), -('2086621845875916801','system:alertRecord:process','sw:alertRecord:process'), -('2086623544338350082','system:oss:upload','sw:oss:upload'), -('2086643768701812738','system:alertRule:query','sw:alertRule:query'), -('2086643813702500354','system:alertRule:add','sw:alertRule:add'), -('2086643981961199618','system:alertRule:edit','sw:alertRule:edit'), -('2086644092393029633','system:alertRule:remove','sw:alertRule:remove'), -('2087069357514440706','system:promote:add','sw:promote:add'), -('2087385085920727041','system:user:add','sw:business:add'), -('2087385679095975937','system:user:query','sw:business:query'), -('2087385949666332673','system:user:edit','sw:business:edit'), -('2087386325354336258','system:user:export','sw:business:export'), -('2087444380922167298','system:user:bind','sw:business:bind'), -('2087447465111326721','system:promote:list','sw:promote:list'), -('2087831493110956033','system:register:export','sw:register:export'), -('2095702540414996481','',''), -('2095702652168032258','system:promoteActivePool:list','sw:promoteActivePool:list'), -('2087072517465325569','system:workbench:query','sw:workbench:query'), -('2087365025688768514','system:workbench:query','sw:workbench:query'); - -INSERT INTO sys_base_menus(id,created_at,updated_at,menu_level,parent_id,path,name,hidden,component,sort,active_name,keep_alive,default_menu,title,icon,close_tab,transition_type) SELECT m.new_id,n.create_time,n.update_time,IF(n.parent_id=0,0,1),COALESCE(pm.new_id,0),IF(n.parent_id=0,CONCAT('sw-',n.path),n.path),CONCAT('sw_',n.path),n.visible='1',IF(n.menu_type='M','view/routerHolder.vue',CONCAT('view/sw/',n.path,'.vue')),n.order_num,'',n.is_cache='Y',0,n.menu_name,CASE n.path - WHEN 'BusMgmt' THEN 'Briefcase' - WHEN 'BusinessList' THEN 'UserFilled' - WHEN 'ChannelList' THEN 'Connection' - WHEN 'ChannelActivationList' THEN 'CircleCheck' - WHEN 'DataAnalysis' THEN 'DataAnalysis' - WHEN 'ChannelDataStatistics' THEN 'Histogram' - WHEN 'RechargeDetails' THEN 'Money' - WHEN 'RegistrationDetails' THEN 'User' - WHEN 'GameAnalytics' THEN 'TrendCharts' - WHEN 'ServerAnalysis' THEN 'Monitor' - WHEN 'RankingAnalysis' THEN 'Star' - WHEN 'AlertCenter' THEN 'Bell' - WHEN 'AlertList' THEN 'Warning' - WHEN 'AlertRules' THEN 'Setting' - ELSE 'Menu' END,0,'' FROM sys_menu n JOIN sw_kra_id_map m ON m.entity='menu' AND m.old_id=CAST(n.menu_id AS CHAR) LEFT JOIN sw_kra_id_map pm ON pm.entity='menu' AND pm.old_id=CAST(n.parent_id AS CHAR) WHERE n.menu_type IN('M','C'); - -UPDATE sys_base_menus SET sort=CASE name WHEN 'dashboard' THEN 1 WHEN 'sw_BusMgmt' THEN 2 WHEN 'sw_DataAnalysis' THEN 3 WHEN 'sw_AlertCenter' THEN 4 WHEN 'permission' THEN 5 WHEN 'org' THEN 6 WHEN 'systemConfig' THEN 7 WHEN 'monitor' THEN 8 WHEN 'media' THEN 9 WHEN 'extensions' THEN 13 WHEN 'person' THEN 16 ELSE sort END WHERE parent_id=0; - -INSERT INTO sys_base_menu_btns(id,created_at,updated_at,name,`desc`,sys_base_menu_id) SELECT m.new_id,n.create_time,n.update_time,p.button_key,n.menu_name,pm.new_id FROM sys_menu n JOIN sw_kra_id_map m ON m.entity='menu' AND m.old_id=CAST(n.menu_id AS CHAR) JOIN sw_kra_id_map pm ON pm.entity='menu' AND pm.old_id=CAST(n.parent_id AS CHAR) JOIN sw_kra_menu_permissions p ON p.source_menu_id=n.menu_id WHERE n.menu_type='F'; - -INSERT INTO sys_authority_menus(sys_authority_authority_id,sys_base_menu_id) SELECT rm.new_id,mm.new_id FROM sys_role_menu x JOIN sw_kra_id_map rm ON rm.entity='role' AND rm.old_id=CAST(x.role_id AS CHAR) JOIN sw_kra_id_map mm ON mm.entity='menu' AND mm.old_id=CAST(x.menu_id AS CHAR) JOIN sys_menu m ON m.menu_id=x.menu_id WHERE m.menu_type IN('M','C'); - -INSERT INTO sys_authority_btns(authority_id,sys_menu_id,sys_base_menu_btn_id) SELECT rm.new_id,pm.new_id,mm.new_id FROM sys_role_menu x JOIN sw_kra_id_map rm ON rm.entity='role' AND rm.old_id=CAST(x.role_id AS CHAR) JOIN sw_kra_id_map mm ON mm.entity='menu' AND mm.old_id=CAST(x.menu_id AS CHAR) JOIN sys_menu m ON m.menu_id=x.menu_id JOIN sw_kra_id_map pm ON pm.entity='menu' AND pm.old_id=CAST(m.parent_id AS CHAR) WHERE m.menu_type='F'; - -INSERT INTO sys_authority_menus(sys_authority_authority_id,sys_base_menu_id) SELECT 888,m.new_id FROM sw_kra_id_map m JOIN sys_menu n ON m.entity='menu' AND m.old_id=CAST(n.menu_id AS CHAR) WHERE n.menu_type IN('M','C'); - -INSERT INTO sys_authority_btns(authority_id,sys_menu_id,sys_base_menu_btn_id) SELECT 888,sys_base_menu_id,id FROM sys_base_menu_btns; - -INSERT INTO sys_authority_menus(sys_authority_authority_id,sys_base_menu_id) SELECT a.authority_id,m.id FROM sys_authorities a JOIN sys_base_menus m ON m.name='dashboard' WHERE a.authority_id<>888 AND a.default_router='dashboard'; - -INSERT INTO sw_kra_api_contract(method,source_path,target_path,source_permission,controller) VALUES -('GET','/system/user/preference','/sw/user/preference','__authenticated__','UserPreference'), -('PUT','/system/user/preference','/sw/user/preference','__authenticated__','UserPreference'), -('GET','/system/promote/list','/sw/promote/list','system:promote:list','Promote'), -('GET','/system/promote/portrait','/sw/promote/portrait','system:promote:list','Promote'), -('GET','/system/promote/game-distribution','/sw/promote/game-distribution','system:promote:list','Promote'), -('GET','/system/promote/bindOptions','/sw/promote/bindOptions','system:promote:add','Promote'), -('POST','/system/promote','/sw/promote','system:promote:add','Promote'), -('GET','/system/promoteActivePool/bindList','/sw/promoteActivePool/bindList','system:promoteActivePool:list','PromoteActivePool'), -('GET','/system/promoteActivePool/bindSpendDetail','/sw/promoteActivePool/bindSpendDetail','system:promoteActivePool:list','PromoteActivePool'), -('GET','/system/workbench/summary','/sw/workbench/summary','system:workbench:query','Workbench'), -('GET','/system/workbench/registerTop','/sw/workbench/registerTop','system:workbench:query','Workbench'), -('GET','/system/workbench/payRank','/sw/workbench/payRank','system:workbench:query','Workbench'), -('GET','/system/workbench/unloginTop','/sw/workbench/unloginTop','system:workbench:query','Workbench'), -('GET','/system/rank/channel','/sw/rank/channel','system:rank:channel','Rank'), -('GET','/system/rank/business','/sw/rank/business','system:rank:channel','Rank'), -('GET','/system/rank/game','/sw/rank/game','system:rank:channel','Rank'), -('GET','/system/gameData/list','/sw/gameData/list','system:gameData:list','GameData'), -('GET','/system/channelData/list','/sw/channelData/list','system:channelData:list','ChannelData'), -('GET','/system/register/list','/sw/register/list','system:register:list','Register'), -('POST','/system/register/export','/sw/register/export','system:register:export','Register'), -('GET','/system/spend/list','/sw/spend/list','system:spend:list','Spend'), -('POST','/system/spend/export','/sw/spend/export','system:spend:export','Spend'), -('GET','/system/serverAnalysis/games','/sw/serverAnalysis/games','system:serverAnalysis:list','ServerAnalysis'), -('GET','/system/serverAnalysis/servers','/sw/serverAnalysis/servers','system:serverAnalysis:list','ServerAnalysis'), -('GET','/system/serverAnalysis/list','/sw/serverAnalysis/list','system:serverAnalysis:list','ServerAnalysis'), -('GET','/system/alertRule/list','/sw/alertRule/list','system:alertRule:list','SysAlertRule'), -('GET','/system/alertRule/ruleTypes','/sw/alertRule/ruleTypes','system:alertRule:list','SysAlertRule'), -('GET','/system/alertRule/{id}','/sw/alertRule/:id','system:alertRule:query','SysAlertRule'), -('POST','/system/alertRule/add','/sw/alertRule/add','system:alertRule:add','SysAlertRule'), -('PUT','/system/alertRule/edit','/sw/alertRule/edit','system:alertRule:edit','SysAlertRule'), -('DELETE','/system/alertRule/{id}','/sw/alertRule/:id','system:alertRule:remove','SysAlertRule'), -('PUT','/system/alertRule/toggle/{id}','/sw/alertRule/toggle/:id','system:alertRule:edit','SysAlertRule'), -('GET','/system/alertRecord/list','/sw/alertRecord/list','system:alertRecord:list','SysAlertRecord'), -('GET','/system/alertRecord/detail/{id}','/sw/alertRecord/detail/:id','system:alertRecord:query','SysAlertRecord'), -('POST','/system/alertRecord/startProcess','/sw/alertRecord/startProcess','system:alertRecord:process','SysAlertRecord'), -('POST','/system/alertRecord/submitAudit','/sw/alertRecord/submitAudit','system:alertRecord:process','SysAlertRecord'), -('POST','/system/alertRecord/approve','/sw/alertRecord/approve','system:alertRecord:audit','SysAlertRecord'), -('POST','/system/alertRecord/reject','/sw/alertRecord/reject','system:alertRecord:audit','SysAlertRecord'), -('POST','/system/alertRecord/reProcess','/sw/alertRecord/reProcess','system:alertRecord:process','SysAlertRecord'), -('POST','/system/alertRecord/addNote','/sw/alertRecord/addNote','system:alertRecord:process','SysAlertRecord'), -('GET','/system/user/list','/sw/business/list','system:user:list','SysUser'), -('GET','/system/user/{userId}/promotes','/sw/business/:userId/promotes','system:user:query','SysUser'), -('GET','/system/user/{userId}/portrait','/sw/business/:userId/portrait','system:user:query','SysUser'), -('GET','/system/user/{userId}/bindPlatform','/sw/business/:userId/bindPlatform','system:user:query','SysUser'), -('POST','/system/user/bindPlatform','/sw/business/bindPlatform','system:user:bind','SysUser'), -('GET','/system/user/bindPlatform','/sw/business/bindPlatform','system:user:query','SysUser'), -('GET','/system/user/bindPlatform/portrait','/sw/business/bindPlatform/portrait','system:user:query','SysUser'), -('DELETE','/system/user/bindPlatform','/sw/business/bindPlatform','system:user:bind','SysUser'), -('POST','/system/user/export','/sw/business/export','system:user:export','SysUser'), -('POST','/system/user/importData','/sw/business/importData','system:user:import','SysUser'), -('GET','/system/user/','/sw/business','system:user:query','SysUser'), -('GET','/system/user/{userId}','/sw/business/:userId','system:user:query','SysUser'), -('POST','/system/user','/sw/business','system:user:add','SysUser'), -('PUT','/system/user','/sw/business','system:user:edit','SysUser'), -('DELETE','/system/user/{userIds}','/sw/business/:userIds','system:user:remove','SysUser'), -('GET','/system/user/optionselect','/sw/business/optionselect','system:user:query','SysUser'), -('PUT','/system/user/resetPwd','/sw/business/resetPwd','system:user:resetPwd','SysUser'), -('PUT','/system/user/changeStatus','/sw/business/changeStatus','system:user:edit','SysUser'), -('GET','/system/user/unlock/{userId}','/sw/business/unlock/:userId','system:user:edit','SysUser'), -('GET','/system/user/authRole/{userId}','/sw/business/authRole/:userId','system:user:query','SysUser'), -('PUT','/system/user/authRole','/sw/business/authRole','system:user:edit','SysUser'), -('GET','/system/user/deptTree','/sw/business/deptTree','system:user:list','SysUser'), -('GET','/system/user/list/dept/{deptId}','/sw/business/list/dept/:deptId','system:user:list','SysUser'); - -INSERT INTO sys_apis(created_at,updated_at,path,description,api_group,method) SELECT NOW(3),NOW(3),target_path,CONCAT('SW ',controller,' - Go handler pending'),'SW business',method FROM sw_kra_api_contract; - -INSERT INTO casbin_rule(ptype,v0,v1,v2,v3,v4,v5) SELECT DISTINCT 'p',CAST(rm.new_id AS CHAR),c.target_path,c.method,'','','' FROM sw_kra_api_contract c JOIN sw_kra_menu_permissions p ON p.source_permission=c.source_permission JOIN sys_role_menu x ON x.menu_id=p.source_menu_id JOIN sw_kra_id_map rm ON rm.entity='role' AND rm.old_id=CAST(x.role_id AS CHAR); - -INSERT INTO casbin_rule(ptype,v0,v1,v2,v3,v4,v5) SELECT 'p','888',target_path,method,'','','' FROM sw_kra_api_contract; - -INSERT INTO casbin_rule(ptype,v0,v1,v2,v3,v4,v5) SELECT 'p',CAST(a.authority_id AS CHAR),p.path,p.method,'','','' FROM sys_authorities a JOIN sys_apis p ON p.path IN('/menu/getMenu','/user/getUserInfo','/user/setSelfInfo','/user/setSelfSetting','/user/setUserAuthority','/user/changePassword') WHERE a.authority_id<>888; - -INSERT INTO casbin_rule(ptype,v0,v1,v2,v3,v4,v5) SELECT 'p',CAST(a.authority_id AS CHAR),c.target_path,c.method,'','','' FROM sys_authorities a JOIN sw_kra_api_contract c ON c.source_permission='__authenticated__' WHERE a.authority_id<>888; - --- 七、转换旧任务定义,保留超时和重试参数;当前 Go 执行器读取 _execution,任务仍保持停用。 - -INSERT INTO sys_timed_tasks(id,created_at,updated_at,name,description,spec,with_seconds,executor_type,method_name,params,http_allow_private,enabled) SELECT m.new_id,j.create_dt,j.update_dt,CONCAT('SW/',j.job_name),j.description,CASE j.trigger_type WHEN 3 THEN CONCAT('CRON_TZ=Asia/Shanghai ',TRIM(j.trigger_interval)) WHEN 2 THEN CONCAT('@every ',TRIM(j.trigger_interval),'s') END,j.trigger_type=3,'method',j.executor_info,JSON_SET(IF(j.args_str IS NULL OR j.args_str='',JSON_OBJECT(),CAST(j.args_str AS JSON)),'$._execution',JSON_OBJECT('timeoutSeconds',j.executor_timeout,'maxRetryTimes',j.max_retry_times,'retryIntervalSeconds',j.retry_interval)),0,0 FROM sj_job j JOIN sw_kra_id_map m ON m.entity='task' AND m.old_id=CAST(j.id AS CHAR) WHERE j.deleted=0; - --- 八、回填业务表中的用户及部门引用,保留业务主键和平台实体 ID。 - -UPDATE `sys_user_bind_platform` x JOIN sw_kra_id_map m ON m.entity='user' AND m.old_id=CAST(x.`user_id` AS CHAR) SET x.`user_id`=m.new_id; - -UPDATE `sys_user_preference` x JOIN sw_kra_id_map m ON m.entity='user' AND m.old_id=CAST(x.`user_id` AS CHAR) SET x.`user_id`=m.new_id; - --- 显式保留更新时间,防止旧表 ON UPDATE CURRENT_TIMESTAMP 把 ID 转换当作业务编辑。 -UPDATE `sys_alert_rule` x JOIN sw_kra_id_map m ON m.entity='user' AND m.old_id=CAST(x.`creator_id` AS CHAR) SET x.`creator_id`=m.new_id,x.`updated_at`=x.`updated_at`; - -UPDATE `sys_alert_record` x JOIN sw_kra_id_map m ON m.entity='user' AND m.old_id=CAST(x.`business_id` AS CHAR) SET x.`business_id`=m.new_id,x.`updated_at`=x.`updated_at`; - -UPDATE `sys_alert_operation_log` x JOIN sw_kra_id_map m ON m.entity='user' AND m.old_id=CAST(x.`operator_id` AS CHAR) SET x.`operator_id`=m.new_id; - -UPDATE `sys_message` x JOIN sw_kra_id_map m ON m.entity='user' AND m.old_id=CAST(x.`create_by` AS CHAR) SET x.`create_by`=m.new_id; - -UPDATE `sys_message` x JOIN sw_kra_id_map m ON m.entity='user' AND m.old_id=CAST(x.`update_by` AS CHAR) SET x.`update_by`=m.new_id; - -UPDATE sys_message x JOIN sw_kra_id_map m ON m.entity='dept' AND m.old_id=CAST(x.create_dept AS CHAR) SET x.create_dept=m.new_id; - -BEGIN DECLARE done INT DEFAULT 0; DECLARE old_user VARCHAR(64); DECLARE new_user BIGINT UNSIGNED; DECLARE users_cursor CURSOR FOR SELECT old_id,new_id FROM sw_kra_id_map WHERE entity='user' ORDER BY id; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1; OPEN users_cursor; user_loop: LOOP FETCH users_cursor INTO old_user,new_user; IF done=1 THEN LEAVE user_loop; END IF; UPDATE sys_message SET send_user_ids=TRIM(BOTH ',' FROM REPLACE(CONCAT(',',BINARY send_user_ids,','),CONCAT(',',BINARY old_user,','),CONCAT(',',BINARY new_user,','))) WHERE FIND_IN_SET(BINARY old_user,BINARY send_user_ids)>0; END LOOP; CLOSE users_cursor; END; - --- 九、核验账号密码、关联、业务引用、菜单和任务;不通过则回滚当前数据事务。 - -SELECT COUNT(*) INTO v_actual FROM sys_alert_rule n JOIN bak_sw2kra_20261103_sys_alert_rule o ON o.id=n.id WHERE NOT(n.created_at <=> o.created_at) OR NOT(n.updated_at <=> o.updated_at); -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','alert rule timestamps unchanged',0,v_actual,v_actual=0); -IF v_actual<>0 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='alert rule timestamps changed'; END IF; - -SELECT COUNT(*) INTO v_actual FROM sys_alert_record n JOIN bak_sw2kra_20261103_sys_alert_record o ON o.id=n.id WHERE NOT(n.created_at <=> o.created_at) OR NOT(n.updated_at <=> o.updated_at); -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','alert record timestamps unchanged',0,v_actual,v_actual=0); -IF v_actual<>0 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='alert record timestamps changed'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_users) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM sys_user WHERE del_flag='0') INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','user count',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='user count'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_users n JOIN sw_kra_id_map m ON m.entity='user' AND m.new_id=n.id JOIN sys_user o ON CAST(o.user_id AS CHAR)=m.old_id WHERE BINARY n.password=BINARY o.password) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM sys_user WHERE del_flag='0') INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','password bytes unchanged',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='password bytes unchanged'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_users n LEFT JOIN sys_authorities a ON a.authority_id=n.authority_id WHERE a.authority_id IS NULL) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','current role references',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='current role references'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_user_authority) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM sys_user_role) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','user role links',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='user role links'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_users n JOIN sw_kra_id_map m ON m.entity='user' AND m.new_id=n.id JOIN sys_user o ON CAST(o.user_id AS CHAR)=m.old_id LEFT JOIN sw_kra_id_map p ON p.entity='user' AND p.old_id=CAST(o.parent_id AS CHAR) WHERE n.parent_id<>COALESCE(p.new_id,0) OR n.level<>o.level) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','business parent and level',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='business parent and level'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_users u JOIN sys_users p ON p.id=u.parent_id WHERE u.id_path<>CONCAT(p.id_path,',',p.id)) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','business ancestor paths',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='business ancestor paths'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_user_bind_platform b LEFT JOIN sys_users u ON u.id=b.user_id WHERE u.id IS NULL) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','platform binding users',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='platform binding users'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_user_bind_platform) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_user_bind_platform`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','platform binding rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='platform binding rows'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_user_preference p LEFT JOIN sys_users u ON u.id=p.user_id WHERE u.id IS NULL) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','preference users',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='preference users'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_user_preference) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_user_preference`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','preference rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='preference rows'; END IF; - -SELECT (SELECT COUNT(*) FROM media_file_upload_and_downloads) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM sys_oss) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','file rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='file rows'; END IF; - -SELECT (SELECT COUNT(*) FROM media_file_upload_and_downloads n JOIN sw_kra_id_map m ON m.entity='file' AND m.new_id=n.id JOIN sys_oss o ON CAST(o.oss_id AS CHAR)=m.old_id WHERE n.size<>COALESCE(CAST(JSON_UNQUOTE(JSON_EXTRACT(IF(JSON_VALID(o.ext1),o.ext1,JSON_OBJECT()),'$.fileSize')) AS UNSIGNED),0) OR BINARY n.mime<>BINARY COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(IF(JSON_VALID(o.ext1),o.ext1,JSON_OBJECT()),'$.contentType')),'null'),'') OR BINARY n.md5<>BINARY COALESCE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(IF(JSON_VALID(o.ext1),o.ext1,JSON_OBJECT()),'$.md5')),'null'),'')) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','file size MIME and MD5',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='file size MIME and MD5'; END IF; - -SELECT (SELECT COUNT(*) FROM sw_kra_id_map WHERE entity='menu') INTO v_actual; - -SELECT (31) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','business source menu nodes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='business source menu nodes'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_base_menus n JOIN sw_kra_id_map m ON m.entity='menu' AND m.new_id=n.id) INTO v_actual; - -SELECT (14) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','business navigation nodes',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='business navigation nodes'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_base_menu_btns) INTO v_actual; - -SELECT (17) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','business buttons',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='business buttons'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_base_menus WHERE name='sw_workbench' OR path='sw-index') INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','workbench reuses dashboard',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='workbench reuses dashboard'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_authorities a WHERE NOT EXISTS(SELECT 1 FROM sys_base_menus m JOIN sys_authority_menus x ON x.sys_base_menu_id=m.id WHERE x.sys_authority_authority_id=a.authority_id AND m.name=a.default_router)) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','default routers accessible',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='default routers accessible'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_base_menus n LEFT JOIN sys_base_menus p ON p.id=n.parent_id WHERE n.parent_id<>0 AND p.id IS NULL) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','menu parent references',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='menu parent references'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_timed_tasks t JOIN sw_kra_id_map m ON m.entity='task' AND m.new_id=t.id) INTO v_actual; - -SELECT (7) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','SW task definitions',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='SW task definitions'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_timed_tasks WHERE enabled=1) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','all tasks disabled for rehearsal',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='all tasks disabled for rehearsal'; END IF; - -SELECT (SELECT COUNT(*) FROM sys_message) INTO v_actual; - -SELECT (SELECT COUNT(*) FROM `bak_sw2kra_20261103_sys_message`) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','message rows',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='message rows'; END IF; - -SELECT (SELECT COUNT(*) FROM (SELECT code FROM sys_positions GROUP BY code HAVING COUNT(*)>1) duplicate_codes) INTO v_actual; - -SELECT (0) INTO v_expected; - -INSERT INTO sw_kra_checks(stage,check_name,expected_value,actual_value,passed) VALUES ('migration','position codes unique',v_expected,v_actual,v_expected=v_actual); - -IF v_expected <> v_actual THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='position codes unique'; END IF; - -UPDATE sw_kra_state SET phase='data_validated' WHERE id=1; - -COMMIT; - --- 十、数据核验通过后归档旧框架表,登记完成状态并释放迁移锁。 - -RENAME TABLE -`sys_social` TO `legacy_sw_20261103_sys_social`, -`sys_dept` TO `legacy_sw_20261103_sys_dept`, -`sys_user` TO `legacy_sw_20261103_sys_user`, -`sys_post` TO `legacy_sw_20261103_sys_post`, -`sys_role` TO `legacy_sw_20261103_sys_role`, -`sys_menu` TO `legacy_sw_20261103_sys_menu`, -`sys_user_role` TO `legacy_sw_20261103_sys_user_role`, -`sys_role_menu` TO `legacy_sw_20261103_sys_role_menu`, -`sys_role_dept` TO `legacy_sw_20261103_sys_role_dept`, -`sys_user_post` TO `legacy_sw_20261103_sys_user_post`, -`sys_oper_log` TO `legacy_sw_20261103_sys_oper_log`, -`sys_dict_type` TO `legacy_sw_20261103_sys_dict_type`, -`sys_dict_data` TO `legacy_sw_20261103_sys_dict_data`, -`sys_config` TO `legacy_sw_20261103_sys_config`, -`sys_login_info` TO `legacy_sw_20261103_sys_login_info`, -`sys_notice` TO `legacy_sw_20261103_sys_notice`, -`sys_oss` TO `legacy_sw_20261103_sys_oss`, -`sys_oss_config` TO `legacy_sw_20261103_sys_oss_config`, -`sys_client` TO `legacy_sw_20261103_sys_client`; - -UPDATE sw_kra_state SET phase='completed',completed_at=NOW(3) WHERE id=1; - -DO RELEASE_LOCK(v_lock_name); SET v_lock=0; -SELECT '完整框架迁移完成' AS result; -SELECT stage,COUNT(*) AS checks,SUM(passed) AS passed FROM sw_kra_checks GROUP BY stage; -END migration_run$$ --- 只调用这一个入口,由库的实际状态决定执行完整迁移还是菜单调整。 -CALL sw_kra_migrate_20261103()$$ -DROP PROCEDURE sw_kra_migrate_20261103$$ -DELIMITER ; --- 输出最终根菜单顺序,便于核对页面效果。 -SELECT id,name,title,sort FROM sys_base_menus WHERE parent_id=0 ORDER BY sort,id; diff --git a/docs/sw6-to-kra/system-api-audit.md b/docs/sw6-to-kra/system-api-audit.md deleted file mode 100644 index 1363911..0000000 --- a/docs/sw6-to-kra/system-api-audit.md +++ /dev/null @@ -1,50 +0,0 @@ -# 系统接口承接核对 - -核对基线:旧后端 `d31082f4a7816d4c83544b8f54e6f42a3b2132b1` 至 `main`。原 SQL 的接口表按控制器收集接口,因此包含基线前已有的 RuoYi 用户管理接口;不能把所有记录都当成新商务新增功能,也不能只凭新路由存在就宣布功能完成。 - -## 商务新增与改动 - -`SysUserController` 的 Git 差异主要是商务列表语义、添加子商务,以及直属渠道、平台绑定和两种商务画像。用户列表查询新增商务树、姓名/等级过滤、直属渠道与正常绑定数量;添加子商务新增层级、归属与偏好初始化。当前列表、子商务、偏好、平台绑定及两种商务画像均已迁移;2026-11-04 已完成 sw8/sw9 同源接口核对。 - -原用户控制器中的以下方法在基线前已经存在,旧 `BusMgmt/BusinessList.vue` 没有为它们增加实际操作入口。新商务页面不据此增加编辑、删除、导入、导出、角色分配等按钮。 - -| 旧目标别名 | 当前 Kra 能力 / 核对结果 | -| --- | --- | -| `GET /sw/business`(新增表单初始化) | 原生用户表单通过用户、角色、部门接口加载;商务新增表单由后端决定商务层级,不开放角色选择 | -| `DELETE /sw/business/:userIds` | 原生 `DELETE /user/deleteUser`;旧商务列表没有删除入口 | -| `GET /sw/business/optionselect` | 原生用户列表/部门用户查询;商务与报表实际使用各自的可见范围接口 | -| `PUT /sw/business/resetPwd` | 原生 `POST /user/resetPassword`;商务自助找回密码使用已迁移的独立流程 | -| `PUT /sw/business/changeStatus` | 原生 `PUT /user/setUserInfo`;本批补齐 enable 与 business_status 联动 | -| `GET /sw/business/authRole/:userId` | 原生用户角色资料及角色列表 | -| `PUT /sw/business/authRole` | 原生 `POST /user/setUserAuthorities` | -| `GET /sw/business/deptTree` | 原生 `POST /department/getDepartmentList` | -| `GET /sw/business/list/dept/:deptId` | 原生 `GET /department/getDepartmentUsers` | -| `POST /sw/business/export` | RuoYi Excel 导出协议尚未增加别名;旧导出调用共享查询构造器,会继承商务过滤,不能把原生通用导出直接算成相同协议已实现 | -| `POST /sw/business/importData` | RuoYi Excel 导入协议尚未实现;当前商务模板没有导入入口 | -| `GET /sw/business/unlock/:userId` | 原先删除 RuoYi Redis 密码错误键;新系统使用 Kra 鉴权/限制机制,不读取旧 Redis 键。旧协议别名尚未注册 | - -以上记录说明框架能力的对应关系,并非宣称旧别名已可调用。别名与原生接口的请求/响应并不相同;最终接口核对仍须保留这项差异,尤其不能把导入/导出列为已经通过兼容验收。当前不删除用户 SQL 中的这些历史接口元数据。 - -## 账号启停与商务状态 - -原 RuoYi 用 `status` 同时表示正常、停用、驳回和待审核。迁移后有 Kra 的 `enable` 和保留语义的 `business_status`。原生用户启停此前只改前者,可能导致商务列表仍显示正常,或启用后仍因旧状态无法登录。 - -本批处理: - -- 新建原生账号时,默认启用与禁用状态同步到商务状态。 -- 管理员明确启用时恢复正常;关闭启用时,普通状态变为停用,待审核/驳回继续保留,避免普通资料编辑丢失审核状态。 -- 读取当前业务状态与写入两个字段在同一行锁事务内完成,规则由 biz 回调决定,data 只做持久化。 -- 个人资料不传 enable 时仍按原有字段更新规则处理;传 enable 时不能越过管理员已经写入的停用、待审或驳回状态。 -- 角色范围检查继续执行,不增加商务列表的编辑入口。 - -隔离 TCP HTTP 测试覆盖原生启停后商务接口返回状态、待审/驳回资料编辑、自行启用被拒绝和不存在用户;仓储测试覆盖失败回滚与越权。现有鉴权测试继续检查停用/待审/驳回会拒绝密码登录和已有会话。 - -sw8/sw9 的账号状态及原密码保留情况见 `validation.md`。 - -## 2026-11-04 实库复核 - -SQL 的 63 项契约已逐项归类:51 项商务接口完成真实 HTTP 核对,12 项本页所列旧框架别名由 Kra 原生能力承接,不宣称旧 Excel/Redis 解锁等协议兼容。详见 `sw8-sw9-recheck-summary-2026-11-04.json`。 - -真实状态写入验证确认:旧系统停用、待审、驳回后已签发会话仍可访问偏好;新系统会拒绝这些会话。该安全差异保留,恢复正常后旧令牌重新可用。 - -原库一级商务角色没有 `system:promote:add` 权限,新库保持同一授权限制。新增渠道的正向实测使用管理员,未擅自扩大角色权限。 diff --git a/docs/sw6-to-kra/validation.md b/docs/sw6-to-kra/validation.md deleted file mode 100644 index dc06175..0000000 --- a/docs/sw6-to-kra/validation.md +++ /dev/null @@ -1,91 +0,0 @@ -# 商务迁移验收与性能记录 - -核验日期:2026-11-04。Java → sw8,Go → sw9。原始响应与备份位于仓库外 `D:/Users/Yvan/backups/sw9/20261104_rehearsal/`。 - -## 迁移与接口 - -- SQL v5 在独立 MySQL 5.7 完成 52 项备份检查、24 项迁移检查;首次执行、重复执行、异常账本拒绝、旧表归档后执行均通过。45 个原用户密码哈希逐字节保留。 -- 全量旧契约 63 项:51 项商务接口已实测(33 读取、18 写入/导出);12 项旧框架别名由原生功能承接,不能视为旧协议兼容。 -- 最近完整演练共 230 项检查:104 组读取、两个 Excel 逐单元格、账号创建/编辑/状态、规则增删改/启停、预警状态流转/备注、SDK 绑定/重提/解绑、创建渠道和任务配置。 -- 日报与区服报表真实重建后,68,857 行逻辑数据一致,随后恢复原分区;预警实际任务两边生成 480 条后恢复原 478 条。 -- 恢复后的两库均为用户 48、平台绑定 58、规则 5、预警 478、预警日志 313。增加的 3 个层级账号为获授权保留的测试账号。 -- SDK 写入使用本机独立平台夹具,OA 审批使用受控夹具;没有宣称真实第三方审核或线上支付已验收。 - -详细旧契约清单保留在 [综合索引](sw8-sw9-recheck-summary-2026-11-04.json)。本轮新增审查及运行结果见 [接口审查](../API_REVIEW.md)。 - -## 明确保留的差异 - -1. 付费率榜单按用户要求统一 `%`,变化率为 `(本期-上期)/上期×100%`,上期为零返回无可比值;不是百分点差。 -2. 仅三个分别创建的测试账号允许创建时刻不同,原迁移用户时间严格比较。 -3. 超出末页时新接口返回空页;旧 MyBatis 会回到第一页。有效页码和总数保持相同。 -4. 新服务立即拒绝停用、待审、驳回用户的已有会话;旧服务未做这项检查。 -5. 本轮修正渠道激活的跨平台同名账号访问:本人已通过绑定的“平台+账号”才有权限。列表及流水明细使用同一规则。 -6. 日期范围只传一端、倒置或非法时返回参数错误;不再静默忽略筛选。 - -## 定时任务 - -7 条实际商务计划及 7 个方法均迁移,cron、秒字段、上海时区、回跑参数与超时/重试配置已经逐条核对。 - -| 方法 | 周期 | 测试库状态 | -|---|---|---| -| swReportDayYesterdayTask | 每日 01:00 | 启用 | -| swReportServerDayYesterdayTask | 每日 01:05 | 启用 | -| swReportDayTodayTask | 每 5 分钟,第 40 秒 | 启用 | -| swReportServerDayTodayTask | 每 5 分钟 | 启用 | -| swReportDayBackfillTask | 每 60 秒,原配置停用 | 停用 | -| swReportServerDayBackfillTask | 每 60 秒,原配置停用 | 停用 | -| alertTriggerTask | 每 30 分钟 | 启用 | - -2026-11-04 按用户确认与旧库启停状态同步,五条常规任务开启自动执行,两个历史回填保持停用;框架自带 ClearDB、CleanStaleUploads 继续停用。七条计划的周期、启停、上海时区、下次执行时间及超时/重试参数逐条核对通过,常规任务仍为 60 秒超时。旧工程的演示、分片、MapReduce 示例没有实际商务计划,不属于漏迁。方法超时后仍未退出时禁止重复执行,同分区报表和预警写入有事务锁及去重测试。 - -### 启用后的实际复测 - -中断续接时,昨日两类汇总均有 60 秒超时记录。用户查询改为按平台分组、ID 排序分批,避开 MySQL 5.7 多列 IN 部分批次的全表扫描;新增用户身份和区服活跃覆盖索引,减少大行回表。原始业务字段、统计规则和任务执行参数不变。 - -版本 `202611040014_business_report_build_indexes` 已在 sw9 应用,迁移版本总数为 28。两条索引分别为 `tab_user.idx_sw_user_report_identity(id,source_db,puid,promote_id,idcard)`、`tab_user_play_info.idx_sw_play_report_active(play_time,user_id,source_db,promote_id,game_id,server_id)`。 - -| 复测项 | 结果 | -|---|---| -| 昨日商务汇总,统计日 2026-11-03 | 最终版本实际执行成功,21.032 秒 | -| 昨日区服汇总,统计日 2026-11-03 | 最终版本实际执行成功,20.243 秒 | -| 今日两个汇总 | 已观察到多轮自动成功执行 | -| 预警任务 | 15:30 自动成功,28.864 秒;两库 480 条业务记录相等,用户 ID 按迁移表映射,排除生成 ID 和创建/更新时间 | -| 区服用户资料读取 | 同批 18,177 用户,71.619 秒降至 0.443 秒,38 批全部使用覆盖索引 | -| 区服活跃输入读取 | 同批 20,564 行,28.545 秒降至 0.074 秒,使用覆盖范围索引 | - -以上为该测试库的单轮实测,包含当时缓存和数据库负载影响,不是固定延迟承诺。Go 全量测试、构建及独立 MySQL 5.7 的六组回归通过;新增回归验证覆盖索引、批量身份读取、索引幂等和同名异列冲突拒绝,既有事务回滚测试通过。 - -四张表的 2026-11-03 重建结果分别为 3,440、15,064、19,682、30,671 行,合计 **68,857 行**,逐行及 SHA-256 均与此前保存的旧程序同日重建结果一致。该比较明确复用旧重算基线,本轮没有重跑或覆盖 sw8 的昨日分区。 - -直接比较两库当前昨日分区仍有差异:sw8 保留此前恢复的旧汇总,日报 8 行指标变化、日报身份键少 10 行,区服汇总 15 行旧结果对应 29 行重建结果、区服身份键少 31 行。不能把重算基线一致表述为两库当前分区一致。2026-11-04 两库四表均为空,sw9 当日注册、登录、成功充值、创角及活跃原始记录均为 0;今日验证覆盖自动触发和空日处理,非空数据核对使用昨日。 - -原始对比、任务日志和查询计划位于仓库外 `D:/Users/Yvan/backups/sw9/20261104_rehearsal/tasks-enabled-20261104_145308/`,最终证据为 `resumed-verification.json`、`final-manual-task-logs.json`、`task-index-installation.json`。辅助脚本同样留在仓库外,未恢复项目内已删除的 scripts 目录。最终版本运行于日常 8000 服务,保持五条自动计划启用。 - -## 已完成的性能优化 - -同一 sw9 副本的多轮中位耗时,单位 ms;首次冷读与负载变化会有波动。数据统计近 30 天,排行榜近 7 天。 - -| 接口 | 优化前 | 优化后 | -|---|---:|---:| -| 渠道列表 | 175 | 108 | -| 渠道数据统计 | 3839 | 1110 | -| 充值明细 | 216 | 113 | -| 注册明细 | 139 | 88 | -| 游戏数据 | 859 | 453 | -| 区服分析 | 3012 | 42 | -| 渠道排行榜 | 863 | 483 | -| 商务排行榜 | 5048 | 325 | -| 游戏排行榜 | 631 | 229 | -| 工作台汇总 | 75 | 42 | -| 工作台最低充值榜 | 1509 | 171 | -| 工作台未登录榜 | 224 | 158 | -| 工作台近 7 天注册榜 | 92 | 74 | -| 工作台近 7 天充值榜 | 147 | 53 | - -优化包括分页主键后回表、按原渠道预聚合、取消相关子查询、合并汇总查询、限制并发为 2、只加载 TOP10 名称,以及关闭 SQL 日志时避免参数展开。61 组业务列表/排行榜和 52 组工作台数据逐字段相等,另有日常 8080 接口调用检查。 - -新增版本 `202611040013_business_query_indexes` 已在 sw9 应用 7 个查询索引,累计 27 个迁移版本;注册转换列索引和区服创角时间索引亦已存在。查询优化不改变用户权限和统计口径。 - -## 页面 - -渠道激活页不再在发起分页请求时清零 total;排行榜与仪表盘四榜并排、付费率用百分比、头部两项偏好直接勾选;三级商务保留商务列表/绑定列表切换。页面检查脚本、运行截图和带业务数据的响应均已保存在仓库外。 diff --git a/docs/sw6-to-kra/workbench-source-notes.md b/docs/sw6-to-kra/workbench-source-notes.md deleted file mode 100644 index d20e3cb..0000000 --- a/docs/sw6-to-kra/workbench-source-notes.md +++ /dev/null @@ -1,26 +0,0 @@ -# 工作台与仪表盘业务数据 - -核对旧 main `WorkbenchServiceImpl`、`ChannelTreeMetricsSupport`、日汇总 Mapper,以及 dev/dev1.0 的 `views/index.vue`,迁移 `/sw/workbench/summary`、`registerTop`、`payRank`、`unloginTop`。 - -## 六项指标 - -- `sourceDbList` 至少选择一个平台;商务范围为本人及下级正常绑定,超管不限;是否包含下级渠道与身份证去重读取当前偏好。 -- 今日注册、活跃人数对比昨日,今日充值对比昨日,本月充值对比上月 1 日至同日(上月无该日期时取月末)。金额固定模式 0,人数模式 0 在全平台汇总时加平台前缀,模式 1 跨平台去重。 -- 活跃渠道数按每个渠道自身当日注册人数大于 0 或汇总充值金额大于 0 计算,不合并一级;同一渠道同时命中只计一次。新增渠道数按可见实体的创建时间统计,包含下级开关同时影响两项。 -- 本期/上期值先保留两位,再算一位小数环比;上期为零时 changeRate=null。changeDiff 保留字段但为 null,与旧服务实际输出一致。 - -## 四组榜单 - -- 注册榜 TOP10:包含下级时使用旧 `countByChannelRoot` 的 INNER JOIN+CASE,在渠道树内去重;不会将缺少实体的官方/历史孤立记录纳入注册榜。此处与渠道统计页的 LEFT JOIN 根口径不同。 -- 充值最高/最低榜按金额固定模式 0,再归并到根渠道。最高榜只保留正值,最低榜额外包含可见一级渠道的零充值实体;负值沿用旧最低榜行为,不擅自清零。官方/缺账号名称按旧规则回退。 -- 注册/最高充值默认今日,最低充值默认近 30 天,支持 today/yesterday/last7/last30;包括今天。最高/最低共用 payRank,通过 order 区分。 -- 未登录榜仅取可见一级实体,先用最后登录时间,无有效登录时用创建时间,两者都无效为 99999;未来日期为 0,按上海自然日计算。 -- 数值排序使用精确有理数;同值按 ID,跨平台同号追加平台稳定排序。充值显示两位小数,未登录天数为整数字符串;所有榜单排名连续 1 至 10。 - -## 实现与验证 - -- 仪表盘直接调用四个接口,并复用已有预警列表查询 status=1/pageSize=5,实现原最新五条轮播。Kra 快捷入口和公告保留。 -- 聚合、资料查询批量执行,未对每个渠道发起独立 SQL。注册榜不依赖金额表,未登录榜不依赖报表,缺少必要表返回明确不可用。 -- 六卡扩展 available=false 并返回 null 值;榜单保留数组成功协议,缺表返回业务错误,避免把未知榜单当作真实空榜。 - -当前验证状态统一见 [验收与性能记录](validation.md),不再维护阶段性运行报告。 diff --git a/internal/biz/business/analytics.go b/internal/biz/business/analytics.go index 9a4a6b5..f321f7a 100644 --- a/internal/biz/business/analytics.go +++ b/internal/biz/business/analytics.go @@ -234,6 +234,15 @@ func (uc *AnalyticsUsecase) List(ctx context.Context, kind AnalyticsKind, filter return out, nil } func sortAnalytics(rows []*AnalyticsRow, kind AnalyticsKind, field string, ascending bool) error { + if kind == GameAnalytics && field == "" { + sort.SliceStable(rows, func(i, j int) bool { + if rows[i].SourceDB != rows[j].SourceDB { + return rows[i].SourceDB < rows[j].SourceDB + } + return rows[i].ID < rows[j].ID + }) + return nil + } allowed := map[string]bool{"newRegisterCount": true, "activeCount": true, "payUserCount": true, "newPayUserCount": true, "totalPay": true, "payRate": true} if kind == GameAnalytics { allowed["arpu"] = true diff --git a/internal/biz/business/analytics_test.go b/internal/biz/business/analytics_test.go index 90229f1..ad3d6ef 100644 --- a/internal/biz/business/analytics_test.go +++ b/internal/biz/business/analytics_test.go @@ -91,6 +91,25 @@ func TestAnalyticsSortAndMissingData(t *testing.T) { } } +func TestGameAnalyticsCancelSortRestoresDefaultOrder(t *testing.T) { + uc, repo := analyticsFixture() + repo.data.Rows = []*AnalyticsRow{ + {AnalyticsKey: AnalyticsKey{SourceDB: "lx", ID: 2}, Pay: "5"}, + {AnalyticsKey: AnalyticsKey{SourceDB: "lx", ID: 1}, Pay: "10"}, + {AnalyticsKey: AnalyticsKey{SourceDB: "lx", ID: 3}, Pay: "20"}, + } + for _, sample := range []struct { + field string + ascending bool + first int64 + }{{"totalPay", true, 2}, {"totalPay", false, 3}, {"", false, 1}} { + page, err := uc.List(accountContext(7, 901), GameAnalytics, AnalyticsFilter{SortField: sample.field, Ascending: sample.ascending}, 1, 1) + if err != nil || page.Rows[0].ID != sample.first || page.Summary.Pay != "35.00" { + t.Fatalf("切换排序不应改变汇总,取消时恢复默认顺序: %+v %v", page, err) + } + } +} + func TestAnalyticsLoadsMetadataOnlyForSelectedPage(t *testing.T) { for _, kind := range []AnalyticsKind{ChannelAnalytics, GameAnalytics} { t.Run(string(kind), func(t *testing.T) { diff --git a/internal/biz/business/ledger.go b/internal/biz/business/ledger.go index ca9cd8f..55a307b 100644 --- a/internal/biz/business/ledger.go +++ b/internal/biz/business/ledger.go @@ -37,6 +37,7 @@ type LedgerListOptions struct { type LedgerNames struct { PromoteID *int64 PromoteAccount, BindingAccount, BindingUserName string + BusinessPath []string } func (n *LedgerNames) DisplayPromote() string { @@ -52,6 +53,9 @@ func (n *LedgerNames) DisplayPromote() string { return "未知渠道(ID:" + strconv.FormatInt(*n.PromoteID, 10) + ")" } func (n *LedgerNames) DisplayBusiness() string { + if len(n.BusinessPath) > 0 { + return strings.Join(n.BusinessPath, "→") + } return (&Channel{BindingAccount: n.BindingAccount, BindingUserName: n.BindingUserName}).BusinessDisplayName() } @@ -91,7 +95,7 @@ type GameOption struct { type LedgerRepo interface { Registrations(context.Context, LedgerScope, LedgerFilter, LedgerListOptions) (*RegistrationPage, error) Spends(context.Context, LedgerScope, LedgerFilter, LedgerListOptions) (*SpendPage, error) - Games(context.Context, []string, string, int) ([]*GameOption, error) + Games(context.Context, UserScope, []string, string, int) ([]*GameOption, error) } type LedgerUsecase struct { repo LedgerRepo @@ -226,14 +230,17 @@ func (uc *LedgerUsecase) ExportSpends(ctx context.Context, filter LedgerFilter) return page.Rows, nil } func (uc *LedgerUsecase) Games(ctx context.Context, sources []string, keyword string, limit int) ([]*GameOption, error) { - if _, _, err := uc.accounts.actor(ctx); err != nil { + actor, account, err := uc.accounts.actor(ctx) + if err != nil { return nil, err } + viewer := portraitUserScope(account) + viewer.All = actor.AuthorityID == 888 if limit <= 0 { limit = 20 } if limit > 50 { limit = 10000 } - return uc.repo.Games(ctx, sources, strings.TrimSpace(keyword), limit) + return uc.repo.Games(ctx, viewer, sources, strings.TrimSpace(keyword), limit) } diff --git a/internal/biz/business/ledger_test.go b/internal/biz/business/ledger_test.go index 9f2f6b6..fbe6f06 100644 --- a/internal/biz/business/ledger_test.go +++ b/internal/biz/business/ledger_test.go @@ -28,7 +28,8 @@ func (r *ledgerRepoFake) Spends(_ context.Context, s LedgerScope, f LedgerFilter r.options = o return &SpendPage{Rows: []*Spend{}, Total: r.total, Available: r.available, TotalPayAmount: stringPointer("0")}, nil } -func (r *ledgerRepoFake) Games(_ context.Context, _ []string, _ string, limit int) ([]*GameOption, error) { +func (r *ledgerRepoFake) Games(_ context.Context, viewer UserScope, _ []string, _ string, limit int) ([]*GameOption, error) { + r.scope.Viewer = viewer r.gameLimit = limit return []*GameOption{}, nil } @@ -89,4 +90,10 @@ func TestLedgerExportLimitAndDisplayFallback(t *testing.T) { if r.gameLimit != 10000 { t.Fatal("原游戏选项的特殊批量上限丢失") } + if !r.scope.Viewer.All { + t.Fatal("超管游戏选项范围未传递") + } + if _, err := uc.Games(accountContext(9, 903), nil, "", 20); err != nil || !r.scope.Viewer.OnlySelf || r.scope.Viewer.All { + t.Fatal("普通商务游戏选项必须限定本人范围") + } } diff --git a/internal/biz/business/server_analysis.go b/internal/biz/business/server_analysis.go index bca9b17..50a075b 100644 --- a/internal/biz/business/server_analysis.go +++ b/internal/biz/business/server_analysis.go @@ -47,7 +47,7 @@ type ServerOption struct { } type ServerAnalysisRepo interface { Aggregate(context.Context, AnalyticsScope, ServerAnalysisFilter) (*ServerAnalysisData, error) - Servers(context.Context, []string, []string, string, int) ([]*ServerOption, error) + Servers(context.Context, UserScope, []string, []string, string, int) ([]*ServerOption, error) } type ServerAnalysisUsecase struct { repo ServerAnalysisRepo @@ -60,9 +60,12 @@ func NewServerAnalysisUsecase(repo ServerAnalysisRepo, accounts *AccountUsecase, return &ServerAnalysisUsecase{repo: repo, accounts: accounts, preferences: preferences, now: time.Now} } func (uc *ServerAnalysisUsecase) Servers(ctx context.Context, sources, games []string, keyword string, limit int) ([]*ServerOption, error) { - if _, _, err := uc.accounts.actor(ctx); err != nil { + actor, account, err := uc.accounts.actor(ctx) + if err != nil { return nil, err } + viewer := portraitUserScope(account) + viewer.All = actor.AuthorityID == 888 if len(games) == 0 { return nil, ErrServerAnalysisGame } @@ -72,7 +75,7 @@ func (uc *ServerAnalysisUsecase) Servers(ctx context.Context, sources, games []s if limit > 100 { limit = 100000 } - return uc.repo.Servers(ctx, sources, games, strings.TrimSpace(keyword), limit) + return uc.repo.Servers(ctx, viewer, sources, games, strings.TrimSpace(keyword), limit) } func (uc *ServerAnalysisUsecase) List(ctx context.Context, f ServerAnalysisFilter, page, size int) (*ServerAnalysisPage, error) { actor, account, err := uc.accounts.actor(ctx) @@ -151,6 +154,19 @@ func (uc *ServerAnalysisUsecase) List(ctx context.Context, f ServerAnalysisFilte return out, nil } func sortServerAnalysis(rows []*ServerAnalysisRow, field string, ascending bool) error { + if field == "" { + sort.SliceStable(rows, func(i, j int) bool { + a, b := rows[i], rows[j] + if a.SourceDB != b.SourceDB { + return a.SourceDB < b.SourceDB + } + if a.GameID != b.GameID { + return a.GameID < b.GameID + } + return a.ServerNum < b.ServerNum + }) + return nil + } values := map[*ServerAnalysisRow]*big.Rat{} for _, row := range rows { var n *big.Rat diff --git a/internal/biz/business/server_analysis_test.go b/internal/biz/business/server_analysis_test.go index 3837118..1c3847d 100644 --- a/internal/biz/business/server_analysis_test.go +++ b/internal/biz/business/server_analysis_test.go @@ -22,7 +22,8 @@ func (r *serverAnalysisFake) Aggregate(_ context.Context, s AnalyticsScope, f Se } return out, nil } -func (r *serverAnalysisFake) Servers(_ context.Context, _, _ []string, _ string, limit int) ([]*ServerOption, error) { +func (r *serverAnalysisFake) Servers(_ context.Context, viewer UserScope, _, _ []string, _ string, limit int) ([]*ServerOption, error) { + r.scope.Viewer = viewer r.limit = limit return []*ServerOption{}, nil } @@ -67,3 +68,20 @@ func TestServerAnalysisSummaryZerosSortingAndLimits(t *testing.T) { } } } + +func TestServerAnalysisCancelSortRestoresIdentityOrder(t *testing.T) { + rows := []*ServerAnalysisRow{ + {ServerAnalysisKey: ServerAnalysisKey{SourceDB: "lx", GameID: 1, ServerNum: "002"}, Pay: "5"}, + {ServerAnalysisKey: ServerAnalysisKey{SourceDB: "lx", GameID: 1, ServerNum: "001"}, Pay: "10"}, + {ServerAnalysisKey: ServerAnalysisKey{SourceDB: "lx", GameID: 1, ServerNum: "003"}, Pay: "20"}, + } + if err := sortServerAnalysis(rows, "totalPay", true); err != nil || rows[0].ServerNum != "002" { + t.Fatal("升序错误") + } + if err := sortServerAnalysis(rows, "totalPay", false); err != nil || rows[0].ServerNum != "003" { + t.Fatal("降序错误") + } + if err := sortServerAnalysis(rows, "", false); err != nil || rows[0].ServerNum != "001" { + t.Fatal("取消排序应恢复稳定的区服顺序") + } +} diff --git a/internal/data/business/analytics.go b/internal/data/business/analytics.go index 92d3157..a749fe6 100644 --- a/internal/data/business/analytics.go +++ b/internal/data/business/analytics.go @@ -79,6 +79,9 @@ type analyticsAggPO struct { func analyticsRoot(db *gorm.DB, kind business.AnalyticsKind, scope business.AnalyticsScope, f business.AnalyticsFilter, table string, mode int, pay bool) (*gorm.DB, string) { q := analyticsQuery(db, scope, f, table, mode) + if kind == business.GameAnalytics { + q = q.Where("(r.source_db,r.game_id) IN (?)", approvedGamesQuery(db, scope.Viewer, f.Sources).Select("g.source_db,g.id")) + } id := "r.game_id" if kind == business.ChannelAnalytics { id = "r.promote_id" @@ -124,6 +127,16 @@ func (r *analyticsRepo) Aggregate(ctx context.Context, kind business.AnalyticsKi if empty || !available { return result, nil } + if kind == business.GameAnalytics { + available, err := approvedGamesAvailable(db) + if err != nil { + return nil, err + } + if !available { + result.Available = false + return result, nil + } + } for _, table := range []string{"tab_sw_report_day", "tab_sw_report_day_key"} { available, err := businessTableAvailable(db, table) if err != nil { diff --git a/internal/data/business/analytics_test.go b/internal/data/business/analytics_test.go index 9a08306..42e010c 100644 --- a/internal/data/business/analytics_test.go +++ b/internal/data/business/analytics_test.go @@ -12,6 +12,7 @@ func prepareAnalyticsData(t *testing.T) (*gorm.DB, business.AnalyticsRepo, busin t.Helper() db, _ := prepareChannels(t) for _, sql := range []string{ + "INSERT INTO tab_promote_apply VALUES('hw',100,1,1)", "ALTER TABLE tab_sw_report_day ADD COLUMN game_name TEXT", "ALTER TABLE tab_sw_report_day_key ADD COLUMN game_name TEXT", "UPDATE tab_sw_report_day SET game_name=CASE WHEN game_id=1 THEN '历史游戏甲' ELSE '游戏乙' END", diff --git a/internal/data/business/approved_games.go b/internal/data/business/approved_games.go new file mode 100644 index 0000000..7f0a0a0 --- /dev/null +++ b/internal/data/business/approved_games.go @@ -0,0 +1,28 @@ +package business + +import ( + "gorm.io/gorm" + "kra/internal/biz/business" +) + +func approvedGamesAvailable(db *gorm.DB) (bool, error) { + for _, table := range []string{"tab_game", "tab_promote", "tab_promote_apply"} { + available, err := businessTableAvailable(db, table) + if err != nil || !available { + return available, err + } + } + return true, nil +} + +// 游戏可选范围来自可见渠道的有效申请,不受统计时是否包含下级的开关影响。 +// 用平台和 ID 配对,避免同号游戏或其他商务的申请扩大可选范围。 +func approvedGamesQuery(db *gorm.DB, viewer business.UserScope, sources []string) *gorm.DB { + promotes := ledgerBasePromotes(db, business.LedgerScope{Viewer: viewer, IncludeSub: true, Unrestricted: viewer.All}, business.LedgerFilter{Sources: sources}, "approved_p").Select("approved_p.source_db,approved_p.id") + applications := db.Table("tab_promote_apply a").Select("a.source_db,a.game_id").Where("a.status=1").Where("(a.source_db,a.promote_id) IN (?)", promotes) + q := db.Table("tab_game g").Where("(g.source_db,g.id) IN (?)", applications) + if len(sources) > 0 { + q = q.Where("g.source_db IN ?", sources) + } + return q +} diff --git a/internal/data/business/approved_games_test.go b/internal/data/business/approved_games_test.go new file mode 100644 index 0000000..61818c2 --- /dev/null +++ b/internal/data/business/approved_games_test.go @@ -0,0 +1,62 @@ +package business + +import ( + "context" + "testing" + + "kra/internal/biz/business" +) + +func TestGameOptionsRequireVisibleApprovedApplications(t *testing.T) { + db, _ := prepareChannels(t) + for _, sql := range []string{ + "INSERT INTO tab_game VALUES('lx',3,'子渠道游戏'),('lx',4,'未申请包服'),('lx',5,'其他商务游戏'),('lx',6,'待审核游戏')", + "INSERT INTO tab_promote_apply VALUES('lx',104,5,1),('lx',100,6,0)", + } { + if err := db.Exec(sql).Error; err != nil { + t.Fatal(err) + } + } + repo := NewLedgerRepo(testData{db}) + ctx := context.Background() + rows, err := repo.Games(ctx, channelTestScope(), nil, "", 100) + if err != nil || len(rows) != 3 { + t.Fatalf("只能返回可见渠道已通过申请的游戏,重复申请不能重复: %+v %v", rows, err) + } + for _, row := range rows { + if row.SourceDB != "lx" || row.ID > 3 { + t.Fatalf("泄漏未申请或其他商务的游戏: %+v", row) + } + } + rows, err = repo.Games(ctx, channelTestScope(), []string{"hw"}, "", 100) + if err != nil || len(rows) != 0 { + t.Fatal("不能借用其他平台同号游戏的申请") + } + rows, err = repo.Games(ctx, business.UserScope{SelfID: 99, OnlySelf: true}, []string{"lx"}, "", 100) + if err != nil || len(rows) != 0 { + t.Fatal("无可见绑定不能退化为全部游戏") + } + rows, err = repo.Games(ctx, channelTestScope(), nil, "子渠道", 1) + if err != nil || len(rows) != 1 || rows[0].ID != 3 { + t.Fatal("应支持已申请游戏的关键词与数量筛选") + } + if err := db.Exec("DROP TABLE tab_promote_apply").Error; err != nil { + t.Fatal(err) + } + if _, err := repo.Games(ctx, channelTestScope(), nil, "", 100); err != business.ErrGameOptionsUnavailable { + t.Fatal("缺申请表不能开放所有游戏") + } +} + +func TestGameReportsRejectUnapprovedGamesEvenWithVisibleHistory(t *testing.T) { + db, repo, scope, filter := prepareAnalyticsData(t) + if err := db.Exec("UPDATE tab_promote_apply SET status=0 WHERE source_db='lx' AND game_id=1").Error; err != nil { + t.Fatal(err) + } + filter.Sources = []string{"lx"} + filter.GameNames = []string{"历史游戏甲"} + rows, err := repo.Aggregate(context.Background(), business.GameAnalytics, scope, filter) + if err != nil || !rows.Available || len(rows.Rows) != 0 { + t.Fatalf("直接指定未申请游戏也不能返回统计: %+v %v", rows, err) + } +} diff --git a/internal/data/business/ledger.go b/internal/data/business/ledger.go index ceb2fe5..05331c4 100644 --- a/internal/data/business/ledger.go +++ b/internal/data/business/ledger.go @@ -32,11 +32,8 @@ func ledgerPromotes(db *gorm.DB, scope business.LedgerScope, filter business.Led return q } hits := ledgerBasePromotes(db, scope, filter, "hit") - exact := "TRIM(hit.account) = ? COLLATE BINARY" - if db.Dialector.Name() == "mysql" { - exact = "BINARY TRIM(hit.account) = ?" - } - hits = hits.Where(exact, filter.PromoteAccount).Where("hit.source_db=" + alias + ".source_db") + keyword := strings.ToLower(strings.TrimSpace(filter.PromoteAccount)) + hits = hits.Where("(INSTR(LOWER(hit.account),?) > 0 OR INSTR(LOWER(hit.nickname),?) > 0)", keyword, keyword).Where("hit.source_db=" + alias + ".source_db") if scope.IncludeSub { root := "CASE WHEN hit.promote_level=1 THEN hit.id WHEN hit.top_promote_id>0 THEN hit.top_promote_id ELSE hit.id END" hits = hits.Where("(" + alias + ".id = (" + root + ") OR " + alias + ".top_promote_id = (" + root + "))") @@ -232,7 +229,8 @@ func spendQuery(db *gorm.DB, scope business.LedgerScope, filter business.LedgerF q := ledgerScopeQuery(db, scope, filter, "tab_spend").Where("r.pay_time BETWEEN ? AND ?", filter.BeginUnix, filter.EndUnix) if successOnly { q = q.Where("r.pay_status = 1") - } else if filter.PayStatus != nil { + } + if filter.PayStatus != nil { q = q.Where("r.pay_status = ?", *filter.PayStatus) } if len(filter.GameNames) > 0 { @@ -353,11 +351,13 @@ func fillLedgerNames(db *gorm.DB, scope business.LedgerScope, filter business.Le SourceDB string `gorm:"column:source_db"` PlatformBusierID uint64 PlatformBusierAccount, Username string + UserID uint + IDPath string `gorm:"column:id_path"` } names := map[business.PlatformKey]bindName{} for start := 0; start < len(pairs); start += 300 { var rows []bindName - q := channelBindingQuery(db, scope.Viewer, business.ChannelFilter{}).Select("b.source_db,b.platform_busier_id,b.platform_busier_account,u.username").Where("(b.source_db,b.platform_busier_id) IN ?", portraitBindingPairs(pairs[start:min(start+300, len(pairs))])).Order("b.user_id") + q := channelBindingQuery(db, scope.Viewer, business.ChannelFilter{}).Select("b.source_db,b.platform_busier_id,b.platform_busier_account,b.user_id,u.username,u.id_path").Where("(b.source_db,b.platform_busier_id) IN ?", portraitBindingPairs(pairs[start:min(start+300, len(pairs))])).Order("b.user_id") if err := q.Scan(&rows).Error; err != nil { return business.ErrStorage } @@ -368,6 +368,31 @@ func fillLedgerNames(db *gorm.DB, scope business.LedgerScope, filter business.Le } } } + ancestorIDs := map[uint]bool{} + paths := map[business.PlatformKey][]uint{} + for key, binding := range names { + for _, part := range strings.Split(binding.IDPath, ",") { + id, err := strconv.ParseUint(strings.TrimSpace(part), 10, 32) + if err == nil && id > 0 && uint(id) != binding.UserID { + paths[key] = append(paths[key], uint(id)) + ancestorIDs[uint(id)] = true + } + } + } + ids := make([]uint, 0, len(ancestorIDs)) + for id := range ancestorIDs { + ids = append(ids, id) + } + ancestors := map[uint]string{} + for start := 0; start < len(ids); start += 300 { + var rows []accountPO + if err := db.Select("id,username").Where("id IN ? AND level > 0", ids[start:min(start+300, len(ids))]).Find(&rows).Error; err != nil { + return business.ErrStorage + } + for _, row := range rows { + ancestors[row.ID] = row.Username + } + } for _, target := range targets { n := target.Names if n.PromoteID == nil || *n.PromoteID < 0 { @@ -380,33 +405,38 @@ func fillLedgerNames(db *gorm.DB, scope business.LedgerScope, filter business.Le if binding, ok := names[business.PlatformKey{SourceDB: c.SourceDB, BusierID: c.BusierID}]; ok { n.BindingAccount = binding.PlatformBusierAccount n.BindingUserName = binding.Username + for _, id := range paths[business.PlatformKey{SourceDB: c.SourceDB, BusierID: c.BusierID}] { + if name := strings.TrimSpace(ancestors[id]); name != "" { + n.BusinessPath = append(n.BusinessPath, name) + } + } + if name := strings.TrimSpace(binding.Username); name != "" { + n.BusinessPath = append(n.BusinessPath, name) + } } } } return nil } -func (r *ledgerRepo) Games(ctx context.Context, sources []string, keyword string, limit int) ([]*business.GameOption, error) { +func (r *ledgerRepo) Games(ctx context.Context, viewer business.UserScope, sources []string, keyword string, limit int) ([]*business.GameOption, error) { db := r.data.DB().WithContext(ctx) - available, err := businessTableAvailable(db, "tab_game") + available, err := approvedGamesAvailable(db) if err != nil { return nil, err } if !available { return nil, business.ErrGameOptionsUnavailable } - q := db.Table("tab_game") - if len(sources) > 0 { - q = q.Where("source_db IN ?", sources) - } + q := approvedGamesQuery(db, viewer, sources) if keyword != "" { - q = q.Where("game_name LIKE ?", "%"+keyword+"%") + q = q.Where("INSTR(LOWER(g.game_name),?) > 0", strings.ToLower(keyword)) } var rows []struct { ID uint64 SourceDB string `gorm:"column:source_db"` GameName string } - if err := q.Select("id,source_db,game_name").Order("game_name,id,source_db").Limit(limit).Scan(&rows).Error; err != nil { + if err := q.Select("g.id,g.source_db,g.game_name").Distinct().Order("g.game_name,g.id,g.source_db").Limit(limit).Scan(&rows).Error; err != nil { return nil, business.ErrStorage } result := make([]*business.GameOption, 0, len(rows)) diff --git a/internal/data/business/ledger_test.go b/internal/data/business/ledger_test.go index 5211596..84056d2 100644 --- a/internal/data/business/ledger_test.go +++ b/internal/data/business/ledger_test.go @@ -40,7 +40,7 @@ func TestRegistrationScopePuidAndUnboundedPlayerPay(t *testing.T) { first = row } } - if first == nil || first.TotalPayAmount == nil || portraitTestMoney(*first.TotalPayAmount) != "710.10" || first.FirstGameName != "历史游戏名" || first.DisplayBusiness() != "lx-business(leaf)" { + if first == nil || first.TotalPayAmount == nil || portraitTestMoney(*first.TotalPayAmount) != "710.10" || first.FirstGameName != "历史游戏名" || first.DisplayBusiness() != "parent→branch→leaf" { t.Fatalf("累计充值不能受本次时间/渠道限制,且需保留游戏快照: %+v", first) } filter.SortField = "totalPayAmount" @@ -59,19 +59,19 @@ func TestRegistrationScopePuidAndUnboundedPlayerPay(t *testing.T) { if err != nil || page.Total != 2 { t.Fatal("精确子渠道账号应扩到同一一级树内的可见渠道") } - filter.PromoteAccount = "CHILD-channel" + filter.PromoteAccount = "CHILD-chan" page, err = repo.Registrations(ctx, scope, filter, business.LedgerListOptions{Limit: 20}) - if err != nil || page.Total != 0 { - t.Fatal("渠道账号应保持区分大小写的精确匹配") + if err != nil || page.Total != 2 { + t.Fatal("渠道应支持不区分大小写的模糊匹配") } } -func TestSpendSummaryIgnoresSelectedFailureStatusAndKeepsSnapshot(t *testing.T) { +func TestSpendSummaryRespectsSelectedStatusAndKeepsSnapshot(t *testing.T) { _, repo, scope, filter := prepareLedgerData(t) status := 0 filter.PayStatus = &status page, err := repo.Spends(context.Background(), scope, filter, business.LedgerListOptions{Limit: 20}) - if err != nil || page.Total != 1 || page.Rows[0].ID != 904 || portraitTestMoney(*page.TotalPayAmount) != "80.80" { - t.Fatalf("失败列表与成功支付合计不能使用同一个状态条件: %+v %v", page, err) + if err != nil || page.Total != 1 || page.Rows[0].ID != 904 || portraitTestMoney(*page.TotalPayAmount) != "0.00" { + t.Fatalf("失败状态筛选下不能汇总筛选外成功订单: %+v %v", page, err) } status = 2 page, err = repo.Spends(context.Background(), scope, filter, business.LedgerListOptions{Limit: 20}) @@ -125,3 +125,25 @@ func TestLedgerLargeTreeFilterDoesNotFallBackToAll(t *testing.T) { t.Fatal("缺渠道范围表不能把限制解释为全量") } } + +func TestLedgerChannelNicknameAndLiteralFuzzyFilter(t *testing.T) { + db, repo, scope, filter := prepareLedgerData(t) + if err := db.Exec("UPDATE tab_promote SET nickname='推广公会' WHERE source_db='lx' AND id=100").Error; err != nil { + t.Fatal(err) + } + filter.PromoteAccount = "公会" + page, err := repo.Spends(context.Background(), scope, filter, business.LedgerListOptions{Limit: 20}) + if err != nil || page.Total != 4 { + t.Fatalf("昵称片段应命中渠道及可见下级: %+v %v", page, err) + } + filter.PromoteAccount = "%" + page, err = repo.Spends(context.Background(), scope, filter, business.LedgerListOptions{Limit: 20}) + if err != nil || page.Total != 0 { + t.Fatal("模糊输入中的百分号应按文字匹配") + } + filter.PromoteAccount = "other" + page, err = repo.Spends(context.Background(), scope, filter, business.LedgerListOptions{Limit: 20}) + if err != nil || page.Total != 0 { + t.Fatal("模糊搜索不得扩大商务范围") + } +} diff --git a/internal/data/business/server_analysis.go b/internal/data/business/server_analysis.go index 2ef2823..12eab75 100644 --- a/internal/data/business/server_analysis.go +++ b/internal/data/business/server_analysis.go @@ -17,6 +17,7 @@ func NewServerAnalysisRepo(data Provider) business.ServerAnalysisRepo { func serverReportQuery(db *gorm.DB, scope business.AnalyticsScope, f business.ServerAnalysisFilter, table string, mode int) *gorm.DB { q := ledgerScopeQuery(db, business.LedgerScope{Viewer: scope.Viewer, IncludeSub: scope.IncludeSub, Unrestricted: scope.Viewer.All}, business.LedgerFilter{Sources: f.Sources}, table) q = q.Where("r.stat_date >= ? AND r.stat_date <= ? AND r.dedup_mode=? AND r.server_num != ''", f.Begin, f.End, mode).Where("r.game_name IN ?", f.GameNames) + q = q.Where("(r.source_db,r.game_id) IN (?)", approvedGamesQuery(db, scope.Viewer, f.Sources).Select("g.source_db,g.id")) if f.ServerNum != "" { q = q.Where("r.server_num=?", f.ServerNum) } @@ -44,7 +45,7 @@ func (r *serverAnalysisRepo) Aggregate(ctx context.Context, scope business.Analy if empty || !available { return out, nil } - for _, table := range []string{"tab_sw_report_server_day", "tab_sw_report_server_day_key", "tab_game_server", "tab_game"} { + for _, table := range []string{"tab_sw_report_server_day", "tab_sw_report_server_day_key", "tab_game_server", "tab_game", "tab_promote_apply"} { available, err := businessTableAvailable(db, table) if err != nil { return nil, err @@ -144,9 +145,9 @@ func fillServerAnalysisNames(db *gorm.DB, rows map[business.ServerAnalysisKey]*b } return nil } -func (r *serverAnalysisRepo) Servers(ctx context.Context, sources, games []string, keyword string, limit int) ([]*business.ServerOption, error) { +func (r *serverAnalysisRepo) Servers(ctx context.Context, viewer business.UserScope, sources, games []string, keyword string, limit int) ([]*business.ServerOption, error) { db := r.data.DB().WithContext(ctx) - for _, table := range []string{"tab_game", "tab_game_server"} { + for _, table := range []string{"tab_game", "tab_game_server", "tab_promote", "tab_promote_apply"} { available, err := businessTableAvailable(db, table) if err != nil { return nil, err @@ -158,7 +159,7 @@ func (r *serverAnalysisRepo) Servers(ctx context.Context, sources, games []strin // MySQL 5.7 不会将相关 EXISTS 展开为半连接,导致扫描全部区服。 // 多列 IN 让优化器先按游戏名索引定位,再使用区服的 game_id 索引, // 同时保留平台匹配和重复游戏资料不扩增结果的语义。 - gamesQuery := db.Table("tab_game g").Select("g.source_db,g.id").Where("g.game_name IN ?", games) + gamesQuery := approvedGamesQuery(db, viewer, sources).Select("g.source_db,g.id").Where("g.game_name IN ?", games) q := db.Table("tab_game_server s").Where("(s.source_db,s.game_id) IN (?)", gamesQuery) if len(sources) > 0 { q = q.Where("s.source_db IN ?", sources) diff --git a/internal/data/business/server_analysis_test.go b/internal/data/business/server_analysis_test.go index 39e898b..0f4ebae 100644 --- a/internal/data/business/server_analysis_test.go +++ b/internal/data/business/server_analysis_test.go @@ -9,6 +9,7 @@ import ( func TestServerAnalysisStorageScopeSnapshotAndPreference(t *testing.T) { db, _ := prepareChannels(t) for _, sql := range []string{ + "INSERT INTO tab_promote_apply VALUES('hw',100,1,1)", "CREATE TABLE tab_game_server(id INTEGER,source_db TEXT,game_id INTEGER,server_num TEXT,server_name TEXT,start_time INTEGER)", "INSERT INTO tab_game_server VALUES(1,'lx',1,'001','龙翔一区',100),(2,'hw',1,'001','汇玩一区',200),(3,'lx',2,'001','游戏乙一区',300),(4,'yq',1,'001','无权区服',400)", "CREATE TABLE tab_sw_report_server_day(source_db TEXT,game_id INTEGER,game_name TEXT,promote_id INTEGER,server_num TEXT,stat_date DATE,dedup_mode INTEGER,total_pay DECIMAL(20,2))", @@ -68,7 +69,7 @@ func TestServerAnalysisStorageScopeSnapshotAndPreference(t *testing.T) { if err != nil || len(p.Rows) != 1 { t.Fatal("区服编号筛选错误") } - options, err := r.Servers(ctx, []string{"lx"}, []string{"游戏甲"}, "一区", 50) + options, err := r.Servers(ctx, s.Viewer, []string{"lx"}, []string{"游戏甲"}, "一区", 50) if err != nil || len(options) != 1 || options[0].Number != "001" || options[0].Name != "龙翔一区" { t.Fatal("选项应按当前游戏名、同平台游戏关联及区服名称筛选") } @@ -77,6 +78,18 @@ func TestServerAnalysisStorageScopeSnapshotAndPreference(t *testing.T) { if err != nil || len(p.Rows) != 0 { t.Fatal("报表必须按快照游戏名筛选") } + if err := db.Exec("UPDATE tab_promote_apply SET status=0 WHERE source_db='lx' AND game_id=1").Error; err != nil { + t.Fatal(err) + } + options, err = r.Servers(ctx, s.Viewer, []string{"lx"}, []string{"游戏甲"}, "", 50) + if err != nil || len(options) != 0 { + t.Fatal("没有有效申请的游戏不能获取区服选项") + } + f.GameNames = []string{"历史游戏"} + p, err = r.Aggregate(ctx, s, f) + if err != nil || len(p.Rows) != 0 { + t.Fatal("直接传入未申请游戏也不能获取区服数据") + } if err := db.Exec("DROP TABLE tab_sw_report_server_day_key").Error; err != nil { t.Fatal(err) } @@ -89,6 +102,10 @@ func TestServerAnalysisStorageScopeSnapshotAndPreference(t *testing.T) { func TestServerOptionsPreservePlatformFilterAndDoNotDuplicateMatches(t *testing.T) { db := openTestDB(t) for _, sql := range []string{ + "CREATE TABLE tab_promote(id INTEGER,source_db TEXT)", + "INSERT INTO tab_promote VALUES(100,'lx'),(100,'hw')", + "CREATE TABLE tab_promote_apply(source_db TEXT,promote_id INTEGER,game_id INTEGER,status INTEGER)", + "INSERT INTO tab_promote_apply VALUES('lx',100,1,1),('lx',100,2,1),('hw',100,1,1)", "CREATE TABLE tab_game(id INTEGER,source_db TEXT,game_name TEXT)", "INSERT INTO tab_game VALUES(1,'lx','甲'),(1,'lx','甲'),(1,'hw','乙'),(2,'lx','乙')", "CREATE TABLE tab_game_server(id INTEGER,source_db TEXT,game_id INTEGER,server_num TEXT,server_name TEXT,start_time INTEGER)", @@ -99,15 +116,15 @@ func TestServerOptionsPreservePlatformFilterAndDoNotDuplicateMatches(t *testing. } } repo := NewServerAnalysisRepo(testData{db}) - rows, err := repo.Servers(context.Background(), nil, []string{"甲"}, "", 100) + rows, err := repo.Servers(context.Background(), business.UserScope{All: true}, nil, []string{"甲"}, "", 100) if err != nil || len(rows) != 2 || rows[0].Name != "一区" || rows[1].Number != "002" { t.Fatalf("相同游戏资料不能扩增区服,异平台同号不能匹配: %+v %v", rows, err) } - rows, err = repo.Servers(context.Background(), []string{"lx"}, []string{"甲", "乙"}, "区", 1) + rows, err = repo.Servers(context.Background(), business.UserScope{All: true}, []string{"lx"}, []string{"甲", "乙"}, "区", 1) if err != nil || len(rows) != 1 || rows[0].Name != "一区" { t.Fatalf("名称筛选、排序或数量限制改变: %+v %v", rows, err) } - rows, err = repo.Servers(context.Background(), []string{"hw"}, []string{"甲"}, "", 100) + rows, err = repo.Servers(context.Background(), business.UserScope{All: true}, []string{"hw"}, []string{"甲"}, "", 100) if err != nil || len(rows) != 0 { t.Fatalf("平台筛选被忽略: %+v %v", rows, err) } diff --git a/web/src/view/sw/ServerAnalysis.vue b/web/src/view/sw/ServerAnalysis.vue index b7882b4..386ffb4 100644 --- a/web/src/view/sw/ServerAnalysis.vue +++ b/web/src/view/sw/ServerAnalysis.vue @@ -3,7 +3,7 @@