2025-03-18 18:05:19 +08:00
|
|
|
|
<template>
|
|
|
|
|
<el-dialog
|
|
|
|
|
:title="title"
|
|
|
|
|
:visible.sync="dialogVisible"
|
|
|
|
|
width="800px"
|
|
|
|
|
append-to-body
|
|
|
|
|
:close-on-click-modal="false"
|
|
|
|
|
@open="handleOpen"
|
|
|
|
|
>
|
|
|
|
|
<el-form ref="form" :model="form" :rules="rules" label-width="80px" size="small" v-loading="loading">
|
|
|
|
|
<el-row :gutter="10">
|
2025-03-25 18:04:07 +08:00
|
|
|
|
<form-col :span="span" label="所属用户" prop="userId">
|
|
|
|
|
<user-input v-model="form.userId" :text.sync="form.userName" :disabled="!checkPermi(['system:user:list'])"/>
|
2025-03-18 18:05:19 +08:00
|
|
|
|
</form-col>
|
|
|
|
|
<form-col :span="span" label="套餐名称" prop="name">
|
|
|
|
|
<el-input v-model="form.name" placeholder="请输入套餐名称" />
|
|
|
|
|
</form-col>
|
2025-03-25 18:04:07 +08:00
|
|
|
|
<form-col :span="span" label="套餐类型" prop="type">
|
|
|
|
|
<el-select v-model="form.type" placeholder="请选择套餐类型" style="width: 100%;">
|
|
|
|
|
<el-option
|
|
|
|
|
v-for="dict in dict.type.suit_type"
|
|
|
|
|
:key="dict.value"
|
|
|
|
|
:label="dict.label"
|
|
|
|
|
:value="dict.value"
|
|
|
|
|
></el-option>
|
|
|
|
|
</el-select>
|
|
|
|
|
</form-col>
|
2025-03-18 18:05:19 +08:00
|
|
|
|
<form-col :span="span" label="预存金额" prop="depositAmount">
|
2025-03-27 18:04:06 +08:00
|
|
|
|
<el-input-number
|
|
|
|
|
v-model="form.depositAmount"
|
|
|
|
|
placeholder="请输入预存金额"
|
|
|
|
|
type="number"
|
|
|
|
|
:precision="2"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
style="width: calc(100% - 2em)"
|
|
|
|
|
/> 元
|
2025-03-18 18:05:19 +08:00
|
|
|
|
</form-col>
|
|
|
|
|
<form-col :span="span" label="免费时长" prop="freeRideTime">
|
|
|
|
|
<el-input v-model="form.freeRideTime" placeholder="请输入免费时长(分钟)">
|
|
|
|
|
<template slot="append">分钟</template>
|
|
|
|
|
</el-input>
|
|
|
|
|
</form-col>
|
|
|
|
|
<form-col :span="span" label="显示顺序" prop="orderNum">
|
|
|
|
|
<el-input-number v-model="form.orderNum" placeholder="请输入显示顺序" controls-position="right" :min="0" style="width: 100%;" />
|
|
|
|
|
</form-col>
|
|
|
|
|
<form-col :span="span" label="状态" prop="status">
|
|
|
|
|
<el-radio-group v-model="form.status">
|
|
|
|
|
<el-radio
|
|
|
|
|
v-for="dict in dict.type.suit_status"
|
|
|
|
|
:key="dict.value"
|
|
|
|
|
:label="dict.value"
|
|
|
|
|
>{{dict.label}}</el-radio>
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
</form-col>
|
|
|
|
|
<form-col :span="24" label="说明" prop="instructions">
|
|
|
|
|
<el-input v-model="form.instructions" type="textarea" placeholder="请输入内容" maxlength="1000" show-word-limit :autosize="{ minRows: 3, maxRows: 10 }"/>
|
|
|
|
|
</form-col>
|
|
|
|
|
<form-col :span="span" label="租赁单位" prop="rentalUnit">
|
|
|
|
|
<el-select v-model="form.rentalUnit" placeholder="请选择租赁单位" style="width: 100%;">
|
|
|
|
|
<el-option
|
|
|
|
|
v-for="dict in dict.type.suit_rental_unit"
|
|
|
|
|
:key="dict.value"
|
|
|
|
|
:label="dict.label"
|
|
|
|
|
:value="dict.value"
|
|
|
|
|
></el-option>
|
|
|
|
|
</el-select>
|
|
|
|
|
</form-col>
|
|
|
|
|
<form-col :span="span" label="计费方式" prop="ridingRule">
|
|
|
|
|
<el-select v-model="form.ridingRule" placeholder="请选择计费方式" style="width: 100%;" >
|
|
|
|
|
<el-option
|
|
|
|
|
v-for="dict in dict.type.suit_riding_rule"
|
|
|
|
|
:key="dict.value"
|
|
|
|
|
:label="dict.label"
|
|
|
|
|
:value="dict.value"
|
|
|
|
|
></el-option>
|
|
|
|
|
</el-select>
|
|
|
|
|
</form-col>
|
2025-03-25 18:04:07 +08:00
|
|
|
|
</el-row>
|
|
|
|
|
<el-row :gutter="10">
|
2025-03-18 18:05:19 +08:00
|
|
|
|
<collapse-panel title="计费规则" :value="true">
|
|
|
|
|
<template v-if="form.ridingRule === SuitRidingRule.START && form.startRule">
|
2025-03-27 18:04:06 +08:00
|
|
|
|
<div class="rule-row">
|
|
|
|
|
在
|
|
|
|
|
<el-input-number
|
|
|
|
|
size="small"
|
|
|
|
|
v-model="form.startRule.startingTime"
|
|
|
|
|
placeholder="起步时间"
|
|
|
|
|
:min="0"
|
|
|
|
|
:precision="0"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
style="width: 120px;"
|
|
|
|
|
/>
|
|
|
|
|
{{unitLabel(form.rentalUnit)}}以内,起步价
|
|
|
|
|
<el-input-number
|
|
|
|
|
size="small"
|
|
|
|
|
v-model="form.startRule.startingPrice"
|
|
|
|
|
placeholder="起步价"
|
|
|
|
|
type="number"
|
|
|
|
|
:precision="2"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
style="width: 120px;"
|
|
|
|
|
/>
|
|
|
|
|
元;
|
|
|
|
|
</div>
|
|
|
|
|
<div class="rule-row">
|
|
|
|
|
超出起步时间后,超出的时间每
|
|
|
|
|
<el-input-number
|
|
|
|
|
size="small"
|
|
|
|
|
v-model="form.startRule.timeoutTime"
|
|
|
|
|
placeholder="超时时间"
|
|
|
|
|
type="number"
|
|
|
|
|
:precision="0"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
style="width: 120px;"
|
|
|
|
|
/>
|
|
|
|
|
{{unitLabel(form.rentalUnit)}}
|
|
|
|
|
<el-input-number
|
|
|
|
|
size="small"
|
|
|
|
|
v-model="form.startRule.timeoutPrice"
|
|
|
|
|
placeholder="超时价格"
|
|
|
|
|
type="number"
|
|
|
|
|
:precision="2"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
style="width: 120px;"
|
|
|
|
|
/>
|
|
|
|
|
元,不满{{form.startRule.timeoutTime}}{{unitLabel(form.rentalUnit)}},按{{form.startRule.timeoutTime}}{{unitLabel(form.rentalUnit)}}计算。
|
|
|
|
|
</div>
|
2025-03-18 18:05:19 +08:00
|
|
|
|
</template>
|
|
|
|
|
<template v-else-if="form.ridingRule === SuitRidingRule.INTERVAL && form.intervalRule">
|
2025-03-27 18:04:06 +08:00
|
|
|
|
<div v-for="(item, index) in form.intervalRule" :key="index" class="rule-row">
|
2025-03-18 18:05:19 +08:00
|
|
|
|
在
|
|
|
|
|
<el-input-number
|
2025-03-27 18:04:06 +08:00
|
|
|
|
size="small"
|
2025-03-18 18:05:19 +08:00
|
|
|
|
:value="startTime(index)"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
style="width: 120px;"
|
|
|
|
|
placeholder="开始"
|
|
|
|
|
disabled
|
2025-03-27 18:04:06 +08:00
|
|
|
|
:precision="0"
|
2025-03-18 18:05:19 +08:00
|
|
|
|
/>
|
|
|
|
|
<template v-if="index < form.intervalRule.length - 1">
|
|
|
|
|
~
|
|
|
|
|
<el-input-number
|
2025-03-27 18:04:06 +08:00
|
|
|
|
size="small"
|
2025-03-18 18:05:19 +08:00
|
|
|
|
v-model="item.end"
|
2025-03-27 18:04:06 +08:00
|
|
|
|
controls-position="right"
|
|
|
|
|
style="width: 120px;"
|
|
|
|
|
placeholder="结束"
|
|
|
|
|
:min="minEnd(index)"
|
|
|
|
|
:max="maxEnd(index)"
|
|
|
|
|
:precision="0"
|
|
|
|
|
/>
|
|
|
|
|
{{unitLabel(form.rentalUnit)}}之间,
|
2025-03-18 18:05:19 +08:00
|
|
|
|
</template>
|
|
|
|
|
<template v-else>
|
|
|
|
|
之后,
|
|
|
|
|
</template>
|
|
|
|
|
每
|
|
|
|
|
<el-input-number
|
2025-03-27 18:04:06 +08:00
|
|
|
|
size="small"
|
2025-03-18 18:05:19 +08:00
|
|
|
|
v-model="item.eachUnit"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
style="width: 120px;"
|
|
|
|
|
placeholder="间隔"
|
2025-03-27 18:04:06 +08:00
|
|
|
|
:min="1"
|
|
|
|
|
:precision="0"
|
2025-03-18 18:05:19 +08:00
|
|
|
|
:max="maxEachUnit(index)"
|
|
|
|
|
/>
|
|
|
|
|
{{unitLabel(form.rentalUnit)}}收费
|
|
|
|
|
<el-input-number
|
2025-03-27 18:04:06 +08:00
|
|
|
|
size="small"
|
2025-03-18 18:05:19 +08:00
|
|
|
|
v-model="item.fee"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
style="width: 120px;"
|
|
|
|
|
placeholder="价格"
|
|
|
|
|
:precision="2"
|
|
|
|
|
/>
|
|
|
|
|
元
|
|
|
|
|
<el-button type="primary" size="small" icon="el-icon-plus" plain @click="addRidingRule(index)" circle/>
|
|
|
|
|
<el-button type="danger" size="small" icon="el-icon-delete" plain @click="deleteRidingRule(index)" circle/>
|
|
|
|
|
</div>
|
|
|
|
|
<span>注:时长不含前面的时间。</span>
|
|
|
|
|
</template>
|
|
|
|
|
</collapse-panel>
|
|
|
|
|
</el-row>
|
|
|
|
|
</el-form>
|
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
|
|
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
|
|
|
|
<el-button @click="cancel">取 消</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
import { getSuit, addSuit, updateSuit } from "@/api/bst/suit";
|
|
|
|
|
import FormCol from "@/components/FormCol/index.vue";
|
|
|
|
|
import UserInput from '@/components/Business/User/UserInput.vue';
|
2025-03-25 18:04:07 +08:00
|
|
|
|
import { SuitRentalUnit, SuitRidingRule, SuitStatus, RoleKeys, SuitType } from '@/utils/enums';
|
2025-03-18 18:05:19 +08:00
|
|
|
|
import CollapsePanel from '@/components/CollapsePanel/index.vue';
|
|
|
|
|
import { deepClone, dictLabel } from '@/utils';
|
|
|
|
|
import { mapGetters } from 'vuex';
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
name: 'SuitEditDialog',
|
|
|
|
|
components: { FormCol, UserInput, CollapsePanel },
|
2025-03-25 18:04:07 +08:00
|
|
|
|
dicts: ['suit_status', 'suit_rental_unit', 'suit_riding_rule', 'suit_type'],
|
2025-03-18 18:05:19 +08:00
|
|
|
|
props: {
|
|
|
|
|
visible: {
|
|
|
|
|
type: Boolean,
|
|
|
|
|
default: false
|
|
|
|
|
},
|
|
|
|
|
id: {
|
|
|
|
|
type: [String, Number],
|
|
|
|
|
default: null
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
SuitRentalUnit,
|
|
|
|
|
SuitRidingRule,
|
|
|
|
|
SuitStatus,
|
|
|
|
|
RoleKeys,
|
2025-03-25 18:04:07 +08:00
|
|
|
|
SuitType,
|
2025-03-18 18:05:19 +08:00
|
|
|
|
span: 12,
|
|
|
|
|
title: '',
|
|
|
|
|
form: {},
|
|
|
|
|
loading: false,
|
|
|
|
|
rules: {
|
|
|
|
|
userId: [
|
|
|
|
|
{ required: true, message: "运营商不能为空", trigger: "change" }
|
|
|
|
|
],
|
|
|
|
|
name: [
|
|
|
|
|
{ required: true, message: "套餐名称不能为空", trigger: "blur" }
|
|
|
|
|
],
|
|
|
|
|
status: [
|
|
|
|
|
{ required: true, message: "状态不能为空", trigger: "change" }
|
|
|
|
|
],
|
|
|
|
|
createTime: [
|
|
|
|
|
{ required: true, message: "创建时间不能为空", trigger: "blur" }
|
|
|
|
|
],
|
|
|
|
|
freeRideTime: [
|
|
|
|
|
{ required: true, message: "免费骑行时长(分钟)不能为空", trigger: "blur" }
|
|
|
|
|
],
|
|
|
|
|
rentalUnit: [
|
|
|
|
|
{ required: true, message: "租赁单位不能为空", trigger: "blur" }
|
|
|
|
|
],
|
|
|
|
|
ridingRule: [
|
|
|
|
|
{ required: true, message: "计费规则不能为空", trigger: "blur" }
|
|
|
|
|
],
|
|
|
|
|
orderNum: [
|
|
|
|
|
{ required: true, message: "显示顺序不能为空", trigger: "blur" }
|
|
|
|
|
],
|
|
|
|
|
depositAmount: [
|
|
|
|
|
{ required: true, message: "预存款不能为空", trigger: "blur" }
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
computed: {
|
|
|
|
|
...mapGetters(['userId', 'nickName']),
|
|
|
|
|
dialogVisible: {
|
|
|
|
|
get() {
|
|
|
|
|
return this.visible;
|
|
|
|
|
},
|
|
|
|
|
set(val) {
|
|
|
|
|
this.$emit('update:visible', val);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 获取最小结束时间
|
|
|
|
|
minEnd() {
|
|
|
|
|
return (index) => {
|
|
|
|
|
if (index == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2025-03-27 18:04:06 +08:00
|
|
|
|
return this.form.intervalRule[index - 1].end + 1;
|
2025-03-18 18:05:19 +08:00
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 获取最大结束时间
|
|
|
|
|
maxEnd() {
|
|
|
|
|
return (index) => {
|
|
|
|
|
if (index >= this.form.intervalRule.length - 2 ) {
|
|
|
|
|
return 999999999;
|
|
|
|
|
} else {
|
2025-03-27 18:04:06 +08:00
|
|
|
|
return this.form.intervalRule[index + 1].end - 1;
|
2025-03-18 18:05:19 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
maxEachUnit() {
|
|
|
|
|
return (index) => {
|
|
|
|
|
if (index >= this.form.intervalRule.length - 1) {
|
|
|
|
|
return 999999999;
|
|
|
|
|
}
|
|
|
|
|
let item = this.form.intervalRule[index];
|
|
|
|
|
return item.end - item.start;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 获取开始时间
|
|
|
|
|
startTime() {
|
|
|
|
|
return (index) => {
|
|
|
|
|
if (index == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return this.form.intervalRule[index - 1].end;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
unitLabel() {
|
|
|
|
|
return (value) => {
|
|
|
|
|
return dictLabel(this.dict.type.suit_rental_unit, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
// 添加计费规则
|
|
|
|
|
addRidingRule(index) {
|
|
|
|
|
let current = this.form.intervalRule[index];
|
|
|
|
|
this.form.intervalRule.splice(index + 1, 0, {
|
2025-03-27 18:04:06 +08:00
|
|
|
|
start: null,
|
2025-03-18 18:05:19 +08:00
|
|
|
|
end: current.end + 1,
|
|
|
|
|
eachUnit: 1,
|
|
|
|
|
fee: null,
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
// 删除计费规则
|
|
|
|
|
deleteRidingRule (index) {
|
|
|
|
|
if (this.form.intervalRule.length == 1) {
|
|
|
|
|
this.$modal.msgError("至少保留一条计费规则");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.form.intervalRule.splice(index, 1);
|
|
|
|
|
},
|
|
|
|
|
handleOpen() {
|
|
|
|
|
if (this.id == null) {
|
|
|
|
|
this.reset();
|
|
|
|
|
this.title = "添加套餐";
|
|
|
|
|
} else {
|
|
|
|
|
this.getDetail();
|
|
|
|
|
this.title = "修改套餐";
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
reset() {
|
|
|
|
|
this.form = {
|
|
|
|
|
id: null,
|
|
|
|
|
userId: this.userId,
|
|
|
|
|
name: null,
|
2025-03-25 18:04:07 +08:00
|
|
|
|
type: SuitType.SHARE,
|
2025-03-18 18:05:19 +08:00
|
|
|
|
status: SuitStatus.NORMAL,
|
|
|
|
|
createTime: null,
|
|
|
|
|
freeRideTime: null,
|
|
|
|
|
rentalUnit: SuitRentalUnit.MINUTE,
|
|
|
|
|
ridingRule: SuitRidingRule.START,
|
|
|
|
|
startRule: {
|
|
|
|
|
startingTime: 60,
|
|
|
|
|
startingPrice: 5,
|
|
|
|
|
timeoutTime: 60,
|
|
|
|
|
timeoutPrice: 5
|
|
|
|
|
},
|
|
|
|
|
intervalRule: [
|
|
|
|
|
{
|
|
|
|
|
start: 0,
|
|
|
|
|
end: 1,
|
|
|
|
|
eachUnit: 1,
|
|
|
|
|
fee: null,
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
instructions: null,
|
|
|
|
|
deleted: null,
|
|
|
|
|
orderNum: null,
|
|
|
|
|
depositAmount: null,
|
|
|
|
|
// vo
|
|
|
|
|
userName: this.nickName,
|
|
|
|
|
};
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.$refs.form && this.$refs.form.clearValidate();
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
getDetail() {
|
|
|
|
|
this.loading = true;
|
|
|
|
|
getSuit(this.id).then(response => {
|
|
|
|
|
let data = response.data;
|
|
|
|
|
this.form = data;
|
|
|
|
|
}).finally(() => {
|
|
|
|
|
this.loading = false;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
submitForm() {
|
|
|
|
|
this.$refs.form.validate(valid => {
|
|
|
|
|
if (valid) {
|
|
|
|
|
// 处理数据,将start和end字段特殊处理
|
|
|
|
|
let data = deepClone(this.form);
|
|
|
|
|
if (data.ridingRule === SuitRidingRule.INTERVAL) {
|
|
|
|
|
data.intervalRule.forEach((item,index) => {
|
|
|
|
|
if (index == 0) {
|
|
|
|
|
item.start = 0;
|
|
|
|
|
} else {
|
|
|
|
|
item.start = data.intervalRule[index - 1].end;
|
|
|
|
|
}
|
2025-03-27 18:04:06 +08:00
|
|
|
|
|
|
|
|
|
if (index == data.intervalRule.length - 1) {
|
|
|
|
|
item.end = null;
|
|
|
|
|
}
|
2025-03-18 18:05:19 +08:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
const promise = this.form.id != null ? updateSuit(data) : addSuit(data);
|
|
|
|
|
promise.then(response => {
|
|
|
|
|
this.$modal.msgSuccess(this.form.id != null ? "修改成功" : "新增成功");
|
|
|
|
|
this.dialogVisible = false;
|
|
|
|
|
this.$emit('success');
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
cancel() {
|
|
|
|
|
this.dialogVisible = false;
|
|
|
|
|
this.reset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
2025-03-27 18:04:06 +08:00
|
|
|
|
.rule-row {
|
|
|
|
|
margin-bottom: 4px;
|
|
|
|
|
}
|
2025-03-18 18:05:19 +08:00
|
|
|
|
</style>
|