diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 7d976d8..2714c8b 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -2,7 +2,8 @@ "permissions": { "allow": [ "Bash(mkdir:*)", - "Bash(tree -L 3 -I 'node_modules|dist')" + "Bash(tree -L 3 -I 'node_modules|dist')", + "Bash(cat:*)" ], "deny": [], "ask": [] diff --git a/src/common/apis/manage/ManageGoodsController接口文档.md b/src/common/apis/manage/ManageGoodsController接口文档.md new file mode 100644 index 0000000..a7dfab7 --- /dev/null +++ b/src/common/apis/manage/ManageGoodsController接口文档.md @@ -0,0 +1,295 @@ +# ManageGoodsController 接口文档 + +## 控制器概述 + +**基础路径:** `/api/manage/goods` + +**控制器类:** `com.agileboot.api.controller.manage.ManageGoodsController` + +**功能描述:** 商品管理接口,提供商品的增删改查功能。 + +--- + +## 接口列表 + +### 1. 获取商品列表 + +**接口路径:** `GET /api/manage/goods/list` + +**功能描述:** 分页查询商品列表,支持多条件筛选和排序。 + +**请求参数:** + +| 参数名 | 类型 | 必填 | 描述 | 示例 | +|--------|------|------|------|------| +| `pageNum` | Integer | 否 | 页码,默认1,最大值200 | `1` | +| `pageSize` | Integer | 否 | 每页大小,默认10,最大值500 | `10` | +| `orderColumn` | String | 否 | 排序字段 | `"createTime"` | +| `orderDirection` | String | 否 | 排序方向:`"ascending"`(升序) 或 `"descending"`(降序) | `"descending"` | +| `beginTime` | Date | 否 | 开始时间(格式:yyyy-MM-dd) | `"2025-01-01"` | +| `endTime` | Date | 否 | 结束时间(格式:yyyy-MM-dd) | `"2025-12-31"` | +| `goodsName` | String | 否 | 商品名称(模糊查询) | `"测试商品"` | +| `categoryId` | Long | 否 | 商品分类ID | `1` | +| `externalGoodsId` | Long | 否 | 外部归属类型的商品ID | `1001` | +| `corpid` | String | 否 | 企业微信id | `"wxcorpid123"` | +| `status` | Integer | 否 | 商品状态(1上架 2下架) | `1` | +| `autoApproval` | Integer | 否 | 免审批(0否 1是) | `1` | +| `minPrice` | BigDecimal | 否 | 最低价格 | `10.00` | +| `maxPrice` | BigDecimal | 否 | 最高价格 | `100.00` | +| `belongType` | Integer | 否 | 归属类型(0-借还柜 1-固资通) | `0` | + +**返回类型:** `ResponseDTO>` + +**响应字段:** + +`ResponseDTO` 通用结构: +- `code`: Integer - 响应码 +- `msg`: String - 响应消息 +- `data`: `PageDTO` - 分页数据 + +`PageDTO` 分页结构: +- `total`: Long - 总记录数 +- `rows`: `List` - 当前页数据列表 + +`ShopGoodsDTO` 商品详情字段: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| `goodsId` | Long | 商品唯一ID | +| `goodsName` | String | 商品名称 | +| `categoryId` | Long | 分类ID | +| `externalGoodsId` | Long | 外部商品ID | +| `corpid` | String | 企业微信id | +| `categoryName` | String | 分类名称 | +| `belongType` | Long | 归属类型(0-借还柜 1-固资通) | +| `price` | BigDecimal | 销售价格 | +| `stock` | Integer | 库存数量 | +| `status` | Integer | 商品状态(1上架 2下架) | +| `autoApproval` | Integer | 免审批(0否 1是) | +| `coverImg` | String | 封面图URL | +| `creatorId` | Long | 创建者ID | +| `creatorName` | String | 创建者名称 | +| `createTime` | Date | 创建时间 | +| `remark` | String | 备注 | +| `cabinetName` | String | 柜机名称 | +| `cellNo` | Integer | 格口号 | +| `cellNoStr` | String | 格口号(字符串格式) | +| `totalStock` | Integer | 已分配库存 | +| `shopNameStr` | String | 地址名称 | +| `usageInstruction` | String | 商品使用说明 | +| `monthlyPurchaseLimit` | Integer | 每人每月限购数量 | + +**示例请求:** +``` +GET /api/manage/goods/list?pageNum=1&pageSize=10&status=1&goodsName=测试 +``` + +--- + +### 2. 新增商品 + +**接口路径:** `POST /api/manage/goods` + +**功能描述:** 创建新商品。 + +**请求体类型:** `AddGoodsCommand` (继承自 `ShopGoodsEntity`) + +**请求字段:** + +| 字段名 | 类型 | 必填 | 描述 | 示例 | +|--------|------|------|------|------| +| `goodsName` | String | 是 | 商品名称 | `"测试商品"` | +| `categoryId` | Long | 否 | 商品分类ID | `1` | +| `externalGoodsId` | Long | 否 | 外部归属类型的商品ID | `1001` | +| `corpid` | String | 否 | 企业微信id | `"wxcorpid123"` | +| `monthlyPurchaseLimit` | Integer | 否 | 每人每月限购数量 | `5` | +| `price` | BigDecimal | 是 | 销售价格 | `99.99` | +| `stock` | Integer | 否 | 库存数量 | `100` | +| `status` | Integer | 否 | 商品状态(1上架 2下架),默认值需确认 | `1` | +| `autoApproval` | Integer | 否 | 免审批(0否 1是),默认值需确认 | `0` | +| `coverImg` | String | 否 | 封面图URL | `"https://example.com/image.jpg"` | +| `goodsDetail` | String | 否 | 商品详情(支持2000汉字+10个图片链接) | `"

商品描述

"` | +| `remark` | String | 否 | 备注 | `"测试商品备注"` | +| `usageInstruction` | String | 否 | 商品使用说明 | `"使用说明内容"` | +| `belongType` | Integer | 否 | 归属类型(0-借还柜 1-固资通) | `0` | + +**注意:** `goodsId` 字段为自增主键,请求时无需提供。 + +**返回类型:** `ResponseDTO` + +**响应字段:** +- `code`: Integer - 响应码 +- `msg`: String - 响应消息 +- `data`: null + +**示例请求:** +```json +{ + "goodsName": "测试商品", + "price": 99.99, + "stock": 100, + "status": 1, + "coverImg": "https://example.com/image.jpg" +} +``` + +--- + +### 3. 删除商品 + +**接口路径:** `DELETE /api/manage/goods/{goodsIds}` + +**功能描述:** 批量删除商品。 + +**路径参数:** +- `goodsIds`: 商品ID列表,多个ID用逗号分隔 + +**请求示例:** +``` +DELETE /api/manage/goods/1,2,3 +``` + +**内部处理:** 控制器将路径参数转换为 `BulkOperationCommand` 对象: +```java +{ + "ids": [1, 2, 3] // Set 类型,自动去重 +} +``` + +**返回类型:** `ResponseDTO` + +**响应字段:** +- `code`: Integer - 响应码 +- `msg`: String - 响应消息 +- `data`: null + +--- + +### 4. 修改商品 + +**接口路径:** `PUT /api/manage/goods/{goodsId}` + +**功能描述:** 更新商品信息。 + +**路径参数:** +- `goodsId`: 商品ID + +**请求体类型:** `UpdateGoodsCommand` (继承自 `AddGoodsCommand`) + +**请求字段:** 与 `AddGoodsCommand` 相同,所有字段均为可选更新。 + +**特殊处理:** 接口会自动将路径参数中的 `goodsId` 设置到 command 对象中。 + +**返回类型:** `ResponseDTO` + +**响应字段:** +- `code`: Integer - 响应码 +- `msg`: String - 响应消息 +- `data`: null + +**示例请求:** +``` +PUT /api/manage/goods/1 +``` +```json +{ + "goodsName": "更新后的商品名称", + "price": 88.88 +} +``` + +--- + +### 5. 获取单个商品信息 + +**接口路径:** `GET /api/manage/goods/getGoodsInfo` + +**功能描述:** 根据商品ID获取单个商品的详细信息。 + +**查询参数:** + +| 参数名 | 类型 | 必填 | 描述 | 示例 | +|--------|------|------|------|------| +| `goodsId` | Long | 是 | 商品ID | `1` | + +**返回类型:** `ResponseDTO` + +**响应字段:** +- `code`: Integer - 响应码 +- `msg`: String - 响应消息 +- `data`: `ShopGoodsDTO` - 商品详情(字段同接口1) + +**示例请求:** +``` +GET /api/manage/goods/getGoodsInfo?goodsId=1 +``` + +--- + +## 通用数据结构 + +### ResponseDTO 通用响应结构 +```java +public class ResponseDTO { + private Integer code; // 响应码 + private String msg; // 响应消息 + private T data; // 响应数据 +} +``` + +### PageDTO 分页结构 +```java +public class PageDTO { + private Long total; // 总记录数 + private List rows; // 当前页数据列表 +} +``` + +### BulkOperationCommand 批量操作命令 +```java +public class BulkOperationCommand { + private Set ids; // 操作ID集合(自动去重) +} +``` + +--- + +## 注意事项 + +1. **字段默认值:** 部分字段(如 `status`, `autoApproval`)的默认值需查看业务逻辑确认 +2. **ID 生成:** `goodsId` 为数据库自增字段,创建时无需提供 +3. **批量删除:** 删除接口支持批量操作,ID列表会自动去重 +4. **分页限制:** 最大页码200,每页最大大小500 +5. **时间格式:** 时间参数需使用 `yyyy-MM-dd` 格式 +6. **企业微信集成:** `corpid` 字段用于企业微信多租户支持 + +--- + +## 相关实体类位置 + +| 类名 | 路径 | +|------|------| +| `ManageGoodsController` | `agileboot-api/src/main/java/com/agileboot/api/controller/manage/` | +| `ShopGoodsEntity` | `agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/db/` | +| `AddGoodsCommand` | `agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/command/` | +| `UpdateGoodsCommand` | `agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/command/` | +| `ShopGoodsDTO` | `agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/dto/` | +| `SearchShopGoodsQuery` | `agileboot-domain/src/main/java/com/agileboot/domain/shop/goods/query/` | +| `BulkOperationCommand` | `agileboot-domain/src/main/java/com/agileboot/domain/common/command/` | + +--- + +## 架构设计说明 + +本控制器遵循项目的 **DDD/CQRS 架构**: + +- **查询操作**(GET):使用 `SearchShopGoodsQuery` 对象,通过 `GoodsApplicationService.getGoodsList()` 处理 +- **命令操作**(POST/PUT/DELETE):使用 `AddGoodsCommand`/`UpdateGoodsCommand`/`BulkOperationCommand`,通过 `GoodsApplicationService` 的对应方法处理 +- **数据流转**:Controller → Command/Query → ApplicationService → Domain Model → DB Entity + +**注意**:`AddGoodsCommand` 和 `UpdateGoodsCommand` 都继承自 `ShopGoodsEntity`,因此共享相同的字段定义。在实际使用中,`goodsId` 字段在新增时由数据库自增生成,在更新时通过路径参数传入。 + +--- + +*文档生成时间:2025-12-11* +*基于代码分析:`agileboot-api/src/main/java/com/agileboot/api/controller/manage/ManageGoodsController.java`* \ No newline at end of file diff --git a/src/common/apis/manage/goods.ts b/src/common/apis/manage/goods.ts index 2bd908a..93250fb 100644 --- a/src/common/apis/manage/goods.ts +++ b/src/common/apis/manage/goods.ts @@ -2,36 +2,52 @@ import { request } from "@/http/axios" import { PageDTO, ResponseData, BasePageQuery } from "../type" export interface ShopGoodsDTO { - goodsId?: number - goodsName?: string - categoryId?: number - categoryName?: string - price?: number - stock?: number - status?: number - autoApproval?: number - coverImg?: string - creatorId?: number - creatorName?: string - createTime?: string - remark?: string - cabinetName?: string - cellNo?: number - cellNoStr?: string - totalStock?: number - usageInstruction?: string + goodsId?: number // 商品唯一ID + goodsName?: string // 商品名称 + categoryId?: number // 分类ID + externalGoodsId?: number // 外部归属类型的商品ID + corpid?: string // 企业微信id + categoryName?: string // 分类名称 + belongType?: number // 归属类型(0-借还柜 1-固资通) + price?: number // 销售价格 + stock?: number // 库存数量 + status?: number // 商品状态(1上架 2下架) + autoApproval?: number // 免审批(0否 1是) + coverImg?: string // 封面图URL + creatorId?: number // 创建者ID + creatorName?: string // 创建者名称 + createTime?: string // 创建时间 + remark?: string // 备注 + cabinetName?: string // 柜机名称 + cellNo?: number // 格口号 + cellNoStr?: string // 格口号(字符串格式) + totalStock?: number // 已分配库存 + shopNameStr?: string // 地址名称 + usageInstruction?: string // 商品使用说明 + monthlyPurchaseLimit?: number // 每人每月限购数量 + goodsDetail?: string // 商品详情(支持2000汉字+10个图片链接) } export interface SearchShopGoodsQuery extends BasePageQuery { - goodsName?: string - categoryId?: number - status?: number - autoApproval?: number - minPrice?: number - maxPrice?: number + goodsName?: string // 商品名称(模糊查询) + categoryId?: number // 商品分类ID + externalGoodsId?: number // 外部归属类型的商品ID + corpid?: string // 企业微信id + status?: number // 商品状态(1上架 2下架) + autoApproval?: number // 免审批(0否 1是) + minPrice?: number // 最低价格 + maxPrice?: number // 最高价格 + belongType?: number // 归属类型(0-借还柜 1-固资通) + beginTime?: string // 开始时间(格式:yyyy-MM-dd) + endTime?: string // 结束时间(格式:yyyy-MM-dd) } -/** 获取商品列表 */ +/** + * 获取商品列表 + * 分页查询商品列表,支持多条件筛选和排序 + * @param query 查询参数(包含分页、筛选条件等) + * @returns Promise>> + */ export function getGoodsList(query: SearchShopGoodsQuery) { return request>>({ url: "manage/goods/list", @@ -40,17 +56,27 @@ export function getGoodsList(query: SearchShopGoodsQuery) { }) } -/** 新增商品 */ +/** + * 新增商品 + * 创建新商品 + * @param data 商品信息 + * @returns Promise> + */ export function addGoods(data: { - goodsName: string - categoryId: number - price: number - stock: number - status: number - autoApproval: number - coverImg: string - goodsDetail?: string - usageInstruction?: string + goodsName: string // 商品名称(必填) + categoryId?: number // 商品分类ID + externalGoodsId?: number // 外部归属类型的商品ID + corpid?: string // 企业微信id + monthlyPurchaseLimit?: number // 每人每月限购数量 + price: number // 销售价格(必填) + stock?: number // 库存数量 + status?: number // 商品状态(1上架 2下架) + autoApproval?: number // 免审批(0否 1是) + coverImg?: string // 封面图URL + goodsDetail?: string // 商品详情(支持2000汉字+10个图片链接) + remark?: string // 备注 + usageInstruction?: string // 商品使用说明 + belongType?: number // 归属类型(0-借还柜 1-固资通) }) { return request>({ url: "manage/goods", @@ -59,7 +85,12 @@ export function addGoods(data: { }) } -/** 删除商品 */ +/** + * 删除商品 + * 批量删除商品 + * @param goodsIds 商品ID数组 + * @returns Promise> + */ export function deleteGoods(goodsIds: number[]) { return request>({ url: `manage/goods/${goodsIds.join(',')}`, @@ -67,17 +98,28 @@ export function deleteGoods(goodsIds: number[]) { }) } -/** 修改商品 */ +/** + * 修改商品 + * 更新商品信息 + * @param goodsId 商品ID(路径参数) + * @param data 更新数据 + * @returns Promise> + */ export function updateGoods(goodsId: number, data: { - goodsName?: string - categoryId?: number - price?: number - stock?: number - status?: number - autoApproval?: number - coverImg?: string - goodsDetail?: string - usageInstruction?: string + goodsName?: string // 商品名称 + categoryId?: number // 商品分类ID + externalGoodsId?: number // 外部归属类型的商品ID + corpid?: string // 企业微信id + monthlyPurchaseLimit?: number // 每人每月限购数量 + price?: number // 销售价格 + stock?: number // 库存数量 + status?: number // 商品状态(1上架 2下架) + autoApproval?: number // 免审批(0否 1是) + coverImg?: string // 封面图URL + goodsDetail?: string // 商品详情(支持2000汉字+10个图片链接) + remark?: string // 备注 + usageInstruction?: string // 商品使用说明 + belongType?: number // 归属类型(0-借还柜 1-固资通) }) { return request>({ url: `manage/goods/${goodsId}`, @@ -86,7 +128,12 @@ export function updateGoods(goodsId: number, data: { }) } -/** 获取单个商品信息 */ +/** + * 获取单个商品信息 + * 根据商品ID获取商品的详细信息 + * @param goodsId 商品ID(查询参数) + * @returns Promise> + */ export function getGoodsInfo(goodsId: number) { return request>({ url: "manage/goods/getGoodsInfo", diff --git a/src/layout/components/Tabbar.vue b/src/layout/components/Tabbar.vue index a058b61..9f71034 100644 --- a/src/layout/components/Tabbar.vue +++ b/src/layout/components/Tabbar.vue @@ -20,6 +20,11 @@ const wxStore = useWxStoreOutside(); const tabbarItemList = computed(() => { if (wxStore.isCabinetAdmin) { return [{ + title: '商品管理', + icon: 'home-o', + path: '/manage/goods' + }, + { title: '柜机管理', icon: 'manager-o', path: '/cabinet' diff --git a/src/pages/manage/goods/goodsAddEdit.vue b/src/pages/manage/goods/goodsAddEdit.vue new file mode 100644 index 0000000..17de5cf --- /dev/null +++ b/src/pages/manage/goods/goodsAddEdit.vue @@ -0,0 +1,387 @@ + + + + + \ No newline at end of file diff --git a/src/pages/manage/goods/goodsDetail.vue b/src/pages/manage/goods/goodsDetail.vue new file mode 100644 index 0000000..dd4f56d --- /dev/null +++ b/src/pages/manage/goods/goodsDetail.vue @@ -0,0 +1,274 @@ + + + + + \ No newline at end of file diff --git a/src/pages/manage/goods/goodsList.vue b/src/pages/manage/goods/goodsList.vue index d3dbc56..abf253f 100644 --- a/src/pages/manage/goods/goodsList.vue +++ b/src/pages/manage/goods/goodsList.vue @@ -1,11 +1,11 @@