From 56bc142d33106db9f226abe39f60d0059d702338 Mon Sep 17 00:00:00 2001
From: rk <94314517@qq.com>
Date: 星期五, 10 四月 2026 20:04:38 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'
---
admin/src/components/business/OperaCityPriceRuleWindow.vue | 349 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 349 insertions(+), 0 deletions(-)
diff --git a/admin/src/components/business/OperaCityPriceRuleWindow.vue b/admin/src/components/business/OperaCityPriceRuleWindow.vue
new file mode 100644
index 0000000..8e40ff5
--- /dev/null
+++ b/admin/src/components/business/OperaCityPriceRuleWindow.vue
@@ -0,0 +1,349 @@
+<template>
+ <GlobalWindow
+ :title="title"
+ :visible.sync="visible"
+ width="60%"
+ >
+ <el-tabs v-model="activeTab">
+ <el-tab-pane label="灏卞湴瀵勫瓨" name="local">
+ <div class="price-tip">鏍规嵁琛屾潕灏哄浠ュ強瀛樻斁澶╂暟鏀惰垂锛堜笉瓒充竴澶╂寜涓�澶╄浠凤級</div>
+ <div class="price-items">
+ <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>
+ </el-tab-pane>
+ <el-tab-pane label="寮傚湴瀵勫瓨" name="remote">
+ <div class="remote-config-title">寮傚湴瀵勯�侀厤缃�</div>
+ <div class="remote-header">
+ <span class="remote-tip">鏍规嵁琛屾潕灏哄銆侀厤閫侀噷绋嬪強閰嶉�佷环鏍兼敹鍙栬垂鐢紙涓嶈冻1鍏噷鎸�1鍏噷璁′环锛�</span>
+ </div>
+ <el-table :data="remoteTableData" border stripe>
+ <el-table-column prop="categoryName" label="琛屾潕灏哄"></el-table-column>
+ <el-table-column label="璧烽�侀噷绋�(鍏噷)">
+ <template slot-scope="{row}">
+ <el-input v-model="row.startDistance" type="number" placeholder="璇疯緭鍏�"></el-input>
+ </template>
+ </el-table-column>
+ <el-table-column label="璧烽�佷环鏍�(鍏�)">
+ <template slot-scope="{row}">
+ <el-input v-model="row.startPrice" type="number" placeholder="璇疯緭鍏�"></el-input>
+ </template>
+ </el-table-column>
+ <el-table-column label="缁�侀噷绋�(鍏噷)">
+ <template slot-scope="{row}">
+ <el-input v-model="row.extraDistance" type="number" placeholder="璇疯緭鍏�"></el-input>
+ </template>
+ </el-table-column>
+ <el-table-column label="缁�佷环鏍�(鍏�)">
+ <template slot-scope="{row}">
+ <el-input v-model="row.extraPrice" type="number" placeholder="璇疯緭鍏�"></el-input>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-tab-pane>
+ <el-tab-pane label="棰勮鏃舵晥" name="time">
+ <div class="remote-config-title">棰勮鏃舵晥瑙勫垯</div>
+ <div class="remote-header">
+ <span class="remote-tip">鏍规嵁閰嶉�侀噷绋嬮璁¢厤閫佹椂闀垮苟灞曠ず鍦ㄥ皬绋嬪簭涓嬪崟椤甸潰</span>
+ </div>
+ <el-table :data="timeTableData" border stripe>
+ <el-table-column label="璧烽�侀噷绋�(鍏噷)">
+ <template slot-scope="{row}">
+ <el-input v-model="row.startDistance" type="number" placeholder="璇疯緭鍏�"></el-input>
+ </template>
+ </el-table-column>
+ <el-table-column label="璧烽�佹椂闀�(灏忔椂)">
+ <template slot-scope="{row}">
+ <el-input v-model="row.startTime" type="number" placeholder="璇疯緭鍏�"></el-input>
+ </template>
+ </el-table-column>
+ <el-table-column label="缁�侀噷绋�(鍏噷)">
+ <template slot-scope="{row}">
+ <el-input v-model="row.continueDistance" type="number" placeholder="璇疯緭鍏�"></el-input>
+ </template>
+ </el-table-column>
+ <el-table-column label="缁�佹椂闀�(灏忔椂)">
+ <template slot-scope="{row}">
+ <el-input v-model="row.continueTime" type="number" placeholder="璇疯緭鍏�"></el-input>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-tab-pane>
+ <el-tab-pane label="闂ㄥ簵娉ㄥ唽鎶奸噾" name="deposit">
+ <div class="price-tip">鏍规嵁鎵�鍦ㄥ煄甯備互鍙婃敞鍐岀被鍨嬩笉鍚岋紝骞冲彴鏀跺彇涓嶅悓鏁伴鎶奸噾銆傛娂閲戜細鍦ㄩ棬搴楅��缃戝悗绾夸笅鍘熼閫�杩橈紙闂ㄥ簵绾夸笂寰俊鏀粯鐨勬娂閲戝洜寰俊瀹樻柟瑕佹眰鍏锋湁鏃舵晥鎬э級</div>
+ <div class="price-items">
+ <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>
+ </el-tab-pane>
+ <el-tab-pane label="鍒嗘垚姣斾緥" name="share">
+ <div class="price-tip">鏍规嵁璁㈠崟涓笉鍚岃繍钀ヨ鑹茶�岀嫭绔嬮厤缃笉鍚屽垎鎴愭瘮渚�</div>
+ <div class="price-items">
+ <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>
+ </el-tab-pane>
+ </el-tabs>
+ <div slot="footer" class="dialog-footer">
+ <el-button @click="visible = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="confirm" :loading="isWorking">纭畾</el-button>
+ </div>
+ </GlobalWindow>
+</template>
+
+<script>
+import BaseOpera from '@/components/base/BaseOpera'
+import GlobalWindow from '@/components/common/GlobalWindow'
+import {
+ localStorage,
+ remoteDelivery,
+ estimatedDelivery,
+ storeDeposit,
+ revenueShare,
+ batchSave,
+ batchSaveRemoteDelivery,
+ batchSaveEstimatedDelivery,
+ batchSaveStoreDeposit,
+ batchSaveRevenueShare
+} from '@/api/business/pricingRule'
+export default {
+ name: 'OperaCityPriceRuleWindow',
+ extends: BaseOpera,
+ components: { GlobalWindow },
+ data () {
+ return {
+ activeTab: 'local',
+
+ jiudiTableData: [],
+ remoteTableData: [],
+ timeTableData: [],
+ storeDepositData: [],
+ shareTableData: [],
+
+ form: {
+ cityId: null
+ }
+ }
+ },
+ created () {
+ this.config({
+ api: '/business/pricingRule',
+ 'field.id': 'id'
+ })
+ },
+ methods: {
+ open (title, target) {
+ this.title = title
+ this.visible = true
+ this.activeTab = 'local'
+ this.jiudiTableData = []
+ this.remoteTableData = []
+ this.timeTableData = []
+ this.storeDepositData = []
+ this.shareTableData = []
+ this.form = {
+ cityId: target
+ }
+ this.fetchPriceRule()
+ this.fetchRemoteDelivery()
+ this.fetchEstimatedDelivery()
+ this.fetchStoreDeposit()
+ this.fetchRevenueShare()
+ },
+ // 鏌ヨ灏卞湴瀛樺彇瑙勫垯鍒楄〃
+ 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 () {
+ if (!this.validateLocalStorage()) return
+ if (!this.validateRemoteDelivery()) return
+ if (!this.validateEstimatedDelivery()) return
+ if (!this.validateStoreDeposit()) return
+ if (!this.validateRevenueShare()) return
+
+ this.isWorking = true
+ 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.visible = false
+ this.$tip.apiSuccess('淇濆瓨鎴愬姛')
+ this.$emit('success')
+ })
+ .catch(e => {
+ this.$tip.apiFailed(e)
+ })
+ .finally(() => {
+ this.isWorking = false
+ })
+ },
+ // 鏍¢獙灏卞湴瀵勫瓨
+ validateLocalStorage () {
+ for (const item of this.jiudiTableData) {
+ if (item.unitPrice === null || item.unitPrice === undefined || item.unitPrice === '') {
+ this.$message.error('璇峰~鍐欐墍鏈夊氨鍦板瘎瀛樼殑鏀惰垂閲戦')
+ return false
+ }
+ }
+ return true
+ },
+ // 鏍¢獙寮傚湴瀵勫瓨
+ 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
+ },
+ // 鏍¢獙棰勮鏃舵晥
+ 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
+ },
+ // 鏍¢獙闂ㄥ簵娉ㄥ唽鎶奸噾
+ validateStoreDeposit () {
+ for (const item of this.storeDepositData) {
+ if (item.depositAmount === null || item.depositAmount === undefined || item.depositAmount === '') {
+ this.$message.error('璇峰~鍐欐墍鏈夐棬搴楁敞鍐屾娂閲戠殑閲戦')
+ return false
+ }
+ }
+ return true
+ },
+ // 鏍¢獙鍒嗘垚姣斾緥
+ validateRevenueShare () {
+ for (const item of this.shareTableData) {
+ if (item.ratio === null || item.ratio === undefined || item.ratio === '') {
+ this.$message.error('璇峰~鍐欐墍鏈夊垎鎴愭瘮渚�')
+ return false
+ }
+ }
+ return true
+ }
+ }
+}
+</script>
+
+<style scoped>
+.price-tip {
+ margin-bottom: 20px;
+ color: #666;
+ font-size: 14px;
+}
+.price-items {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+}
+.price-item {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+.price-label {
+ flex-shrink: 0;
+ font-weight: 500;
+}
+.price-unit {
+ color: #666;
+ white-space: nowrap;
+}
+.dialog-footer {
+ text-align: right;
+ padding: 0 20px;
+ box-sizing: border-box;
+ border-top: 1px solid #eee;
+}
+.remote-config-title {
+ font-weight: bold;
+ margin-bottom: 15px;
+}
+.remote-header {
+ display: flex;
+ align-items: center;
+ gap: 15px;
+ margin-bottom: 15px;
+}
+.remote-tip {
+ color: #666;
+ font-size: 14px;
+}
+.remote-pagination {
+ margin-top: 15px;
+ text-align: right;
+}
+</style>
\ No newline at end of file
--
Gitblit v1.9.3