MrShi
6 天以前 02f424925fbafc0e6e94f82afd4189c277daed89
admin/src/components/business/OperaCityPriceRuleWindow.vue
@@ -8,19 +8,9 @@
      <el-tab-pane label="就地寄存" name="local">
        <div class="price-tip">根据行李尺寸以及存放天数收费(不足一天按一天计价)</div>
        <div class="price-items">
          <div class="price-item">
            <span class="price-label">其中大件行李每天收费</span>
            <el-input style="width: 200px;" v-model="form.bigPriceDay" type="number" placeholder="请输入"></el-input>
            <span class="price-unit">元</span>
          </div>
          <div class="price-item">
            <span class="price-label">其中中件行李每天收费</span>
            <el-input style="width: 200px;" v-model="form.mediumPriceDay" type="number" placeholder="请输入"></el-input>
            <span class="price-unit">元</span>
          </div>
          <div class="price-item">
            <span class="price-label">其中小件行李每天收费</span>
            <el-input style="width: 200px;" v-model="form.smallPriceDay" type="number" placeholder="请输入"></el-input>
          <div class="price-item" v-for="(item, index) in jiudiTableData" :key="index">
            <span class="price-label">其中{{item.categoryName}}每天收费</span>
            <el-input style="width: 200px;" v-model="item.unitPrice" type="number" placeholder="请输入"></el-input>
            <span class="price-unit">元</span>
          </div>
        </div>
@@ -31,25 +21,25 @@
          <span class="remote-tip">根据行李尺寸、配送里程及配送价格收取费用(不足1公里按1公里计价)</span>
        </div>
        <el-table :data="remoteTableData" border stripe>
          <el-table-column prop="baggageSize" label="行李尺寸" min-width="100px"></el-table-column>
          <el-table-column prop="deliveryDistance" label="起送里程(公里)" min-width="120px">
          <el-table-column prop="categoryName" label="行李尺寸"></el-table-column>
          <el-table-column label="起送里程(公里)">
            <template slot-scope="{row}">
              <el-input v-model="row.deliveryDistance" type="number" placeholder="请输入"></el-input>
              <el-input v-model="row.startDistance" type="number" placeholder="请输入"></el-input>
            </template>
          </el-table-column>
          <el-table-column prop="deliveryPrice" label="起送价格(元)" min-width="140px">
          <el-table-column label="起送价格(元)">
            <template slot-scope="{row}">
              <el-input v-model="row.deliveryPrice" type="number" placeholder="请输入"></el-input>
              <el-input v-model="row.startPrice" type="number" placeholder="请输入"></el-input>
            </template>
          </el-table-column>
          <el-table-column prop="sortnum" label="续送里程(公里)" min-width="80px">
          <el-table-column label="续送里程(公里)">
            <template slot-scope="{row}">
              <el-input v-model="row.sortnum" type="number" placeholder="请输入"></el-input>
              <el-input v-model="row.extraDistance" type="number" placeholder="请输入"></el-input>
            </template>
          </el-table-column>
          <el-table-column prop="sortnum" label="续送价格(元)" min-width="80px">
          <el-table-column label="续送价格(元)">
            <template slot-scope="{row}">
              <el-input v-model="row.sortnum" type="number" placeholder="请输入"></el-input>
              <el-input v-model="row.extraPrice" type="number" placeholder="请输入"></el-input>
            </template>
          </el-table-column>
        </el-table>
@@ -60,24 +50,24 @@
          <span class="remote-tip">根据配送里程预计配送时长并展示在小程序下单页面</span>
        </div>
        <el-table :data="timeTableData" border stripe>
          <el-table-column prop="deliveryDistance" label="起送里程(公里)" min-width="120px">
          <el-table-column label="起送里程(公里)">
            <template slot-scope="{row}">
              <el-input v-model="row.deliveryDistance" type="number" placeholder="请输入"></el-input>
              <el-input v-model="row.startDistance" type="number" placeholder="请输入"></el-input>
            </template>
          </el-table-column>
          <el-table-column prop="deliveryHours" label="起送时长(小时)" min-width="120px">
          <el-table-column label="起送时长(小时)">
            <template slot-scope="{row}">
              <el-input v-model="row.deliveryHours" type="number" placeholder="请输入"></el-input>
              <el-input v-model="row.startTime" type="number" placeholder="请输入"></el-input>
            </template>
          </el-table-column>
          <el-table-column prop="sortnum" label="续送里程(公里)" min-width="80px">
          <el-table-column label="续送里程(公里)">
            <template slot-scope="{row}">
              <el-input v-model="row.sortnum" type="number" placeholder="请输入"></el-input>
              <el-input v-model="row.continueDistance" type="number" placeholder="请输入"></el-input>
            </template>
          </el-table-column>
          <el-table-column prop="sortnum" label="续送时长(小时)" min-width="80px">
          <el-table-column label="续送时长(小时)">
            <template slot-scope="{row}">
              <el-input v-model="row.sortnum" type="number" placeholder="请输入"></el-input>
              <el-input v-model="row.continueTime" type="number" placeholder="请输入"></el-input>
            </template>
          </el-table-column>
        </el-table>
@@ -85,14 +75,9 @@
      <el-tab-pane label="门店注册押金" name="deposit">
        <div class="price-tip">根据所在城市以及注册类型不同,平台收取不同数额押金。押金会在门店退网后线下原额退还(门店线上微信支付的押金因微信官方要求具有时效性)</div>
        <div class="price-items">
          <div class="price-item">
            <span class="price-label">其中企业收取押金</span>
            <el-input style="width: 200px;" v-model="form.corporateDepositAmount" type="number" placeholder="请输入"></el-input>
            <span class="price-unit">元</span>
          </div>
          <div class="price-item">
            <span class="price-label">其中个人收取押金</span>
            <el-input style="width: 200px;" v-model="form.personalDepositAmount" type="number" placeholder="请输入"></el-input>
          <div class="price-item" v-for="(item, index) in storeDepositData" :key="index">
            <span class="price-label">其中{{item.fieldTypeName}}收取押金</span>
            <el-input style="width: 200px;" v-model="item.depositAmount" type="number" placeholder="请输入"></el-input>
            <span class="price-unit">元</span>
          </div>
        </div>
@@ -100,29 +85,9 @@
      <el-tab-pane label="分成比例" name="share">
        <div class="price-tip">根据订单中不同运营角色而独立配置不同分成比例</div>
        <div class="price-items">
          <div class="price-item">
            <span class="price-label">其中门店类型为企业并在订单中作为寄件点时,分成比例为</span>
            <el-input style="width: 100px;" v-model="form.corporateSenderRatio" type="number" placeholder="请输入"></el-input>
            <span class="price-unit">%</span>
          </div>
          <div class="price-item">
            <span class="price-label">其中门店类型为个人并在订单中作为寄件点时,分成比例为</span>
            <el-input style="width: 100px;" v-model="form.personalSenderRatio" type="number" placeholder="请输入"></el-input>
            <span class="price-unit">%</span>
          </div>
          <div class="price-item">
            <span class="price-label">其中门店类型为企业并在订单中作为收件点时,分成比例为</span>
            <el-input style="width: 100px;" v-model="form.corporateReceiverRatio" type="number" placeholder="请输入"></el-input>
            <span class="price-unit">%</span>
          </div>
          <div class="price-item">
            <span class="price-label">其中门店类型为个人并在订单中作为收件点时,分成比例为</span>
            <el-input style="width: 100px;" v-model="form.personalReceiverRatio" type="number" placeholder="请输入"></el-input>
            <span class="price-unit">%</span>
          </div>
          <div class="price-item">
            <span class="price-label">在订单中作为配送员时,分成比例为</span>
            <el-input style="width: 100px;" v-model="form.deliverRatio" type="number" placeholder="请输入"></el-input>
          <div class="price-item" v-for="(item, index) in shareTableData" :key="index">
            <span class="price-label">{{item.fieldType === 4 ? '在订单中作为配送员时,' : '其中门店类型为'}}{{item.fieldTypeName}}分成比例为</span>
            <el-input style="width: 100px;" v-model="item.ratio" type="number" placeholder="请输入"></el-input>
            <span class="price-unit">%</span>
          </div>
        </div>
@@ -138,7 +103,18 @@
<script>
import BaseOpera from '@/components/base/BaseOpera'
import GlobalWindow from '@/components/common/GlobalWindow'
import { fetchPriceRule } from '@/api/business/areas'
import {
  localStorage,
  remoteDelivery,
  estimatedDelivery,
  storeDeposit,
  revenueShare,
  batchSave,
  batchSaveRemoteDelivery,
  batchSaveEstimatedDelivery,
  batchSaveStoreDeposit,
  batchSaveRevenueShare
} from '@/api/business/pricingRule'
export default {
  name: 'OperaCityPriceRuleWindow',
  extends: BaseOpera,
@@ -146,50 +122,21 @@
  data () {
    return {
      activeTab: 'local',
      remoteTableData: [
        { size: 1, a: '', b: '', c: '', d: '' }
      ],
      remotePageIndex: 1,
      remotePageSize: 5,
      remoteTotal: 0,
      jiudiTableData: [],
      remoteTableData: [],
      timeTableData: [],
      timePageIndex: 1,
      timePageSize: 5,
      timeTotal: 0,
      storeDepositData: [],
      shareTableData: [],
      form: {
        id: null,
        cityName: '',
        bigPrice: '大件',
        bigPriceDay: null,
        mediumPrice: '中件',
        mediumPriceDay: null,
        smallPrice: '小件',
        smallPriceDay: null,
        remoteBigPrice: '大件',
        remoteBigPriceDay: null,
        remoteMediumPrice: '中件',
        remoteMediumPriceDay: null,
        remoteSmallPrice: '小件',
        remoteSmallPriceDay: null,
        timeLimit: '',
        corporateDeposit: '企业',
        corporateDepositAmount: null,
        personalDeposit: '个人',
        personalDepositAmount: null,
        corporateType: '企业',
        corporateSenderRatio: null,
        corporateReceiverRatio: null,
        personalType: '个人',
        personalSenderRatio: null,
        personalReceiverRatio: null,
        deliverType: '配送员',
        deliverRatio: null
        cityId: null
      }
    }
  },
  created () {
    this.config({
      api: '/business/area',
      api: '/business/pricingRule',
      'field.id': 'id'
    })
  },
@@ -198,80 +145,91 @@
      this.title = title
      this.visible = true
      this.activeTab = 'local'
      this.jiudiTableData = []
      this.remoteTableData = []
      this.remotePageIndex = 1
      this.remoteTotal = 0
      this.timeTableData = [{
        deliveryDistance: null,
        deliveryHours: null,
        sortnum: null
      }]
      this.timePageIndex = 1
      this.timeTotal = 0
      this.timeTableData = []
      this.storeDepositData = []
      this.shareTableData = []
      this.form = {
        id: target.id,
        cityName: target.name,
        bigPrice: '大件',
        bigPriceDay: null,
        mediumPrice: '中件',
        mediumPriceDay: null,
        smallPrice: '小件',
        smallPriceDay: null,
        remoteBigPrice: '大件',
        remoteBigPriceDay: null,
        remoteMediumPrice: '中件',
        remoteMediumPriceDay: null,
        remoteSmallPrice: '小件',
        remoteSmallPriceDay: null,
        timeLimit: '',
        corporateDeposit: '企业',
        corporateDepositAmount: null,
        personalDeposit: '个人',
        personalDepositAmount: null,
        corporateType: '企业',
        corporateSenderRatio: null,
        corporateReceiverRatio: null,
        personalType: '个人',
        personalSenderRatio: null,
        personalReceiverRatio: null,
        deliverType: '配送员',
        deliverRatio: null
        cityId: target
      }
      this.loadPriceRule(target.id)
      this.fetchPriceRule()
      this.fetchRemoteDelivery()
      this.fetchEstimatedDelivery()
      this.fetchStoreDeposit()
      this.fetchRevenueShare()
    },
    loadPriceRule (cityId) {
      fetchPriceRule({ cityId }).then(res => {
        if (res) {
          try {
            const data = typeof res === 'string' ? JSON.parse(res) : res
            if (data.remoteList && Array.isArray(data.remoteList)) {
              this.remoteTableData = data.remoteList
              this.remoteTotal = data.remoteList.length
            }
            if (data.timeList && Array.isArray(data.timeList)) {
              this.timeTableData = data.timeList
              this.timeTotal = data.timeList.length
            }
            Object.assign(this.form, data)
          } catch (e) {
            console.error('Parse price rule failed', e)
          }
        }
      }).catch(e => {
    // 查询就地存取规则列表
    fetchPriceRule () {
      localStorage(this.form.cityId)
        .then(data => {
          this.jiudiTableData = data
        })
        .catch(e => {
        this.$tip.apiFailed(e)
      })
    },
    // 查询异地寄送规则列表
    fetchRemoteDelivery () {
      remoteDelivery(this.form.cityId)
        .then(data => {
          this.remoteTableData = data
        })
        .catch(e => {
          this.$tip.apiFailed(e)
        })
    },
    // 查询异地寄送规则列表
    fetchEstimatedDelivery () {
      estimatedDelivery(this.form.cityId)
        .then(data => {
          this.timeTableData = [
            data
          ]
        })
        .catch(e => {
          this.$tip.apiFailed(e)
        })
    },
    // 查询门店注册押金规则列表
    fetchStoreDeposit () {
      storeDeposit(this.form.cityId)
        .then(data => {
          this.storeDepositData = data
        })
        .catch(e => {
          this.$tip.apiFailed(e)
        })
    },
    // 查询分成比例规则列表
    fetchRevenueShare () {
      revenueShare(this.form.cityId)
        .then(data => {
          this.shareTableData = data
        })
        .catch(e => {
          this.$tip.apiFailed(e)
        })
    },
    // 保存所有规则
    confirm () {
      const submitData = {
        ...this.form,
        remoteList: this.remoteTableData,
        timeList: this.timeTableData
      }
      if (!this.validateLocalStorage()) return
      if (!this.validateRemoteDelivery()) return
      if (!this.validateEstimatedDelivery()) return
      if (!this.validateStoreDeposit()) return
      if (!this.validateRevenueShare()) return
      this.isWorking = true
      this.api.updateById(submitData)
      Promise.all([
        batchSave({ cityId: this.form.cityId, items: this.jiudiTableData }),
        batchSaveRemoteDelivery({ cityId: this.form.cityId, items: this.remoteTableData }),
        batchSaveEstimatedDelivery({ cityId: this.form.cityId, ...this.timeTableData[0] }),
        batchSaveStoreDeposit({ cityId: this.form.cityId, items: this.storeDepositData }),
        batchSaveRevenueShare({ cityId: this.form.cityId, items: this.shareTableData })
      ])
        .then(() => {
          this.$tip.apiSuccess('保存成功')
          this.visible = false
          this.$tip.apiSuccess('保存成功')
          this.$emit('success')
        })
        .catch(e => {
@@ -281,126 +239,60 @@
          this.isWorking = false
        })
    },
    handleAddRemote () {
      this.$prompt('请输入行李尺寸', '新增异地寄存配置', {
        inputValue: '',
        confirmButtonText: '确定',
        cancelButtonText: '取消'
      }).then(({ value }) => {
        if (!value) {
          this.$message.warning('行李尺寸不能为空')
          return
    // 校验就地寄存
    validateLocalStorage () {
      for (const item of this.jiudiTableData) {
        if (item.unitPrice === null || item.unitPrice === undefined || item.unitPrice === '') {
          this.$message.error('请填写所有就地寄存的收费金额')
          return false
        }
        this.remoteTableData.push({
          id: null,
          baggageSize: value,
          deliveryDistance: null,
          deliveryPrice: null,
          sortnum: this.remoteTableData.length + 1
        })
        this.remoteTotal = this.remoteTableData.length
      }).catch(() => {})
    },
    handleEditRemote (row, index) {
      this.$prompt('请输入行李尺寸', '编辑异地寄存配置', {
        inputValue: row.baggageSize,
        confirmButtonText: '确定',
        cancelButtonText: '取消'
      }).then(({ value }) => {
        if (!value) {
          this.$message.warning('行李尺寸不能为空')
          return
        }
        this.$prompt('请输入配送里程(公里)', '编辑配送里程', {
          inputValue: row.deliveryDistance,
          confirmButtonText: '确定',
          cancelButtonText: '取消'
        }).then(({ value: distance }) => {
          this.$prompt('请输入配送价格(每公里/元)', '编辑配送价格', {
            inputValue: row.deliveryPrice,
            confirmButtonText: '确定',
            cancelButtonText: '取消'
          }).then(({ value: price }) => {
            this.$prompt('请输入排序', '编辑排序', {
              inputValue: row.sortnum,
              confirmButtonText: '确定',
              cancelButtonText: '取消'
            }).then(({ value: sortnum }) => {
              this.$prompt('请输入行李尺寸', '编辑异地寄存配置', {
                inputValue: row.baggageSize
              })
              this.remoteTableData.splice(index, 1, {
                ...row,
                baggageSize: value,
                deliveryDistance: distance ? Number(distance) : null,
                deliveryPrice: price ? Number(price) : null,
                sortnum: sortnum ? Number(sortnum) : this.remoteTableData.length + 1
              })
            }).catch(() => {})
          }).catch(() => {})
        }).catch(() => {})
      }).catch(() => {})
      return true
    },
    handleDeleteRemote (row, index) {
      this.$confirm('确认删除该异地寄存配置吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.remoteTableData.splice(index, 1)
        this.remoteTotal = this.remoteTableData.length
      }).catch(() => {})
    },
    handleAddTime () {
      this.$refs.operaTimeRuleWindow.open('新建预计时效规则', null)
    },
    handleTimeRuleSuccess (data) {
      if (data) {
        this.timeTableData.push(data)
        this.timeTotal = this.timeTableData.length
    // 校验异地寄存
    validateRemoteDelivery () {
      for (const item of this.remoteTableData) {
        if (item.startDistance === null || item.startDistance === undefined || item.startDistance === '' ||
            item.startPrice === null || item.startPrice === undefined || item.startPrice === '' ||
            item.extraDistance === null || item.extraDistance === undefined || item.extraDistance === '' ||
            item.extraPrice === null || item.extraPrice === undefined || item.extraPrice === '') {
          this.$message.error('请填写所有异地寄送的配置信息')
          return false
      }
      }
      return true
    },
    handleEditTime (row, index) {
      this.$prompt('请输入配送里程(公里)', '编辑预计时效配置', {
        inputValue: row.deliveryDistance,
        confirmButtonText: '确定',
        cancelButtonText: '取消'
      }).then(({ value }) => {
        this.$prompt('请输入配送时长(小时)', '编辑预计时效配置', {
          inputValue: row.deliveryHours,
          confirmButtonText: '确定',
          cancelButtonText: '取消'
        }).then(({ value: hours }) => {
          this.$prompt('请输入排序', '编辑预计时效配置', {
            inputValue: row.sortnum,
            confirmButtonText: '确定',
            cancelButtonText: '取消'
          }).then(({ value: sortnum }) => {
            this.timeTableData.splice(index, 1, {
              ...row,
              deliveryDistance: value ? Number(value) : null,
              deliveryHours: hours ? Number(hours) : null,
              sortnum: sortnum ? Number(sortnum) : this.timeTableData.length + 1
            })
          }).catch(() => {})
        }).catch(() => {})
      }).catch(() => {})
    // 校验预计时效
    validateEstimatedDelivery () {
      const item = this.timeTableData[0]
      if (!item || item.startDistance === null || item.startDistance === undefined || item.startDistance === '' ||
          item.startTime === null || item.startTime === undefined || item.startTime === '' ||
          item.continueDistance === null || item.continueDistance === undefined || item.continueDistance === '' ||
          item.continueTime === null || item.continueTime === undefined || item.continueTime === '') {
        this.$message.error('请填写预计时效的所有配置信息')
        return false
      }
      return true
    },
    handleDeleteTime (row, index) {
      this.$confirm('确认删除该预计时效配置吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.timeTableData.splice(index, 1)
        this.timeTotal = this.timeTableData.length
      }).catch(() => {})
    // 校验门店注册押金
    validateStoreDeposit () {
      for (const item of this.storeDepositData) {
        if (item.depositAmount === null || item.depositAmount === undefined || item.depositAmount === '') {
          this.$message.error('请填写所有门店注册押金的金额')
          return false
        }
      }
      return true
    },
    handleTimePageChange (page) {
      this.timePageIndex = page
    },
    handleRemotePageChange (page) {
      this.remotePageIndex = page
    // 校验分成比例
    validateRevenueShare () {
      for (const item of this.shareTableData) {
        if (item.ratio === null || item.ratio === undefined || item.ratio === '') {
          this.$message.error('请填写所有分成比例')
          return false
        }
      }
      return true
    }
  }
}
@@ -432,7 +324,8 @@
}
.dialog-footer {
  text-align: right;
  padding: 10px 20px;
  padding: 0 20px;
  box-sizing: border-box;
  border-top: 1px solid #eee;
}
.remote-config-title {