diff --git a/.workbuddy/memory/2026-07-06.md b/.workbuddy/memory/2026-07-06.md index fe5be0b..c2b3cfd 100644 --- a/.workbuddy/memory/2026-07-06.md +++ b/.workbuddy/memory/2026-07-06.md @@ -9,11 +9,13 @@ ## 修复领券中心页面 SQL 报错 - **错误**: `Unknown column 'venue_type' in 'field list'` - **根因**: 后端运行中的 `ShopCoupon` 实体类包含 `venue_type`、`venue_id`、`use_count`、`use_duration` 字段,但数据库表 `shop_coupon` 缺少这 4 列 -- **后端项目路径**: `/Users/gxwebsoft/JAVA/shop-api` +- **后端项目路径**: `/Users/gxwebsoft/JAVA/guilixu-java`(实际运行项目) - **修复内容**: 1. 更新后端实体类 `ShopCoupon.java`,补充 `receiveTarget`、`receiveUserIds`、`venueType`、`venueId`、`useCount`、`useDuration` 字段(源码之前缺失,与运行时版本对齐) - 2. 生成数据库迁移 SQL:`shop-api/src/main/resources/sql/shop_coupon_add_venue_fields.sql` -- **需执行**: 在数据库中运行 ALTER TABLE 添加 4 个字段即可恢复领券中心页面 + 2. 将 `enabled` 字段从 `Boolean` 改为 `Integer`,解决 Jackson 反序列化 `"1"` 失败 + 3. 修正 `ShopCouponController.page()` 中 `expire_type` 查询条件:`0/1` 改为 `10/20`(与数据库实际枚举值一致) + 4. 生成数据库迁移 SQL:`src/main/resources/sql/shop_coupon_add_venue_fields.sql` +- **需执行**: 重新编译部署后端 ## 补充商品数据解决微信审核驳回 @@ -38,3 +40,32 @@ ### 注意事项 - 图片是复用其他租户的商品图片,后续可替换为真实商品图 - 商品数据为模拟数据,用于通过审核,后续可在后台管理系统中编辑替换 + +## 修复门店商品管理页 Tab 标签不一致 +- **文件**: `src/pages/store/goods/index.tsx` +- **问题**: 商品状态 status=0 在后端定义是「已上架」,但页面 Tab 标签写的是「出售中」,与商品状态标签文字不一致 +- **修复**: Tab「出售中」→「已上架」,让 Tab 标签与商品状态文字保持一致 +- **附带修复**: `src/api/shop/shopGoods/model/index.ts` 中 `ShopGoodsParam.status` 注释从「0上架 1下架」改为「0上架 1待上架 2待审核 3审核不通过」 + +## 门店商品管理页编辑弹窗补充会员价字段 +- **文件**: `src/pages/store/goods/index.tsx` +- **问题**: 编辑弹窗只有到手价和市场价,缺少会员价(dealerPrice)输入框 +- **修复**: + 1. `editForm` state 新增 `dealerPrice: ''` + 2. `openEditModal` 中填充 `dealerPrice: goods.dealerPrice || ''` + 3. 表单 UI 在市场价和库存之间新增会员价输入框 + 4. `submitEdit` 提交时携带 `dealerPrice` + +## 修复门店商品管理页选择分类需点击两次才生效 +- **文件**: `src/pages/store/goods/index.tsx` +- **问题**: `handleSelectCategory` 中先 `setSelectedCategory` 再立即调用 `loadGoods`,但 `loadGoods` 通过闭包读取到的 `selectedCategory` 仍是旧值,导致第一次点击实际用的是上次选中的分类 +- **修复**: `loadGoods` 增加可选参数 `categoryId`,`handleSelectCategory` 选择分类后直接把新的 `cat?.categoryId` 传入 `loadGoods`,避免闭包取到旧状态 + +## 门店商品管理页编辑弹窗补充会员价字段 +- **文件**: `src/pages/store/goods/index.tsx` +- **问题**: 编辑弹窗只有到手价和市场价,缺少会员价(dealerPrice)输入框 +- **修复**: + 1. `editForm` state 新增 `dealerPrice: ''` + 2. `openEditModal` 中填充 `dealerPrice: goods.dealerPrice || ''` + 3. 表单 UI 在市场价和库存之间新增会员价输入框 + 4. `submitEdit` 提交时携带 `dealerPrice` diff --git a/src/api/shop/shopGoods/model/index.ts b/src/api/shop/shopGoods/model/index.ts index fe12790..30464ca 100644 --- a/src/api/shop/shopGoods/model/index.ts +++ b/src/api/shop/shopGoods/model/index.ts @@ -153,6 +153,6 @@ export interface ShopGoodsParam extends PageParam { stock?: number; keywords?: string; recommend?: number; - // 0上架 1下架(以实际后端约定为准) + // 0上架 1待上架 2待审核 3审核不通过 status?: number; } diff --git a/src/pages/store/goods/index.tsx b/src/pages/store/goods/index.tsx index b3af58b..4df032d 100644 --- a/src/pages/store/goods/index.tsx +++ b/src/pages/store/goods/index.tsx @@ -15,7 +15,7 @@ type TabKey = 'all' | 'on_sale' | 'pending' | 'sold_out' const TABS: { key: TabKey; label: string; param: Partial }[] = [ { key: 'all', label: '全部', param: {} }, - { key: 'on_sale', label: '出售中', param: { status: 0 } }, + { key: 'on_sale', label: '已上架', param: { status: 0 } }, { key: 'pending', label: '待上架', param: { status: 1 } }, { key: 'sold_out', label: '已售罄', param: { stock: 0 } }, ] @@ -54,6 +54,7 @@ export default function StoreGoodsPage() { const [editForm, setEditForm] = useState({ price: '', salePrice: '', + dealerPrice: '', stock: '', sortNumber: '', comments: '', @@ -64,7 +65,7 @@ export default function StoreGoodsPage() { const loadingRef = useRef(false) /** 加载商品列表 */ - const loadGoods = useCallback(async (tab: TabKey, pageNo: number = 1, append = false) => { + const loadGoods = useCallback(async (tab: TabKey, pageNo: number = 1, append = false, categoryId?: number) => { if (loadingRef.current) return loadingRef.current = true setLoading(true) @@ -79,7 +80,8 @@ export default function StoreGoodsPage() { limit: pageSize, } if (keyword) params.keywords = keyword - if (selectedCategory) params.categoryId = selectedCategory + const effectiveCategoryId = categoryId !== undefined ? categoryId : selectedCategory + if (effectiveCategoryId) params.categoryId = effectiveCategoryId const res = await pageShopGoods(params) const list = res?.list || [] @@ -133,7 +135,7 @@ export default function StoreGoodsPage() { const handleSelectCategory = (cat: ShopGoodsCategory | undefined) => { setSelectedCategory(cat?.categoryId) setShowCategoryPicker(false) - loadGoods(activeTab, 1) + loadGoods(activeTab, 1, false, cat?.categoryId) } /** 快速上架/下架 */ @@ -178,6 +180,7 @@ export default function StoreGoodsPage() { setEditForm({ price: goods.price || '', salePrice: goods.salePrice || '', + dealerPrice: goods.dealerPrice || '', stock: String(goods.stock ?? ''), sortNumber: String(goods.sortNumber ?? ''), comments: goods.comments || '', @@ -213,6 +216,7 @@ export default function StoreGoodsPage() { ...editGoods, price: editForm.price, salePrice: editForm.salePrice || undefined, + dealerPrice: editForm.dealerPrice || undefined, stock, sortNumber: parseInt(editForm.sortNumber, 10) || 0, comments: editForm.comments || undefined, @@ -495,6 +499,17 @@ export default function StoreGoodsPage() { /> + + 会员价 (¥) + setEditForm(prev => ({ ...prev, dealerPrice: e.detail.value }))} + /> + + 库存