HHE-5476 před 3 týdny
rodič
revize
1c7639b1b9

+ 25 - 15
api/merchant.js

@@ -5,21 +5,21 @@ import request from "@/utils/request.js";
  * @param
  */
 export function getSbmerchantInfo(data) {
-  return request.get("sbmerchant/info",data);
+  return request.get("sbmerchant/info", data);
 }
 /**
  * 扫描二维码访问商家
  * @param
  */
 export function footprintScan(data) {
-  return request.get("merchant/footprint/scan",data);
+  return request.get("merchant/footprint/scan", data);
 }
 /**
  * 查询当前登录用户的历史足迹列表
  * @param
  */
 export function footprintList(data) {
-  return request.get("merchant/footprint/list",data);
+  return request.get("merchant/footprint/list", data);
 }
 /**
  * 商家提交补货申请
@@ -29,7 +29,6 @@ export function restockSubmitAPI(data) {
   return request.post("merchant/restock/submit", data);
 }
 
-
 /**
  * 查询当前登录商户金属资产明细
  * @param
@@ -38,13 +37,14 @@ export function fetchMerchantMetalBalanceAPI(data) {
   return request.get("merchantgoldprincipal/statistics");
 }
 
-
 /**
  * 根据金属类型和增减类型查询流水记录
  * @param
  */
 export function fetchMerchantRecordAPI(params) {
-  return request.get(`merchantgoldprincipal/records?metalType=${params.metalType}&limit=${params.limit}&page=${params.page}&type=${params.type}`);
+  return request.get(
+    `merchantgoldprincipal/records?metalType=${params.metalType}&limit=${params.limit}&page=${params.page}&type=${params.type}`
+  );
 }
 
 /**
@@ -52,7 +52,9 @@ export function fetchMerchantRecordAPI(params) {
  * @param
  */
 export function fetchMerchantRestockListAPI(params) {
-	return request.get(`merchant/restock/list?metalType=${params.metalType}&limit=${params.limit}&page=${params.page}`);
+  return request.get(
+    `merchant/restock/list?metalType=${params.metalType}&limit=${params.limit}&page=${params.page}`
+  );
 }
 
 /**
@@ -60,14 +62,14 @@ export function fetchMerchantRestockListAPI(params) {
  * @param
  */
 export function merchantSalesSummary(data) {
-  return request.get(`order/merchant/sales/summary`,data);
+  return request.get(`order/merchant/sales/summary`, data);
 }
 /**
  * 获取商家销售汇总数据
  * @param
  */
 export function productsList(data) {
-  return request.get(`products`,data);
+  return request.get(`products`, data);
 }
 /**
  * 商品上架
@@ -88,28 +90,28 @@ export function productOffShell(id) {
  * @param
  */
 export function productCategory(data) {
-  return request.get(`category/list/tree`,data,{noAuth: true});
+  return request.get(`category/list/tree`, data, { noAuth: true });
 }
 /**
  * 获取运费模板
  * @param
  */
 export function templatesList(data) {
-  return request.get(`express/shipping/templates/list`,data);
+  return request.get(`express/shipping/templates/list`, data);
 }
 /**
  * 新增商品
  * @param
  */
 export function productSave(data) {
-  return request.post(`product/save`,data);
+  return request.post(`product/save`, data);
 }
 /**
  * 修改商品
  * @param
  */
 export function productUpdate(data) {
-  return request.post(`product/update`,data);
+  return request.post(`product/update`, data);
 }
 /**
  * 获取运费模板
@@ -130,5 +132,13 @@ export function productDelete(id) {
  * @param
  */
 export function batchStatus(data) {
-  return request.post(`batch/status`,data);
-}
+  return request.post(`batch/status`, data);
+}
+
+/**
+ * 获取商家类目
+ * @param
+ */
+export function getMerchantCategory(data) {
+  return request.get(`sbmerchant/category/list`, data);
+}

+ 6 - 4
config/app.js

@@ -1,15 +1,17 @@
-let domain = "https://www.shuibeibyg.com/front-api"; // 正式环境IP
+// let domain = "https://www.shuibeibyg.com/front-api"; // 正式环境IP
 // let domain = "https://test.shuibeibyg.com/front-api"; // 测试环境IP
 // let domain = 'http://192.168.100.199:8081' // 晋守桦IP
 // let domain = 'http://192.168.100.246:8081' // 韩朝龙IP
+let domain = "http://192.168.3.29:8081"; // 宏广IP
 let share = "https://www.shuibeibyg.com";
 
-let imgUrl = "https://sb-admin.oss-cn-shenzhen.aliyuncs.com/shuibei-mini/new-mini/" //服務器上图片地址
+let imgUrl =
+  "https://sb-admin.oss-cn-shenzhen.aliyuncs.com/shuibei-mini/new-mini/"; //服務器上图片地址
 
-// export const H5_BASE_URL = "http://192.168.3.10:5174"; // 本地测试
+export const H5_BASE_URL = "http://192.168.3.10:5174"; // 本地测试
 // export const H5_BASE_URL = "http://192.168.100.35:5175"; // 本地测试
 // export const H5_BASE_URL = "https://test.shuibeibyg.com/web-h5/"; // 测试环境H5地址
-export const H5_BASE_URL = "https://www.shuibeibyg.com/web-h5/"; // 正式环境H5地址
+// export const H5_BASE_URL = "https://www.shuibeibyg.com/web-h5/"; // 正式环境H5地址
 
 // PC 后台 API 地址(用于上传图片)
 export const HTTP_ADMIN_URL = domain;

+ 2 - 2
pages/merchantCenter/index.vue

@@ -230,7 +230,7 @@
 			{
 				src: `${HTTP_REQUEST_URL_IMG}setting/jinqian.png`,
 				name: '我的收益',
-				pageUrl: '',
+				pageUrl: '/pages/users/vault/wallet',
 				show: wdsyShow.value
 			},
 			{
@@ -309,7 +309,7 @@
 	// 功能点击
 	const handleFunctionClick = (url, name) => {
 		if (!url) return;
-		if (name == '库存管理' || name == '卡包管理') {
+		if (name == '库存管理' || name == '卡包管理'|| name == '我的收益') {
 			goDetail(url);
 		} else if (name == '我的商城') {
 			console.log(appStore.userInfo.merchant.id)

+ 182 - 35
pages/merchantCenters/releaseProduct.vue

@@ -32,6 +32,29 @@
           </template>
         </up-form-item>
 
+        <!-- 商家类目 -->
+        <up-form-item
+            class="form-item"
+            label="商家类目"
+            prop="merchantCategoryId"
+            :borderBottom="false"
+            @click="showMerchantCategory = true"
+            :required="true"
+            v-if="!isProductCenter"
+        >
+          <up-input
+              v-model="formData.merchantCategoryDisplayName"
+              disabled
+              disabledColor="#ffffff"
+              placeholder="请选择商家类目"
+              inputAlign="right"
+              border="none"
+          ></up-input>
+          <template #right>
+            <up-icon name="arrow-right"></up-icon>
+          </template>
+        </up-form-item>
+
         <!-- 商品信息 -->
         <view class="card-title">商品信息</view>
         <up-form-item
@@ -324,7 +347,7 @@
       <button class="submit" @click="submitForm">立即发布</button>
     </view>
 
-    <!-- 类选择弹窗 -->
+    <!-- 商品分类选择弹窗 -->
     <up-popup
         :show="showCategory"
         @close="showCategory = false"
@@ -350,7 +373,36 @@
         </view>
       </view>
     </up-popup>
-<!--    运费模板-->
+
+    <!-- 商家类目选择弹窗 -->
+    <up-popup
+        :show="showMerchantCategory"
+        @close="showMerchantCategory = false"
+        mode="bottom"
+        round="20"
+        :closeable="true"
+    >
+      <view class="popup-content">
+        <view class="popup-header">
+          <text class="popup-title">选择商家类目</text>
+        </view>
+
+        <category-selector
+            :categoryList="merchantCategoryData"
+            :selectedIds="formData.merchantCategoryId"
+            @change="onMerchantCategoryChange"
+            ref="merchantCategoryRef"
+            :multiple="false"
+        />
+
+        <view class="popup-actions">
+          <button class="action-btn cancel" @click="showMerchantCategory = false">取消</button>
+          <button class="action-btn confirm" @click="confirmMerchantCategory">确定</button>
+        </view>
+      </view>
+    </up-popup>
+
+    <!-- 运费模板 -->
     <up-picker :show="showTemp" v-model="formData.tempIds"  :columns="tempColumns" keyName="name" valueName ="id"
                confirmColor="#F8C008"
                @close="showTemp = false" @confirm="tempConfirm" @cancel="showTemp = false"></up-picker>
@@ -360,7 +412,7 @@
 <script setup>
 import { ref, computed, watch,nextTick } from 'vue';
 import { onShow,onLoad } from "@dcloudio/uni-app";
-import { productCategory,productSave,productUpdate,templatesList,productInfo } from "@/api/merchant";
+import { productCategory,productSave,productUpdate,templatesList,productInfo,getMerchantCategory } from "@/api/merchant";
 import CategorySelector from '@/components/CategorySelector';
 import { useAppStore } from "@/stores/app";
 import { useImageUpload } from "@/hooks/useImageUpload";
@@ -378,8 +430,10 @@ const formRef = ref(null);
 
 // 表单数据
 const formData = ref({
-  categoryIds: [], // 选中的分类ID数组
-  categoryDisplayName: '', // 显示的分类名称
+  categoryIds: [], // 选中的商品分类ID数组
+  categoryDisplayName: '', // 显示的商品分类名称
+  merchantCategoryId: [], // 选中的商家类目ID数组(单选:数组长度始终为1)
+  merchantCategoryDisplayName: '', // 显示的商家类目名称
   tempName: '', // 显示的运费模板名称
   tempIds: [],
   storeName: '',
@@ -411,6 +465,11 @@ const showCategory = ref(false);
 const categoryData = ref([]);
 const categoryRef = ref();
 
+// 商家类目相关变量
+const showMerchantCategory = ref(false);
+const merchantCategoryData = ref([]);
+const merchantCategoryRef = ref();
+
 const showTemp = ref(false);
 const tempColumns = ref([])
 // 图片列表
@@ -436,6 +495,14 @@ const rules = ref({
     message: '请选择商品分类',
     trigger: ['blur','change']
   },
+  // 商家类目验证规则:改为单选(数组长度必须为1)
+  merchantCategoryId: {
+    type: 'array',
+    required: true,
+    len: 1, // 新增:限制数组长度为1,确保单选
+    message: '请选择一个商家类目', // 文案优化:强调“一个”
+    trigger: ['blur','change']
+  },
   storeName: {
     type: 'string',
     required: true,
@@ -451,7 +518,7 @@ const rules = ref({
   storeInfo: {
     type: 'string',
     required: true,
-    message: '请输入商品关键字',
+    message: '请输入商品简介', 
     trigger: ['blur', 'change']
   },
   unitName: {
@@ -524,7 +591,6 @@ const rules = ref({
       if (!value || value.trim().length === 0) return false;
       return /^\d+$/.test(value);
     }
-
   },
 });
 
@@ -534,6 +600,7 @@ onShow(() => {
 })
 onLoad(async (options)=>{
   await getProductCategory();
+  await getMerchantCategoryList();
   await getTempData();
   console.log(options)
   if(options.id){
@@ -570,6 +637,25 @@ async function getProductCategory(){
   }
 }
 
+// 取商家类目列表
+async function getMerchantCategoryList(){
+  try {
+    const { data } = await getMerchantCategory();
+    console.log('原始商家类目数据:', data);
+    
+    merchantCategoryData.value = data.map(item => ({
+      id: item.id,
+      name: item.categoryName, 
+      child: [] 
+    }));
+    console.log('适配后的商家类目数据:', merchantCategoryData.value);
+
+  } catch (error) {
+    console.error('获取商家类目失败:', error);
+    uni.showToast({ title: '获取商家类目失败', icon: 'none' });
+  }
+}
+
 // 获取运费模板
 async function getTempData(){
   let obj = {
@@ -581,10 +667,11 @@ async function getTempData(){
     tempColumns.value[0] = data.list;
 
   } catch (error) {
-    console.error('获取商品分类失败:', error);
-    uni.showToast({ title: '获取分类失败', icon: 'none' });
+    console.error('获取运费模板失败:', error); 
+    uni.showToast({ title: '获取运费模板失败', icon: 'none' });
   }
 }
+
 const initFormValidation = async () => {
   await nextTick();
 
@@ -600,7 +687,7 @@ const initFormValidation = async () => {
     // 方法2:延迟触发字段验证
     setTimeout(async () => {
       // 逐个触发必填字段的验证
-      const requiredFields = ['categoryIds', 'storeName', 'keyword', 'storeInfo', 'unitName',
+      const requiredFields = ['categoryIds', 'merchantCategoryId', 'storeName', 'keyword', 'storeInfo', 'unitName',
         'tempIds', 'metalType', 'weight', 'laborCost', 'additionalFee',
         'stock', 'barCode'];
 
@@ -617,6 +704,7 @@ const initFormValidation = async () => {
     console.error('初始化表单验证状态失败:', error);
   }
 };
+
 // 获取商品详情
 async function getProductDetail(id){
   try {
@@ -626,15 +714,16 @@ async function getProductDetail(id){
     // 使用Object.assign确保响应式更新
     Object.assign(formData.value, {
       ...data,
-      // 确保categoryIds是数组格式
       categoryIds: data.cateId ? (Array.isArray(data.cateId) ? data.cateId : data.cateId.split(',')) : [],
+      merchantCategoryId: data.merchantCategoryId ? (Array.isArray(data.merchantCategoryId) ? data.merchantCategoryId : [data.merchantCategoryId]) : [],
       // 确保tempIds是数组格式
       tempIds: data.tempId ? [data.tempId] : []
     });
 
     productImages.value = [];
 
-    console.log('分类IDs:', formData.value.categoryIds);
+    console.log('商品分类IDs:', formData.value.categoryIds);
+    console.log('商家类目IDs:', formData.value.merchantCategoryId); 
     console.log('运费模板IDs:', formData.value.tempIds);
 
     // 等待DOM更新
@@ -642,8 +731,10 @@ async function getProductDetail(id){
 
     // 更新显示名称
     formData.value.categoryDisplayName = getCategoryDisplayName(formData.value.categoryIds);
+    formData.value.merchantCategoryDisplayName = getMerchantCategoryDisplayName(formData.value.merchantCategoryId);
     formData.value.tempName = formatterTemp(data.tempId);
-    console.log('分类显示名称:', formData.value.categoryDisplayName);
+    console.log('商品分类显示名称:', formData.value.categoryDisplayName);
+    console.log('商家类目显示名称:', formData.value.merchantCategoryDisplayName); 
 
     // 图片处理
     previewImages.value = data.image ? [{ url: data.image }] : [];
@@ -677,17 +768,22 @@ async function getProductDetail(id){
     descriptionText.value = data.content ? data.content.replace(/<[^>]*>/g, '').substring(0, 500) : '';
     formData.value.content = data.content || '';
 
-    // 设置分类选择器
+    // 设置商品分类选择器
     if (categoryRef.value && formData.value.categoryIds.length > 0) {
-
-      // 使用nextTick确保组件已渲染
       await nextTick();
-
       if (categoryRef.value.setSelectedIds) {
         categoryRef.value.setSelectedIds(formData.value.categoryIds);
       }
     }
 
+    // 设置商家类目选择器
+    if (merchantCategoryRef.value && formData.value.merchantCategoryId.length > 0) {
+      await nextTick();
+      if (merchantCategoryRef.value.setSelectedIds) {
+        merchantCategoryRef.value.setSelectedIds(formData.value.merchantCategoryId);
+      }
+    }
+
     // 重要:手动初始化表单验证状态
     await initFormValidation();
 
@@ -696,12 +792,13 @@ async function getProductDetail(id){
     uni.showToast({ title: '获取商品详情失败', icon: 'none' });
   }
 }
+
 // 运费模板id获取中文名
 function formatterTemp(id) {
-  // 假设 tempColumns 是一个数组
-  const foundItem = tempColumns.value[0].find(item => item.id == id);
+  const foundItem = tempColumns.value[0]?.find(item => item.id == id);
   return foundItem ? foundItem.name : '';
 }
+
 function tempConfirm(obj){
   formData.value.tempId = obj.value[0].id;
   formData.value.tempName = obj.value[0].name;
@@ -712,19 +809,24 @@ function tempConfirm(obj){
     }
   }, 100);
 }
-// 分类选择变化
+
+// 商品分类选择变化
 const onCategoryChange = (result) => {
-  console.log('分类选择变化:', result);
-  // 这里只更新显示,不直接更新表单数据,等用户点击确定
+  console.log('商品分类选择变化:', result);
+}
+
+// 商家类目选择变化
+const onMerchantCategoryChange = (result) => {
+  console.log('商家类目选择变化:', result);
 }
 
-// 确认分类选择
+// 确认商品分类选择
 const confirmCategory = () => {
   if (categoryRef.value) {
     const selectedIds = categoryRef.value.getSelectedIds()
 
     if (selectedIds.length === 0) {
-      uni.showToast({ title: '请至少选择一个分类', icon: 'none' })
+      uni.showToast({ title: '请至少选择一个商品分类', icon: 'none' })
       return
     }
 
@@ -733,7 +835,7 @@ const confirmCategory = () => {
     formData.value.categoryDisplayName = getCategoryDisplayName(selectedIds)
 
     showCategory.value = false
-    console.log('最终选中的分类ID:', selectedIds)
+    console.log('最终选中的商品分类ID:', selectedIds)
     // 触发校验
     setTimeout(() => {
       if (formRef.value) {
@@ -743,7 +845,38 @@ const confirmCategory = () => {
   }
 }
 
-// 根据选中的ID生成显示名称
+// 确认商家类目选择(核心修改:限制单选)
+const confirmMerchantCategory = () => {
+  if (merchantCategoryRef.value) {
+    let selectedIds = merchantCategoryRef.value.getSelectedIds()
+
+    // 核心修改1:限制只能选择一个商家类目
+    if (selectedIds.length === 0) {
+      uni.showToast({ title: '请选择一个商家类目', icon: 'none' })
+      return
+    }
+    // 如果选中多个,只保留第一个(强制单选)
+    if (selectedIds.length > 1) {
+      selectedIds = [selectedIds[0]]
+      uni.showToast({ title: '商家类目仅支持选择一个', icon: 'none' })
+    }
+
+    // 更新表单数据(数组长度始终为1)
+    formData.value.merchantCategoryId = selectedIds
+    formData.value.merchantCategoryDisplayName = getMerchantCategoryDisplayName(selectedIds)
+
+    showMerchantCategory.value = false
+    console.log('最终选中的商家类目ID(单选):', selectedIds)
+    // 触发校验
+    setTimeout(() => {
+      if (formRef.value) {
+        formRef.value.validateField('merchantCategoryId');
+      }
+    }, 100);
+  }
+}
+
+// 根据选中的ID生成商品分类显示名称
 const getCategoryDisplayName = (selectedIds) => {
   if (!selectedIds || selectedIds.length === 0) return ''
 
@@ -780,41 +913,51 @@ const getCategoryDisplayName = (selectedIds) => {
   return names.join('、')
 }
 
+// 根据选中的ID生成商家类目显示名称(优化:单选场景只取第一个名称)
+const getMerchantCategoryDisplayName = (selectedIds) => {
+  if (!selectedIds || selectedIds.length === 0) return ''
+
+  // 核心修改2:单选场景直接取第一个选中项的名称
+  const firstId = selectedIds[0]
+  const category = merchantCategoryData.value.find(item => item.id == firstId)
+  return category ? category.name : ''
+}
+
 async function getImage() {
   console.log(imageList.value)
   if (imageList.value.length > 0) {
     if (imageList.value[0].status == "success") {
       previewImages.value = imageList.value;
       console.log('previewImages.value',previewImages.value)
-      // change();
     } else {
       Toast({ title: "上传失败" });
     }
   }
   imageList.value = [];
 }
+
 async function getImageProduct() {
   if (imageList.value.length > 0) {
     if (imageList.value[0].status == "success") {
       productImages.value = [...productImages.value,...imageList.value];
-      // change();
     } else {
       Toast({ title: "上传失败" });
     }
   }
   imageList.value = [];
 }
+
 async function getImageProductGg() {
   if (imageList.value.length > 0) {
     if (imageList.value[0].status == "success") {
       productImagesGg.value = imageList.value;
-      // change();
     } else {
       Toast({ title: "上传失败" });
     }
   }
   imageList.value = [];
 }
+
 const onPreviewImageDelete =(e) => {
   previewImages.value.splice(e.index, 1);
 };
@@ -822,6 +965,7 @@ const onPreviewImageDelete =(e) => {
 const onProductImageDelete = (e) => {
   productImages.value.splice(e.index, 1);
 };
+
 const onProductImageGgDelete = (e) => {
   productImagesGg.value.splice(e.index, 1);
 };
@@ -851,8 +995,6 @@ const onUpinImage = (tempFiles, editorCtx) => {
   });
 };
 
-
-
 const validateForm = () => {
   try {
     if(!isProductCenter.value){
@@ -873,7 +1015,6 @@ const validateForm = () => {
       }
     }
 
-
     if (productImagesGg.value.length === 0) {
       uni.showToast({ title: '请上传商品规格图片', icon: 'none' });
       return;
@@ -911,6 +1052,7 @@ const validateForm = () => {
     return false;
   }
 };
+
 const submitForm = async () => {
   const valid = validateForm();
 
@@ -923,12 +1065,14 @@ const submitForm = async () => {
       submitData.image =previewImages.value[0].url;
       urlString = JSON.stringify(productImages.value.map(item => item.url));
     }else{
-      submitData.image =previewImages.value[0].info.url;
-      urlString = JSON.stringify(productImages.value.map(item => item.info.url));
+      submitData.image =previewImages.value[0].url;
+      urlString = JSON.stringify(productImages.value.map(item => item.url));
     }
     submitData.sliderImage =urlString;
     submitData.cateId =formData.value.categoryIds.join(',');
-
+    
+    // 核心修改3:merchantCateId改为数组格式(不再拼接字符串)
+    submitData.merchantCategoryId = formData.value.merchantCategoryId; // 直接赋值数组(长度为1)
 
     submitData.merchantId =parseInt(merchantInfo.id);
     submitData.specType = 0;
@@ -965,11 +1109,14 @@ const submitForm = async () => {
     })
   }
 }
+
 // 重置表单(用于新建场景)
 const resetForm = () => {
   formData.value = {
     categoryIds: [],
     categoryDisplayName: '',
+    merchantCategoryId: [], 
+    merchantCategoryDisplayName: '', 
     tempName: '',
     tempIds: [],
     storeName: '',