Преглед на файлове

feat(product): 添加分类管理功能并优化产品分类组件

- 在产品分类API中新增平台参数支持和大客户ID字段
- 添加categoryA10分类管理和categoryBinding绑定相关API接口
- 新增商品管理路由页面用于分类下的商品管理功能
- 在VIP站点页面添加分类管理入口链接
- 修复多处产品状态比较逻辑,统一使用数字类型判断
- 移除产品分类页面中的平台列显示
- 添加商品管理按钮到分类表格操作列
- 集成A10分类选择树形组件到分类表单
- 实现路由参数传递平台和大客户ID功能
- 添加分类管理相关类型定义文件
肖路 преди 18 часа
родител
ревизия
2cd3718298

+ 14 - 3
src/api/product/category/index.ts

@@ -66,10 +66,11 @@ export const delCategory = (id: string | number | Array<string | number>) => {
  * 查询产品分类列表(排除节点)
  * @param id
   */
-export const listCategoryExcludeChild = (id: string | number): AxiosPromise<CategoryVO[]> => {
+export const listCategoryExcludeChild = (id: string | number, platform?: number): AxiosPromise<CategoryVO[]> => {
   return request({
-    url: '/product/category/list/exclude/' + id,
-    method: 'get'
+    url: '/product/category/tree/exclude/' + id,
+    method: 'get',
+    params: platform !== undefined ? { platform } : undefined
   });
 };
 
@@ -85,3 +86,13 @@ export const setCategoryReviewer = (id: string | number, reviewerId: string | nu
     data: { id, reviewerId }
   });
 };
+
+/**
+ * 获取产品分类列表
+ */
+export const getProductCategoryList = () => {
+  return request({
+    url: '/product/category/getProductCategoryList',
+    method: 'get'
+  });
+};

+ 10 - 0
src/api/product/category/types.ts

@@ -256,6 +256,11 @@ export interface CategoryForm extends BaseEntity {
    */
   platform?: number;
 
+  /**
+   * 大客户ID
+   */
+  customerId?: string | number;
+
   /**
    * 备注
    */
@@ -375,6 +380,11 @@ export interface CategoryQuery extends PageQuery {
    */
   platform?: number;
 
+  /**
+   * 大客户ID
+   */
+  customerId?: string | number;
+
   /**
    * 平台标识
    */

+ 97 - 0
src/api/product/categoryA10/index.ts

@@ -0,0 +1,97 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { CategoryVO, CategoryForm, CategoryQuery } from '@/api/product/categoryA10/types';
+
+/**
+ * 查询产品分类列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listCategory = (query?: Partial<CategoryQuery>): AxiosPromise<CategoryVO[]> => {
+  return request({
+    url: '/product/categoryA10/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询产品分类详细
+ * @param id
+ */
+export const getCategory = (id: string | number): AxiosPromise<CategoryVO> => {
+  return request({
+    url: '/product/categoryA10/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增产品分类
+ * @param data
+ */
+export const addCategory = (data: CategoryForm) => {
+  return request({
+    url: '/product/category',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改产品分类
+ * @param data
+ */
+export const updateCategory = (data: CategoryForm) => {
+  return request({
+    url: '/product/category',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除产品分类
+ * @param id
+ */
+export const delCategory = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/product/categoryA10/' + id,
+    method: 'delete'
+  });
+};
+
+/**
+ * 查询产品分类列表(排除节点)
+ * @param id
+  */
+export const listCategoryExcludeChild = (id: string | number): AxiosPromise<CategoryVO[]> => {
+  return request({
+    url: '/product/categoryA10/tree/exclude/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 设置分类审核员
+ * @param id 分类ID
+ * @param reviewerId 审核员用户ID
+ */
+export const setCategoryReviewer = (id: string | number, reviewerId: string | number) => {
+  return request({
+    url: '/product/categoryA10/setReviewer',
+    method: 'put',
+    data: { id, reviewerId }
+  });
+};
+
+/**
+ * 获取产品分类列表
+ */
+export const getProductCategoryList = () => {
+  return request({
+    url: '/product/categoryA10/getProductCategoryList',
+    method: 'get'
+  });
+};

+ 402 - 0
src/api/product/categoryA10/types.ts

@@ -0,0 +1,402 @@
+export interface CategoryVO {
+  /**
+   * 主键
+   */
+  id: string | number;
+
+  /**
+   * 分类编号
+   */
+  categoryNo: string;
+
+  /**
+   * 分类名称
+   */
+  categoryName: string;
+
+  /**
+   * 父级分类ID
+   */
+  parentId: string | number;
+
+  /**
+   * 父级分类名称
+   */
+  parentName?: string;
+
+  /**
+   * 祖籍列表
+   */
+  ancestors: string;
+
+  /**
+   * 分类层级(1=一级,2=二级, 3三级)
+   */
+  classLevel: number;
+
+  /**
+   * 是否显示(1=显示,0=隐藏)
+   */
+  isShow: number;
+
+  /**
+   * 是否在GPS中显示
+   */
+  isShowGps: number;
+
+  /**
+   * 折扣率(可能为JSON或文本)
+   */
+  discountRate: number;
+
+  /**
+   * 拼音码(用于快速检索)
+   */
+  pyCode: string;
+
+  /**
+   * 分类描述
+   */
+  classDescription: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource: string;
+
+  /**
+   * 自定义标签1
+   */
+  oneLable1: string;
+
+  /**
+   * 自定义标签2
+   */
+  oneLable2: string;
+
+  /**
+   * 自定义链接1
+   */
+  oneLink1: string;
+
+  /**
+   * 自定义链接2
+   */
+  oneLink2: string;
+
+  /**
+   * 排序值,默认为0
+   */
+  sort: number;
+
+  /**
+   * 颜色(如CSS颜色值)
+   */
+  color: string;
+
+  /**
+   * 采购编号
+   */
+  purchaseNo: string;
+
+  /**
+   * 采购名称
+   */
+  purchaseName: string;
+
+  /**
+   * 采购负责人编号
+   */
+  purchaseManagerNo: string;
+
+  /**
+   * 采购负责人姓名
+   */
+  purchaseManagerName: string;
+
+  /**
+   * 所属平台(0=Web, 1=小程序)
+   */
+  platform: number;
+
+  /**
+   * 备注
+   */
+  remark: string;
+
+  /**
+   * 子级分类
+   */
+  children?: CategoryVO[];
+
+  /**
+   * 是否有子节点(用于懒加载)
+   */
+  hasChildren?: boolean;
+}
+
+export interface CategoryForm extends BaseEntity {
+  /**
+   * 主键
+   */
+  id?: string | number;
+
+  /**
+   * 分类编号
+   */
+  categoryNo?: string;
+
+  /**
+   * 分类名称
+   */
+  categoryName?: string;
+
+  /**
+   * 父级分类ID
+   */
+  parentId?: string | number;
+
+  /**
+   * 父级分类名称
+   */
+  parentName?: string;
+
+  /**
+   * 祖籍列表
+   */
+  ancestors?: string;
+
+  /**
+   * 分类层级(1=一级,2=二级, 3三级)
+   */
+  classLevel?: number;
+
+  /**
+   * 是否显示(1=显示,0=隐藏)
+   */
+  isShow?: number;
+
+  /**
+   * 是否在GPS中显示
+   */
+  isShowGps?: number;
+
+  /**
+   * 折扣率(可能为JSON或文本)
+   */
+  discountRate?: number;
+
+  /**
+   * 拼音码(用于快速检索)
+   */
+  pyCode?: string;
+
+  /**
+   * 分类描述
+   */
+  classDescription?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 自定义标签1
+   */
+  oneLable1?: string;
+
+  /**
+   * 自定义标签2
+   */
+  oneLable2?: string;
+
+  /**
+   * 自定义链接1
+   */
+  oneLink1?: string;
+
+  /**
+   * 自定义链接2
+   */
+  oneLink2?: string;
+
+  /**
+   * 排序值,默认为0
+   */
+  sort?: number;
+
+  /**
+   * 颜色(如CSS颜色值)
+   */
+  color?: string;
+
+  /**
+   * 采购编号
+   */
+  purchaseNo?: string;
+
+  /**
+   * 采购名称
+   */
+  purchaseName?: string;
+
+  /**
+   * 采购负责人编号
+   */
+  purchaseManagerNo?: string;
+
+  /**
+   * 采购负责人姓名
+   */
+  purchaseManagerName?: string;
+
+  /**
+   * 所属平台(0=Web, 1=小程序)
+   */
+  platform?: number;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+
+}
+
+export interface CategoryQuery extends PageQuery {
+
+  /**
+   * 分类编号
+   */
+  categoryNo?: string;
+
+  /**
+   * 分类名称
+   */
+  categoryName?: string;
+
+  /**
+   * 父级分类ID
+   */
+  parentId?: string | number;
+
+  /**
+   * 祖籍列表
+   */
+  ancestors?: string;
+
+  /**
+   * 分类层级(1=一级,2=二级, 3三级)
+   */
+  classLevel?: number;
+
+  /**
+   * 是否显示(1=显示,0=隐藏)
+   */
+  isShow?: number;
+
+  /**
+   * 是否在GPS中显示
+   */
+  isShowGps?: number;
+
+  /**
+   * 折扣率(可能为JSON或文本)
+   */
+  discountRate?: number;
+
+  /**
+   * 拼音码(用于快速检索)
+   */
+  pyCode?: string;
+
+  /**
+   * 分类描述
+   */
+  classDescription?: string;
+
+  /**
+   * 数据来源
+   */
+  dataSource?: string;
+
+  /**
+   * 自定义标签1
+   */
+  oneLable1?: string;
+
+  /**
+   * 自定义标签2
+   */
+  oneLable2?: string;
+
+  /**
+   * 自定义链接1
+   */
+  oneLink1?: string;
+
+  /**
+   * 自定义链接2
+   */
+  oneLink2?: string;
+
+  /**
+   * 排序值,默认为0
+   */
+  sort?: number;
+
+  /**
+   * 颜色(如CSS颜色值)
+   */
+  color?: string;
+
+  /**
+   * 采购编号
+   */
+  purchaseNo?: string;
+
+  /**
+   * 采购名称
+   */
+  purchaseName?: string;
+
+  /**
+   * 采购负责人编号
+   */
+  purchaseManagerNo?: string;
+
+  /**
+   * 采购负责人姓名
+   */
+  purchaseManagerName?: string;
+
+  /**
+   * 所属平台(0=Web, 1=小程序)
+   */
+  platform?: number;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+    /**
+     * 日期范围参数
+     */
+    params?: any;
+}
+
+/**
+ * 部门类型
+ */
+export interface categoryTreeVO extends BaseEntity {
+  id: number | string;
+  label: string;
+  parentId: number | string;
+  weight: number;
+  children: categoryTreeVO[];
+  isShow: '';
+}
+
+
+

+ 78 - 0
src/api/product/categoryBinding/index.ts

@@ -0,0 +1,78 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { CategoryBindingVO, CategoryBindingForm, CategoryBindingQuery } from '@/api/product/categoryBinding/types';
+import { BaseVO, BaseForm, BaseQuery, StatusCountVo } from '@/api/product/base/types';
+
+/**
+ * 查询其它分类与商品的绑定列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listCategoryBinding = (query?: CategoryBindingQuery): AxiosPromise<CategoryBindingVO[]> => {
+  return request({
+    url: '/product/categoryBinding/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询其它分类与商品的绑定详细
+ * @param id
+ */
+export const getCategoryBinding = (id: string | number): AxiosPromise<CategoryBindingVO> => {
+  return request({
+    url: '/product/categoryBinding/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增其它分类与商品的绑定
+ * @param data
+ */
+export const addCategoryBinding = (data: CategoryBindingForm) => {
+  return request({
+    url: '/product/categoryBinding',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改其它分类与商品的绑定
+ * @param data
+ */
+export const updateCategoryBinding = (data: CategoryBindingForm) => {
+  return request({
+    url: '/product/categoryBinding',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除其它分类与商品的绑定
+ * @param id
+ */
+export const delCategoryBinding = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/product/categoryBinding/' + id,
+    method: 'delete'
+  });
+};
+
+/**
+ * 获取其他分类下关联的商品列表
+ * @param query
+ * @returns {*}
+ */
+
+export const getCategoryBindingProductPage = (query?: BaseQuery): AxiosPromise<BaseVO[]> => {
+  return request({
+    url: '/product/categoryBinding/getCategoryBindingProductPage',
+    method: 'get',
+    params: query
+  });
+};

+ 151 - 0
src/api/product/categoryBinding/types.ts

@@ -0,0 +1,151 @@
+export interface CategoryBindingVO {
+  /**
+   * 
+   */
+  id: string | number;
+
+  /**
+   * 商品id
+   */
+  productId: string | number;
+
+  /**
+   * 商品编号
+   */
+  productNo: string;
+
+  /**
+   * 顶级分类id
+   */
+  topCategoryId: string | number;
+
+  /**
+   * 中级分类id
+   */
+  mediumCategoryId: string | number;
+
+  /**
+   * 低级分类id
+   */
+  bottomCategoryId: string | number;
+
+  /**
+   * 所属平台 (0=平台,1=工业品,2=福利,3=企业购,4=大客户)
+   */
+  platform: number;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status: string;
+
+  /**
+   * 备注
+   */
+  remark: string;
+
+}
+
+export interface CategoryBindingForm extends BaseEntity {
+  /**
+   * 
+   */
+  id?: string | number;
+
+  /**
+   * 商品id
+   */
+  productId?: string | number;
+
+  /**
+   * 商品编号
+   */
+  productNo?: string;
+
+  /**
+   * 顶级分类id
+   */
+  topCategoryId?: string | number;
+
+  /**
+   * 中级分类id
+   */
+  mediumCategoryId?: string | number;
+
+  /**
+   * 低级分类id
+   */
+  bottomCategoryId?: string | number;
+
+  /**
+   * 所属平台 (0=平台,1=工业品,2=福利,3=企业购,4=大客户)
+   */
+  platform?: number;
+
+  /**
+   * 客户id
+   */
+  customerId?: string | number;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 备注
+   */
+  remark?: string;
+
+}
+
+export interface CategoryBindingQuery extends PageQuery {
+
+  /**
+   * 商品id
+   */
+  productId?: string | number;
+
+  /**
+   * 商品编号
+   */
+  productNo?: string;
+
+  /**
+   * 顶级分类id
+   */
+  topCategoryId?: string | number;
+
+  /**
+   * 中级分类id
+   */
+  mediumCategoryId?: string | number;
+
+  /**
+   * 低级分类id
+   */
+  bottomCategoryId?: string | number;
+
+  /**
+   * 所属平台 (0=平台,1=工业品,2=福利,3=企业购,4=大客户)
+   */
+  platform?: number;
+
+  /**
+   * 状态(0正常 1停用)
+   */
+  status?: string;
+
+  /**
+   * 平台标识
+   */
+  platformCode?: string;
+
+    /**
+     * 日期范围参数
+     */
+    params?: any;
+}
+
+
+

+ 6 - 0
src/router/index.ts

@@ -204,6 +204,12 @@ export const constantRoutes: RouteRecordRaw[] = [
         component: () => import('@/views/product/productProgram/form.vue'),
         name: 'ProductProgramForm',
         meta: { title: '编辑产品', activeMenu: '/product/productProgram', noCache: true }
+      },
+      {
+        path: 'category/categoryProduct',
+        component: () => import('@/views/product/category/categoryProduct.vue'),
+        name: 'CategoryProduct',
+        meta: { title: '商品管理', activeMenu: '/product/category', noCache: true }
       }
     ]
   },

+ 18 - 1
src/views/platform/customerOperation/vipSite/index.vue

@@ -113,6 +113,7 @@
               <!-- <el-link type="primary" :underline="false" @click="handleProductConfig(scope.row)">商品配置</el-link>
               <el-link type="primary" :underline="false" @click="handleStyleDesign(scope.row)">样式设计</el-link> -->
               <el-link type="primary" :underline="false" @click="handleDiy(scope.row)">diy设计</el-link>
+              <el-link type="primary" :underline="false" @click="handleCategoryManage(scope.row)">分类管理</el-link>
               <el-link :type="scope.row.status === '0' ? 'danger' : 'success'" :underline="false" @click="handleStatusChange(scope.row)">
                 {{ scope.row.status === '0' ? '停 用' : '启 用' }}
               </el-link>
@@ -198,7 +199,12 @@ const enrichListWithCustomerInfo = async () => {
   siteList.value = siteList.value.map((item) => {
     const customer = customerMap.get(String(item.clientId));
     if (customer) {
-      return { ...item, clientNo: customer.customerNo || item.clientNo, clientName: customer.customerName || item.clientName };
+      return {
+        ...item,
+        clientNo: customer.customerNo || item.clientNo,
+        clientName: customer.customerName || item.clientName,
+        platformCode: 4
+      };
     }
     return item;
   });
@@ -296,6 +302,17 @@ const handleDiy = (row: any) => {
   });
 };
 
+/** 分类管理 */
+const handleCategoryManage = (row: any) => {
+  router.push({
+    path: '/customerOperation/customer-category',
+    query: {
+      platform: row.platformCode,
+      customerId: String(row.clientId)
+    }
+  });
+};
+
 /** 状态切换 */
 const handleStatusChange = async (row: SiteVO) => {
   const newStatus = row.status === '0' ? '1' : '0';

+ 2 - 2
src/views/platform/customerOperation/vipSite/productConfig.vue

@@ -103,7 +103,7 @@
         </el-table-column>
         <el-table-column label="商品状态" align="center" width="100">
           <template #default="scope">
-            <el-tag v-if="scope.row.productStatus === '1'" type="success" size="small">上架</el-tag>
+            <el-tag v-if="scope.row.productStatus === 1" type="success" size="small">上架</el-tag>
             <el-tag v-else type="info" size="small">下架</el-tag>
           </template>
         </el-table-column>
@@ -236,7 +236,7 @@
           <el-table-column label="采购价" align="center" prop="purchasingPrice" width="80" />
           <el-table-column label="商品状态" align="center" prop="productStatus" width="80" >
             <template #default="scope">
-              <el-tag v-if="scope.row.productStatus === '1'" type="success" size="small">上架</el-tag>
+              <el-tag v-if="scope.row.productStatus === 1" type="success" size="small">上架</el-tag>
               <el-tag v-else type="info" size="small">下架</el-tag>
             </template>
           </el-table-column>

+ 8 - 101
src/views/platform/enterprise/product/productConfig.vue

@@ -95,22 +95,15 @@
           </template>
         </el-table-column>
         <el-table-column label="采购价" align="center" prop="purchasePrice" width="100" />
-        <el-table-column label="协议价" align="center" prop="agreementPrice" width="100" />
-        <el-table-column label="毛利率" align="center" width="130">
-          <template #default="scope">
-            {{ calcGrossMargin(scope.row) }}
-          </template>
-        </el-table-column>
         <el-table-column label="商品状态" align="center" width="100">
           <template #default="scope">
-            <el-tag v-if="scope.row.productStatus === '1'" type="success" size="small">上架</el-tag>
+            <el-tag v-if="scope.row.productStatus === 1" type="success" size="small">上架</el-tag>
             <el-tag v-else type="info" size="small">下架</el-tag>
           </template>
         </el-table-column>
         <el-table-column label="操作" align="center" width="100" fixed="right">
           <template #default="scope">
             <div class="flex flex-col items-center gap-1">
-              <el-link type="primary" :underline="false" @click="handlePriceEdit(scope.row)">价格修改</el-link>
               <el-link type="danger" :underline="false" @click="handleDelete(scope.row)">删 除</el-link>
             </div>
           </template>
@@ -120,22 +113,6 @@
       <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
     </el-card>
 
-    <!-- 价格修改弹窗 -->
-    <el-dialog title="价格修改" v-model="priceDialog.visible" width="500px" append-to-body>
-      <el-form ref="priceFormRef" :model="priceDialog.form" :rules="priceRules" label-width="100px">
-        <el-form-item label="商品名称">
-          <span>{{ priceDialog.row?.itemName }}</span>
-        </el-form-item>
-        <el-form-item label="协议价" prop="agreementPrice">
-          <el-input-number v-model="priceDialog.form.agreementPrice" :precision="2" :min="0" controls-position="right" style="width: 100%" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <el-button @click="priceDialog.visible = false">取 消</el-button>
-        <el-button type="primary" @click="submitPriceForm">确 定</el-button>
-      </template>
-    </el-dialog>
-
     <!-- 导入商品弹窗 -->
     <el-dialog title="导入商品" v-model="importDialog.visible" width="500px" append-to-body>
       <el-form label-width="100px">
@@ -236,22 +213,10 @@
           <el-table-column label="采购价" align="center" prop="purchasingPrice" width="80" />
           <el-table-column label="商品状态" align="center" prop="productStatus" width="80" >
             <template #default="scope">
-              <el-tag v-if="scope.row.productStatus === '1'" type="success" size="small">上架</el-tag>
+              <el-tag v-if="scope.row.productStatus === 1" type="success" size="small">上架</el-tag>
               <el-tag v-else type="info" size="small">下架</el-tag>
             </template>
           </el-table-column>
-          <el-table-column label="协议价" align="center" width="150">
-            <template #default="scope">
-              <el-input-number
-                v-model="scope.row.agreementPrice"
-                :precision="2"
-                :min="0"
-                controls-position="right"
-                style="width: 120px"
-                placeholder="请输入"
-              />
-            </template>
-          </el-table-column>
           <el-table-column label="操作" align="center" width="100" fixed="right">
             <template #default="scope">
               <el-link type="primary" :underline="false" @click="handleAddSingleProduct(scope.row)">加入清单</el-link>
@@ -286,7 +251,6 @@ import {
   exportSiteProductData,
   importSiteProductData,
   getSiteProductImportTemplate,
-  updateSiteProduct,
   delSiteProduct
 } from '@/api/product/siteProduct/index';
 import FileSaver from 'file-saver';
@@ -323,20 +287,6 @@ const queryParams = ref({
   bottomCategoryId: undefined as number | undefined
 });
 
-// 价格修改弹窗
-const priceDialog = reactive({
-  visible: false,
-  row: null as any,
-  form: {
-    id: undefined as number | undefined,
-    agreementPrice: 0
-  }
-});
-const priceFormRef = ref<FormInstance>();
-const priceRules = {
-  agreementPrice: [{ required: true, message: '请输入协议价', trigger: 'blur' }]
-};
-
 // 添加商品弹窗
 const addProductDialog = reactive({
   visible: false,
@@ -347,7 +297,7 @@ const addProductDialog = reactive({
 const addProductQuery = ref({
   pageNum: 1,
   pageSize: 10,
-  isSelf: 1,
+  isSelf: 0,
   productNo: undefined as string | undefined,
   itemName: undefined as string | undefined
 });
@@ -427,13 +377,9 @@ const handleMediumCategoryChange = (val: number | undefined) => {
   }
 };
 
-/** 计算毛利率:(协议价 - 采购价) ÷ 采购价 × 100% */
-const calcGrossMargin = (row: any): string => {
-  const agreement = parseFloat(row.agreementPrice);
-  const purchase = parseFloat(row.purchasePrice || row.purchasingPrice);
-  if (!purchase || purchase === 0 || isNaN(agreement) || isNaN(purchase)) return '-';
-  const margin = ((agreement - purchase) / purchase) * 100;
-  return `${margin.toFixed(2)}%`;
+/** 返回 */
+const handleBack = () => {
+  router.back();
 };
 
 /** 搜索 */
@@ -460,33 +406,6 @@ const resetQuery = () => {
   handleQuery();
 };
 
-/** 返回 */
-const handleBack = () => {
-  router.back();
-};
-
-/** 价格修改 */
-const handlePriceEdit = (row: any) => {
-  priceDialog.row = row;
-  priceDialog.form = {
-    id: row.id,
-    agreementPrice: row.agreementPrice || 0
-  };
-  priceDialog.visible = true;
-};
-
-/** 提交价格修改 */
-const submitPriceForm = async () => {
-  await priceFormRef.value?.validate();
-  await updateSiteProduct({
-    id: priceDialog.form.id,
-    agreementPrice: String(priceDialog.form.agreementPrice)
-  });
-  proxy?.$modal.msgSuccess('价格修改成功');
-  priceDialog.visible = false;
-  await getList();
-};
-
 /** 删除商品 */
 const handleDelete = async (row: any) => {
   await proxy?.$modal.confirm(`确认要删除商品"${row.itemName}"吗?`);
@@ -542,19 +461,12 @@ const handleBatchAdd = async () => {
     proxy?.$modal.msgWarning('请先选择要添加的商品');
     return;
   }
-  // 校验是否填写协议价
-  const noPrice = (selectedProducts.value as any[]).filter((item: any) => !item.agreementPrice || Number(item.agreementPrice) <= 0);
-  if (noPrice.length > 0) {
-    proxy?.$modal.msgWarning(`有 ${noPrice.length} 个商品未填写协议价,请填写后再加入清单`);
-    return;
-  }
   try {
     await Promise.all(
       (selectedProducts.value as any[]).map((item: any) =>
         addSiteProduct({
           productId: item.id,
-          productNo: item.productNo,
-          agreementPrice: String(item.agreementPrice)
+          productNo: item.productNo
         })
       )
     );
@@ -572,15 +484,10 @@ const handleBatchAdd = async () => {
 
 /** 添加单个商品 */
 const handleAddSingleProduct = async (row: any) => {
-  if (!row.agreementPrice || Number(row.agreementPrice) <= 0) {
-    proxy?.$modal.msgWarning('请先填写协议价');
-    return;
-  }
   try {
     await addSiteProduct({
       productId: row.id,
-      productNo: row.productNo,
-      agreementPrice: String(row.agreementPrice)
+      productNo: row.productNo
     });
     proxy?.$modal.msgSuccess('添加成功');
     await getList();

+ 4 - 4
src/views/platform/gift/siteProduct/index.vue

@@ -149,8 +149,8 @@
           </el-table-column>
           <el-table-column label="上下架状态" align="center" width="80">
             <template #default="scope">
-              <span :class="scope.row.productStatus === '1' ? 'status-up' : 'status-down'">
-                {{ scope.row.productStatus === '1' ? '上架' : '下架' }}
+              <span :class="scope.row.productStatus === 1 ? 'status-up' : 'status-down'">
+                {{ scope.row.productStatus === 1 ? '上架' : '下架' }}
               </span>
             </template>
           </el-table-column>
@@ -436,14 +436,14 @@ onMounted(() => {
 
 .product-info {
   text-align: left;
-  
+
   .product-name {
     font-size: 13px;
     color: #303133;
     line-height: 1.4;
     margin-bottom: 4px;
   }
-  
+
   .product-brand {
     font-size: 12px;
     color: #909399;

+ 1 - 1
src/views/product/base/index.vue

@@ -531,7 +531,7 @@ const handleView = (row: BaseVO) => {
 /** 上下架操作 */
 const handleShelf = async (row: BaseVO) => {
   // productStatus字段定义为string类型:1=已上架,0=下架,2=上架中
-  const isOnShelf = row.productStatus === '1';
+  const isOnShelf = row.productStatus === 1;
   const action = isOnShelf ? '下架' : '上架';
   await proxy?.$modal.confirm(`确认${action}该商品吗?`);
 

+ 2 - 2
src/views/product/base/shelfReview.vue

@@ -142,7 +142,7 @@
         <el-table-column label="商品状态" align="center" width="100">
           <template #default="scope">
             <el-tag v-if="scope.row.productStatus === '2' || scope.row.productStatus === 2" type="warning">上架中</el-tag>
-            <el-tag v-else-if="scope.row.productStatus === '1' || scope.row.productStatus === 1" type="success">已上架</el-tag>
+            <el-tag v-else-if="scope.row.productStatus === 1 || scope.row.productStatus === 1" type="success">已上架</el-tag>
             <el-tag v-else-if="scope.row.productStatus === '0' || scope.row.productStatus === 0" type="info">已下架</el-tag>
             <span v-else>-</span>
           </template>
@@ -163,7 +163,7 @@
                   <el-link type="success" :underline="false" @click="handleShelfReview(scope.row)">上架审核</el-link>
                 </div>
               </template>
-              <template v-else-if="scope.row.productStatus === '1' || scope.row.productStatus === 1">
+              <template v-else-if="scope.row.productStatus === 1 || scope.row.productStatus === 1">
                 <!-- 已上架:显示下架按钮 -->
                 <div class="flex gap-1 justify-center">
                   <el-link type="primary" :underline="false" @click="handleEdit(scope.row)">编辑</el-link>

+ 89 - 23
src/views/product/category/index.vue

@@ -44,11 +44,6 @@
           </template>
         </el-table-column>
         <el-table-column prop="sort" align="center" label="排序" width="150"></el-table-column>
-        <el-table-column prop="platform" align="center" label="平台" width="150">
-          <template #default="scope">
-            <span>{{ scope.row.platform === 0 ? '工业品' : scope.row.platform === 1 ? 'PC端' : '未知' }}</span>
-          </template>
-        </el-table-column>
         <el-table-column prop="isShow" align="center" label="是否提示" width="150">
           <template #default="scope">
             <span>{{ scope.row.isShow === 1 ? '是' : '否' }}</span>
@@ -68,6 +63,9 @@
             <el-tooltip v-if="scope.row.classLevel === 3" content="设置审核员" placement="top">
               <el-button v-hasPermi="['product:category:edit']" link type="primary" icon="User" @click="handleSetReviewer(scope.row)" />
             </el-tooltip>
+            <el-tooltip v-if="scope.row.classLevel === 3" content="商品管理" placement="top">
+              <el-button v-hasPermi="['product:category:edit']" link type="primary" icon="Goods" @click="handleProductManage(scope.row)" />
+            </el-tooltip>
           </template>
         </el-table-column>
       </el-table>
@@ -88,14 +86,25 @@
               />
             </el-form-item>
           </el-col>
-          <el-col :span="12">
-            <el-form-item label="分类名称" prop="categoryName">
-              <el-input v-model="form.categoryName" placeholder="请输入分类名称" />
+          <el-col :span="24">
+            <el-form-item label="A10分类" prop="categoryNo">
+              <el-tree-select
+                v-model="form.categoryNo"
+                :data="a10TreeOptions"
+                :props="{ value: 'categoryNo', label: 'categoryName', children: 'children' } as any"
+                node-key="categoryNo"
+                value-key="categoryNo"
+                placeholder="请选择A10分类"
+                filterable
+                clearable
+                check-strictly
+                style="width: 100%"
+              />
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="分类编号" prop="categoryNo">
-              <el-input v-model="form.categoryNo" placeholder="请输入分类编号" />
+            <el-form-item label="分类名称" prop="categoryName">
+              <el-input v-model="form.categoryName" placeholder="请输入分类名称" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -123,14 +132,7 @@
               <el-input-number v-model="form.sort" controls-position="right" :min="0" style="width: 100%" />
             </el-form-item>
           </el-col>
-          <el-col :span="12">
-            <el-form-item label="平台" prop="platform">
-              <el-select v-model="form.platform" placeholder="请选择所属平台" style="width: 100%">
-                <el-option label="PC端" :value="0" />
-                <el-option label="工业品" :value="1" />
-              </el-select>
-            </el-form-item>
-          </el-col>
+        
           <el-col :span="12">
             <el-form-item label="是否提示" prop="isShow">
               <el-switch v-model="form.isShow" :active-value="1" :inactive-value="0" />
@@ -163,6 +165,8 @@
 
 <script setup name="Category" lang="ts">
 import { listCategory, getCategory, delCategory, addCategory, updateCategory, listCategoryExcludeChild, setCategoryReviewer } from '@/api/product/category';
+import { listCategory as listCategoryA10 } from '@/api/product/categoryA10';
+import { CategoryVO as CategoryA10VO } from '@/api/product/categoryA10/types';
 import UserSelect from '@/components/UserSelect/index.vue';
 import { UserVO } from '@/api/system/user/types';
 import { CategoryVO, CategoryQuery, CategoryForm } from '@/api/product/category/types';
@@ -174,11 +178,29 @@ interface CategoryOptionsType {
 }
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const route = useRoute();
+const router = useRouter();
+
+// 从路由参数中获取 platform
+const routePlatform = computed(() => {
+  const p = route.query.platform;
+  return p !== undefined && p !== '' ? Number(p) : undefined;
+});
+
+// 从路由参数中获取 customerId(大客户分类场景)
+const routeCustomerId = computed(() => {
+  const cid = route.query.customerId;
+  return cid !== undefined && cid !== '' ? String(cid) : undefined;
+});
 
 const categoryList = ref<CategoryVO[]>([]);
 const loading = ref(true);
 const showSearch = ref(true);
 const categoryOptions = ref<CategoryOptionsType[]>([]);
+// A10 分类列表(用于分类编号选择框)
+const a10Options = ref<CategoryA10VO[]>([]);
+// A10 分类树形结构(用于 el-tree-select)
+const a10TreeOptions = ref<any[]>([]);
 // 存储懒加载的子节点加载状态和 resolve 函数
 const lazyTreeNodeMap = ref<Map<string | number, { tree: any; treeNode: any; resolve: (data: CategoryVO[]) => void }>>(new Map());
 
@@ -202,6 +224,7 @@ const initFormData: CategoryForm = {
   parentId: undefined,
   sort: 0,
   platform: undefined,
+  customerId: undefined,
   isShow: 1,
   isShowGps: 0,
   oneLable1: undefined,
@@ -213,7 +236,9 @@ const initFormData: CategoryForm = {
 const data = reactive<PageData<CategoryForm, Partial<CategoryQuery>>>({
   form: {...initFormData},
   queryParams: {
-    categoryName: undefined
+    categoryName: undefined,
+    platform: undefined as number | undefined,
+    customerId: undefined as string | number | undefined
   },
   rules: {
     categoryName: [
@@ -233,7 +258,7 @@ const getList = async () => {
   // 清空懒加载缓存
   lazyTreeNodeMap.value.clear();
   // 只加载顶级分类(parentId = 0)
-  const res = await listCategory({ ...queryParams.value, parentId: 0 });
+  const res = await listCategory({ ...queryParams.value, parentId: 0, platform: routePlatform.value, customerId: routeCustomerId.value });
   const data = (res as any).rows || res.data || [];
   // 根据 hasChildren 字段标记是否有子节点
   categoryList.value = data.map((item: CategoryVO) => ({
@@ -248,7 +273,7 @@ const loadChildren = async (row: CategoryVO, treeNode: any, resolve: (data: Cate
   // 存储加载状态,便于刷新时重新加载
   lazyTreeNodeMap.value.set(row.id, { tree: row, treeNode, resolve });
   try {
-    const res = await listCategory({ parentId: row.id });
+    const res = await listCategory({ parentId: row.id, platform: routePlatform.value, customerId: routeCustomerId.value });
     const data = (res as any).rows || res.data || [];
     // 标记子节点是否还有子级
     const children = data.map((item: CategoryVO) => ({
@@ -296,10 +321,19 @@ const refreshLazyNodes = () => {
   });
 };
 
+/** 加载 A10 分类选项列表 */
+const loadA10Options = async () => {
+  const res = await listCategoryA10();
+  const list = (res as any).rows || res.data || [];
+  a10Options.value = list;
+  // 构建树形结构
+  a10TreeOptions.value = proxy?.handleTree<any>(list, 'id') || [];
+}
+
 /** 新增按钮操作 */
 const handleAdd = async (row?: CategoryVO) => {
   reset();
-  const res = await listCategory();
+  const res = await listCategory({ platform: routePlatform.value, customerId: routeCustomerId.value });
   const responseData = (res as any).rows || res.data || [];
   const data = proxy?.handleTree<CategoryOptionsType>(responseData, 'id');
   if (data) {
@@ -307,6 +341,14 @@ const handleAdd = async (row?: CategoryVO) => {
     if (row && row.id) {
       form.value.parentId = row?.id;
     }
+    // 预填充路由中的平台
+    if (routePlatform.value !== undefined) {
+      form.value.platform = routePlatform.value;
+    }
+    // 预填充路由中的大客户ID
+    if (routeCustomerId.value !== undefined) {
+      form.value.customerId = routeCustomerId.value;
+    }
     dialog.visible = true;
     dialog.title = '添加产品分类';
   }
@@ -317,7 +359,7 @@ const handleUpdate = async (row: CategoryVO) => {
   reset();
   const res = await getCategory(row.id);
   form.value = res.data;
-  const response = await listCategoryExcludeChild(row.id);
+  const response = await listCategoryExcludeChild(row.id, routePlatform.value);
   // 根据后端返回结构,如果是 TableDataInfo 则用 rows,如果是直接数组则用 data
   const responseData = (response as any).rows || response.data || [];
   const data = proxy?.handleTree<CategoryOptionsType>(responseData, 'id');
@@ -340,6 +382,14 @@ const handleUpdate = async (row: CategoryVO) => {
 const submitForm = () => {
   categoryFormRef.value?.validate(async (valid: boolean) => {
     if (valid) {
+      // 统一使用路由中的 platform 提交
+      if (routePlatform.value !== undefined) {
+        form.value.platform = routePlatform.value;
+      }
+      // 统一使用路由中的 customerId 提交
+      if (routeCustomerId.value !== undefined) {
+        form.value.customerId = routeCustomerId.value;
+      }
       form.value.id ? await updateCategory(form.value) : await addCategory(form.value);
       proxy?.$modal.msgSuccess('操作成功');
       dialog.visible = false;
@@ -362,6 +412,20 @@ const handleSetReviewer = (row: CategoryVO) => {
   userSelectRef.value?.open();
 };
 
+/** 商品管理按钮操作 */
+const handleProductManage = (row: CategoryVO) => {
+  const query: Record<string, string> = {
+    categoryId: String(row.id)
+  };
+  if (routePlatform.value !== undefined) {
+    query.platform = String(routePlatform.value);
+  }
+  if (routeCustomerId.value !== undefined) {
+    query.customerId = routeCustomerId.value;
+  }
+  router.push({ path: '/product/category/categoryProduct', query });
+};
+
 /** 审核员选择回调 */
 const handleReviewerSelected = async (users: UserVO[]) => {
   if (!currentReviewerCategory.value || users.length === 0) return;
@@ -377,5 +441,7 @@ const handleReviewerSelected = async (users: UserVO[]) => {
 
 onMounted(() => {
   getList();
+  // 页面加载时预加载 A10 分类树
+  loadA10Options();
 });
 </script>

+ 1 - 1
src/views/product/pool/reviewDetail.vue

@@ -157,7 +157,7 @@
         <el-table-column label="项目平台价" align="center" prop="platformPrice" width="100" />
         <el-table-column label="商品状态" align="center" width="80">
           <template #default="scope">
-            <el-tag v-if="scope.row.productStatus === '1'" type="success">已上架</el-tag>
+            <el-tag v-if="scope.row.productStatus === 1" type="success">已上架</el-tag>
             <el-tag v-else-if="scope.row.productStatus === '0'" type="warning">下架</el-tag>
             <el-tag v-else-if="scope.row.productStatus === '2'" type="info">上架中</el-tag>
             <el-tag v-else type="info">未知</el-tag>

+ 1 - 1
src/views/product/poolLink/index.vue

@@ -151,7 +151,7 @@
         <el-table-column label="项目平台价" align="center" prop="platformPrice" width="100" />
         <el-table-column label="商品状态" align="center" width="80">
           <template #default="scope">
-            <el-tag v-if="scope.row.productStatus === '1'" type="success">上架</el-tag>
+            <el-tag v-if="scope.row.productStatus === 1" type="success">上架</el-tag>
             <el-tag v-else type="warning">下架</el-tag>
           </template>
         </el-table-column>

+ 1 - 1
src/views/product/poolLink/index1.vue

@@ -157,7 +157,7 @@
         <el-table-column label="项目平台价" align="center" prop="platformPrice" width="100" />
         <el-table-column label="商品状态" align="center" width="80">
           <template #default="scope">
-            <el-tag v-if="scope.row.productStatus === '1'" type="success">已上架</el-tag>
+            <el-tag v-if="scope.row.productStatus === 1" type="success">已上架</el-tag>
             <el-tag v-else-if="scope.row.productStatus === '0'" type="warning">下架</el-tag>
             <el-tag v-else-if="scope.row.productStatus === '2'" type="info">上架中</el-tag>
             <el-tag v-else type="info">未知</el-tag>