1
This commit is contained in:
@@ -21,29 +21,6 @@ export function EditContent(params) {
|
|||||||
return request.post('/UpdateDiscount', params)
|
return request.post('/UpdateDiscount', params)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户
|
|
||||||
*/
|
|
||||||
// 用户列表
|
|
||||||
export function GetAdmin(params) {
|
|
||||||
return request.post('/admin_list', params)
|
|
||||||
}
|
|
||||||
// 查询用户
|
|
||||||
export function searchAdmin(params) {
|
|
||||||
return request.post('/admin/read', params)
|
|
||||||
}
|
|
||||||
// 编辑用户
|
|
||||||
export function editAdmin(params) {
|
|
||||||
return request.post('/admin/update', params)
|
|
||||||
}
|
|
||||||
// 用户删除
|
|
||||||
export function deleteAdmin(params) {
|
|
||||||
return request.post('/admin/delete', params)
|
|
||||||
}
|
|
||||||
// 用户新增
|
|
||||||
export function addAdmin(params) {
|
|
||||||
return request.post('/admin/save', params)
|
|
||||||
}
|
|
||||||
// 导出
|
// 导出
|
||||||
export function exportAdminAll(params) {
|
export function exportAdminAll(params) {
|
||||||
return request.post('/admin/admin_all', params)
|
return request.post('/admin/admin_all', params)
|
||||||
@@ -406,6 +383,10 @@ export function getRefundOrder(params) {
|
|||||||
return request.get('/getRefundOrder', { params })
|
return request.get('/getRefundOrder', { params })
|
||||||
}
|
}
|
||||||
// 权限
|
// 权限
|
||||||
|
export function getRoleList(params) {
|
||||||
|
return request.get('/getRoleList', { params })
|
||||||
|
}
|
||||||
|
// 权限
|
||||||
export function GetRole(params) {
|
export function GetRole(params) {
|
||||||
return request.get('/getRoleList', { params })
|
return request.get('/getRoleList', { params })
|
||||||
}
|
}
|
||||||
@@ -419,7 +400,7 @@ export function getLogList(params) {
|
|||||||
}
|
}
|
||||||
// 运营数据
|
// 运营数据
|
||||||
export function getYunYingData(params) {
|
export function getYunYingData(params) {
|
||||||
return request.get('/getYunYingData', { params })
|
return request.get('/yunying', { params })
|
||||||
}
|
}
|
||||||
// 财务数据
|
// 财务数据
|
||||||
export function getCaiWuData(params) {
|
export function getCaiWuData(params) {
|
||||||
@@ -466,3 +447,34 @@ export function getPileUpdate(params) {
|
|||||||
export function getPileDelete(params) {
|
export function getPileDelete(params) {
|
||||||
return request.post('/getPileDelete', params)
|
return request.post('/getPileDelete', params)
|
||||||
}
|
}
|
||||||
|
// 用户金额记录
|
||||||
|
export function getUserMoneyLog(params) {
|
||||||
|
return request.get('/getUserMoneyLog', { params })
|
||||||
|
}
|
||||||
|
// 订单统计
|
||||||
|
export function orderTotal(params) {
|
||||||
|
return request.get('/orderTotal', { params })
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 用户
|
||||||
|
*/
|
||||||
|
// 用户列表
|
||||||
|
export function getAdminList(params) {
|
||||||
|
return request.get('/getAdminList', { params })
|
||||||
|
}
|
||||||
|
// 用户详情
|
||||||
|
export function getAdmin(params) {
|
||||||
|
return request.get('/getAdmin', { params })
|
||||||
|
}
|
||||||
|
// 用户新增
|
||||||
|
export function addAdmin(params) {
|
||||||
|
return request.post('/addAdmin', params)
|
||||||
|
}
|
||||||
|
// 用户更新
|
||||||
|
export function getAdminUpdate(params) {
|
||||||
|
return request.post('/getAdminUpdate', params)
|
||||||
|
}
|
||||||
|
// 用户删除
|
||||||
|
export function getAdminDelete(params) {
|
||||||
|
return request.post('/getAdminDelete', params)
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
<div class="action-btn">
|
<div class="action-btn">
|
||||||
<Button type="primary" @click="show_modal = true">添加</Button>
|
<!-- <Button type="primary" @click="show_modal = true">添加</Button> -->
|
||||||
<!-- <Button type="error">删除</Button> -->
|
<!-- <Button type="error">删除</Button> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="search-area">
|
<div class="search-area">
|
||||||
<Form ref="formInline" inline :label-width="120" :model="formInline" :rules="ruleInline">
|
<Form ref="formInline" inline :label-width="120" :model="formInline" :rules="ruleInline">
|
||||||
<FormItem prop="user" label="充电桩名称:">
|
<FormItem prop="user" label="充电站名称:">
|
||||||
<Input type="text" v-model="formInline.user" placeholder="" />
|
<Input type="text" clearable v-model="formInline.charge_station_name" placeholder="" />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
||||||
@@ -30,54 +30,23 @@
|
|||||||
<!-- no 位号 -->
|
<!-- no 位号 -->
|
||||||
|
|
||||||
<!-- 添加、编辑 -->
|
<!-- 添加、编辑 -->
|
||||||
<Modal v-model="show_modal" title="Common Modal dialog box title" :mask-closable="false" @on-ok="ok"
|
<Modal v-model="show_modal" :title="formValidate.charge_pile_id ? '编辑充电桩' : '添加充电桩'" :mask-closable="false"
|
||||||
@on-cancel="cancel">
|
@on-ok="ok" @on-cancel="cancel">
|
||||||
<Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="80">
|
<Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="100">
|
||||||
<FormItem label="Name" prop="name">
|
<FormItem label="所属充电站" prop="charge_station_id">
|
||||||
<Input v-model="formValidate.name" placeholder="Enter your name" />
|
<Select v-model="formValidate.charge_station_id" placeholder="请选择充电站" style="width: 240px"
|
||||||
</FormItem>
|
filterable>
|
||||||
<FormItem label="E-mail" prop="mail">
|
<Option v-for="station in stationOptions" :key="station.charge_station_id"
|
||||||
<Input v-model="formValidate.mail" placeholder="Enter your e-mail" />
|
:value="station.charge_station_id">
|
||||||
</FormItem>
|
{{ station.charge_station_name }}
|
||||||
<FormItem label="City" prop="city">
|
</Option>
|
||||||
<Select v-model="formValidate.city" placeholder="Select your city">
|
|
||||||
<Option value="beijing">New York</Option>
|
|
||||||
<Option value="shanghai">London</Option>
|
|
||||||
<Option value="shenzhen">Sydney</Option>
|
|
||||||
</Select>
|
</Select>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label="Date">
|
<FormItem label="充电桩编号" prop="ConnectorID">
|
||||||
<Row>
|
<Input v-model="formValidate.ConnectorID" placeholder="请输入充电桩编号" style="width: 240px" />
|
||||||
<Col span="11">
|
|
||||||
<DatePicker type="date" placeholder="Select date" v-model="formValidate.date"></DatePicker>
|
|
||||||
</Col>
|
|
||||||
<Col span="2" style="text-align: center">-</Col>
|
|
||||||
<Col span="11">
|
|
||||||
<TimePicker type="time" placeholder="Select time" v-model="formValidate.time"></TimePicker>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label="Gender" prop="gender">
|
<FormItem label="位号" prop="no">
|
||||||
<RadioGroup v-model="formValidate.gender">
|
<Input v-model="formValidate.no" placeholder="请输入充电枪位号" style="width: 240px" />
|
||||||
<Radio label="male">Male</Radio>
|
|
||||||
<Radio label="female">Female</Radio>
|
|
||||||
</RadioGroup>
|
|
||||||
</FormItem>
|
|
||||||
<FormItem label="Hobby" prop="interest">
|
|
||||||
<CheckboxGroup v-model="formValidate.interest">
|
|
||||||
<Checkbox label="Eat"></Checkbox>
|
|
||||||
<Checkbox label="Sleep"></Checkbox>
|
|
||||||
<Checkbox label="Run"></Checkbox>
|
|
||||||
<Checkbox label="Movie"></Checkbox>
|
|
||||||
</CheckboxGroup>
|
|
||||||
</FormItem>
|
|
||||||
<FormItem label="Desc" prop="desc">
|
|
||||||
<Input v-model="formValidate.desc" type="textarea" :autosize="{ minRows: 2, maxRows: 5 }"
|
|
||||||
placeholder="Enter something..." />
|
|
||||||
</FormItem>
|
|
||||||
<FormItem>
|
|
||||||
<Button type="primary" @click="handleSubmit2('formValidate')">Submit</Button>
|
|
||||||
<Button @click="handleReset('formValidate')" style="margin-left: 8px">Reset</Button>
|
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
@@ -86,14 +55,19 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
getPileList, addPile, getPileRead, getPileUpdate, getPileDelete,
|
getPileList,
|
||||||
|
addPile,
|
||||||
|
getPileRead,
|
||||||
|
getPileUpdate,
|
||||||
|
getPileDelete,
|
||||||
|
getStationList,
|
||||||
} from '@/api'
|
} from '@/api'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'charging_station',
|
name: 'charging_station',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
age: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
show_modal: false,
|
show_modal: false,
|
||||||
total: 100,
|
total: 100,
|
||||||
@@ -127,86 +101,39 @@
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
data: [],
|
data: [],
|
||||||
|
stationOptions: [], // 站点下拉缓存,避免重复请求
|
||||||
formValidate: {
|
formValidate: {
|
||||||
name: '',
|
// charge_pile_id 仅用于编辑态,后端凭此判断更新目标
|
||||||
mail: '',
|
charge_pile_id: '',
|
||||||
city: '',
|
// charge_station_id 对应所属充电站主键
|
||||||
gender: '',
|
charge_station_id: '',
|
||||||
interest: [],
|
// ConnectorID 平台内唯一充电桩编号
|
||||||
date: '',
|
ConnectorID: '',
|
||||||
time: '',
|
// no 充电枪位号,方便现场定位
|
||||||
desc: '',
|
no: '',
|
||||||
},
|
},
|
||||||
ruleValidate: {
|
ruleValidate: {
|
||||||
name: [{
|
charge_station_id: [{
|
||||||
required: true,
|
required: true,
|
||||||
message: 'The name cannot be empty',
|
message: '请选择所属充电站',
|
||||||
trigger: 'blur',
|
|
||||||
}],
|
|
||||||
mail: [{
|
|
||||||
required: true,
|
|
||||||
message: 'Mailbox cannot be empty',
|
|
||||||
trigger: 'blur',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'email',
|
|
||||||
message: 'Incorrect email format',
|
|
||||||
trigger: 'blur',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
city: [{
|
|
||||||
required: true,
|
|
||||||
message: 'Please select the city',
|
|
||||||
trigger: 'change',
|
trigger: 'change',
|
||||||
}],
|
}],
|
||||||
gender: [{
|
ConnectorID: [{
|
||||||
required: true,
|
required: true,
|
||||||
message: 'Please select gender',
|
message: '请输入充电桩编号',
|
||||||
trigger: 'change',
|
|
||||||
}],
|
|
||||||
interest: [{
|
|
||||||
required: true,
|
|
||||||
type: 'array',
|
|
||||||
min: 1,
|
|
||||||
message: 'Choose at least one hobby',
|
|
||||||
trigger: 'change',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'array',
|
|
||||||
max: 2,
|
|
||||||
message: 'Choose two hobbies at best',
|
|
||||||
trigger: 'change',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
date: [{
|
|
||||||
required: true,
|
|
||||||
type: 'date',
|
|
||||||
message: 'Please select the date',
|
|
||||||
trigger: 'change',
|
|
||||||
}],
|
|
||||||
time: [{
|
|
||||||
required: true,
|
|
||||||
type: 'string',
|
|
||||||
message: 'Please select time',
|
|
||||||
trigger: 'change',
|
|
||||||
}],
|
|
||||||
desc: [{
|
|
||||||
required: true,
|
|
||||||
message: 'Please enter a personal introduction',
|
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
}],
|
||||||
{
|
no: [{
|
||||||
type: 'string',
|
required: true,
|
||||||
min: 20,
|
message: '请输入位号',
|
||||||
message: 'Introduce no less than 20 words',
|
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
}],
|
||||||
],
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getList()
|
this.getList()
|
||||||
|
this.fetchStationOptions()
|
||||||
this.calculateTableHeight()
|
this.calculateTableHeight()
|
||||||
window.addEventListener('resize', this.calculateTableHeight)
|
window.addEventListener('resize', this.calculateTableHeight)
|
||||||
},
|
},
|
||||||
@@ -214,6 +141,34 @@
|
|||||||
window.removeEventListener('resize', this.calculateTableHeight)
|
window.removeEventListener('resize', this.calculateTableHeight)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 提取站点 ID,兼容不同接口字段
|
||||||
|
getStationId(source) {
|
||||||
|
if (!source || typeof source !== 'object') {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
const idKeys = ['charge_station_id', 'id', 'station_id']
|
||||||
|
for (let i = 0; i < idKeys.length; i += 1) {
|
||||||
|
const key = idKeys[i]
|
||||||
|
const candidate = source[key]
|
||||||
|
if (candidate !== undefined && candidate !== null && `${candidate}` !== '') {
|
||||||
|
return String(candidate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
},
|
||||||
|
// 提取显示名称,保持兜底描述
|
||||||
|
getStationLabel(source, fallbackValue = '') {
|
||||||
|
if (!source || typeof source !== 'object') {
|
||||||
|
return fallbackValue ? `站点-${fallbackValue}` : ''
|
||||||
|
}
|
||||||
|
const label = source.charge_station_name
|
||||||
|
|| source.station_name
|
||||||
|
|| source.name
|
||||||
|
if (label) {
|
||||||
|
return label
|
||||||
|
}
|
||||||
|
return fallbackValue ? `站点-${fallbackValue}` : ''
|
||||||
|
},
|
||||||
calculateTableHeight() {
|
calculateTableHeight() {
|
||||||
// 计算表格高度 = 窗口高度 - 搜索区域高度 - 分页高度 - 其他间距
|
// 计算表格高度 = 窗口高度 - 搜索区域高度 - 分页高度 - 其他间距
|
||||||
const searchHeight = document.querySelector('.search-area').offsetHeight
|
const searchHeight = document.querySelector('.search-area').offsetHeight
|
||||||
@@ -222,6 +177,31 @@
|
|||||||
const margins = 40 // 上下边距总和
|
const margins = 40 // 上下边距总和
|
||||||
this.tableHeight = window.innerHeight - actionBtnHeight - searchHeight - pageHeight - margins - 130
|
this.tableHeight = window.innerHeight - actionBtnHeight - searchHeight - pageHeight - margins - 130
|
||||||
},
|
},
|
||||||
|
// 获取充电站列表,保持与电价管理页面一致的下拉选项
|
||||||
|
async fetchStationOptions() {
|
||||||
|
try {
|
||||||
|
const res = await getStationList({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 9999,
|
||||||
|
})
|
||||||
|
const list = res && res.data && Array.isArray(res.data.data) ? res.data.data : []
|
||||||
|
const normalizedList = list.map((item) => {
|
||||||
|
const id = this.getStationId(item)
|
||||||
|
if (!id) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
charge_station_id: id,
|
||||||
|
charge_station_name: this.getStationLabel(item, id),
|
||||||
|
}
|
||||||
|
}).filter(option => option)
|
||||||
|
this.stationOptions = normalizedList
|
||||||
|
return normalizedList
|
||||||
|
} catch (error) {
|
||||||
|
this.$Message.error('获取充电站列表失败,请稍后重试')
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
async getList() {
|
async getList() {
|
||||||
await getPileList({
|
await getPileList({
|
||||||
page: this.page,
|
page: this.page,
|
||||||
@@ -235,18 +215,42 @@
|
|||||||
handleSubmit() {
|
handleSubmit() {
|
||||||
this.getList()
|
this.getList()
|
||||||
},
|
},
|
||||||
add() {
|
async add() {
|
||||||
|
if (!this.stationOptions.length) {
|
||||||
|
await this.fetchStationOptions()
|
||||||
|
}
|
||||||
|
Object.assign(this.formValidate, {
|
||||||
|
charge_pile_id: '',
|
||||||
|
charge_station_id: '',
|
||||||
|
ConnectorID: '',
|
||||||
|
no: '',
|
||||||
|
})
|
||||||
this.show_modal = true
|
this.show_modal = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.formValidate) {
|
||||||
this.$refs.formValidate.resetFields()
|
this.$refs.formValidate.resetFields()
|
||||||
this.formValidate.charge_pile_id = ''
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
cancel() {
|
cancel() {
|
||||||
|
if (this.$refs.formValidate) {
|
||||||
this.$refs.formValidate.resetFields()
|
this.$refs.formValidate.resetFields()
|
||||||
|
}
|
||||||
this.show_modal = false
|
this.show_modal = false
|
||||||
},
|
},
|
||||||
async show(id) {
|
async show(id) {
|
||||||
|
if (!this.stationOptions.length) {
|
||||||
|
await this.fetchStationOptions()
|
||||||
|
}
|
||||||
await getPileRead({ id }).then(res => {
|
await getPileRead({ id }).then(res => {
|
||||||
this.formValidate = { ...res.data }
|
const detail = (res && res.data) || {}
|
||||||
|
const stationId = this.getStationId(detail)
|
||||||
|
Object.assign(this.formValidate, {
|
||||||
|
charge_pile_id: detail.charge_pile_id || '',
|
||||||
|
charge_station_id: stationId || '',
|
||||||
|
ConnectorID: detail.ConnectorID || '',
|
||||||
|
no: detail.no || '',
|
||||||
|
})
|
||||||
this.show_modal = true
|
this.show_modal = true
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -274,14 +278,15 @@
|
|||||||
this.$Message.error('请正确填写表单')
|
this.$Message.error('请正确填写表单')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.formValidate.charge_station_id) {
|
const payload = { ...this.formValidate }
|
||||||
await getPileUpdate(this.formValidate).then(res => {
|
if (payload.charge_pile_id) {
|
||||||
|
await getPileUpdate(payload).then(res => {
|
||||||
this.$Message.success(res.msg)
|
this.$Message.success(res.msg)
|
||||||
this.getList()
|
this.getList()
|
||||||
this.cancel()
|
this.cancel()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
await addPile(this.formValidate).then((res) => {
|
await addPile(payload).then((res) => {
|
||||||
this.$Message.success(res.msg)
|
this.$Message.success(res.msg)
|
||||||
this.cancel()
|
this.cancel()
|
||||||
this.getList()
|
this.getList()
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="search-area">
|
<div class="search-area">
|
||||||
<Form ref="formInline" inline :label-width="120" :model="formInline" :rules="ruleInline">
|
<Form ref="formInline" inline :label-width="120" :model="formInline" :rules="ruleInline">
|
||||||
<FormItem prop="user" label="站点名称:">
|
<FormItem prop="charge_station_name" label="站点名称:">
|
||||||
<Input type="text" v-model="formInline.user" placeholder="" />
|
<Input type="text" clearable v-model="formInline.charge_station_name" placeholder="" />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
<div class="action-btn">
|
<div class="action-btn">
|
||||||
<Button type="primary" @click="add">添加</Button>
|
<!-- <Button type="primary" @click="add">添加</Button> -->
|
||||||
<!-- <Button type="error">删除</Button> -->
|
<!-- <Button type="error">删除</Button> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<!-- 添加、编辑 -->
|
<!-- 添加、编辑 -->
|
||||||
<Modal v-model="show_modal" title="添加" :mask-closable="false" @on-ok="ok" @on-cancel="cancel">
|
<Modal v-model="show_modal" title="添加" :mask-closable="false">
|
||||||
<Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="80">
|
<Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="80">
|
||||||
<FormItem label="站点名称" prop="charge_station_id">
|
<FormItem label="站点名称" prop="charge_station_id">
|
||||||
<Select v-model="formValidate.charge_station_id" style="width:200px">
|
<Select v-model="formValidate.charge_station_id" style="width:200px">
|
||||||
@@ -57,9 +57,8 @@
|
|||||||
v-model="item.endTime" />
|
v-model="item.endTime" />
|
||||||
</Col>
|
</Col>
|
||||||
<Col span="6">
|
<Col span="6">
|
||||||
<InputNumber placeholder="金额" style="width: 100px" :min="0" :precision="2"
|
<Input placeholder="金额" style="width: 100px" :precision="2"
|
||||||
v-model="item.feeAmount" />
|
v-model="item.amount" />
|
||||||
元
|
|
||||||
</Col>
|
</Col>
|
||||||
<Col span="3">
|
<Col span="3">
|
||||||
<Button type="danger" icon="delete" size="small" @click="removeItem(index)"
|
<Button type="danger" icon="delete" size="small" @click="removeItem(index)"
|
||||||
@@ -68,19 +67,48 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<div v-if="electricityFeeArr.length === 0" class="empty-state">
|
<div v-if="electricityFeeArr.length === 0" class="empty-state">
|
||||||
暂无电费时段配置,请点击上方按钮添加
|
暂无电费时段配置,请点击上方按钮添加
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label="服务费" prop="ServiceFee">
|
<FormItem label="服务费" prop="ServiceFee">
|
||||||
<Input v-model="formValidate.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>
|
</FormItem>
|
||||||
|
</Form>
|
||||||
<div slot="footer">
|
<div slot="footer">
|
||||||
<Button type="text" @click="cancel">取消</Button>
|
<Button type="text" @click="cancel">取消</Button>
|
||||||
<Button type="primary" @click="ok">确定</Button>
|
<Button type="primary" @click="ok">确定</Button>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -104,8 +132,7 @@
|
|||||||
total: 100,
|
total: 100,
|
||||||
tableHeight: 500,
|
tableHeight: 500,
|
||||||
formInline: {
|
formInline: {
|
||||||
user: '',
|
charge_station_name: '',
|
||||||
password: '',
|
|
||||||
},
|
},
|
||||||
ruleInline: {},
|
ruleInline: {},
|
||||||
columns: [{
|
columns: [{
|
||||||
@@ -130,8 +157,6 @@
|
|||||||
data: [],
|
data: [],
|
||||||
formValidate: {
|
formValidate: {
|
||||||
charge_station_id: '',
|
charge_station_id: '',
|
||||||
ElectricityFee: '',
|
|
||||||
ServiceFee: '',
|
|
||||||
},
|
},
|
||||||
ruleValidate: {
|
ruleValidate: {
|
||||||
charge_station_id: [{
|
charge_station_id: [{
|
||||||
@@ -139,30 +164,9 @@
|
|||||||
message: '请选择充电站',
|
message: '请选择充电站',
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
}],
|
}],
|
||||||
ElectricityFee: [{
|
|
||||||
required: true,
|
|
||||||
message: '请输入电费',
|
|
||||||
trigger: 'change',
|
|
||||||
}],
|
|
||||||
ServiceFee: [{
|
|
||||||
required: true,
|
|
||||||
message: '请输入服务费',
|
|
||||||
trigger: 'change',
|
|
||||||
}],
|
|
||||||
},
|
},
|
||||||
electricityFeeArr: [{
|
electricityFeeArr: [],
|
||||||
id: 1,
|
serverFeeArr: [],
|
||||||
startTime: '00:00',
|
|
||||||
endTime: '08:00',
|
|
||||||
feeAmount: 0.50,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
startTime: '08:00',
|
|
||||||
endTime: '18:00',
|
|
||||||
feeAmount: 0.80,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -203,15 +207,43 @@
|
|||||||
cancel() {
|
cancel() {
|
||||||
this.$refs.formValidate.resetFields()
|
this.$refs.formValidate.resetFields()
|
||||||
this.show_modal = false
|
this.show_modal = false
|
||||||
|
this.electricityFeeArr = []
|
||||||
|
this.serverFeeArr = []
|
||||||
},
|
},
|
||||||
// 详情
|
// 详情
|
||||||
async show(id) {
|
async show(id) {
|
||||||
await getStationRead({
|
await getStationRead({
|
||||||
id,
|
id,
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
this.formValidate = {
|
let ElectricityFee = res.data.ElectricityFee.split('电费:')[1].split(',')
|
||||||
...res.data,
|
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
|
this.show_modal = true
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -236,11 +268,29 @@
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
async ok() {
|
async ok() {
|
||||||
const valid = await new Promise(resolve => this.$refs.formValidate.validate(resolve))
|
if (this.electricityFeeArr.length < 1) {
|
||||||
if (!valid) {
|
this.$Message.error('请正确填写电费')
|
||||||
this.$Message.error('请正确填写表单')
|
|
||||||
return
|
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) {
|
if (this.formValidate.charge_station_id) {
|
||||||
await getStationUpdate(this.formValidate).then(res => {
|
await getStationUpdate(this.formValidate).then(res => {
|
||||||
this.$Message.success(res.msg)
|
this.$Message.success(res.msg)
|
||||||
@@ -271,12 +321,11 @@
|
|||||||
// 添加新的电费时段
|
// 添加新的电费时段
|
||||||
addNewItem() {
|
addNewItem() {
|
||||||
const lastItem = this.electricityFeeArr[this.electricityFeeArr.length - 1]
|
const lastItem = this.electricityFeeArr[this.electricityFeeArr.length - 1]
|
||||||
|
|
||||||
this.electricityFeeArr.push({
|
this.electricityFeeArr.push({
|
||||||
id: Date.now(), // 使用时间戳作为唯一标识
|
id: Date.now(), // 使用时间戳作为唯一标识
|
||||||
startTime: '',
|
startTime: '',
|
||||||
endTime: '',
|
endTime: '',
|
||||||
feeAmount: lastItem ? lastItem.feeAmount : 0.60,
|
amount: lastItem ? lastItem.amount : 0.00,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@@ -287,27 +336,9 @@
|
|||||||
this.$message.warning('至少保留一个电费时段')
|
this.$message.warning('至少保留一个电费时段')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$confirm({
|
|
||||||
title: '确认删除',
|
|
||||||
content: '确定要删除这个电费时段吗?',
|
|
||||||
onOk: () => {
|
|
||||||
this.electricityFeeArr.splice(index, 1)
|
this.electricityFeeArr.splice(index, 1)
|
||||||
this.$message.success('删除成功')
|
this.$message.success('删除成功')
|
||||||
},
|
},
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取完整的电费配置数据
|
|
||||||
*/
|
|
||||||
getFeeConfigData() {
|
|
||||||
return this.electricityFeeArr.map(item => ({
|
|
||||||
start_time: item.startTime,
|
|
||||||
end_time: item.endTime,
|
|
||||||
amount: Number(item.feeAmount || 0),
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
/**
|
/**
|
||||||
* 校验电费配置数据的有效性
|
* 校验电费配置数据的有效性
|
||||||
*/
|
*/
|
||||||
@@ -323,11 +354,11 @@
|
|||||||
errors.push(`第${index + 1}行的结束时间为空`)
|
errors.push(`第${index + 1}行的结束时间为空`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!item.feeAmount && item.feeAmount !== 0) {
|
if (!item.amount && item.amount !== 0) {
|
||||||
errors.push(`第${index + 1}行的电费金额为空`)
|
errors.push(`第${index + 1}行的电费金额为空`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parseFloat(item.feeAmount) < 0) {
|
if (parseFloat(item.amount) < 0) {
|
||||||
errors.push(`第${index + 1}行的电费金额不能为负数`)
|
errors.push(`第${index + 1}行的电费金额不能为负数`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -336,11 +367,72 @@
|
|||||||
errors,
|
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: {
|
watch: {
|
||||||
electricityFeeArr: {
|
electricityFeeArr: {
|
||||||
handler(newVal) {
|
handler(newVal) {
|
||||||
console.log('电费配置发生变化:', newVal)
|
// 如果需要实时提交到父组件
|
||||||
|
// this.$emit('config-change', newVal);
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
},
|
||||||
|
serverFeeArr: {
|
||||||
|
handler(newVal) {
|
||||||
// 如果需要实时提交到父组件
|
// 如果需要实时提交到父组件
|
||||||
// this.$emit('config-change', newVal);
|
// this.$emit('config-change', newVal);
|
||||||
},
|
},
|
||||||
@@ -400,6 +492,7 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
color: #1890ff;
|
color: #1890ff;
|
||||||
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-row {
|
.data-row {
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="search-area">
|
<div class="search-area">
|
||||||
<Form ref="formInline" inline :label-width="120" :model="formInline" :rules="ruleInline">
|
<Form ref="formInline" inline :label-width="120" :model="formInline" :rules="ruleInline">
|
||||||
<FormItem prop="user" label="客户名称:">
|
<FormItem prop="user" label="搜索内容:">
|
||||||
<Input type="text" v-model="formInline.user" placeholder="" />
|
<Input type="text" clearable v-model="formInline.user" placeholder="用户手机号,用户openid" />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
||||||
@@ -11,17 +11,18 @@
|
|||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
<div class="action-btn">
|
<div class="action-btn">
|
||||||
<Button type="primary" @click="show_modal = true">添加</Button>
|
<!-- <Button type="primary" @click="show_modal = true">添加</Button> -->
|
||||||
<!-- <Button type="error">删除</Button> -->
|
<!-- <Button type="error">删除</Button> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<Table border :columns="columns" stripe :height="tableHeight" :data="data">
|
<Table border :columns="columns" stripe :height="tableHeight" :data="data">
|
||||||
<template #action="{ row, index }">
|
<template #action="{ row, index }">
|
||||||
<Button type="primary" size="small" style="margin-right: 5px" @click="show(index)">编辑</Button>
|
<Button type="primary" size="small" style="margin-right: 5px"
|
||||||
<Button type="error" size="small" @click="remove(index)">删除</Button>
|
@click="moneyLog(row.openid)">查看消费记录</Button>
|
||||||
</template>
|
</template>
|
||||||
</Table>
|
</Table>
|
||||||
<Page :total="total" show-total show-sizer class="page" />
|
<Page :total="total" show-total show-sizer class="page" @on-change="onChangePage"
|
||||||
|
@on-page-size-change="onChangePageSize" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@@ -77,17 +78,32 @@
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
<!-- 查看余额记录 -->
|
||||||
|
<Drawer title="余额记录" :closable="false" v-model="show_money_log" width="800">
|
||||||
|
<Table border :columns="show_money_columns" stripe :height="log_tableHeight" :data="show_money_data">
|
||||||
|
</Table>
|
||||||
|
|
||||||
|
<Page :total="show_money_total" show-total show-sizer class="page" @on-change="onChangeLogPage"
|
||||||
|
@on-page-size-change="onChangeLogPageSize" />
|
||||||
|
</Drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { GetUser } from '@/api'
|
import {
|
||||||
|
GetUser,
|
||||||
|
getUserMoneyLog,
|
||||||
|
} from '@/api'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'charging_station',
|
name: 'charging_station',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
show_money_log: false,
|
||||||
show_modal: false,
|
show_modal: false,
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
total: 100,
|
total: 100,
|
||||||
tableHeight: 500,
|
tableHeight: 500,
|
||||||
formInline: {
|
formInline: {
|
||||||
@@ -95,12 +111,7 @@ export default {
|
|||||||
password: '',
|
password: '',
|
||||||
},
|
},
|
||||||
ruleInline: {},
|
ruleInline: {},
|
||||||
columns: [
|
columns: [{
|
||||||
{
|
|
||||||
title: '区域',
|
|
||||||
key: 'area',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '用户名称',
|
title: '用户名称',
|
||||||
key: 'username',
|
key: 'username',
|
||||||
},
|
},
|
||||||
@@ -117,8 +128,12 @@ export default {
|
|||||||
key: 'account',
|
key: 'account',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '冻结余额',
|
title: '创建时间',
|
||||||
key: 'FrozenAccount',
|
key: 'createtime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '上一次登录时间',
|
||||||
|
key: 'logintime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
@@ -130,43 +145,44 @@ export default {
|
|||||||
data: [],
|
data: [],
|
||||||
formValidate: {
|
formValidate: {
|
||||||
name: '',
|
name: '',
|
||||||
mail: '',
|
|
||||||
city: '',
|
|
||||||
gender: '',
|
|
||||||
interest: [],
|
|
||||||
date: '',
|
|
||||||
time: '',
|
|
||||||
desc: '',
|
|
||||||
},
|
},
|
||||||
ruleValidate: {
|
ruleValidate: {
|
||||||
name: [
|
name: [{
|
||||||
{ required: true, message: 'The name cannot be empty', trigger: 'blur' },
|
required: true,
|
||||||
],
|
message: 'The name cannot be empty',
|
||||||
mail: [
|
trigger: 'blur',
|
||||||
{ required: true, message: 'Mailbox cannot be empty', trigger: 'blur' },
|
}],
|
||||||
{ type: 'email', message: 'Incorrect email format', trigger: 'blur' },
|
|
||||||
],
|
|
||||||
city: [
|
|
||||||
{ required: true, message: 'Please select the city', trigger: 'change' },
|
|
||||||
],
|
|
||||||
gender: [
|
|
||||||
{ required: true, message: 'Please select gender', trigger: 'change' },
|
|
||||||
],
|
|
||||||
interest: [
|
|
||||||
{ required: true, type: 'array', min: 1, message: 'Choose at least one hobby', trigger: 'change' },
|
|
||||||
{ type: 'array', max: 2, message: 'Choose two hobbies at best', trigger: 'change' },
|
|
||||||
],
|
|
||||||
date: [
|
|
||||||
{ required: true, type: 'date', message: 'Please select the date', trigger: 'change' },
|
|
||||||
],
|
|
||||||
time: [
|
|
||||||
{ required: true, type: 'string', message: 'Please select time', trigger: 'change' },
|
|
||||||
],
|
|
||||||
desc: [
|
|
||||||
{ required: true, message: 'Please enter a personal introduction', trigger: 'blur' },
|
|
||||||
{ type: 'string', min: 20, message: 'Introduce no less than 20 words', trigger: 'blur' },
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
|
log_page: 1,
|
||||||
|
log_pageSize: 10,
|
||||||
|
show_money_total: 100,
|
||||||
|
log_tableHeight: 500,
|
||||||
|
show_money_data: [],
|
||||||
|
show_money_columns: [{
|
||||||
|
title: 'openid',
|
||||||
|
key: 'openid',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '金额',
|
||||||
|
key: 'money',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '变化前',
|
||||||
|
key: 'before',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '变化后',
|
||||||
|
key: 'after',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '描述',
|
||||||
|
key: 'mark',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
key: 'createtime',
|
||||||
|
},
|
||||||
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -187,20 +203,18 @@ export default {
|
|||||||
this.tableHeight = window.innerHeight - actionBtnHeight - searchHeight - pageHeight - margins - 130
|
this.tableHeight = window.innerHeight - actionBtnHeight - searchHeight - pageHeight - margins - 130
|
||||||
},
|
},
|
||||||
async getList() {
|
async getList() {
|
||||||
await GetUser({ type: '', page: 1 }).then((res) => {
|
await GetUser({
|
||||||
|
type: '',
|
||||||
|
page: this.page,
|
||||||
|
pageSize: this.pageSize,
|
||||||
|
...this.formInline,
|
||||||
|
}).then((res) => {
|
||||||
this.total = res.total
|
this.total = res.total
|
||||||
this.data = res.data
|
this.data = res.data
|
||||||
this.page = res.current_page
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleSubmit(name) {
|
handleSubmit() {
|
||||||
this.$refs[name].validate((valid) => {
|
this.getList()
|
||||||
if (valid) {
|
|
||||||
this.$Message.success('Success!')
|
|
||||||
} else {
|
|
||||||
this.$Message.error('Fail!')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
handleReset(name) {
|
handleReset(name) {
|
||||||
this.$refs[name].resetFields()
|
this.$refs[name].resetFields()
|
||||||
@@ -229,19 +243,61 @@ export default {
|
|||||||
cancel() {
|
cancel() {
|
||||||
this.$Message.info('Clicked cancel')
|
this.$Message.info('Clicked cancel')
|
||||||
},
|
},
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onChangeLogPage(e) {
|
||||||
|
if (this.log_page != e) {
|
||||||
|
this.log_page = e
|
||||||
|
this.getUserMoneyLog()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onChangeLogPageSize(e) {
|
||||||
|
if (this.log_pageSize != e) {
|
||||||
|
this.log_page = 1
|
||||||
|
this.log_pageSize = e
|
||||||
|
this.getUserMoneyLog()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
moneyLog(openid) {
|
||||||
|
this.show_money_log = true
|
||||||
|
// 获取余额使用记录
|
||||||
|
this.openid = openid
|
||||||
|
this.getUserMoneyLog()
|
||||||
|
},
|
||||||
|
async getUserMoneyLog(openid) {
|
||||||
|
await getUserMoneyLog({
|
||||||
|
openid: this.openid,
|
||||||
|
page: this.log_page,
|
||||||
|
pageSize: this.log_pageSize,
|
||||||
|
}).then((res) => {
|
||||||
|
this.show_money_data = res.data.data
|
||||||
|
this.show_money_total = res.data.total
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.container {
|
.container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn {
|
.action-btn {
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
@@ -249,25 +305,27 @@ export default {
|
|||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-container {
|
.table-container {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
.search-area{
|
|
||||||
|
.search-area {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
border: 1px solid #F3F7FD;
|
border: 1px solid #F3F7FD;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -1,27 +1,59 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="search-area">
|
<div class="search-area">
|
||||||
<Form ref="formInline" :model="formInline" :rules="ruleInline" inline :label-width="120">
|
<Form ref="formInline" :model="formInline" inline :label-width="120">
|
||||||
<FormItem prop="user" label="时间">
|
<FormItem prop="user" label="时间">
|
||||||
<Input type="text" v-model="formInline.user" placeholder="Username"></Input>
|
<Select v-model="formInline.time_type" clearable style="width:200px">
|
||||||
</FormItem>
|
<Option :value="1">天</Option>
|
||||||
<FormItem prop="password" label="充电桩">
|
<Option :value="4">周</Option>
|
||||||
<Input type="password" v-model="formInline.password" placeholder="Password"></Input>
|
<Option :value="2">月</Option>
|
||||||
|
<Option :value="3">年</Option>
|
||||||
|
<Option :value="5">自定义</Option>
|
||||||
|
</Select>
|
||||||
|
<DatePicker v-if="formInline.time_type == 1" :value="formInline.time" type="date"
|
||||||
|
placeholder="请选择日期" style="width: 200px" @on-change="chage" />
|
||||||
|
<DatePicker v-if="formInline.time_type == 2" type="month" placeholder="请选择日期" style="width: 200px"
|
||||||
|
@on-change="chage" />
|
||||||
|
<DatePicker v-if="formInline.time_type == 3" type="year" placeholder="请选择日期" style="width: 200px"
|
||||||
|
@on-change="chage" />
|
||||||
|
<DatePicker v-if="formInline.time_type == 4" type="daterange" show-week-numbers
|
||||||
|
placement="bottom-end" placeholder="请选择日期" style="width: 200px" @on-change="chage" />
|
||||||
|
<DatePicker v-if="formInline.time_type == 5" type="daterange" placement="bottom-end"
|
||||||
|
placeholder="请选择日期" style="width: 200px" @on-change="chage" />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem prop="password" label="充电站">
|
<FormItem prop="password" label="充电站">
|
||||||
<Input type="password" v-model="formInline.password" placeholder="Password"></Input>
|
<Select v-model="formInline.charge_station_id" style="width:200px" clearable @on-change="changeStation">
|
||||||
|
<Option v-for="item in stationList" :value="item.charge_station_id"
|
||||||
|
:key="item.charge_station_id">{{ item.charge_station_name }}</Option>
|
||||||
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem prop="password" label="充电桩">
|
||||||
|
<Select v-model="formInline.connectorID" style="width:200px" clearable>
|
||||||
|
<Option v-for="item in pileList" :value="item.ConnectorID" :key="item.charge_pile_id">
|
||||||
|
{{ item.ConnectorID }}
|
||||||
|
</Option>
|
||||||
|
</Select>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<div>总订单数:{{ total_order_num }}</div>
|
||||||
|
<div>总收入:{{ total_order_money }}</div>
|
||||||
|
</div>
|
||||||
<div id="main" ref="chartContainer" style="width: 100%; height: 400px;"></div>
|
<div id="main" ref="chartContainer" style="width: 100%; height: 400px;"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
|
import {
|
||||||
|
orderTotal,
|
||||||
|
getStationList,
|
||||||
|
getPileList,
|
||||||
|
} from '@/api'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Total',
|
name: 'Total',
|
||||||
@@ -30,13 +62,21 @@
|
|||||||
data: [],
|
data: [],
|
||||||
chartInstance: null,
|
chartInstance: null,
|
||||||
formInline: {
|
formInline: {
|
||||||
user: '',
|
charge_station_id: '',
|
||||||
password: '',
|
time_type: 1,
|
||||||
|
connectorID: '',
|
||||||
|
time: '',
|
||||||
},
|
},
|
||||||
|
stationList: [],
|
||||||
|
pileList: [],
|
||||||
|
total_order_num: 0,
|
||||||
|
total_order_money: '0.00',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initChart()
|
this.initChart()
|
||||||
|
this.getStationList()
|
||||||
|
this.getPileList()
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
if (this.chartInstance) {
|
if (this.chartInstance) {
|
||||||
@@ -45,7 +85,7 @@
|
|||||||
window.removeEventListener('resize', this.handleResize)
|
window.removeEventListener('resize', this.handleResize)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initChart() {
|
async initChart() {
|
||||||
if (!this.$refs.chartContainer) return
|
if (!this.$refs.chartContainer) return
|
||||||
|
|
||||||
// 销毁旧实例
|
// 销毁旧实例
|
||||||
@@ -53,12 +93,25 @@
|
|||||||
this.chartInstance.dispose()
|
this.chartInstance.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.formInline.time = new Date().toLocaleDateString().replace('///g', '-')
|
||||||
this.chartInstance = echarts.init(this.$refs.chartContainer)
|
this.chartInstance = echarts.init(this.$refs.chartContainer)
|
||||||
|
|
||||||
// 模拟数据
|
const xData = []
|
||||||
const xData = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
const orderData = []
|
||||||
const orderData = [120, 132, 101, 134, 90, 230, 210]
|
const revenueData = []
|
||||||
const revenueData = [220, 182, 191, 234, 290, 330, 310]
|
|
||||||
|
await orderTotal({
|
||||||
|
...this.formInline,
|
||||||
|
}).then((res) => {
|
||||||
|
this.total_order_num = res.summary.total_count
|
||||||
|
this.total_order_money = res.summary.total_money
|
||||||
|
this.$nextTick()
|
||||||
|
res.data.forEach((i) => {
|
||||||
|
xData.push(i.value)
|
||||||
|
orderData.push(i.count)
|
||||||
|
revenueData.push(i.total_money)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
const option = {
|
const option = {
|
||||||
title: {
|
title: {
|
||||||
@@ -118,6 +171,40 @@
|
|||||||
this.chartInstance.resize()
|
this.chartInstance.resize()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async getStationList() {
|
||||||
|
await getStationList({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 999,
|
||||||
|
}).then((res) => {
|
||||||
|
this.stationList = res.data.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async getPileList() {
|
||||||
|
await getPileList({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 999,
|
||||||
|
charge_station_id: this.formInline.charge_station_id,
|
||||||
|
}).then((res) => {
|
||||||
|
this.pileList = res.data.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
chage(e) {
|
||||||
|
this.formInline.time = ''
|
||||||
|
this.formInline.start_time = ''
|
||||||
|
this.formInline.end_time = ''
|
||||||
|
if (this.formInline.time_type == 4 || this.formInline.time_type == 5) {
|
||||||
|
this.formInline.start_time = e[0]
|
||||||
|
this.formInline.end_time = e[1]
|
||||||
|
} else {
|
||||||
|
this.formInline.time = e
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSubmit() {
|
||||||
|
this.initChart()
|
||||||
|
},
|
||||||
|
changeStation(e) {
|
||||||
|
this.getPileList()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -54,11 +54,11 @@
|
|||||||
key: 'openid',
|
key: 'openid',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '充值金额',
|
title: '充值金额(元)',
|
||||||
key: 'total',
|
key: 'total',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '已用金额',
|
title: '已用金额(分)',
|
||||||
key: 'total_used',
|
key: 'total_used',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,124 +1,160 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="search-area">
|
<div class="search-area">
|
||||||
<Form ref="formInline" inline :label-width="120" :model="formInline" :rules="ruleInline">
|
<Form ref="searchForm" inline :label-width="100" :model="formInline">
|
||||||
<FormItem prop="user" label="用户名:">
|
<FormItem prop="username" label="用户名:">
|
||||||
<Input type="text" v-model="formInline.user" placeholder="" />
|
<Input
|
||||||
|
v-model="formInline.username"
|
||||||
|
clearable
|
||||||
|
placeholder="请输入用户名"
|
||||||
|
@on-enter="handleSubmit"
|
||||||
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
<Button type="primary" @click="handleSubmit">搜索</Button>
|
||||||
|
<Button style="margin-left: 8px" @click="resetSearch">重置</Button>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
<div class="action-btn">
|
<div class="action-btn">
|
||||||
<Button type="primary" @click="show_modal = true">添加</Button>
|
<Button type="primary" @click="handleAdd">添加用户</Button>
|
||||||
<!-- <Button type="error">删除</Button> -->
|
|
||||||
</div>
|
</div>
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<Table border :columns="columns" stripe :height="tableHeight" :data="data">
|
<Table
|
||||||
<template #action="{ row, index }">
|
border
|
||||||
<Button type="primary" size="small" style="margin-right: 5px" @click="show(index)">编辑</Button>
|
stripe
|
||||||
<Button type="error" size="small" @click="remove(index)">删除</Button>
|
:loading="tableLoading"
|
||||||
|
:columns="columns"
|
||||||
|
:height="tableHeight"
|
||||||
|
:data="data"
|
||||||
|
>
|
||||||
|
<template #roles="{ row }">
|
||||||
|
<span>{{ formatRoleLabel(row.roles) }}</span>
|
||||||
|
</template>
|
||||||
|
<template #action="{ row }">
|
||||||
|
<Button type="primary" size="small" style="margin-right: 5px" @click="handleEdit(row.id)">编辑</Button>
|
||||||
|
<Button type="error" size="small" @click="handleRemove(row.id)">删除</Button>
|
||||||
</template>
|
</template>
|
||||||
</Table>
|
</Table>
|
||||||
<Page :total="total" show-total show-sizer class="page" />
|
<Page
|
||||||
|
:current="page"
|
||||||
|
:page-size="pageSize"
|
||||||
|
:total="total"
|
||||||
|
show-total
|
||||||
|
show-sizer
|
||||||
|
show-elevator
|
||||||
|
class="page"
|
||||||
|
@on-change="onChangePage"
|
||||||
|
@on-page-size-change="onChangePageSize"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Modal
|
||||||
<!-- 添加、编辑 -->
|
v-model="showModal"
|
||||||
<Modal v-model="show_modal" title="Common Modal dialog box title" :mask-closable="false" @on-ok="ok"
|
:title="modalTitle"
|
||||||
@on-cancel="cancel">
|
:mask-closable="false"
|
||||||
<Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="80">
|
@on-cancel="cancel"
|
||||||
<FormItem label="Name" prop="name">
|
>
|
||||||
<Input v-model="formValidate.name" placeholder="Enter your name" />
|
<Form ref="formValidate" :model="formValidate" :rules="formRules" :label-width="100">
|
||||||
|
<FormItem label="用户名" prop="username" :required="true">
|
||||||
|
<Input v-model="formValidate.username" placeholder="请输入用户名" />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label="E-mail" prop="mail">
|
<FormItem label="姓名" prop="nickname" :required="true">
|
||||||
<Input v-model="formValidate.mail" placeholder="Enter your e-mail" />
|
<Input v-model="formValidate.nickname" placeholder="请输入姓名" />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label="City" prop="city">
|
<FormItem label="登录密码" prop="password" :required="!isEdit">
|
||||||
<Select v-model="formValidate.city" placeholder="Select your city">
|
<Input
|
||||||
<Option value="beijing">New York</Option>
|
type="password"
|
||||||
<Option value="shanghai">London</Option>
|
password
|
||||||
<Option value="shenzhen">Sydney</Option>
|
v-model="formValidate.password"
|
||||||
|
:placeholder="isEdit ? '不修改可留空' : '请输入登录密码'"
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="手机号" prop="phone" :required="true">
|
||||||
|
<Input v-model="formValidate.phone" placeholder="请输入11位手机号" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="邮箱" prop="email">
|
||||||
|
<Input v-model="formValidate.email" placeholder="选填,需符合邮箱格式" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="角色" prop="roles" :required="true">
|
||||||
|
<Select v-model="formValidate.roles" placeholder="请选择角色">
|
||||||
|
<Option v-for="item in roleOptions" :value="item.id" :key="item.id">{{ item.name }}</Option>
|
||||||
</Select>
|
</Select>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label="Date">
|
|
||||||
<Row>
|
|
||||||
<Col span="11">
|
|
||||||
<DatePicker type="date" placeholder="Select date" v-model="formValidate.date"></DatePicker>
|
|
||||||
</Col>
|
|
||||||
<Col span="2" style="text-align: center">-</Col>
|
|
||||||
<Col span="11">
|
|
||||||
<TimePicker type="time" placeholder="Select time" v-model="formValidate.time"></TimePicker>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</FormItem>
|
|
||||||
<FormItem label="Gender" prop="gender">
|
|
||||||
<RadioGroup v-model="formValidate.gender">
|
|
||||||
<Radio label="male">Male</Radio>
|
|
||||||
<Radio label="female">Female</Radio>
|
|
||||||
</RadioGroup>
|
|
||||||
</FormItem>
|
|
||||||
<FormItem label="Hobby" prop="interest">
|
|
||||||
<CheckboxGroup v-model="formValidate.interest">
|
|
||||||
<Checkbox label="Eat"></Checkbox>
|
|
||||||
<Checkbox label="Sleep"></Checkbox>
|
|
||||||
<Checkbox label="Run"></Checkbox>
|
|
||||||
<Checkbox label="Movie"></Checkbox>
|
|
||||||
</CheckboxGroup>
|
|
||||||
</FormItem>
|
|
||||||
<FormItem label="Desc" prop="desc">
|
|
||||||
<Input v-model="formValidate.desc" type="textarea" :autosize="{ minRows: 2, maxRows: 5 }"
|
|
||||||
placeholder="Enter something..." />
|
|
||||||
</FormItem>
|
|
||||||
<FormItem>
|
|
||||||
<Button type="primary" @click="handleSubmit2('formValidate')">Submit</Button>
|
|
||||||
<Button @click="handleReset('formValidate')" style="margin-left: 8px">Reset</Button>
|
|
||||||
</FormItem>
|
|
||||||
</Form>
|
</Form>
|
||||||
|
<div slot="footer">
|
||||||
|
<Button type="text" @click="cancel">取消</Button>
|
||||||
|
<Button type="primary" :loading="submitLoading" @click="ok">确定</Button>
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { GetAdmin } from '@/api'
|
import {
|
||||||
|
getAdminList,
|
||||||
|
addAdmin,
|
||||||
|
getAdmin,
|
||||||
|
getAdminUpdate,
|
||||||
|
getAdminDelete,
|
||||||
|
getRoleList,
|
||||||
|
} from '@/api'
|
||||||
|
|
||||||
|
const createDefaultForm = () => ({
|
||||||
|
id: '',
|
||||||
|
username: '',
|
||||||
|
nickname: '',
|
||||||
|
password: '',
|
||||||
|
email: '',
|
||||||
|
phone: '',
|
||||||
|
roles: '',
|
||||||
|
})
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'charging_station',
|
name: 'system_admin',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
show_modal: false,
|
showModal: false,
|
||||||
total: 100,
|
|
||||||
tableHeight: 500,
|
tableHeight: 500,
|
||||||
|
tableLoading: false,
|
||||||
|
submitLoading: false,
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0,
|
||||||
formInline: {
|
formInline: {
|
||||||
user: '',
|
username: '',
|
||||||
password: '',
|
|
||||||
},
|
},
|
||||||
ruleInline: {},
|
// 表格列的结构描述,保持字段展示的一致性
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
title: 'ID',
|
title: 'ID',
|
||||||
key: 'id',
|
key: 'id',
|
||||||
|
minWidth: 80,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '用户名',
|
title: '用户名',
|
||||||
key: 'username',
|
key: 'username',
|
||||||
|
minWidth: 140,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '账号',
|
title: '姓名',
|
||||||
key: 'nickname',
|
key: 'nickname',
|
||||||
|
minWidth: 120,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '手机号',
|
title: '手机号',
|
||||||
key: 'phone',
|
key: 'phone',
|
||||||
|
minWidth: 140,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '岗位',
|
title: '邮箱',
|
||||||
key: 'position',
|
key: 'email',
|
||||||
|
minWidth: 180,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '角色名',
|
title: '角色',
|
||||||
key: 'roles',
|
slot: 'roles',
|
||||||
|
minWidth: 120,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
@@ -127,50 +163,44 @@ export default {
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
data: [],
|
data: [], // 系统用户表格数据
|
||||||
formValidate: {
|
roleOptions: [], // 角色下拉选项
|
||||||
name: '',
|
formValidate: createDefaultForm(), // 弹窗表单数据
|
||||||
mail: '',
|
|
||||||
city: '',
|
|
||||||
gender: '',
|
|
||||||
interest: [],
|
|
||||||
date: '',
|
|
||||||
time: '',
|
|
||||||
desc: '',
|
|
||||||
},
|
|
||||||
ruleValidate: {
|
|
||||||
name: [
|
|
||||||
{ required: true, message: 'The name cannot be empty', trigger: 'blur' },
|
|
||||||
],
|
|
||||||
mail: [
|
|
||||||
{ required: true, message: 'Mailbox cannot be empty', trigger: 'blur' },
|
|
||||||
{ type: 'email', message: 'Incorrect email format', trigger: 'blur' },
|
|
||||||
],
|
|
||||||
city: [
|
|
||||||
{ required: true, message: 'Please select the city', trigger: 'change' },
|
|
||||||
],
|
|
||||||
gender: [
|
|
||||||
{ required: true, message: 'Please select gender', trigger: 'change' },
|
|
||||||
],
|
|
||||||
interest: [
|
|
||||||
{ required: true, type: 'array', min: 1, message: 'Choose at least one hobby', trigger: 'change' },
|
|
||||||
{ type: 'array', max: 2, message: 'Choose two hobbies at best', trigger: 'change' },
|
|
||||||
],
|
|
||||||
date: [
|
|
||||||
{ required: true, type: 'date', message: 'Please select the date', trigger: 'change' },
|
|
||||||
],
|
|
||||||
time: [
|
|
||||||
{ required: true, type: 'string', message: 'Please select time', trigger: 'change' },
|
|
||||||
],
|
|
||||||
desc: [
|
|
||||||
{ required: true, message: 'Please enter a personal introduction', trigger: 'blur' },
|
|
||||||
{ type: 'string', min: 20, message: 'Introduce no less than 20 words', trigger: 'blur' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
isEdit() {
|
||||||
|
return Boolean(this.formValidate.id)
|
||||||
|
},
|
||||||
|
modalTitle() {
|
||||||
|
return this.isEdit ? '编辑系统用户' : '新增系统用户'
|
||||||
|
},
|
||||||
|
formRules() {
|
||||||
|
return {
|
||||||
|
username: [
|
||||||
|
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||||
|
],
|
||||||
|
nickname: [
|
||||||
|
{ required: true, message: '请输入姓名', trigger: 'blur' },
|
||||||
|
],
|
||||||
|
password: [
|
||||||
|
{ validator: this.validatePassword, trigger: 'blur' },
|
||||||
|
],
|
||||||
|
phone: [
|
||||||
|
{ validator: this.validatePhone, trigger: 'blur' },
|
||||||
|
],
|
||||||
|
email: [
|
||||||
|
{ validator: this.validateEmail, trigger: 'blur' },
|
||||||
|
],
|
||||||
|
roles: [
|
||||||
|
{ validator: this.validateRoles, trigger: 'change' },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getList()
|
this.getList()
|
||||||
|
this.fetchRoles()
|
||||||
this.calculateTableHeight()
|
this.calculateTableHeight()
|
||||||
window.addEventListener('resize', this.calculateTableHeight)
|
window.addEventListener('resize', this.calculateTableHeight)
|
||||||
},
|
},
|
||||||
@@ -178,56 +208,217 @@ export default {
|
|||||||
window.removeEventListener('resize', this.calculateTableHeight)
|
window.removeEventListener('resize', this.calculateTableHeight)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 统一创建弹窗表单的初始值,方便新增/编辑时复用
|
||||||
|
getDefaultForm() {
|
||||||
|
return createDefaultForm()
|
||||||
|
},
|
||||||
calculateTableHeight() {
|
calculateTableHeight() {
|
||||||
// 计算表格高度 = 窗口高度 - 搜索区域高度 - 分页高度 - 其他间距
|
// 根据浏览器高度动态计算表格剩余空间,保证页面结构自适应
|
||||||
const searchHeight = document.querySelector('.search-area').offsetHeight
|
const searchArea = document.querySelector('.search-area')
|
||||||
const actionBtnHeight = document.querySelector('.action-btn').offsetHeight
|
const actionArea = document.querySelector('.action-btn')
|
||||||
const pageHeight = 32 // 分页组件大约高度
|
const searchHeight = searchArea ? searchArea.offsetHeight : 0
|
||||||
const margins = 40 // 上下边距总和
|
const actionHeight = actionArea ? actionArea.offsetHeight : 0
|
||||||
this.tableHeight = window.innerHeight - actionBtnHeight - searchHeight - pageHeight - margins - 130
|
const pageHeight = 70
|
||||||
|
const basePadding = 80
|
||||||
|
const height = window.innerHeight - searchHeight - actionHeight - pageHeight - basePadding
|
||||||
|
this.tableHeight = height > 320 ? height : 320
|
||||||
|
},
|
||||||
|
async fetchRoles() {
|
||||||
|
// 角色列表仅需偶尔变动,进入页面时加载一次即可
|
||||||
|
try {
|
||||||
|
const res = await getRoleList()
|
||||||
|
const list = res.data || res
|
||||||
|
this.roleOptions = Array.isArray(list) ? list : []
|
||||||
|
} catch (error) {
|
||||||
|
this.roleOptions = []
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async getList() {
|
async getList() {
|
||||||
await GetAdmin({ page: 1 }).then((res) => {
|
// 列表查询会根据分页与搜索条件拼接参数,接口结果兼容 data/list 两种结构
|
||||||
this.total = res.total
|
this.tableLoading = true
|
||||||
this.data = res.data
|
try {
|
||||||
this.page = res.current_page
|
const res = await getAdminList({
|
||||||
|
page: this.page,
|
||||||
|
pageSize: this.pageSize,
|
||||||
|
...this.formInline,
|
||||||
})
|
})
|
||||||
},
|
const responseData = res.data || {}
|
||||||
handleSubmit(name) {
|
const list = responseData.data || responseData.list || []
|
||||||
this.$refs[name].validate((valid) => {
|
this.data = Array.isArray(list) ? list : []
|
||||||
if (valid) {
|
this.total = typeof responseData.total === 'number' ? responseData.total : (res.total || 0)
|
||||||
this.$Message.success('Success!')
|
} finally {
|
||||||
} else {
|
this.tableLoading = false
|
||||||
this.$Message.error('Fail!')
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
},
|
},
|
||||||
handleReset(name) {
|
handleSubmit() {
|
||||||
this.$refs[name].resetFields()
|
this.page = 1
|
||||||
|
this.getList()
|
||||||
},
|
},
|
||||||
handleSubmit2(name) {
|
resetSearch() {
|
||||||
this.$refs[name].validate((valid) => {
|
this.formInline.username = ''
|
||||||
if (valid) {
|
this.handleSubmit()
|
||||||
this.$Message.success('Success!')
|
},
|
||||||
} else {
|
handleAdd() {
|
||||||
this.$Message.error('Fail!')
|
this.formValidate = this.getDefaultForm()
|
||||||
|
this.showModal = true
|
||||||
|
},
|
||||||
|
async handleEdit(id) {
|
||||||
|
// 编辑前需要获取详情,避免列表中数据字段不完整
|
||||||
|
try {
|
||||||
|
const res = await getAdmin({ id })
|
||||||
|
const detail = res.data || {}
|
||||||
|
this.formValidate = {
|
||||||
|
id: detail.id,
|
||||||
|
username: detail.username || '',
|
||||||
|
nickname: detail.nickname || '',
|
||||||
|
password: detail.password || '',
|
||||||
|
email: detail.email || '',
|
||||||
|
phone: detail.phone || '',
|
||||||
|
roles: detail.roles === 0 || detail.roles ? Number(detail.roles) : '',
|
||||||
}
|
}
|
||||||
|
this.showModal = true
|
||||||
|
} catch (error) {
|
||||||
|
this.$Message.error('获取用户信息失败')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async handleRemove(id) {
|
||||||
|
// 删除需二次确认,避免误操作
|
||||||
|
const confirm = await new Promise(resolve => {
|
||||||
|
this.$Modal.confirm({
|
||||||
|
title: '删除确认',
|
||||||
|
content: '删除后不可恢复,是否继续?',
|
||||||
|
onOk: () => resolve(true),
|
||||||
|
onCancel: () => resolve(false),
|
||||||
})
|
})
|
||||||
},
|
|
||||||
show(index) {
|
|
||||||
this.$Modal.info({
|
|
||||||
title: 'User Info',
|
|
||||||
content: `Name:${this.data[index].name}<br>Age:${this.data[index].age}<br>Address:${this.data[index].address}`,
|
|
||||||
})
|
})
|
||||||
|
if (!confirm) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await getAdminDelete({ id })
|
||||||
|
this.$Message.success('删除成功')
|
||||||
|
if (this.data.length === 1 && this.page > 1) {
|
||||||
|
this.page -= 1
|
||||||
|
}
|
||||||
|
this.getList()
|
||||||
|
} catch (error) {
|
||||||
|
this.$Message.error('删除失败,请稍后重试')
|
||||||
|
}
|
||||||
},
|
},
|
||||||
remove(index) {
|
validatePhone(rule, value, callback) {
|
||||||
this.data.splice(index, 1)
|
// 手机号验证:要求以 1 开头且总长 11 位,避免明显输入错误
|
||||||
|
const phonePattern = /^1[3-9]\d{9}$/
|
||||||
|
if (!value) {
|
||||||
|
callback(new Error('请输入手机号'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!phonePattern.test(value)) {
|
||||||
|
callback(new Error('手机号格式不正确'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
callback()
|
||||||
},
|
},
|
||||||
ok() {
|
validateEmail(rule, value, callback) {
|
||||||
this.$Message.info('Clicked ok')
|
// 邮箱验证:允许省略,填写时需符合基础格式,连字符放在末尾避免正则范围冲突
|
||||||
|
if (!value) {
|
||||||
|
callback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const emailPattern = /^[\w.-]+@[\w-]+(\.[\w-]+)+$/
|
||||||
|
if (!emailPattern.test(value)) {
|
||||||
|
callback(new Error('邮箱格式不正确'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
callback()
|
||||||
|
},
|
||||||
|
validatePassword(rule, value, callback) {
|
||||||
|
// 密码验证:编辑时可留空,新建或主动修改时必须至少 6 位
|
||||||
|
if (this.isEdit && !value) {
|
||||||
|
callback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!value) {
|
||||||
|
callback(new Error('请输入登录密码'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (value.length < 6) {
|
||||||
|
callback(new Error('密码至少6位'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
callback()
|
||||||
|
},
|
||||||
|
validateRoles(rule, value, callback) {
|
||||||
|
// 角色校验:接口允许 0 作为合法角色 ID,因此判空时需单独处理
|
||||||
|
if (value === 0 || value === '0') {
|
||||||
|
callback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!value) {
|
||||||
|
callback(new Error('请选择角色'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
callback()
|
||||||
|
},
|
||||||
|
formatRoleLabel(value) {
|
||||||
|
// 将角色 ID 转为人类可读名称,兼容数组或单个值
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.map(item => this.formatRoleLabel(item)).join('、')
|
||||||
|
}
|
||||||
|
const target = this.roleOptions.find(item => String(item.id) === String(value))
|
||||||
|
return target ? target.name : value || '--'
|
||||||
|
},
|
||||||
|
async ok() {
|
||||||
|
const valid = await new Promise(resolve => this.$refs.formValidate.validate(resolve))
|
||||||
|
if (!valid) {
|
||||||
|
this.$Message.error('请正确填写表单')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const payload = {
|
||||||
|
...this.formValidate,
|
||||||
|
}
|
||||||
|
if (this.isEdit) {
|
||||||
|
if (!payload.password) {
|
||||||
|
delete payload.password
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
delete payload.id
|
||||||
|
}
|
||||||
|
this.submitLoading = true
|
||||||
|
try {
|
||||||
|
if (this.isEdit) {
|
||||||
|
await getAdminUpdate(payload)
|
||||||
|
this.$Message.success('更新成功')
|
||||||
|
} else {
|
||||||
|
await addAdmin(payload)
|
||||||
|
this.$Message.success('新增成功')
|
||||||
|
}
|
||||||
|
this.cancel()
|
||||||
|
this.getList()
|
||||||
|
} finally {
|
||||||
|
this.submitLoading = false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
cancel() {
|
cancel() {
|
||||||
this.$Message.info('Clicked cancel')
|
this.showModal = false
|
||||||
|
this.formValidate = this.getDefaultForm()
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.formValidate) {
|
||||||
|
this.$refs.formValidate.resetFields()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onChangePage(page) {
|
||||||
|
if (this.page !== page) {
|
||||||
|
this.page = page
|
||||||
|
this.getList()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onChangePageSize(size) {
|
||||||
|
if (this.pageSize !== size) {
|
||||||
|
this.page = 1
|
||||||
|
this.pageSize = size
|
||||||
|
this.getList()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -249,9 +440,10 @@ export default {
|
|||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
button {
|
}
|
||||||
|
|
||||||
|
.action-btn button {
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-container {
|
.table-container {
|
||||||
@@ -264,9 +456,10 @@ export default {
|
|||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
.search-area{
|
|
||||||
|
.search-area {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
padding-top: 20px;
|
padding: 20px;
|
||||||
border: 1px solid #F3F7FD;
|
border: 1px solid #F3F7FD;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user