Bläddra i källkod

📖 MALL:商品编辑 => 简化 InfoForm 基础设置

YunaiV 1 år sedan
förälder
incheckning
efe702d383

+ 2 - 2
src/components/UploadFile/src/UploadImg.vue

@@ -16,7 +16,7 @@
       <template v-if="modelValue">
         <img :src="modelValue" class="upload-image" />
         <div class="upload-handle" @click.stop>
-          <div class="handle-icon" @click="editImg">
+          <div class="handle-icon" @click="editImg" v-if="!disabled">
             <Icon icon="ep:edit" />
             <span v-if="showBtnText">{{ t('action.edit') }}</span>
           </div>
@@ -24,7 +24,7 @@
             <Icon icon="ep:zoom-in" />
             <span v-if="showBtnText">{{ t('action.detail') }}</span>
           </div>
-          <div v-if="showDelete" class="handle-icon" @click="deleteImg">
+          <div v-if="showDelete && !disabled" class="handle-icon" @click="deleteImg">
             <Icon icon="ep:delete" />
             <span v-if="showBtnText">{{ t('action.del') }}</span>
           </div>

+ 1 - 1
src/components/UploadFile/src/UploadImgs.vue

@@ -28,7 +28,7 @@
             <Icon icon="ep:zoom-in" />
             <span>查看</span>
           </div>
-          <div class="handle-icon" @click="handleRemove(file)">
+          <div class="handle-icon" @click="handleRemove(file)" v-if="!disabled">
             <Icon icon="ep:delete" />
             <span>删除</span>
           </div>

+ 1 - 1
src/utils/index.ts

@@ -177,7 +177,7 @@ export const fileSizeFormatter = (row, column, cellValue) => {
  * @param target 目标对象
  * @param source 源对象
  */
-export const copyValueToTarget = (target, source) => {
+export const copyValueToTarget = (target: any, source: any) => {
   const newObj = Object.assign({}, target, source)
   // 删除多余属性
   Object.keys(newObj).forEach((key) => {

+ 22 - 28
src/views/mall/product/spu/form/BasicInfoForm.vue → src/views/mall/product/spu/form/InfoForm.vue

@@ -1,3 +1,4 @@
+<!-- 商品发布 - 基础设置 -->
 <template>
   <el-form ref="formRef" :model="formData" :rules="rules" label-width="120px" :disabled="isDetail">
     <el-form-item label="商品名称" prop="name">
@@ -49,10 +50,10 @@
       />
     </el-form-item>
     <el-form-item label="商品封面图" prop="picUrl">
-      <UploadImg v-model="formData.picUrl" height="80px" />
+      <UploadImg v-model="formData.picUrl" height="80px" :disabled="isDetail" />
     </el-form-item>
     <el-form-item label="商品轮播图" prop="sliderPicUrls">
-      <UploadImgs v-model:modelValue="formData.sliderPicUrls" />
+      <UploadImgs v-model:modelValue="formData.sliderPicUrls" :disabled="isDetail" />
     </el-form-item>
   </el-form>
 </template>
@@ -60,16 +61,14 @@
 import { PropType } from 'vue'
 import { copyValueToTarget } from '@/utils'
 import { propTypes } from '@/utils/propTypes'
-import { defaultProps, handleTree, treeToString } from '@/utils/tree'
+import { defaultProps, handleTree } from '@/utils/tree'
 import type { Spu } from '@/api/mall/product/spu'
 import * as ProductCategoryApi from '@/api/mall/product/category'
 import * as ProductBrandApi from '@/api/mall/product/brand'
 import { BrandVO } from '@/api/mall/product/brand'
+import { CategoryVO } from '@/api/mall/product/category'
 
 defineOptions({ name: 'ProductSpuBasicInfoForm' })
-
-const message = useMessage() // 消息弹窗
-
 const props = defineProps({
   propFormData: {
     type: Object as PropType<Spu>,
@@ -79,6 +78,8 @@ const props = defineProps({
   isDetail: propTypes.bool.def(false) // 是否作为详情组件
 })
 
+const message = useMessage() // 消息弹窗
+
 const formRef = ref() // 表单 Ref
 const formData = reactive<Spu>({
   name: '', // 商品名称
@@ -109,6 +110,7 @@ watch(
       return
     }
     copyValueToTarget(formData, data)
+    // TODO @puhui999:优化多文件上传,看看有没可能搞成返回 v-model 图片列表这种
     formData.sliderPicUrls = data['sliderPicUrls']?.map((item) => ({
       url: item
     }))
@@ -118,38 +120,30 @@ watch(
   }
 )
 
-/**
- * 表单校验
- */
+/** 表单校验 */
 const emit = defineEmits(['update:activeName'])
 const validate = async () => {
   // 校验表单
   if (!formRef) return
-  return await unref(formRef).validate((valid) => {
-    if (!valid) {
-      message.warning('商品信息未完善!!')
-      emit('update:activeName', 'basicInfo')
-      // 目的截断之后的校验
-      throw new Error('商品信息未完善!!')
-    } else {
-      // 校验通过更新数据
-      Object.assign(props.propFormData, formData)
-    }
-  })
+  try {
+    await unref(formRef)?.validate()
+    // 校验通过更新数据
+    Object.assign(props.propFormData, formData)
+  } catch (e) {
+    message.error('【基础设置】不完善,请填写相关信息')
+    emit('update:activeName', 'info')
+    throw e // 目的截断之后的校验
+  }
 }
 defineExpose({ validate })
 
-/** 获取分类的节点的完整结构 */
-const categoryList = ref<any[]>([]) // 分类树
-const formatCategoryName = (categoryId: number) => {
-  return treeToString(categoryList.value, categoryId)
-}
-
-const brandList = ref<BrandVO[]>([]) // 精简商品品牌列表
+/** 初始化 */
+const brandList = ref<BrandVO[]>([]) // 商品品牌列表
+const categoryList = ref<CategoryVO[]>([]) // 商品分类树
 onMounted(async () => {
   // 获得分类树
   const data = await ProductCategoryApi.getCategoryList({})
-  categoryList.value = handleTree(data, 'id', 'parentId')
+  categoryList.value = handleTree(data, 'id')
   // 获取商品品牌列表
   brandList.value = await ProductBrandApi.getSimpleBrandList()
 })

+ 9 - 10
src/views/mall/product/spu/form/index.vue

@@ -1,9 +1,9 @@
 <template>
   <ContentWrap v-loading="formLoading">
     <el-tabs v-model="activeName">
-      <el-tab-pane label="基础设置" name="basicInfo">
-        <BasicInfoForm
-          ref="basicInfoRef"
+      <el-tab-pane label="基础设置" name="info">
+        <InfoForm
+          ref="infoRef"
           v-model:activeName="activeName"
           :is-detail="isDetail"
           :propFormData="formData"
@@ -57,7 +57,7 @@
 import { cloneDeep } from 'lodash-es'
 import { useTagsViewStore } from '@/store/modules/tagsView'
 import * as ProductSpuApi from '@/api/mall/product/spu'
-import BasicInfoForm from './BasicInfoForm.vue'
+import InfoForm from './InfoForm.vue'
 import DescriptionForm from './DescriptionForm.vue'
 import OtherSettingsForm from './OtherSettingsForm.vue'
 import SkuForm from './SkuForm.vue'
@@ -73,9 +73,9 @@ const { params, name } = useRoute() // 查询参数
 const { delView } = useTagsViewStore() // 视图操作
 
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
-const activeName = ref('basicInfo') // Tag 激活的窗口
+const activeName = ref('info') // Tag 激活的窗口
 const isDetail = ref(false) // 是否查看详情
-const basicInfoRef = ref() // 商品信息 Ref
+const infoRef = ref() // 商品信息 Ref
 const skuRef = ref() // 商品规格 Ref
 const deliveryRef = ref() // 物流设置 Ref
 const descriptionRef = ref() // 商品详情 Ref
@@ -149,15 +149,14 @@ const getDetail = async () => {
 const submitForm = async () => {
   // 提交请求
   formLoading.value = true
-  // 三个表单逐一校验,如果有一个表单校验不通过则切换到对应表单,如果有两个及以上的情况则切换到最前面的一个并弹出提示消息
-  // 校验各表单
   try {
-    await unref(basicInfoRef)?.validate()
+    // 校验各表单
+    await unref(infoRef)?.validate()
     await unref(skuRef)?.validate()
     await unref(deliveryRef)?.validate()
     await unref(descriptionRef)?.validate()
     await unref(otherSettingsRef)?.validate()
-    // 深拷贝一份, 这样最终 server 端不满足,不需要恢复,
+    // 深拷贝一份, 这样最终 server 端不满足,不需要影响原始数据
     const deepCopyFormData = cloneDeep(unref(formData.value)) as ProductSpuApi.Spu
     deepCopyFormData.skus!.forEach((item) => {
       // 给sku name赋值