rk
11 小时以前 c74a6f59490cfb9a0ee37f70427739b74e7fbd58
admin/src/components/business/OperaShopEditWindow.vue
@@ -49,6 +49,17 @@
            <el-button type="primary" @click="openMapSelector">选择</el-button>
          </div>
        </el-form-item>
        <el-form-item label="位置标签" prop="locationTagIds">
          <el-select v-model="form.locationTagIds" multiple placeholder="请选择位置标签" style="width: 100%;">
            <el-option v-for="item in locationTagList" :key="item.id" :label="item.name" :value="item.id"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="门店配送范围" prop="deliveryRange">
          <div class="delivery-range">
            <el-input v-model.number="form.deliveryRange" placeholder="请输入配送范围" style="width: 150px;"></el-input>
            <span class="unit">公里</span>
          </div>
        </el-form-item>
      </div>
      <div class="form-section">
@@ -143,6 +154,34 @@
                @deleteRow="index => form.otherMaterialImgs.splice(index, 1)" />
            </el-form-item>
          </el-tab-pane>
          <el-tab-pane label="门店分成" name="profit">
            <div class="profit-section">
              <h4 class="section-title">就地寄存模式</h4>
              <el-form-item label="在订单中作为寄件点时,分成比例为" label-suffix=":*">
                <div class="profit-input">
                  <el-input v-model.number="form.localDeposit" placeholder="请输入分成比例" style="width: 150px;"></el-input>
                  <span class="unit">%</span>
                </div>
              </el-form-item>
            </div>
            <div class="profit-section">
              <h4 class="section-title">同城寄送模式</h4>
              <el-form-item label="在订单中作为寄件点时,分成比例为" label-suffix=":*">
                <div class="profit-input">
                  <el-input v-model.number="form.remoteTake" placeholder="请输入分成比例" style="width: 150px;"></el-input>
                  <span class="unit">%</span>
                </div>
              </el-form-item>
              <el-form-item label="在订单中作为收件点时,分成比例为" label-suffix=":*">
                <div class="profit-input">
                  <el-input v-model.number="form.remoteDeposit" placeholder="请输入分成比例" style="width: 150px;"></el-input>
                  <span class="unit">%</span>
                </div>
              </el-form-item>
            </div>
          </el-tab-pane>
        </el-tabs>
      </div>
    </el-form>
@@ -155,6 +194,7 @@
import UploadImages from '@/components/common/uploadImages'
import { detail, updateById } from '@/api/business/shopInfo'
import { listByParentId } from '@/api/business/areas'
import { fetchList } from '@/api/business/category'
export default {
  name: 'OperaShopEditWindow',
  extends: BaseOpera,
@@ -176,6 +216,11 @@
        address: '',
        longitude: '',
        latitude: '',
        locationTagIds: [],
        deliveryRange: '',
        localDeposit: '',
        remoteTake: '',
        remoteDeposit: '',
        legalPersonName: '',
        legalPersonPhone: '',
        legalPersonCard: '',
@@ -188,6 +233,7 @@
        storeInteriorImgs: '',
        otherMaterialImgs: ''
      },
      locationTagList: [],
      rules: {
        name: [{ required: true, message: '请输入门店名称', trigger: 'blur' }],
        companyType: [{ required: true, message: '请选择门店类型', trigger: 'change' }],
@@ -206,8 +252,8 @@
        laborContractImgs: [{ required: true, message: '请输入有效劳动合同', trigger: 'blur' }],
        socialSecurityImgs: [{ required: true, message: '请输入社保缴纳证明', trigger: 'blur' }],
        storeFrontImgs: [{ required: true, message: '请输入门店门头照', trigger: 'blur' }],
        storeInteriorImgs: [{ required: true, message: '请输入门店内部照片', trigger: 'blur' }],
        otherMaterialImgs: [{ required: true, message: '请输入其它材料', trigger: 'blur' }]
        storeInteriorImgs: [{ required: true, message: '请输入门店内部照片', trigger: 'blur' }]
        // otherMaterialImgs: [{ required: true, message: '请输入其它材料', trigger: 'blur' }]
      },
      qualificationTab: 'enterprise',
      areaOptions: [],
@@ -222,47 +268,57 @@
      'field.id': 'id'
    })
    this.loadAreaOptions()
    this.getLocationTagList()
  },
  methods: {
    open (title, row) {
      this.isWorking.save = false
      detail(row.id)
        .then(res => {
          this.form = {
            id: res.id,
            telephone: res.telephone || '',
            name: res.name || '',
            companyType: res.companyType ?? 1,
            linkName: res.linkName || '',
            linkPhone: res.linkPhone || '',
            idcard: res.idcard || '',
            areaCode: res.provinceId ? [res.provinceId, res.cityId, res.areaId] : [],
            provinceId: res.provinceId || '',
            cityId: res.cityId || '',
            areaId: res.areaId || '',
            address: res.address || '',
            longitude: res.longitude || '',
            latitude: res.latitude || '',
            legalPersonName: res.legalPersonName || '',
            legalPersonPhone: res.legalPersonPhone || '',
            legalPersonCard: res.legalPersonCard || '',
            businessImg: res.companyType === 1 ? [{ fileurl: res.businessImg, url: res.imgPrefix + res.businessImg }] : [],
            idcardImg: [{ fileurl: res.idcardImg, url: res.imgPrefix + res.idcardImg }],
            idcardImgBack: [{ fileurl: res.idcardImgBack, url: res.imgPrefix + res.idcardImgBack }],
            laborContractImgs: res.laborContractImgs.map(item => ({ fileurl: item, url: res.imgPrefix + item })),
            socialSecurityImgs: res.socialSecurityImgs.map(item => ({ fileurl: item, url: res.imgPrefix + item })),
            storeFrontImgs: res.storeFrontImgs.map(item => ({ fileurl: item, url: res.imgPrefix + item })),
            storeInteriorImgs: res.storeInteriorImgs.map(item => ({ fileurl: item, url: res.imgPrefix + item })),
            otherMaterialImgs: res.otherMaterialImgs ? res.otherMaterialImgs.map(item => ({ fileurl: item, url: res.imgPrefix + item })) : []
          }
          this.qualificationTab = res.companyType === 1 ? 'enterprise' : 'personal'
          this.title = title
          this.visible = true
        })
        .catch(e => {
          this.$tip.apiFailed(e)
        })
    },
    this.isWorking.save = false
    detail(row.id)
      .then(res => {
        this.form = {
          id: res.id,
          telephone: res.telephone || '',
          name: res.name || '',
          companyType: res.companyType ?? 1,
          linkName: res.linkName || '',
          linkPhone: res.linkPhone || '',
          idcard: res.idcard || '',
          areaCode: res.provinceId ? [res.provinceId, res.cityId, res.areaId] : [],
          provinceId: res.provinceId || '',
          cityId: res.cityId || '',
          areaId: res.areaId || '',
          address: res.address || '',
          longitude: res.longitude || '',
          latitude: res.latitude || '',
          locationTagIds: res.locationTagIds || [],
          deliveryRange: res.deliveryRange || '',
          localDeposit: res.localDeposit || '',
          remoteTake: res.remoteTake || '',
          remoteDeposit: res.remoteDeposit || '',
          legalPersonName: res.legalPersonName || '',
          legalPersonPhone: res.legalPersonPhone || '',
          legalPersonCard: res.legalPersonCard || '',
          businessImg: res.companyType === 1 ? [{ fileurl: res.businessImg, url: res.imgPrefix + res.businessImg }] : [],
          idcardImg: [{ fileurl: res.idcardImg, url: res.imgPrefix + res.idcardImg }],
          idcardImgBack: [{ fileurl: res.idcardImgBack, url: res.imgPrefix + res.idcardImgBack }],
          laborContractImgs: res.laborContractImgs.map(item => ({ fileurl: item, url: res.imgPrefix + item })),
          socialSecurityImgs: res.socialSecurityImgs.map(item => ({ fileurl: item, url: res.imgPrefix + item })),
          storeFrontImgs: res.storeFrontImgs.map(item => ({ fileurl: item, url: res.imgPrefix + item })),
          storeInteriorImgs: res.storeInteriorImgs.map(item => ({ fileurl: item, url: res.imgPrefix + item })),
          otherMaterialImgs: res.otherMaterialImgs ? res.otherMaterialImgs.map(item => ({ fileurl: item, url: res.imgPrefix + item })) : []
        }
        // 处理位置标签(字符串转数组)
        if (this.form.locationTagIds && typeof this.form.locationTagIds === 'string') {
          this.form.locationTagIds = this.form.locationTagIds.split(',').map(Number)
        }
        this.qualificationTab = res.companyType === 1 ? 'enterprise' : 'personal'
        this.title = title
        this.visible = true
      })
      .catch(e => {
        this.$tip.apiFailed(e)
      })
  },
    loadAreaOptions () {
      listByParentId({ })
        .then(data => {
@@ -272,6 +328,19 @@
        .catch(e => {
          this.$tip.apiFailed(e)
        })
    },
    // 获取位置标签列表
    async getLocationTagList() {
      try {
        const res = await fetchList({
          capacity: 9999,
          page: 1,
          model: {}
        })
        this.locationTagList = res.records
      } catch (e) {
        this.$tip.apiFailed(e.message)
      }
    },
    formatAreaData (data) {
      const map = {}
@@ -303,40 +372,64 @@
    openMapSelector () {
      window.open('https://lbs.qq.com/getPoint/', '_blank')
    },
    handleConfirm () {
      this.$refs.form.validate(valid => {
    async handleConfirm () {
      try {
        // 校验分成比例
        if (!this.form.localDeposit) {
          this.$message.error('请填写就地寄存模式的分成比例')
          return
        }
        if (!this.form.remoteTake) {
          this.$message.error('请填写同城寄送模式下作为寄件点的分成比例')
          return
        }
        if (!this.form.remoteDeposit) {
          this.$message.error('请填写同城寄送模式下作为收件点的分成比例')
          return
        }
        const valid = await this.$refs.form.validate()
        if (!valid) return
        this.isWorking.save = true
        const imageFields = ['laborContractImgs', 'socialSecurityImgs', 'storeFrontImgs', 'storeInteriorImgs', 'otherMaterialImgs']
        const singleImageFields = ['businessImg', 'idcardImg', 'idcardImgBack']
        const data = { ...this.form }
        singleImageFields.forEach(field => {
          if (data[field] && Array.isArray(data[field])) {
            data[field] = data[field].map(item => typeof item === 'object' ? item.fileurl : item).join(',')
          }
        })
        const params = { ...this.form }
        // 处理省市区编码
        if (params.areaCode && params.areaCode.length === 3) {
          params.provinceId = params.areaCode[0]
          params.cityId = params.areaCode[1]
          params.areaId = params.areaCode[2]
        }
        delete params.areaCode
        // 处理位置标签(数组转逗号分隔字符串)
        if (params.locationTagIds && Array.isArray(params.locationTagIds)) {
          params.locationTagIds = params.locationTagIds.join(',')
        }
        // 处理图片数组
        const imageFields = ['idcardImg', 'idcardImgBack', 'businessImg', 'laborContractImgs', 'socialSecurityImgs', 'storeFrontImgs', 'storeInteriorImgs', 'otherMaterialImgs']
        imageFields.forEach(field => {
          if (data[field] && Array.isArray(data[field])) {
            data[field] = data[field].map(item => typeof item === 'object' ? item.fileurl : item)
          if (params[field] && Array.isArray(params[field])) {
            // 身份证和营业执照图片需要传字符串(单个图片)
            if (['idcardImg', 'idcardImgBack', 'businessImg'].includes(field)) {
              params[field] = params[field].map(item => item.fileurl).join(',')
            } else {
              // 其他图片传数组
              params[field] = params[field].map(item => item.fileurl)
            }
          }
        })
        data.provinceId = this.form.areaCode[0] || ''
        data.cityId = this.form.areaCode[1] || ''
        data.areaId = this.form.areaCode[2] || ''
        delete data.areaCode
        updateById(data)
          .then(res => {
            this.$tip.apiSuccess(res || '保存成功')
            this.visible = false
            this.$emit('success')
          })
          .catch(e => {
            this.$tip.apiFailed(e)
          })
          .finally(() => {
            this.isWorking.save = false
          })
      })
        // 个人门店不需要传businessImg
        if (params.companyType === 0) {
          delete params.businessImg
        }
        await updateById(params)
        this.$tip.apiSuccess('保存成功')
        this.visible = false
        this.$emit('success')
      } catch (e) {
        this.$tip.apiFailed(e)
        console.error('保存失败:', e)
      } finally {
        this.isWorking.save = false
      }
    }
  }
}
@@ -360,13 +453,46 @@
  margin: -10px 0 15px 0;
}
.longitude-latitude {
  display: flex;
  align-items: center;
  gap: 10px;
}
.longitude-latitude .separator {
  color: #606266;
}
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .longitude-latitude .separator {
    color: #909399;
  }
  .delivery-range {
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .unit {
    color: #909399;
    font-size: 14px;
  }
  .profit-section {
    margin-bottom: 30px;
    padding: 20px;
    background: #f5f7fa;
    border-radius: 4px;
  }
  .profit-section .section-title {
    font-size: 16px;
    font-weight: bold;
    color: #303133;
    margin-bottom: 20px;
    padding-bottom: 10px;
    border-bottom: 1px solid #e4e7ed;
  }
  .profit-input {
    display: flex;
    align-items: center;
    gap: 10px;
  }
.inline-form /deep/ .el-form-item {
  display: block;
  margin-right: 0;