CLAUDE.md 12 KB

foodie_server Development Guidelines

Auto-generated from all feature plans. Last updated: 2026-05-15

Tech Stack

  • 后端: Java (Spring Boot, MyBatis with XML mappers)
  • 前端: Vue.js (Element UI)
  • 支持语言: Vietnamese (vi), Simplified Chinese (zh), Traditional Chinese (tw), English (en)
  • 数据库: MySQL
  • 开发环境: Windows

Project Structure

平台管理前端代码路径:E:\QtwCode\foodie\foodie-admin-vue
商家端管理前端代码路径:E:\QtwCode\foodie\foodie-store

已废弃代码清单(订单/支付,勿作为改动基准)

以下代码仍存在于仓库中但已废弃,排查问题或新增功能时不要参考其逻辑、不要在其上做增量改动,否则会改到死代码:

文件 状态 备注
ZaloPayController.java 整体废弃 ZaloPay 支付已下线
PayController.java VNPay 回调及多数方法废弃 特例sendAcceptRiderPush(...) 仍被 PosOrderController 货到付款路径与 NewebpayPayController(未启用)引用;迁移推迟到接入新支付时
TestTask.java 定时任务全部废弃 含 refundProcessing / 抽成返还 / 自动开店 / 超时退款;相关推送当前均不存在
OrderAppealController.java 取消/申诉整片注释 仅留 parseLocale;取消/申诉推送全部失效

当前在用的订单操作入口(状态流转/推送以此为准):

  • PosOrderShOprateController — 商家操作(出餐 chuCan、商家取消)
  • PosOrderQsOprateController — 骑手操作(接单/取餐/送达,按 deliveryStatus 1/2/3)
  • UserOrderController — 用户操作(下单、用户取消)
  • NewebpayPayController — 蓝新金流支付,代码就绪但尚未启用;支付链路含 sendAcceptRiderPush 迁移,等接入新支付时再做
  • PosOrderController — 仅 /addorder(下单,含货到付款 sendHdfkMessage)、/setorderuzt(平台改状态)及 list 查询在用;订单状态流转已迁出

推送通道: PayPush 无 Android FCM(cte_server 有,本项目砍掉),仅 iOS uni 云函数(msduser/msdrider/msdstore)+ 入库(PushEventpush_message);cidType 形同虚设(到处传 "")。详见 specs/012-im-user-integration/code-status.md

前端多语言(i18n)添加规范

所有前端新功能必须实现多语言,不例外。 平台管理端(foodie-admin-vue)和商家端(foodie-store) 新增的任何面向用户的文字都必须使用 $t() 而非硬编码中文。

商家端(foodie-store)使用 vue-i18n,语言文件在 src/lang/ 下(zh.js、tw.js、en.js、vi.js)。

添加多语言 key 时必须注意:

  1. 先确认 key 所属的对象层级。 语言文件中有多层嵌套对象(如 foots:{}cuxiao:{}fenlei:{} 等),使用 $t('foots.XXX') 的 key 必须添加到 foots 对象内部,不能加到文件顶部或其它对象里。
  2. 找到该对象的最后一个属性(通过 grep 或阅读文件定位),在其后追加新 key,确保逗号正确(中间属性末尾要有逗号,最后一个属性无逗号)。
  3. 四个语言文件(zh.js、tw.js、en.js、vi.js)都要添加,缺一不可。
  4. key 必须使用有意义的英文单词(驼峰命名),禁止使用 text1text2text55 等无意义序号。例如:按钮用 orderBtn,标题用 orderDialogTitle,状态用 diningStatus。四个语言文件的 key 名称必须完全一致。

曾经犯的错误:AddCategoryFirst 加到了文件第 141 行的公共区域,而 $t('foots.AddCategoryFirst') 是在 foots 对象(第 190+ 行)下查找,导致页面显示原始 key 而非翻译文本。

前端文件编辑注意事项

前端项目(foodie-store、foodie-admin-vue)的文件使用 CRLF 换行符(Windows 风格 \r\n)。使用编辑工具进行字符串替换时,由于换行符不匹配会导致 "String to replace not found" 错误。

正确做法: 编辑前端文件时,使用 Python 脚本(python << 'PYEOF')通过 content.replace() 或行号操作来修改文件内容,避免换行符匹配问题。

数据库变更管理

所有数据库变更(ALTER TABLE、数据迁移等)不直接执行,必须写入 updatesql/sql.md 文件。由开发者统一到数据库手动执行。SQL 语句需标注日期和用途注释,例如:

-- 2026-05-15 订单状态四字段分离
ALTER TABLE pos_order ADD COLUMN delivery_status BIGINT DEFAULT NULL COMMENT '配送状态';

全栈字段添加清单

添加新字段到实体时,必须按顺序更新以下所有层级:

  1. Java 实体类(Entity)
  2. MyBatis XML mapper(resultMap + 相关的 select/insert/update 语句)
  3. DTO 类(如适用)
  4. Service 层业务逻辑
  5. Controller 层接口
  6. 前端 Vue 组件
  7. 四个 i18n 语言文件(vi.js、zh.js、tw.js、en.js)
  8. SQL 迁移脚本

商家类型与订单查询逻辑

InfoUser.userType 区分不同商家角色,查询订单时必须按类型使用不同字段过滤:

userType 角色 订单过滤条件
1 普通商家 PosOrder.shId = userId
3 夜市商家 PosOrder.shId = userId
其他 摊位商家 PosOrder.mdId = InfoUser.storeId(从用户表查关联的摊位门店ID)

关键字段:

  • InfoUser.userType:0=普通用户, 1=商家, 2=骑手, 3=夜市
  • InfoUser.storeId:摊位商家关联的摊位门店ID
  • PosOrder.shId:商家ID(普通/夜市商家直接等于userId)
  • PosOrder.mdId:门店ID(摊位商家用 InfoUser.storeId 匹配)

范围控制

当用户说"只改 X"时,就只改 X——不要广泛探索、创建任务或为简单的定向修改启动 Agent。从用户提到的具体文件或区域开始,做最小的必要修改。

对于简单的格式化或显示变更(如截断小数、重命名 key、单文件修改),不要创建任务计划或启动 Agent,直接做编辑。

Controller 请求参数规范

创建或修改任何 Spring Controller 时,必须遵守以下规则:

  1. 需要登录 token 的接口必须直接声明 @RequestHeader String token,禁止通过 HttpServletRequest 读取 token,也不得仅为读取 token 而注入 HttpServletRequest
  2. POST 接口接收业务参数时,必须使用类型明确的 DTO,并在参数前显式添加 @RequestBody,例如 @RequestBody OrderDTO orderDTO;禁止使用未标注注解的隐式绑定。
  3. GET 接口接收查询参数时,每个查询参数必须显式添加 @RequestParam,例如 @RequestParam Integer page;token 仍使用 @RequestHeader,URL 路径变量仍使用 @PathVariable
  4. 禁止使用 Map<String, String>(或其它 Map)作为请求处理方法的入参。
  5. 第三方 form-urlencoded 回调同样使用 DTO(例如 @ModelAttribute)接收;如签名 SDK 必须使用 Map,只允许在 Controller 边界之后由 DTO 转换为内部 Map,不得把 Map 暴露为接口入参。
  6. DTO 只用于承载请求数据,禁止在 DTO 字段上使用 @NotNull@NotBlank@Size 等 Bean Validation 注解,也不要依赖 Controller 参数上的 @Valid / @Validated 返回校验错误。业务参数校验必须放在 Controller 或 Service 中,并通过 MessageUtils.message(...) 等项目国际化机制返回错误信息,禁止硬编码仅支持单一语言的校验消息。

后端构建与模块边界

  1. 本项目 Maven 编译目标为 JDK 21。当前机器执行构建时使用 C:\Users\qmj\.jdks\graalvm-jdk-21.0.7,只在当前命令环境临时设置 JAVA_HOMEPATH,不要修改用户的全局 Java 配置。
  2. 模块依赖方向为 ruoyi-admin -> ruoyi-system,禁止 ruoyi-system 反向依赖或导入 com.ruoyi.app.*
  3. 同时依赖外部 HTTP(项目使用 httpclient4 + fastjson2)与应用层 Service 的集成代码应放在 ruoyi-admin,不要放入 ruoyi-system
  4. 后端 Java/XML/YAML 与前端文件均可能使用 CRLF;编辑时保留原换行风格,禁止因小改动格式化或重写整个文件。

spec-kit 工作流

  1. 用户提到 spec kitspec-kitspeckit 时,指 GitHub github/spec-kit,项目配置位于 .specify/,规格位于 specs/
  2. 新功能默认按 specify -> plan -> tasks -> implement 流程进行。
  3. 已有功能追加或变更需求时,直接更新现有 spec.mdplan.mdtasks.md 并顺延任务,不重新启动完整 spec-kit 流程,除非用户明确要求。

Java 注释安全

Java 块注释或 Javadoc 的正文中禁止出现额外的 */ 字符序列。描述 ATM_*CVS_* 等通配值时,改写为“ATM 系列”“CVS 系列”,避免提前关闭注释导致编译失败。

餐桌码适用范围

餐桌码功能必须覆盖普通商家,不得仅按夜市摊主或夜市管理员设计权限。普通商家也可以查看自己门店的餐桌码及其关联订单。

CLAUDE.md

Behavioral guidelines to reduce common LLM coding mistakes. Merge with project-specific instructions as needed.

Tradeoff: These guidelines bias toward caution over speed. For trivial tasks, use judgment.

1. Think Before Coding

Don't assume. Don't hide confusion. Surface tradeoffs.

Before implementing:

  • State your assumptions explicitly. If uncertain, ask.
  • If multiple interpretations exist, present them - don't pick silently.
  • If a simpler approach exists, say so. Push back when warranted.
  • If something is unclear, stop. Name what's confusing. Ask.

2. Simplicity First

Minimum code that solves the problem. Nothing speculative.

  • No features beyond what was asked.
  • No abstractions for single-use code.
  • No "flexibility" or "configurability" that wasn't requested.
  • No error handling for impossible scenarios.
  • If you write 200 lines and it could be 50, rewrite it.

Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.

3. Surgical Changes

Touch only what you must. Clean up only your own mess.

When editing existing code:

  • Don't "improve" adjacent code, comments, or formatting.
  • Don't refactor things that aren't broken.
  • Match existing style, even if you'd do it differently.
  • If you notice unrelated dead code, mention it - don't delete it.

When your changes create orphans:

  • Remove imports/variables/functions that YOUR changes made unused.
  • Don't remove pre-existing dead code unless asked.

The test: Every changed line should trace directly to the user's request.

4. Goal-Driven Execution

Define success criteria. Loop until verified.

Transform tasks into verifiable goals:

  • "Add validation" → "Write tests for invalid inputs, then make them pass"
  • "Fix the bug" → "Write a test that reproduces it, then make it pass"
  • "Refactor X" → "Ensure tests pass before and after"

For multi-step tasks, state a brief plan:

1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]

Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.


These guidelines are working if: fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes.

For additional context about technologies to be used, project structure, shell commands, and other important information, read the current plan: specs/016-omg-payment/plan.md