fix(merchant-products): 严格锁定商品价格与库存编辑权限,仅对平台超级管理员开放

1. 前端 ProductsTab 增加 canEditPricing={isAdmin} 显式权限透传,仅超级管理员可见【编辑】按钮,普通分销商/商户完全隐藏;
2. 后端 UpdateProduct 接口补充 middleware.GetRole(c) != model.RoleAdmin 强校验,普通分销商发起请求直接 403 阻断;
3. 保障平台商品进货成本与对外积分售价的权威性,杜绝下游分销商私自篡改价格与库存风险。
This commit is contained in:
yml2213
2026-10-05 15:14:33 +08:00
parent 0dff9d892e
commit 611c658a8a
3 changed files with 18 additions and 7 deletions
+6
View File
@@ -7,6 +7,7 @@ import (
"time"
"affiliate_dash/internal/middleware"
"affiliate_dash/internal/model"
"affiliate_dash/internal/pkg/response"
"affiliate_dash/internal/service"
@@ -78,7 +79,12 @@ type merchantProductStatusReq struct {
// UpdateProductStatus PATCH /api/merchant/products/:id/status
// 商户仅能上架/下架商品,价格、成本等配置由平台管理员维护。
// UpdateProduct PATCH /api/merchant/products/:id — 编辑商品(显示名称、售价、成本、库存、状态)。
// 严格风控门禁:仅平台超级管理员(model.RoleAdmin)拥有修改商品价格、成本、库存与名称的权限,普通分销商严禁修改。
func (h *MerchantHandler) UpdateProduct(c *gin.Context) {
if middleware.GetRole(c) != model.RoleAdmin {
response.Forbidden(c, "权限不足:仅平台超级管理员可编辑商品价格、成本与库存")
return
}
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
if id == 0 {
response.BadRequest(c, "参数错误")
+1
View File
@@ -564,6 +564,7 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer
loading={loading}
products={products}
canManage={canManage}
canEditPricing={isAdmin}
filters={productFilters}
onToggleProduct={openProductToggle}
onDeleteProduct={deleteProduct}
+11 -7
View File
@@ -63,6 +63,7 @@ export function ProductsTab({
loading,
products,
canManage,
canEditPricing = false,
filters,
onToggleProduct,
onDeleteProduct,
@@ -73,6 +74,7 @@ export function ProductsTab({
loading: boolean
products: PageResult<MerchantProduct>
canManage: boolean
canEditPricing?: boolean
filters: { keyword: string; status: string }
onToggleProduct: (record: MerchantProduct) => void
onDeleteProduct: (record: MerchantProduct) => void
@@ -196,13 +198,15 @@ export function ProductsTab({
fixed: 'right',
render: (_, record) => canManage ? (
<Space size={4}>
<Button
type="link"
size="small"
onClick={() => openEditModal(record)}
>
编辑
</Button>
{canEditPricing && (
<Button
type="link"
size="small"
onClick={() => openEditModal(record)}
>
编辑
</Button>
)}
<Popconfirm
title={record.status === 'active' ? '下架该商品?' : '上架该商品?'}
description={record.status === 'active' ? '下架后商户将无法再创建该商品订单' : '上架后商户可正常下单'}