Prechádzať zdrojové kódy

feat(product): 更新产品名称自动拼接规则和供应商合同管理功能

- 修改产品名称自动拼接逻辑:从"品牌名+规格型号+产品分类+发票规格"改为"品牌+规格型号+【描述】+(单位:单位)
- 在产品基础页面添加商品描述字段并更新相关提示信息
- 移除三级分类选择时的多余代码调用
- 更新供应商授权页面路由返回逻辑,改为跳转到供应商授权列表页
- 移除供应商合约供货编辑页面中的供应商选择下拉框及相关API调用
- 从用户存储中获取供应商ID,移除供应商列表获取功能
- 添加供应商合约供货新增和编辑页面的路由配置
- 在供应商授权列表页面添加onActivated钩子以支持页面缓存激活时刷新数据
- 移除供应商合约供货列表页面的权限控制和供应商名称搜索条件
- 为合约供货列表查询自动设置当前登录供应商ID
- 在合约供货类型定义中添加供应商ID字段
- 更新产品审核查看页面的商品描述显示方式,移除富文本编辑器依赖
肖路 2 dní pred
rodič
commit
9c961bacdf

+ 5 - 0
src/api/supplier/contractsupply/types.ts

@@ -110,6 +110,11 @@ export interface ContractsupplyQuery extends PageQuery {
    */
   contractSupplyNo?: number;
 
+  /**
+   * 供应商ID
+   */
+  supplierId?: string | number;
+
   /**
    * 供应商名称
    */

+ 20 - 0
src/router/index.ts

@@ -114,6 +114,26 @@ export const constantRoutes: RouteRecordRaw[] = [
         meta: { title: '查看授权详情', activeMenu: '/supplier/author' }
       }
     ]
+  },  
+  {
+    path: '/supplier',
+    component: Layout,
+    hidden: true,
+    redirect: 'noredirect',
+    children: [
+      {
+        path: 'contractsupply/add',
+        component: () => import('@/views/supplier/contractsupply/add.vue'),
+        name: 'SupplierContractsupplyAdd',
+        meta: { title: '新增合约供货', activeMenu: '/supplier/contractsupply' }
+      },
+      {
+        path: 'contractsupply/edit/:id',
+        component: () => import('@/views/supplier/contractsupply/edit.vue'),
+        name: 'SupplierContractsupplyEdit',
+        meta: { title: '编辑合约供货', activeMenu: '/supplier/contractsupply' }
+      }
+    ]
   },
   {
     path: '/product',

+ 13 - 6
src/views/product/base/add.vue

@@ -183,9 +183,9 @@
                 type="textarea"
                 :rows="2"
                 disabled
-                placeholder="自动拼接:品牌名 + 规格型号 + 产品分类 + 发票规格"
+                placeholder="自动拼接:品牌+规格型号+【描述】+(单位:单位)"
               />
-              <div class="form-item-tip">A10产品名称由系统自动拼接:品牌名 + 规格型号 + 产品分类(三级分类)+ 发票规格,无需手动填写</div>
+              <div class="form-item-tip">A10产品名称由系统自动拼接:品牌+规格型号+【描述】+(单位:单位),无需手动填写</div>
             </el-form-item>
 
             <!-- 商品描述 -->
@@ -1546,14 +1546,21 @@ const handleSalesVolumeInput = (val: string) => {
   }
 };
 
-// A10产品名称自动拼接(品牌名 + 规格型号 + 产品分类 + 发票规格
+// A10产品名称自动拼接(品牌+规格型号+【描述】+(单位:单位)
 const a10ProductNameComputed = computed(() => {
   const brand = brandOptions.value.find((b) => Number(b.id) === Number(productForm.brandId));
   const brandName = brand?.brandName || '';
   const specificationsCode = productForm.specificationsCode || '';
-  const categoryName = selectedLevel3Name.value || '';
-  const invoiceSpecs = productForm.invoiceSpecs || '';
-  return [brandName, specificationsCode, categoryName, invoiceSpecs].filter((s) => s.trim()).join(' ');
+  const description = (productForm.productDescription || '').trim();
+  const unit = unitOptions.value.find((u: any) => Number(u.id) === Number(productForm.unitId));
+  const unitName = unit?.unitName || '';
+
+  const parts: string[] = [];
+  if (brandName.trim()) parts.push(brandName.trim());
+  if (specificationsCode.trim()) parts.push(specificationsCode.trim());
+  if (description) parts.push(`【${description}】`);
+  if (unitName.trim()) parts.push(`(单位:${unitName.trim()})`);
+  return parts.join(' ');
 });
 
 // 格式化价格为两位小数(不允许负数)

+ 15 - 11
src/views/product/baseAudit/add.vue

@@ -169,9 +169,9 @@
                 type="textarea"
                 :rows="2"
                 disabled
-                placeholder="自动拼接:品牌名 + 规格型号 + 产品分类 + 发票规格"
+                placeholder="自动拼接:品牌+规格型号+【描述】+(单位:单位)"
               />
-              <div class="form-item-tip">A10产品名称由系统自动拼接:品牌名 + 规格型号 + 产品分类(三级分类)+ 发票规格,无需手动填写</div>
+              <div class="form-item-tip">A10产品名称由系统自动拼接:品牌+规格型号+【描述】+(单位:单位),无需手动填写</div>
             </el-form-item>
 
             <!-- 商品描述 -->
@@ -233,7 +233,7 @@
               </el-col>
 
               <el-col :span="12">
-                <el-form-item label="单位:" disabled>
+                <el-form-item label="单位:" >
                   <el-select
                     v-model="productForm.unitId"
                     placeholder="请选择"
@@ -1521,14 +1521,21 @@ const handleSalesVolumeInput = (val: string) => {
   }
 };
 
-// A10产品名称自动拼接(品牌名 + 规格型号 + 产品分类 + 发票规格
+// A10产品名称自动拼接(品牌+规格型号+【描述】+(单位:单位)
 const a10ProductNameComputed = computed(() => {
   const brand = brandOptions.value.find((b) => Number(b.id) === Number(productForm.brandId));
   const brandName = brand?.brandName || '';
   const specificationsCode = productForm.specificationsCode || '';
-  const categoryName = selectedLevel3Name.value || '';
-  const invoiceSpecs = productForm.invoiceSpecs || '';
-  return [brandName, specificationsCode, categoryName, invoiceSpecs].filter((s) => s.trim()).join(' ');
+  const description = (productForm.productDescription || '').trim();
+  const unit = unitOptions.value.find((u: any) => Number(u.id) === Number(productForm.unitId));
+  const unitName = unit?.unitName || '';
+
+  const parts: string[] = [];
+  if (brandName.trim()) parts.push(brandName.trim());
+  if (specificationsCode.trim()) parts.push(specificationsCode.trim());
+  if (description) parts.push(`【${description}】`);
+  if (unitName.trim()) parts.push(`(单位:${unitName.trim()})`);
+  return parts.join(' ');
 });
 
 // 格式化价格为两位小数(不允许负数)
@@ -2032,10 +2039,7 @@ const restoreCategorySelection = async () => {
         if (level3) {
           categoryForm.bottomCategoryId = level3.id;
           selectedLevel3Name.value = level3.label;
-          console.log('设置三级分类名称:', selectedLevel3Name.value);
-          await loadCategoryAttributes(level3.id);
-        }
-      }
+          console.log('设置三级分类名称:', selectedLevel3Name.value); 
     }
   }
 };

+ 50 - 25
src/views/product/baseAudit/view.vue

@@ -38,9 +38,20 @@
                 type="textarea"
                 :rows="2"
                 disabled
-                placeholder="自动拼接:品牌名 + 规格型号 + 产品分类 + 发票规格"
+                placeholder="自动拼接:品牌+规格型号+【描述】+(单位:单位)"
+              />
+              <div class="form-item-tip">A10产品名称由系统自动拼接:品牌+规格型号+【描述】+(单位:单位),无需手动填写</div>
+            </el-form-item>
+
+            <!-- 商品描述 -->
+            <el-form-item label="商品说明:">
+              <el-input
+                v-model="productForm.productDescription"
+                :rows="3"
+                placeholder="请输入商品描述"
+                maxlength="30"
+                show-word-limit
               />
-              <div class="form-item-tip">A10产品名称由系统自动拼接:品牌名 + 规格型号 + 产品分类(三级分类)+ 发票规格,无需手动填写</div>
             </el-form-item>
 
             <!-- 规格型号 和 UPC(69)条码 -->
@@ -159,9 +170,9 @@
               <el-input v-model="productForm.promotionTitle" type="textarea" :rows="3" placeholder="请输入促销标题" maxlength="300" show-word-limit />
             </el-form-item>
 
-            <!-- 商品简介 -->
-            <el-form-item label="商品简介:">
-              <el-input v-model="productForm.productDescription" type="textarea" :rows="3" placeholder="请输入商品简介" maxlength="500" show-word-limit />
+            <!-- 商品说明 -->
+            <el-form-item label="商品说明:">
+              <el-input v-model="productForm.productExplain" type="textarea" :rows="3" placeholder="请输入商品说明" maxlength="500" show-word-limit />
             </el-form-item>
 
 
@@ -417,18 +428,8 @@
 
             <!-- 商品详情 -->
             <el-form-item label="商品详情:" required>
-              <el-tabs v-model="activeDetailTab" type="border-card">
-                <el-tab-pane label="电脑端详情" name="pc">
-                  <div class="view-disabled-wrapper">
-                    <Editor v-model="productForm.pcDetail" :height="400" :readOnly="true" />
-                  </div>
-                </el-tab-pane>
-                <el-tab-pane label="移动端详情" name="mobile">
-                  <div class="view-disabled-wrapper">
-                    <Editor v-model="productForm.mobileDetail" :height="400" :readOnly="true" />
-                  </div>
-                </el-tab-pane>
-              </el-tabs>
+              <div class="pc-detail-content" v-if="productForm.pcDetail" v-html="productForm.pcDetail"></div>
+              <div v-else class="text-gray-400">暂无详情</div>
             </el-form-item>
           </el-form>
         </el-card>
@@ -534,7 +535,6 @@ import { ref, reactive, computed, onMounted, watch, nextTick } from 'vue';
 import { useRoute, useRouter } from 'vue-router';
 import { ElMessage } from 'element-plus';
 import { Warning, ArrowRight, Check, Plus, CircleCheck, Search } from '@element-plus/icons-vue';
-import Editor from '@/components/Editor/index.vue';
 import UploadImage from '@/components/upload-image/index.vue';
 import TaxCodeSelect from '@/components/TaxCodeSelect/index.vue';
 import { categoryTreeVO, CategoryVO } from '@/api/product/category/types';
@@ -579,9 +579,6 @@ const productFormRef = ref();
 const serviceGuarantees = ref<(string | number)[]>([]);
 const installationServices = ref<string[]>([]);
 
-// 商品详情选项卡
-const activeDetailTab = ref('pc');
-
 // 轮播图URL数组(UI管理用)
 const carouselImages = ref<string[]>([]);
 
@@ -1176,14 +1173,21 @@ const handleSalesVolumeInput = (val: string) => {
   }
 };
 
-// A10产品名称自动拼接(品牌名 + 规格型号 + 产品分类 + 发票规格
+// A10产品名称自动拼接(品牌+规格型号+【描述】+(单位:单位)
 const a10ProductNameComputed = computed(() => {
   const brand = brandOptions.value.find((b) => Number(b.id) === Number(productForm.brandId));
   const brandName = brand?.brandName || '';
   const specificationsCode = productForm.specificationsCode || '';
-  const categoryName = selectedLevel3Name.value || '';
-  const invoiceSpecs = productForm.invoiceSpecs || '';
-  return [brandName, specificationsCode, categoryName, invoiceSpecs].filter((s) => s.trim()).join(' ');
+  const description = (productForm.productDescription || '').trim();
+  const unit = unitOptions.value.find((u: any) => Number(u.id) === Number(productForm.unitId));
+  const unitName = unit?.unitName || '';
+
+  const parts: string[] = [];
+  if (brandName.trim()) parts.push(brandName.trim());
+  if (specificationsCode.trim()) parts.push(specificationsCode.trim());
+  if (description) parts.push(`【${description}】`);
+  if (unitName.trim()) parts.push(`(单位:${unitName.trim()})`);
+  return parts.join(' ');
 });
 
 // 格式化价格为两位小数(不允许负数)
@@ -1789,5 +1793,26 @@ onMounted(async () => {
     opacity: 0.9;
     width: 100%;
   }
+
+  .pc-detail-content {
+    width: 100%;
+    line-height: 1.6;
+    color: #303133;
+    word-break: break-word;
+
+    :deep(img) {
+      max-width: 100%;
+      height: auto;
+    }
+
+    :deep(table) {
+      max-width: 100%;
+      border-collapse: collapse;
+    }
+
+    :deep(p) {
+      margin: 0 0 8px;
+    }
+  }
 }
 </style>

+ 1 - 1
src/views/supplier/author/edit.vue

@@ -1497,7 +1497,7 @@ const handleSubmit = async () => {
       ElMessage.success('提交成功');
     }
     
-    router.back();
+    router.push('/supplier/author');
   } catch (error) {
     console.error('提交失败:', error);
     ElMessage.error('提交失败,请重试');

+ 6 - 1
src/views/supplier/author/index.vue

@@ -154,7 +154,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref, onMounted, nextTick } from 'vue';
+import { ref, onMounted, onActivated, nextTick } from 'vue';
 import { useRouter } from 'vue-router';
 import { useUserStore } from '@/store/modules/user';
 import { getAuthorizeDetailList } from '@/api/supplier/supplierauthorize';
@@ -559,6 +559,11 @@ onMounted(async () => {
     getAuthorizationList()
   ]);
 });
+
+// 从缓存激活时刷新列表(例如从编辑页返回)
+onActivated(() => {
+  getAuthorizationList();
+});
 </script>
 
 <style scoped>

+ 4 - 26
src/views/supplier/contractsupply/edit.vue

@@ -27,18 +27,6 @@
               </el-select>
             </el-form-item>
           </el-col>
-          <el-col :span="8">
-            <el-form-item label="供应商" prop="supplierId">
-              <el-select v-model="form.supplierId" placeholder="请选择" style="width: 100%;" size="large">
-                <el-option
-                  v-for="item in supplierList"
-                  :key="item.id"
-                  :label="item.enterpriseName"
-                  :value="item.id"
-                />
-              </el-select>
-            </el-form-item>
-          </el-col>
         </el-row>
 
         <el-row :gutter="20">
@@ -171,18 +159,19 @@ import { ref, onMounted, reactive } from 'vue';
 import { useRoute, useRouter } from 'vue-router';
 import { ArrowLeft } from '@element-plus/icons-vue';
 import { getContractsupply, updateContractsupply } from '@/api/supplier/contractsupply';
-import { getCompanyList, listInfo } from '@/api/customer/info';
+import { getCompanyList } from '@/api/customer/info';
 import { ElMessage } from 'element-plus';
 import FileUpload from '@/components/FileUpload/index.vue';
 import Product from './components/Product.vue';
+import { useUserStore } from '@/store/modules/user';
 
 const route = useRoute();
 const router = useRouter();
+const userStore = useUserStore();
 
 const formRef = ref();
 const productList = ref<any[]>([]);
 const companyList = ref<any[]>([]);
-const supplierList = ref<any[]>([]);
 
 // 商品对话框相关
 const productDialog = reactive({
@@ -222,16 +211,6 @@ const getCompanyData = async () => {
   }
 };
 
-/** 获取供应商列表 */
-const getSupplierData = async () => {
-  try {
-    const res = await listInfo();
-    supplierList.value = res.rows || [];
-  } catch (e) {
-    console.error('获取供应商列表失败:', e);
-  }
-};
-
 /** 获取详情数据 */
 const getDetail = async () => {
   const id = route.params.id as string;
@@ -245,7 +224,7 @@ const getDetail = async () => {
         id: String(data.id ?? ''),
         contractSupplyNo: String(data.contractSupplyNo ?? ''),
         companyId: data.companyId ?? '',
-        supplierId: data.supplierId ?? '',
+        supplierId: (userStore.supplierId ?? data.supplierId) as any,
         supplyNo: data.supplyNo || '',
         supplierName: data.supplierName,
         startTime: data.startTime,
@@ -319,7 +298,6 @@ const handleSubmit = async () => {
 };
 
 onMounted(() => {
-  getSupplierData();
   getDetail();
   getCompanyData();
 });

+ 8 - 9
src/views/supplier/contractsupply/index.vue

@@ -8,10 +8,6 @@
               <el-input v-model="queryParams.contractSupplyNo" placeholder="请输入协议单号" clearable @keyup.enter="handleQuery" />
             </el-form-item>
 
-            <el-form-item label="供应商名称" prop="supplierName">
-              <el-input v-model="queryParams.supplierName" placeholder="供应商名称" clearable @keyup.enter="handleQuery" />
-            </el-form-item>
-
             <el-form-item label="开始时间" prop="startTime">
               <el-date-picker clearable
                 v-model="queryParams.startTime"
@@ -31,7 +27,7 @@
             <el-form-item>
               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
               <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-              <el-button type="primary" icon="Plus" @click="handleAdd" v-hasPermi="['supplier:contractsupply:add']">新增</el-button>
+              <el-button type="primary" icon="Plus" @click="handleAdd" >新增</el-button>
             </el-form-item>
 
 
@@ -72,9 +68,9 @@
         </el-table-column>
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
           <template #default="scope">
-            <el-button link type="primary" @click="handleAudit(scope.row)" v-hasPermi="['supplier:contractsupply:edit']">审核</el-button>
-            <el-divider direction="vertical" />
-            <el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['supplier:contractsupply:edit']">编辑</el-button>
+          
+          
+            <el-button link type="primary" @click="handleUpdate(scope.row)" >编辑</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -117,8 +113,10 @@
 import { listContractsupply, getContractsupply, delContractsupply, addContractsupply, updateContractsupply, auditContractsupply } from '@/api/supplier/contractsupply';
 import { ContractsupplyVO, ContractsupplyQuery, ContractsupplyForm } from '@/api/supplier/contractsupply/types';
 import { useRouter } from 'vue-router';
+import { useUserStore } from '@/store/modules/user';
 
 const router = useRouter();
+const userStore = useUserStore();
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { contract_supplier_status } = toRefs<any>(proxy?.useDict('contract_supplier_status'));
@@ -161,7 +159,6 @@ const data = reactive<PageData<ContractsupplyForm, ContractsupplyQuery>>({
     pageNum: 1,
     pageSize: 10,
     contractSupplyNo: undefined,
-    supplierName: undefined,
     startTime: undefined,
     endTime: undefined,
     params: {
@@ -176,6 +173,8 @@ const { queryParams, form, rules } = toRefs(data);
 /** 查询协议供货列表 */
 const getList = async () => {
   loading.value = true;
+  // 自动设置当前登录供应商的ID
+  queryParams.value.supplierId = userStore.supplierId!;
   const res = await listContractsupply(queryParams.value);
   contractsupplyList.value = res.rows;
   total.value = res.total;