This commit is contained in:
MeSHard
2025-11-24 15:54:25 +08:00
parent 12fa604884
commit e72f6eb001
4 changed files with 365 additions and 4 deletions

View File

@@ -85,6 +85,14 @@ export const asyncRoutes = {
}, },
component: () => import('../views/customer_center/WxUser.vue'), component: () => import('../views/customer_center/WxUser.vue'),
}, },
user_car: {
path: 'user_car',
name: 'user_car',
meta: {
title: '车辆管理',
},
component: () => import('../views/customer_center/user_car.vue'),
},
// 运营中心 // 运营中心
activity: { activity: {
path: 'activity', path: 'activity',

View File

@@ -75,6 +75,7 @@ const store = new Vuex.Store({
{ {
size: 18, size: 18,
text: '车辆管理', text: '车辆管理',
name: 'user_car',
type: 'ios-paper', type: 'ios-paper',
}, },
], ],

View File

@@ -0,0 +1,331 @@
<template>
<div class="container">
<div class="search-area">
<Form ref="formInline" inline :label-width="120" :model="formInline" :rules="ruleInline">
<FormItem prop="user" label="搜索内容:">
<Input type="text" clearable v-model="formInline.user" placeholder="用户手机号用户openid" />
</FormItem>
<FormItem>
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
</FormItem>
</Form>
</div>
<div class="action-btn">
<!-- <Button type="primary" @click="show_modal = true">添加</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="moneyLog(row.openid)">查看消费记录</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="Common Modal dialog box title" :mask-closable="false" @on-ok="ok"
@on-cancel="cancel">
<Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="80">
<FormItem label="Name" prop="name">
<Input v-model="formValidate.name" placeholder="Enter your name" />
</FormItem>
<FormItem label="E-mail" prop="mail">
<Input v-model="formValidate.mail" placeholder="Enter your e-mail" />
</FormItem>
<FormItem label="City" prop="city">
<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>
</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>
</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>
</template>
<script>
import {
GetUser,
getUserMoneyLog,
} from '@/api'
export default {
name: 'charging_station',
data() {
return {
show_money_log: false,
show_modal: false,
page: 1,
pageSize: 10,
total: 100,
tableHeight: 500,
formInline: {
user: '',
password: '',
},
ruleInline: {},
columns: [{
title: '用户名称',
key: 'username',
},
{
title: 'openid',
key: 'openid',
},
{
title: '手机号',
key: 'phone',
},
{
title: '余额',
key: 'account',
},
{
title: '创建时间',
key: 'createtime',
},
{
title: '上一次登录时间',
key: 'logintime',
},
{
title: '操作',
slot: 'action',
width: 150,
align: 'center',
},
],
data: [],
formValidate: {
name: '',
},
ruleValidate: {
name: [{
required: true,
message: 'The name cannot be empty',
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() {
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 GetUser({
type: '',
page: this.page,
pageSize: this.pageSize,
...this.formInline,
}).then((res) => {
this.total = res.total
this.data = res.data
})
},
handleSubmit() {
this.getList()
},
handleReset(name) {
this.$refs[name].resetFields()
},
handleSubmit2(name) {
this.$refs[name].validate((valid) => {
if (valid) {
this.$Message.success('Success!')
} else {
this.$Message.error('Fail!')
}
})
},
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}`,
})
},
remove(index) {
this.data.splice(index, 1)
},
ok() {
this.$Message.info('Clicked ok')
},
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>
<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;
}
</style>

View File

@@ -3,7 +3,7 @@
<div class="search-area"> <div class="search-area">
<Form ref="formInline" :model="formInline" inline :label-width="120"> <Form ref="formInline" :model="formInline" inline :label-width="120">
<FormItem prop="user" label="时间"> <FormItem prop="user" label="时间">
<Select v-model="formInline.time_type" clearable style="width:200px"> <Select v-model="formInline.time_type" clearable style="width:100px">
<Option :value="1"></Option> <Option :value="1"></Option>
<Option :value="4"></Option> <Option :value="4"></Option>
<Option :value="2"></Option> <Option :value="2"></Option>
@@ -42,7 +42,7 @@
</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 class="table-container"> <div class="table-container">
<Table border :columns="columns" stripe :height="tableHeight" :data="data"> <Table border :columns="columns" :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" @click="show(index)">详情</Button> -->
</template> </template>
@@ -106,12 +106,15 @@
this.initChart() this.initChart()
this.getStationList() this.getStationList()
this.getPileList() this.getPileList()
this.calculateTableHeight()
window.addEventListener('resize', this.calculateTableHeight)
}, },
beforeDestroy() { beforeDestroy() {
if (this.chartInstance) { if (this.chartInstance) {
this.chartInstance.dispose() this.chartInstance.dispose()
} }
window.removeEventListener('resize', this.handleResize) window.removeEventListener('resize', this.handleResize)
window.removeEventListener('resize', this.calculateTableHeight)
}, },
methods: { methods: {
async initChart() { async initChart() {
@@ -248,7 +251,13 @@
// 响应式调整 // 响应式调整
window.addEventListener('resize', this.handleResize) window.addEventListener('resize', this.handleResize)
}, },
calculateTableHeight() {
// 计算表格高度 = 窗口高度 - 搜索区域高度 - 分页高度 - 其他间距
const searchHeight = document.querySelector('.search-area').offsetHeight
const pageHeight = 32 // 分页组件大约高度
const margins = 40 // 上下边距总和
this.tableHeight = window.innerHeight - searchHeight - pageHeight - margins - 230
},
handleResize() { handleResize() {
if (this.chartInstance) { if (this.chartInstance) {
this.chartInstance.resize() this.chartInstance.resize()
@@ -297,13 +306,25 @@
background: #fff; background: #fff;
border-radius: 8px; border-radius: 8px;
padding: 20px; padding: 20px;
margin: 20px; margin: 2px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
} }
.search-area { .search-area {
background-color: white; background-color: white;
border: 1px solid #F3F7FD; border: 1px solid #F3F7FD;
padding-top: 2px;
border-radius: 15px; border-radius: 15px;
} }
.table-container {
flex: 1;
display: flex;
flex-direction: column;
}
.page {
margin-top: 10px;
text-align: right;
}
</style> </style>