接口实现进度-第3批.md 6.8 KB

第 3 批接口移植报告(权限管理 / 商城地址 / 页面装修 / 内容管理)

更新时间:2026-10-17 工程:java-rewrite/yoshop-java(Spring Boot 3.2.5 + MyBatis-Plus)

一、本批新增接口(21 个)

模块 接口 说明
权限-角色 /store/store.role/add /edit /delete 角色树增删改,菜单权限差集同步 yoshop_store_role_menu
权限-管理员 /store/store.user/add /edit /delete /renew 账号增删改、当前登录人改资料(同步刷新登录态缓存)
商城地址 /store/store.address/add /edit /delete 省市区 cascader 拆成 province/city/region 三列落库
页面装修 /store/page/defaultData /detail /add /edit /delete /setHome 默认组件库、默认值合并、富文本解码、首页唯一性
帮助中心 /store/content.help/add /edit /delete
文章分类 /store/content.article.category/add /edit /delete 删除前校验分类下文章数
文章管理 /store/content.article/detail /add /edit /delete 详情返回 content(实体解码)、image 对象、image_url、show_views

顺带修正的既有行为:/store/store.address/all、/list 之前忽略 type(10 发货 / 20 退货)与 search(收货人 / 电话)筛选参数,已按 PHP Address::getFilter 补齐。

二、关键实现点

1. 统一响应体:成功提示语要放 message

PHP renderSuccess('添加成功') 会把字符串参数当成提示语:

{"status":200,"message":"添加成功","data":[]}

Java 之前写成 R.ok("添加成功"),结果提示语跑进了 data,message 仍是 success——前端 message.success(res.message) 就会弹出 "success"。已新增 R.okMsg(String) 并替换全部写接口,同时把方法返回类型由 R<String> 改为 R<Void>。

2. 页面装修的默认值合并(resetOptions)

page_data 在库里是 JSON 字符串,出参却是「默认值 + 实际值」合并后的对象。PHP 的 resetOptions() 语义有三处容易踩:

  • 键顺序以默认值为准,实际值多出来的键追加在尾部;
  • 两边都是数组时:默认值是关联数组则递归合并,是索引数组(如 data、items)则整体用实际值覆盖;
  • 取值为 null 时回退到默认值(?? 语义)。

已抽到 common/util/PhpArray.reset() 复用。默认组件库(20 种组件)以 PHP getDefaultItems() 的实际输出落成 resources/page/default-data.json,图片地址用 {{BASE}} 占位、运行时替换 yoshop.base-url,避免换域名后图片 404。

3. 口令哈希与 PHP 互认

PHP encryption_hash() = password_hash($pwd, PASSWORD_DEFAULT) → bcrypt cost 10、前缀 $2y$。Java 用 BCrypt.hashpw(..., gensalt(10)) 生成 $2a$,算法一致但与库内历史数据不同构,统一转成 $2y$(common/util/PasswordUtil)。

实测:Java 新增的管理员账号可以直接用 PHP 端 password_verify() 校验通过(反向也成立),因此迁移期两套后端共存不会出现"改了密码另一边登不上"。

4. 关联表的差集同步

管理员-角色、角色-菜单的编辑都走「差集删除 + 差集新增」,而不是先清空再插入——保证关联行 id 稳定,与 PHP UserRole::updates() / RoleMenu::updates() 行为一致。

5. 软删除要显式写 update_time

yoshop_store_user / yoshop_store_address / yoshop_page / yoshop_help / yoshop_article 的 is_delete 是 0/1(不是商品的 10/30)。删除统一用 lambdaUpdate().set(is_delete, 1).set(update_time, now),避免 MyBatis-Plus 的 @TableLogic 在 updateById 时把逻辑删除列一起塞进 SET 造成歧义。

三、校验结果

读接口逐字段对比(30 个,全部 PASS)

  • 第 1、2 批 28 个接口:tools/compare_batch.py → 28/28 PASS,差异 0
  • 本批新增:tools/compare_batch3.py
    • /store/page/defaultData → 0.7 万字符默认组件库,与 PHP 逐字段一致
    • /store/page/detail?pageId=10001 → 合并后的 page_data 逐字段一致(合并算法正确性由此验证)

写接口端到端自测(62 项断言,全部通过)

tools/test_batch3_writes.py(38 项)+ tools/test_content_writes.py(24 项),覆盖:新增 → 落库校验 → 编辑生效 → 删除 → 删除后不可见,以及 8 类异常文案:

场景 期望提示
角色未选菜单 菜单权限不能为空,请重新选择
用户名重复 用户名已存在
两次密码不一致 确认密码不正确
管理员未选角色 请选择所属角色
删除默认首页 默认首页不可以删除
文章缺封面图 请上传封面图
文章缺内容 请输入文章内容
删除被引用的文章分类 该分类下存在 N 个文章,不允许删除

另外校验了:user_name 自动转小写、cascader → province/city/region_id 拆分、地址 full_address 组装、type/search 过滤、页面 page_data 合并、文章详情 content 的 HTML 实体解码、show_views = virtual + actual。

所有测试数据均在脚本末尾清理并复核,库内未残留(备份见 java-rewrite/backup/*.json)。

四、整体进度

按 API清单.csv(store 模块 151 个接口):

  • 已实现 81 个(含 default_data/set_home/move_group 等 ThinkPHP 下划线写法的等价路由)
  • 待实现 约 70 个,集中在:
优先级 模块 接口
高 商品 add / edit / state / delete / basic / list_by_ids、goods.spec/list、goods.comment/*
高 订单 order.event/*(改价、备注、改地址、取消、删除、打印)、order.delivery/*、order.refund/*、order.export/*
高 上传 upload/image、upload/video
中 设置 setting.payment/options+update、payment.template/*、delivery 增删改查、express 增删改、printer 增删改
中 营销 market.coupon add/edit/detail/delete/receive、market.recharge.plan add/edit/delete
中 会员 user.delete、user.grade(改等级)、user.recharge/*、user.grade add/edit/delete
低 统计 statistics.data/initialize+data+survey
低 客户端 client.h5.setting/*、client.wxapp.setting/*

另外 checkPrivilege(API 级权限拦截)仍未实现,上线前必须补:目前只校验登录态,低权限角色会比 PHP 端多访问到接口。

五、复跑方式

cd java-rewrite/tools
python compare_batch.py       # 28 个读接口逐字段对比
python compare_batch3.py     # 页面装修对比
python test_batch3_writes.py  # 权限/地址/页面 写接口自测(自动清理)
python test_content_writes.py # 内容模块写接口自测(自动清理)
python check_progress.py      # 接口实现进度盘点