对照基准:线上 PHP 站点
https://shop.qinys.cn(同一套库、同一份数据) 校验方式:逐个接口抓 PHP 黄金样本 → Java 同参数请求 → 递归逐字段 diff(tools/compare_batch.py) 最近一次运行:28 个接口全部 PASS,0 差异
/store/store/info 报 500根因:该路由此前没有实现。Spring 找不到处理器时抛 NoResourceFoundException,被全局异常兜底成
{"status":500,"message":"服务器内部错误"},前端只看到 500,无法判断是"没实现"还是"真报错"。
修复:
StoreController(/store/store/info、/store/store/update),出参与 PHP Store::info 一致:
{"storeInfo":{...,"logoImage":null}}。GlobalExceptionHandler 增加 NoResourceFoundException 专门处理,未实现的路由现在返回
{"status":500,"message":"接口未实现:/store/xxx/yyy"},一眼能定位。注意路由规则:PHP 的 URL 是「模块 + 控制器 + 方法」,所以前端
api/store/store/info对应 Java 的/store/store/info(第一个store是模块,第二个是控制器Store.php); 多级控制器写成点号,如/store/goods.service/list、/store/store.menu/list。
| 接口 | 说明 |
|---|---|
GET /store/store/info |
商城信息(含 logoImage) |
POST /store/store/update |
更新商城信息 |
GET /store/store.menu/list |
后台菜单树(含 menuApi / apiIds,过滤空操作菜单) |
GET /store/store.role/list |
角色树(含 roleMenu / menuIds) |
GET /store/store.user/list |
管理员列表(含 role / roleIds) |
GET /store/category/list |
商品分类树(含 image / children) |
POST /store/category/add\|edit\|delete |
分类增删改(含"上级不能设为自己子级""被商品引用不能删"校验) |
GET /store/goods.service/list\|all |
商品服务(保障服务) |
POST /store/goods.service/add\|edit\|delete |
商品服务增删改(软删除) |
GET /store/files/list |
文件库列表(类型/分组/来源/回收站筛选,15 条分页) |
GET /store/files.group/list |
文件分组树 |
POST /store/files.group/add\|edit\|delete |
分组增删改(删组时文件归还"未分组") |
POST /store/files/edit\|delete\|moveGroup |
文件改名/批量删除(≤15)/移动分组 |
GET /store/region/all |
全部地区(约 240KB,key 为地区 ID) |
GET /store/region/tree |
地区树(省→city→region) |
GET /store/user/list |
会员列表(昵称/手机号/性别/等级/注册时间筛选) |
GET /store/user.grade/all\|list |
会员等级(upgrade / equity 由 JSON 串转对象) |
GET /store/order/list?dataType= |
订单列表(paginate(10),7 种 dataType,6 种关键词检索) |
GET /store/order/detail |
订单详情(goods / user / address / trade) |
GET /store/setting/detail |
设置项(无该项时 values: []) |
POST /store/setting/update |
更新设置项 |
GET /store/setting.cache/items |
缓存清理项 |
GET /store/setting.delivery/all\|list |
配送模板 |
GET /store/setting.express/all\|list |
物流公司 |
GET /store/setting.printer/all\|list |
打印机 |
GET /store/store.address/all\|list |
商城地址(cascader / region / full_address) |
GET /store/page/list |
页面列表(不含 page_data 长文本) |
GET /store/content.article/list |
文章列表(不含 content,含 image / category) |
GET /store/content.article.category/list |
文章分类 |
GET /store/content.help/list |
帮助列表 |
GET /store/market.coupon/list |
优惠券列表 |
GET /store/market.points/log |
积分明细(含会员) |
GET /store/market.recharge.plan/list |
充值套餐 |
GET /store/user.balance/log |
余额明细(含会员) |
| 现象 | 处理 |
|---|---|
PHP 关联字段名是 camelCase(logoImage、menuApi、roleMenu、menuIds、roleIds、apiIds) |
Jackson 全局 SNAKE_CASE 会把它们变成 logo_image,逐个加 @JsonProperty("xxxYyy") |
菜单无 api 绑定时 PHP 输出 "apiIds": []、"menuApi": [] |
关联设为空 List,不用 null |
订单 update_price 是对象 {symbol,value} |
用 getUpdatePriceVo() 组对象 |
订单 pay_time/delivery_time/receipt_time 为 0 时输出 "" |
TimeUtil.formatOrBlank()(对齐 PHP format_time()) |
订单 order_source_data 库内是 json 串,出参是数组 |
出参时 JSON 解析,空串返回 [] |
订单/流水里的 user 只 with 了 avatar,没有 grade 键 |
UserLiteSerializer 序列化后剔除 grade |
订单商品 content 列表不返回 |
查询排除 + @JsonInclude(NON_NULL) |
yoshop_store_setting 主键是字符串 key |
@TableId(value="key", IdType.INPUT),更新走条件更新 |
按页面优先级排序:
goods/add、goods/edit、goods/delete、goods/state、goods/basic、goods/list_by_idsorder.event/*(确认取消、改价、改地址、备注、打印)、order.refund/*、order.delivery/*upload/image、upload/video(需要落盘 + 写 yoshop_upload_file)setting.payment/options、setting.payment.template/*statistics.data/survey、statistics.data/initializecheckPrivilege()(按角色校验 store_api),当前只校验登录态# 后端
cd F:\shop\java-rewrite\yoshop-java
mvn spring-boot:run -Dspring-boot.run.arguments="--server.port=18080 --yoshop.auth.mode=file --yoshop.auth.runtime-cache-path=F:/shop/java-rewrite/runtime/cache"
# 前端
cd F:\shop\yoshop2.0-store
NODE_OPTIONS=--openssl-legacy-provider ./node_modules/.bin/vue-cli-service serve # 8120
# 回归对比(需本地 Java 服务 + golden 样本)
cd F:\shop\java-rewrite\tools
python compare_batch.py
本机有系统代理(
HTTP_PROXY=127.0.0.1:xxx),会让127.0.0.1也走代理并返回 502, 联调脚本里已用trust_env = False;手工 curl 记得加--noproxy '*'。