Files
charge-pile-system/src/views/charging_pile/Price.vue
MeSHard 26ecddea1e 1
2025-11-20 17:32:46 +08:00

518 lines
14 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>
<div class="container">
<div class="search-area">
<Form ref="formInline" inline :label-width="120" :model="formInline" :rules="ruleInline">
<FormItem prop="charge_station_name" label="站点名称:">
<Input type="text" clearable v-model="formInline.charge_station_name" placeholder="" />
</FormItem>
<FormItem>
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
</FormItem>
</Form>
</div>
<div class="action-btn">
<!-- <Button type="primary" @click="add">添加</Button> -->
<!-- <Button type="error">删除</Button> -->
</div>
<div class="table-container">
<Table border :columns="columns" stripe :height="tableHeight" :data="data">
<template #action="{ row, index }">
<Button type="primary" size="small" style="margin-right: 5px"
@click="show(row.charge_station_id)">编辑</Button>
<Button type="error" size="small" @click="remove(row.charge_station_id)">删除</Button>
</template>
</Table>
<Page :total="total" show-total show-sizer class="page" @on-change="onChangePage"
@on-page-size-change="onChangePageSize" />
</div>
<!-- 添加编辑 -->
<Modal v-model="show_modal" title="添加" :mask-closable="false">
<Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="80">
<FormItem label="站点名称" prop="charge_station_id">
<Select v-model="formValidate.charge_station_id" style="width:200px">
<Option v-for="item in data" :value="item.charge_station_id" :key="item.charge_station_id">
{{ item.charge_station_name }}
</Option>
</Select>
</FormItem>
<FormItem label="电费" prop="ElectricityFee">
<Row class="header-row">
<Col span="6">开始时间</Col>
<Col span="6">结束时间</Col>
<Col span="6">电费金额</Col>
<Col span="3">
<Button type="primary" @click="addNewItem" icon="plus">新增时段</Button>
</Col>
</Row>
<Row v-for="(item, index) in electricityFeeArr" :key="item.id || index" class="data-row">
<Col span="6">
<TimePicker placeholder="开始时间" format="HH:mm" valueFormat="HH:mm" style="width: 100px"
v-model="item.startTime" />
</Col>
<Col span="6">
<TimePicker placeholder="结束时间" format="HH:mm" valueFormat="HH:mm" style="width: 100px"
v-model="item.endTime" />
</Col>
<Col span="6">
<Input placeholder="金额" style="width: 100px" :precision="2"
v-model="item.amount" />
</Col>
<Col span="3">
<Button type="danger" icon="delete" size="small" @click="removeItem(index)"
:disabled="electricityFeeArr.length <= 1">
删除
</Button>
</Col>
</Row>
<div v-if="electricityFeeArr.length === 0" class="empty-state">
暂无电费时段配置请点击上方按钮添加
</div>
</FormItem>
<FormItem label="服务费" prop="ServiceFee">
<Row class="header-row">
<Col span="6">开始时间</Col>
<Col span="6">结束时间</Col>
<Col span="6">服务费金额</Col>
<Col span="3">
<Button type="primary" @click="addNewServeItem" icon="plus">新增时段</Button>
</Col>
</Row>
<Row v-for="(item, index) in serverFeeArr" :key="item.id || index" class="data-row">
<Col span="6">
<TimePicker placeholder="开始时间" format="HH:mm" valueFormat="HH:mm" style="width: 100px"
v-model="item.startTime" />
</Col>
<Col span="6">
<TimePicker placeholder="结束时间" format="HH:mm" valueFormat="HH:mm" style="width: 100px"
v-model="item.endTime" />
</Col>
<Col span="6">
<Input placeholder="金额" style="width: 100px" :min="0" :precision="2"
v-model="item.amount" />
</Col>
<Col span="3">
<Button type="danger" icon="delete" size="small" @click="removeServeItem(index)"
:disabled="serverFeeArr.length <= 1">
删除
</Button>
</Col>
</Row>
<div v-if="serverFeeArr.length === 0" class="empty-state">
暂无
</div>
</FormItem>
</Form>
<div slot="footer">
<Button type="text" @click="cancel">取消</Button>
<Button type="primary" @click="ok">确定</Button>
</div>
</Modal>
</div>
</template>
<script>
import {
getStationList,
addPosition,
getStationRead,
getStationUpdate,
getStationDelete,
} from '@/api'
export default {
name: 'charging_station',
data() {
return {
page: 1,
pageSize: 10,
show_modal: false,
total: 100,
tableHeight: 500,
formInline: {
charge_station_name: '',
},
ruleInline: {},
columns: [{
title: '站点名称',
key: 'charge_station_name',
},
{
title: '电费',
key: 'ElectricityFee',
},
{
title: '服务费',
key: 'ServiceFee',
},
{
title: '操作',
slot: 'action',
width: 150,
align: 'center',
},
],
data: [],
formValidate: {
charge_station_id: '',
},
ruleValidate: {
charge_station_id: [{
required: true,
message: '请选择充电站',
trigger: 'blur',
}],
},
electricityFeeArr: [],
serverFeeArr: [],
}
},
mounted() {
this.getList()
this.calculateTableHeight()
window.addEventListener('resize', this.calculateTableHeight)
},
beforeDestroy() {
window.removeEventListener('resize', this.calculateTableHeight)
},
methods: {
calculateTableHeight() {
// 计算表格高度 = 窗口高度 - 搜索区域高度 - 分页高度 - 其他间距
const searchHeight = document.querySelector('.search-area').offsetHeight
const actionBtnHeight = document.querySelector('.action-btn').offsetHeight
const pageHeight = 32 // 分页组件大约高度
const margins = 40 // 上下边距总和
this.tableHeight = window.innerHeight - actionBtnHeight - searchHeight - pageHeight - margins - 130
},
async getList() {
await getStationList({
page: this.page,
pageSize: this.pageSize,
...this.formInline,
}).then((res) => {
this.total = res.data.total
this.data = res.data.data
})
},
handleSubmit() {
this.getList()
},
add() {
this.show_modal = true
this.$refs.formValidate.resetFields()
this.formValidate.charge_station_id = ''
},
cancel() {
this.$refs.formValidate.resetFields()
this.show_modal = false
this.electricityFeeArr = []
this.serverFeeArr = []
},
// 详情
async show(id) {
await getStationRead({
id,
}).then(res => {
let ElectricityFee = res.data.ElectricityFee.split('电费:')[1].split(',')
let ServiceFee = res.data.ServiceFee.split('服务费:')[1].split(',')
let ElectricityFeeArr = []
let ServiceFeeArr = []
ElectricityFeeArr = ElectricityFee.map(item => {
const parts = item.split(':')
const amount = parts.pop()
const timePart = parts.join(':')
const times = timePart.split('~')
return {
startTime: times[0],
endTime: times[1],
amount,
}
})
ServiceFeeArr = ServiceFee.map(item => {
const parts = item.split(':')
const amount = parts.pop()
const timePart = parts.join(':')
const times = timePart.split('~')
return {
startTime: times[0],
endTime: times[1],
amount,
}
})
this.electricityFeeArr = ElectricityFeeArr
this.serverFeeArr = ServiceFeeArr
this.formValidate.charge_station_id = res.data.charge_station_id
this.show_modal = true
})
},
async remove(id) {
const confirm = await new Promise(resolve => {
this.$Modal.confirm({
title: '确认删除',
content: '您确定要删除此项吗?',
onOk: () => resolve(true),
onCancel: () => resolve(false),
})
})
if (!confirm) {
this.$Message.info('已取消删除')
return
}
await getStationDelete({
id,
}).then(res => {
this.$Message.success(res.msg)
this.getList()
})
},
async ok() {
if (this.electricityFeeArr.length < 1) {
this.$Message.error('请正确填写电费')
return
}
this.validateConfig()
if (this.serverFeeArr.length < 1) {
this.$Message.error('请正确填写服务费')
return
}
this.validateServeConfig()
if (!this.formValidate.charge_station_id) {
this.$Message.error('请选择充电站')
return
}
// console.log(this.formValidate)
// const valid = await new Promise(resolve => this.$refs.formValidate.validate(resolve))
// console.log(this.valid)
// if (!valid) {
// this.$Message.error('请正确填写表单')
// return
// }
this.formValidate.electricityFee = this.electricityFeeArr
this.formValidate.serverFee = this.serverFeeArr
if (this.formValidate.charge_station_id) {
await getStationUpdate(this.formValidate).then(res => {
this.$Message.success(res.msg)
this.getList()
this.cancel()
})
} else {
await addPosition(this.formValidate).then((res) => {
this.$Message.success(res.msg)
this.cancel()
this.getList()
})
}
},
onChangePage(e) {
if (this.page != e) {
this.page = e
this.getList()
}
},
onChangePageSize(e) {
if (this.pageSize != e) {
this.page = 1
this.pageSize = e
this.getList()
}
},
// 添加新的电费时段
addNewItem() {
const lastItem = this.electricityFeeArr[this.electricityFeeArr.length - 1]
this.electricityFeeArr.push({
id: Date.now(), // 使用时间戳作为唯一标识
startTime: '',
endTime: '',
amount: lastItem ? lastItem.amount : 0.00,
})
},
/**
* 删除指定索引的电费时段
*/
removeItem(index) {
if (this.electricityFeeArr.length <= 1) {
this.$message.warning('至少保留一个电费时段')
return
}
this.electricityFeeArr.splice(index, 1)
this.$message.success('删除成功')
},
/**
* 校验电费配置数据的有效性
*/
validateConfig() {
const errors = []
this.electricityFeeArr.forEach((item, index) => {
if (!item.startTime) {
errors.push(`${index + 1}行的开始时间为空`)
}
if (!item.endTime) {
errors.push(`${index + 1}行的结束时间为空`)
}
if (!item.amount && item.amount !== 0) {
errors.push(`${index + 1}行的电费金额为空`)
}
if (parseFloat(item.amount) < 0) {
errors.push(`${index + 1}行的电费金额不能为负数`)
}
})
return {
isValid: errors.length === 0,
errors,
}
},
// 添加新的服务费费时段
addNewServeItem() {
const lastItem = this.serverFeeArr[this.serverFeeArr.length - 1]
this.serverFeeArr.push({
id: Date.now(), // 使用时间戳作为唯一标识
startTime: '',
endTime: '',
amount: lastItem ? lastItem.amount : 0.00,
})
},
/**
* 删除指定索引的服务费时段
*/
removeServeItem(index) {
if (this.serverFeeArr.length <= 1) {
this.$message.warning('至少保留一个服务费时段')
return
}
this.serverFeeArr.splice(index, 1)
this.$message.success('删除成功')
},
/**
* 获取完整的服务费配置数据
*/
getServeFeeConfigData() {
return this.serverFeeArr.map(item => ({
start_time: item.startTime,
end_time: item.endTime,
amount: Number(item.amount || 0),
}))
},
/**
* 校验服务费配置数据的有效性
*/
validateServeConfig() {
const errors = []
this.serverFeeArr.forEach((item, index) => {
if (!item.startTime) {
errors.push(`${index + 1}行的开始时间为空`)
}
if (!item.endTime) {
errors.push(`${index + 1}行的结束时间为空`)
}
if (!item.amount && item.amount !== 0) {
errors.push(`${index + 1}行的服务费金额为空`)
}
if (parseFloat(item.amount) < 0) {
errors.push(`${index + 1}行的服务费金额不能为负数`)
}
})
return {
isValid: errors.length === 0,
errors,
}
},
},
watch: {
electricityFeeArr: {
handler(newVal) {
// 如果需要实时提交到父组件
// this.$emit('config-change', newVal);
},
deep: true,
},
serverFeeArr: {
handler(newVal) {
// 如果需要实时提交到父组件
// this.$emit('config-change', newVal);
},
deep: true,
},
},
}
</script>
<style scoped>
.container {
display: flex;
flex-direction: column;
height: 100vh;
padding: 20px;
box-sizing: border-box;
}
.action-btn {
margin: 20px 0;
background-color: white;
padding: 20px;
border: 1px solid #F3F7FD;
border-radius: 15px;
display: flex;
align-items: center;
button {
margin-right: 20px;
}
}
.table-container {
flex: 1;
display: flex;
flex-direction: column;
}
.page {
margin-top: 10px;
text-align: right;
}
.search-area {
background-color: white;
padding-top: 20px;
border: 1px solid #F3F7FD;
border-radius: 15px;
}
.electricity-fee-container {
padding: 20px;
border: 1px solid #e8e8e8;
border-radius: 6px;
}
.header-row {
font-weight: bold;
margin-bottom: 15px;
color: #1890ff;
font-size: 12px;
}
.data-row {
margin-bottom: 12px;
align-items: center;
transition: all 0.3s ease;
}
.data-row:hover {
background-color: #fafafa;
}
.last-row {
margin-bottom: 25px;
}
.empty-state {
text-align: center;
color: #999;
padding: 40px 0;
font-style: italic;
}
</style>