From b7a362f33239b6a10df298eb34d623986b2aeb1e Mon Sep 17 00:00:00 2001
From: fanfan <franceesfan@163.com>
Date: Fri, 22 Mar 2024 14:34:49 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8C=BA=E5=9F=9F=E5=92=8C?=
 =?UTF-8?q?=E6=95=B4=E7=90=86=E5=95=86=E5=93=81=E7=BB=84=E5=90=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/components/SelectGoods/SelectGoods.vue |  30 +--
 src/views/goods/Create.vue                 | 299 +++++++++++++++------
 src/views/goods/Update.vue                 | 148 +++++++++-
 src/views/goods/modules/MultiSpec.vue      |  11 +-
 4 files changed, 363 insertions(+), 125 deletions(-)

diff --git a/src/components/SelectGoods/SelectGoods.vue b/src/components/SelectGoods/SelectGoods.vue
index 5a1d409..1cfff62 100644
--- a/src/components/SelectGoods/SelectGoods.vue
+++ b/src/components/SelectGoods/SelectGoods.vue
@@ -1,31 +1,6 @@
 <template>
   <div>
     <a-button @click="handleSelectGoods">选择商品</a-button>
-    <a-table
-      v-show="selectedItems.length"
-      class="table-goodsList"
-      rowKey="goods_id"
-      :columns="columns"
-      :dataSource="selectedItems"
-      :pagination="false"
-    >
-      <!-- 商品信息 -->
-      <template slot="item" slot-scope="item">
-        <GoodsItem
-          :data="{
-            image: item.goods_image,
-            imageAlt: '商品图片',
-            title: item.goods_name,
-            subtitle: `¥${item.goods_price_min}`
-          }"
-          :subTitleColor="true"
-        />
-      </template>
-      <!-- 操作项 -->
-      <span slot="action" slot-scope="text, item, index">
-        <a v-action:delete @click="handleDeleteItem(index)">删除</a>
-      </span>
-    </a-table>
     <GoodsModal
       ref="GoodsModal"
       :multiple="multiple"
@@ -40,7 +15,6 @@
 import PropTypes from 'ant-design-vue/es/_util/vue-types'
 import cloneDeep from 'lodash.clonedeep'
 import { GoodsModal } from '@/components/Modal'
-import { GoodsItem } from '@/components/Table'
 
 const columns = [
   {
@@ -67,8 +41,7 @@ const columns = [
 export default {
   name: 'SelectGoods',
   components: {
-    GoodsModal,
-    GoodsItem
+    GoodsModal
   },
   model: {
     prop: 'value',
@@ -145,6 +118,7 @@ export default {
     onChange () {
       const { multiple, selectedGoodsIds } = this
       const sGoodsIds = multiple ? selectedGoodsIds : (selectedGoodsIds.length ? selectedGoodsIds[0] : undefined)
+      this.$emit('select', multiple ? this.selectedItems : this.selectedItems[0])
       return this.$emit('change', sGoodsIds)
     }
 
diff --git a/src/views/goods/Create.vue b/src/views/goods/Create.vue
index bb8c63c..92a1832 100644
--- a/src/views/goods/Create.vue
+++ b/src/views/goods/Create.vue
@@ -53,26 +53,20 @@
             </a-form-item>
 
             <a-form-item label="是否大牌正品" :labelCol="labelCol" :wrapperCol="wrapperCol">
-              <a-radio-group
-                v-decorator="['is_brand', { initialValue: 0, rules: [{ required: true }] }]"
-              >
+              <a-radio-group v-decorator="['is_brand', { initialValue: 0, rules: [{ required: true }] }]">
                 <a-radio :value="0">否</a-radio>
                 <a-radio :value="1">是</a-radio>
               </a-radio-group>
             </a-form-item>
 
             <a-form-item label="是否新品首发" :labelCol="labelCol" :wrapperCol="wrapperCol">
-              <a-radio-group
-                v-decorator="['is_new', { initialValue: 0, rules: [{ required: true }] }]"
-              >
+              <a-radio-group v-decorator="['is_new', { initialValue: 0, rules: [{ required: true }] }]">
                 <a-radio :value="0">否</a-radio>
                 <a-radio :value="1">是</a-radio>
               </a-radio-group>
             </a-form-item>
             <a-form-item label="是否店内" :labelCol="labelCol" :wrapperCol="wrapperCol">
-              <a-radio-group
-                v-decorator="['is_in_store', { initialValue: 0, rules: [{ required: true }] }]"
-              >
+              <a-radio-group v-decorator="['is_in_store', { initialValue: 0, rules: [{ required: true }] }]">
                 <a-radio :value="0">否</a-radio>
                 <a-radio :value="1">是</a-radio>
               </a-radio-group>
@@ -106,8 +100,14 @@
               <div v-show="form.getFieldValue('is_ind_delivery_type')">
                 <a-form-item extra="需在 [设置 - 配送方式] 中,开启支持的配送方式才可生效">
                   <a-checkbox-group
-                    :options="[{ label: '快递配送', value: 10 }, { label: '上门自提', value: 20 }]"
-                    v-decorator="['delivery_type', { initialValue: [10, 20], rules: [{ required: true, message: '配送方式至少选择一个' }] }]"
+                    :options="[
+                      { label: '快递配送', value: 10 },
+                      { label: '上门自提', value: 20 },
+                    ]"
+                    v-decorator="[
+                      'delivery_type',
+                      { initialValue: [10, 20], rules: [{ required: true, message: '配送方式至少选择一个' }] },
+                    ]"
                   />
                 </a-form-item>
               </div>
@@ -127,29 +127,22 @@
                   v-for="(item, index) in formData.deliveryList"
                   :key="index"
                   :value="item.delivery_id"
-                >{{ item.name }}</a-select-option>
+                  >{{ item.name }}</a-select-option
+                >
               </a-select>
               <div class="form-item-help">
-                <router-link
-                  target="_blank"
-                  :to="{ path: '/setting/delivery/template/create' }"
-                >新增模板</router-link>
+                <router-link target="_blank" :to="{ path: '/setting/delivery/template/create' }">新增模板</router-link>
                 <a href="javascript:;" @click="onReloadDeliveryList">刷新</a>
               </div>
             </a-form-item>
             <a-form-item label="商品状态" :labelCol="labelCol" :wrapperCol="wrapperCol">
-              <a-radio-group
-                v-decorator="['status', { initialValue: 10, rules: [{ required: true }] }]"
-              >
+              <a-radio-group v-decorator="['status', { initialValue: 10, rules: [{ required: true }] }]">
                 <a-radio :value="10">上架</a-radio>
                 <a-radio :value="20">下架</a-radio>
               </a-radio-group>
             </a-form-item>
             <a-form-item label="商品排序" :labelCol="labelCol" :wrapperCol="wrapperCol" extra="数字越小越靠前">
-              <a-input-number
-                :min="0"
-                v-decorator="['sort', { initialValue: 100, rules: [{ required: true }] }]"
-              />
+              <a-input-number :min="0" v-decorator="['sort', { initialValue: 100, rules: [{ required: true }] }]" />
             </a-form-item>
           </div>
 
@@ -179,16 +172,14 @@
                 <a-input-number
                   :min="0.01"
                   :precision="2"
-                  v-decorator="['goods_price', { initialValue: 1, rules: [{ required: true, message: '请输入商品价格' }] }]"
+                  v-decorator="[
+                    'goods_price',
+                    { initialValue: 1, rules: [{ required: true, message: '请输入商品价格' }] },
+                  ]"
                 />
                 <span class="ml-10">元</span>
               </a-form-item>
-              <a-form-item
-                label="成本价"
-                :labelCol="labelCol"
-                :wrapperCol="wrapperCol"
-                extra="成本价仅用于商品页展示"
-              >
+              <a-form-item label="成本价" :labelCol="labelCol" :wrapperCol="wrapperCol" extra="成本价仅用于商品页展示">
                 <a-input-number :min="0" :precision="2" v-decorator="['cost_price']" />
                 <span class="ml-10">元</span>
               </a-form-item>
@@ -201,7 +192,10 @@
                 <a-input-number
                   :min="0"
                   :precision="0"
-                  v-decorator="['stock_num', { initialValue: 100, rules: [{ required: true, message: '请输入库存数量' }] }]"
+                  v-decorator="[
+                    'stock_num',
+                    { initialValue: 100, rules: [{ required: true, message: '请输入库存数量' }] },
+                  ]"
                 />
                 <span class="ml-10">件</span>
               </a-form-item>
@@ -213,15 +207,16 @@
               >
                 <a-input-number
                   :min="0"
-                  v-decorator="['goods_weight', { initialValue: 0, rules: [{ required: true, message: '请输入库存数量' }] }]"
+                  v-decorator="[
+                    'goods_weight',
+                    { initialValue: 0, rules: [{ required: true, message: '请输入库存数量' }] },
+                  ]"
                 />
                 <span class="ml-10">千克 (Kg)</span>
               </a-form-item>
             </div>
             <a-form-item label="库存计算方式" :labelCol="labelCol" :wrapperCol="wrapperCol">
-              <a-radio-group
-                v-decorator="['deduct_stock_type', { initialValue: 10, rules: [{ required: true }] }]"
-              >
+              <a-radio-group v-decorator="['deduct_stock_type', { initialValue: 10, rules: [{ required: true }] }]">
                 <a-radio :value="10">下单减库存</a-radio>
                 <a-radio :value="20">付款减库存</a-radio>
               </a-radio-group>
@@ -264,10 +259,8 @@
 
           <!-- 商品详情 -->
           <div class="tab-pane" v-show="tabKey == 2">
-            <a-form-item label="商品详情" :labelCol="labelCol" :wrapperCol="{span: 16}">
-              <Ueditor
-                v-decorator="['content', { rules: [{ required: true, message: '商品详情不能为空' }] }]"
-              />
+            <a-form-item label="商品详情" :labelCol="labelCol" :wrapperCol="{ span: 16 }">
+              <Ueditor v-decorator="['content', { rules: [{ required: true, message: '商品详情不能为空' }] }]" />
             </a-form-item>
           </div>
 
@@ -304,11 +297,9 @@
                 v-decorator="['serviceIds', { initialValue: formData.defaultServiceIds }]"
                 placeholder="请选择服务与承诺"
               >
-                <a-select-option
-                  v-for="(item, index) in formData.serviceList"
-                  :key="index"
-                  :value="item.service_id"
-                >{{ item.name }}</a-select-option>
+                <a-select-option v-for="(item, index) in formData.serviceList" :key="index" :value="item.service_id">{{
+                  item.name
+                }}</a-select-option>
               </a-select>
               <div class="form-item-help">
                 <router-link target="_blank" :to="{ path: '/goods/service/index' }">去新增</router-link>
@@ -321,9 +312,43 @@
               :wrapperCol="wrapperCol"
               extra="用户端展示的销量 = 初始销量 + 实际销量"
             >
-              <a-input-number v-decorator="['sales_initial', { initialValue: 0}]" />
+              <a-input-number v-decorator="['sales_initial', { initialValue: 0 }]" />
             </a-form-item>
-
+            <div>
+              <a-divider orientation="left">销售区域</a-divider>
+              <a-form-item label="销售区域" :labelCol="labelCol" :wrapperCol="{ span: 15 }">
+                <a-table
+                  v-show="ruleList.length"
+                  class="table-rules"
+                  :columns="columns"
+                  :dataSource="ruleList"
+                  :pagination="false"
+                  bordered
+                >
+                  <!-- 销售区域 -->
+                  <template slot="region_text" slot-scope="text, item, index">
+                    <p class="content">
+                      <span v-for="(province, pidx) in text" :key="pidx">
+                        <span>{{ province.name }}</span>
+                        <template v-if="province.citys.length">
+                          <span>(</span>
+                          <span class="city-name" v-for="(city, cidx) in province.citys" :key="cidx"
+                            >{{ city.name }}{{ province.citys.length > cidx + 1 ? '、' : '' }}</span
+                          >
+                          <span>)</span>
+                        </template>
+                        <span>{{ ' ' }}</span>
+                      </span>
+                    </p>
+                    <p class="operation">
+                      <a href="javascript:void(0);" class="edit" @click="handleEdit(index, item)">编辑</a>
+                      <a href="javascript:void(0);" class="delete" @click="handleDelete(index)">删除</a>
+                    </p>
+                  </template>
+                </a-table>
+                <a-button icon="environment" v-if="ruleList.length == 0" @click="handleAdd">点击添加销售区域</a-button>
+              </a-form-item>
+            </div>
             <div v-show="$module('market-points')">
               <a-divider orientation="left">积分设置</a-divider>
               <a-form-item
@@ -332,9 +357,7 @@
                 :wrapperCol="wrapperCol"
                 extra="开启后用户购买此商品将获得积分"
               >
-                <a-radio-group
-                  v-decorator="['is_points_gift', { initialValue: 1, rules: [{ required: true }] }]"
-                >
+                <a-radio-group v-decorator="['is_points_gift', { initialValue: 1, rules: [{ required: true }] }]">
                   <a-radio :value="1">开启</a-radio>
                   <a-radio :value="0">关闭</a-radio>
                 </a-radio-group>
@@ -345,9 +368,7 @@
                 :wrapperCol="wrapperCol"
                 extra="开启后用户购买此商品可以使用积分进行抵扣"
               >
-                <a-radio-group
-                  v-decorator="['is_points_discount', { initialValue: 1, rules: [{ required: true }] }]"
-                >
+                <a-radio-group v-decorator="['is_points_discount', { initialValue: 1, rules: [{ required: true }] }]">
                   <a-radio :value="1">开启</a-radio>
                   <a-radio :value="0">关闭</a-radio>
                 </a-radio-group>
@@ -390,17 +411,20 @@
                       :addonBefore="item.name"
                       addonAfter="折"
                       :inputProps="{ min: 0, max: 9.9 }"
-                      v-decorator="[`alone_grade_equity[grade_id:${item.grade_id}]`, {
-                        initialValue: formData.defaultUserGradeValue[item.grade_id], rules: [{ required: true, message: '折扣率不能为空' }]
-                      }]"
+                      v-decorator="[
+                        `alone_grade_equity[grade_id:${item.grade_id}]`,
+                        {
+                          initialValue: formData.defaultUserGradeValue[item.grade_id],
+                          rules: [{ required: true, message: '折扣率不能为空' }],
+                        },
+                      ]"
                     />
                   </a-form-item>
                 </div>
                 <div class="form-item-help">
-                  <p
-                    class="extra"
-                    v-if="form.getFieldValue('is_alone_grade')"
-                  >单独折扣:折扣率范围0.0-9.9,例如: 9.8代表98折,0代表不折扣</p>
+                  <p class="extra" v-if="form.getFieldValue('is_alone_grade')">
+                    单独折扣:折扣率范围0.0-9.9,例如: 9.8代表98折,0代表不折扣
+                  </p>
                   <p class="extra" v-else>默认折扣:默认为用户所属会员等级的折扣率</p>
                 </div>
               </a-form-item>
@@ -450,6 +474,7 @@
           <a-button type="primary" html-type="submit" :loading="isBtnLoading">提交</a-button>
         </a-form-item>
       </a-form>
+      <AreasModal ref="AreasModal" @handleSubmit="handleAreaSubmit" />
     </a-spin>
   </a-card>
 </template>
@@ -459,7 +484,12 @@ import * as GoodsApi from '@/api/goods'
 import { SelectImage, SelectVideo, Ueditor, InputNumberGroup } from '@/components'
 import GoodsModel from '@/common/model/goods/Index'
 import { GoodsType, MultiSpec } from './modules'
-
+import { AreasModal } from '@/components/Modal'
+const defaultItem = {
+  key: 0,
+  region: [],
+  region_text: [],
+}
 export default {
   components: {
     GoodsType,
@@ -467,9 +497,10 @@ export default {
     SelectVideo,
     Ueditor,
     InputNumberGroup,
-    MultiSpec
+    MultiSpec,
+    AreasModal,
   },
-  data () {
+  data() {
     return {
       // 默认的标签索引
       tabKey: 0,
@@ -483,37 +514,50 @@ export default {
       // 当前表单元素
       form: this.$form.createForm(this),
       // 表单数据
-      formData: GoodsModel.formData
+      formData: GoodsModel.formData,
+      checkList: [],
+      // 销售区域
+      ruleList: [],
+      // 销售区域表头
+      columns: [
+        {
+          title: '销售区域',
+          dataIndex: 'region_text',
+          width: '400px',
+          scopedSlots: { customRender: 'region_text' },
+        },
+      ],
+      // 城市总数
+      citysCount: null,
     }
   },
   // 初始化数据
-  created () {
+  created() {
     this.isLoading = true
     // 获取form所需的数据
-    GoodsModel.getFromData()
-      .then(() => {
-        this.isLoading = false
-      })
+    GoodsModel.getFromData().then(() => {
+      this.isLoading = false
+    })
   },
   methods: {
-
     // 手动强制更新页面
-    onForceUpdate (bool = false) {
+    onForceUpdate(bool = false) {
       this.$forceUpdate()
       // bool为true时再执行一次 $forceUpdate, 特殊情况下需执行两次,原因如下:
       // 第一次执行 $forceUpdate时, 新元素绑定v-decorator无法获取到form.getFieldValue
-      bool && setTimeout(() => {
-        this.$forceUpdate()
-      }, 10)
+      bool &&
+        setTimeout(() => {
+          this.$forceUpdate()
+        }, 10)
     },
 
     // 切换tab选项卡
-    handleTabs (key) {
+    handleTabs(key) {
       this.tabKey = key
     },
 
     // 刷新分类列表
-    onReloadCategoryList () {
+    onReloadCategoryList() {
       this.isLoading = true
       GoodsModel.getCategoryList().then(() => {
         this.isLoading = false
@@ -521,7 +565,7 @@ export default {
     },
 
     // 刷新服务与承诺列表
-    onReloadServiceList () {
+    onReloadServiceList() {
       this.isLoading = true
       GoodsModel.getServiceList().then(() => {
         this.isLoading = false
@@ -529,7 +573,7 @@ export default {
     },
 
     // 刷新配送模板列表
-    onReloadDeliveryList () {
+    onReloadDeliveryList() {
       this.isLoading = true
       GoodsModel.getDeliveryList().then(() => {
         this.isLoading = false
@@ -537,10 +581,12 @@ export default {
     },
 
     // 确认按钮
-    handleSubmit (e) {
+    handleSubmit(e) {
       e.preventDefault()
       // 表单验证
-      const { form: { validateFields } } = this
+      const {
+        form: { validateFields }, ruleList 
+      } = this
       validateFields((errors, values) => {
         // 定位到错误的tab选项卡
         if (errors) {
@@ -557,8 +603,9 @@ export default {
           // 记录多规格数据
           values.specData = MultiSpec.getFromSpecData()
         }
+        values.rules = ruleList
         // 整理商品分类ID集
-        values.categoryIds = values.categorys.map(item => item.value)
+        values.categoryIds = values.categorys.map((item) => item.value)
         delete values.categorys
         // 提交到后端api
         this.onFormSubmit(values)
@@ -567,14 +614,14 @@ export default {
     },
 
     // 定位到错误的tab选项卡
-    onTargetTabError (errors) {
+    onTargetTabError(errors) {
       // 表单字段与tabKey对应关系
       // 只需要必填字段就可
       const tabsFieldsMap = [
         ['goods_type', 'goods_name', 'categorys', 'imagesIds', 'delivery_id', 'is_ind_delivery_type', 'delivery_type'],
         ['spec_type', 'goods_price', 'is_restrict', 'restrict_total', 'restrict_single'],
         ['content'],
-        ['alone_grade_equity', 'first_money', 'second_money', 'third_money']
+        ['alone_grade_equity', 'first_money', 'second_money', 'third_money'],
       ]
       const field = Object.keys(errors).shift()
       for (const key in tabsFieldsMap) {
@@ -586,11 +633,11 @@ export default {
     },
 
     // 提交到后端api
-    onFormSubmit (values) {
+    onFormSubmit(values) {
       this.isLoading = true
       this.isBtnLoading = true
       GoodsApi.add({ form: values })
-        .then(result => {
+        .then((result) => {
           // 显示提示信息
           this.$message.success(result.message, 1.5)
           // 跳转到列表页
@@ -601,13 +648,89 @@ export default {
         .catch(() => {
           this.isBtnLoading = false
         })
-        .finally(() => this.isLoading = false)
-    }
+        .finally(() => (this.isLoading = false))
+    },
+    // 新增记录
+    handleAdd() {
+      const index = this.ruleList.length
+      const newItem = { ...defaultItem, key: index }
+      // 排除的城市id集(已存在的城市id集)
+      const excludedCityIds = this.getExcludedCityIds()
+      if (excludedCityIds.length === this.citysCount) {
+        this.$message.error('已选择了所有的区域', 0.8)
+        return false
+      }
+      // 显示选择地区对话框
+      this.handleAreasModal('add', index, newItem, excludedCityIds)
+    },
 
-  }
-}
+    // 编辑记录
+    handleEdit(index, item) {
+      // 排除的城市id集(已存在的城市id集)
+      const excludedCityIds = this.getExcludedCityIds()
+      // 显示选择地区对话框
+      this.handleAreasModal('edit', index, item, excludedCityIds)
+    },
+
+    // 选择地区后的回调
+    handleAreaSubmit(result) {
+      const {
+        custom: { scene, item },
+      } = result
+      item.region = result.selectedCityIds
+      item.region_text = result.selectedText
+      if (scene === 'add') {
+        this.ruleList.push(item)
+      }
+    },
+
+    // 排除的城市id集(已存在的城市id集)
+    getExcludedCityIds() {
+      const excludedCityIds = []
+      this.ruleList.forEach((item) => {
+        item.region.forEach((cityId) => {
+          excludedCityIds.push(cityId)
+        })
+      })
+      return excludedCityIds
+    },
 
+    // 显示选择地区对话框
+    handleAreasModal(scene, index, item, excludedCityIds) {
+      this.$refs.AreasModal.handle({ scene, index, item }, item.region, excludedCityIds)
+    },
+
+    // 删除记录
+    handleDelete(index) {
+      const app = this
+      const modal = this.$confirm({
+        title: '您确定要删除该记录吗?',
+        onOk() {
+          app.ruleList.splice(index, 1)
+          modal.destroy()
+        },
+      })
+    },
+  },
+}
 </script>
 <style lang="less" scoped>
 @import './style.less';
+.table-rules {
+  .operation {
+    text-align: right;
+    a {
+      font-size: @font-size-base;
+      margin-left: 6px;
+    }
+  }
+  .content {
+    color: #505050;
+    white-space: normal;
+    .city-name {
+      font-size: 12.5px;
+      color: #7b7b7b;
+    }
+  }
+}
 </style>
diff --git a/src/views/goods/Update.vue b/src/views/goods/Update.vue
index 81d4b6e..dcc5aca 100644
--- a/src/views/goods/Update.vue
+++ b/src/views/goods/Update.vue
@@ -342,7 +342,41 @@
             >
               <a-input-number v-decorator="['sales_initial', { initialValue: 0}]" />
             </a-form-item>
-
+            <div>
+              <a-divider orientation="left">销售区域</a-divider>
+              <a-form-item label="销售区域" :labelCol="labelCol" :wrapperCol="{ span: 15 }">
+                <a-table
+                  v-show="ruleList.length"
+                  class="table-rules"
+                  :columns="columns"
+                  :dataSource="ruleList"
+                  :pagination="false"
+                  bordered
+                >
+                  <!-- 销售区域 -->
+                  <template slot="region_text" slot-scope="text, item, index">
+                    <p class="content">
+                      <span v-for="(province, pidx) in text" :key="pidx">
+                        <span>{{ province.name }}</span>
+                        <template v-if="province.citys.length">
+                          <span>(</span>
+                          <span class="city-name" v-for="(city, cidx) in province.citys" :key="cidx"
+                            >{{ city.name }}{{ province.citys.length > cidx + 1 ? '、' : '' }}</span
+                          >
+                          <span>)</span>
+                        </template>
+                        <span>{{ ' ' }}</span>
+                      </span>
+                    </p>
+                    <p class="operation">
+                      <a href="javascript:void(0);" class="edit" @click="handleEdit(index, item)">编辑</a>
+                      <a href="javascript:void(0);" class="delete" @click="handleDelete(index)">删除</a>
+                    </p>
+                  </template>
+                </a-table>
+                <a-button icon="environment" v-if="ruleList.length == 0" @click="handleAdd">点击添加销售区域</a-button>
+              </a-form-item>
+            </div>
             <div v-show="$module('market-points')">
               <a-divider orientation="left">积分设置</a-divider>
               <a-form-item
@@ -469,6 +503,7 @@
           <a-button type="primary" html-type="submit" :loading="isBtnLoading">提交</a-button>
         </a-form-item>
       </a-form>
+      <AreasModal ref="AreasModal" @handleSubmit="handleAreaSubmit" />
     </a-spin>
   </a-card>
 </template>
@@ -479,7 +514,12 @@ import { SelectImage, SelectVideo, Ueditor, InputNumberGroup } from '@/component
 import GoodsModel from '@/common/model/goods/Index'
 import { GoodsType, MultiSpec } from './modules'
 import { isEmptyObject } from '@/utils/util'
-
+import { AreasModal } from '@/components/Modal'
+const defaultItem = {
+  key: 0,
+  region: [],
+  region_text: [],
+}
 export default {
   components: {
     GoodsType,
@@ -487,7 +527,8 @@ export default {
     SelectVideo,
     Ueditor,
     InputNumberGroup,
-    MultiSpec
+    MultiSpec,
+    AreasModal
   },
   data () {
     return {
@@ -505,7 +546,21 @@ export default {
       // 商品ID
       goodsId: null,
       // 表单数据
-      formData: GoodsModel.formData
+      formData: GoodsModel.formData,
+      checkList: [],
+      // 销售区域
+      ruleList: [],
+      // 销售区域表头
+      columns: [
+        {
+          title: '销售区域',
+          dataIndex: 'region_text',
+          width: '400px',
+          scopedSlots: { customRender: 'region_text' },
+        },
+      ],
+      // 城市总数
+      citysCount: null,
     }
   },
   watch: {
@@ -543,6 +598,7 @@ export default {
             // 第二次赋值 (适用于动态渲染的form-item)
             this.$nextTick(() => {
               this.form.setFieldsValue(GoodsModel.getFieldsValue2())
+              this.ruleList = this.formData.goods.rules?this.formData.goods.rules:[]
               this.onForceUpdate()
             })
           }
@@ -593,7 +649,7 @@ export default {
     handleSubmit (e) {
       e.preventDefault()
       // 表单验证
-      const { form: { validateFields } } = this
+      const { form: { validateFields },ruleList } = this
       validateFields((errors, values) => {
         // 定位到错误的tab选项卡
         if (errors) {
@@ -610,6 +666,7 @@ export default {
           // 记录多规格数据
           values.specData = MultiSpec.getFromSpecData()
         }
+        values.rules = ruleList
         // 整理商品分类ID集
         values.categoryIds = values.categorys.map(item => item.value)
         delete values.categorys
@@ -655,7 +712,69 @@ export default {
           this.isBtnLoading = false
         })
         .finally(() => this.isLoading = false)
-    }
+    },
+    
+    // 新增记录
+    handleAdd() {
+      const index = this.ruleList.length
+      const newItem = { ...defaultItem, key: index }
+      // 排除的城市id集(已存在的城市id集)
+      const excludedCityIds = this.getExcludedCityIds()
+      if (excludedCityIds.length === this.citysCount) {
+        this.$message.error('已选择了所有的区域', 0.8)
+        return false
+      }
+      // 显示选择地区对话框
+      this.handleAreasModal('add', index, newItem, excludedCityIds)
+    },
+
+    // 编辑记录
+    handleEdit(index, item) {
+      // 排除的城市id集(已存在的城市id集)
+      const excludedCityIds = this.getExcludedCityIds()
+      // 显示选择地区对话框
+      this.handleAreasModal('edit', index, item, excludedCityIds)
+    },
+
+    // 选择地区后的回调
+    handleAreaSubmit(result) {
+      const {
+        custom: { scene, item },
+      } = result
+      item.region = result.selectedCityIds
+      item.region_text = result.selectedText
+      if (scene === 'add') {
+        this.ruleList.push(item)
+      }
+    },
+
+    // 排除的城市id集(已存在的城市id集)
+    getExcludedCityIds() {
+      const excludedCityIds = []
+      this.ruleList.forEach((item) => {
+        item.region.forEach((cityId) => {
+          excludedCityIds.push(cityId)
+        })
+      })
+      return excludedCityIds
+    },
+
+    // 显示选择地区对话框
+    handleAreasModal(scene, index, item, excludedCityIds) {
+      this.$refs.AreasModal.handle({ scene, index, item }, item.region, excludedCityIds)
+    },
+
+    // 删除记录
+    handleDelete(index) {
+      const app = this
+      const modal = this.$confirm({
+        title: '您确定要删除该记录吗?',
+        onOk() {
+          app.ruleList.splice(index, 1)
+          modal.destroy()
+        },
+      })
+    },
 
   }
 }
@@ -663,4 +782,21 @@ export default {
 </script>
 <style lang="less" scoped>
 @import './style.less';
+.table-rules {
+  .operation {
+    text-align: right;
+    a {
+      font-size: @font-size-base;
+      margin-left: 6px;
+    }
+  }
+  .content {
+    color: #505050;
+    white-space: normal;
+    .city-name {
+      font-size: 12.5px;
+      color: #7b7b7b;
+    }
+  }
+}
 </style>
diff --git a/src/views/goods/modules/MultiSpec.vue b/src/views/goods/modules/MultiSpec.vue
index 3a6ccea..c380ffc 100644
--- a/src/views/goods/modules/MultiSpec.vue
+++ b/src/views/goods/modules/MultiSpec.vue
@@ -290,8 +290,13 @@ export default {
         return false
       }
 
-      console.log(goodsId, item)
       this.getGoodsDetail(goodsId).then(res => {
+        const queryGoodsId = this.$route.query.goodsId
+        if (res.spec_type === 20 && queryGoodsId !== goodsId) {
+          this.$message.error('您选择的商品是多规格商品', 2)
+          return false
+        }
+
         const sku = res.skuList[0]
         item.goods_price = sku.goods_price
         item.cost_price = sku.cost_price
@@ -319,7 +324,7 @@ export default {
 <style lang="less" scoped>
 // 商品多规格
 .spec-group {
-  width: 895px;
+  width: 1100px;
   margin-bottom: 15px;
   line-height: normal;
 
@@ -427,7 +432,7 @@ export default {
 
 // sku列表
 .sku-list {
-  width: 895px;
+  width: 1100px;
   /deep/.ant-table-thead > tr > th,
   /deep/.ant-table-tbody > tr > td {
     white-space: nowrap;