init
2
.browserslistrc
Normal file
@@ -0,0 +1,2 @@
|
||||
> 1%
|
||||
last 2 versions
|
||||
7
.editorconfig
Normal file
@@ -0,0 +1,7 @@
|
||||
[*.{js,jsx,ts,tsx,vue}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
max_line_length = 140
|
||||
67
.eslintrc.js
Normal file
@@ -0,0 +1,67 @@
|
||||
module.exports = {
|
||||
root: false,
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
extends: [
|
||||
'plugin:vue/essential',
|
||||
'@vue/airbnb',
|
||||
],
|
||||
rules: {
|
||||
'indent': 'off',
|
||||
'no-tabs': 'off', // 禁用 no-tabs 规则
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'array-element-newline': ['error', 'consistent'],
|
||||
// 'indent': ['error',4,{ 'MemberExpression': 0, 'SwitchCase': 1 }],
|
||||
'quotes': ['error', 'single'],
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
'semi': ['error', 'never'],
|
||||
'object-curly-spacing': ['error', 'always'],
|
||||
'max-len': ['error', 140],
|
||||
'no-new': 'off',
|
||||
'linebreak-style': 'off',
|
||||
'import/extensions': 'off',
|
||||
'eol-last': 'off',
|
||||
'no-shadow': 'off',
|
||||
'no-unused-vars': 'warn',
|
||||
'import/no-cycle': 'off',
|
||||
'arrow-parens': 'off',
|
||||
'eqeqeq': 'off',
|
||||
'no-param-reassign': 'off',
|
||||
'import/prefer-default-export': 'off',
|
||||
'no-use-before-define': 'off',
|
||||
'no-continue': 'off',
|
||||
'prefer-destructuring': 'off',
|
||||
'no-plusplus': 'off',
|
||||
'prefer-const': 'off',
|
||||
'global-require': 'off',
|
||||
'no-prototype-builtins': 'off',
|
||||
'consistent-return': 'off',
|
||||
'vue/require-component-is': 'off',
|
||||
'prefer-template': 'off',
|
||||
'one-var-declaration-per-line': 'off',
|
||||
'one-var': 'off',
|
||||
'import/named': 'off',
|
||||
'object-curly-newline': 'off',
|
||||
'default-case': 'off',
|
||||
'import/no-dynamic-require': 'off',
|
||||
'vue/no-parsing-error': [2, {
|
||||
'x-invalid-end-tag': false
|
||||
}],
|
||||
},
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint',
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: [
|
||||
'**/__tests__/*.{j,t}s?(x)',
|
||||
'**/tests/unit/**/*.spec.{j,t}s?(x)',
|
||||
],
|
||||
env: {
|
||||
jest: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
21
.gitignore
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 bin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
5
babel.config.js
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset',
|
||||
],
|
||||
};
|
||||
3
jest.config.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
preset: '@vue/cli-plugin-unit-jest',
|
||||
};
|
||||
39300
package-lock.json
generated
Normal file
34
package.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "vue-admin-template",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint",
|
||||
"test": "vue-cli-service test:unit"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.19.0",
|
||||
"core-js": "^3.31.0",
|
||||
"echarts": "^6.0.0",
|
||||
"element-ui": "^2.15.14",
|
||||
"view-design": "^4.0.2",
|
||||
"view-ui-plus": "^1.3.21",
|
||||
"vue": "^2.6.10",
|
||||
"vue-router": "^3.0.6",
|
||||
"vuex": "^3.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^4.1.0",
|
||||
"@vue/cli-plugin-eslint": "^4.1.0",
|
||||
"@vue/cli-plugin-unit-jest": "^4.1.0",
|
||||
"@vue/cli-service": "^4.1.0",
|
||||
"@vue/eslint-config-airbnb": "^4.0.0",
|
||||
"@vue/test-utils": "1.0.0-beta.29",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-plugin-vue": "^5.0.0",
|
||||
"vue-template-compiler": "^2.6.10"
|
||||
}
|
||||
}
|
||||
BIN
public/favicon.ico
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
17
public/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title>爱京科技</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but new doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
61
src/App.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view/>
|
||||
<div class="global-loading" v-show="isShowLoading">
|
||||
<Spin size="large"></Spin>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
data() {
|
||||
return {
|
||||
keepAliveData: ['manage'],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
'isShowLoading',
|
||||
]),
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Avenir', Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
li, ul, p, div, body, html, table {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html, body {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
li {
|
||||
list-style: none;
|
||||
}
|
||||
#app {
|
||||
height: 100%;
|
||||
}
|
||||
/* loading */
|
||||
.global-loading {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(255,255,255,.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
427
src/api/index.js
Normal file
@@ -0,0 +1,427 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function fetchUserData() {
|
||||
return request.get('https://api.github.com/users/woai3c')
|
||||
}
|
||||
|
||||
// 登录
|
||||
export function login(params) {
|
||||
return request.post('/login_check', params)
|
||||
}
|
||||
// 修改密码
|
||||
export function Modify(params) {
|
||||
return request.post('/admin/update_password', params)
|
||||
}
|
||||
// 显示通知
|
||||
export function showContent(params) {
|
||||
return request.post('/user/DiscountInfo', params)
|
||||
}
|
||||
// 修改通知
|
||||
export function EditContent(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) {
|
||||
return request.post('/admin/admin_all', params)
|
||||
}
|
||||
// 用户权限修改
|
||||
export function PermissUpdate(params) {
|
||||
return request.post('/UpdatePermission', params)
|
||||
}
|
||||
// 用户权限读取
|
||||
export function PermissRead(params) {
|
||||
return request.post('/UpdatePermission', params)
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单
|
||||
*/
|
||||
// 潜江-------获取充电订单数据
|
||||
export function getChargeOrder(params) {
|
||||
return request.get('/getChargeOrder', { params })
|
||||
}
|
||||
// 潜江-------获取充值订单数据
|
||||
export function getReChargeOrder(params) {
|
||||
return request.get('/getRechargeOrder', { params })
|
||||
}
|
||||
// 获取订单信息
|
||||
export function GetOrder(params) {
|
||||
return request.post('/ChargeOrder/read_order', params)
|
||||
}
|
||||
// 获取大足地址信息
|
||||
export function GetpositionData(params) {
|
||||
return request.post('/ChargeOrder/StreetWithName', params)
|
||||
}
|
||||
// 订单号查询订单
|
||||
export function GetOneOrder(params) {
|
||||
return request.post('/ChargeOrder/read_order', params)
|
||||
}
|
||||
// 获取充电桩信息
|
||||
export function GetChargeZ(params) {
|
||||
return request.post('/ChargeOrder/read_equipment', params)
|
||||
}
|
||||
// 获取总量
|
||||
export function GetTotal(params) {
|
||||
return request.post('/ChargeOrder/read_total', params)
|
||||
}
|
||||
// 按照时间查询
|
||||
export function GetTimeData(params) {
|
||||
return request.post('/ChargeStation/Time_Data', params)
|
||||
}
|
||||
// 充值按照时间查询
|
||||
export function ReGetTimeData(params) {
|
||||
return request.post('/ChargeStation/Recharge_Total', params)
|
||||
}
|
||||
// 导出充电站信息
|
||||
export function exportstationAll(params) {
|
||||
return request.post('/ChargeStation/station_all', params)
|
||||
}
|
||||
// 导出订单
|
||||
export function exportOrderAll(params) {
|
||||
return request.post('/OrderExport', params)
|
||||
}
|
||||
// 导出充值
|
||||
export function exportRecharge(params) {
|
||||
return request.post('/RechargeAllExport', params)
|
||||
}
|
||||
// 按照范围查询
|
||||
export function GetDatabyRound(params) {
|
||||
return request.post('/ChargeStation/Order_Total', params)
|
||||
}
|
||||
// 按照范围查询
|
||||
export function GetTotalround(params) {
|
||||
return request.post('/ChargeStation/Time_Data_Total', params)
|
||||
}
|
||||
// 充值记录
|
||||
export function GetRecharge(params) {
|
||||
return request.post('/RechargeAll', params)
|
||||
}
|
||||
// 订单模糊查询
|
||||
export function GetFuzzyOrder(params) {
|
||||
return request.post('/FuzzyOrder', params)
|
||||
}
|
||||
// 订单模糊查询2
|
||||
export function GetFuzzyOrder1(params) {
|
||||
return request.post('/FuzzyOrder', params)
|
||||
}
|
||||
// 订单查询
|
||||
export function GettheOrder(params) {
|
||||
return request.post('/FuzzyOrder', params)
|
||||
}
|
||||
// /尖峰
|
||||
export function Electricity(params) {
|
||||
return request.post('/Electricity', params)
|
||||
}
|
||||
// /尖峰
|
||||
export function ElectricityStation(params) {
|
||||
return request.post('/Electricity', params)
|
||||
}
|
||||
export function FindRechargeOrder(params) {
|
||||
return request.post('/FindRechargeOrder', params)
|
||||
}
|
||||
export function RefundQuery(params) {
|
||||
return request.post('/RefundQuery', params)
|
||||
}
|
||||
export function RefundQuery1(params) {
|
||||
return request.post('/RefundQuery', params)
|
||||
}
|
||||
// 退款可视化
|
||||
export function RefundTotal(params) {
|
||||
return request.post('/Refund_Total', params)
|
||||
}
|
||||
// 收支报表
|
||||
export function AmountExcel(params) {
|
||||
return request.post('/AmountExcel', params)
|
||||
}
|
||||
/**
|
||||
* 车辆
|
||||
*/
|
||||
// 公交车报表
|
||||
export function SearchBusMessage(params) {
|
||||
return request.post('/Bus/BusOrderPark', params)
|
||||
}
|
||||
// 公交车总报表
|
||||
export function SearchtotalBusMessage(params) {
|
||||
return request.post('/Bus/SearchMessage', params)
|
||||
}
|
||||
// 公交车报表单个
|
||||
export function SearchperBusMessage(params) {
|
||||
return request.post('/Bus/SearchMessage', params)
|
||||
}
|
||||
// 公交车更新余额
|
||||
export function ChangeSpecialUserBalance(params) {
|
||||
return request.post('/Bus/ChangeSpecialUserBalance', params)
|
||||
}
|
||||
// 公交车汇总表
|
||||
export function BusDataStatistics(params) {
|
||||
return request.post('/Bus/DataStatistics', params)
|
||||
}
|
||||
// 展示VIN和车牌号
|
||||
export function ShowVinLicense(params) {
|
||||
return request.post('/Bus/ShowVinLicense', params)
|
||||
}
|
||||
export function ShowVinLicense1(params) {
|
||||
return request.post('/Bus/ShowVinLicense', params)
|
||||
}
|
||||
// 绑定车辆和车牌号
|
||||
export function AddVinLicense(params) {
|
||||
return request.post('/Bus/AddVinLicense', params)
|
||||
}
|
||||
// 删除车辆和车牌号
|
||||
export function DeleteVinLicense(params) {
|
||||
return request.post('/Bus/DeleteVinLicense', params)
|
||||
}
|
||||
// 编辑车辆信息
|
||||
export function UpdateVinLicense(params) {
|
||||
return request.post('/Bus/UpdateVinLicense', params)
|
||||
}
|
||||
// 车辆列表
|
||||
export function ParkNoShow(params) {
|
||||
return request.post('/Bus/ParkNo', params)
|
||||
}
|
||||
/**
|
||||
* event
|
||||
*/
|
||||
// 活动列表
|
||||
export function ShowEvent(params) {
|
||||
return request.post('/ShowEvent', params)
|
||||
}
|
||||
// 新增列表
|
||||
export function AddEvent(params) {
|
||||
return request.post('/AddEvent', params)
|
||||
}
|
||||
// 编辑列表
|
||||
export function EditEvent(params) {
|
||||
return request.post('/EditEvent', params)
|
||||
}
|
||||
// 删除列表
|
||||
export function DeleteEvent(params) {
|
||||
return request.post('/DeleteEvent', params)
|
||||
}
|
||||
// 监控列表
|
||||
export function MonitorList(params) {
|
||||
return request.post('/MonitorList', params)
|
||||
}
|
||||
// 查询监控
|
||||
export function ParkNoShowEvent(params) {
|
||||
return request.post('/MonitorId', params)
|
||||
}
|
||||
/**
|
||||
* position
|
||||
*/
|
||||
// 获取位置信息
|
||||
export function GetPosition(params) {
|
||||
return request.post('/ChargeStation/index', params)
|
||||
}
|
||||
// 搜索充电站
|
||||
export function searchStation(params) {
|
||||
return request.post('/ChargeStation/index', params)
|
||||
}
|
||||
// 修改定价
|
||||
export function ChangeCharge(params) {
|
||||
return request.post('/StationPriceUpdate', params)
|
||||
}
|
||||
// 导出
|
||||
export function exportAll(params) {
|
||||
return request.post('/ChargeStation/station_all', params)
|
||||
}
|
||||
// 故障
|
||||
export function Getwarning(params) {
|
||||
return request.post('/ChargeStation/FaultInfo', params)
|
||||
}
|
||||
// 获取电站价格
|
||||
export function GetPerPrice(params) {
|
||||
return request.post('/StationPrice', params)
|
||||
}
|
||||
/**
|
||||
* table
|
||||
*/
|
||||
// 用户列表
|
||||
export function GetUser(params) {
|
||||
return request.post('/UserList', params)
|
||||
}
|
||||
// 查询用户
|
||||
export function searchUser(params) {
|
||||
return request.post('/user/read', params)
|
||||
}
|
||||
// 编辑用户
|
||||
export function editUser(params) {
|
||||
return request.post('/user/update', params)
|
||||
}
|
||||
// 用户删除
|
||||
export function deleteUser(params) {
|
||||
return request.post('/DeleteEnterpriseUser', params)
|
||||
}
|
||||
// 导出
|
||||
export function exportUserAll(params) {
|
||||
return request.post('/user/user_all', params)
|
||||
}
|
||||
// 查订单
|
||||
export function OrderQuery(params) {
|
||||
return request.post('/OrderQuery', params)
|
||||
}
|
||||
// 获取企业用户组
|
||||
export function GetGroup(params) {
|
||||
return request.post('/GetGroup', params)
|
||||
}
|
||||
// 获取企业列表
|
||||
export function getEnterpriseList(params) {
|
||||
return request.get('/enterprise/index', { params })
|
||||
}
|
||||
// 企业列表-添加
|
||||
export function getEnterpriseSave(params) {
|
||||
return request.post('/enterprise/save', params)
|
||||
}
|
||||
// 企业列表-只读
|
||||
export function getEnterpriseRead(params) {
|
||||
return request.post('/enterprise/read', params)
|
||||
}
|
||||
// 企业列表-编辑
|
||||
export function getEnterpriseUpdate(params) {
|
||||
return request.post('/enterprise/update', params)
|
||||
}
|
||||
// 企业列表-删除
|
||||
export function getEnterpriseDelete(params) {
|
||||
return request.post('/enterprise/delete', params)
|
||||
}
|
||||
// 获取企业用户列表
|
||||
export function getEnterpriseUserList(params) {
|
||||
return request.get('/enterpriseUser/index', { params })
|
||||
}
|
||||
// 企业用户-添加
|
||||
export function getEnterpriseUserSave(params) {
|
||||
return request.post('/enterpriseUser/save', params)
|
||||
}
|
||||
// 企业用户-只读
|
||||
export function getEnterpriseUserRead(params) {
|
||||
return request.post('/enterpriseUser/read', params)
|
||||
}
|
||||
// 企业用户-编辑
|
||||
export function getEnterpriseUserUpdate(params) {
|
||||
return request.post('/enterpriseUser/update', params)
|
||||
}
|
||||
// 企业用户-删除
|
||||
export function getEnterpriseUserDelete(params) {
|
||||
return request.post('/enterpriseUser/delete', params)
|
||||
}
|
||||
// 获取企业车辆列表
|
||||
export function getEnterpriseCarList(params) {
|
||||
return request.get('/enterpriseCar/index', { params })
|
||||
}
|
||||
// 企业车辆-添加
|
||||
export function getEnterpriseCarSave(params) {
|
||||
return request.post('/enterpriseCar/save', params)
|
||||
}
|
||||
// 企业车辆-只读
|
||||
export function getEnterpriseCarRead(params) {
|
||||
return request.post('/enterpriseCar/read', params)
|
||||
}
|
||||
// 企业车辆-编辑
|
||||
export function getEnterpriseCarUpdate(params) {
|
||||
return request.post('/enterpriseCar/update', params)
|
||||
}
|
||||
// 企业车辆-删除
|
||||
export function getEnterpriseCarDelete(params) {
|
||||
return request.post('/enterpriseCar/delete', params)
|
||||
}
|
||||
// 企业组搜索用户
|
||||
export function NormalSearch(params) {
|
||||
return request.post('/NormalSearch', params)
|
||||
}
|
||||
// 查询企业
|
||||
export function EnterpriseGroupList(params) {
|
||||
return request.post('/EnterpriseGroupAdd', params)
|
||||
}
|
||||
// 新增企业成员
|
||||
export function NormalToEnterprise(params) {
|
||||
return request.post('/NormalToEnterprise', params)
|
||||
}
|
||||
// 删除组
|
||||
export function DeleteEnterpriseGroup(params) {
|
||||
return request.post('/DeleteEnterpriseGroup', params)
|
||||
}
|
||||
// 电话查找
|
||||
export function PhoneSearch(params) {
|
||||
return request.post('/PhoneSearch', params)
|
||||
}
|
||||
// 修改组
|
||||
export function EnterpriserUserEdit(params) {
|
||||
return request.post('/EnterpriserUserEdit', params)
|
||||
}
|
||||
// 查询服务费
|
||||
export function ShowServiceFee(params) {
|
||||
return request.post('/ShowServiceFee', params)
|
||||
}
|
||||
// 更新服务费
|
||||
export function UpdateServiceFee(params) {
|
||||
return request.post('/UpdateServiceFee', params)
|
||||
}
|
||||
// 查看该用户充值详情
|
||||
export function RechargeMessage(params) {
|
||||
return request.post('/RechargeMessage', params)
|
||||
}
|
||||
// 查看该用户提现详情
|
||||
export function RefundMessage(params) {
|
||||
return request.post('/RefundMessage', params)
|
||||
}
|
||||
// 显示预约时间
|
||||
export function ShowAppointmentTime(params) {
|
||||
return request.post('/ShowAppointmentTime', params)
|
||||
}
|
||||
// 修改预约时间
|
||||
export function ModifyAppointmentTime(params) {
|
||||
return request.post('/ModifyAppointmentTime', params)
|
||||
}
|
||||
|
||||
// 活动
|
||||
export function getEventList(params) {
|
||||
return request.post('/eventList2', params)
|
||||
}
|
||||
// 退款订单
|
||||
export function getRefundOrder(params) {
|
||||
return request.get('/getRefundOrder', { params })
|
||||
}
|
||||
// 权限
|
||||
export function GetRole(params) {
|
||||
return request.get('/getRoleList', { params })
|
||||
}
|
||||
// 权限
|
||||
export function getMenuList(params) {
|
||||
return request.get('/getMenuList', { params })
|
||||
}
|
||||
// 日志
|
||||
export function getLogList(params) {
|
||||
return request.get('/getLogList', { params })
|
||||
}
|
||||
// 运营数据
|
||||
export function getYunYingData(params) {
|
||||
return request.get('/getYunYingData', { params })
|
||||
}
|
||||
// 财务数据
|
||||
export function getCaiWuData(params) {
|
||||
return request.get('/getCaiWuData', { params })
|
||||
}
|
||||
BIN
src/assets/imgs/404.jpg
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
src/assets/imgs/bg00.jpg
Normal file
|
After Width: | Height: | Size: 951 KiB |
BIN
src/assets/imgs/bg01.jpg
Normal file
|
After Width: | Height: | Size: 331 KiB |
BIN
src/assets/imgs/bg02.jpg
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
src/assets/imgs/bg03.jpg
Normal file
|
After Width: | Height: | Size: 343 KiB |
BIN
src/assets/imgs/bg04.jpg
Normal file
|
After Width: | Height: | Size: 308 KiB |
BIN
src/assets/imgs/bg05.jpg
Normal file
|
After Width: | Height: | Size: 405 KiB |
BIN
src/assets/imgs/bg06.jpg
Normal file
|
After Width: | Height: | Size: 405 KiB |
BIN
src/assets/imgs/logo.png
Normal file
|
After Width: | Height: | Size: 276 KiB |
BIN
src/assets/imgs/user.jpg
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
49
src/components/404.vue
Normal file
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<div>
|
||||
<img :src="img">
|
||||
<p>未到找指定页面</p>
|
||||
<Button class="back" @click="back">返回页面</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'error',
|
||||
data() {
|
||||
return {
|
||||
img: require('../assets/imgs/404.jpg'),
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
back() {
|
||||
this.$router.back()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
div {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #f8f5ec;
|
||||
}
|
||||
img {
|
||||
display: block;
|
||||
margin: auto;
|
||||
}
|
||||
p {
|
||||
font-size: 40px;
|
||||
text-align: center;
|
||||
margin-bottom: 100px;
|
||||
}
|
||||
.back {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
</style>
|
||||
702
src/components/Index.vue
Normal file
@@ -0,0 +1,702 @@
|
||||
<template>
|
||||
<div class="index-vue">
|
||||
<!-- 侧边栏 -->
|
||||
<aside :class="asideClassName">
|
||||
<!-- logo -->
|
||||
<div class="logo-c">
|
||||
<img src="../assets/imgs/logo.png" alt="logo" class="logo">
|
||||
<span v-show="isShowAsideTitle">潜江市充电桩</span>
|
||||
</div>
|
||||
<!-- 菜单栏 -->
|
||||
<Menu class="menu" ref="asideMenu" theme="dark" width="100%" @on-select="selectMenuCallback"
|
||||
accordion :open-names="openMenus" :active-name="currentPage" @on-open-change="menuChange">
|
||||
<!-- 动态菜单 -->
|
||||
<div v-for="(item, index) in menuItems" :key="index">
|
||||
<Submenu :class="isShowAsideTitle? '' : 'shrink'" v-if="item.children" :name="index">
|
||||
<template slot="title">
|
||||
<Icon :size="item.size" :type="item.type"/>
|
||||
<span v-show="isShowAsideTitle">{{item.text}}</span>
|
||||
</template>
|
||||
<div v-for="(subItem, i) in item.children" :key="index + i">
|
||||
<Submenu :class="isShowAsideTitle? '' : 'shrink'" v-if="subItem.children" :name="index + '-' + i">
|
||||
<template slot="title">
|
||||
<Icon :size="subItem.size" :type="subItem.type"/>
|
||||
<span v-show="isShowAsideTitle">{{subItem.text}}</span>
|
||||
</template>
|
||||
<template v-for="(threeItem, k) in subItem.children">
|
||||
<a href="https://www.baidu.com" target="_blank" :key="index + i + k" v-if="threeItem.isExternal">
|
||||
<MenuItem :class="isShowAsideTitle? '' : 'shrink'" class="menu-level-3"
|
||||
:name="'external-link-' + index + i + k">
|
||||
<template v-if="!threeItem.hidden">
|
||||
<a :href="threeItem.url" target="_blank" class="external">
|
||||
<Icon :size="threeItem.size" :type="threeItem.type"/>
|
||||
<span v-show="isShowAsideTitle">{{threeItem.text}}</span>
|
||||
</a>
|
||||
</template>
|
||||
</MenuItem>
|
||||
</a>
|
||||
<MenuItem v-else :class="isShowAsideTitle? '' : 'shrink'" class="menu-level-3"
|
||||
:name="threeItem.name" :key="index + i + k">
|
||||
<template v-if="!threeItem.hidden">
|
||||
<Icon :size="threeItem.size" :type="threeItem.type"/>
|
||||
<span v-show="isShowAsideTitle">{{threeItem.text}}</span>
|
||||
</template>
|
||||
</MenuItem>
|
||||
</template>
|
||||
</Submenu>
|
||||
<template v-else-if="!subItem.hidden">
|
||||
<a :href="subItem.url" v-if="subItem.isExternal" target="_blank" class="external">
|
||||
<MenuItem :class="isShowAsideTitle? '' : 'shrink'"
|
||||
:name="'external-link-' + index + '-' + i">
|
||||
<Icon :size="subItem.size" :type="subItem.type"/>
|
||||
<span v-show="isShowAsideTitle">{{subItem.text}}</span>
|
||||
</MenuItem>
|
||||
</a>
|
||||
<MenuItem v-else :class="isShowAsideTitle? '' : 'shrink'" :name="subItem.name">
|
||||
<Icon :size="subItem.size" :type="subItem.type"/>
|
||||
<span v-show="isShowAsideTitle">{{subItem.text}}</span>
|
||||
</MenuItem>
|
||||
</template>
|
||||
</div>
|
||||
</Submenu>
|
||||
<template v-else-if="!item.hidden">
|
||||
<a :href="item.url" v-if="item.isExternal" target="_blank" class="external">
|
||||
<MenuItem :class="isShowAsideTitle? '' : 'shrink'" :name="'external-link-' + index">
|
||||
<Icon :size="item.size" :type="item.type"/>
|
||||
<span v-show="isShowAsideTitle">{{item.text}}</span>
|
||||
</MenuItem>
|
||||
</a>
|
||||
<MenuItem v-else :class="isShowAsideTitle? '' : 'shrink'" :name="item.name">
|
||||
<Icon :size="item.size" :type="item.type" />
|
||||
<span v-show="isShowAsideTitle">{{item.text}}</span>
|
||||
</MenuItem>
|
||||
</template>
|
||||
</div>
|
||||
</Menu>
|
||||
</aside>
|
||||
|
||||
<!-- 右侧部分 -->
|
||||
<section class="sec-right">
|
||||
<!-- 头部 -->
|
||||
<div class="top-c">
|
||||
<header>
|
||||
<div class="h-left">
|
||||
<div class="pointer" @click="isShrinkAside" title="收缩/展开">
|
||||
<Icon type="ios-apps" />
|
||||
</div>
|
||||
<!-- 面包屑功能 -->
|
||||
<p class="crumbs">{{crumbs}}</p>
|
||||
</div>
|
||||
<div class="h-right">
|
||||
<!-- 消息 -->
|
||||
<div class="notice-c" @click="info" title="查看新消息">
|
||||
<div :class="{newMsg: hasNewMsg}"></div>
|
||||
<Icon type="ios-notifications-outline" />
|
||||
</div>
|
||||
<!-- 用户头像 -->
|
||||
<div class="user-img-c">
|
||||
<img :src="userImg">
|
||||
</div>
|
||||
<!-- 下拉菜单 -->
|
||||
<Dropdown trigger="click" @on-click="userOperate" @on-visible-change="showArrow">
|
||||
<div class="pointer">
|
||||
<span>{{userName}}</span>
|
||||
<Icon v-show="arrowDown" type="md-arrow-dropdown"/>
|
||||
<Icon v-show="arrowUp" type="md-arrow-dropup"/>
|
||||
</div>
|
||||
<DropdownMenu slot="list">
|
||||
<!-- name标识符 -->
|
||||
<DropdownItem name="1">修改密码</DropdownItem>
|
||||
<DropdownItem name="2">基本资料</DropdownItem>
|
||||
<DropdownItem divided name="3">退出登陆</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- 标签栏 -->
|
||||
<div class="div-tags">
|
||||
<ul class="ul-c">
|
||||
<li v-for="(item, index) in tagsArry" :key="index" :class="{active: isActive(item.name)}" @click="activeTag(index)">
|
||||
<a class="li-a">
|
||||
{{item.text}}
|
||||
</a>
|
||||
<Icon size="16" @click="closeTag(index)" type="md-close" />
|
||||
</li>
|
||||
</ul>
|
||||
<!-- 标签栏相关功能 -->
|
||||
<div class="div-icons">
|
||||
<div class="refresh-c" @click="reloadPage" title="刷新当前标签页">
|
||||
<Icon type="md-refresh" />
|
||||
</div>
|
||||
<div class="tag-options" title="关闭标签">
|
||||
<Dropdown trigger="click" @on-click="closeTags">
|
||||
<Icon type="ios-options" />
|
||||
<DropdownMenu slot="list">
|
||||
<DropdownItem name="1">关闭其他标签</DropdownItem>
|
||||
<DropdownItem name="2">关闭所有标签</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 页面主体 -->
|
||||
<div class="main-content">
|
||||
<div class="view-c">
|
||||
<keep-alive :include="keepAliveData">
|
||||
<!-- 子页面 -->
|
||||
<router-view v-if="isShowRouter"/>
|
||||
</keep-alive>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { resetTokenAndClearUser } from '../utils'
|
||||
|
||||
export default {
|
||||
name: 'index',
|
||||
data() {
|
||||
return {
|
||||
// 用于储存页面路径
|
||||
paths: {},
|
||||
// 当前显示页面
|
||||
currentPage: '',
|
||||
openMenus: [], // 要打开的菜单名字 name属性
|
||||
menuCache: [], // 缓存已经打开的菜单
|
||||
hasNewMsg: true, // 是否有新消息
|
||||
isShowRouter: true,
|
||||
msgNum: '10', // 新消息条数
|
||||
// 标签栏 标签标题 路由名称
|
||||
// 数据格式 {text: '首页', name: 'home'}
|
||||
// 用于缓存打开的路由 在标签栏上展示
|
||||
tagsArry: [],
|
||||
arrowUp: false, // 用户详情向上箭头
|
||||
arrowDown: true, // 用户详情向下箭头
|
||||
isShowAsideTitle: true, // 是否展示侧边栏内容
|
||||
main: null, // 页面主要内容区域
|
||||
asideClassName: 'aside-big', // 控制侧边栏宽度变化
|
||||
asideArrowIcons: [], // 缓存侧边栏箭头图标 收缩时用
|
||||
// 面包屑
|
||||
crumbs: '主页',
|
||||
userName: '',
|
||||
userImg: '',
|
||||
// 主页路由名称
|
||||
home: 'home',
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 第一个标签
|
||||
const name = this.$route.name
|
||||
this.currentPage = name
|
||||
this.tagsArry.push({
|
||||
text: this.nameToTitle[name],
|
||||
name,
|
||||
})
|
||||
|
||||
// 根据路由打开对应的菜单栏
|
||||
this.openMenus = this.getMenus(name)
|
||||
this.$nextTick(() => {
|
||||
this.$refs.asideMenu.updateOpened()
|
||||
})
|
||||
|
||||
// 设置用户信息
|
||||
this.userName = localStorage.getItem('userName')
|
||||
this.userImg = localStorage.getItem('userImg')
|
||||
|
||||
this.main = document.querySelector('.sec-right')
|
||||
this.asideArrowIcons = document.querySelectorAll('aside .ivu-icon-ios-arrow-down')
|
||||
|
||||
// 监听窗口大小 自动收缩侧边栏
|
||||
this.monitorWindowSize()
|
||||
},
|
||||
watch: {
|
||||
$route(to) {
|
||||
const name = to.name
|
||||
this.currentPage = name
|
||||
if (name == 'error') {
|
||||
this.crumbs = '404'
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.keepAliveData.includes(name)) {
|
||||
// 如果标签超过8个 则将第一个标签删除
|
||||
if (this.tagsArry.length == 8) {
|
||||
this.tagsArry.shift()
|
||||
}
|
||||
this.tagsArry.push({ name, text: this.nameToTitle[name] })
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.crumbs = this.paths[name]
|
||||
}, 0)
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
// 菜单栏
|
||||
menuItems() {
|
||||
return this.$store.state.menuItems
|
||||
},
|
||||
// 需要缓存的路由
|
||||
keepAliveData() {
|
||||
return this.tagsArry.map(item => item.name)
|
||||
},
|
||||
// 由于iView的导航菜单比较坑 只能设定一个name参数
|
||||
// 所以需要在这定义组件名称和标签栏标题的映射表 有多少个页面就有多少个映射条数
|
||||
nameToTitle() {
|
||||
const obj = {}
|
||||
this.menuItems.forEach(e => {
|
||||
this.processNameToTitle(obj, e)
|
||||
})
|
||||
|
||||
return obj
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getMenus(name) {
|
||||
let menus
|
||||
const tagTitle = this.nameToTitle[name]
|
||||
for (let i = 0, l = this.menuItems.length; i < l; i++) {
|
||||
const item = this.menuItems[i]
|
||||
menus = []
|
||||
menus[0] = i
|
||||
if (item.text == tagTitle) {
|
||||
return menus
|
||||
}
|
||||
|
||||
if (item.children) {
|
||||
for (let j = 0, ll = item.children.length; j < ll; j++) {
|
||||
const child = item.children[j]
|
||||
menus[1] = i + '-' + j
|
||||
menus.length = 2
|
||||
if (child.text == tagTitle) {
|
||||
return menus
|
||||
}
|
||||
|
||||
if (child.children) {
|
||||
for (let k = 0, lll = child.children.length; k < lll; k++) {
|
||||
const grandson = child.children[k]
|
||||
menus[2] = i + '-' + j + '-' + k
|
||||
if (grandson.text == tagTitle) {
|
||||
return menus
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
monitorWindowSize() {
|
||||
let w = document.documentElement.clientWidth || document.body.clientWidth
|
||||
if (w < 1300) {
|
||||
this.shrinkAside()
|
||||
}
|
||||
|
||||
window.onresize = () => {
|
||||
// 可视窗口宽度太小 自动收缩侧边栏
|
||||
if (w < 1300 && this.isShowAsideTitle
|
||||
&& w > (document.documentElement.clientWidth || document.body.clientWidth)) {
|
||||
this.shrinkAside()
|
||||
}
|
||||
|
||||
w = document.documentElement.clientWidth || document.body.clientWidth
|
||||
}
|
||||
},
|
||||
|
||||
// 判断当前标签页是否激活状态
|
||||
isActive(name) {
|
||||
return this.$route.name === name
|
||||
},
|
||||
// 跳转页面 路由名称和参数
|
||||
gotoPage(name, params) {
|
||||
this.currentPage = name
|
||||
this.crumbs = this.paths[name]
|
||||
this.$router.push({ name, params })
|
||||
|
||||
if (!this.keepAliveData.includes(name)) {
|
||||
// 如果标签超过8个 则将第一个标签删除
|
||||
if (this.tagsArry.length == 8) {
|
||||
this.tagsArry.shift()
|
||||
}
|
||||
this.tagsArry.push({ name, text: this.nameToTitle[name] })
|
||||
}
|
||||
},
|
||||
// 选择菜单回调函数
|
||||
selectMenuCallback(name) {
|
||||
if (name.includes('external-link')) return
|
||||
this.gotoPage(name)
|
||||
this.expandAside()
|
||||
setTimeout(() => {
|
||||
this.isShowAsideTitle = true
|
||||
}, 200)
|
||||
},
|
||||
// 用户操作
|
||||
userOperate(name) {
|
||||
switch (name) {
|
||||
case '1':
|
||||
// 修改密码
|
||||
this.gotoPage('password')
|
||||
break
|
||||
case '2':
|
||||
// 基本资料
|
||||
this.gotoPage('userinfo')
|
||||
break
|
||||
case '3':
|
||||
resetTokenAndClearUser()
|
||||
this.$router.push({ name: 'login' })
|
||||
break
|
||||
}
|
||||
},
|
||||
// 控制用户三角箭头显示状态
|
||||
showArrow(flag) {
|
||||
this.arrowUp = flag
|
||||
this.arrowDown = !flag
|
||||
},
|
||||
// 判断
|
||||
isShrinkAside() {
|
||||
if (this.isShowAsideTitle) {
|
||||
this.shrinkAside()
|
||||
} else {
|
||||
this.expandAside()
|
||||
}
|
||||
},
|
||||
// 收缩
|
||||
shrinkAside() {
|
||||
for (let i = 0, len = this.asideArrowIcons.length; i < len; i++) {
|
||||
this.asideArrowIcons[i].style.display = 'none'
|
||||
}
|
||||
|
||||
this.isShowAsideTitle = false
|
||||
this.openMenus = []
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.asideMenu) {
|
||||
this.$refs.asideMenu.updateOpened()
|
||||
}
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
this.asideClassName = ''
|
||||
this.main.style.marginLeft = '90px'
|
||||
}, 0)
|
||||
},
|
||||
// 展开
|
||||
expandAside() {
|
||||
setTimeout(() => {
|
||||
this.isShowAsideTitle = true
|
||||
for (let i = 0, len = this.asideArrowIcons.length; i < len; i++) {
|
||||
this.asideArrowIcons[i].style.display = 'block'
|
||||
}
|
||||
|
||||
this.openMenus = this.menuCache
|
||||
if (this.$refs.asideMenu) {
|
||||
this.$refs.asideMenu.updateOpened()
|
||||
}
|
||||
}, 200)
|
||||
this.asideClassName = 'aside-big'
|
||||
this.main.style.marginLeft = '220px'
|
||||
},
|
||||
// 刷新当前标签页
|
||||
reloadPage() {
|
||||
let name = this.$route.name
|
||||
let index = this.keepAliveData.indexOf(name)
|
||||
this.$nextTick(() => {
|
||||
if (this.tagsArry.length) {
|
||||
this.isShowRouter = false
|
||||
this.tagsArry.splice(index, 1)
|
||||
this.$nextTick(() => {
|
||||
this.tagsArry.splice(index, 0, { name, text: this.nameToTitle[name] })
|
||||
this.gotoPage(name)
|
||||
this.isShowRouter = true
|
||||
})
|
||||
} else {
|
||||
this.isShowRouter = false
|
||||
this.$nextTick(() => {
|
||||
this.tagsArry.push({ name, text: this.nameToTitle[name] })
|
||||
this.gotoPage(name)
|
||||
this.isShowRouter = true
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
// 关闭单个标签
|
||||
closeTag(i) {
|
||||
let name = this.tagsArry[i].name
|
||||
this.tagsArry.splice(i, 1)
|
||||
window.event.stopPropagation()
|
||||
// 如果关闭的是当前标签 则激活前一个标签
|
||||
// 如果关闭的是第一个标签 则激活后一个标签
|
||||
if (this.tagsArry.length) {
|
||||
if (this.isActive(name)) {
|
||||
if (i != 0) {
|
||||
this.gotoPage(this.tagsArry[i - 1].name)
|
||||
} else {
|
||||
this.gotoPage(this.tagsArry[i].name)
|
||||
}
|
||||
}
|
||||
} else if (name != this.home) {
|
||||
// 如果没有标签则跳往首页
|
||||
this.gotoPage(this.home)
|
||||
} else {
|
||||
this.reloadPage()
|
||||
}
|
||||
},
|
||||
// 根据路由名称关闭页面
|
||||
closeName(name) {
|
||||
for (let i = 0, len = this.tagsArry.length; i < len; i++) {
|
||||
if (this.tagsArry[i].name == name) {
|
||||
this.closeTag(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
// 批量关闭标签
|
||||
closeTags(flag) {
|
||||
if (flag == 1) {
|
||||
// 关闭其他标签
|
||||
this.tagsArry = []
|
||||
this.gotoPage(this.$route.name)
|
||||
} else {
|
||||
// 关闭所有标签
|
||||
this.tagsArry = []
|
||||
this.gotoPage(this.home)
|
||||
this.reloadPage()
|
||||
}
|
||||
},
|
||||
// 激活标签
|
||||
activeTag(i) {
|
||||
this.gotoPage(this.tagsArry[i].name)
|
||||
},
|
||||
// 消息通知
|
||||
info() {
|
||||
const self = this
|
||||
this.$Notice.info({
|
||||
title: `您有${this.msgNum}条消息`,
|
||||
render(h) {
|
||||
return h('Button', {
|
||||
attrs: {
|
||||
type: 'info',
|
||||
size: 'small',
|
||||
},
|
||||
on: {
|
||||
click() {
|
||||
// 点击查看跳转到消息页
|
||||
self.gotoPage('msg')
|
||||
self.hasNewMsg = false
|
||||
self.msgNum = 0
|
||||
},
|
||||
},
|
||||
}, [
|
||||
'点击查看',
|
||||
])
|
||||
},
|
||||
})
|
||||
},
|
||||
// 菜单栏改变事件
|
||||
menuChange(data) {
|
||||
this.menuCache = data
|
||||
},
|
||||
processNameToTitle(obj, data, text) {
|
||||
if (data.name) {
|
||||
obj[data.name] = data.text
|
||||
this.paths[data.name] = text ? `${text} / ${data.text}` : data.text
|
||||
}
|
||||
if (data.children) {
|
||||
data.children.forEach(e => {
|
||||
this.processNameToTitle(obj, e, text ? `${text} / ${data.text}` : data.text)
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.index-vue {
|
||||
height: 100%;
|
||||
color: #666;
|
||||
}
|
||||
/* 侧边栏 */
|
||||
aside {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 90px;
|
||||
background: #20222A;
|
||||
height: 100%;
|
||||
transition: width .3s;
|
||||
overflow: auto;
|
||||
}
|
||||
.logo-c {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: rgba(255,255,255,.8);
|
||||
font-size: 16px;
|
||||
margin: 20px 0;
|
||||
justify-content: center;
|
||||
}
|
||||
.logo {
|
||||
width: 40px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.aside-big {
|
||||
width: 220px;
|
||||
}
|
||||
/* 主体页面 */
|
||||
.sec-right {
|
||||
height: 100%;
|
||||
margin-left: 220px;
|
||||
transition: margin-left .3s;
|
||||
overflow: hidden;;
|
||||
background: #f3f7fd;
|
||||
}
|
||||
/* 主体页面头部 */
|
||||
header {
|
||||
height: 50px;
|
||||
border-bottom: none;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-right: 40px;
|
||||
padding-left: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
header .ivu-icon {
|
||||
font-size: 24px;
|
||||
}
|
||||
.refresh-c {
|
||||
margin: 0 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.h-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.h-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.user-img-c img {
|
||||
width: 100%;
|
||||
}
|
||||
.notice-c {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
.newMsg {
|
||||
position: absolute;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background-color: #FF5722;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
.user-img-c {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
background: #ddd;
|
||||
border-radius: 50%;
|
||||
margin: 0 40px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.tag-options {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
.div-tags {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 4px 0;
|
||||
}
|
||||
.div-icons {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
height: 34px;
|
||||
width: 160px;
|
||||
font-size: 18px;
|
||||
}
|
||||
/* 标签栏 */
|
||||
.ul-c {
|
||||
height: 34px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 0 10px;
|
||||
overflow: hidden;
|
||||
width: calc(100% - 160px);
|
||||
}
|
||||
.ul-c li {
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
height: 24px;
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 3px 5px 2px 3px;
|
||||
border: 1px solid #e6e6e6;
|
||||
}
|
||||
a {
|
||||
color: #666;
|
||||
transition: none;
|
||||
}
|
||||
.li-a {
|
||||
max-width: 80px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.ul-c .ivu-icon {
|
||||
margin-left: 6px;
|
||||
}
|
||||
.active {
|
||||
background: #409eff;
|
||||
border: 1px solid #409eff;
|
||||
}
|
||||
.active a {
|
||||
color: #fff;
|
||||
}
|
||||
.active .ivu-icon {
|
||||
color: #fff;
|
||||
}
|
||||
/* 主要内容区域 */
|
||||
.main-content {
|
||||
height: calc(100% - 88px);
|
||||
overflow: hidden;
|
||||
}
|
||||
.view-c {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
.crumbs {
|
||||
margin-left: 10px;
|
||||
color: #97a8be;
|
||||
cursor: default;
|
||||
}
|
||||
.menu-level-3 .ivu-icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
.shrink {
|
||||
text-align: center;
|
||||
}
|
||||
.external {
|
||||
color: rgba(255,255,255,.7);
|
||||
}
|
||||
.external > i {
|
||||
margin-right: 6px;
|
||||
}
|
||||
</style>
|
||||
167
src/components/Login.vue
Normal file
@@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<div class="login-vue" :style="bg">
|
||||
<div class="container">
|
||||
<p class="title">高新投绿源</p>
|
||||
<div class="input-c">
|
||||
<Input prefix="ios-contact" v-model="account" placeholder="用户名" clearable />
|
||||
<p class="error">{{ accountError }}</p>
|
||||
</div>
|
||||
<div class="input-c">
|
||||
<Input type="password" v-model="pwd" prefix="md-lock" placeholder="密码" clearable
|
||||
@keyup.enter.native="submit" />
|
||||
<p class="error">{{ pwdError }}</p>
|
||||
</div>
|
||||
<Button :loading="isShowLoading" class="submit" type="primary" @click="submit">登陆</Button>
|
||||
<!-- <p class="account"><span @click="register">注册账号</span> | <span @click="forgetPwd">忘记密码</span></p> -->
|
||||
<p>@重庆爱京数字科技有限公司</p>
|
||||
<div>
|
||||
<a href=" " rel="noreferrer" target="_blank">渝公网安备50011502001173号</a >
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import { login } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'login',
|
||||
data() {
|
||||
return {
|
||||
account: '',
|
||||
pwd: '',
|
||||
accountError: '',
|
||||
pwdError: '',
|
||||
isShowLoading: false,
|
||||
bg: {},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.bg.backgroundImage = 'url(' + require('../assets/imgs/bg0' + new Date().getDay() + '.jpg') + ')'
|
||||
},
|
||||
watch: {
|
||||
$route: {
|
||||
handler(route) {
|
||||
this.redirect = route.query && route.query.redirect
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
register() {
|
||||
|
||||
},
|
||||
forgetPwd() {
|
||||
|
||||
},
|
||||
async submit() {
|
||||
this.accountError = ''
|
||||
this.pwdError = ''
|
||||
if (this.account == '') {
|
||||
this.accountError = '请输入用户名'
|
||||
return
|
||||
}
|
||||
if (this.pwd == '') {
|
||||
this.pwdError = '请输入密码'
|
||||
return
|
||||
}
|
||||
await login({ username: this.account, password: this.pwd }).then((res) => {
|
||||
if (res.code == 200) {
|
||||
localStorage.setItem('permissions', res.permissions)
|
||||
localStorage.setItem('authority', res.authority)
|
||||
localStorage.setItem('adminId', res.adminId)
|
||||
localStorage.setItem('token', res.token)
|
||||
this.$router.push({ path: this.redirect || '/' })
|
||||
} else {
|
||||
this.$Message.error(res.message[0])
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.login-vue {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.login-vue .container {
|
||||
background: rgba(255, 255, 255, .5);
|
||||
width: 300px;
|
||||
text-align: center;
|
||||
border-radius: 10px;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.login-vue .ivu-input {
|
||||
background-color: transparent;
|
||||
color: #fff;
|
||||
outline: #fff;
|
||||
border-color: #fff;
|
||||
}
|
||||
|
||||
.login-vue ::-webkit-input-placeholder {
|
||||
/* WebKit, Blink, Edge */
|
||||
color: rgba(255, 255, 255, .8);
|
||||
}
|
||||
|
||||
.login-vue :-moz-placeholder {
|
||||
/* Mozilla Firefox 4 to 18 */
|
||||
color: rgba(255, 255, 255, .8);
|
||||
}
|
||||
|
||||
.login-vue ::-moz-placeholder {
|
||||
/* Mozilla Firefox 19+ */
|
||||
color: rgba(255, 255, 255, .8);
|
||||
}
|
||||
|
||||
.login-vue :-ms-input-placeholder {
|
||||
/* Internet Explorer 10-11 */
|
||||
color: rgba(255, 255, 255, .8);
|
||||
}
|
||||
|
||||
.login-vue .title {
|
||||
font-size: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.login-vue .input-c {
|
||||
margin: auto;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.login-vue .error {
|
||||
color: red;
|
||||
text-align: left;
|
||||
margin: 5px auto;
|
||||
font-size: 12px;
|
||||
padding-left: 30px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.login-vue .submit {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.login-vue .account {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.login-vue .account span {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.login-vue .ivu-icon {
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.login-vue .ivu-icon-ios-close-circle {
|
||||
color: #777;
|
||||
}
|
||||
</style>
|
||||
20
src/main.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import Vue from 'vue'
|
||||
import axios from 'axios'
|
||||
import ViewUI from 'view-design'
|
||||
import App from './App'
|
||||
import store from './store'
|
||||
import router from './router'
|
||||
import 'view-design/dist/styles/iview.css'
|
||||
import './permission'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
Vue.use(ViewUI)
|
||||
|
||||
Vue.prototype.$axios = axios
|
||||
|
||||
new Vue({
|
||||
el: '#app',
|
||||
router,
|
||||
store,
|
||||
render: h => h(App),
|
||||
})
|
||||
44
src/permission.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import { LoadingBar } from 'view-design'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import createRoutes from '@/utils/createRoutes'
|
||||
import { getDocumentTitle, resetTokenAndClearUser } from './utils'
|
||||
|
||||
// 是否有菜单数据
|
||||
let hasMenus = false
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
document.title = getDocumentTitle(to.meta.title)
|
||||
LoadingBar.start()
|
||||
if (localStorage.getItem('token')) {
|
||||
if (to.path === '/login') {
|
||||
next({ path: '/' })
|
||||
} else if (hasMenus) {
|
||||
next()
|
||||
} else {
|
||||
try {
|
||||
// 这里可以用 await 配合请求后台数据来生成路由
|
||||
// const data = await axios.get('xxx')
|
||||
// const routes = createRoutes(data)
|
||||
const routes = createRoutes(store.state.menuItems)
|
||||
// 动态添加路由
|
||||
router.addRoutes(routes)
|
||||
hasMenus = true
|
||||
next({ path: to.path || '/' })
|
||||
} catch (error) {
|
||||
resetTokenAndClearUser()
|
||||
next(`/login?redirect=${to.path}`)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hasMenus = false
|
||||
if (to.path === '/login') {
|
||||
next()
|
||||
} else {
|
||||
next(`/login?redirect=${to.path}`)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
router.afterEach(() => {
|
||||
LoadingBar.finish()
|
||||
})
|
||||
290
src/router/index.js
Normal file
@@ -0,0 +1,290 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
const commonRoutes = [{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
meta: {
|
||||
title: '登录',
|
||||
},
|
||||
component: () => import('../components/Login.vue'),
|
||||
},
|
||||
{
|
||||
path: '/other', // 点击侧边栏跳到一个单独的路由页面,需要定义,层级和其他顶级路由一样
|
||||
name: 'other',
|
||||
meta: {
|
||||
title: '单独的路由',
|
||||
},
|
||||
component: () => import('../views/Other.vue'),
|
||||
},
|
||||
{
|
||||
path: '/404',
|
||||
name: '404',
|
||||
meta: {
|
||||
title: '404',
|
||||
},
|
||||
component: () => import('../components/404.vue'),
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/charging_station',
|
||||
},
|
||||
]
|
||||
|
||||
// 本地所有的页面 需要配合后台返回的数据生成页面
|
||||
export const asyncRoutes = {
|
||||
// 充电桩
|
||||
charging_station: {
|
||||
path: 'charging_station',
|
||||
name: 'charging_station',
|
||||
meta: {
|
||||
title: '站点管理',
|
||||
},
|
||||
component: () => import('../views/charging_pile/Station.vue'),
|
||||
},
|
||||
charging_pile: {
|
||||
path: 'charging_pile',
|
||||
name: 'charging_pile',
|
||||
meta: {
|
||||
title: '充电桩管理',
|
||||
},
|
||||
component: () => import('../views/charging_pile/Pile.vue'),
|
||||
},
|
||||
charging_price: {
|
||||
path: 'charging_price',
|
||||
name: 'charging_price',
|
||||
meta: {
|
||||
title: '电价管理',
|
||||
},
|
||||
component: () => import('../views/charging_pile/Price.vue'),
|
||||
},
|
||||
charging_fault: {
|
||||
path: 'charging_fault',
|
||||
name: 'charging_fault',
|
||||
meta: {
|
||||
title: '故障运维',
|
||||
},
|
||||
component: () => import('../views/charging_pile/Fault.vue'),
|
||||
},
|
||||
// 客户
|
||||
corporate_client: {
|
||||
path: 'corporate_client',
|
||||
name: 'corporate_client',
|
||||
meta: {
|
||||
title: '企业客户',
|
||||
},
|
||||
component: () => import('../views/customer_center/CorporateClient.vue'),
|
||||
},
|
||||
wx_user: {
|
||||
path: 'wx_user',
|
||||
name: 'wx_user',
|
||||
meta: {
|
||||
title: '用户管理',
|
||||
},
|
||||
component: () => import('../views/customer_center/WxUser.vue'),
|
||||
},
|
||||
// 运营中心
|
||||
activity: {
|
||||
path: 'activity',
|
||||
name: 'activity',
|
||||
meta: {
|
||||
title: '活动发布',
|
||||
},
|
||||
component: () => import('../views/operations_center/activity.vue'),
|
||||
},
|
||||
coupon: {
|
||||
path: 'coupon',
|
||||
name: 'coupon',
|
||||
meta: {
|
||||
title: '优惠券',
|
||||
},
|
||||
component: () => import('../views/operations_center/coupon.vue'),
|
||||
},
|
||||
user_vip: {
|
||||
path: 'user_vip',
|
||||
name: 'user_vip',
|
||||
meta: {
|
||||
title: '会员',
|
||||
},
|
||||
component: () => import('../views/operations_center/user_vip.vue'),
|
||||
},
|
||||
invoice: {
|
||||
path: 'invoice',
|
||||
name: 'invoice',
|
||||
meta: {
|
||||
title: '发票管理',
|
||||
},
|
||||
component: () => import('../views/operations_center/invoice.vue'),
|
||||
},
|
||||
// 订单
|
||||
charge_order: {
|
||||
path: 'charge_order',
|
||||
name: 'charge_order',
|
||||
meta: {
|
||||
title: '充电订单',
|
||||
},
|
||||
component: () => import('../views/order/charge_order.vue'),
|
||||
},
|
||||
recharge_order: {
|
||||
path: 'recharge_order',
|
||||
name: 'recharge_order',
|
||||
meta: {
|
||||
title: '充值订单',
|
||||
},
|
||||
component: () => import('../views/order/recharge_order.vue'),
|
||||
},
|
||||
refund_order: {
|
||||
path: 'refund_order',
|
||||
name: 'refund_order',
|
||||
meta: {
|
||||
title: '充电退款订单',
|
||||
},
|
||||
component: () => import('../views/order/refund_order.vue'),
|
||||
},
|
||||
order_total: {
|
||||
path: 'order_total',
|
||||
name: 'order_total',
|
||||
meta: {
|
||||
title: '订单统计',
|
||||
},
|
||||
component: () => import('../views/order/order_total.vue'),
|
||||
},
|
||||
// 数据中心
|
||||
yunying_reports: {
|
||||
path: 'yunying_reports',
|
||||
name: 'yunying_reports',
|
||||
meta: {
|
||||
title: '运营报表',
|
||||
},
|
||||
component: () => import('../views/reports/yunying_reports.vue'),
|
||||
},
|
||||
caiwu_reports: {
|
||||
path: 'caiwu_reports',
|
||||
name: 'caiwu_reports',
|
||||
meta: {
|
||||
title: '财务报表',
|
||||
},
|
||||
component: () => import('../views/reports/caiwu_reports.vue'),
|
||||
},
|
||||
yunwei_reports: {
|
||||
path: 'yunwei_reports',
|
||||
name: 'yunwei_reports',
|
||||
meta: {
|
||||
title: '运维报表',
|
||||
},
|
||||
component: () => import('../views/reports/yunwei_reports.vue'),
|
||||
},
|
||||
// 系统配置
|
||||
system: {
|
||||
path: 'system',
|
||||
name: 'system',
|
||||
meta: {
|
||||
title: '参数设置',
|
||||
},
|
||||
component: () => import('../views/system/system.vue'),
|
||||
},
|
||||
admin: {
|
||||
path: 'admin',
|
||||
name: 'admin',
|
||||
meta: {
|
||||
title: '系统用户',
|
||||
},
|
||||
component: () => import('../views/system/admin.vue'),
|
||||
},
|
||||
auth: {
|
||||
path: 'auth',
|
||||
name: 'auth',
|
||||
meta: {
|
||||
title: '权限管理',
|
||||
},
|
||||
component: () => import('../views/system/auth.vue'),
|
||||
},
|
||||
log: {
|
||||
path: 'log',
|
||||
name: 'log',
|
||||
meta: {
|
||||
title: '日志管理',
|
||||
},
|
||||
component: () => import('../views/system/log.vue'),
|
||||
},
|
||||
// 报表分析
|
||||
rate: {
|
||||
path: 'rate',
|
||||
name: 'rate',
|
||||
meta: {
|
||||
title: '日志管理',
|
||||
},
|
||||
component: () => import('../views/reports/rate.vue'),
|
||||
},
|
||||
backup_and_repair: {
|
||||
path: 'backup_and_repair',
|
||||
name: 'backup_and_repair',
|
||||
meta: {
|
||||
title: '日志管理',
|
||||
},
|
||||
component: () => import('../views/reports/backup_and_repair.vue'),
|
||||
},
|
||||
activation: {
|
||||
path: 'activation',
|
||||
name: 'activation',
|
||||
meta: {
|
||||
title: '日志管理',
|
||||
},
|
||||
component: () => import('../views/reports/activation.vue'),
|
||||
},
|
||||
income_analysis: {
|
||||
path: 'income_analysis',
|
||||
name: 'income_analysis',
|
||||
meta: {
|
||||
title: '日志管理',
|
||||
},
|
||||
component: () => import('../views/reports/income_analysis.vue'),
|
||||
},
|
||||
t1: {
|
||||
path: 't1',
|
||||
name: 't1',
|
||||
meta: {
|
||||
title: '表格',
|
||||
},
|
||||
component: () => import('../views/T1.vue'),
|
||||
},
|
||||
password: {
|
||||
path: 'password',
|
||||
name: 'password',
|
||||
meta: {
|
||||
title: '修改密码',
|
||||
},
|
||||
component: () => import('../views/Password.vue'),
|
||||
},
|
||||
msg: {
|
||||
path: 'msg',
|
||||
name: 'msg',
|
||||
meta: {
|
||||
title: '通知消息',
|
||||
},
|
||||
component: () => import('../views/Msg.vue'),
|
||||
},
|
||||
userinfo: {
|
||||
path: 'userinfo',
|
||||
name: 'userinfo',
|
||||
meta: {
|
||||
title: '用户信息',
|
||||
},
|
||||
component: () => import('../views/UserInfo.vue'),
|
||||
},
|
||||
}
|
||||
|
||||
const createRouter = () => new Router({
|
||||
routes: commonRoutes,
|
||||
})
|
||||
|
||||
const router = createRouter()
|
||||
|
||||
export function resetRouter() {
|
||||
const newRouter = createRouter()
|
||||
router.matcher = newRouter.matcher
|
||||
}
|
||||
|
||||
export default router
|
||||
252
src/store/index.js
Normal file
@@ -0,0 +1,252 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
const store = new Vuex.Store({
|
||||
state: {
|
||||
isShowLoading: false, // 全局 loading
|
||||
// 左侧菜单栏数据
|
||||
menuItems: [{
|
||||
text: '充电桩管理',
|
||||
type: 'ios-paper',
|
||||
children: [
|
||||
{
|
||||
type: 'ios-grid',
|
||||
name: 'msg',
|
||||
text: '文档',
|
||||
// hidden 属性 隐藏此菜单 可以通过在地址栏上输入对应的 URL 来显示页面
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
type: 'ios-grid',
|
||||
name: 'charging_station',
|
||||
text: '站点管理',
|
||||
// hidden 属性 隐藏此菜单 可以通过在地址栏上输入对应的 URL 来显示页面
|
||||
// hidden: true,
|
||||
},
|
||||
{
|
||||
size: 18, // icon大小
|
||||
type: 'md-arrow-forward', // icon类型
|
||||
name: 'charging_pile',
|
||||
text: '充电桩管理',
|
||||
// url: 'https://www.baidu.com',
|
||||
// isExternal: true, // 外链 跳到一个外部的 URL 页面
|
||||
},
|
||||
{
|
||||
size: 18,
|
||||
text: '电价管理',
|
||||
name: 'charging_price',
|
||||
type: 'ios-paper',
|
||||
},
|
||||
{
|
||||
size: 18,
|
||||
text: '故障运维',
|
||||
name: 'charging_fault',
|
||||
type: 'ios-paper',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
size: 18, // icon大小
|
||||
type: 'md-home', // icon类型
|
||||
text: '客户中心', // 文本内容
|
||||
children: [
|
||||
{
|
||||
type: 'ios-grid',
|
||||
name: 'corporate_client',
|
||||
text: '企业客户',
|
||||
// hidden 属性 隐藏此菜单 可以通过在地址栏上输入对应的 URL 来显示页面
|
||||
// hidden: true,
|
||||
},
|
||||
{
|
||||
size: 18, // icon大小
|
||||
type: 'md-arrow-forward', // icon类型
|
||||
name: 'wx_user',
|
||||
text: '用户管理',
|
||||
// url: 'https://www.baidu.com',
|
||||
// isExternal: true, // 外链 跳到一个外部的 URL 页面
|
||||
},
|
||||
{
|
||||
size: 18,
|
||||
text: '钱包账户',
|
||||
type: 'ios-paper',
|
||||
},
|
||||
{
|
||||
size: 18,
|
||||
text: '车辆管理',
|
||||
type: 'ios-paper',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
size: 18, // icon大小
|
||||
type: 'ios-egg-outline', // icon类型
|
||||
text: '运营中心', // 点击侧边栏跳到一个单独的路由页面,需要提前在 router.js 定义
|
||||
children: [
|
||||
{
|
||||
type: 'ios-grid',
|
||||
name: 'activity',
|
||||
text: '活动发布',
|
||||
// hidden 属性 隐藏此菜单 可以通过在地址栏上输入对应的 URL 来显示页面
|
||||
// hidden: true,
|
||||
},
|
||||
{
|
||||
size: 18, // icon大小
|
||||
type: 'md-arrow-forward', // icon类型
|
||||
name: 'coupon',
|
||||
text: '优惠券',
|
||||
// url: 'https://www.baidu.com',
|
||||
// isExternal: true, // 外链 跳到一个外部的 URL 页面
|
||||
},
|
||||
{
|
||||
size: 18,
|
||||
text: '会员',
|
||||
name: 'user_vip',
|
||||
type: 'ios-paper',
|
||||
},
|
||||
{
|
||||
size: 18,
|
||||
text: '发票管理',
|
||||
name: 'invoice',
|
||||
type: 'ios-paper',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
size: 18, // icon大小
|
||||
type: 'md-arrow-forward', // icon类型
|
||||
text: '订单管理',
|
||||
// url: 'https://www.baidu.com',
|
||||
// isExternal: true, // 外链 跳到一个外部的 URL 页面
|
||||
children: [
|
||||
{
|
||||
type: 'ios-grid',
|
||||
name: 'charge_order',
|
||||
text: '充电订单',
|
||||
// hidden 属性 隐藏此菜单 可以通过在地址栏上输入对应的 URL 来显示页面
|
||||
// hidden: true,
|
||||
},
|
||||
{
|
||||
size: 18, // icon大小
|
||||
type: 'md-arrow-forward', // icon类型
|
||||
name: 'recharge_order',
|
||||
text: '充值订单',
|
||||
// url: 'https://www.baidu.com',
|
||||
// isExternal: true, // 外链 跳到一个外部的 URL 页面
|
||||
},
|
||||
{
|
||||
size: 18,
|
||||
text: '充电退款订单',
|
||||
name: 'refund_order',
|
||||
type: 'ios-paper',
|
||||
},
|
||||
{
|
||||
size: 18,
|
||||
text: '订单统计',
|
||||
name: 'order_total',
|
||||
type: 'ios-paper',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '数据中心',
|
||||
type: 'ios-paper',
|
||||
children: [
|
||||
{
|
||||
type: 'ios-grid',
|
||||
name: 'yunying_reports',
|
||||
text: '运营报表',
|
||||
// hidden 属性 隐藏此菜单 可以通过在地址栏上输入对应的 URL 来显示页面
|
||||
// hidden: true,
|
||||
},
|
||||
{
|
||||
size: 18, // icon大小
|
||||
type: 'md-arrow-forward', // icon类型
|
||||
name: 'caiwu_reports',
|
||||
text: '财务报表',
|
||||
},
|
||||
{
|
||||
size: 18,
|
||||
text: '运维报表',
|
||||
name: 'yunwei_reports',
|
||||
type: 'ios-paper',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '系统设置',
|
||||
type: 'ios-paper',
|
||||
children: [
|
||||
{
|
||||
type: 'ios-grid',
|
||||
name: 'system',
|
||||
text: '参数设置',
|
||||
// hidden 属性 隐藏此菜单 可以通过在地址栏上输入对应的 URL 来显示页面
|
||||
// hidden: true,
|
||||
},
|
||||
{
|
||||
size: 18, // icon大小
|
||||
type: 'md-arrow-forward', // icon类型
|
||||
name: 'admin',
|
||||
text: '系统用户',
|
||||
},
|
||||
{
|
||||
size: 18,
|
||||
text: '权限管理',
|
||||
name: 'auth',
|
||||
type: 'ios-paper',
|
||||
},
|
||||
{
|
||||
size: 18,
|
||||
text: '日志管理',
|
||||
name: 'log',
|
||||
type: 'ios-paper',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '报表分析',
|
||||
type: 'ios-paper',
|
||||
children: [
|
||||
{
|
||||
type: 'ios-grid',
|
||||
name: 'rate',
|
||||
text: '充电桩使用率',
|
||||
// hidden 属性 隐藏此菜单 可以通过在地址栏上输入对应的 URL 来显示页面
|
||||
// hidden: true,
|
||||
},
|
||||
{
|
||||
type: 'ios-grid',
|
||||
name: 'backup_and_repair',
|
||||
text: '数据备份与修复',
|
||||
// hidden 属性 隐藏此菜单 可以通过在地址栏上输入对应的 URL 来显示页面
|
||||
// hidden: true,
|
||||
},
|
||||
{
|
||||
size: 18, // icon大小
|
||||
type: 'md-arrow-forward', // icon类型
|
||||
name: 'activation',
|
||||
text: '用户活跃度',
|
||||
},
|
||||
{
|
||||
size: 18,
|
||||
text: '收入分析',
|
||||
name: 'income_analysis',
|
||||
type: 'ios-paper',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
mutations: {
|
||||
setMenus(state, items) {
|
||||
state.menuItems = [...items]
|
||||
},
|
||||
setLoading(state, isShowLoading) {
|
||||
state.isShowLoading = isShowLoading
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export default store
|
||||
34
src/utils/createRoutes.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import { asyncRoutes } from '@/router'
|
||||
|
||||
// 将菜单信息转成对应的路由信息 动态添加
|
||||
export default function createRoutes(data) {
|
||||
const result = []
|
||||
const children = []
|
||||
|
||||
result.push({
|
||||
path: '/',
|
||||
component: () => import('../components/Index.vue'),
|
||||
children,
|
||||
})
|
||||
|
||||
data.forEach(item => {
|
||||
generateRoutes(children, item)
|
||||
})
|
||||
|
||||
// 最后添加404页面 否则会在登陆成功后跳到404页面
|
||||
result.push(
|
||||
{ path: '*', redirect: '/404' },
|
||||
)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
function generateRoutes(children, item) {
|
||||
if (item.name) {
|
||||
if (asyncRoutes[item.name]) children.push(asyncRoutes[item.name])
|
||||
} else if (item.children) {
|
||||
item.children.forEach(e => {
|
||||
generateRoutes(children, e)
|
||||
})
|
||||
}
|
||||
}
|
||||
16
src/utils/index.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import { resetRouter } from '@/router'
|
||||
|
||||
export function resetTokenAndClearUser() {
|
||||
// 退出登陆 清除用户资料
|
||||
localStorage.setItem('token', '')
|
||||
localStorage.setItem('userImg', '')
|
||||
localStorage.setItem('userName', '')
|
||||
// 重设路由
|
||||
resetRouter()
|
||||
}
|
||||
|
||||
export const defaultDocumentTitle = '爱京科技'
|
||||
export function getDocumentTitle(pageTitle) {
|
||||
if (pageTitle) return `${defaultDocumentTitle} - ${pageTitle}`
|
||||
return `${defaultDocumentTitle}`
|
||||
}
|
||||
19
src/utils/loading.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import store from '@/store'
|
||||
|
||||
let loadingCounter = 0
|
||||
|
||||
export function showLoading() {
|
||||
if (loadingCounter === 0) {
|
||||
store.commit('setLoading', true)
|
||||
}
|
||||
|
||||
loadingCounter++
|
||||
}
|
||||
|
||||
export function closeLoading() {
|
||||
loadingCounter--
|
||||
if (loadingCounter <= 0) {
|
||||
loadingCounter = 0
|
||||
store.commit('setLoading', false)
|
||||
}
|
||||
}
|
||||
56
src/utils/request.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import axios from 'axios'
|
||||
import { Message } from 'view-design'
|
||||
import router from '@/router'
|
||||
import { showLoading, closeLoading } from '@/utils/loading'
|
||||
import { resetTokenAndClearUser } from '@/utils'
|
||||
|
||||
const service = axios.create({
|
||||
baseURL: '/chargingapi/',
|
||||
timeout: 60000,
|
||||
})
|
||||
|
||||
service.interceptors.request.use(config => {
|
||||
showLoading()
|
||||
if (localStorage.getItem('token')) {
|
||||
config.headers.Authorization = localStorage.getItem('token')
|
||||
}
|
||||
|
||||
return config
|
||||
}, (error) => Promise.reject(error))
|
||||
|
||||
service.interceptors.response.use(response => {
|
||||
closeLoading()
|
||||
const res = response.data
|
||||
// 这里是接口处理的一个示范,可以根据自己的项目需求更改
|
||||
// 错误处理
|
||||
if (res.code != 0 && res.msg) {
|
||||
Message.error({
|
||||
content: res.msg,
|
||||
})
|
||||
|
||||
// token 无效,清空路由,退出登录
|
||||
if (res.code == 2) {
|
||||
resetTokenAndClearUser()
|
||||
router.push('login')
|
||||
}
|
||||
|
||||
return Promise.reject()
|
||||
}
|
||||
// 如果接口正常,直接返回数据
|
||||
return res
|
||||
}, (error) => {
|
||||
closeLoading()
|
||||
if (error.name == 'Error') {
|
||||
Message.error({
|
||||
content: error.msg,
|
||||
})
|
||||
} else {
|
||||
Message.error({
|
||||
content: error.response.data.data || error.message,
|
||||
})
|
||||
}
|
||||
|
||||
return Promise.reject(error)
|
||||
})
|
||||
|
||||
export default service
|
||||
41
src/views/Home.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div class="home-container">
|
||||
<div class="home-content">
|
||||
<Button @click="getUserData">ajax 测试</Button>
|
||||
|
||||
<Input :rows="30" style="margin-top: 20px" v-model="userInfo" type="textarea" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { fetchUserData } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'home',
|
||||
data() {
|
||||
return {
|
||||
userInfo: '',
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getUserData() {
|
||||
fetchUserData().then(res => {
|
||||
this.userInfo = JSON.stringify(res, null, 4)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.home-container {
|
||||
padding: 10px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
.home-content {
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
86
src/views/Msg.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
|
||||
<div>
|
||||
<div>按钮</div>
|
||||
<Space direction="vertical">
|
||||
<Space wrap>
|
||||
<Button>Default</Button>
|
||||
<Button type="primary">Primary</Button>
|
||||
<Button type="dashed">Dashed</Button>
|
||||
<Button type="text">Text</Button>
|
||||
</Space>
|
||||
<Space wrap>
|
||||
<Button type="info">Info</Button>
|
||||
<Button type="success">Success</Button>
|
||||
<Button type="warning">Warning</Button>
|
||||
<Button type="error">Error</Button>
|
||||
</Space>
|
||||
</Space>
|
||||
<div>图标</div>
|
||||
<Icon type="ios-checkmark" />
|
||||
<div>
|
||||
<Title>h1. View Design</Title>
|
||||
<Title :level="2">h2. View Design</Title>
|
||||
<Title :level="3">h3. View Design</Title>
|
||||
<Title :level="4">h4. View Design</Title>
|
||||
<Title :level="5">h5. View Design</Title>
|
||||
</div>
|
||||
<div>分页</div>
|
||||
<Table border :columns="columns" :data="data"></Table>
|
||||
<Page :total="100" show-sizer />
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'msg',
|
||||
data() {
|
||||
return {
|
||||
columns: [
|
||||
{
|
||||
title: 'Name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: 'Age',
|
||||
key: 'age',
|
||||
},
|
||||
{
|
||||
title: 'Address',
|
||||
key: 'address',
|
||||
},
|
||||
],
|
||||
data: [
|
||||
{
|
||||
name: 'John Brown',
|
||||
age: 18,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
date: '2016-10-03',
|
||||
},
|
||||
{
|
||||
name: 'Jim Green',
|
||||
age: 24,
|
||||
address: 'London No. 1 Lake Park',
|
||||
date: '2016-10-01',
|
||||
},
|
||||
{
|
||||
name: 'Joe Black',
|
||||
age: 30,
|
||||
address: 'Sydney No. 1 Lake Park',
|
||||
date: '2016-10-02',
|
||||
},
|
||||
{
|
||||
name: 'Jon Snow',
|
||||
age: 26,
|
||||
address: 'Ottawa No. 2 Lake Park',
|
||||
date: '2016-10-04',
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
23
src/views/Other.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div>
|
||||
单独的路由
|
||||
<div>
|
||||
<Button @click="reback" type="primary" style="margin-left: 100px">返回</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'other',
|
||||
methods: {
|
||||
reback() {
|
||||
this.$router.back()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
21
src/views/Password.vue
Normal file
@@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<div>
|
||||
修改密码
|
||||
<input type="text">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'password',
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
284
src/views/T1.vue
Normal file
@@ -0,0 +1,284 @@
|
||||
<template>
|
||||
<div style="padding: 10px">
|
||||
<div style="background: #fff; border-radius: 8px; padding: 20px;">
|
||||
<div class="query-c">
|
||||
查询:
|
||||
<Input search placeholder="请输入查询内容" style="width: auto" />
|
||||
</div>
|
||||
<br>
|
||||
<Table max-height="670" border stripe :columns="columns1" :data="data1"></Table>
|
||||
<br>
|
||||
<Page :total="100" show-sizer show-elevator/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 't1',
|
||||
data() {
|
||||
return {
|
||||
columns1: [
|
||||
{
|
||||
title: 'Name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: 'Age',
|
||||
key: 'age',
|
||||
},
|
||||
{
|
||||
title: 'Address',
|
||||
key: 'address',
|
||||
},
|
||||
],
|
||||
data1: [
|
||||
{
|
||||
name: 'John Brown',
|
||||
age: 20,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
date: '2016-10-03',
|
||||
},
|
||||
{
|
||||
name: 'Jim Green',
|
||||
age: 24,
|
||||
address: 'London No. 1 Lake Park',
|
||||
date: '2016-10-01',
|
||||
},
|
||||
{
|
||||
name: 'Joe Black',
|
||||
age: 30,
|
||||
address: 'Sydney No. 1 Lake Park',
|
||||
date: '2016-10-02',
|
||||
},
|
||||
{
|
||||
name: 'Jon Snow',
|
||||
age: 26,
|
||||
address: 'Ottawa No. 2 Lake Park',
|
||||
date: '2016-10-04',
|
||||
},
|
||||
{
|
||||
name: 'John Brown',
|
||||
age: 18,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
date: '2016-10-03',
|
||||
},
|
||||
{
|
||||
name: 'Jim Green',
|
||||
age: 24,
|
||||
address: 'London No. 1 Lake Park',
|
||||
date: '2016-10-01',
|
||||
},
|
||||
{
|
||||
name: 'Joe Black',
|
||||
age: 30,
|
||||
address: 'Sydney No. 1 Lake Park',
|
||||
date: '2016-10-02',
|
||||
},
|
||||
{
|
||||
name: 'Jon Snow',
|
||||
age: 26,
|
||||
address: 'Ottawa No. 2 Lake Park',
|
||||
date: '2016-10-04',
|
||||
},
|
||||
{
|
||||
name: 'John Brown',
|
||||
age: 18,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
date: '2016-10-03',
|
||||
},
|
||||
{
|
||||
name: 'Jim Green',
|
||||
age: 24,
|
||||
address: 'London No. 1 Lake Park',
|
||||
date: '2016-10-01',
|
||||
},
|
||||
{
|
||||
name: 'Joe Black',
|
||||
age: 30,
|
||||
address: 'Sydney No. 1 Lake Park',
|
||||
date: '2016-10-02',
|
||||
},
|
||||
{
|
||||
name: 'Jon Snow',
|
||||
age: 26,
|
||||
address: 'Ottawa No. 2 Lake Park',
|
||||
date: '2016-10-04',
|
||||
},
|
||||
{
|
||||
name: 'John Brown',
|
||||
age: 18,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
date: '2016-10-03',
|
||||
},
|
||||
{
|
||||
name: 'Jim Green',
|
||||
age: 24,
|
||||
address: 'London No. 1 Lake Park',
|
||||
date: '2016-10-01',
|
||||
},
|
||||
{
|
||||
name: 'Joe Black',
|
||||
age: 30,
|
||||
address: 'Sydney No. 1 Lake Park',
|
||||
date: '2016-10-02',
|
||||
},
|
||||
{
|
||||
name: 'Jon Snow',
|
||||
age: 26,
|
||||
address: 'Ottawa No. 2 Lake Park',
|
||||
date: '2016-10-04',
|
||||
},
|
||||
{
|
||||
name: 'John Brown',
|
||||
age: 18,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
date: '2016-10-03',
|
||||
},
|
||||
{
|
||||
name: 'Jim Green',
|
||||
age: 24,
|
||||
address: 'London No. 1 Lake Park',
|
||||
date: '2016-10-01',
|
||||
},
|
||||
{
|
||||
name: 'Joe Black',
|
||||
age: 30,
|
||||
address: 'Sydney No. 1 Lake Park',
|
||||
date: '2016-10-02',
|
||||
},
|
||||
{
|
||||
name: 'Jon Snow',
|
||||
age: 26,
|
||||
address: 'Ottawa No. 2 Lake Park',
|
||||
date: '2016-10-04',
|
||||
},
|
||||
{
|
||||
name: 'John Brown',
|
||||
age: 18,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
date: '2016-10-03',
|
||||
},
|
||||
{
|
||||
name: 'Jim Green',
|
||||
age: 24,
|
||||
address: 'London No. 1 Lake Park',
|
||||
date: '2016-10-01',
|
||||
},
|
||||
{
|
||||
name: 'Joe Black',
|
||||
age: 30,
|
||||
address: 'Sydney No. 1 Lake Park',
|
||||
date: '2016-10-02',
|
||||
},
|
||||
{
|
||||
name: 'Jon Snow',
|
||||
age: 26,
|
||||
address: 'Ottawa No. 2 Lake Park',
|
||||
date: '2016-10-04',
|
||||
},
|
||||
{
|
||||
name: 'John Brown',
|
||||
age: 18,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
date: '2016-10-03',
|
||||
},
|
||||
{
|
||||
name: 'Jim Green',
|
||||
age: 24,
|
||||
address: 'London No. 1 Lake Park',
|
||||
date: '2016-10-01',
|
||||
},
|
||||
{
|
||||
name: 'Joe Black',
|
||||
age: 30,
|
||||
address: 'Sydney No. 1 Lake Park',
|
||||
date: '2016-10-02',
|
||||
},
|
||||
{
|
||||
name: 'Jon Snow',
|
||||
age: 26,
|
||||
address: 'Ottawa No. 2 Lake Park',
|
||||
date: '2016-10-04',
|
||||
},
|
||||
{
|
||||
name: 'John Brown',
|
||||
age: 18,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
date: '2016-10-03',
|
||||
},
|
||||
{
|
||||
name: 'Jim Green',
|
||||
age: 24,
|
||||
address: 'London No. 1 Lake Park',
|
||||
date: '2016-10-01',
|
||||
},
|
||||
{
|
||||
name: 'Joe Black',
|
||||
age: 30,
|
||||
address: 'Sydney No. 1 Lake Park',
|
||||
date: '2016-10-02',
|
||||
},
|
||||
{
|
||||
name: 'Jon Snow',
|
||||
age: 26,
|
||||
address: 'Ottawa No. 2 Lake Park',
|
||||
date: '2016-10-04',
|
||||
},
|
||||
{
|
||||
name: 'John Brown',
|
||||
age: 18,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
date: '2016-10-03',
|
||||
},
|
||||
{
|
||||
name: 'Jim Green',
|
||||
age: 24,
|
||||
address: 'London No. 1 Lake Park',
|
||||
date: '2016-10-01',
|
||||
},
|
||||
{
|
||||
name: 'Joe Black',
|
||||
age: 30,
|
||||
address: 'Sydney No. 1 Lake Park',
|
||||
date: '2016-10-02',
|
||||
},
|
||||
{
|
||||
name: 'Jon Snow',
|
||||
age: 26,
|
||||
address: 'Ottawa No. 2 Lake Park',
|
||||
date: '2016-10-04',
|
||||
},
|
||||
{
|
||||
name: 'John Brown',
|
||||
age: 18,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
date: '2016-10-03',
|
||||
},
|
||||
{
|
||||
name: 'Jim Green',
|
||||
age: 24,
|
||||
address: 'London No. 1 Lake Park',
|
||||
date: '2016-10-01',
|
||||
},
|
||||
{
|
||||
name: 'Joe Black',
|
||||
age: 30,
|
||||
address: 'Sydney No. 1 Lake Park',
|
||||
date: '2016-10-02',
|
||||
},
|
||||
{
|
||||
name: 'Jon Snow',
|
||||
age: 26,
|
||||
address: 'Ottawa No. 2 Lake Park',
|
||||
date: '2016-10-04',
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
22
src/views/UserInfo.vue
Normal file
@@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div>
|
||||
基本资料
|
||||
<input type="text">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'userinfo',
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
261
src/views/charging_pile/Fault.vue
Normal file
@@ -0,0 +1,261 @@
|
||||
<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" v-model="formInline.user" placeholder="" />
|
||||
</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="show(index)">编辑</Button>
|
||||
<Button type="error" size="small" @click="remove(index)">删除</Button>
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" />
|
||||
</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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { GetChargeZ } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [
|
||||
{
|
||||
title: '站点名称',
|
||||
key: 'charge_station_id',
|
||||
},
|
||||
{
|
||||
title: '充电桩编号',
|
||||
key: 'ConnectorID',
|
||||
},
|
||||
{
|
||||
title: '充电桩类型',
|
||||
key: 'EquipmentType',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
formValidate: {
|
||||
name: '',
|
||||
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' },
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
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 GetChargeZ({ page: 1, status: 'fault' }).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$Message.success('Success!')
|
||||
} else {
|
||||
this.$Message.error('Fail!')
|
||||
}
|
||||
})
|
||||
},
|
||||
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')
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
265
src/views/charging_pile/Pile.vue
Normal file
@@ -0,0 +1,265 @@
|
||||
<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" v-model="formInline.user" placeholder="" />
|
||||
</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="show(index)">编辑</Button>
|
||||
<Button type="error" size="small" @click="remove(index)">删除</Button>
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" />
|
||||
</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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { GetChargeZ } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [
|
||||
{
|
||||
title: '站点名称',
|
||||
key: 'charge_station_name',
|
||||
},
|
||||
{
|
||||
title: '充电桩编号',
|
||||
key: 'ConnectorID',
|
||||
},
|
||||
{
|
||||
title: '充电桩状态',
|
||||
key: 'status_text',
|
||||
},
|
||||
{
|
||||
title: '位号',
|
||||
key: 'no',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
formValidate: {
|
||||
name: '',
|
||||
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' },
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
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 GetChargeZ({ page: 1 }).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$Message.success('Success!')
|
||||
} else {
|
||||
this.$Message.error('Fail!')
|
||||
}
|
||||
})
|
||||
},
|
||||
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')
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
262
src/views/charging_pile/Price.vue
Normal file
@@ -0,0 +1,262 @@
|
||||
<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" v-model="formInline.user" placeholder="" />
|
||||
</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="show(index)">编辑</Button>
|
||||
<Button type="error" size="small" @click="remove(index)">删除</Button>
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" />
|
||||
</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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { GetPerPrice } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [
|
||||
{
|
||||
title: '站点名称',
|
||||
key: 'charge_station_name',
|
||||
},
|
||||
{
|
||||
title: '电费',
|
||||
key: 'ElectricityFee',
|
||||
},
|
||||
{
|
||||
title: '服务费',
|
||||
key: 'ServiceFee',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
formValidate: {
|
||||
name: '',
|
||||
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' },
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
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 GetPerPrice({ page: 1 }).then((res) => {
|
||||
this.total = res.total
|
||||
|
||||
this.data = res.yuan
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$Message.success('Success!')
|
||||
} else {
|
||||
this.$Message.error('Fail!')
|
||||
}
|
||||
})
|
||||
},
|
||||
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')
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
273
src/views/charging_pile/Station.vue
Normal file
@@ -0,0 +1,273 @@
|
||||
<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" v-model="formInline.user" placeholder="" />
|
||||
</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="show(index)">编辑</Button>
|
||||
<Button type="error" size="small" @click="remove(index)">删除</Button>
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" />
|
||||
</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_name">
|
||||
<Input v-model="formValidate.charge_station_name" placeholder="站点名称" />
|
||||
</FormItem>
|
||||
<FormItem label="站点编号" prop="charge_station_number">
|
||||
<Input v-model="formValidate.charge_station_number" placeholder="站点编号" />
|
||||
</FormItem>
|
||||
<FormItem label="城市" 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="地址" prop="address">
|
||||
<Input v-model="formValidate.address" placeholder="地址" />
|
||||
</FormItem>
|
||||
<FormItem label="联系电话" prop="charge_station_phone">
|
||||
<Input v-model="formValidate.charge_station_phone" placeholder="联系电话" />
|
||||
</FormItem>
|
||||
<FormItem label="精度" prop="longitude">
|
||||
<Input v-model="formValidate.longitude" placeholder="精度" />
|
||||
</FormItem>
|
||||
<FormItem label="纬度" prop="latitude">
|
||||
<Input v-model="formValidate.latitude" placeholder="纬度" />
|
||||
</FormItem>
|
||||
<FormItem label="电费" prop="ElectricityFee">
|
||||
<Input v-model="formValidate.ElectricityFee" placeholder="电费" />
|
||||
</FormItem>
|
||||
<FormItem label="服务费" prop="ServiceFee">
|
||||
<Input v-model="formValidate.ServiceFee" placeholder="服务费" />
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="cancel">取消</Button>
|
||||
<Button type="primary" @click="ok">确定</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
GetPosition,
|
||||
} from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [{
|
||||
title: '站点名称',
|
||||
key: 'charge_station_name',
|
||||
},
|
||||
{
|
||||
title: '站点编号',
|
||||
key: 'charge_station_number',
|
||||
},
|
||||
{
|
||||
title: '站点地址',
|
||||
key: 'address',
|
||||
},
|
||||
{
|
||||
title: '精度',
|
||||
key: 'longitude',
|
||||
},
|
||||
{
|
||||
title: '纬度',
|
||||
key: 'latitude',
|
||||
},
|
||||
{
|
||||
title: '电价',
|
||||
key: 'ElectricityFee',
|
||||
},
|
||||
{
|
||||
title: '服务费',
|
||||
key: 'ServiceFee',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
formValidate: {
|
||||
charge_station_name: '',
|
||||
charge_station_number: '',
|
||||
city: '',
|
||||
charge_station_phone: '',
|
||||
longitude: [],
|
||||
latitude: '',
|
||||
ElectricityFee: '',
|
||||
ServiceFee: '',
|
||||
},
|
||||
ruleValidate: {
|
||||
charge_station_name: [{
|
||||
required: true,
|
||||
message: 'The name cannot be empty',
|
||||
trigger: 'blur',
|
||||
}],
|
||||
charge_station_number: [{
|
||||
required: true,
|
||||
message: 'Mailbox cannot be empty',
|
||||
trigger: 'blur',
|
||||
}],
|
||||
city: [{
|
||||
required: true,
|
||||
message: 'Please select the city',
|
||||
trigger: 'change',
|
||||
}],
|
||||
address: [{
|
||||
required: true,
|
||||
message: 'Please select gender',
|
||||
trigger: 'change',
|
||||
}],
|
||||
longitude: [{
|
||||
required: true,
|
||||
message: 'Please select the date',
|
||||
trigger: 'change',
|
||||
}],
|
||||
latitude: [{
|
||||
required: true,
|
||||
message: 'Please select time',
|
||||
trigger: 'change',
|
||||
}],
|
||||
},
|
||||
}
|
||||
},
|
||||
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 GetPosition({
|
||||
page: 1,
|
||||
}).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$Message.success('Success!')
|
||||
} else {
|
||||
this.$Message.error('Fail!')
|
||||
}
|
||||
})
|
||||
},
|
||||
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')
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
702
src/views/customer_center/CorporateClient.vue
Normal file
@@ -0,0 +1,702 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="search-area">
|
||||
<Form ref="formInline" inline :label-width="120" :model="formInline" :rules="ruleInline">
|
||||
<FormItem prop="name" label="企业名称:">
|
||||
<Input type="text" v-model="formInline.name" placeholder="" />
|
||||
</FormItem>
|
||||
<FormItem prop="credit_code" label="企业代码:">
|
||||
<Input type="text" v-model="formInline.credit_code" placeholder="" />
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
||||
<Button type="primary" @click="resetSubmit('formInline')" style="margin-left: 8px">重置</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_user_list(row.id)">员工账号</Button>
|
||||
<Button type="primary" size="small" style="margin-right: 5px" @click="show_car_list(row.id)">企业车辆</Button>
|
||||
<Button type="primary" size="small" style="margin-right: 5px" @click="show_rechage_list(row.id)">充值记录</Button>
|
||||
<Button type="primary" size="small" style="margin-right: 5px" @click="show_chage_list(row.id)">充电记录</Button>
|
||||
<Button type="primary" size="small" style="margin-right: 5px" @click="show(row.id)">编辑</Button>
|
||||
<Button type="error" size="small" @click="remove(row.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="formValidate.id ? '编辑企业' : '新增企业'" :mask-closable="false">
|
||||
<Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="80">
|
||||
<FormItem label="企业名称" prop="name">
|
||||
<Input v-model="formValidate.name" placeholder="请输入企业名称" />
|
||||
</FormItem>
|
||||
<FormItem label="企业统一社会信用代码" prop="credit_code">
|
||||
<Input v-model="formValidate.credit_code" placeholder="请输入企业统一社会信用代码" />
|
||||
</FormItem>
|
||||
<div style="display: flex;">
|
||||
<FormItem label="联系人" prop="username">
|
||||
<Input v-model="formValidate.username" placeholder="请输入联系人" />
|
||||
</FormItem>
|
||||
<FormItem label="联系电话" prop="phone">
|
||||
<Input v-model="formValidate.phone" placeholder="请输入联系电话" />
|
||||
</FormItem>
|
||||
</div>
|
||||
<FormItem label="折扣" prop="discount">
|
||||
<RadioGroup v-model="formValidate.discount">
|
||||
<Radio label="1">电费和服务费</Radio>
|
||||
<Radio label="2">仅服务费</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="折扣范围" prop="range">
|
||||
<Input v-model="formValidate.range" placeholder="请输入折扣">
|
||||
<template #suffix>
|
||||
<div style="line-height:32px;border-left:1px solid #c3b8b8;">%</div>
|
||||
</template>
|
||||
</Input>
|
||||
</FormItem>
|
||||
<FormItem label="扣款账户" prop="account">
|
||||
<RadioGroup v-model="formValidate.account">
|
||||
<Radio label="1">企业账户</Radio>
|
||||
<Radio label="2">个人钱包</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="备注" prop="marks">
|
||||
<Input v-model="formValidate.marks" type="textarea" :autosize="{ minRows: 2, maxRows: 5 }"
|
||||
placeholder="请输入备注信息..." />
|
||||
</FormItem>
|
||||
</Form>
|
||||
<!--解决弹框自动关闭-->
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="cancel">取消</Button>
|
||||
<Button type="primary" @click="ok">确定</Button>
|
||||
</div>
|
||||
|
||||
</Modal>
|
||||
|
||||
<!-- 员工账号 -->
|
||||
<Modal v-model="user_list_show_modal" title="员工账号" :mask-closable="false" :fullscreen="true"
|
||||
:footer-hide="true">
|
||||
<div class="action-btn">
|
||||
<Button type="primary" @click="addUser">添加</Button>
|
||||
</div>
|
||||
<div class="table-container">
|
||||
<Table border :columns="user_columns" stripe :height="tableHeight" :data="user_data">
|
||||
<template #group_id="{ row }">
|
||||
<strong v-if="row.group_id == 1">管理员</strong>
|
||||
</template>
|
||||
<template #action="{ row, index }">
|
||||
<Button type="primary" size="small" style="margin-right: 5px"
|
||||
@click="showUser(row.id)">编辑</Button>
|
||||
<Button type="error" size="small" @click="removeUser(row.id)">删除</Button>
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="user_total" show-total show-sizer class="page" @on-change="onChangeUserPage"
|
||||
@on-page-size-change="onChangeUserPageSize" />
|
||||
</div>
|
||||
</Modal>
|
||||
<!-- 员工账号 添加、编辑 -->
|
||||
<Modal v-model="user_show_modal" :title="formUserValidate.id ? '编辑员工账号' : '新增员工账号'" :mask-closable="false">
|
||||
<Form ref="formUserValidate" :model="formUserValidate" :rules="ruleUserValidate" :label-width="80">
|
||||
<FormItem label="联系电话" prop="phone">
|
||||
<Input v-model="formUserValidate.phone" placeholder="请输入联系电话" />
|
||||
</FormItem>
|
||||
<FormItem label="管理员" prop="group_id">
|
||||
<RadioGroup v-model="formUserValidate.group_id">
|
||||
<Radio label="1">是</Radio>
|
||||
<Radio label="0">否</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<!--解决弹框自动关闭-->
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="user_cancel">取消</Button>
|
||||
<Button type="primary" @click="user_ok">确定</Button>
|
||||
</div>
|
||||
|
||||
</Modal>
|
||||
|
||||
<!-- 企业车辆 -->
|
||||
<Modal v-model="car_list_show_modal" title="企业车辆" :mask-closable="false" :fullscreen="true"
|
||||
:footer-hide="true">
|
||||
<div class="action-btn">
|
||||
<Button type="primary" @click="addCar">添加</Button>
|
||||
</div>
|
||||
<div class="table-container">
|
||||
<Table border :columns="car_columns" stripe :height="tableHeight" :data="car_data">
|
||||
<template #vin_type="{ row }">
|
||||
{{ row.vin_type == 2 ? '关闭' : '开启' }}
|
||||
</template>
|
||||
<template #action="{ row, index }">
|
||||
<Button type="primary" size="small" style="margin-right: 5px"
|
||||
@click="showCar(row.id)">编辑</Button>
|
||||
<Button type="error" size="small" @click="removeCar(row.id)">删除</Button>
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="user_total" show-total show-sizer class="page" @on-change="onChangeUserPage"
|
||||
@on-page-size-change="onChangeUserPageSize" />
|
||||
</div>
|
||||
</Modal>
|
||||
<!-- 企业车辆 添加、编辑 -->
|
||||
<Modal v-model="car_show_modal" :title="formCarValidate.id ? '编辑车辆信息' : '新增企业车辆'" :mask-closable="false">
|
||||
<Form ref="formCarValidate" :model="formCarValidate" :rules="ruleCarValidate" :label-width="80">
|
||||
<FormItem label="车辆" prop="car_number">
|
||||
<Input v-model="formCarValidate.car_number" placeholder="请输入车辆车牌号" />
|
||||
</FormItem>
|
||||
<FormItem label="VIN码" prop="car_vin">
|
||||
<Input v-model="formCarValidate.car_vin" placeholder="请输入VIN码" />
|
||||
</FormItem>
|
||||
<FormItem label="内部编号" prop="car_no">
|
||||
<Input v-model="formCarValidate.car_no" placeholder="请输入内部编号" />
|
||||
</FormItem>
|
||||
<FormItem label="车辆所有人" prop="car_user">
|
||||
<Input v-model="formCarValidate.car_user" placeholder="请输入车辆所有人" />
|
||||
</FormItem>
|
||||
<FormItem label="VIN充电类型" prop="vin_type">
|
||||
<RadioGroup v-model="formCarValidate.vin_type">
|
||||
<Radio label="1">开启</Radio>
|
||||
<Radio label="2">关闭</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<!--解决弹框自动关闭-->
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="car_cancel">取消</Button>
|
||||
<Button type="primary" @click="car_ok">确定</Button>
|
||||
</div>
|
||||
|
||||
</Modal>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getEnterpriseList, getEnterpriseSave, getEnterpriseDelete, getEnterpriseRead, getEnterpriseUpdate,
|
||||
getEnterpriseUserList, getEnterpriseUserUpdate, getEnterpriseUserSave, getEnterpriseUserRead, getEnterpriseUserDelete,
|
||||
getEnterpriseCarList, getEnterpriseCarUpdate, getEnterpriseCarSave, getEnterpriseCarRead, getEnterpriseCarDelete } from '@/api'
|
||||
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
total: 100,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
name: '',
|
||||
credit_code: '',
|
||||
},
|
||||
ruleInline: {
|
||||
},
|
||||
columns: [{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: '企业名称',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '企业统一社会信用代码',
|
||||
key: 'credit_code',
|
||||
},
|
||||
{
|
||||
title: '账户余额',
|
||||
key: 'money',
|
||||
},
|
||||
{
|
||||
title: '联系人',
|
||||
key: 'username',
|
||||
},
|
||||
{
|
||||
title: '联系电话',
|
||||
key: 'phone',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 300,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
formValidate: {
|
||||
id: null,
|
||||
name: '',
|
||||
credit_code: '',
|
||||
username: '',
|
||||
phone: '',
|
||||
discount: '1',
|
||||
range: '',
|
||||
account: '1',
|
||||
marks: '',
|
||||
},
|
||||
ruleValidate: {
|
||||
name: [{
|
||||
required: true,
|
||||
message: '请输入企业名称',
|
||||
trigger: 'blur',
|
||||
}],
|
||||
credit_code: [{
|
||||
required: true,
|
||||
message: '请输入企业统一社会信用代码',
|
||||
trigger: 'blur',
|
||||
}],
|
||||
username: [{
|
||||
required: true,
|
||||
message: '请输入联系人',
|
||||
trigger: 'change',
|
||||
}],
|
||||
phone: [{
|
||||
required: true,
|
||||
message: '请输入联系电话',
|
||||
trigger: 'change',
|
||||
}],
|
||||
},
|
||||
// 用户
|
||||
user_list_show_modal: false,
|
||||
user_show_modal: false,
|
||||
user_columns: [{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: '用户',
|
||||
key: 'phone',
|
||||
},
|
||||
{
|
||||
title: '管理员',
|
||||
slot: 'group_id',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 300,
|
||||
align: 'center',
|
||||
}],
|
||||
formUserValidate: {
|
||||
id: null,
|
||||
phone: '',
|
||||
group_id: '0',
|
||||
enterprise_id: '',
|
||||
},
|
||||
ruleUserValidate: {
|
||||
phone: [{
|
||||
required: true,
|
||||
message: '请输入联系电话',
|
||||
trigger: 'blur',
|
||||
}],
|
||||
},
|
||||
user_data: [],
|
||||
user_total: 0,
|
||||
userPage: 1,
|
||||
userPageSize: 10,
|
||||
// 车辆
|
||||
car_list_show_modal: false,
|
||||
car_show_modal: false,
|
||||
car_columns: [{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: '车辆',
|
||||
key: 'car_number',
|
||||
},
|
||||
{
|
||||
title: 'VIN码',
|
||||
key: 'car_vin',
|
||||
},
|
||||
{
|
||||
title: '内部编号',
|
||||
key: 'car_no',
|
||||
},
|
||||
{
|
||||
title: '车辆所有人',
|
||||
key: 'car_user',
|
||||
},
|
||||
{
|
||||
title: 'VIN充电类型',
|
||||
slot: 'vin_type',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 300,
|
||||
align: 'center',
|
||||
}],
|
||||
formCarValidate: {
|
||||
id: null,
|
||||
car_number: '',
|
||||
car_vin: '',
|
||||
enterprise_id: '',
|
||||
car_no: '',
|
||||
car_user: '',
|
||||
vin_type: '1',
|
||||
},
|
||||
ruleCarValidate: {
|
||||
car_number: [{
|
||||
required: true,
|
||||
message: '请输入车辆车牌号',
|
||||
trigger: 'blur',
|
||||
}],
|
||||
car_vin: [{
|
||||
required: true,
|
||||
message: '请输入车辆VIN码',
|
||||
trigger: 'blur',
|
||||
}],
|
||||
},
|
||||
car_data: [],
|
||||
car_total: 0,
|
||||
carPage: 1,
|
||||
carPageSize: 10,
|
||||
}
|
||||
},
|
||||
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 getEnterpriseList({
|
||||
page: this.page,
|
||||
pageSize: this.pageSize,
|
||||
...this.formInline,
|
||||
}).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
})
|
||||
},
|
||||
handleSubmit() {
|
||||
this.getList()
|
||||
},
|
||||
resetSubmit() {
|
||||
this.$refs.formInline.resetFields()
|
||||
this.getList()
|
||||
},
|
||||
// 详情
|
||||
async show(id) {
|
||||
await getEnterpriseRead({ id }).then(res => {
|
||||
this.formValidate = { ...res.data }
|
||||
this.formValidate.discount = String(this.formValidate.discount)
|
||||
this.formValidate.account = String(this.formValidate.account)
|
||||
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 getEnterpriseDelete({ id }).then(res => {
|
||||
this.$Message.success(res.msg)
|
||||
this.getList()
|
||||
})
|
||||
},
|
||||
// 新增
|
||||
async ok() {
|
||||
const valid = await new Promise(resolve => this.$refs.formValidate.validate(resolve))
|
||||
|
||||
if (!valid) {
|
||||
this.$Message.error('请正确填写表单')
|
||||
return
|
||||
}
|
||||
if (this.formValidate.id) {
|
||||
await getEnterpriseUpdate(this.formValidate).then(res => {
|
||||
this.$Message.success(res.msg)
|
||||
this.getList()
|
||||
this.cancel()
|
||||
})
|
||||
} else {
|
||||
await getEnterpriseSave(this.formValidate).then(res => {
|
||||
this.$Message.success(res.msg)
|
||||
this.getList()
|
||||
this.cancel()
|
||||
})
|
||||
}
|
||||
},
|
||||
add() {
|
||||
this.show_modal = true
|
||||
this.$refs.formValidate.resetFields()
|
||||
this.formValidate.id = ''
|
||||
},
|
||||
cancel() {
|
||||
this.$refs.formValidate.resetFields()
|
||||
this.show_modal = false
|
||||
},
|
||||
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()
|
||||
}
|
||||
},
|
||||
// 员工账号列表
|
||||
show_user_list(id) {
|
||||
this.user_list_show_modal = true
|
||||
this.formUserValidate.enterprise_id = id
|
||||
this.getEnterpriseUserList()
|
||||
},
|
||||
async getEnterpriseUserList() {
|
||||
await getEnterpriseUserList({
|
||||
enterprise_id: this.formUserValidate.enterprise_id,
|
||||
page: this.userPage,
|
||||
pageSize: this.userPageSize,
|
||||
}).then((res) => {
|
||||
this.user_data = res.data
|
||||
this.user_total = res.total
|
||||
})
|
||||
},
|
||||
// 添加员工账号 弹窗显示
|
||||
addUser() {
|
||||
this.$refs.formUserValidate.resetFields()
|
||||
this.formUserValidate.id = ''
|
||||
this.user_show_modal = true
|
||||
},
|
||||
// 关闭新增弹窗
|
||||
user_cancel() {
|
||||
this.user_show_modal = false
|
||||
this.$refs.formUserValidate.resetFields()
|
||||
},
|
||||
// 提交员工账号数据
|
||||
async user_ok() {
|
||||
const valid = await new Promise(resolve => this.$refs.formUserValidate.validate(resolve))
|
||||
|
||||
if (!valid) {
|
||||
this.$Message.error('请正确填写表单')
|
||||
return
|
||||
}
|
||||
if (this.formUserValidate.id) {
|
||||
await getEnterpriseUserUpdate(this.formUserValidate).then(res => {
|
||||
this.$Message.success(res.msg)
|
||||
this.getEnterpriseUserList()
|
||||
this.user_cancel()
|
||||
})
|
||||
} else {
|
||||
await getEnterpriseUserSave(this.formUserValidate).then(res => {
|
||||
this.$Message.success(res.msg)
|
||||
this.getEnterpriseUserList()
|
||||
this.user_cancel()
|
||||
})
|
||||
}
|
||||
},
|
||||
// 编辑员工账号信息
|
||||
async showUser(id) {
|
||||
await getEnterpriseUserRead({ id }).then(res => {
|
||||
this.formUserValidate = { ...res.data }
|
||||
this.formUserValidate.group_id = String(this.formUserValidate.group_id)
|
||||
this.user_show_modal = true
|
||||
})
|
||||
},
|
||||
// 删除员工账号信息
|
||||
async removeUser(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 getEnterpriseUserDelete({ id }).then(res => {
|
||||
this.$Message.success(res.msg)
|
||||
this.getEnterpriseUserList()
|
||||
})
|
||||
},
|
||||
onChangeUserPage(e) {
|
||||
if (this.userPage != e) {
|
||||
this.userPage = e
|
||||
this.getEnterpriseUserList()
|
||||
}
|
||||
},
|
||||
onChangeUserPageSize(e) {
|
||||
if (this.userPageSize != e) {
|
||||
this.userPage = 1
|
||||
this.userPageSize = e
|
||||
this.getEnterpriseUserList()
|
||||
}
|
||||
},
|
||||
// 企业车辆列表
|
||||
show_car_list(id) {
|
||||
this.car_list_show_modal = true
|
||||
this.formCarValidate.enterprise_id = id
|
||||
this.getEnterpriseCarList()
|
||||
},
|
||||
async getEnterpriseCarList() {
|
||||
await getEnterpriseCarList({
|
||||
enterprise_id: this.formCarValidate.enterprise_id,
|
||||
page: this.carPage,
|
||||
pageSize: this.carPageSize,
|
||||
}).then((res) => {
|
||||
this.car_data = res.data
|
||||
this.car_total = res.total
|
||||
})
|
||||
},
|
||||
// 添加车辆信息 弹窗显示
|
||||
addCar() {
|
||||
this.$refs.formCarValidate.resetFields()
|
||||
this.formCarValidate.id = ''
|
||||
this.car_show_modal = true
|
||||
},
|
||||
// 关闭新增弹窗
|
||||
car_cancel() {
|
||||
this.car_show_modal = false
|
||||
this.$refs.formCarValidate.resetFields()
|
||||
},
|
||||
// 提交车辆数据
|
||||
async car_ok() {
|
||||
const valid = await new Promise(resolve => this.$refs.formCarValidate.validate(resolve))
|
||||
|
||||
if (!valid) {
|
||||
this.$Message.error('请正确填写表单')
|
||||
return
|
||||
}
|
||||
if (this.formCarValidate.id) {
|
||||
await getEnterpriseCarUpdate(this.formCarValidate).then(res => {
|
||||
this.$Message.success(res.msg)
|
||||
this.getEnterpriseCarList()
|
||||
this.car_cancel()
|
||||
})
|
||||
} else {
|
||||
await getEnterpriseCarSave(this.formCarValidate).then(res => {
|
||||
this.$Message.success(res.msg)
|
||||
this.getEnterpriseCarList()
|
||||
this.car_cancel()
|
||||
})
|
||||
}
|
||||
},
|
||||
// 编辑车辆信息
|
||||
async showCar(id) {
|
||||
await getEnterpriseCarRead({ id }).then(res => {
|
||||
this.formCarValidate = { ...res.data }
|
||||
this.formCarValidate.vin_type = String(this.formCarValidate.vin_type)
|
||||
this.car_show_modal = true
|
||||
})
|
||||
},
|
||||
// 删除车辆信息
|
||||
async removeCar(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 getEnterpriseCarDelete({ id }).then(res => {
|
||||
this.$Message.success(res.msg)
|
||||
this.getEnterpriseCarList()
|
||||
})
|
||||
},
|
||||
onChangeCarPage(e) {
|
||||
if (this.carPage != e) {
|
||||
this.carPage = e
|
||||
this.getEnterpriseCarList()
|
||||
}
|
||||
},
|
||||
onChangeCarPageSize(e) {
|
||||
if (this.carPageSize != e) {
|
||||
this.carPage = 1
|
||||
this.carPageSize = e
|
||||
this.getEnterpriseCarList()
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
273
src/views/customer_center/WxUser.vue
Normal file
@@ -0,0 +1,273 @@
|
||||
<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" v-model="formInline.user" placeholder="" />
|
||||
</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="show(index)">编辑</Button>
|
||||
<Button type="error" size="small" @click="remove(index)">删除</Button>
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" />
|
||||
</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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { GetUser } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [
|
||||
{
|
||||
title: '区域',
|
||||
key: 'area',
|
||||
},
|
||||
{
|
||||
title: '用户名称',
|
||||
key: 'username',
|
||||
},
|
||||
{
|
||||
title: 'openid',
|
||||
key: 'openid',
|
||||
},
|
||||
{
|
||||
title: '手机号',
|
||||
key: 'phone',
|
||||
},
|
||||
{
|
||||
title: '余额',
|
||||
key: 'account',
|
||||
},
|
||||
{
|
||||
title: '冻结余额',
|
||||
key: 'FrozenAccount',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
formValidate: {
|
||||
name: '',
|
||||
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' },
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
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: 1 }).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$Message.success('Success!')
|
||||
} else {
|
||||
this.$Message.error('Fail!')
|
||||
}
|
||||
})
|
||||
},
|
||||
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')
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
261
src/views/operations_center/activity.vue
Normal file
@@ -0,0 +1,261 @@
|
||||
<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" v-model="formInline.user" placeholder="" />
|
||||
</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="show(index)">编辑</Button>
|
||||
<Button type="error" size="small" @click="remove(index)">删除</Button>
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" />
|
||||
</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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getEventList } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [
|
||||
{
|
||||
title: '活动名称',
|
||||
key: 'title',
|
||||
},
|
||||
{
|
||||
title: '活动状态',
|
||||
key: 'statusMsg',
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'create_time',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
formValidate: {
|
||||
name: '',
|
||||
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' },
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
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 getEventList({ page: 1 }).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$Message.success('Success!')
|
||||
} else {
|
||||
this.$Message.error('Fail!')
|
||||
}
|
||||
})
|
||||
},
|
||||
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')
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
261
src/views/operations_center/coupon.vue
Normal file
@@ -0,0 +1,261 @@
|
||||
<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" v-model="formInline.user" placeholder="" />
|
||||
</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="show(index)">编辑</Button>
|
||||
<Button type="error" size="small" @click="remove(index)">删除</Button>
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" />
|
||||
</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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getEventList } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [
|
||||
{
|
||||
title: '优惠券名称',
|
||||
key: 'title',
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'statusMsg',
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'create_time',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
formValidate: {
|
||||
name: '',
|
||||
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' },
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
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 getEventList({ page: 1 }).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$Message.success('Success!')
|
||||
} else {
|
||||
this.$Message.error('Fail!')
|
||||
}
|
||||
})
|
||||
},
|
||||
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')
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
9
src/views/operations_center/invoice.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<view>safsa</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
9
src/views/operations_center/user_vip.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<view>safsa</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
201
src/views/order/charge_order.vue
Normal file
@@ -0,0 +1,201 @@
|
||||
<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" v-model="formInline.phone" placeholder="" />
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
<div class="table-container">
|
||||
<Table border :columns="columns" stripe :height="tableHeight" :data="data">
|
||||
<template #order="{ row, index }">
|
||||
订单编号: {{ row.order_number }}<br>
|
||||
开始时间: {{ row.start_time }}<br>
|
||||
结束时间: {{ row.end_time }}
|
||||
</template>
|
||||
<template #pile="{ row, index }">
|
||||
充电站名称: {{ row.charge_station_name }}<br>
|
||||
充电桩编号: {{ row.ConnectorID}}
|
||||
</template>
|
||||
<template #user="{ row, index }">
|
||||
openId: {{ row.openid }}<br>
|
||||
手机号: {{ row.phone}}<br>
|
||||
VIN: {{ row.vin }}
|
||||
</template>
|
||||
<template #power="{ row, index }">
|
||||
电量: {{ row.TotalPower }}<br>
|
||||
电费: {{ row.ElecMoney}}<br>
|
||||
服务费: {{ row.SeviceMoney }}<br>
|
||||
总计: {{ row.TotalMoney }}<br>
|
||||
</template>
|
||||
<template #type="{ row, index }">
|
||||
订单类型: {{ row.type_text }}<br>
|
||||
<div v-if="row.type == 1">
|
||||
充值金额: {{ row.WithholdingMoney }}<br>
|
||||
退还金额: {{ row.FeedbackMoney }}<br>
|
||||
{{row.is_wind == 0 ? '未结算' : '已结算'}}
|
||||
</div>
|
||||
</template>
|
||||
<template #action="{ row, index }">
|
||||
<!-- <Button type="primary" size="small" style="margin-right: 5px" @click="show(index)">详情</Button> -->
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" @on-change="onChangePage"
|
||||
@on-page-size-change="onChangePageSize"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getChargeOrder } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [
|
||||
{
|
||||
title: 'id',
|
||||
key: 'order_id',
|
||||
width: '80',
|
||||
},
|
||||
{
|
||||
title: '订单信息',
|
||||
slot: 'order',
|
||||
width: '280',
|
||||
},
|
||||
{
|
||||
title: '充电站信息',
|
||||
slot: 'pile',
|
||||
width: '240',
|
||||
},
|
||||
{
|
||||
title: '用户信息',
|
||||
slot: 'user',
|
||||
width: '310',
|
||||
},
|
||||
{
|
||||
title: '充电信息',
|
||||
slot: 'power',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '充电类型',
|
||||
slot: 'type',
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
}
|
||||
},
|
||||
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 pageHeight = 32 // 分页组件大约高度
|
||||
const margins = 40 // 上下边距总和
|
||||
this.tableHeight = window.innerHeight - searchHeight - pageHeight - margins - 130
|
||||
},
|
||||
async getList() {
|
||||
await getChargeOrder({ page: this.page, pageSize: this.pageSize, ...this.formInline }).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit() {
|
||||
this.getList()
|
||||
},
|
||||
handleReset(name) {
|
||||
this.$refs[name].resetFields()
|
||||
},
|
||||
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}`,
|
||||
})
|
||||
},
|
||||
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()
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
140
src/views/order/order_total.vue
Normal file
@@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="search-area">
|
||||
<Form ref="formInline" :model="formInline" :rules="ruleInline" inline :label-width="120">
|
||||
<FormItem prop="user" label="时间">
|
||||
<Input type="text" v-model="formInline.user" placeholder="Username"></Input>
|
||||
</FormItem>
|
||||
<FormItem prop="password" label="充电桩">
|
||||
<Input type="password" v-model="formInline.password" placeholder="Password"></Input>
|
||||
</FormItem>
|
||||
<FormItem prop="password" label="充电站">
|
||||
<Input type="password" v-model="formInline.password" placeholder="Password"></Input>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
<div id="main" ref="chartContainer" style="width: 100%; height: 400px;"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as echarts from 'echarts'
|
||||
|
||||
export default {
|
||||
name: 'Total',
|
||||
data() {
|
||||
return {
|
||||
data: [],
|
||||
chartInstance: null,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.chartInstance) {
|
||||
this.chartInstance.dispose()
|
||||
}
|
||||
window.removeEventListener('resize', this.handleResize)
|
||||
},
|
||||
methods: {
|
||||
initChart() {
|
||||
if (!this.$refs.chartContainer) return
|
||||
|
||||
// 销毁旧实例
|
||||
if (this.chartInstance) {
|
||||
this.chartInstance.dispose()
|
||||
}
|
||||
|
||||
this.chartInstance = echarts.init(this.$refs.chartContainer)
|
||||
|
||||
// 模拟数据
|
||||
const xData = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
||||
const orderData = [120, 132, 101, 134, 90, 230, 210]
|
||||
const revenueData = [220, 182, 191, 234, 290, 330, 310]
|
||||
|
||||
const option = {
|
||||
title: {
|
||||
text: '充电订单趋势',
|
||||
left: 'center',
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
},
|
||||
legend: {
|
||||
data: ['订单量', '收入'],
|
||||
top: 30,
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: xData,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
series: [{
|
||||
name: '订单量',
|
||||
type: 'line',
|
||||
data: orderData,
|
||||
smooth: true,
|
||||
itemStyle: {
|
||||
color: '#5470c6',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '收入',
|
||||
type: 'line',
|
||||
data: revenueData,
|
||||
smooth: true,
|
||||
itemStyle: {
|
||||
color: '#91cc75',
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
this.chartInstance.setOption(option)
|
||||
|
||||
// 响应式调整
|
||||
window.addEventListener('resize', this.handleResize)
|
||||
},
|
||||
|
||||
handleResize() {
|
||||
if (this.chartInstance) {
|
||||
this.chartInstance.resize()
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#main {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin: 20px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.search-area {
|
||||
background-color: white;
|
||||
padding-top: 20px;
|
||||
border: 1px solid #F3F7FD;
|
||||
border-radius: 15px;
|
||||
}
|
||||
</style>
|
||||
177
src/views/order/recharge_order.vue
Normal file
@@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="search-area">
|
||||
<Form ref="formInline" inline :label-width="120" :model="formInline" :rules="ruleInline">
|
||||
<FormItem prop="user" label="openid">
|
||||
<Input type="text" v-model="formInline.openid" placeholder="" />
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</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(index)">详情</Button> -->
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" @on-change="onChangePage"
|
||||
@on-page-size-change="onChangePageSize" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getReChargeOrder } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
openid: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [{
|
||||
title: 'id',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: '订单编号',
|
||||
key: 'out_trade_no',
|
||||
},
|
||||
{
|
||||
title: '用户',
|
||||
key: 'openid',
|
||||
},
|
||||
{
|
||||
title: '充值金额',
|
||||
key: 'total',
|
||||
},
|
||||
{
|
||||
title: '已用金额',
|
||||
key: 'total_used',
|
||||
},
|
||||
{
|
||||
title: '充值状态',
|
||||
key: 'trade_state',
|
||||
},
|
||||
{
|
||||
title: '充值时间',
|
||||
key: 'success_time',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
}
|
||||
},
|
||||
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 pageHeight = 32 // 分页组件大约高度
|
||||
const margins = 40 // 上下边距总和
|
||||
this.tableHeight = window.innerHeight - searchHeight - pageHeight - margins - 130
|
||||
},
|
||||
async getList() {
|
||||
await getReChargeOrder({
|
||||
page: this.page,
|
||||
pageSize: this.pageSize,
|
||||
...this.formInline,
|
||||
}).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.getList()
|
||||
},
|
||||
handleReset(name) {
|
||||
this.$refs[name].resetFields()
|
||||
},
|
||||
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}`,
|
||||
})
|
||||
},
|
||||
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()
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
190
src/views/order/refund_order.vue
Normal file
@@ -0,0 +1,190 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="search-area">
|
||||
<Form ref="formInline" inline :label-width="120" :model="formInline" :rules="ruleInline">
|
||||
<FormItem prop="user" label="openid">
|
||||
<Input type="text" v-model="formInline.openid" placeholder="" />
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</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(index)">详情</Button> -->
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" @on-change="onChangePage"
|
||||
@on-page-size-change="onChangePageSize"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getRefundOrder } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
openid: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [{
|
||||
title: 'id',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: '订单编号',
|
||||
key: 'out_trade_no',
|
||||
},
|
||||
{
|
||||
title: '用户',
|
||||
key: 'openid',
|
||||
},
|
||||
{
|
||||
title: '用户手机号',
|
||||
key: 'phone',
|
||||
},
|
||||
{
|
||||
title: '退款金额',
|
||||
key: 'refund_total',
|
||||
},
|
||||
{
|
||||
title: '退还账户',
|
||||
key: 'user_received_account',
|
||||
},
|
||||
{
|
||||
title: '退款状态',
|
||||
key: 'status',
|
||||
},
|
||||
{
|
||||
title: '退款时间',
|
||||
key: 'create_time',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
}
|
||||
},
|
||||
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 pageHeight = 32 // 分页组件大约高度
|
||||
const margins = 40 // 上下边距总和
|
||||
this.tableHeight = window.innerHeight - searchHeight - pageHeight - margins - 130
|
||||
},
|
||||
async getList() {
|
||||
await getRefundOrder({
|
||||
page: this.page,
|
||||
pageSize: this.pageSize,
|
||||
...this.formInline,
|
||||
}).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$Message.success('Success!')
|
||||
} else {
|
||||
this.$Message.error('Fail!')
|
||||
}
|
||||
})
|
||||
},
|
||||
handleReset(name) {
|
||||
this.$refs[name].resetFields()
|
||||
},
|
||||
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)
|
||||
},
|
||||
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()
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
9
src/views/reports/activation.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<view>11</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
9
src/views/reports/backup_and_repair.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<view>11</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
183
src/views/reports/caiwu_reports.vue.vue
Normal file
@@ -0,0 +1,183 @@
|
||||
<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" v-model="formInline.user" placeholder="" />
|
||||
</FormItem>
|
||||
<FormItem prop="user" label="类型">
|
||||
<Input type="text" v-model="formInline.user" placeholder="" />
|
||||
</FormItem>
|
||||
<FormItem prop="user" label="起止时间">
|
||||
<Input type="text" v-model="formInline.user" placeholder="" />
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</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(index)">详情</Button> -->
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" @on-change="onChangePage"
|
||||
@on-page-size-change="onChangePageSize" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getCaiWuData } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [{
|
||||
title: 'Id',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: '用户',
|
||||
key: 'openid',
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
key: 'type_text',
|
||||
},
|
||||
{
|
||||
title: '金额',
|
||||
key: 'money',
|
||||
},
|
||||
{
|
||||
title: '说明',
|
||||
key: 'mark',
|
||||
},
|
||||
{
|
||||
title: '时间',
|
||||
key: 'createtime',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
}
|
||||
},
|
||||
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 pageHeight = 32 // 分页组件大约高度
|
||||
const margins = 40 // 上下边距总和
|
||||
this.tableHeight = window.innerHeight - searchHeight - pageHeight - margins - 130
|
||||
},
|
||||
async getList() {
|
||||
await getCaiWuData({
|
||||
page: this.page,
|
||||
pageSize: this.pageSize,
|
||||
}).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$Message.success('Success!')
|
||||
} else {
|
||||
this.$Message.error('Fail!')
|
||||
}
|
||||
})
|
||||
},
|
||||
handleReset(name) {
|
||||
this.$refs[name].resetFields()
|
||||
},
|
||||
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}`,
|
||||
})
|
||||
},
|
||||
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()
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
9
src/views/reports/income_analysis.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<view>11</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
9
src/views/reports/rate.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<view>11</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
9
src/views/reports/yunwei_reports.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<view>322534</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
203
src/views/reports/yunying_reports.vue
Normal file
@@ -0,0 +1,203 @@
|
||||
<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" v-model="formInline.user" placeholder="" />
|
||||
</FormItem>
|
||||
<FormItem prop="user" label="充电桩">
|
||||
<Input type="text" v-model="formInline.user" placeholder="" />
|
||||
</FormItem>
|
||||
<FormItem prop="user" label="起止时间">
|
||||
<Input type="text" v-model="formInline.user" placeholder="" />
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</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(index)">详情</Button> -->
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" @on-change="onChangePage"
|
||||
@on-page-size-change="onChangePageSize" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getYunYingData } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [{
|
||||
title: '充电站名称',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: '桩类型',
|
||||
key: 'out_trade_no',
|
||||
},
|
||||
{
|
||||
title: '桩数量',
|
||||
key: 'openid',
|
||||
},
|
||||
{
|
||||
title: '枪数量',
|
||||
key: 'total',
|
||||
},
|
||||
{
|
||||
title: '充电次数',
|
||||
key: 'total_used',
|
||||
},
|
||||
{
|
||||
title: '充电电量(度)',
|
||||
key: 'trade_state',
|
||||
},
|
||||
{
|
||||
title: '充电金额(元)',
|
||||
key: 'success_time',
|
||||
},
|
||||
{
|
||||
title: '电费',
|
||||
key: 'success_time',
|
||||
},
|
||||
{
|
||||
title: '服务费',
|
||||
key: 'success_time',
|
||||
},
|
||||
{
|
||||
title: '总时长',
|
||||
key: 'success_time',
|
||||
},
|
||||
{
|
||||
title: '尖峰平谷电量',
|
||||
key: 'success_time',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
}
|
||||
},
|
||||
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 pageHeight = 32 // 分页组件大约高度
|
||||
const margins = 40 // 上下边距总和
|
||||
this.tableHeight = window.innerHeight - searchHeight - pageHeight - margins - 130
|
||||
},
|
||||
async getList() {
|
||||
await getYunYingData({
|
||||
page: this.page,
|
||||
pageSize: this.pageSize,
|
||||
}).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$Message.success('Success!')
|
||||
} else {
|
||||
this.$Message.error('Fail!')
|
||||
}
|
||||
})
|
||||
},
|
||||
handleReset(name) {
|
||||
this.$refs[name].resetFields()
|
||||
},
|
||||
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}`,
|
||||
})
|
||||
},
|
||||
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()
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
273
src/views/system/admin.vue
Normal file
@@ -0,0 +1,273 @@
|
||||
<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" v-model="formInline.user" placeholder="" />
|
||||
</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="show(index)">编辑</Button>
|
||||
<Button type="error" size="small" @click="remove(index)">删除</Button>
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" />
|
||||
</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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { GetAdmin } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [
|
||||
{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: '用户名',
|
||||
key: 'username',
|
||||
},
|
||||
{
|
||||
title: '账号',
|
||||
key: 'nickname',
|
||||
},
|
||||
{
|
||||
title: '手机号',
|
||||
key: 'phone',
|
||||
},
|
||||
{
|
||||
title: '岗位',
|
||||
key: 'position',
|
||||
},
|
||||
{
|
||||
title: '角色名',
|
||||
key: 'roles',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
formValidate: {
|
||||
name: '',
|
||||
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' },
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
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 GetAdmin({ page: 1 }).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$Message.success('Success!')
|
||||
} else {
|
||||
this.$Message.error('Fail!')
|
||||
}
|
||||
})
|
||||
},
|
||||
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')
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
247
src/views/system/auth.vue
Normal file
@@ -0,0 +1,247 @@
|
||||
<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" v-model="formInline.user" 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(index)">编辑</Button>
|
||||
<Button type="error" size="small" @click="remove(index)">删除</Button>
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" />
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 添加、编辑 -->
|
||||
<Modal v-model="show_modal" title="添加角色" :mask-closable="false">
|
||||
<Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="80">
|
||||
<FormItem label="角色名" prop="name">
|
||||
<Input v-model="formValidate.name" placeholder="请输入角色名" />
|
||||
</FormItem>
|
||||
<FormItem label="所属上级" prop="pid">
|
||||
<Select v-model="formValidate.pid" style="width:200px">
|
||||
<Option :value="0">无</Option>
|
||||
<Option v-for="item in roles_data" :value="item.id" :key="item.id">{{ item.name }}</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem label="权限菜单" prop="roles">
|
||||
<Tree :data="menu_data" ref="tree" show-checkbox style="height: 300px;overflow-y: auto;"></Tree>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer">
|
||||
<Button type="text" @click="cancel">取消</Button>
|
||||
<Button type="primary" @click="ok">确定</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
GetRole,
|
||||
getMenuList,
|
||||
} from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: '角色名称',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
formValidate: {
|
||||
name: '',
|
||||
pid: 0,
|
||||
roles: '',
|
||||
},
|
||||
ruleValidate: {
|
||||
name: [{
|
||||
required: true,
|
||||
message: '请输入角色名',
|
||||
trigger: 'blur',
|
||||
}],
|
||||
roles: [{
|
||||
required: true,
|
||||
message: '请选择权限菜单',
|
||||
}],
|
||||
},
|
||||
cityList: [{
|
||||
value: 'New York',
|
||||
label: 'New York',
|
||||
}],
|
||||
menu_data: [{
|
||||
title: 'parent 1',
|
||||
expand: false,
|
||||
children: [{
|
||||
title: 'parent 1-1',
|
||||
expand: true,
|
||||
children: [{
|
||||
title: 'leaf 1-1-1',
|
||||
id: 1,
|
||||
},
|
||||
{
|
||||
title: 'leaf 1-1-2',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'parent 1-2',
|
||||
expand: true,
|
||||
children: [{
|
||||
title: 'leaf 1-2-1',
|
||||
},
|
||||
{
|
||||
title: 'leaf 1-2-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}],
|
||||
}
|
||||
},
|
||||
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 GetRole({
|
||||
page: 1,
|
||||
}).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit(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)
|
||||
},
|
||||
async ok() {
|
||||
let menuIds = this.$refs.tree.getCheckedAndIndeterminateNodes()
|
||||
this.formValidate.roles = menuIds.map(item => item.id)
|
||||
const valid = await new Promise(resolve => this.$refs.formValidate.validate(resolve))
|
||||
if (!valid) {
|
||||
this.$Message.error('请正确填写表单')
|
||||
return
|
||||
}
|
||||
// if (this.formValidate.id) { } else { }
|
||||
this.$Message.info('Clicked ok')
|
||||
},
|
||||
cancel() {
|
||||
this.show_modal = false
|
||||
this.$refs.formValidate.resetFields()
|
||||
},
|
||||
async add() {
|
||||
this.show_modal = true
|
||||
await this.getMenuList()
|
||||
},
|
||||
async getMenuList() {
|
||||
await getMenuList().then((res) => {
|
||||
this.menu_data = res
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
188
src/views/system/log.vue
Normal file
@@ -0,0 +1,188 @@
|
||||
<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" v-model="formInline.user" placeholder="" />
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button type="primary" @click="handleSubmit('formInline')">搜索</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
<div class="table-container">
|
||||
<Table border :columns="columns" stripe :height="tableHeight" :data="data">
|
||||
<template #action="{ row, index }">
|
||||
</template>
|
||||
</Table>
|
||||
<Page :total="total" show-total show-sizer class="page" @on-change="onChangePage"
|
||||
@on-page-size-change="onChangePageSize"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getLogList } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'charging_station',
|
||||
data() {
|
||||
return {
|
||||
show_modal: false,
|
||||
total: 100,
|
||||
tableHeight: 500,
|
||||
formInline: {
|
||||
user: '',
|
||||
password: '',
|
||||
},
|
||||
ruleInline: {},
|
||||
columns: [
|
||||
{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: 'ip',
|
||||
key: 'ip',
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
key: 'method',
|
||||
},
|
||||
{
|
||||
title: '参数',
|
||||
key: 'params',
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
key: 'url',
|
||||
},
|
||||
{
|
||||
title: '时间',
|
||||
key: 'create_time',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
slot: 'action',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
}
|
||||
},
|
||||
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 getLogList({ page: this.page, pageSize: this.pageSize }).then((res) => {
|
||||
this.total = res.total
|
||||
this.data = res.data
|
||||
this.page = res.current_page
|
||||
})
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$Message.success('Success!')
|
||||
} else {
|
||||
this.$Message.error('Fail!')
|
||||
}
|
||||
})
|
||||
},
|
||||
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()
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</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>
|
||||
152
src/views/system/system.vue
Normal file
@@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<!-- tab切换 -->
|
||||
<div class="tab" ref="tabHeader">
|
||||
<div v-for="(item, index) in tab" @click="changeTab(index)" :key="index" class="tab_children"
|
||||
:class="{ active: item.check }">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 内容区域(动态高度) -->
|
||||
<div class="content" :style="{ height: tableHeight + 'px', overflow: 'auto' }">
|
||||
<div v-if="currentTab === 'system'">系统参数内容</div>
|
||||
<div v-else-if="currentTab === 'charge_sate'">充电费率内容</div>
|
||||
<div v-else-if="currentTab === 'invoice'">发票配置内容</div>
|
||||
</div>
|
||||
|
||||
<!-- 固定在底部的提交按钮 -->
|
||||
<div class="footer">
|
||||
<Button type="primary" @click="submitForm">提交</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
show: true,
|
||||
tableHeight: 500, // 初始高度,单位px
|
||||
currentTab: 'system',
|
||||
tab: [{
|
||||
type: 'system',
|
||||
name: '系统参数',
|
||||
check: true,
|
||||
},
|
||||
{
|
||||
type: 'charge_sate',
|
||||
name: '充电费率',
|
||||
check: false,
|
||||
},
|
||||
{
|
||||
type: 'invoice',
|
||||
name: '发票配置',
|
||||
check: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.calculateTableHeight()
|
||||
window.addEventListener('resize', this.calculateTableHeight)
|
||||
// 添加防抖处理,避免频繁计算
|
||||
this.debouncedCalculate = this.$utils.debounce(this.calculateTableHeight, 100)
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('resize', this.debouncedCalculate)
|
||||
},
|
||||
methods: {
|
||||
calculateTableHeight() {
|
||||
try {
|
||||
const container = this.$el
|
||||
const tabHeader = this.$refs.tabHeader
|
||||
const footer = container.querySelector('.footer')
|
||||
|
||||
if (!container || !tabHeader || !footer) return
|
||||
|
||||
// 计算可用高度 = 容器高度 - tab高度 - footer高度 - 内边距
|
||||
const containerHeight = container.clientHeight
|
||||
const tabHeight = tabHeader.offsetHeight
|
||||
const footerHeight = footer.offsetHeight
|
||||
const padding = 40 // 上下内边距总和
|
||||
|
||||
this.tableHeight = containerHeight - tabHeight - footerHeight - padding
|
||||
|
||||
// 设置最小高度,避免内容区域太小
|
||||
this.tableHeight = Math.max(this.tableHeight, 200)
|
||||
} catch (e) {
|
||||
// console.error('计算高度出错:', e)
|
||||
}
|
||||
},
|
||||
handleClose() {
|
||||
this.show = false
|
||||
},
|
||||
changeTab(index) {
|
||||
this.tab.forEach((item, i) => {
|
||||
item.check = i === index
|
||||
})
|
||||
this.currentTab = this.tab[index].type
|
||||
},
|
||||
submitForm() {
|
||||
// console.log('提交表单')
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.tab_children {
|
||||
padding: 8px 16px;
|
||||
background: #ccc;
|
||||
color: #000;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.tab_children:hover {
|
||||
background: #bbb;
|
||||
}
|
||||
|
||||
.active {
|
||||
color: #fff;
|
||||
background-color: #409eff;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 20px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 20px;
|
||||
flex-shrink: 0;
|
||||
/* 防止内容区域被压缩 */
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
background: white;
|
||||
padding: 15px 0;
|
||||
text-align: center;
|
||||
border-top: 1px solid #eee;
|
||||
z-index: 10;
|
||||
}
|
||||
</style>
|
||||
6
tests/unit/utils.spec.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import { defaultDocumentTitle, getDocumentTitle } from '@/utils'
|
||||
|
||||
it('getDocumentTitle test', () => {
|
||||
const title = '这是一个测试'
|
||||
expect(getDocumentTitle(title)).toMatch(`${defaultDocumentTitle} - ${title}`)
|
||||
})
|
||||
124
update.md
Normal file
@@ -0,0 +1,124 @@
|
||||
## 更新日志
|
||||
### 2020.8.30 更新
|
||||
* build: 打包后的文件从绝对路径改成相对路径,也就是说打包后的文件不能放在服务器根目录下。
|
||||
### 2020.8.14 更新
|
||||
* new: loading 从 `components/Index.vue` 挪到了 `App.vue`。axios 从 `components/Index.vue` 挪到了 `utils/request.js`,并对其进行了封装,方便复用。
|
||||
* new: 重构了 loading 和 axios 拦截器使用方式,并提供了一个 ajax DEMO 放在首页。
|
||||
### 2020.6.5 更新
|
||||
* new: 新增外链功能,点击菜单可以跳到一个新页面,地址为指定的 URL。
|
||||
* new: 新增独立路由页面功能,点击侧边栏可以跳转到单独的路由页面(铺满屏幕,顶级路由)。
|
||||
|
||||
具体示例请查看源码 `src/store/index` 和 [demo](https://woai3c.github.io/)
|
||||
### 2019.12.21 更新
|
||||
* refactor: 将 `404` 页面独立出来,单独展示(占满屏幕)
|
||||
* new: [新增 eslint,配合 vscode 可以自动格式化代码](https://github.com/woai3c/Front-end-articles/blob/master/eslint-vscode-format.md)
|
||||
* new: 新增 jest 单元测试
|
||||
* new: 页面标题 `document.title`,在 `src/utils/index` 下可设置默认的 `title`,在每个路由配置项上可设置对应的 `title`,具体示例请看代码
|
||||
|
||||
### 2019.12.13 更新
|
||||
* fix: 修复在IE下关闭标签栏时,页面抖动的问题
|
||||
* refactor: 同时将左右两栏的布局方式从 flex 布局更改为 fixed + margin 的方式
|
||||
|
||||
### 2019.10.30 更新
|
||||
* new: 在对应的菜单项上添加 `hidden` 属性,即可隐藏对应的菜单项,但还是可以在地址栏上输入对应的 URL 来访问页面。
|
||||
使用方法
|
||||
```js
|
||||
{
|
||||
type: 'ios-grid',
|
||||
name: 't1',
|
||||
text: '表格',
|
||||
hidden: true, // 隐藏此菜单 可以通过在地址栏上输入对应的 URL 来显示页面
|
||||
}
|
||||
```
|
||||
|
||||
### 2019.10.14 更新
|
||||
* fix: 修复窗口宽度过小不会收缩侧边栏的问题
|
||||
* new: 打开页面时,默认展开和路由对应的菜单栏
|
||||
|
||||
### 2019.8.19 更新
|
||||
* fix: `components/Index.vue` 文件第 31 行代码的 `v-show="isShowAsideTitle"` 会造成侧边栏收缩时二级菜单隐藏,目前已修复。
|
||||
### 2019.7.24 更新
|
||||
* new: 增加页面进度条,跳转时显示
|
||||
|
||||
### 2019.6.25 更新
|
||||
* fix: 修复路由表冲突问题
|
||||
|
||||
退出当前用户,换账号重新登陆时,上个账号和现在的账号路由表会有冲突的问题,解决办法是在退出登陆时重置路由表。
|
||||
|
||||
具体实现请查看 `router/index.js`、`Login.vue` 和 `Index.vue` 的退出登陆回调方法。
|
||||
|
||||
### 2019.6.18 更新
|
||||
* new: 优化动态添加路由功能
|
||||
|
||||
以前的动态路由功能并不完善,首先要将所有的路由都添加到路由表里,然后根据后台返回的菜单栏数据来生成菜单。
|
||||
|
||||
导致的问题就是,虽然有页面在菜单栏上不显示,但由于已经添加到路由表里了,所以可以在地址栏上手动输入在菜单栏上不存在(但在路由表存在)的页面,进而可以越权访问。
|
||||
|
||||
现在除了必要的页面需要在一开始添加到路由表里,其他的页面都可以根据后台数据来自动生成。而且菜单栏上没有的页面,在地址栏上输入地址也是访问不了的。
|
||||
|
||||
另外,如果在未登陆时要访问某一指定页面,会重定向到登陆页,登陆成功后会自动跳到这个指定页面。
|
||||
|
||||
具体实现请看 `permission.js` 和 `util` 目录下的 `index.js` 文件
|
||||
|
||||
### 2019.3.14 更新
|
||||
|
||||
* new: 增加404页面
|
||||
|
||||
假如跳转到一个不存在的页面时会重定向到404页面
|
||||
|
||||
### 2019.3.8 更新
|
||||
|
||||
* new: 增加面包屑功能 用于展示当前页面的路径
|
||||
|
||||
* new: 增加权限控制功能,如果未登陆,访问所有页面都重定向到登陆页
|
||||
|
||||
### 2019.3.1 更新
|
||||
* new: 增加动态菜单栏功能
|
||||
|
||||
菜单项中的 `icon` 使用的是 `iview` 组件的 `icon` 组件。
|
||||
|
||||
数据格式:
|
||||
```js
|
||||
// 左侧菜单栏数据
|
||||
menuItems: [
|
||||
{
|
||||
name: 'Home', // 要跳转的路由名称 不是路径
|
||||
size: 18, // icon大小 非必填
|
||||
type: 'md-home', // icon类型 非必填
|
||||
text: '主页' // 文本内容
|
||||
},
|
||||
{
|
||||
text: '二级菜单',
|
||||
type: 'ios-paper',
|
||||
children: [
|
||||
{
|
||||
type: 'ios-grid',
|
||||
name: 'T1',
|
||||
text: '表格',
|
||||
hidden: true, // 可以在菜单中隐藏此菜单项,但还是可以访问此页面,只是不能在菜单栏中看见。
|
||||
},
|
||||
{
|
||||
text: '三级菜单',
|
||||
type: 'ios-paper',
|
||||
children: [
|
||||
{
|
||||
type: 'ios-notifications-outline',
|
||||
name: 'Msg',
|
||||
text: '查看消息'
|
||||
},
|
||||
{
|
||||
type: 'md-lock',
|
||||
name: 'Password',
|
||||
text: '修改密码'
|
||||
},
|
||||
{
|
||||
type: 'md-person',
|
||||
name: 'UserInfo',
|
||||
text: '基本资料',
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
15
vue.config.js
Normal file
@@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
devServer: {
|
||||
proxy: {
|
||||
'/chargingapi': {
|
||||
target: 'https://www.cqaijing.top', // 对应自己的接口
|
||||
changeOrigin: true,
|
||||
ws: true,
|
||||
pathRewrite: {
|
||||
'^/chargingapi': '',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
publicPath: './',
|
||||
}
|
||||