feat: 同城配送模块
This commit is contained in:
parent
ff60bd5719
commit
553bd5cd89
|
|
@ -727,5 +727,30 @@ export const mer_admin = {
|
|||
params: query,
|
||||
data: data
|
||||
});
|
||||
},
|
||||
|
||||
// ==================== 同城配送配置相关接口 ====================
|
||||
|
||||
/**
|
||||
* 获取同城配送配置
|
||||
* @param {object} data 查询参数
|
||||
* @param {number} data.marketId 市场ID
|
||||
* @returns {Promise}
|
||||
*/
|
||||
getCityDeliveryConfig: data => {
|
||||
return $http.request({
|
||||
method: "get",
|
||||
url: `/merchant-api/city/delivery/config/detail`,
|
||||
params: data
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 保存同城配送配置
|
||||
* @param {object} data 配置数据
|
||||
* @returns {Promise}
|
||||
*/
|
||||
saveCityDeliveryConfig: data => {
|
||||
return $http.post(`/merchant-api/city/delivery/config/save`, data);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,625 @@
|
|||
<template>
|
||||
<div>同城运费配置</div>
|
||||
<div class="page-container">
|
||||
<div class="form-container">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formModel"
|
||||
:rules="formRules"
|
||||
label-width="180px"
|
||||
size="small"
|
||||
>
|
||||
<!-- 同城配送开关 -->
|
||||
<div class="section-header">
|
||||
<el-divider content-position="left">
|
||||
<span class="section-title">同城配送开关</span>
|
||||
</el-divider>
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
class="help-btn"
|
||||
@click="openDescModal('CityDeliverySwitch')"
|
||||
>
|
||||
<i class="el-icon-question"></i> 字段说明
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-form-item label="是否开启同城配送" prop="isEnable">
|
||||
<el-switch
|
||||
v-model="formModel.isEnable"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
active-text="已开启"
|
||||
inactive-text="未开启"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 基础配置 -->
|
||||
<div class="section-header">
|
||||
<el-divider content-position="left">
|
||||
<span class="section-title">基础配置</span>
|
||||
</el-divider>
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
class="help-btn"
|
||||
@click="openDescModal('Base')"
|
||||
>
|
||||
<i class="el-icon-question"></i> 字段说明
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-form-item label="订单包装费" prop="orderPackagePrice">
|
||||
<el-input
|
||||
v-model="formModel.orderPackagePrice"
|
||||
placeholder="请输入数字,支持两位小数"
|
||||
style="width: 200px"
|
||||
>
|
||||
<template slot="append">元/单</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="订单起送价" prop="minOrderPrice">
|
||||
<el-input
|
||||
v-model="formModel.minOrderPrice"
|
||||
placeholder="请输入数字,支持两位小数"
|
||||
style="width: 200px"
|
||||
>
|
||||
<template slot="append">元/单</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="最大配送距离" prop="maxDeliveryDistance">
|
||||
<el-input
|
||||
v-model="formModel.maxDeliveryDistance"
|
||||
placeholder="请输入数字"
|
||||
style="width: 200px"
|
||||
>
|
||||
<template slot="append">公里</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="承诺订单送达时间" prop="maxDeliveryTime">
|
||||
<el-input
|
||||
v-model="formModel.maxDeliveryTime"
|
||||
placeholder="请输入数字"
|
||||
style="width: 200px"
|
||||
>
|
||||
<template slot="append">小时以内</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 运费收益方 -->
|
||||
<div class="section-header">
|
||||
<el-divider content-position="left">
|
||||
<span class="section-title">运费收益方</span>
|
||||
</el-divider>
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
class="help-btn"
|
||||
@click="openDescModal('DeliveryProfitSide')"
|
||||
>
|
||||
<i class="el-icon-question"></i> 字段说明
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-form-item label="运费收益方" prop="deliveryProfitSide">
|
||||
<el-select
|
||||
v-model="formModel.deliveryProfitSide"
|
||||
placeholder="请选择运费收益方"
|
||||
style="width: 200px"
|
||||
>
|
||||
<el-option label="市场经营者" :value="1" />
|
||||
<el-option label="专员" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 运费计算 -->
|
||||
<div class="section-header">
|
||||
<el-divider content-position="left">
|
||||
<span class="section-title">运费计算</span>
|
||||
</el-divider>
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
class="help-btn"
|
||||
@click="openDescModal('SelfDeliver')"
|
||||
>
|
||||
<i class="el-icon-question"></i> 字段说明
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-form-item label="运费模式" prop="deliveryPriceMode">
|
||||
<el-select
|
||||
v-model="formModel.deliveryPriceMode"
|
||||
placeholder="请选择运费模式"
|
||||
style="width: 200px"
|
||||
>
|
||||
<el-option label="距离运费" value="DISTANCE" />
|
||||
<el-option label="固定运费" value="FIX" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<template v-if="formModel.deliveryPriceMode === 'DISTANCE'">
|
||||
<el-form-item label="配送起步价" prop="basicDeliveryDistance">
|
||||
<el-input
|
||||
v-model="formModel.basicDeliveryDistance"
|
||||
placeholder="请输入数字"
|
||||
style="width: 200px"
|
||||
>
|
||||
<template slot="append">公里内</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="" prop="basicDeliveryPrice">
|
||||
<el-input
|
||||
v-model="formModel.basicDeliveryPrice"
|
||||
placeholder="请输入数字,支持两位小数"
|
||||
style="width: 200px"
|
||||
>
|
||||
<template slot="append">元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="每+0.1公里加收" prop="addDeliveryPrice">
|
||||
<el-input
|
||||
v-model="formModel.addDeliveryPrice"
|
||||
placeholder="请输入数字,支持两位小数"
|
||||
style="width: 200px"
|
||||
>
|
||||
<template slot="append">元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<template v-if="formModel.deliveryPriceMode === 'FIX'">
|
||||
<el-form-item label="配送费用" prop="fixDeliveryPrice">
|
||||
<el-input
|
||||
v-model="formModel.fixDeliveryPrice"
|
||||
placeholder="请输入数字,支持两位小数"
|
||||
style="width: 200px"
|
||||
>
|
||||
<template slot="append">元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<!-- 免运费条件 -->
|
||||
<div class="section-header">
|
||||
<el-divider content-position="left">
|
||||
<span class="section-title">免运费条件</span>
|
||||
</el-divider>
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
class="help-btn"
|
||||
@click="openDescModal('FreeDelivery')"
|
||||
>
|
||||
<i class="el-icon-question"></i> 字段说明
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-form-item label="订单满额免运费" prop="isFreeDelivery">
|
||||
<el-switch
|
||||
v-model="formModel.isFreeDelivery"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
active-text="已开启"
|
||||
inactive-text="已关闭"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
v-if="formModel.isFreeDelivery"
|
||||
label="订单满"
|
||||
prop="freeDeliveryOrderPrice"
|
||||
>
|
||||
<el-input
|
||||
v-model="formModel.freeDeliveryOrderPrice"
|
||||
placeholder="请输入数字"
|
||||
style="width: 200px"
|
||||
>
|
||||
<template slot="append">元,免运费</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item class="form-actions">
|
||||
<el-button @click="handleCancel" size="medium">取消</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleSubmit"
|
||||
:loading="loading"
|
||||
size="medium"
|
||||
>
|
||||
提交
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 字段说明弹窗 -->
|
||||
<el-dialog :title="descTitle" :visible.sync="descVisible" width="600px">
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item
|
||||
v-for="(item, index) in descList"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:label-class-name="'desc-label'"
|
||||
>
|
||||
<div style="line-height: 1.6" v-html="item.desc"></div>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div slot="footer">
|
||||
<el-button type="primary" @click="descVisible = false">
|
||||
知道了
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mer_admin } from "@/api/modules/mer_admin.js";
|
||||
|
||||
export default {
|
||||
name: "CityDeliveryConfig",
|
||||
data() {
|
||||
// 价格验证
|
||||
const validatePrice = (rule, value, callback) => {
|
||||
if (!value && value !== 0) {
|
||||
callback(new Error("请输入价格"));
|
||||
return;
|
||||
}
|
||||
const pattern = /^\d+(\.\d{1,2})?$/;
|
||||
if (pattern.test(value)) {
|
||||
callback();
|
||||
} else {
|
||||
callback(new Error("请输入数字,支持两位小数"));
|
||||
}
|
||||
};
|
||||
|
||||
// 数字验证
|
||||
const validateNumber = (rule, value, callback) => {
|
||||
if (!value && value !== 0) {
|
||||
callback(new Error("请输入数字"));
|
||||
return;
|
||||
}
|
||||
if (/^\d+$/.test(value)) {
|
||||
callback();
|
||||
} else {
|
||||
callback(new Error("请输入整数"));
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
loading: false,
|
||||
formModel: {
|
||||
isEnable: 1,
|
||||
id: undefined,
|
||||
orderPackagePrice: "",
|
||||
minOrderPrice: "",
|
||||
maxDeliveryDistance: "",
|
||||
maxDeliveryTime: "",
|
||||
basicDeliveryDistance: "",
|
||||
basicDeliveryPrice: "",
|
||||
addDeliveryPrice: "",
|
||||
fixDeliveryPrice: "",
|
||||
deliveryPriceMode: "DISTANCE",
|
||||
freeDeliveryOrderPrice: "",
|
||||
deliveryProfitSide: "",
|
||||
isFreeDelivery: 0
|
||||
},
|
||||
formRules: {
|
||||
isEnable: [
|
||||
{ required: true, message: "请选择是否开启", trigger: "change" }
|
||||
],
|
||||
orderPackagePrice: [
|
||||
{ required: true, validator: validatePrice, trigger: "blur" }
|
||||
],
|
||||
minOrderPrice: [
|
||||
{ required: true, validator: validatePrice, trigger: "blur" }
|
||||
],
|
||||
maxDeliveryDistance: [
|
||||
{ required: true, validator: validateNumber, trigger: "blur" }
|
||||
],
|
||||
maxDeliveryTime: [
|
||||
{ required: true, validator: validateNumber, trigger: "blur" }
|
||||
],
|
||||
deliveryProfitSide: [
|
||||
{ required: true, message: "请选择运费收益方", trigger: "change" }
|
||||
],
|
||||
deliveryPriceMode: [
|
||||
{ required: true, message: "请选择运费模式", trigger: "change" }
|
||||
],
|
||||
basicDeliveryDistance: [{ validator: validateNumber, trigger: "blur" }],
|
||||
basicDeliveryPrice: [{ validator: validatePrice, trigger: "blur" }],
|
||||
addDeliveryPrice: [{ validator: validatePrice, trigger: "blur" }],
|
||||
fixDeliveryPrice: [{ validator: validatePrice, trigger: "blur" }],
|
||||
freeDeliveryOrderPrice: [{ validator: validatePrice, trigger: "blur" }]
|
||||
},
|
||||
|
||||
// 字段说明
|
||||
descVisible: false,
|
||||
descTitle: "",
|
||||
descList: []
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
marketId() {
|
||||
return this.$store.state.userData.marketId;
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.fetchData();
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 获取数据
|
||||
async fetchData() {
|
||||
try {
|
||||
this.loading = true;
|
||||
const res = await mer_admin.getCityDeliveryConfig({
|
||||
marketId: this.marketId
|
||||
});
|
||||
console.log("同城配送配置返回:", res);
|
||||
|
||||
// 处理返回数据结构:res.data.data 或 res.data
|
||||
let data = null;
|
||||
if (res.data && res.data.data !== undefined) {
|
||||
data = res.data.data;
|
||||
} else if (res.data) {
|
||||
data = res.data;
|
||||
}
|
||||
|
||||
console.log("同城配送配置数据:", data);
|
||||
|
||||
// 如果有数据则填充表单
|
||||
if (data && typeof data === "object" && data !== null) {
|
||||
Object.assign(this.formModel, {
|
||||
...data,
|
||||
isEnable: Number(data.isEnable) || 0,
|
||||
isFreeDelivery: Number(data.isFreeDelivery) || 0,
|
||||
freeDeliveryOrderPrice:
|
||||
data.freeDeliveryOrderPrice || data.freeDeliveryOrderPrice === 0
|
||||
? data.freeDeliveryOrderPrice
|
||||
: ""
|
||||
});
|
||||
} else {
|
||||
console.log("暂无配置数据,使用默认值");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取数据失败:", error);
|
||||
this.$message.error("获取配置失败");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
// 提交表单
|
||||
handleSubmit() {
|
||||
this.$refs.formRef.validate(async valid => {
|
||||
if (!valid) return;
|
||||
|
||||
try {
|
||||
this.loading = true;
|
||||
const params = {
|
||||
marketId: this.marketId,
|
||||
...this.formModel
|
||||
};
|
||||
|
||||
console.log("提交同城配送配置:", params);
|
||||
const res = await mer_admin.saveCityDeliveryConfig(params);
|
||||
console.log("保存返回:", res);
|
||||
this.$message.success("保存成功");
|
||||
this.fetchData();
|
||||
} catch (error) {
|
||||
console.error("保存失败:", error);
|
||||
this.$message.error("保存失败");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 取消
|
||||
handleCancel() {
|
||||
this.$confirm("退出将不对此页面内容进行保存,是否确认退出?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
})
|
||||
.then(() => {
|
||||
this.$router.go(-1);
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
|
||||
// 字段说明
|
||||
openDescModal(type) {
|
||||
const descEnum = {
|
||||
CityDeliverySwitch: {
|
||||
title: "同城配送设置-同城配送开关-字段说明",
|
||||
descList: [
|
||||
{
|
||||
label: "是否开启同城配送",
|
||||
desc:
|
||||
"开启后,顾客才可以选择【同城配送】方式下单;关闭后,所有顾客均无法选择【同城配送】方式下单。"
|
||||
}
|
||||
]
|
||||
},
|
||||
FreeDelivery: {
|
||||
title: "同城配送设置-免运费条件-字段说明",
|
||||
descList: [
|
||||
{
|
||||
label: "订单满额免运费",
|
||||
desc: "开启后,顾客订单金额满足此条件,即可免运费。"
|
||||
}
|
||||
]
|
||||
},
|
||||
DeliveryProfitSide: {
|
||||
title: "同城配送设置-运费收益方-字段说明",
|
||||
descList: [
|
||||
{
|
||||
label: "运费收益方",
|
||||
desc:
|
||||
"顾客支付的运费,将由哪一方获得;若选择【市场经营者】,则顾客支付的运费,将由市场经营者获得;若选择【专员】,则顾客支付的运费,将由专员获得。"
|
||||
}
|
||||
]
|
||||
},
|
||||
Base: {
|
||||
title: "同城配送设置-基础配置-字段说明",
|
||||
descList: [
|
||||
{
|
||||
label: "订单包装费",
|
||||
desc:
|
||||
"通过【同城配送】方式下的订单,顾客需要为每个订单额外支付的包装费用。"
|
||||
},
|
||||
{
|
||||
label: "订单起送价",
|
||||
desc:
|
||||
"订单的实付金额若不满足此条件,无法通过【同城配送】方式下订单。"
|
||||
},
|
||||
{
|
||||
label: "订单配送费",
|
||||
desc:
|
||||
"通过【同城配送】方式下的订单,顾客需要为每个订单额外支付的配送费用。"
|
||||
},
|
||||
{
|
||||
label: "最大配送距离",
|
||||
desc:
|
||||
"若顾客收货地址距离市场定位的距离超出此条件,将无法通过【同城配送】方式下单。"
|
||||
},
|
||||
{
|
||||
label: "承诺订单送达时间",
|
||||
desc:
|
||||
"顾客通过【同城配送】方式下单后,承诺在此配置时间内送达,请根据实际情况配置。"
|
||||
}
|
||||
]
|
||||
},
|
||||
SelfDeliver: {
|
||||
title: "同城配送设置-运费计算-字段说明",
|
||||
descList: [
|
||||
{
|
||||
label: "配送起步价",
|
||||
desc:
|
||||
"配送费的起步价;举例:起步价为3公里内,3元;配送3公里内的订单,在订单完成后,将获得3元配送费。"
|
||||
},
|
||||
{
|
||||
label: "每+0.1公里加收",
|
||||
desc:
|
||||
"配送距离超出起步价公里数,每超出0.1公里加收的配送费;举例:起步价为3公里内,3元,每超出0.1公里加收0.3元;配送一单3.5公里的订单,在订单完成后,将获得3+(3.5-3)/0.1*0.3=4.5元配送费。"
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const config = descEnum[type];
|
||||
this.descTitle = config.title;
|
||||
this.descList = config.descList;
|
||||
this.descVisible = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
padding: 0;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
background-color: #fff;
|
||||
padding: 30px 40px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
position: relative;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.el-divider {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.help-btn {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
padding: 0;
|
||||
color: #909399;
|
||||
|
||||
&:hover {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-form-item {
|
||||
margin-bottom: 24px;
|
||||
|
||||
.el-form-item__label {
|
||||
font-weight: 500;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.el-form-item__content {
|
||||
line-height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
margin-top: 40px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
|
||||
::v-deep .el-form-item__content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
min-width: 100px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.desc-label {
|
||||
width: 150px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
::v-deep .el-descriptions-item__label {
|
||||
font-weight: 500;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
::v-deep .el-switch {
|
||||
.el-switch__label {
|
||||
color: #606266;
|
||||
font-weight: normal;
|
||||
|
||||
&.is-active {
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue