2025-05-07 15:57:15 +08:00

780 lines
23 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<a-spin
:spinning="spinning"
:tip="tipContent"
>
<a-form
:model="form"
:label-col="{sm: { span: 8 } }"
:wrapper-col="{ span:24}"
ref="formRef"
>
<a-row :gutter="8">
<a-col :xs="12">
<a-form-item
label="计费方式"
required
name="chargingMode"
:rules="[{ required: true, message: '请选择计费方式' }]"
>
<a-select
v-model:value="form.chargingMode"
placeholder="请选择计费方式"
allow-clear
>
<a-select-option value="1">时间计费</a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="8">
<a-col :xs="12">
<a-form-item
:label="freeDuration"
required
name="freeDuration"
:rules="[{ required: true, message: '请输入免费时长' }]"
>
<a-input
v-model:value="form.freeDuration"
placeholder="请输入免费时长"
type="number"
/>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="8">
<a-col :xs="12">
<a-form-item
label="分时段计费"
required
name="timeDivisionCharging"
:rules="[{ required: true, message: '请选择分时段计费' }]"
>
<a-radio-group
v-model:value="form.timeDivisionCharging"
name="radioGroup"
@change="changeTimeDivisionCharging"
>
<a-radio value="1">关闭</a-radio>
<a-radio value="2">时间段</a-radio>
<a-radio value="3"></a-radio>
</a-radio-group>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="8">
<a-col :xs="12">
<a-form-item
label="起步费用(元)"
required
name="startupCost"
:rules="[{ required: true, message: '请输入起步费用' }]"
>
<a-input
v-model:value="form.startupCost"
placeholder="请输入起步费用"
type="number"
/>
</a-form-item>
</a-col>
<a-col :xs="12">
<a-form-item
label="起步时长(分钟)"
required
name="startupDuration"
:rules="[{ required: true, message: '起步时长' }]"
>
<a-input
v-model:value="form.startupDuration"
placeholder="起步时长"
type="number"
/>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="8">
<a-col :xs="12">
<a-form-item
label="时长费用(元)"
required
name="durationCost"
:rules="[{ required: true, message: '请输入时长费用' }]"
>
<a-input
v-model:value="form.durationCost"
placeholder="请输入时长费用"
type="number"
/>
</a-form-item>
</a-col>
<a-col :xs="12">
<a-form-item
label="时长(分钟)"
required
name="duration"
:rules="[{ required: true, message: '请输入时长' }]"
>
<a-input
v-model:value="form.duration"
placeholder="请输入时长"
type="number"
/>
</a-form-item>
</a-col>
</a-row>
<a-row
:gutter="8"
v-if="deteilShow"
>
<a-col :xs="24">
<a-form-item
label="分时段明细"
:name="field"
:label-col="{ sm: { span: 4 }}"
:wrapper-Col="{span: 24 }"
>
<a-table
bordered
:columns="columns"
:dataSource="form[field]"
:scroll="{ x: 'max-content' }"
:pagination="false"
>
<template #headerCell="{ column }">
<template v-if="column.key === 'action'">
<SettingOutlined style="margin-right: 5px" />{{ column.title }}
</template>
</template>
<template #bodyCell="{ column,record,index }">
<template v-if="column.key === 'phase'">
<a-space>
{{index + 1}}
</a-space>
</template>
<template v-if="column.key === 'action'">
<a-popconfirm
title="删除此行?"
ok-text="确定"
cancel-text="取消"
@confirm="deleteRecord(record)"
>
<a-space>
<a href="#">删除</a>
</a-space>
</a-popconfirm>
</template>
<template v-if=" column.type == 'input'">
<a-input
v-model:value="record[column.dataIndex]"
:placeholder="`请输入`"
:style="{ width: '100%' }"
/>
</template>
<div id="timePicker"></div>
<template v-if="column.type == 'time'">
<a-tooltip
color="white"
:open="true"
:getPopupContainer="getPopupContainerFunc"
v-if="record['toolTip'] && column.dataIndex == 'startupTime'"
>
<template #title>
<div style="color: red;">时间重叠!</div>
</template>
<TimePicker
placeholder="请选择"
format="HH:mm:ss"
v-model:value="record[column.dataIndex]"
@change="checkWorkTime"
/>
</a-tooltip>
<TimePicker
v-else
placeholder="请选择"
format="HH:mm:ss"
v-model:value="record[column.dataIndex]"
@change="checkWorkTime"
/>
</template>
<template v-if=" column.type == 'select'">
<a-tooltip
color="white"
:open="true"
:getPopupContainer="getPopupContainerFunc"
v-if="record['toolTip']"
>
<template #title>
<div style="color: red;">已选择相同的周天数!</div>
</template>
<a-select
v-model:value="record[column.dataIndex]"
mode="multiple"
style="width: 100%"
placeholder="请选择"
:max-tag-count="1"
@change="checkWeek"
>
<a-select-option value="1">周一</a-select-option>
<a-select-option value="2">周二</a-select-option>
<a-select-option value="3">周三</a-select-option>
<a-select-option value="4">周四</a-select-option>
<a-select-option value="5">周五</a-select-option>
<a-select-option value="6">周六</a-select-option>
<a-select-option value="7">周日</a-select-option>
</a-select>
</a-tooltip>
<a-select
v-else
v-model:value="record[column.dataIndex]"
mode="multiple"
style="width: 100%"
placeholder="请选择"
:max-tag-count="1"
@change="checkWeek"
>
<a-select-option value="1">周一</a-select-option>
<a-select-option value="2">周二</a-select-option>
<a-select-option value="3">周三</a-select-option>
<a-select-option value="4">周四</a-select-option>
<a-select-option value="5">周五</a-select-option>
<a-select-option value="6">周六</a-select-option>
<a-select-option value="7">周日</a-select-option>
</a-select>
</template>
</template>
</a-table>
<a-button
type="default"
@click="addRecord"
:style="{
width: '100%',
marginTop: '5px',
border: '1px dashed #1890ff',
backgroundColor: 'transparent',
color: '#1890ff'
}"
>
<PlusOutlined />
向下添加一行
</a-button>
<div style="width: 100%;margin-top: 15px;color: rgb(140,140,140);">{{warmReminder}}</div>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="8">
<a-col :xs="12">
<a-form-item
label="运营区域外调度费(元)"
required
name="dispatchFeeOutOperateArea"
:rules="[{ required: true, message: '请输入运营区域外调度费' }]"
>
<a-input
v-model:value="form.dispatchFeeOutOperateArea"
placeholder="请输入运营区域外调度费"
type="number"
/>
</a-form-item>
</a-col>
<a-col :xs="12">
<a-form-item
label="禁停区调度费(元)"
required
name="dispatchFeeBanArea"
:rules="[{ required: true, message: '请输入禁停区调度费' }]"
>
<a-input
v-model:value="form.dispatchFeeBanArea"
placeholder="请输入禁停区调度费"
type="number"
/>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="8">
<a-col :xs="12">
<a-form-item
label="停车区外调度费(元)"
required
name="parkingAreaOutDispatchFee"
:rules="[{ required: true, message: '请输入停车区外调度费' }]"
>
<a-input
v-model:value="form.parkingAreaOutDispatchFee"
placeholder="请输入停车区外调度费"
type="number"
/>
</a-form-item>
</a-col>
<a-col :xs="12">
<a-form-item
label="头盔管理费(元)"
required
name="helmetManagementFee"
:rules="[{ required: true, message: '请输入头盔管理费' }]"
>
<a-input
v-model:value="form.helmetManagementFee"
placeholder="请输入头盔管理费"
type="number"
/>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="8">
<a-col :xs="12">
<a-form-item
label="封顶金额(元)"
required
name="cappedAmount"
:rules="[{ required: true, message: '请输入封顶金额' }]"
>
<a-input
v-model:value="form.cappedAmount"
placeholder="请输入封顶金额"
type="number"
/>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="8">
<a-col :xs="12">
<a-form-item
label="短租预付款"
required
name="shortRentAdvance"
:rules="[{ required: true, message: '请选择短租预付款' }]"
>
<a-radio-group
v-model:value="form.shortRentAdvance"
name="radioGroup"
>
<a-radio value="1">是</a-radio>
<a-radio value="2">否</a-radio>
</a-radio-group>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="8">
<a-col :xs="12">
<a-form-item
label="是否开启长租"
required
name="whetherOpenLongRent"
:rules="[{ required: true, message: '请选择计费方式' }]"
>
<a-radio-group
v-model:value="form.whetherOpenLongRent"
name="radioGroup"
>
<a-radio value="1"></a-radio>
<a-radio value="2"></a-radio>
</a-radio-group>
</a-form-item>
</a-col>
</a-row>
</a-form>
</a-spin>
</template>
<style scoped>
.a-tabs-card {
position: relative;
}
</style>
<script setup>
import { ref } from 'vue'
import { callOperate } from '@/apis/call.js'
import { message } from 'ant-design-vue'
import { getGUID } from '@/utils/tools';
import _ from 'lodash'
import { TimePicker } from 'ant-design-vue'
import dayjs from 'dayjs';
const formRef = ref();
const spinning = ref(false);
const tipContent = ref("加载中...");
const freeDuration = ref("免费时长(分钟)");
const deteilShow = ref(false);
const isAdd = ref(true);
const warmReminder = ref("");
const field = ref("");
const saveFlag = ref(true);
const openTimeTip = ref(false)
const openWeekTip = ref(false)
const costConfigId = ref("");
const formData = () => ({
costConfigId: "",
operationRegionId: "",
chargingMode: "",
freeDurationMode: "1",
freeDuration: "免费时长(分钟)",
timeDivisionCharging: "",
ebikeSysRcostsetTimePeriodDtos: [],
ebikeSysRcostsetWeekDtos: [],
startupCost: "",
startupDuration: "",
durationCost: "",
duration: "",
dispatchFeeOutOperateArea: "",
dispatchFeeBanArea: "",
parkingAreaOutDispatchFee: "",
helmetManagementFee: "",
cappedAmount: "",
shortRentAdvance: "",
whetherOpenLongRent: ""
});
const form = ref(formData());
// 表格列配置
const columns = ref([])
const timePeriodColumns = [
{
title: '阶段',
key: 'phase',
width: 70,
align: 'center',
dataIndex: 'phase'
},
{
title: '起始时间',
key: 'startupTime',
width: 130,
align: 'center',
dataIndex: 'startupTime',
type: 'time'
},
{
title: '结束时间',
key: 'endTime',
width: 130,
align: 'center',
dataIndex: 'endTime',
type: 'time'
},
{
title: '起步费用(元)',
key: 'startupCost',
width: 120,
align: 'center',
dataIndex: 'startupCost',
type: 'input'
},
{
title: '起步时长(分)',
key: 'startupDuration',
width: 120,
align: 'center',
dataIndex: 'startupDuration',
type: 'input'
},
{
title: '时长费用(元)',
key: 'durationCost',
width: 120,
align: 'center',
dataIndex: 'durationCost',
type: 'input'
},
{
title: '时长(分)',
key: 'duration',
width: 100,
align: 'center',
dataIndex: 'duration',
type: 'input'
},
{
title: '操作',
key: 'action',
width: 80,
align: 'center',
fixed: 'right',
}
]
const weekColumns = [
{
title: '名称',
key: 'configName',
width: 100,
align: 'center',
dataIndex: 'configName',
type: 'input'
},
{
title: '周',
key: 'week',
width: 170,
align: 'center',
dataIndex: 'week',
type: 'select'
},
{
title: '起步费用(元)',
key: 'startupCost',
width: 120,
align: 'center',
dataIndex: 'startupCost',
type: 'input'
},
{
title: '起步时长(分)',
key: 'startupDuration',
width: 120,
align: 'center',
dataIndex: 'startupDuration',
type: 'input'
},
{
title: '时长费用(元)',
key: 'durationCost',
width: 120,
align: 'center',
dataIndex: 'durationCost',
type: 'input'
},
{
title: '时长(分)',
key: 'duration',
width: 100,
align: 'center',
dataIndex: 'duration',
type: 'input'
},
{
title: '操作',
key: 'action',
width: 80,
align: 'center',
fixed: 'right',
}
]
const changeTimeDivisionCharging = (data) => {
const value = data.target.value;
if (value == "2") {
field.value = "ebikeSysRcostsetTimePeriodDtos";
if (form.value['ebikeSysRcostsetTimePeriodDtos'] == null) {
form.value['ebikeSysRcostsetTimePeriodDtos'] = [];
}
form.value.ebikeSysRcostsetWeekDtos = [];
deteilShow.value = true;
warmReminder.value = "温馨提示当天结束的阶段为23:59:59没有设置的话默认配置为上面的字段。";
columns.value = timePeriodColumns;
} else if (value == "3") {
field.value = "ebikeSysRcostsetWeekDtos";
if (form.value['ebikeSysRcostsetWeekDtos'] == null) {
form.value['ebikeSysRcostsetWeekDtos'] = [];
}
form.value.ebikeSysRcostsetTimePeriodDtos = [];
deteilShow.value = true;
warmReminder.value = "温馨提示周的日期支持多选比如可以选择周一、周二、周三为1种计费方式没有选择的按默认选择方式来。";
columns.value = weekColumns;
} else {
field.value = "";
deteilShow.value = false;
warmReminder.value = "";
columns.value = []
form.value.ebikeSysRcostsetTimePeriodDtos = [];
form.value.ebikeSysRcostsetWeekDtos = [];
}
}
const openForm = (params = {}) => {
deteilShow.value = false;
Object.assign(form.value, formData());
isAdd.value = true;
if (params['operationRegionId']) {
form.value.operationRegionId = params['operationRegionId']
spinning.value = true;
callOperate("/ebikesysrcostset/getRegionFeeConfigById?operationRegionId="
+ params['operationRegionId'], {}, "get").then(res => {
spinning.value = false;
if (res.code == 200) {
if (res.data.costConfigId) {
isAdd.value = false;
form.value = res.data;
if (res.data.timeDivisionCharging == '2') {
const item = res.data.ebikeSysRcostsetTimePeriodDtos;
if (item.length > 0) {
item.forEach(t => {
t['startupTime'] = dayjs(t['startupTime'], 'HH:mm:ss');
t['endTime'] = dayjs(t['endTime'], 'HH:mm:ss');
})
}
form.value.ebikeSysRcostsetTimePeriodDtos = item;
field.value = "ebikeSysRcostsetTimePeriodDtos";
deteilShow.value = true;
warmReminder.value = "温馨提示当天结束的阶段为23:59:59没有设置的话默认配置为上面的字段。";
columns.value = timePeriodColumns;
} else if (res.data.timeDivisionCharging == '3') {
field.value = "ebikeSysRcostsetWeekDtos";
deteilShow.value = true;
warmReminder.value = "温馨提示周的日期支持多选比如可以选择周一、周二、周三为1种计费方式没有选择的按默认选择方式来。";
columns.value = weekColumns;
} else {
field.value = "";
}
} else {
callOperate("/ebikesysrcostset/createSnowflakeId", {}, "get").then(res => {
if (res.code == 200) {
costConfigId.value = res.data;
}
})
}
} else {
message.error(res.message);
}
})
}
};
const addRecord = () => {
const timeDivisionCharging = form.value.timeDivisionCharging;
let item = {};
let timeSegmentDetail = field.value
const record = form.value[timeSegmentDetail][form.value[timeSegmentDetail].length - 1];
if (timeDivisionCharging == '2') {
let startupTime = dayjs("00:00:00", 'HH:mm:ss');
if (record) {
startupTime = dayjs(record['endTime'], 'HH:mm:ss')
}
item = {
key: getGUID(),
phase: "",
startupTime: startupTime,
endTime: dayjs("23:59:59", 'HH:mm:ss'),
startupCost: "",
startupDuration: "",
durationCost: "",
duration: ""
};
} else if (timeDivisionCharging == '3') {
item = {
key: getGUID(),
configName: "",
week: [],
startupCost: "",
startupDuration: "",
durationCost: "",
duration: "",
};
}
form.value[timeSegmentDetail].push(item)
}
const deleteRecord = (record) => {
const key = record['key'];
let timeSegmentDetail = field.value
let item = _.clone(form.value[timeSegmentDetail]);
remove(key, "key", item)
form.value[timeSegmentDetail] = item;
if (timeSegmentDetail == 'ebikeSysRcostsetWeekDtos') {
checkWeek();
} else {
checkWorkTime();
}
}
const remove = (val, filed, array) => {
const index = array.findIndex(obj => obj[filed] === val);
if (index > -1) {
array.splice(index, 1);
}
}
const getPopupContainerFunc = () => {
return document.getElementById("timePicker");
}
/**
* 检查周有无重叠
*/
const checkWeek = () => {
openWeekTip.value = false;
saveFlag.value = true;
const seenWeeks = [];
form.value['ebikeSysRcostsetWeekDtos'].forEach(items => {
const week = items['week'];
items['toolTip'] = false;
if (week.some(item => seenWeeks.includes(item))) {
openWeekTip.value = true;
items['toolTip'] = true;
saveFlag.value = false;
} else {
seenWeeks.push(...week);
}
});
}
/**
* 检查时间段有无重叠
*/
const checkWorkTime = () => {
openTimeTip.value = false;
saveFlag.value = true;
const periods = form.value['ebikeSysRcostsetTimePeriodDtos'];
for (let i = 0; i < periods.length; i++) {
const currentPeriod = periods[i];
const currentStartTime = new Date(currentPeriod['startupTime']);
const currentEndTime = new Date(currentPeriod['endTime']);
for (let j = i + 1; j < periods.length; j++) {
const comparePeriod = periods[j];
const compareStartTime = new Date(comparePeriod['startupTime']);
const compareEndTime = new Date(comparePeriod['endTime']);
comparePeriod['toolTip'] = false;
if (
(currentStartTime < compareEndTime && currentEndTime > compareStartTime) ||
(compareStartTime < currentEndTime && compareEndTime > currentStartTime)
) {
openTimeTip.value = true;
saveFlag.value = false;
comparePeriod['toolTip'] = true;
}
}
}
}
const formSave = (callBack) => {
if (saveFlag.value) {
formRef.value.validate().then(() => {
tipContent.value = "保存中..."
spinning.value = true;
let url = "regionFeeConfigAdds";
if (!isAdd.value) {
url = "updateRegionFeeConfig"
}
isAdd.value = false;
const param = _.cloneDeep(form.value)
if (!param['costConfigId'] && costConfigId.value) {
param['costConfigId'] = costConfigId.value;
}
if (param['ebikeSysRcostsetTimePeriodDtos'] && param['ebikeSysRcostsetTimePeriodDtos'].length > 0) {
param['ebikeSysRcostsetTimePeriodDtos'].forEach(item => {
item['startupTime'] = item['startupTime'].format('HH:mm:ss');
item['endTime'] = item['endTime'].format('HH:mm:ss');
})
}
callOperate("/ebikesysrcostset/" + url, param).then(res => {
spinning.value = false;
if (callBack) {
res.data = param;
callBack(res);
}
})
}).catch(error => {
console.log('error', error);
});
}
};
defineExpose({ openForm, formSave });
</script>