|
|
@@ -0,0 +1,341 @@
|
|
|
+# 餐桌码查看关联订单 Implementation Plan
|
|
|
+
|
|
|
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
+
|
|
|
+**Goal:** 在商家端餐桌码管理页面增加「订单」按钮,点击后弹窗展示该餐桌关联的所有订单列表。
|
|
|
+
|
|
|
+**Architecture:** 后端在 TableQrcodeController 新增 `getTableOrders` 接口,通过 tableId 查询 pos_order 表;前端在 TableQRCode.vue 操作列新增按钮和订单弹窗。权限复用现有 verifyOwnership 模式。
|
|
|
+
|
|
|
+**Tech Stack:** Java 21 / Spring Boot / MyBatis Plus / Vue 2 + Element UI
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## File Structure
|
|
|
+
|
|
|
+| File | Action | Responsibility |
|
|
|
+|------|--------|---------------|
|
|
|
+| `ruoyi-admin/src/main/java/com/ruoyi/app/tableqrcode/TableQrcodeController.java` | Modify | 新增 getTableOrders 接口 |
|
|
|
+| `foodie-store/src/api/tableQrcode.js` | Modify | 新增 getTableOrders API 方法 |
|
|
|
+| `foodie-store/src/views/TableQRCode.vue` | Modify | 新增订单按钮和订单弹窗 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 1: 后端 — 新增 getTableOrders 接口
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Modify: `ruoyi-admin/src/main/java/com/ruoyi/app/tableqrcode/TableQrcodeController.java`
|
|
|
+
|
|
|
+- [ ] **Step 1: 添加新的 import 语句**
|
|
|
+
|
|
|
+在 `TableQrcodeController.java` 文件顶部的 import 区域,添加 PosOrder 和 PosOrderService 相关的 import:
|
|
|
+
|
|
|
+```java
|
|
|
+import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import com.ruoyi.system.domain.PosOrder;
|
|
|
+import com.ruoyi.system.service.IPosOrderService;
|
|
|
+```
|
|
|
+
|
|
|
+注意:`IPage` 和 `Page` 需要检查是否与已有 import 冲突。文件中没有这些 import,直接添加即可。
|
|
|
+
|
|
|
+- [ ] **Step 2: 注入 PosOrderService**
|
|
|
+
|
|
|
+在已有的 `@Autowired private IPosStoreService posStoreService;` 之后添加:
|
|
|
+
|
|
|
+```java
|
|
|
+@Autowired
|
|
|
+private IPosOrderService posOrderService;
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 3: 添加 getTableOrders 方法**
|
|
|
+
|
|
|
+在 `getQrcodeImage` 方法之前(约第 366 行),添加以下方法:
|
|
|
+
|
|
|
+```java
|
|
|
+/**
|
|
|
+ * 查看餐桌关联订单
|
|
|
+ */
|
|
|
+@Anonymous
|
|
|
+@Auth
|
|
|
+@GetMapping("/getTableOrders")
|
|
|
+public AjaxResult getTableOrders(@RequestHeader String token,
|
|
|
+ @RequestParam Long id,
|
|
|
+ @RequestParam(defaultValue = "1") Integer page,
|
|
|
+ @RequestParam(defaultValue = "10") Integer size,
|
|
|
+ @RequestParam(required = false) String state)
|
|
|
+{
|
|
|
+ if (!verifyOwnership(token, id))
|
|
|
+ {
|
|
|
+ return error("无权访问");
|
|
|
+ }
|
|
|
+ TableQrcode tableQrcode = tableQrcodeService.selectTableQrcodeById(id);
|
|
|
+ if (tableQrcode == null)
|
|
|
+ {
|
|
|
+ return error("餐桌码不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ IPage<PosOrder> pageParam = new Page<>(page, size);
|
|
|
+ QueryWrapper<PosOrder> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.eq("table_id", id).orderByDesc("cretim");
|
|
|
+ if (state != null && !state.isEmpty())
|
|
|
+ {
|
|
|
+ if (state.equals("z01"))
|
|
|
+ {
|
|
|
+ queryWrapper.apply("((state = 0 AND (collect_payment = 1 OR type = 1)) OR (state = 1))");
|
|
|
+ }
|
|
|
+ else if (state.equals("z234"))
|
|
|
+ {
|
|
|
+ queryWrapper.in("state", 2, 3, 4);
|
|
|
+ }
|
|
|
+ else if (state.equals("z23"))
|
|
|
+ {
|
|
|
+ queryWrapper.in("state", 2, 3);
|
|
|
+ }
|
|
|
+ else if (state.equals("z34"))
|
|
|
+ {
|
|
|
+ queryWrapper.in("state", 3, 4);
|
|
|
+ }
|
|
|
+ else if (state.equals("z678911"))
|
|
|
+ {
|
|
|
+ queryWrapper.in("state", 6, 7, 8, 9, 11);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ queryWrapper.eq("state", state);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ IPage<PosOrder> result = posOrderService.page(pageParam, queryWrapper);
|
|
|
+ return success(result);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+还需要在 import 区域添加 `QueryWrapper`(如果还没有的话):
|
|
|
+
|
|
|
+```java
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+```
|
|
|
+
|
|
|
+注意:检查文件顶部是否已有 `LambdaQueryWrapper` 的 import — 如果有,`QueryWrapper` 在同一个包下,只需额外添加这一行。
|
|
|
+
|
|
|
+- [ ] **Step 4: 编译验证**
|
|
|
+
|
|
|
+Run: `cd E:/QtwCode/foodie/foodie_server && mvn compile -pl ruoyi-admin -am -q`
|
|
|
+Expected: BUILD SUCCESS
|
|
|
+
|
|
|
+- [ ] **Step 5: Commit**
|
|
|
+
|
|
|
+```bash
|
|
|
+git add ruoyi-admin/src/main/java/com/ruoyi/app/tableqrcode/TableQrcodeController.java
|
|
|
+git commit -m "feat: 添加餐桌码关联订单查询接口 GET /table-qrcode/getTableOrders"
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 2: 前端 — API 模块新增 getTableOrders
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Modify: `foodie-store/src/api/tableQrcode.js`
|
|
|
+
|
|
|
+- [ ] **Step 1: 添加 getTableOrders 方法**
|
|
|
+
|
|
|
+在 `tableQrcode.js` 文件末尾(`getQrcodeImage` 函数之后)添加:
|
|
|
+
|
|
|
+```javascript
|
|
|
+// 查看餐桌关联订单
|
|
|
+export function getTableOrders(params) {
|
|
|
+ return request({
|
|
|
+ url: '/table-qrcode/getTableOrders',
|
|
|
+ method: 'get',
|
|
|
+ headers: { isToken: true },
|
|
|
+ params
|
|
|
+ })
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: Commit**
|
|
|
+
|
|
|
+```bash
|
|
|
+git add foodie-store/src/api/tableQrcode.js
|
|
|
+git commit -m "feat: 前端API模块添加 getTableOrders 方法"
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 3: 前端 — TableQRCode.vue 新增订单按钮和弹窗
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Modify: `foodie-store/src/views/TableQRCode.vue`
|
|
|
+
|
|
|
+由于前端文件使用 CRLF 换行符,**必须使用 Python 脚本进行编辑**,不能用 Edit 工具直接替换。
|
|
|
+
|
|
|
+- [ ] **Step 1: 在 import 行添加 getTableOrders**
|
|
|
+
|
|
|
+当前第 134 行:
|
|
|
+```javascript
|
|
|
+import { getTableQrcodeList, addTableQrcode, updateTableQrcode, deleteTableQrcode, changeTableQrcodeStatus, getQrcodeImage } from '@/api/tableQrcode'
|
|
|
+```
|
|
|
+
|
|
|
+改为:
|
|
|
+```javascript
|
|
|
+import { getTableQrcodeList, addTableQrcode, updateTableQrcode, deleteTableQrcode, changeTableQrcodeStatus, getQrcodeImage, getTableOrders } from '@/api/tableQrcode'
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: 在操作列添加「订单」按钮**
|
|
|
+
|
|
|
+在模板第 69 行的「查看二维码」按钮之前,添加订单按钮:
|
|
|
+
|
|
|
+当前代码(第 68-73 行):
|
|
|
+```html
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-button @click="handleViewQrcode(scope.row)" type="text" size="small">查看二维码</el-button>
|
|
|
+ <el-button @click="handleEdit(scope.row)" type="text" size="small">编辑</el-button>
|
|
|
+ <el-button @click="handleDelete(scope.row)" type="text" size="small" style="color: red;">删除</el-button>
|
|
|
+ </template>
|
|
|
+```
|
|
|
+
|
|
|
+改为:
|
|
|
+```html
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-button @click="handleViewOrders(scope.row)" type="text" size="small">订单</el-button>
|
|
|
+ <el-button @click="handleViewQrcode(scope.row)" type="text" size="small">查看二维码</el-button>
|
|
|
+ <el-button @click="handleEdit(scope.row)" type="text" size="small">编辑</el-button>
|
|
|
+ <el-button @click="handleDelete(scope.row)" type="text" size="small" style="color: red;">删除</el-button>
|
|
|
+ </template>
|
|
|
+```
|
|
|
+
|
|
|
+同时将操作列宽度从 `width="220"` 改为 `width="280"` 以容纳新按钮。
|
|
|
+
|
|
|
+- [ ] **Step 3: 添加订单弹窗模板**
|
|
|
+
|
|
|
+在二维码查看弹窗(第 119-130 行)的 `</el-dialog>` 之后、`</div>` 之前(第 130 行后),添加:
|
|
|
+
|
|
|
+```html
|
|
|
+
|
|
|
+ <!-- 订单查看弹窗 -->
|
|
|
+ <el-dialog :title="'餐桌订单 - ' + orderDialogTableNo" :visible.sync="orderDialogVisible" width="800px" append-to-body>
|
|
|
+ <el-form :inline="true" style="margin-bottom: 15px;">
|
|
|
+ <el-form-item label="订单状态">
|
|
|
+ <el-select v-model="orderQueryState" placeholder="全部" clearable size="small" @change="loadOrders">
|
|
|
+ <el-option label="待处理" value="z01"></el-option>
|
|
|
+ <el-option label="进行中" value="z234"></el-option>
|
|
|
+ <el-option label="已完成" value="z678911"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <el-table v-loading="orderLoading" :data="orderList" :header-cell-style="{ background: '#f0f0f0' }" max-height="400">
|
|
|
+ <el-table-column prop="ddId" label="订单号" width="180"></el-table-column>
|
|
|
+ <el-table-column prop="amount" label="金额" width="100"></el-table-column>
|
|
|
+ <el-table-column prop="state" label="订单状态" width="100">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-tag :type="orderStateTagType(scope.row.state)" size="small">{{ orderStateText(scope.row.state) }}</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="diningStatus" label="出餐状态" width="100">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-tag :type="scope.row.diningStatus === 1 ? 'success' : 'info'" size="small">
|
|
|
+ {{ scope.row.diningStatus === 1 ? '已出餐' : '未出餐' }}
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="cretim" label="下单时间" width="180"></el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <el-pagination
|
|
|
+ v-if="orderTotal > 0"
|
|
|
+ :current-page.sync="orderPage"
|
|
|
+ :page-size="10"
|
|
|
+ :total="orderTotal"
|
|
|
+ layout="total, prev, pager, next"
|
|
|
+ @current-change="loadOrders"
|
|
|
+ style="margin-top: 15px; text-align: right;">
|
|
|
+ </el-pagination>
|
|
|
+ </el-dialog>
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 4: 添加 data 属性**
|
|
|
+
|
|
|
+在 data() 的 `currentRow: {}` 之后添加:
|
|
|
+
|
|
|
+```javascript
|
|
|
+ orderDialogVisible: false,
|
|
|
+ orderDialogTableNo: '',
|
|
|
+ orderDialogTableId: null,
|
|
|
+ orderLoading: false,
|
|
|
+ orderList: [],
|
|
|
+ orderTotal: 0,
|
|
|
+ orderPage: 1,
|
|
|
+ orderQueryState: ''
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 5: 添加 methods**
|
|
|
+
|
|
|
+在 `downloadQrcode` 方法之后,`methods` 闭合 `}` 之前,添加以下方法:
|
|
|
+
|
|
|
+```javascript
|
|
|
+ handleViewOrders(row) {
|
|
|
+ this.orderDialogTableNo = row.tableNo
|
|
|
+ this.orderDialogTableId = row.id
|
|
|
+ this.orderPage = 1
|
|
|
+ this.orderQueryState = ''
|
|
|
+ this.orderDialogVisible = true
|
|
|
+ this.loadOrders()
|
|
|
+ },
|
|
|
+ loadOrders() {
|
|
|
+ this.orderLoading = true
|
|
|
+ const params = { id: this.orderDialogTableId, page: this.orderPage, size: 10 }
|
|
|
+ if (this.orderQueryState) {
|
|
|
+ params.state = this.orderQueryState
|
|
|
+ }
|
|
|
+ getTableOrders(params).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ const data = res.data
|
|
|
+ this.orderList = data.records || []
|
|
|
+ this.orderTotal = data.total || 0
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.msg || '获取订单失败')
|
|
|
+ }
|
|
|
+ this.orderLoading = false
|
|
|
+ }).catch(() => {
|
|
|
+ this.$message.error('获取订单失败')
|
|
|
+ this.orderLoading = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ orderStateText(state) {
|
|
|
+ const map = { 0: '待处理', 1: '已付款', 2: '已接单', 3: '配送中', 4: '已送达', 6: '已取消', 7: '退款中', 8: '已退款', 9: '退款拒绝', 11: '已评价' }
|
|
|
+ return map[state] || '未知'
|
|
|
+ },
|
|
|
+ orderStateTagType(state) {
|
|
|
+ if (state === 0 || state === 1) return 'warning'
|
|
|
+ if (state === 2 || state === 3) return ''
|
|
|
+ if (state === 4) return 'success'
|
|
|
+ if (state === 6 || state === 7 || state === 8) return 'danger'
|
|
|
+ return 'info'
|
|
|
+ }
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 6: 验证前端编译**
|
|
|
+
|
|
|
+Run: `cd E:/QtwCode/foodie/foodie-store && npm run build`
|
|
|
+Expected: 编译成功无报错
|
|
|
+
|
|
|
+- [ ] **Step 7: Commit**
|
|
|
+
|
|
|
+```bash
|
|
|
+git add foodie-store/src/views/TableQRCode.vue
|
|
|
+git commit -m "feat: 餐桌码管理页面新增查看关联订单功能"
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Spec Coverage Check
|
|
|
+
|
|
|
+| Spec 需求 | 对应 Task |
|
|
|
+|-----------|----------|
|
|
|
+| GET /table-qrcode/getTableOrders 接口 | Task 1 |
|
|
|
+| 权限校验(userType 1/3/4) | Task 1(复用 verifyOwnership) |
|
|
|
+| 按 tableId 查询订单,支持分页和状态筛选 | Task 1 |
|
|
|
+| 前端 API 模块 | Task 2 |
|
|
|
+| 操作列「订单」按钮 | Task 3 |
|
|
|
+| 订单弹窗(订单号、金额、状态、出餐状态、时间) | Task 3 |
|
|
|
+| 订单状态筛选下拉 | Task 3 |
|
|
|
+| 分页 | Task 3 |
|