Browse Source

📖 MALL:商品编辑的简化

YunaiV 1 năm trước cách đây
mục cha
commit
c0905fdc8e

+ 0 - 25
src/views/mall/product/spu/form/BasicInfoForm.vue

@@ -47,17 +47,6 @@
     <el-form-item label="商品轮播图" prop="sliderPicUrls">
       <UploadImgs v-model:modelValue="formData.sliderPicUrls" />
     </el-form-item>
-    <!-- TODO 芋艿:这里要挪出去 -->
-    <el-form-item label="运费模板" prop="deliveryTemplateId">
-      <el-select v-model="formData.deliveryTemplateId" placeholder="请选择">
-        <el-option
-          v-for="item in deliveryTemplateList"
-          :key="item.id"
-          :label="item.name"
-          :value="item.id"
-        />
-      </el-select>
-    </el-form-item>
     <el-form-item label="品牌" prop="brandId">
       <el-select v-model="formData.brandId" placeholder="请选择">
         <el-option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id" />
@@ -71,15 +60,6 @@
     <template #brandId="{ row }">
       {{ brandList.find((item) => item.id === row.brandId)?.name }}
     </template>
-    <template #deliveryTemplateId="{ row }">
-      {{ deliveryTemplateList.find((item) => item.id === row.deliveryTemplateId)?.name }}
-    </template>
-    <template #specType="{ row }">
-      {{ row.specType ? '多规格' : '单规格' }}
-    </template>
-    <template #subCommissionType="{ row }">
-      {{ row.subCommissionType ? '单独设置' : '默认设置' }}
-    </template>
     <template #picUrl="{ row }">
       <el-image :src="row.picUrl" class="h-60px w-60px" @click="imagePreview(row.picUrl)" />
     </template>
@@ -146,7 +126,6 @@ const formData = reactive<Spu>({
   picUrl: '', // 商品封面图
   sliderPicUrls: [], // 商品轮播图
   introduction: '', // 商品简介
-  deliveryTemplateId: null, // 运费模版
   brandId: null // 商品品牌
 })
 const rules = reactive({
@@ -156,7 +135,6 @@ const rules = reactive({
   introduction: [required],
   picUrl: [required],
   sliderPicUrls: [required],
-  deliveryTemplateId: [required],
   brandId: [required]
 })
 
@@ -207,14 +185,11 @@ const formatCategoryName = (categoryId: number) => {
 }
 
 const brandList = ref([]) // 精简商品品牌列表
-const deliveryTemplateList = ref([]) // 运费模版
 onMounted(async () => {
   // 获得分类树
   const data = await ProductCategoryApi.getCategoryList({})
   categoryList.value = handleTree(data, 'id', 'parentId')
   // 获取商品品牌列表
   brandList.value = await ProductBrandApi.getSimpleBrandList()
-  // 获取运费模版
-  deliveryTemplateList.value = await ExpressTemplateApi.getSimpleTemplateList()
 })
 </script>

+ 105 - 0
src/views/mall/product/spu/form/DeliveryForm.vue

@@ -0,0 +1,105 @@
+<template>
+  <!-- 情况一:添加/修改 -->
+  <el-form
+    v-if="!isDetail"
+    ref="productSpuBasicInfoRef"
+    :model="formData"
+    :rules="rules"
+    label-width="120px"
+  >
+    <!-- TODO 芋艿:宽度!! -->
+    <!-- TODO 芋艿:这里要挪出去 -->
+    <el-form-item label="运费模板" prop="deliveryTemplateId">
+      <el-select v-model="formData.deliveryTemplateId" placeholder="请选择">
+        <el-option
+          v-for="item in deliveryTemplateList"
+          :key="item.id"
+          :label="item.name"
+          :value="item.id"
+        />
+      </el-select>
+    </el-form-item>
+  </el-form>
+
+  <!-- 情况二:详情 -->
+  <Descriptions v-if="isDetail" :data="formData" :schema="allSchemas.detailSchema">
+    <template #deliveryTemplateId="{ row }">
+      {{ deliveryTemplateList.find((item) => item.id === row.deliveryTemplateId)?.name }}
+    </template>
+  </Descriptions>
+</template>
+<script lang="ts" setup>
+import { PropType } from 'vue'
+import { copyValueToTarget } from '@/utils'
+import { propTypes } from '@/utils/propTypes'
+import { basicInfoSchema } from './spu.data'
+import type { Spu } from '@/api/mall/product/spu'
+import * as ExpressTemplateApi from '@/api/mall/trade/delivery/expressTemplate'
+
+defineOptions({ name: 'ProductSpuBasicInfoForm' })
+
+// ====== 商品详情相关操作 ======
+const { allSchemas } = useCrudSchemas(basicInfoSchema)
+
+// ====== end ======
+
+const message = useMessage() // 消息弹窗
+
+const props = defineProps({
+  propFormData: {
+    type: Object as PropType<Spu>,
+    default: () => {}
+  },
+  activeName: propTypes.string.def(''),
+  isDetail: propTypes.bool.def(false) // 是否作为详情组件
+})
+const productSpuBasicInfoRef = ref() // 表单 Ref
+const formData = reactive<Spu>({
+  deliveryTemplateId: null // 运费模版
+})
+const rules = reactive({
+  deliveryTemplateId: [required]
+})
+
+/**
+ * 将传进来的值赋值给 formData
+ */
+watch(
+  () => props.propFormData,
+  (data) => {
+    if (!data) {
+      return
+    }
+    copyValueToTarget(formData, data)
+  },
+  {
+    immediate: true
+  }
+)
+
+/**
+ * 表单校验
+ */
+const emit = defineEmits(['update:activeName'])
+const validate = async () => {
+  // 校验表单
+  if (!productSpuBasicInfoRef) return
+  return await unref(productSpuBasicInfoRef).validate((valid) => {
+    if (!valid) {
+      message.warning('商品信息未完善!!')
+      emit('update:activeName', 'delivery')
+      // 目的截断之后的校验
+      throw new Error('商品信息未完善!!')
+    } else {
+      // 校验通过更新数据
+      Object.assign(props.propFormData, formData)
+    }
+  })
+}
+defineExpose({ validate })
+
+const deliveryTemplateList = ref([]) // 运费模版
+onMounted(async () => {
+  deliveryTemplateList.value = await ExpressTemplateApi.getSimpleTemplateList()
+})
+</script>

+ 13 - 1
src/views/mall/product/spu/form/index.vue

@@ -1,7 +1,7 @@
 <template>
   <ContentWrap v-loading="formLoading">
     <el-tabs v-model="activeName">
-      <el-tab-pane label="基础信息" name="basicInfo">
+      <el-tab-pane label="基础设置" name="basicInfo">
         <BasicInfoForm
           ref="basicInfoRef"
           v-model:activeName="activeName"
@@ -17,6 +17,14 @@
           :propFormData="formData"
         />
       </el-tab-pane>
+      <el-tab-pane label="物流设置" name="delivery">
+        <DeliveryForm
+          ref="deliveryRef"
+          v-model:activeName="activeName"
+          :is-detail="isDetail"
+          :propFormData="formData"
+        />
+      </el-tab-pane>
       <el-tab-pane label="商品详情" name="description">
         <DescriptionForm
           ref="descriptionRef"
@@ -35,6 +43,7 @@
         />
       </el-tab-pane>
     </el-tabs>
+    <!-- TODO 芋艿:位置 -->
     <el-form>
       <el-form-item style="float: right">
         <el-button v-if="!isDetail" :loading="formLoading" type="primary" @click="submitForm">
@@ -53,6 +62,7 @@ import BasicInfoForm from './BasicInfoForm.vue'
 import DescriptionForm from './DescriptionForm.vue'
 import OtherSettingsForm from './OtherSettingsForm.vue'
 import SkuForm from './SkuForm.vue'
+import DeliveryForm from './DeliveryForm.vue'
 import { convertToInteger, floatToFixed2, formatToFraction } from '@/utils'
 
 defineOptions({ name: 'ProductSpuForm' })
@@ -68,6 +78,7 @@ const activeName = ref('basicInfo') // Tag 激活的窗口
 const isDetail = ref(false) // 是否查看详情
 const basicInfoRef = ref() // 商品信息 Ref
 const skuRef = ref() // 商品规格 Ref
+const deliveryRef = ref() // 物流设置 Ref
 const descriptionRef = ref() // 商品详情 Ref
 const otherSettingsRef = ref() // 其他设置 Ref
 // spu 表单数据
@@ -144,6 +155,7 @@ const submitForm = async () => {
   try {
     await unref(basicInfoRef)?.validate()
     await unref(skuRef)?.validate()
+    await unref(deliveryRef)?.validate()
     await unref(descriptionRef)?.validate()
     await unref(otherSettingsRef)?.validate()
     // 深拷贝一份, 这样最终 server 端不满足,不需要恢复,