浏览代码

feat(goods): 重构商品编辑页面

- 更新商品编辑页面的表单结构和字段
-移除不必要的规格相关代码
- 调整商品详情和购买须知等字段的名称
- 更新商品编辑和详情获取的 API 调用
- 优化图片上传和处理逻辑
tangy 1 月之前
父节点
当前提交
17a2dafa97
共有 6 个文件被更改,包括 232 次插入356 次删除
  1. 2 2
      src/api/goods/list.ts
  2. 16 15
      src/components/upload/index.vue
  3. 42 122
      src/views/goods/list/edit.vue
  4. 2 2
      src/views/goods/list/index.vue
  5. 4 4
      src/views/material/index.vue
  6. 166 211
      src/views/shop/info.vue

+ 2 - 2
src/api/goods/list.ts

@@ -2,12 +2,12 @@ import request from '@/utils/request'
 
 // 商品列表
 export function goodsPage(params?: any) {
-    return request.get({url: '/product/list', params})
+    return request.get({url: '/product/listByShop', params})
 }
 
 // 商品列表
 export function goodsEdit(params?: any) {
-    return request.get({url: '/product/save', params})
+    return request.post({url: '/product/save', params})
 }
 
 // 添加商品

+ 16 - 15
src/components/upload/index.vue

@@ -107,27 +107,28 @@ export default defineComponent({
                 ...props.data,
                 fileName: rawFile.name
             }
-            
-            let q = 0.5
-            if (rawFile.size > 1000000 && rawFile.size < 5000000) {
+            if(props.type === 'image'){
+              let q = 0.5
+              if (rawFile.size > 1000000 && rawFile.size < 5000000) {
                 q = 0.5
-            } else if (rawFile.size >= 5000000 && rawFile.size < 10000000) {
+              } else if (rawFile.size >= 5000000 && rawFile.size < 10000000) {
                 q = 0.25
-            } else if (rawFile.size >= 10000000) {
+              } else if (rawFile.size >= 10000000) {
                 q = 0.1
-            } else {
+              } else {
                 return true
-            }
-            return new Promise((resolve) => {
+              }
+              return new Promise((resolve) => {
                 new ImageCompressor(rawFile, {
-                    quality: q, //压缩质量
-                    checkOrientation: false, //图片翻转,默认为false
-                    success(result: any) {
-                        console.log(result)
-                        resolve(result)
-                    }
+                  quality: q, //压缩质量
+                  checkOrientation: false, //图片翻转,默认为false
+                  success(result: any) {
+                    console.log(result)
+                    resolve(result)
+                  }
                 })
-            })
+              })
+            }
         }
 
         const handleProgress = (event: any, file: any, fileLists: any[]) => {

+ 42 - 122
src/views/goods/list/edit.vue

@@ -103,10 +103,10 @@
                 </el-select>
               </div>
             </el-form-item>
-            <el-form-item label="购买须知" prop="purchaseNotice">
+            <el-form-item label="购买须知" prop="needKnown">
               <div class="w-32vw">
                 <el-input
-                    v-model="formData.purchaseNotice"
+                    v-model="formData.needKnown"
                     placeholder="请输入购买须知"
                     show-word-limit
                     clearable
@@ -146,9 +146,9 @@
           </div>
         </div>
         <div class="xl:flex">
-          <el-form-item label="商品详情" prop="content">
+          <el-form-item label="商品详情" prop="detail">
             <div style="width: 100%">
-              <editor v-model="formData.content" :height="500"/>
+              <editor v-model="formData.detail" :height="500"/>
             </div>
           </el-form-item>
         </div>
@@ -165,40 +165,40 @@
                 />
               </div>
             </el-form-item>
-            <el-form-item label="已售数量" prop="title">
+            <el-form-item label="已售数量" prop="saleNum">
               <div class="w-32vw">
                 <el-input-number
-                    v-model="formData.summary"
+                    v-model="formData.saleNum"
                     :precision="2"
                     :min="0.01"
                     controls-position="right"
                 />
               </div>
             </el-form-item>
-            <el-form-item label="商品推荐" prop="title">
+            <el-form-item label="商品推荐" prop="recommndType">
               <div class="w-32vw">
                 <el-input-number
-                    v-model="formData.summary"
+                    v-model="formData.recommndType"
                     :precision="2"
                     :min="0.01"
                     controls-position="right"
                 />
               </div>
             </el-form-item>
-            <el-form-item label="会员专属" prop="title">
+            <el-form-item label="会员专属" prop="onlyMember">
               <div class="w-32vw">
                 <el-input-number
-                    v-model="formData.summary"
+                    v-model="formData.onlyMember"
                     :precision="2"
                     :min="0.01"
                     controls-position="right"
                 />
               </div>
             </el-form-item>
-            <el-form-item label="买就送" prop="title">
+            <el-form-item label="买就送" prop="buyToGift">
               <div class="w-32vw">
                 <el-input-number
-                    v-model="formData.summary"
+                    v-model="formData.buyToGift"
                     :precision="2"
                     :min="0.01"
                     controls-position="right"
@@ -219,26 +219,31 @@
 import type {FormInstance} from 'element-plus'
 import feedback from '@/utils/feedback'
 import {useDictOptions} from '@/hooks/useDictOptions'
-import {articleAdd, articleCateAll, articleDetail, articleEdit} from '@/api/article'
 import useMultipleTabs from '@/hooks/useMultipleTabs'
 import Editor from '@/components/editor/index.vue'
 import {goodsCategoryPage} from "@/api/goods/category";
+import {goodsEdit, goodsDetail} from "@/api/goods/list";
 
 const route = useRoute()
 const router = useRouter()
 const formData = reactive<any>({
-  id: '',
+  id: null,
+  shopId: null,
   title: '',
-  image: '',
-  cid: '',
-  intro: '',
-  author: '',
-  content: '',
-  visit: 0,
+  productCategoryId: null,
+  price: null,
+  originalPrice: null,
+  stock: 0,
   sort: 0,
+  unit: 0,
+  tags: 0,
   isShow: 1,
-  summary: 0,
-  specs: [] // 规格
+  needKnown: null,
+  guarantee: null,
+  image: '',
+  mainResourceList: null,
+  video: '',
+  detail: ''
 })
 const goodsTagOption = [{
   value: '日用品',
@@ -268,7 +273,7 @@ const rules = reactive({
 
 // getDetails 函数修改
 const getDetails = async () => {
-  const data = await articleDetail({
+  const data = await goodsDetail({
     id: route.query.id
   })
   Object.keys(formData).forEach((key) => {
@@ -278,64 +283,29 @@ const getDetails = async () => {
       formData[key] = Number(formData[key])
     }
   })
-
-  // 转换规格数据
-  if (data.specsList && data.specsList.length > 0) {
-    const specsMap = new Map()
-    data.specsList.forEach((spec: { name: string; value: string; id: number }) => {
-      if (!specsMap.has(spec.name)) {
-        specsMap.set(spec.name, {
-          name: spec.name,
-          items: [],
-          inputVisible: false,
-          inputValue: ''
-        })
-      }
-      specsMap.get(spec.name).items.push({
-        id: spec.id,
-        tag: spec.value
-      })
-    })
-    formData.specs = Array.from(specsMap.values())
-  }
 }
 
 const handleSave = async () => {
   await formRef.value?.validate()
-  if (formData.specs && formData.specs.length > 5) {
-    feedback.msgWarning('最多添加5个规格')
-    return
-  }
-  const specsList: Array<{
-    name: string;
-    value: string;
-    status: number;
-    articleId: number | null;
-    id: number | null;
-    img: string | null;
-  }> = [];
-  formData.specs?.forEach((spec: { name: string; items: Array<{ id: number | null, tag: string }> }) => {
-    spec.items.forEach(item => {
-      specsList.push({
-        name: spec.name,
-        value: item.tag,
-        status: 1,
-        articleId: formData.id || null,
-        id: item.id || null,
-        img: null
-      })
-    })
-  })
 
   const submitData = {
-    ...formData,
-    specsList
+    ...formData
   }
-
+  if(formData.bannerImages){
+    submitData.mainResourceList = formData.bannerImages.map((item:any) => {
+      return {
+        resourceUrl: item
+      }
+    })
+  }
+  if(formData.tags){
+    submitData.tags = formData.tags.join(',')
+  }
+  feedback.msgSuccess('操作成功')
   if (route.query.id) {
-    await articleEdit(submitData)
+    await goodsEdit(submitData)
   } else {
-    await articleAdd(submitData)
+    await goodsEdit(submitData)
   }
   feedback.msgSuccess('操作成功')
   removeTab()
@@ -344,56 +314,6 @@ const handleSave = async () => {
 
 route.query.id && getDetails()
 
-// 添加规格
-const handleSpecs = () => {
-  if (!formData.specs) {
-    formData.specs = []
-  }
-  formData.specs.push({
-    name: '',
-    items: [],
-    inputVisible: false,
-    inputValue: ''
-  })
-}
-
-// 删除规格
-const removeSpec = (index: number) => {
-  formData.specs.splice(index, 1)
-}
-
-// 显示输入框
-const showInput = (specIndex: number) => {
-  formData.specs[specIndex].inputVisible = true
-  nextTick(() => {
-    InputRef.value?.input?.focus()
-  })
-}
-
-// 确认输入
-const handleInputConfirm = (specIndex: number) => {
-  const spec = formData.specs[specIndex]
-  if (spec.inputValue) {
-    spec.items.push({
-      id: null,
-      tag: spec.inputValue
-    })
-  }
-  spec.inputVisible = false
-  spec.inputValue = ''
-}
-
-// 删除标签
-const handleClose = (specIndex: number, tagIndex: number) => {
-  formData.specs[specIndex].items.splice(tagIndex, 1)
-}
-
-// 添加规格项
-const handleAddSpecItem = (index: number) => {
-  showInput(index)
-}
-
-const InputRef = ref()
 </script>
 <style>
 .w-32vw {

+ 2 - 2
src/views/goods/list/index.vue

@@ -25,8 +25,8 @@
           <el-select class="w-[280px]" v-model="queryParams.auditStatus">
             <el-option label="全部" value/>
             <el-option label="待审核" :value="0"/>
-            <el-option label="审核通过" :value="1"/>
-            <el-option label="审核拒绝" :value="2"/>
+            <el-option label="通过" :value="1"/>
+            <el-option label="已驳回" :value="2"/>
           </el-select>
         </el-form-item>
         <el-form-item>

+ 4 - 4
src/views/material/index.vue

@@ -29,10 +29,10 @@ const tabsMap = [
         type: 'image',
         name: '图片'
     },
-    // {
-    //     type: 'video',
-    //     name: '视频'
-    // }
+    {
+        type: 'video',
+        name: '视频'
+    }
 ]
 const activeTab = ref('image')
 </script>

+ 166 - 211
src/views/shop/info.vue

@@ -1,236 +1,191 @@
 <!-- 网站信息 -->
 <template>
-    <div class="website-information">
+  <div class="website-information">
+    <div style="display: flex">
+      <div style="width: 50%;">
         <el-form ref="formRef" :model="formData" label-width="120px">
-            <el-card shadow="never" class="!border-none">
-                <div class="text-xl font-medium mb-[20px]">店铺设置</div>
-                <el-form-item label="店铺名称" prop="name">
-                    <div class="w-80">
-                        <el-input
-                            v-model="formData.name"
-                            placeholder="请输入店铺名称"
-                            maxlength="20"
-                            show-word-limit
-                        ></el-input>
-                    </div>
-                </el-form-item>
-                <el-form-item label="店铺简介" prop="intro">
-                    <div class="w-80">
-                        <el-input
-                            v-model="formData.intro"
-                            :rows="5"
-                            type="textarea"
-                            placeholder="请输入店铺介绍"
-                            maxlength="90"
-                            show-word-limit
-                        ></el-input>
-                    </div>
-                </el-form-item>
-                <el-form-item label="店铺公告" prop="notice">
-                    <div class="w-80">
-                        <el-input
-                            v-model="formData.notice"
-                            :rows="5"
-                            type="textarea"
-                            placeholder="请输入店铺公告"
-                            maxlength="100"
-                            show-word-limit
-                        ></el-input>
-                    </div>
-                </el-form-item>
-                <el-form-item label="店铺图片" prop="image">
-                    <div>
-                        <material-picker v-model="formData.image" :limit="1" />
-                        <div class="form-tips">建议尺寸:100*100像素,支持jpg,jpeg,png格式</div>
-                    </div>
-                </el-form-item>
-                <el-form-item label="预支付" prop="prePay">
-                    <el-switch v-model="formData.prePay" :active-value="1" :inactive-value="0" />
-                </el-form-item>
-                <el-form-item label="店铺状态" prop="status">
-                    <el-switch v-model="formData.status" :active-value="1" :inactive-value="0" />
-                </el-form-item>
-                <!-- <el-form-item label="网站logo" prop="logo">
-                    <div>
-                        <material-picker v-model="formData.logo" :limit="1" />
-                        <div class="form-tips">建议尺寸:200*200像素,支持jpg,jpeg,png格式</div>
-                    </div>
-                </el-form-item>
-                <el-form-item label="登录页广告图" prop="backdrop">
-                    <div>
-                        <material-picker v-model="formData.backdrop" :limit="1" />
-                        <div class="form-tips">建议尺寸:400*400像素,支持jpg,jpeg,png格式</div>
-                    </div>
-                </el-form-item> -->
-            </el-card>
-            <!-- <el-card shadow="never" class="!border-none mt-4">
-                <div class="text-xl font-medium mb-[20px]">前台设置</div>
-                <el-form-item label="商城名称" prop="shopName">
-                    <div class="w-80">
-                        <el-input
-                            v-model="formData.shopName"
-                            placeholder="请输入店铺/商城名称"
-                            maxlength="30"
-                            show-word-limit
-                        ></el-input>
-                    </div>
-                </el-form-item>
-                <el-form-item label="商城LOGO" prop="shopLogo">
-                    <div>
-                        <material-picker v-model="formData.shopLogo" :limit="1" />
-                        <div class="form-tips">建议尺寸:100*100px,支持jpg,jpeg,png格式</div>
-                    </div>
-                </el-form-item>
-            </el-card>
-            <el-card shadow="never" class="!border-none mt-4">
-                <div class="text-xl font-medium mb-[20px]">PC端设置</div>
-                <el-form-item label="PC端LOGO" prop="pcLogo">
-                    <div>
-                        <material-picker v-model="formData.pcLogo" :limit="1" />
-                        <div class="form-tips">建议尺寸:120*28px,支持jpg,jpeg,png格式</div>
-                    </div>
-                </el-form-item>
-                <el-form-item label="网站标题" prop="pcTitle">
-                    <div class="w-80">
-                        <el-input
-                            v-model.trim="formData.pcTitle"
-                            placeholder="请输入PC端网站标题"
-                            maxlength="30"
-                            show-word-limit
-                        />
-                    </div>
-                </el-form-item>
-                <el-form-item label="网站图标" prop="pcIco">
-                    <div>
-                        <material-picker v-model="formData.pcIco" :limit="1" />
-                        <div class="form-tips">建议尺寸:100*100像素,支持jpg,jpeg,png格式</div>
-                    </div>
-                </el-form-item>
-                <el-form-item label="网站描述" prop="pcDesc">
-                    <div class="w-80">
-                        <el-input v-model.trim="formData.pcDesc" placeholder="请输入PC端网站描述" />
-                    </div>
-                </el-form-item>
-                <el-form-item label="网站关键词" prop="pcKeywords">
-                    <div class="w-80">
-                        <el-input
-                            v-model.trim="formData.pcKeywords"
-                            placeholder="请输入PC端网站关键词"
-                        />
-                    </div>
-                </el-form-item>
-            </el-card> -->
+          <el-card shadow="never" class="!border-none">
+            <div class="text-xl font-medium mb-[20px]">店铺信息</div>
+            <el-form-item label="店铺名称" prop="name">
+              <div class="w-80">
+                <el-input
+                    v-model="formData.name"
+                    placeholder="请输入店铺名称"
+                    maxlength="20"
+                    show-word-limit
+                ></el-input>
+              </div>
+            </el-form-item>
+            <el-form-item label="店铺简介" prop="intro">
+              <div class="w-80">
+                <el-input
+                    v-model="formData.intro"
+                    :rows="5"
+                    type="textarea"
+                    placeholder="请输入店铺介绍"
+                    maxlength="90"
+                    show-word-limit
+                ></el-input>
+              </div>
+            </el-form-item>
+            <el-form-item label="店铺公告" prop="notice">
+              <div class="w-80">
+                <el-input
+                    v-model="formData.notice"
+                    :rows="5"
+                    type="textarea"
+                    placeholder="请输入店铺公告"
+                    maxlength="100"
+                    show-word-limit
+                ></el-input>
+              </div>
+            </el-form-item>
+            <el-form-item label="店铺图片" prop="image">
+              <div>
+                <material-picker v-model="formData.image" :limit="1"/>
+                <div class="form-tips">建议尺寸:100*100像素,支持jpg,jpeg,png格式</div>
+              </div>
+            </el-form-item>
+            <el-form-item label="banner图片" prop="banner">
+              <div>
+                <material-picker v-model="formData.banner" :limit="3"/>
+                <div class="form-tips">建议尺寸:100*100像素,支持jpg,jpeg,png格式</div>
+              </div>
+            </el-form-item>
+<!--            <el-form-item label="预支付" prop="prePay">
+              <el-switch v-model="formData.prePay" :active-value="1" :inactive-value="0"/>
+            </el-form-item>-->
+          </el-card>
         </el-form>
-        <footer-btns v-perms="['setting:website:save']">
-            <el-button type="primary" @click="handleSubmit">保存</el-button>
-        </footer-btns>
+      </div>
+      <div style="width: 50%;">
+        <el-form label-width="120px">
+          <el-card shadow="never" class="!border-none">
+            <div class="text-xl font-medium mb-[20px]">&nbsp;</div>
+            <el-form-item label="联系人" prop="contactPsn">
+              <div class="w-80">
+                <el-input
+                    v-model="formData.contactPsn"
+                    placeholder="请输入联系人"
+                    clearable
+                />
+              </div>
+            </el-form-item>
+            <el-form-item label="联系方式" prop="contactTel">
+              <div class="w-80">
+                <el-input
+                    v-model="formData.contactTel"
+                    placeholder="请输入联系方式"
+                    clearable
+                />
+              </div>
+            </el-form-item>
+            <el-form-item label="身份证照">
+              <div style="display: flex">
+                <material-picker v-model="formData.idCardFront" :limit="1"/>
+                <material-picker v-model="formData.idCardBack" :limit="1"/>
+              </div>
+            </el-form-item>
+            <el-form-item label="资质证件">
+              <div style="display: flex">
+                <material-picker v-model="formData.businessLicense" :limit="1"/>
+                <material-picker v-model="formData.operatingLicense" :limit="1"/>
+              </div>
+            </el-form-item>
+            <el-form-item label="地址" prop="address">
+              <div class="w-80">
+                <el-input
+                    v-model="formData.address"
+                    placeholder="请输入地址"
+                    clearable
+                />
+              </div>
+            </el-form-item>
+            <el-form-item label="店铺状态" prop="status">
+              <el-switch v-model="formData.status" :active-value="1" :inactive-value="0"
+                         active-text="开始营业" inactive-text="暂停营业"/>
+            </el-form-item>
+          </el-card>
+        </el-form>
+      </div>
     </div>
+    <footer-btns v-perms="['setting:website:save']">
+      <el-button type="primary" @click="handleSubmit">保存</el-button>
+    </footer-btns>
+  </div>
 </template>
 
 <script lang="ts" setup name="webInformation">
-import { getShopConfig, saveShopConfig } from '@/api/shop'
+import {getShopConfig, saveShopConfig} from '@/api/shop'
 import feedback from '@/utils/feedback'
-import type { FormInstance } from 'element-plus'
+import type {FormInstance} from 'element-plus'
+
 const formRef = ref<FormInstance>()
 // 表单数据
 const formData = reactive({
-    id: '',
-    name: '', // 店铺名称
-    intro: '',
-    notice: '',
-    image: '',
-    status: '',
-    prePay: ''
+  id: null,
+  name: '', // 店铺名称
+  intro: '',
+  notice: '',
+  image: '',
+  status: '',
+  prePay: '',
+  banner: '',
+  contactPsn: '',
+  contactTel: '',
+  address: '',
+  idCardFront: '',
+  idCardBack: '',
+  businessLicense: '',
+  operatingLicense: ''
 })
 
-// 表单验证
-// const rules = {
-//     name: [
-//         {
-//             required: true,
-//             message: '请输入网站名称',
-//             trigger: ['blur']
-//         }
-//     ],
-//     favicon: [
-//         {
-//             required: true,
-//             message: '请选择网站图标',
-//             trigger: ['change']
-//         }
-//     ],
-//     logo: [
-//         {
-//             required: true,
-//             message: '请选择网站logo',
-//             trigger: ['change']
-//         }
-//     ],
-//     backdrop: [
-//         {
-//             required: true,
-//             message: '请选择登录页广告图',
-//             trigger: ['change']
-//         }
-//     ],
-//     shopName: [
-//         {
-//             required: true,
-//             message: '请输入店铺/商城名称',
-//             trigger: ['blur']
-//         }
-//     ],
-//     shopLogo: [
-//         {
-//             required: true,
-//             message: '请选择商城LOGO',
-//             trigger: ['change']
-//         }
-//     ],
-//     pcLogo: [
-//         {
-//             required: true,
-//             message: '请选择PC端LOGO',
-//             trigger: ['change']
-//         }
-//     ],
-//     pcTitle: [
-//         {
-//             required: true,
-//             message: '请输入PC端网站标题',
-//             trigger: ['blur']
-//         }
-//     ],
-//     pcIco: [
-//         {
-//             required: true,
-//             message: '请选择PC端网站图标',
-//             trigger: ['change']
-//         }
-//     ]
-// }
-
 // 获取店铺信息
 const getData = async () => {
-    const data = await getShopConfig()
-    for (const key in formData) {
-        //@ts-ignore
-        formData[key] = data[key]
-    }
-    if(!formData.image){//不能是null,会报错
-        formData.image = '';
-    }
+  const data = await getShopConfig()
+  for (const key in formData) {
+    //@ts-ignore
+    formData[key] = data[key]
+  }
+  if (formData.banner) {
+    formData.banner = formData.banner.split(',')
+  }
+  if (!formData.image) {//不能是null,会报错
+    formData.image = '';
+  }
+  if (!formData.banner) {//不能是null,会报错
+    formData.banner = '';
+  }
+  if (!formData.idCardFront) {//不能是null,会报错
+    formData.idCardFront = '';
+  }
+  if (!formData.idCardBack) {//不能是null,会报错
+    formData.idCardBack = '';
+  }
+  if (!formData.businessLicense) {//不能是null,会报错
+    formData.businessLicense = '';
+  }
+  if (!formData.operatingLicense) {//不能是null,会报错
+    formData.operatingLicense = '';
+  }
 }
 
 // 保存店铺信息
 const handleSubmit = async () => {
-    // await formRef.value?.validate()
-    await saveShopConfig(formData)
-    feedback.msgSuccess('操作成功')
-    getData()
+  console.log(formData)
+  if(formData.banner){
+    formData.banner = formData.banner.join(',')
+  }
+  await saveShopConfig(formData)
+  feedback.msgSuccess('操作成功')
+  getData()
 }
 
 getData()
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+.website-information{
+  background: #fff;
+}
+</style>