qmj 1 месяц назад
Родитель
Сommit
445bc85b5d

+ 64 - 0
.claude/skills/add-field/SKILL.md

@@ -0,0 +1,64 @@
+---
+name: add-field
+description: 全栈字段添加技能 — 从实体到前端 i18n 一站式添加新字段
+---
+
+# 全栈字段添加技能
+
+给定字段名称、类型和所属实体,按以下清单依次更新所有层级。
+
+## 输入参数
+
+用户需提供:
+- **字段名**: 如 `tableNo`
+- **类型**: 如 `String`、`Integer`
+- **所属实体**: 如 `PosOrder`
+- **业务说明**: 如 "餐桌号"
+
+## 执行步骤
+
+### 第1步:Java 实体类
+- 找到实体类文件,添加字段声明 + getter/setter
+- 验证:字段在类中存在
+
+### 第2步:MyBatis XML Mapper
+- 更新 `resultMap` 添加新字段映射
+- 更新所有相关的 `select`、`insert`、`update` SQL 语句
+- 验证:grep 确认所有引用该表的 mapper 语句已更新
+
+### 第3步:DTO 类(如适用)
+- 检查是否有对应的 DTO/VO 类需要同步添加字段
+- 验证:DTO 中字段与实体一致
+
+### 第4步:Service 层
+- 检查业务逻辑是否需要处理新字段(默认值、计算逻辑、校验等)
+- 验证:相关 Service 方法已处理新字段
+
+### 第5步:Controller 层
+- 检查 API 接口是否需要返回或接收新字段
+- 验证:相关接口的请求/响应包含新字段
+
+### 第6步:前端 Vue 组件
+- 在相关页面中添加字段展示/编辑
+- **注意:** 前端文件使用 CRLF 换行符,Edit 工具可能失败,优先使用 Python 脚本编辑
+- 验证:Vue 组件中字段可见
+
+### 第7步:i18n 多语言
+- 在所有4个语言文件中添加对应的翻译 key:
+  - `vi.js`(越南语)
+  - `zh.js`(简体中文)
+  - `tw.js`(繁体中文)
+  - `en.js`(英语)
+- **注意:** key 必须添加到正确的嵌套对象内部,使用有意义的英文驼峰命名
+- 验证:grep 确认4个文件中都存在该 key
+
+### 第8步:SQL 迁移脚本
+- 生成 ALTER TABLE 语句添加新列
+- 验证:SQL 语法正确
+
+## 完成检查
+
+最后执行一次全局检查:
+- grep 字段名,确认没有遗漏的引用
+- 确认 i18n key 在4个语言文件中都存在且 key 名一致
+- 确认 mapper XML 中 resultMap 和所有 SQL 语句都已更新

+ 55 - 0
.claude/skills/add-i18n/SKILL.md

@@ -0,0 +1,55 @@
+---
+name: add-i18n
+description: 添加 i18n 多语言 key 到所有4个语言文件
+---
+
+# i18n 多语言 Key 添加技能
+
+将指定的翻译 key 添加到所有4个语言文件中,确保 key 位置正确、命名规范。
+
+## 输入参数
+
+用户需提供:
+- **所属对象**: 如 `foots`、`cuxiao`、`fenlei`(对应 `$t('对象名.key名')` 中的对象名)
+- **key 列表**: 每个语言的翻译内容,格式如下:
+  ```
+  keyName: zh=简体中文 en=English tw=繁體中文 vi=Tiếng Việt
+  ```
+
+## 执行步骤
+
+### 第1步:读取语言文件
+- 读取所有4个语言文件:`vi.js`、`zh.js`、`tw.js`、`en.js`
+- 语言文件路径:
+  - 商家端(foodie-store): `E:\QtwCode\foodie\foodie-store\src\lang\`
+  - 平台管理端(foodie-admin-vue): 需确认路径
+
+### 第2步:定位目标对象
+- 在每个文件中找到用户指定的嵌套对象(如 `foots: {`)
+- 定位该对象的最后一个属性
+- **关键:** key 必须添加到该对象**内部**,不能加到文件顶部或其他对象中
+
+### 第3步:添加 key
+- **前端文件使用 CRLF 换行符**,Edit 工具可能失败,优先使用 Python 脚本:
+  ```python
+  python << 'PYEOF'
+  import pathlib
+  for lang, value in [('zh', '值'), ('tw', '值'), ('en', 'value'), ('vi', 'value')]:
+      f = pathlib.Path(f'path/to/{lang}.js')
+      content = f.read_text(encoding='utf-8')
+      # 在目标对象的最后一个属性后插入新 key
+      content = content.replace(old_tail, new_tail_with_key)
+      f.write_text(content, encoding='utf-8')
+  PYEOF
+  ```
+
+### 第4步:验证
+- grep 确认每个 key 在所有4个文件中都存在
+- 确认4个文件中的 key 名称完全一致
+- 确认 key 在正确的嵌套对象内部
+
+## 命名规范
+
+- 使用**有意义的英文驼峰命名**
+- 禁止使用 `text1`、`text2`、`text55` 等无意义序号
+- 示例:按钮用 `orderBtn`,标题用 `orderDialogTitle`,状态用 `diningStatus`

+ 2 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/UserOrderController.java

@@ -164,6 +164,8 @@ public class UserOrderController extends BaseController {
             posOrder.setShdzId(input.getShdzId());
             posOrder.setShAddress(shdz);
             posOrder.setFoodAmount(item.getFoodAmount());
+            posOrder.setPickUpTime(input.getPickUpTime());
+            posOrder.setReservePhone(input.getReservePhone());
            Optional<PosStore> storeOptional = storeList.stream()
                    .filter(x -> item.getMdId().equals(Long.valueOf(x.getId())))
                    .findFirst();

+ 5 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/dto/OrderCreateInput.java

@@ -42,5 +42,10 @@ public class OrderCreateInput {
     /** 整单备注 */
     private String remarks;
 
+    /** 自取时间 */
+    private String pickUpTime;
+    /** 自取预留电话 */
+    private String reservePhone;
+
     private List<OrderCreatItem> items;
 }

+ 2 - 3
ruoyi-system/src/main/java/com/ruoyi/system/domain/PosOrder.java

@@ -307,9 +307,8 @@ public class PosOrder {
     /** 取餐号 */
     private Long pickUpNum;
     /** 自取时间 */
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private Date pickUpTime;
-    /** 预留电话 */
+    private String pickUpTime;
+    /** 自取预留电话 */
     private String reservePhone;
     /** 商家是否已接单 */
     private Boolean isAccepted;

+ 3 - 3
ruoyi-system/src/main/resources/mapper/system/PosOrderMapper.xml

@@ -181,7 +181,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="posName != null and posName != ''">pos_name,</if>
             <if test="foodAmount != null">food_amount,</if>
             <if test="pickUpNum != null">pick_up_num,</if>
-            <if test="pickUpTime != null">pick_up_time,</if>
+            <if test="pickUpTime != null and pickUpTime != ''">pick_up_time,</if>
             <if test="reservePhone != null and reservePhone != ''">reserve_phone,</if>
             <if test="isAccepted != null">is_accepted,</if>
             <if test="isDisplay != null">is_display,</if>
@@ -221,7 +221,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="posName != null and posName != ''">#{posName},</if>
             <if test="foodAmount != null">#{foodAmount},</if>
             <if test="pickUpNum != null">#{pickUpNum},</if>
-            <if test="pickUpTime != null">#{pickUpTime},</if>
+            <if test="pickUpTime != null and pickUpTime != ''">#{pickUpTime},</if>
             <if test="reservePhone != null and reservePhone != ''">#{reservePhone},</if>
             <if test="isAccepted != null">#{isAccepted},</if>
             <if test="isDisplay != null">#{isDisplay},</if>
@@ -267,7 +267,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="posName != null and posName != ''">pos_name = #{posName},</if>
             <if test="foodAmount != null">food_amount = #{foodAmount},</if>
             <if test="pickUpNum != null">pick_up_num = #{pickUpNum},</if>
-            <if test="pickUpTime != null">pick_up_time = #{pickUpTime},</if>
+            <if test="pickUpTime != null and pickUpTime != ''">pick_up_time = #{pickUpTime},</if>
             <if test="reservePhone != null and reservePhone != ''">reserve_phone = #{reservePhone},</if>
             <if test="isAccepted != null">is_accepted = #{isAccepted},</if>
             <if test="isDisplay != null">is_display = #{isDisplay},</if>