Преглед изворни кода

refactor(收款): 「商户映射」改叫「手工登记商户号」—— 菜单名说操作员要干的事

计划 Task 5 / Step 3。使用者是柜台操作员,不是开发。「映射」是我们的领域词
(企业 ↔ 商户号的那条对应关系),它准确描述了**数据库里的一行**,
但没告诉操作员**这一页要他干什么**。这一页要他干的事只有一件:把已经开好的
商户号登记进来。菜单名就说这件事。

改动的判据是「**操作员会不会在界面上读到这个旧名字**」,不是「仓库里还有没有这四个字」:

改了(引号里指名菜单,或同页用户可见):
  db/lsy-merchant-menu-rename.sql   新增;sys_menu 的 name 与 title
                                    (title 驱动侧边栏显示 —— 有代码依据:
                                     permission.store.ts:72 `title: item.title`)
  LsyMerchantService.java:56        404 文案
  LsyMerchantService.java:85        404 文案
  LsyOnboardingService.java:44      **逐字引用**上面那句 404 的 javadoc
  merchant/index.vue:7              页面顶部说明(由三行术语改成一句人话)
  merchant/index.vue:69             弹窗标题(编辑/新增)
  merchant/index.vue:239            删除确认文案

没改(领域术语 —— 那里说的是事实,只是不适合当菜单名):
  LsyMerchantService 的类注释、LsyMerchantService.java:561/:570 的
  「商户映射不存在」、各 javadoc、表注释、SQL 文件里的历史描述。
  ★ 561/570 是**有意保留**的:它们不指菜单、不构成断链,而换一个词需要判断
    新词会不会引起另一种误读(「该商户号不存在」会被读成「上游没有这个号」),
    这个判断我没有依据,所以不猜。

route_name 保持 CollectionMerchant 不动 —— 它是**身份**不是标签,页面靠它做
keep-alive 与 tags-view 匹配。route_path / component_path / permission 一律不动。

改名 SQL 里留下的断言都是**先量后写**的,不是照模板抄的:
  count(route_name='CollectionMerchant') = 1
  parent_id = 268(收付款),其下 4 个 type=2 子行
  定位用 route_name 而不是 name —— name 正是要被改掉的那一列。

影响面实测:测试里**零**断言旧菜单名。唯一两处相近的命中是注释、
以及 LsyMerchantServiceTest 的 contains("未配置商户号")(子串不含菜单名)
⇒ 改名不需要动任何测试。全量 688 绿 / 0 失败 / 0 错误,BUILD SUCCESS。

★ SQL **由用户执行**,本提交只落文件。执行后需重新登录(菜单树在登录时拉取)。

顺带:lsy-cashier-menu.sql 里「活库只读实测」那段加了一条时点注记 ——
那四个菜单名是 2026-09-23 那一刻的读数,其中 id=271 随后在本提交改名了。
不加这句,那份脚本的读者会去库里找一个已经不存在的名字。
alphaH пре 3 недеља
родитељ
комит
fb1c618865

+ 3 - 3
frontend/src/views/module_payment/collection/merchant/index.vue

@@ -4,7 +4,7 @@
       type="info"
       :closable="false"
       style="margin-bottom: 12px"
-      title="本平台开通的商户号。企业 ID 留空即「租户级」——该租户下所有下单都走这一行;填了企业 ID 则只有该企业可用。不配置则无法下单。"
+      title="手工登记商户号。收款前必须先在这里登记一行 —— 下单时提示「未配置商户号」就是这里还没登记。企业 ID 留空 = 整个租户共用这个号;填了 = 只有这家企业用。"
     />
 
     <el-card shadow="never">
@@ -66,7 +66,7 @@
       />
     </el-card>
 
-    <el-dialog v-model="formVisible" :title="form.id ? '编辑商户映射' : '新增商户映射'" width="560px">
+    <el-dialog v-model="formVisible" :title="form.id ? '编辑商户号' : '登记商户号'" width="560px">
       <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
         <!-- ★ 选填(2026-09-22 去企业化):留空 ⇒ 这一行是**租户级**映射,
              下单时不带 enterprise_id 的请求都会落到它上面。 -->
@@ -236,7 +236,7 @@ async function handleSubmit() {
 
 async function handleDelete(row: any) {
   const scope = row.enterprise_id ? `企业「${row.enterprise_id}」` : "本租户";
-  await ElMessageBox.confirm(`确认删除商户映射「${row.mch_no}」?删除后${scope}将无法下单。`, "提示", {
+  await ElMessageBox.confirm(`确认删除登记「${row.mch_no}」?删除后${scope}将无法下单。`, "提示", {
     type: "warning",
   });
   await deleteLsyMerchant(row.id);

+ 2 - 2
java/src/main/java/com/payment/platform/module/payment/leshouying/service/LsyMerchantService.java

@@ -53,7 +53,7 @@ public class LsyMerchantService {
                 .last("LIMIT 1"));
         if (m == null) {
             throw new BusinessException(404,
-                    "该企业未配置商户号,请先在「商户映射」中配置: " + enterpriseId);
+                    "该企业未配置商户号,请先在「手工登记商户号」中登记: " + enterpriseId);
         }
         return m;
     }
@@ -82,7 +82,7 @@ public class LsyMerchantService {
                 .last("LIMIT 1"));
         if (m == null) {
             throw new BusinessException(404,
-                    "该租户未配置商户号,请先在「商户映射」中配置");
+                    "该租户未配置商户号,请先在「手工登记商户号」中登记");
         }
         return m;
     }

+ 1 - 1
java/src/main/java/com/payment/platform/module/payment/leshouying/service/LsyOnboardingService.java

@@ -41,7 +41,7 @@ import java.util.Set;
  *   <li><b>不查本地映射是有意的,不是漏了。</b>进件阶段这个商户<b>还没进
  *       {@code pay_lsy_merchant}</b>(那一行是进件成功之后才写的)—— 所以在这里调
  *       {@code LsyMerchantService.requireByTenant} / {@code requireByMchNo} 必然落空,
- *       报的是它们各自那句 404({@code 该租户未配置商户号,请先在「商户映射」中配置} /
+ *       报的是它们各自那句 404({@code 该租户未配置商户号,请先在「手工登记商户号」中登记} /
  *       {@code "商户号不存在: " + mchNo})。那正是本轮要防的「校验前提不成立」:**在进件阶段,
  *       『配置里没有这个商户』不是异常,而是这个阶段的常态** —— 一句 404 会把操作者
  *       送去配一个此刻不可能存在的映射。</li>

+ 74 - 0
java/src/main/resources/db/lsy-merchant-menu-rename.sql

@@ -0,0 +1,74 @@
+-- ============================================================================
+-- 菜单改名:「商户映射」→「手工登记商户号」
+--
+-- 计划:.claude/plan/2026-09-23-lsy-simple-flow.md   Task 5 / Step 3
+-- 时点:2026-09-23        作者:实现侧        执行:用户
+--                        (本仓约定:SQL 只由用户执行,实现侧只写不跑)
+-- ============================================================================
+--
+-- ── 为什么改 ────────────────────────────────────────────────────────────────
+-- 使用者是柜台操作员,不是开发。「映射」是我们内部的领域词(企业 ↔ 商户号的那条
+-- 对应关系),它准确地描述了**数据库里的一行**,但没告诉操作员**这一页要他干什么**。
+-- 这一页要他干的事只有一件:把已经开好的商户号登记进来。菜单名就说这件事。
+--
+-- ── 只改哪两列 ──────────────────────────────────────────────────────────────
+-- `name` 与 `title` 两个都改,因为它们是两份不同用途的名字:
+--   · `title` —— **驱动侧边栏显示的那一列**。有代码依据,不是推测:
+--     frontend/src/store/modules/permission.store.ts:72  `title: item.title`
+--     ⇒ 该值变成 route.meta.title ⇒ 侧边栏渲染它
+--     (layouts/components/Menu/components/MenuItemContent.vue:13)。
+--   · `name` —— 同一行在菜单管理页里的名字。一并改,免得同一行有两个名字。
+--
+-- ── 不改什么,以及为什么 ────────────────────────────────────────────────────
+--   · `route_name` 保持 `CollectionMerchant` 不动。它是**身份**不是标签:
+--     页面靠它做 keep-alive 与 tags-view 匹配,改它要连着动前端,
+--     而本批次的目标只是让操作员看懂这个名字。
+--   · `route_path` / `component_path` / `permission` 一律不动 —— 改名不涉及路由。
+--   · 源码里的**领域描述**(javadoc、表注释、类名里的「商户映射」)不改:
+--     那里说的事实是对的(确实是一条映射关系),只是不适合当菜单名。
+--     只有**引号里指名菜单**的地方跟着改了 —— 否则操作员照着提示找不到菜单。
+--     同步改过的源码位置(供核对,本文件执行后会与代码一致):
+--       LsyMerchantService.java:56  该企业未配置商户号,请先在「手工登记商户号」中登记
+--       LsyMerchantService.java:85  该租户未配置商户号,请先在「手工登记商户号」中登记
+--       merchant/index.vue:7        页面顶部说明
+--       merchant/index.vue:69       弹窗标题(编辑/新增)
+--       merchant/index.vue:239      删除确认文案
+--
+-- ── 定位方式 ────────────────────────────────────────────────────────────────
+-- 用 `route_name` 定位而不是 `name`:`name` 正是要被改掉的那一列,
+-- 拿它当 WHERE 条件在未来某次改名后会失效,而 `route_name` 是稳定身份。
+-- 先只读核对一次(见下),确认命中的就是那一行。
+--
+-- ── 只读核对(先跑这一段,期望:1 行,id=271「商户映射」/CollectionMerchant)──
+--   SELECT id, name, title, type, route_name, route_path, permission
+--     FROM sys_menu WHERE route_name = 'CollectionMerchant';
+--
+-- ============================================================================
+
+UPDATE sys_menu
+   SET name  = '手工登记商户号',
+       title = '手工登记商户号'
+ WHERE route_name = 'CollectionMerchant'
+   AND type = 2;
+
+-- ── 执行后核对(期望:1 行,name/title 都是「手工登记商户号」,其余列与改前相同)──
+--   SELECT id, name, title, type, route_name, route_path, component_path,
+--          permission, hidden, keep_alive, status
+--     FROM sys_menu WHERE route_name = 'CollectionMerchant';
+--
+-- ── 对照查询:确认没有误伤别的行 ────────────────────────────────────────────
+--   期望 1 行(就是上面那行);若出现多行说明库里有两行同 route_name,先查清楚再改。
+--   SELECT count(*) FROM sys_menu WHERE route_name = 'CollectionMerchant';
+--
+--   -- 期望:只列出本目录下的 4 个页面行,其中只有「手工登记商户号」是本次改的
+--   SELECT id, name, type, route_name FROM sys_menu WHERE parent_id = 268 ORDER BY "order";
+--
+-- ── 回滚 ────────────────────────────────────────────────────────────────────
+--   UPDATE sys_menu SET name = '商户映射', title = '商户映射'
+--    WHERE route_name = 'CollectionMerchant' AND type = 2;
+--   ★ 回滚 SQL 与代码不同步:源码里那几处文案已经改成「手工登记商户号」,
+--     只回滚菜单会让提示又指向一个不存在的名字。
+--
+-- ── 生效方式 ────────────────────────────────────────────────────────────────
+-- 菜单树由登录时拉取,改完让操作员**重新登录**(或刷新页面重新拉菜单)即可看到新名字,
+-- 不需要重启后端。