647 行
26 KiB
HTML
647 行
26 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8"/>
|
|
<title>骑手配置管理</title>
|
|
<link rel="stylesheet" type="text/css" href="__PUBLIC__/css/menu.css?v=1.0.5"/>
|
|
<link rel="stylesheet" type="text/css" href="__PUBLIC__/css/minimal-admin.css?v=1.0.0"/>
|
|
<link rel="stylesheet" type="text/css" href="__PUBLIC__/Retail/css/myscroll.css?v=1.0.2"/>
|
|
<link rel="stylesheet" type="text/css" href="__PUBLIC__/layui-v2.4.3/layui/css/layui.css"/>
|
|
<link rel="stylesheet" type="text/css" href="__PUBLIC__/Retail/css/home.css"/>
|
|
<link rel="stylesheet" type="text/css" href="__PUBLIC__/vue/element-ui.css?v=2.13.2">
|
|
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
<script type="text/javascript" charset="utf-8" src="__PUBLIC__/vue/js/vue2.5.16.js"></script>
|
|
<script type="text/javascript" charset="utf-8" src="__PUBLIC__/vue/element-ui.js?v=2.13.2"></script>
|
|
<script type="text/javascript" charset="utf-8" src="__PUBLIC__/js/common.js?v=1.0.2"></script>
|
|
<script type="text/javascript" charset="utf-8" src="__PUBLIC__/jquery/js/jquery-3.2.1.min.js"></script>
|
|
<style>
|
|
.config-container {
|
|
padding: 20px;
|
|
background: #f5f7fa;
|
|
min-height: calc(100vh - 100px);
|
|
}
|
|
|
|
.config-header {
|
|
background: white;
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.config-title {
|
|
font-size: 24px;
|
|
font-weight: 600;
|
|
color: #303133;
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.config-description {
|
|
color: #909399;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.config-card {
|
|
background: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
margin-bottom: 20px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.config-card-header {
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
color: white;
|
|
padding: 15px 20px;
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.config-card-body {
|
|
padding: 20px;
|
|
}
|
|
|
|
.form-section {
|
|
margin-bottom: 30px;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: #303133;
|
|
margin-bottom: 15px;
|
|
padding-bottom: 8px;
|
|
border-bottom: 2px solid #e4e7ed;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.section-title i {
|
|
margin-right: 8px;
|
|
color: #409EFF;
|
|
}
|
|
|
|
.fee-preview {
|
|
background: #f8f9fa;
|
|
border: 1px solid #e9ecef;
|
|
border-radius: 6px;
|
|
padding: 15px;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.fee-preview-title {
|
|
font-weight: 600;
|
|
color: #495057;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.fee-result {
|
|
font-size: 18px;
|
|
font-weight: 700;
|
|
color: #28a745;
|
|
}
|
|
|
|
.test-form {
|
|
background: #fff3cd;
|
|
border: 1px solid #ffeaa7;
|
|
border-radius: 6px;
|
|
padding: 15px;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.save-actions {
|
|
text-align: center;
|
|
padding: 20px;
|
|
background: #f8f9fa;
|
|
border-top: 1px solid #e9ecef;
|
|
}
|
|
|
|
.el-form-item {
|
|
margin-bottom: 18px;
|
|
}
|
|
|
|
.switch-item {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 12px 0;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
}
|
|
|
|
.switch-item:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.switch-label {
|
|
font-weight: 500;
|
|
color: #303133;
|
|
}
|
|
|
|
.switch-description {
|
|
font-size: 12px;
|
|
color: #909399;
|
|
margin-top: 4px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="RiderConfig" v-cloak>
|
|
<div class="config-container">
|
|
<!-- 页面头部 -->
|
|
<div class="config-header">
|
|
<div class="config-title">
|
|
<i class="fas fa-cogs" style="margin-right: 12px; color: #409EFF;"></i>
|
|
骑手配置管理
|
|
</div>
|
|
<div class="config-description">
|
|
配置订单同步规则、配送费用计算方式等骑手端相关设置
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 基础配置 -->
|
|
<div class="config-card">
|
|
<div class="config-card-header">
|
|
<i class="fas fa-toggle-on" style="margin-right: 8px;"></i>
|
|
基础配置
|
|
</div>
|
|
<div class="config-card-body">
|
|
<el-form :model="config" label-width="140px" size="medium">
|
|
<div class="switch-item">
|
|
<div>
|
|
<div class="switch-label">自动同步订单</div>
|
|
<div class="switch-description">开启后,新订单将自动同步到骑手端</div>
|
|
</div>
|
|
<el-switch
|
|
v-model="config.auto_sync_enabled"
|
|
:active-value="1"
|
|
:inactive-value="0">
|
|
</el-switch>
|
|
</div>
|
|
|
|
<div class="switch-item">
|
|
<div>
|
|
<div class="switch-label">时间加价</div>
|
|
<div class="switch-description">在特定时间段内增加配送费用</div>
|
|
</div>
|
|
<el-switch
|
|
v-model="config.time_fee_enabled"
|
|
:active-value="1"
|
|
:inactive-value="0">
|
|
</el-switch>
|
|
</div>
|
|
|
|
<div class="switch-item">
|
|
<div>
|
|
<div class="switch-label">恶劣天气加价</div>
|
|
<div class="switch-description">恶劣天气条件下增加配送费用</div>
|
|
</div>
|
|
<el-switch
|
|
v-model="config.weather_fee_enabled"
|
|
:active-value="1"
|
|
:inactive-value="0">
|
|
</el-switch>
|
|
</div>
|
|
|
|
<div class="switch-item">
|
|
<div>
|
|
<div class="switch-label">加急配送</div>
|
|
<div class="switch-description">允许用户选择加急配送服务</div>
|
|
</div>
|
|
<el-switch
|
|
v-model="config.urgent_fee_enabled"
|
|
:active-value="1"
|
|
:inactive-value="0">
|
|
</el-switch>
|
|
</div>
|
|
</el-form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 配送费用配置 -->
|
|
<div class="config-card">
|
|
<div class="config-card-header">
|
|
<i class="fas fa-calculator" style="margin-right: 8px;"></i>
|
|
配送费用配置
|
|
</div>
|
|
<div class="config-card-body">
|
|
<el-form :model="config" label-width="140px" size="medium">
|
|
<div class="form-section">
|
|
<div class="section-title">
|
|
<i class="fas fa-coins"></i>
|
|
计费方式
|
|
</div>
|
|
<el-form-item label="计费类型">
|
|
<el-radio-group v-model="config.delivery_fee_type">
|
|
<el-radio :label="1">按距离计费</el-radio>
|
|
<el-radio :label="2">固定费用</el-radio>
|
|
<el-radio :label="3">阶梯计费</el-radio>
|
|
</el-radio-group>
|
|
</el-form-item>
|
|
</div>
|
|
|
|
<div class="form-section">
|
|
<div class="section-title">
|
|
<i class="fas fa-money-bill-wave"></i>
|
|
基础费用设置
|
|
</div>
|
|
<el-row :gutter="20">
|
|
<el-col :span="12">
|
|
<el-form-item label="基础配送费">
|
|
<el-input-number
|
|
v-model="config.base_fee"
|
|
:precision="2"
|
|
:step="0.5"
|
|
:min="0"
|
|
:max="100">
|
|
</el-input-number>
|
|
<span style="margin-left: 8px; color: #909399;">元</span>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="12">
|
|
<el-form-item label="每公里费用" v-if="config.delivery_fee_type === 1">
|
|
<el-input-number
|
|
v-model="config.distance_fee"
|
|
:precision="2"
|
|
:step="0.1"
|
|
:min="0"
|
|
:max="10">
|
|
</el-input-number>
|
|
<span style="margin-left: 8px; color: #909399;">元/公里</span>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="20">
|
|
<el-col :span="12">
|
|
<el-form-item label="免费配送距离">
|
|
<el-input-number
|
|
v-model="config.free_distance"
|
|
:precision="2"
|
|
:step="0.5"
|
|
:min="0"
|
|
:max="20">
|
|
</el-input-number>
|
|
<span style="margin-left: 8px; color: #909399;">公里</span>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="12">
|
|
<el-form-item label="最大配送距离">
|
|
<el-input-number
|
|
v-model="config.max_distance"
|
|
:precision="2"
|
|
:step="1"
|
|
:min="1"
|
|
:max="50">
|
|
</el-input-number>
|
|
<span style="margin-left: 8px; color: #909399;">公里</span>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
</div>
|
|
|
|
<div class="form-section" v-if="config.time_fee_enabled">
|
|
<div class="section-title">
|
|
<i class="fas fa-clock"></i>
|
|
时间加价设置
|
|
</div>
|
|
<el-row :gutter="20">
|
|
<el-col :span="8">
|
|
<el-form-item label="夜间加价比例">
|
|
<el-input-number
|
|
v-model="config.night_fee_rate"
|
|
:precision="2"
|
|
:step="0.1"
|
|
:min="0"
|
|
:max="2">
|
|
</el-input-number>
|
|
<span style="margin-left: 8px; color: #909399;">倍</span>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="8">
|
|
<el-form-item label="夜间开始时间">
|
|
<el-time-picker
|
|
v-model="nightStartTime"
|
|
format="HH:mm"
|
|
value-format="HH:mm"
|
|
placeholder="选择时间">
|
|
</el-time-picker>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="8">
|
|
<el-form-item label="夜间结束时间">
|
|
<el-time-picker
|
|
v-model="nightEndTime"
|
|
format="HH:mm"
|
|
value-format="HH:mm"
|
|
placeholder="选择时间">
|
|
</el-time-picker>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
</div>
|
|
|
|
<div class="form-section">
|
|
<div class="section-title">
|
|
<i class="fas fa-plus-circle"></i>
|
|
附加费用设置
|
|
</div>
|
|
<el-row :gutter="20">
|
|
<el-col :span="8">
|
|
<el-form-item label="恶劣天气加价" v-if="config.weather_fee_enabled">
|
|
<el-input-number
|
|
v-model="config.weather_fee_rate"
|
|
:precision="2"
|
|
:step="0.5"
|
|
:min="0"
|
|
:max="20">
|
|
</el-input-number>
|
|
<span style="margin-left: 8px; color: #909399;">元</span>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="8">
|
|
<el-form-item label="加急费用" v-if="config.urgent_fee_enabled">
|
|
<el-input-number
|
|
v-model="config.urgent_fee"
|
|
:precision="2"
|
|
:step="0.5"
|
|
:min="0"
|
|
:max="20">
|
|
</el-input-number>
|
|
<span style="margin-left: 8px; color: #909399;">元</span>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="8">
|
|
<el-form-item label="包装费">
|
|
<el-input-number
|
|
v-model="config.packaging_fee"
|
|
:precision="2"
|
|
:step="0.5"
|
|
:min="0"
|
|
:max="10">
|
|
</el-input-number>
|
|
<span style="margin-left: 8px; color: #909399;">元</span>
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-form-item label="最小起送金额">
|
|
<el-input-number
|
|
v-model="config.min_order_amount"
|
|
:precision="2"
|
|
:step="5"
|
|
:min="0"
|
|
:max="200">
|
|
</el-input-number>
|
|
<span style="margin-left: 8px; color: #909399;">元</span>
|
|
</el-form-item>
|
|
</div>
|
|
</el-form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 费用计算测试 -->
|
|
<div class="config-card">
|
|
<div class="config-card-header">
|
|
<i class="fas fa-flask" style="margin-right: 8px;"></i>
|
|
费用计算测试
|
|
</div>
|
|
<div class="config-card-body">
|
|
<div class="test-form">
|
|
<el-form :model="testData" label-width="120px" size="medium" inline>
|
|
<el-form-item label="配送距离">
|
|
<el-input-number
|
|
v-model="testData.distance"
|
|
:precision="2"
|
|
:step="0.5"
|
|
:min="0"
|
|
:max="50">
|
|
</el-input-number>
|
|
<span style="margin-left: 8px;">公里</span>
|
|
</el-form-item>
|
|
|
|
<el-form-item label="订单金额">
|
|
<el-input-number
|
|
v-model="testData.orderAmount"
|
|
:precision="2"
|
|
:step="10"
|
|
:min="0"
|
|
:max="1000">
|
|
</el-input-number>
|
|
<span style="margin-left: 8px;">元</span>
|
|
</el-form-item>
|
|
|
|
<el-form-item label="是否加急">
|
|
<el-switch v-model="testData.isUrgent"></el-switch>
|
|
</el-form-item>
|
|
|
|
<el-form-item label="是否夜间">
|
|
<el-switch v-model="testData.isNight"></el-switch>
|
|
</el-form-item>
|
|
|
|
<el-form-item label="恶劣天气">
|
|
<el-switch v-model="testData.isBadWeather"></el-switch>
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
<el-button type="primary" @click="calculateTestFee" :loading="calculating">
|
|
<i class="fas fa-calculator" style="margin-right: 5px;"></i>
|
|
计算费用
|
|
</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</div>
|
|
|
|
<div class="fee-preview" v-if="testResult.total !== null">
|
|
<div class="fee-preview-title">费用计算结果:</div>
|
|
<div class="fee-result">
|
|
总配送费:¥{{ testResult.total }}
|
|
</div>
|
|
<div style="margin-top: 10px; font-size: 14px; color: #666;">
|
|
<div>基础费用:¥{{ testResult.baseFee }}</div>
|
|
<div v-if="testResult.distanceFee > 0">距离费用:¥{{ testResult.distanceFee }}</div>
|
|
<div v-if="testResult.urgentFee > 0">加急费用:¥{{ testResult.urgentFee }}</div>
|
|
<div v-if="testResult.nightFee > 0">夜间加价:¥{{ testResult.nightFee }}</div>
|
|
<div v-if="testResult.weatherFee > 0">恶劣天气加价:¥{{ testResult.weatherFee }}</div>
|
|
<div v-if="testResult.packagingFee > 0">包装费:¥{{ testResult.packagingFee }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 保存操作 -->
|
|
<div class="save-actions">
|
|
<el-button size="large" @click="resetConfig">
|
|
<i class="fas fa-undo" style="margin-right: 5px;"></i>
|
|
重置配置
|
|
</el-button>
|
|
<el-button type="primary" size="large" @click="saveConfig" :loading="saving">
|
|
<i class="fas fa-save" style="margin-right: 5px;"></i>
|
|
保存配置
|
|
</el-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
new Vue({
|
|
el: '#RiderConfig',
|
|
data() {
|
|
return {
|
|
config: {
|
|
auto_sync_enabled: 1,
|
|
delivery_fee_type: 1,
|
|
base_fee: 5.00,
|
|
distance_fee: 1.50,
|
|
free_distance: 3.00,
|
|
max_distance: 20.00,
|
|
time_fee_enabled: 0,
|
|
night_fee_rate: 0.50,
|
|
night_start_time: '22:00',
|
|
night_end_time: '06:00',
|
|
weather_fee_enabled: 0,
|
|
weather_fee_rate: 1.00,
|
|
urgent_fee_enabled: 1,
|
|
urgent_fee: 3.00,
|
|
min_order_amount: 20.00,
|
|
packaging_fee: 2.00
|
|
},
|
|
testData: {
|
|
distance: 5.0,
|
|
orderAmount: 50.0,
|
|
isUrgent: false,
|
|
isNight: false,
|
|
isBadWeather: false
|
|
},
|
|
testResult: {
|
|
total: null,
|
|
baseFee: 0,
|
|
distanceFee: 0,
|
|
urgentFee: 0,
|
|
nightFee: 0,
|
|
weatherFee: 0,
|
|
packagingFee: 0
|
|
},
|
|
saving: false,
|
|
calculating: false
|
|
}
|
|
},
|
|
computed: {
|
|
nightStartTime: {
|
|
get() {
|
|
return this.config.night_start_time;
|
|
},
|
|
set(val) {
|
|
this.config.night_start_time = val;
|
|
}
|
|
},
|
|
nightEndTime: {
|
|
get() {
|
|
return this.config.night_end_time;
|
|
},
|
|
set(val) {
|
|
this.config.night_end_time = val;
|
|
}
|
|
}
|
|
},
|
|
methods: {
|
|
// 加载配置
|
|
loadConfig() {
|
|
this.sendRequest('Retail/RiderConfig/getConfig', {
|
|
success: (response) => {
|
|
if (response.status === 1) {
|
|
this.config = { ...this.config, ...response.data };
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
// 保存配置
|
|
saveConfig() {
|
|
this.saving = true;
|
|
this.sendRequest('Retail/RiderConfig/saveConfig', {
|
|
data: this.config,
|
|
success: (response) => {
|
|
this.saving = false;
|
|
if (response.status === 1) {
|
|
this.$message.success('配置保存成功!');
|
|
} else {
|
|
this.$message.error(response.message || '保存失败');
|
|
}
|
|
},
|
|
error: () => {
|
|
this.saving = false;
|
|
this.$message.error('保存失败,请重试');
|
|
}
|
|
});
|
|
},
|
|
|
|
// 重置配置
|
|
resetConfig() {
|
|
this.$confirm('确定要重置所有配置吗?', '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}).then(() => {
|
|
this.loadConfig();
|
|
this.$message.success('配置已重置');
|
|
});
|
|
},
|
|
|
|
// 计算测试费用
|
|
calculateTestFee() {
|
|
this.calculating = true;
|
|
this.sendRequest('Retail/RiderConfig/testFeeCalculation', {
|
|
data: {
|
|
distance: this.testData.distance,
|
|
order_amount: this.testData.orderAmount,
|
|
is_urgent: this.testData.isUrgent,
|
|
is_night: this.testData.isNight,
|
|
is_bad_weather: this.testData.isBadWeather
|
|
},
|
|
success: (response) => {
|
|
this.calculating = false;
|
|
if (response.status === 1) {
|
|
this.testResult = response.data;
|
|
} else {
|
|
this.$message.error(response.message || '计算失败');
|
|
}
|
|
},
|
|
error: () => {
|
|
this.calculating = false;
|
|
this.$message.error('计算失败,请重试');
|
|
}
|
|
});
|
|
},
|
|
|
|
// 发送请求
|
|
sendRequest(url, options) {
|
|
const defaultOptions = {
|
|
method: 'POST',
|
|
data: {},
|
|
success: () => {},
|
|
error: () => {}
|
|
};
|
|
|
|
const config = { ...defaultOptions, ...options };
|
|
|
|
$.ajax({
|
|
url: `{:U('${url}')}`,
|
|
type: config.method,
|
|
data: config.data,
|
|
success: config.success,
|
|
error: config.error
|
|
});
|
|
}
|
|
},
|
|
|
|
created() {
|
|
this.loadConfig();
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |