Commit b014a068 by 姜雷

Merge branch 'test' into 'master'

Test See merge request !49
parents 98d1cbb6 4f7588bd
......@@ -3,6 +3,8 @@ VUE_APP_LIB_BASE_URL=/systemManageShell/
VUE_APP_CUSTOMER_MENU_CODE=0001
VUE_APP_BASE_MENU_CODE=0002
VUE_APP_SYSTEM_MENU_CODE=0003
VUE_APP_STATISTICS_MENU_CODE=0044
VUE_APP_DEVICE_MENU_CODE=0048
VUE_APP_DASHBOARD_CODE=0079
VUE_APP_WHITE_LIST=/login,/404,/401
VUE_APP_LIB_MANAGER=http://ex-dev-dcxy-static.168cad.top
......
<!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" />
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@3.1.0/dist/vuex.js"></script>
<script src="https://unpkg.com/vue-router@3.0.1/dist/vue-router.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %><%= VUE_APP_LIB_BASE_URL %>lib/manageShell.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/customerManage/lib/customerManage.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/baseManage/lib/baseManage.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/systemManage/lib/systemManage.umd.min.js"></script>
<link
rel="stylesheet"
href="<%= VUE_APP_LIB_MANAGER %><%= VUE_APP_LIB_BASE_URL %>lib/manageShell.css"
/>
<title>系统管理</title>
</head>
<body>
<noscript>
<strong
>We're sorry but hello-world 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>
<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" />
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@3.1.0/dist/vuex.js"></script>
<script src="https://unpkg.com/vue-router@3.0.1/dist/vue-router.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %><%= VUE_APP_LIB_BASE_URL %>lib/manageShell.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/customerManage/lib/customerManage.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/baseManage/lib/baseManage.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/systemManage/lib/systemManage.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/operateManage/lib/operateManage.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/statisticsManage/lib/statisticsManage.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/deviceManage/lib/deviceManage.umd.min.js"></script>
<link rel="stylesheet" href="<%= VUE_APP_LIB_MANAGER %><%= VUE_APP_LIB_BASE_URL %>lib/manageShell.css" />
<title>系统管理</title>
</head>
<body>
<noscript>
<strong>We're sorry but hello-world 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>
......@@ -73,8 +73,8 @@ export default {
title: '',
selectedRoute: [],
routerDone: false,
isInnerPage: true,
showFastLink: false,
isInnerPage: false,
showFastLink: true,
showSelected: false,
};
},
......@@ -144,4 +144,7 @@ export default {
.loading-container {
margin: 50px;
}
.left-box {
transition: all 0.48s;
}
</style>
......@@ -12,3 +12,8 @@ export const fetchUserBaseInfoByPhone = entity =>
url: path + '/dcxy/customerInfo/baseCustomer',
params: entity,
});
export const fetchUserAccount = entity =>
fetch({
url: path + '/dcxy/customerInfo/queryAccount',
params: entity,
});
......@@ -14,6 +14,12 @@ export const fetchAccessAreaList = req =>
method: 'get',
...req,
});
export const fetchDashboardAreaList = req =>
fetch({
url: path + '/dcxy/baseArea/findAccessArea',
method: 'POST',
...req,
});
//获取下拉列表
export const fetchSelectList = req =>
fetch({
......
import axios from 'axios';
import { Message, MessageBox } from 'element-ui';
import store from '@/store';
import { errorHandle } from './validate';
const createBaseFetch = config => {
const service = axios.create({
timeout: 10000,
...config,
});
let logout = false;
// request拦截器
service.interceptors.request.use(
conf => {
const { notLoading } = conf;
store.dispatch('fetchStart', notLoading);
conf.headers = {
...conf.headers,
reqSource: 'pc',
token: store.getters.token ? store.getters.token : '',
};
return conf;
},
error => {
// Do something with request error
console.error(error); // for debug
Promise.reject(error);
}
);
// respone拦截器
service.interceptors.response.use(response => {
const res = response.data;
/**
* code为非 1000 是抛错
*/
setTimeout(() => {
const { notLoading } = response.config;
store.dispatch('fetchDone', notLoading);
}, 500);
if (res.code !== 1000) {
if (
response.headers &&
/application\/octet-stream/.test(response.headers['content-type'])
) {
return response;
}
Message({
message: res.msg || '网络错误!',
type: 'error',
duration: 5 * 1000,
});
// -2:其他客户端登录了;Token 过期了;
if (res.code === -2) {
if (logout) return;
logout = true;
MessageBox.confirm(
'你已被登出,可以取消继续留在该页面,或者重新登录',
'确定登出',
{
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
store.dispatch('FedLogOut').then(() => {
location.reload(); // 为了重新实例化vue-router对象 避免bug
});
})
.catch(err => {
console.error(err);
logout = false;
});
}
return Promise.reject(response.data);
} else {
return response.data;
}
}, errorHandle);
return service;
};
export default createBaseFetch;
......@@ -56,7 +56,9 @@ service.interceptors.response.use(response => {
if (res.code !== SUCCESS_CODE) {
if (
response.headers &&
response.headers['content-type'] === 'application/octet-stream'
/application\/octet-stream/.test(
response.headers['content-type'].toLowerCase()
)
) {
return response;
}
......
......@@ -20,7 +20,8 @@
>
<user-with-content
:customerId="customerId"
:visible='visible'
:visible="visible"
:showMoney="showMoney"
ref="userContent"
>
<button
......@@ -59,6 +60,10 @@ export default {
extends: Dialog,
props: {
customerId: Number,
showMoney: {
type: Boolean,
default: false,
},
},
// mounted() {
// let dialogWidth = 0;
......
......@@ -73,6 +73,10 @@ export default {
type: Boolean,
default: false,
},
showMoney: {
type: Boolean,
default: false,
},
},
data() {
return {
......@@ -123,6 +127,7 @@ export default {
{...updateVisible}
customerId={this.customerId}
visible={this.visible}
showMoney={this.showMoney}
title={this.title}
fullscreen={this.fullscreen}
top={this.top}
......@@ -146,6 +151,7 @@ export default {
{...updateVisible}
customerId={this.customerId}
visible={this.visible}
showMoney={this.showMoney}
title={this.title}
fullscreen={this.fullscreen}
top={this.top}
......
......@@ -61,6 +61,19 @@
</div>
<div class="UserInfo-Content-Col">注册时间:{{$formatDate(customerBaseInfo.createAt,'yyyy-MM-dd')}}</div>
<div class="UserInfo-Content-Col UserInfo-CampusName">{{customerBaseInfo.areaName}}</div>
<div
class="UserInfo-Content-serviceBox"
v-if="showMoney"
>
<div
v-for="(item, index) in serviceList"
:key="index"
class="UserInfo-Content-serviceBox-item"
>
<div>{{getServiceName(item.serviceId)}}</div>
<div>{{item.money}}</div>
</div>
</div>
</div>
</div>
</template>
......@@ -71,10 +84,6 @@ import UserBaseInfoMixin from '../../mixins/user/userBaseInfo.js';
import getUserInfoLabelMixin from '@/mixins/user/getUserInfoLabel.js';
export default {
props: {
customerId: Number,
customerPhone: String,
},
mixins: [UserBaseInfoMixin, getUserInfoLabelMixin],
};
</script>
......@@ -85,7 +94,6 @@ export default {
.UserInfo-Box {
width: 170px;
min-width: 170px;
height: 157px;
font-family: 'Microsoft YaHei';
font-size: 12px;
border-radius: 8px;
......@@ -132,7 +140,7 @@ export default {
}
}
.UserInfo-Content {
height: 90px;
// height: 90px;
background-color: #fff;
padding: 10px;
.UserInfo-Content-Col {
......@@ -156,13 +164,19 @@ export default {
line-height: 1;
margin-top: 0px;
}
.UserInfo-Content-serviceBox {
line-height: 24px;
.UserInfo-Content-serviceBox-item {
display: flex;
justify-content: space-between;
}
}
}
}
@media screen and (min-width: $bigScreenWidth) {
.UserInfo-Box {
width: 300px;
min-width: 300px;
height: 300px;
font-size: 16px;
.UserInfo-Title {
height: 120px;
......@@ -187,7 +201,7 @@ export default {
}
}
.UserInfo-Content {
height: 180px;
// height: 180px;
padding: 20px;
.UserInfo-Content-Col {
line-height: 38px;
......
......@@ -5,6 +5,7 @@
class="left-part"
:customerId="customerId"
:customerPhone="customerPhone"
:showMoney="showMoney"
:visible="visible"
/>
<div class="right-part">
......@@ -39,6 +40,10 @@ export default {
default: true,
},
customerPhone: String,
showMoney: {
type: Boolean,
default: false,
},
},
};
</script>
......@@ -51,6 +56,7 @@ export default {
display: flex;
background: transparent;
box-shadow: none;
align-items: flex-start;
.UserInfo-Box {
border-radius: 8px;
.UserInfo-Title {
......
<template>
<el-select
:clearable="clearable"
:disabled="disabled"
filterable
:value="value"
@change="changeHandle"
:multiple="multiple"
>
<slot></slot>
<el-option
v-for="(item, index) in dashboardArea"
:key="index"
:value="item.id"
:label="item.areaName"
></el-option>
</el-select>
</template>
<script>
import areaMixin from './mixin.js';
export default {
name: 'dashboard-area-select',
props: {
size: String,
value: {
required: true,
},
multiple: {
type: Boolean,
default: false,
},
disabled: Boolean,
clearable: {
type: Boolean,
default: true,
},
},
mixins: [areaMixin],
methods: {
changeHandle(val) {
if (val) {
if (val && val.length && val.indexOf(-1) > -1) {
if (val.length === this.dashboardArea.length + 1) {
this.$emit('input', []);
return;
} else {
this.$emit('input', this.dashboardArea.map(item => item.id));
return;
}
}
// if (this.multiple && val.length == 0) {
// this.$emit('input', this.dashboardArea.map(item => item.id));
// } else {
this.$emit('input', val);
// }
} else {
this.$emit('input', null);
}
},
},
};
</script>
import { fetchDashboardAreaList } from '@/api/base/index';
const GET_AREA_LIST = 'GET_AREA_LIST';
const FETCH_STATE = 'FETCH_STATE';
const FETCH_END = 'FETCH_END';
const state = () => ({
fetching: false,
list: [],
});
const initGetters = () => ({
dashboardArea: state => state.list,
});
const getters = initGetters();
const initAction = () => ({
fetchDashboardAreaList({ commit }, entity) {
return fetchDashboardAreaList({
data: entity,
}).then(res => {
const list = res.data;
commit(GET_AREA_LIST, list);
});
},
});
const actions = initAction();
const mutations = {
[GET_AREA_LIST](state, list) {
state.list = list;
},
[FETCH_STATE](state) {
state.fetching = true;
},
[FETCH_END](state) {
state.fetching = false;
},
};
export default {
namespaced: true,
state,
getters,
actions,
mutations,
};
import AreaSelect from './AreaSelect';
import areaMixin from './mixin';
export { areaMixin };
export default AreaSelect;
import store from './store';
export default {
props: {
operateId: {
type: Number,
},
},
data() {
return {
storeIndex: 0,
};
},
created() {
this.storeIndex = store.install(this.$store);
},
mounted() {
if (this.dashboardArea && !this.dashboardArea.length) {
this.fetchDashboardAreaList({
operateId: null,
});
}
},
watch: {
operateId(val) {
this.fetchDashboardAreaList({
operateId: val,
});
},
},
computed: {
dashboardArea() {
return this.$store.getters[
`dashboardArea${this.storeIndex}/dashboardArea`
];
},
},
methods: {
fetchDashboardAreaList(entity) {
return this.$store.dispatch(
`dashboardArea${this.storeIndex}/fetchDashboardAreaList`,
entity
);
},
getAreaName(id) {
let item = this.dashboardArea.find(area => area.id === id);
if (item) {
return item.areaName;
} else {
return '';
}
},
getAreaOperatorInfo(id) {
let item = this.dashboardArea.find(area => area.id === id);
if (item) {
return {
rechargeOperateId: item.rechargeOperateId,
rechargeOperateName: item.rechargeOperateName,
};
} else {
return null;
}
},
},
};
import areaStroe from './areaStore';
let index = 0;
export default {
install(store) {
if (!store.state.base) {
store.registerModule(['base'], {
state: {},
});
}
if (!store.state.base['dashboardArea' + index]) {
store.registerModule(['base', 'dashboardArea' + index], areaStroe);
} else {
index++;
store.registerModule(['base', 'dashboardArea' + index], areaStroe);
}
return index;
},
uninstall(store) {
store.unregisterModule(['base', 'dashboardArea' + index]);
},
};
<template>
<el-select
clearable
:clearable="clearable"
:disabled="disabled"
filterable
:value="value"
@change="changeHandle"
......@@ -16,12 +17,18 @@
<script>
import areaMixin from './mixin.js';
import { Select } from 'element-ui';
export default {
name: 'area-select',
props: {
size: String,
value: Number,
disabled: Boolean,
clearable: {
type:Boolean,
default: true,
},
},
mixins: [areaMixin],
computed: {
......
<template>
<el-select
clearable
:clearable="clearable"
:disabled="disabled"
filterable
:value="value"
@change="changeHandle"
......@@ -35,6 +36,11 @@ export default {
type: String,
default: '',
},
disabled: Boolean,
clearable: {
type: Boolean,
default: true,
},
},
data() {
return {
......
<template>
<el-select
clearable
:clearable="clearable"
:disabled="disabled"
filterable
:value="value"
@change="changeHandle"
......@@ -22,6 +23,11 @@ export default {
props: {
size: String,
value: Number,
disabled: Boolean,
clearable: {
type: Boolean,
default: true,
},
},
mixins: [beansMixin],
methods: {
......
<template>
<el-select
clearable
:clearable="clearable"
:disabled="disabled"
filterable
:value="value"
@change="changeHandle"
......@@ -28,6 +29,11 @@ export default {
type: Number,
default: null,
},
disabled: Boolean,
clearable: {
type:Boolean,
default: true,
},
},
computed: {
......
<template>
<el-select
clearable
:clearable="clearable"
:disabled="disabled"
filterable
:value="value"
@change="changeHandle"
......@@ -28,6 +29,11 @@ export default {
type: Number,
default: null,
},
disabled: Boolean,
clearable: {
type: Boolean,
default: true,
},
},
mixins: [serviceTypeMixin],
methods: {
......
......@@ -72,6 +72,15 @@ export const operClassifyName4User = [
{ label: '新增', value: '05' },
];
export const serviceMap = [
{ label: '艾米', value: '0' },
{ label: '通用', value: '1' },
{ label: '洗衣', value: '2' },
{ label: '饮水', value: '3' },
{ label: '吹风', value: '4' },
{ label: '洗浴', value: '5' },
];
export default {
selectTypeMapping,
customerStateOptions,
......
<template>
<div
class="Dashboard-DataCard"
class="Dashboard-DataCard CampusRank-wrap"
v-loading="loading.area"
>
<div class="Dashboard-SearchBar">
......@@ -8,13 +8,23 @@
<operator-select
:accessType="1"
:value="filters.operateId"
@input="val => changeFilterHandle({ operateId: val })"
@input="val => changeOperatorHandle({ operateId: val })"
/>
</search-item>
<search-item label="区域">
<dashboard-area-select
:operateId="filters.operateId"
:value="filters.choiceareaIds"
multiple
@input="val => updateFilters({choiceareaIds: val})"
>
<el-option :value="-1">全选</el-option>
</dashboard-area-select>
</search-item>
<el-radio-group
class="Dashboard-Radio"
:value="filters.timeType"
@input="val => changeFilterHandle({ timeType: val })"
@input="val => updateFilters({ timeType: val })"
>
<el-radio
class="Dashboard-Radio-item"
......@@ -29,9 +39,14 @@
:label="2"
>本年</el-radio>
</el-radio-group>
<el-button
type="primary"
@click="fetchConsumeList"
class="CampusRank-search"
>搜索</el-button>
</div>
<CampusRankChart
:data="campusRankList"
:data="campusRankListFillAreaname"
:changeCampusHandle="changeCampusHandle"
:updateCampusName="updateCampusName"
:showOtherNameHandle="showOtherNameHandle"
......@@ -43,10 +58,12 @@
<script>
import CampusRankChart from './CampusRankChart';
import { mapGetters, mapActions } from 'vuex';
import AreaDashboardMixin from '../../../components/input/AreaDashboard/mixin';
export default {
name: 'CampusRank',
components: { CampusRankChart },
mixins: [AreaDashboardMixin],
computed: {
...mapGetters('Dashboard', [
'campusRankList',
......@@ -54,6 +71,19 @@ export default {
'areaInfo',
'loading',
]),
campusRankListFillAreaname() {
return this.campusRankList.map(item => {
if (item.areaName) {
return item;
} else {
let areaName = this.getAreaName(item.areaId);
return {
...item,
areaName: areaName,
};
}
});
},
},
data() {
return { showOther: false };
......@@ -77,9 +107,36 @@ export default {
this.showOther = false;
});
},
changeOperatorHandle(data) {
this.updateFilters({ ...data, choiceareaIds: [] });
// this.fetchConsumeList();
},
showOtherNameHandle() {
this.showOther = true;
},
},
};
</script>
<style lang="scss">
.CampusRank-wrap {
.el-select {
.el-select__tags {
height: 90%;
overflow: hidden;
input {
display: none;
}
}
.el-input {
overflow: hidden;
}
.el-input__inner {
height: 100% !important;
}
}
.CampusRank-search {
margin-right: 5px;
}
}
</style>
<template>
<div class="CampusRank">
<div id="CampusRank">
<div class="CampusRank-legend">
<template v-if="this.data && this.data.length === 10">
其他校区:<span>{{other.toFixed(2)}}</span><br>
前十校区:<span>{{topTen.toFixed(2)}}</span>
</template>
<template v-else-if="this.data.length">
校区汇总:<span>{{topTen.toFixed(2)}}</span>
</template>
</div>
</div>
<div id="CampusRank"></div>
</div>
</template>
......@@ -48,7 +38,7 @@ export default {
container: 'CampusRank',
forceFit: true,
height: this.height,
padding: [20, 160, 20, 0],
padding: [20, 230, 20, 0],
});
this.chart.source(this.data);
this.chart.coord('theta', {
......@@ -57,7 +47,57 @@ export default {
});
this.chart.tooltip(false);
// 图例
this.chart.legend(false);
this.chart.legend({
position: 'right-center',
marker: 'square',
clickable: false,
offsetX: -4,
useHtml: true,
containerTpl: `
<div class="g2-legend">
<ul class="g2-legend-list" style="list-style-type:none;margin:0;padding:0;"></ul>
</div>`,
itemTpl: (value, color, checked, index) => {
const obj = this.data[index];
checked = checked ? 'checked' : 'unChecked';
return `
<li
class="g2-legend-list-item item-${index} ${checked}"
data-value="${value}"
data-color=${color}
style="cursor: pointer;font-size:14px;width:100%;"
>
<i
class="g2-legend-marker"
style="display:inline-block;margin-right:10px;background-color:${color};"
></i>
<span class="g2-legend-text" title="${value}">${value}: </span>
<span>${obj.count.toFixed(2)}</span>
</li>
`;
},
'g2-legend': {
width: '230px',
'max-width': '230px',
'max-height': this.height + 'px',
right: 0,
},
'g2-legend-list-item': {
color: '#333',
},
'g2-legend-text': {
display: 'inline-block',
width: '100px',
overflow: 'hidden',
'text-overflow': 'ellipsis',
'white-space': 'nowrap',
},
'g2-legend-marker': {
width: '10px',
height: '5px',
borderRadius: 'none',
},
});
// 坐标系及着色
this.chartGeom = this.chart
.intervalStack()
......@@ -125,9 +165,13 @@ export default {
this.percentDom = document.querySelector('.CampusRank-percent');
this.areaNameDom = document.querySelector('.CampusRank-areaName');
if (this.percentDom) {
this.percentDom.innerHTML = ((data.count / this.total) * 100).toFixed(
2
);
if (this.total === 0) {
this.percentDom.innerHTML = '0.00';
} else {
this.percentDom.innerHTML = ((data.count / this.total) * 100).toFixed(
2
);
}
}
if (this.areaNameDom) {
this.areaNameDom.innerHTML = data.areaName;
......@@ -153,5 +197,17 @@ export default {
top: 50%;
right: 0;
}
.g2-legend {
max-height: 270px;
overflow-y: auto;
}
.g2-legend-text {
display: inline-block;
width: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: middle;
}
}
</style>
<template>
<div
class="Dashboard-DataCard CustomerConsumption"
class="CustomerConsumption"
v-loading="loading"
>
<div class="Dashboard-SearchBar">
<search-item label="运营商">
<operator-select
:accessType="1"
:value="filters.operateId"
@input="val => getConsumeOrderList({operateId: val})"
/>
</search-item>
<search-item label="区域">
<area-select
:value="filters.areaId"
@input="val => getConsumeOrderList({areaId: val})"
type="user"
/>
</search-item>
<el-radio-group
class="Dashboard-Radio"
:value="filters.timeType"
@input="val => getConsumeOrderList({timeType: val})"
>
<el-radio
class="Dashboard-Radio-item"
:label="0"
>本日</el-radio>
<el-radio
class="Dashboard-Radio-item"
:label="1"
>本月</el-radio>
<el-radio
class="Dashboard-Radio-item"
:label="2"
>本年</el-radio>
</el-radio-group>
</div>
<div class="Dashboard-title">消费视图
<div
class="CustomerConsumptionChart-tip"
......@@ -69,10 +35,9 @@ export default {
Chart,
},
computed: {
...mapGetters('Dashboard/customerConsumption', [
...mapGetters('Dashboard/customerData/customerConsumption', [
'consumeList',
'consumeCount',
'filters',
'loading',
]),
},
......@@ -80,8 +45,7 @@ export default {
this.initData();
},
methods: {
...mapActions('Dashboard/customerConsumption', [
'updateFilters',
...mapActions('Dashboard/customerData/customerConsumption', [
'getConsumeOrderList',
]),
initData() {
......
import { getConsumeOrderList } from '@/api/dashboard/dashboard';
import initFiltersStore from '@/store/modules/filters';
// import initFiltersStore from '@/store/modules/filters';
import { getFilters, formatDate } from '@/utils/index';
const FETCH_CONSUME_LIST = 'FETCH_CONSUME_LIST';
const FETCH_DATA = 'FETCH_DATA';
const initFilters = () => ({
operateId: undefined,
areaId: undefined,
timeType: 0, // 0 本日,1 本月, 2 本年
});
const filtersStore = initFiltersStore(initFilters);
// const initFilters = () => ({
// operateId: undefined,
// areaId: undefined,
// timeType: 0, // 0 本日,1 本月, 2 本年
// });
// const filtersStore = initFiltersStore(initFilters);
const nowTime = new Date();
const state = () => ({
......@@ -28,12 +28,9 @@ const getters = {
};
const actions = {
getConsumeOrderList({ commit, getters, dispatch }, data) {
getConsumeOrderList({ commit, rootGetters }) {
commit(FETCH_DATA, true);
if (data) {
dispatch('updateFilters', data);
}
let entity = getFilters(getters.filters);
let entity = getFilters(rootGetters['Dashboard/customerData/filters']);
switch (entity.timeType) {
case 1:
entity.month = formatDate(nowTime, 'yyyy-MM');
......@@ -73,7 +70,7 @@ const mutations = {
export default {
namespaced: true,
modules: { filtersStore },
// modules: { filtersStore },
state,
getters,
actions,
......
<template>
<div class="Dashboard-CustomerMoneyData">
<div class="Dashboard-SearchBar bothSearch">
<search-item label="运营商">
<operator-select
:accessType="1"
:value="filters.operateId"
@input="val => updateFilters({operateId: val,areaId:undefined})"
/>
</search-item>
<search-item label="区域">
<dashboard-area-select
:operateId="filters.operateId"
:value="filters.areaId"
@input="val => updateFilters({areaId: val})"
/>
</search-item>
<el-radio-group
class="Dashboard-Radio"
:value="filters.timeType"
@input="val => updateFilters({timeType: val})"
>
<el-radio
class="Dashboard-Radio-item"
:label="0"
>本日</el-radio>
<el-radio
class="Dashboard-Radio-item"
:label="1"
>本月</el-radio>
<el-radio
class="Dashboard-Radio-item"
:label="2"
>本年</el-radio>
</el-radio-group>
<el-button
:loading="consumptionLoading||rechargeLoading"
type="primary"
@click="fetchAllData"
>搜索</el-button>
</div>
<div class="Dashboard-CustomerMoneyData-chart">
<CustomerRecharge />
<CustomerConsumption />
</div>
</div>
</template>
<script>
import CustomerRecharge from '../CustomerRecharge/CustomerRecharge';
import CustomerConsumption from '../CustomerConsumption/CustomerConsumption';
import { mapGetters, mapActions } from 'vuex';
import { getFilters } from '@/utils/index';
export default {
name: 'CustomerMoneyData',
components: {
CustomerRecharge,
CustomerConsumption,
},
computed: {
...mapGetters('Dashboard/customerData', ['filters']),
...mapGetters('Dashboard/customerData/customerConsumption', {
consumptionLoading: 'loading',
}),
...mapGetters('Dashboard/customerData/customerRecharge', {
rechargeLoading: 'loading',
}),
},
methods: {
...mapActions('Dashboard/customerData', ['updateFilters']),
...mapActions('Dashboard/customerData/customerConsumption', [
'getConsumeOrderList',
]),
...mapActions('Dashboard/customerData/customerRecharge', [
'getRechargeOrderList',
]),
fetchAllData() {
this.getConsumeOrderList();
this.getRechargeOrderList();
},
},
};
</script>
<style lang="scss">
.Dashboard-CustomerMoneyData {
.Dashboard & .Dashboard-SearchBar.bothSearch {
justify-content: flex-start;
align-items: center;
.Dashboard-Radio {
margin-left: 20px;
}
}
.Dashboard-CustomerMoneyData-chart {
display: flex;
width: 100%;
.CustomerRecharge {
flex: 1;
position: relative;
margin-right: 30px;
}
.CustomerRecharge::after {
content: '';
position: absolute;
height: 80%;
top: 10%;
right: -25px;
border-right: 1px dotted #eee;
}
.CustomerConsumption {
flex: 1;
}
}
}
</style>
import customerRecharge from '../CustomerRecharge/CustomerRechargeStore';
import customerConsumption from '../CustomerConsumption/CustomerConsumptionStore';
import initFiltersStore from '@/store/modules/filters';
const initFilters = () => ({
operateId: undefined,
areaId: undefined,
timeType: 0, // 0 本日,1 本月, 2 本年
});
const filtersStore = initFiltersStore(initFilters);
export default {
namespaced: true,
modules: { filtersStore, customerRecharge, customerConsumption },
};
<template>
<div
class="Dashboard-DataCard CustomerRecharge"
class="CustomerRecharge"
v-loading="loading"
>
<div class="Dashboard-SearchBar">
<search-item label="运营商">
<operator-select
:accessType="1"
:value="filters.operateId"
@input="val => getRechargeOrderList({operateId: val})"
/>
</search-item>
<el-radio-group
class="Dashboard-Radio"
:value="filters.timeType"
@input="val => getRechargeOrderList({timeType: val})"
>
<el-radio
class="Dashboard-Radio-item"
:label="0"
>本日</el-radio>
<el-radio
class="Dashboard-Radio-item"
:label="1"
>本月</el-radio>
<el-radio
class="Dashboard-Radio-item"
:label="2"
>本年</el-radio>
</el-radio-group>
</div>
<div class="Dashboard-title">储值视图
<div class="CustomerRechargeChart-tip">
<span
......@@ -58,10 +31,9 @@ export default {
Chart,
},
computed: {
...mapGetters('Dashboard/customerRecharge', [
...mapGetters('Dashboard/customerData/customerRecharge', [
'rechargeList',
'rechargeCount',
'filters',
'loading',
]),
},
......@@ -69,8 +41,7 @@ export default {
this.initData();
},
methods: {
...mapActions('Dashboard/customerRecharge', [
'updateFilters',
...mapActions('Dashboard/customerData/customerRecharge', [
'getRechargeOrderList',
]),
initData() {
......
import { getRechargeOrderList } from '@/api/dashboard/dashboard';
import initFiltersStore from '@/store/modules/filters';
// import initFiltersStore from '@/store/modules/filters';
import { getFilters, formatDate } from '@/utils';
const FETCH_RECHARGE_LIST = 'FETCH_RECHARGE_LIST';
const FETCH_DATA = 'FETCH_DATA';
const initFilters = () => ({
operateId: undefined,
timeType: 0, // 0 本日,1 本月, 2 本年
});
const filtersStore = initFiltersStore(initFilters);
// const initFilters = () => ({
// operateId: undefined,
// areaId: undefined,
// timeType: 0, // 0 本日,1 本月, 2 本年
// });
// const filtersStore = initFiltersStore(initFilters);
const nowTime = new Date();
const state = () => ({
......@@ -27,12 +28,9 @@ const getters = {
};
const actions = {
getRechargeOrderList({ commit, getters, dispatch }, data) {
getRechargeOrderList({ commit, rootGetters }) {
commit(FETCH_DATA, true);
if (data) {
dispatch('updateFilters', data);
}
let entity = getFilters(getters.filters);
let entity = getFilters(rootGetters['Dashboard/customerData/filters']);
switch (entity.timeType) {
case 1:
entity.month = formatDate(nowTime, 'yyyy-MM');
......@@ -72,7 +70,7 @@ const mutations = {
export default {
namespaced: true,
modules: { filtersStore },
// modules: { filtersStore },
state,
getters,
actions,
......
......@@ -4,13 +4,13 @@
id='CustomerRechargeChart'
:style="`height: ${height}px;width: ${width?width+'px':'auto'}`"
></div>
<!-- <div id='CustomerRechangeSlider'></div> -->
<CustomerRechangeSlider
<div id='CustomerRechangeSlider'></div>
<!-- <CustomerRechangeSlider
class="CustomerRechangeSlider"
:data="data"
:span="4"
:onChange="wheelHandle"
/>
/> -->
</div>
</template>
......@@ -20,7 +20,7 @@ import Slider from '@antv/g2-plugin-slider';
import chartMixin from '../chartMixin';
import DataSet from '@antv/data-set';
import _ from 'lodash';
import CustomerRechangeSlider from './slider';
// import CustomerRechangeSlider from './slider';
const Shape = G2.Shape;
const Util = G2.Util;
......@@ -75,7 +75,7 @@ Shape.registerShape('interval', 'right', {
export default {
name: 'CustomerRechargeChart',
components: { CustomerRechangeSlider },
// components: { CustomerRechangeSlider },
mixins: [chartMixin],
props: {
rechargeCount: {
......@@ -101,32 +101,45 @@ export default {
SelectedDataIndex: null,
};
},
computed: {
dataList() {
return this.data.map((item, index, array) => ({
...item,
index: index,
scaleValue: array.length - 1 ? index / (array.length - 1) : 0,
}));
},
},
methods: {
initData() {
let start =
this.dataList.length - 4 >= 0
? (this.dataList.length - 4) / this.dataList.length
: 0;
let end = 1;
this.ds = new DataSet({
state: {
startRadio: 0,
endRadio: 0.2,
start: start,
end: end,
},
});
const dv = this.ds.createView().source(this.data);
const dv = this.ds.createView().source(this.dataList);
this.dv = dv;
// dv.transform({
// type: 'map',
// callback(row, index) {
// // 加工数据后返回新的一行,默认返回行数据本身
// row.index = index;
// return row;
// },
// });
dv.transform({
type: 'filter',
callback: obj => {
if (
_.isNil(this.ds.state.startRadio) ||
_.isNil(this.ds.state.endRadio)
) {
return true;
}
const dataIndex = _.findIndex(this.data, {
areaName: obj.areaName,
});
const currentRadio = dataIndex / this.data.length;
const currentRadio = obj.scaleValue;
return (
currentRadio >= this.ds.state.startRadio &&
currentRadio <= this.ds.state.endRadio
currentRadio >= this.ds.state.start &&
currentRadio <= this.ds.state.end
);
},
});
......@@ -146,14 +159,11 @@ export default {
alias: '充值人数',
},
});
// this.chart.tooltip({
// offset: 250,
// });
this.chart.axis('areaName', {
label: {
offsetX: -80,
htmlTemplate(text, item, index) {
htmlTemplate: (text, item, index) => {
return `<div class="CustomerRechargeChart-areaTitle">${text}</div>`;
},
},
......@@ -168,13 +178,13 @@ export default {
.position('areaName*rechargeMoney')
.color('#4e82fb')
.shape('left')
.size(18);
.size(15);
this.chart
.interval()
.position('areaName*rechargeMen')
.shape('right')
.color('#26c9a8')
.size(18);
.size(15);
this.chart.legend(false);
......@@ -196,27 +206,31 @@ export default {
this.chart.render();
// this.initSlider();
this.initSlider();
},
initSlider() {
const wrapDom = document.getElementById('CustomerRechargeChart');
let height = wrapDom.clientHeight;
// let height = wrapDom.clientHeight;
// const arrLength = this.data.length;
// let spanNum = 4 / arrLength;
this.sliderDom = document.getElementById('CustomerRechangeSlider');
this.sliderDom.style = `height:${this.height}px`;
const spanNum = 4 / this.dataList.length;
this.sliderDom.style = `height:${height}px`;
this.slider = new Slider({
container: this.sliderDom, // dom 容器 id 或者 dom 容器对象
width: 26, // slider 的宽度,默认为 'auto',即自适应宽度
height: height, // slider 的高度,默认为 '26px'
padding: [50, 0, 50, 0],
height: this.height, // slider 的高度,默认为 '26px'
padding: [20, 0, 20, 0],
xAxis: 'rechargeMen', // 背景图的横轴对应字段,同时为数据筛选的字段
yAxis: 'areaName', // 背景图的纵轴对应字段
startRadio: this.ds.state.startRadio, // 新增
endRadio: this.ds.state.endRadio, // 新增
data: this.data, // slider 的数据源
yAxis: 'scaleValue', // 背景图的纵轴对应字段
start: 0,
end: 3 / this.dataList.length,
minSpan: spanNum,
maxSpan: spanNum,
data: this.dataList, // slider 的数据源
textStyle: {
display: 'none',
},
......@@ -225,44 +239,58 @@ export default {
width: 26,
height: 5,
},
onChange: ({ startRadio, endRadio }) => {
this.ds.setState('startRadio', startRadio);
this.ds.setState('endRadio', endRadio);
onChange: ({ startValue, endValue }) => {
this.ds.setState('start', startValue);
this.ds.setState('end', endValue);
}, // 更新数据状态量的回调函数
});
this.slider.layout = 'vertical';
this.slider.render(); // 渲染
},
updateSlider() {
const wrapDom = document.getElementById('CustomerRechargeChart');
let height = wrapDom.clientHeight;
this.sliderDom.innerHTML = '';
let dom = this.sliderDom;
dom.innerHTML = '';
const arrLength = this.data.length;
const arrLength = this.dataList.length;
let start =
this.dataList.length - 4 >= 0
? (this.dataList.length - 4) / this.dataList.length
: 0;
let end = 1;
// console.log('2222', this.dataList.length - 1, start, end);
const spanNum = 4 / this.dataList.length;
if (arrLength) {
// let spanNum = 4 / arrLength;
this.slider = new Slider({
container: this.sliderDom,
width: 26,
height: height,
padding: [50, 0, 50, 0],
xAxis: 'value',
yAxis: 'areaName',
startRadio: this.ds.state.startRadio,
endRadio: this.ds.state.endRadio,
data: this.data,
// minSpan: this.ds.state.endRadio,
// maxSpan: this.ds.state.endRadio,
height: this.height,
padding: [20, 0, 20, 0],
xAxis: 'rechargeMoney',
yAxis: 'scaleValue',
scales: {
scaleValue: {
formatter: val => {
let indexValue = val * (this.dataList.length - 1);
// console.log(val, indexValue);
return parseInt(indexValue, 10);
},
},
},
start: start,
end: end,
minSpan: spanNum,
maxSpan: spanNum,
data: this.dataList,
handleStyle: {
img: require('@/assets/images/dashboard/QXtfhORGlDuRvLXFzpsQ.png'),
width: 26,
height: 5,
},
onChange: ({ startRadio, endRadio }) => {
this.ds.setState('startRadio', startRadio);
this.ds.setState('endRadio', endRadio);
onChange: ({ startValue, endValue }) => {
// console.log('update:', startValue, endValue);
this.ds.setState('start', startValue);
this.ds.setState('end', endValue);
},
});
this.slider.layout = 'vertical';
......@@ -273,17 +301,22 @@ export default {
if (this.chart) {
const arrLength = this.data.length;
let spanNum = 4 / arrLength;
let start =
this.dataList.length - 4 >= 0
? (this.dataList.length - 4) / this.dataList.length
: 0;
let end = 1;
this.ds.setState('start', start);
this.ds.setState('end', end);
this.dv.source(this.dataList);
this.ds.setState('startRadio', Math.abs(1 - spanNum));
this.ds.setState('endRadio', 1);
this.dv.source(this.data);
// let height = this.data.length * 50;
// this.chart.changeHeight(height);
// this.updateSlider();
this.updateSlider();
this.updateData();
console.log(this.chart.getYScales());
} else {
this.initData();
// this.initSlider();
this.initSlider();
}
},
wheelHandle({ startRadio, endRadio }) {
......
......@@ -3,8 +3,9 @@ import {
fetchReportList,
fetchTitleList,
} from '@/api/dashboard/dashboard';
import customerRecharge from './CustomerRecharge/CustomerRechargeStore';
import customerConsumption from './CustomerConsumption/CustomerConsumptionStore';
import customerData from './CustomerData/CustomerDataStore';
// import customerRecharge from './CustomerRecharge/CustomerRechargeStore';
// import customerConsumption from './CustomerConsumption/CustomerConsumptionStore';
import customerFeedback from './CustomerFeedback/CustomerFeedbackStore';
import initFiltersStore from '@/store/modules/filters';
import { getFilters, formatDate } from '@/utils/index';
......@@ -22,6 +23,7 @@ const LOADING_REGIST = 'LOADING_REGIST';
const initFilters = () => ({
operateId: undefined,
choiceareaIds: [],
timeType: 0, // 0 本日,1 本月, 2 本年
});
const filtersStore = initFiltersStore(initFilters);
......@@ -68,13 +70,17 @@ const getters = {
areaInfo: state => state.consume.areaInfo,
consumeAfterVos: state => state.consume.consumeAfterVos,
consumeHardVos: state => state.consume.consumeHardVos,
campusRankList: state => state.consume.list,
campusRankList: state => {
return state.consume.list.filter(item => {
return state.filtersStore.filters.choiceareaIds.indexOf(item.areaId) > -1;
});
},
seviceRatioList: state => state.consume.percentList,
loading: state => state.loading,
};
const actions = {
fetchConsumeList({ commit, getters }, data) {
fetchConsumeList({ commit, getters, dispatch }, data) {
let entity = getFilters(getters.filters);
switch (entity.timeType) {
case 1:
......@@ -114,6 +120,18 @@ const actions = {
commit(GET_EUIPMENT_DATA, list);
commit(LOADING_EQUIPMENT, false);
} else {
if (entity && entity.choiceareaIds) {
} else if (list.list && list.list.length > 5) {
let areaList = list.list.slice(0, 5);
dispatch('updateFilters', {
choiceareaIds: areaList.map(item => item.areaId),
});
} else if (list.list) {
dispatch('updateFilters', {
choiceareaIds: list.list.map(item => item.areaId),
});
}
commit(GET_CONSUME_DATA, list);
commit(LOADING_AREA, false);
}
......@@ -166,22 +184,7 @@ const mutations = {
state.consume.consumeAfterVos = data.consumeAfterVos
? data.consumeAfterVos
: [];
let campusList = data.list ? data.list : [];
if (campusList.length > 10) {
let arrStart = campusList.slice(0, 9);
let arrEnd = campusList.slice(9).reduce(
(item, curentVal) => ({
...item,
count: item.count + curentVal.count,
}),
{
areaName: '其他校区',
count: 0,
}
);
campusList = [...arrStart, arrEnd];
}
state.consume.list = campusList;
state.consume.list = data.list ? data.list : [];
state.consume.percentList = data.percentList ? data.percentList : [];
},
[GET_PERCENT_DATA]: (state, data) => {
......@@ -235,8 +238,9 @@ export default {
namespaced: true,
modules: {
filtersStore,
customerRecharge,
customerConsumption,
customerData,
// customerRecharge,
// customerConsumption,
customerFeedback,
},
state,
......
......@@ -2,8 +2,7 @@
<div>
<div class="Dashboard">
<div class="Dashboard-Row Dashboard-CustomerData">
<CustomerRecharge class="Dashboard-DataCard" />
<CustomerConsumption class="Dashboard-DataCard" />
<CustomerData class="Dashboard-DataCard" />
<CustomerFeedback class="Dashboard-DataCard" />
</div>
<div class="Dashboard-Row Dashboard-OperatorData">
......@@ -18,20 +17,18 @@
<script>
import { mapActions, mapGetters } from 'vuex';
import CustomerRegister from './CustomerRegister/CustomerRegister';
// import CustomerRegister from './CustomerRegister/CustomerRegister';
import SeviceRatio from './SeviceRatio/SeviceRatio';
import CampusRank from './CampusRank/CampusRank';
import EquipmentList from './EquipmentList/EquipmentList';
import CustomerRecharge from './CustomerRecharge/CustomerRecharge';
import CustomerConsumption from './CustomerConsumption/CustomerConsumption';
import CustomerFeedback from './CustomerFeedback/CustomerFeedback';
import CustomerData from './CustomerData/CustomerData';
export default {
name: 'Dashboard',
components: {
CustomerRegister,
CustomerRecharge,
CustomerConsumption,
// CustomerRegister,
CustomerData,
CustomerFeedback,
SeviceRatio,
CampusRank,
......@@ -104,7 +101,7 @@ export default {
justify-self: flex-end;
.Dashboard-Radio-item {
font-size: 12px;
margin: 0 5px 0 0;
margin: 0 10px 0 0;
.el-radio__label {
padding-left: 2px;
}
......@@ -125,10 +122,7 @@ export default {
}
.Dashboard-DataCard {
&:first-child {
flex: 2;
}
&:nth-child(2) {
flex: 2;
flex: 4;
}
&:last-child {
flex: 1;
......
......@@ -45,10 +45,21 @@ export default {
</script>
<style lang="scss">
@import '@/assets/styles/variables.scss';
.EquipmentList {
.Dashboard-title {
.el-radio-button__inner {
line-height: 0;
padding: 12px 20px;
}
}
}
@media screen and (max-width: $bigScreenWidth) {
.EquipmentList {
.Dashboard-title {
.el-radio-button__inner {
padding: 12px 5px;
}
}
}
}
......
......@@ -46,6 +46,7 @@ export default {
position: 'right-center',
marker: 'square',
clickable: false,
offsetX: -10,
useHtml: true,
containerTpl: `
<div class="g2-legend">
......@@ -71,7 +72,7 @@ export default {
`;
},
'g2-legend': {
width: '125px',
width: '140px',
// left: '-20px',
},
'g2-legend-list-item': {
......@@ -123,9 +124,13 @@ export default {
this.serviceNameDom = document.querySelector('.SeviceRatio-serviceName');
if (this.percentDom) {
this.percentDom.innerHTML = ((data.count / this.totle) * 100).toFixed(
2
);
if (this.total === 0) {
this.percentDom.innerHTML = '0.00';
} else {
this.percentDom.innerHTML = ((data.count / this.totle) * 100).toFixed(
2
);
}
}
if (this.serviceNameDom) {
this.serviceNameDom.innerHTML = data.serviceName;
......
<template>
<list-layout>
<template slot="filterItem">
<search-item label="赠送类型">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
<search-item label="会员ID">
<el-input></el-input>
</search-item>
</template>
<template slot="filterBtn">
<el-button @click="showSearchBarHandle">qiehuan</el-button>
</template>
</list-layout>
</template>
<script>
import searchMixin from '@/mixins/searchBar';
export default {
name: 'Demo',
mixins: [searchMixin],
};
</script>
......@@ -22,10 +22,21 @@ export default {
},
computed: {
routeList() {
return this.collectList.map(item => {
let name = item.menuId.toString();
return getCollectMenu(this.routers, name);
});
if (
this.collectList &&
this.collectList.length &&
this.routers &&
this.routers.length
) {
let list = this.collectList.map(item => {
let name = item.menuId.toString();
return getCollectMenu(this.routers, name);
});
list = list.filter(item => !!item);
return list;
} else {
return [];
}
},
},
};
......
......@@ -40,12 +40,7 @@
src="@/assets/images/layout/icon_jichu@2x.png"
/>
</MenuItem>
<!-- <MenuItem menuName="统计系统">
<img
slot="icon"
src="@/assets/images/layout/icon_tongji@2x.png"
/>
</MenuItem> -->
<MenuItem
v-if="systemManage && systemManage.length"
menuName="系统管理"
......@@ -57,6 +52,28 @@
src="@/assets/images/layout/icon_xitong@2x.png"
/>
</MenuItem>
<MenuItem
v-if="statisticsManage && statisticsManage.length"
menuName="统计系统"
:menuList="statisticsManage[0].children"
:selectRouteMenu="selectRouteMenu"
>
<img
slot="icon"
src="@/assets/images/layout/icon_baobiao.png"
/>
</MenuItem>
<MenuItem
v-if="deviceManage && deviceManage.length"
menuName="设备系统"
:menuList="deviceManage[0].children"
:selectRouteMenu="selectRouteMenu"
>
<img
slot="icon"
src="@/assets/images/layout/icon_shebei.png"
/>
</MenuItem>
<div @click="() => toggleFastLink(false)">
<MenuItem menuName="全业态">
<img
......@@ -71,6 +88,8 @@
<MenuItem
:class="`fastLink ${dashboardVisiable?'marleft':''}`"
menuName="快速访问"
:menuList="collectRouteList"
:noTitle="true"
>
<img
slot="icon"
......@@ -98,7 +117,7 @@
<script>
import MenuItem from './components/MenuItem';
import { mapGetters } from 'vuex';
import { formatRouteLink } from '@/utils/route';
import { formatRouteLink, getFilterMenu } from '@/utils/route';
export default {
name: 'IconMenus',
......@@ -120,34 +139,12 @@ export default {
},
data() {
return {
menuList: [
{
path: '/OperLog',
name: '19',
meta: { title: '后台操作日志', icon: '' },
},
{
path: '/interface',
name: '27',
meta: { title: '接口管理', icon: '' },
children: [
{
path: '/interface/interfaceApp',
name: '29',
meta: { title: 'APP接口', icon: '' },
},
{
path: '/interface/interfaceManager',
name: '30',
meta: { title: '后台接口', icon: '' },
},
],
},
],
collectRouteList: [],
};
},
computed: {
...mapGetters('Dashboard', ['titleData']),
...mapGetters(['collectList']),
customerManage() {
let item = this.routers.find(
menu => menu.menuCode === process.env.VUE_APP_CUSTOMER_MENU_CODE
......@@ -172,8 +169,44 @@ export default {
);
return item ? true : false;
},
statisticsManage() {
let item = this.routers.find(
menu => menu.menuCode === process.env.VUE_APP_STATISTICS_MENU_CODE
);
return item ? formatRouteLink([item]) : null;
},
deviceManage() {
let item = this.routers.find(
menu => menu.menuCode === process.env.VUE_APP_DEVICE_MENU_CODE
);
return item ? formatRouteLink([item]) : null;
},
// collectRouteList() {
// let list = this.collectList.map(item => {
// let id = item.menuId;
// return getFilterMenu(this.routers, id);
// });
// list = list.filter(item => !!item);
// return list ? formatRouteLink(list) : null;
// },
},
watch: {
collectList(val) {
this.getCollectList(val);
},
},
mounted() {
this.getCollectList(this.collectList);
},
methods: {
getCollectList(val) {
let list = val.map(item => {
let id = item.menuId;
return getFilterMenu(this.routers, id);
});
list = list.filter(item => !!item);
this.collectRouteList = list && list.length ? formatRouteLink(list) : [];
},
clickHandle() {
if (this.dashboardVisiable) {
this.$router.go(-1);
......
......@@ -2,8 +2,8 @@
<div
ref="MenuItem"
:class="`MenuItem ${showSubMenus?'Selected':''}`"
@mouseenter="toggleSubmenus"
@mouseleave="toggleSubmenus"
@mouseenter="toggleSubmenus(true)"
@mouseleave="toggleSubmenus(false)"
>
<div
class="IconMenu"
......@@ -21,36 +21,56 @@
:style="style"
v-if="menuList && menuList.length"
>
<div
class="Submenu"
v-for="(item, index) in menuList"
:key="index"
>
<div class="Submenu-title">
<span>{{item.meta.title}}</span>
<LikeIcon
v-if="!item.children"
:name="item.name"
/>
<template v-if="noTitle">
<div class="Submenu">
<div class="Submenu-list">
<div
class="Submenu-link"
v-for="(item, index) in menuList"
:key="index"
>
<LikeIcon :name="item.name" />
<router-link
class="Submenu-link-text"
:to="item.path"
>{{item.meta.title}}</router-link>
</div>
</div>
</div>
</template>
<template v-else>
<div
class="Submenu-list"
v-if="item.children && item.children.length"
class="Submenu"
v-for="(item, index) in menuList"
:key="index"
>
<div class="Submenu-title">
<span>{{item.meta.title}}</span>
<LikeIcon
v-if="!item.children"
:name="item.name"
/>
</div>
<div
class="Submenu-link"
v-for="(item, index) in item.children"
:key="index"
class="Submenu-list"
v-if="item.children && item.children.length"
>
<LikeIcon :name="item.name" />
<router-link
class="Submenu-link-text"
:to="item.path"
>{{item.meta.title}}</router-link>
<div
class="Submenu-link"
v-for="(item, index) in item.children"
:key="index"
>
<LikeIcon :name="item.name" />
<router-link
class="Submenu-link-text"
:to="item.path"
>{{item.meta.title}}</router-link>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
</template>
......@@ -73,6 +93,10 @@ export default {
selectRouteMenu: {
type: Function,
},
noTitle: {
type: Boolean,
default: false,
},
},
data() {
return {
......@@ -92,8 +116,8 @@ export default {
}
},
methods: {
toggleSubmenus() {
this.showSubMenus = !this.showSubMenus;
toggleSubmenus(visiable) {
this.showSubMenus = visiable;
},
selectHandle() {
if (typeof this.selectRouteMenu === 'function') {
......@@ -148,6 +172,7 @@ export default {
height: auto;
}
.Submenu-title {
width: 560px;
height: 30px;
line-height: 30px;
font-size: 14px;
......
......@@ -5,7 +5,7 @@
<span>欢迎您,{{ userInfo.name }}</span>
<span
class="avatar-name-icon"
@click="toggleUserMenus"
@click.stop="toggleUserMenus"
>
<img src="@/assets/images/layout/icon_xiala@2x.png" />
<div
......@@ -359,6 +359,13 @@ export default {
...mapActions(['updatePassword', 'updateUserinfo', 'updateUserCellphone']),
toggleUserMenus() {
this.userMenusVisble = !this.userMenusVisble;
setTimeout(() => {
if (this.userMenusVisble) {
document.addEventListener('click', this.toggleUserMenus);
} else {
document.removeEventListener('click', this.toggleUserMenus);
}
}, 400);
},
cancelPwdUpdate(done) {
this.resetPwdForm();
......
<script>
import { getVcode } from '@/api/user/update';
import { clearTimeout } from 'timers';
export default {
props: {
......@@ -26,6 +27,8 @@ export default {
const count = this.count;
if (count == 1) {
this.counting = false;
this.count = 60;
this.timer = null;
} else {
const timer = setTimeout(() => {
this.countDown();
......
......@@ -143,10 +143,18 @@ export default {
varifyCode: this.loginForm.vcode,
remenberAccount: this.remenberAccount,
})
.then(() => {
.then(userRoles => {
console.log('login done');
this.loading = false;
this.$router.push({ path: '/' });
if (
userRoles.find(
item => item.menuCode === process.env.VUE_APP_DASHBOARD_CODE
)
) {
this.$router.push({ name: 'dashboard' });
} else {
this.$router.push({ path: '/' });
}
})
.catch(err => {
console.error(err);
......
<!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" />
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@3.1.0/dist/vuex.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router@3.0.1/dist/vue-router.js"></script>
<title>系统管理</title>
</head>
<body>
<noscript>
<strong
>We're sorry but hello-world 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>
<script src="<%= VUE_APP_LIB_MANAGER %>/customerManage/lib/customerManage.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/baseManage/lib/baseManage.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/systemManage/lib/systemManage.umd.min.js"></script>
<script src="https://webapi.amap.com/maps?v=1.4.12&key=dd6103c90f2f17310a8711f2d330a0a6"></script>
<script src="https://webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>
<script src="https://unpkg.com/@antv/data-set"></script>
<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" />
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@3.1.0/dist/vuex.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router@3.0.1/dist/vue-router.js"></script>
<title>系统管理</title>
</head>
<body>
<noscript>
<strong>We're sorry but hello-world 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>
<script src="<%= VUE_APP_LIB_MANAGER %>/customerManage/lib/customerManage.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/baseManage/lib/baseManage.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/systemManage/lib/systemManage.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/operateManage/lib/operateManage.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/statisticsManage/lib/statisticsManage.umd.min.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/deviceManage/lib/deviceManage.umd.min.js"></script>
<script src="https://webapi.amap.com/maps?v=1.4.12&key=dd6103c90f2f17310a8711f2d330a0a6"></script>
<script src="https://webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>
<script src="https://unpkg.com/@antv/data-set"></script>
</html>
......@@ -7,6 +7,9 @@ setTimeout(() => {
...customerManage.default,
...baseManage.default,
...systemManage.default,
...operateManage.default,
...statisticsManage.default,
...deviceManage.default,
];
System.createSystem({
......
......@@ -57,7 +57,9 @@ const createBaseFetch = config => {
if (res.code !== SUCCESS_CODE) {
if (
response.headers &&
response.headers['content-type'] === 'application/octet-stream'
/application\/octet-stream/.test(
response.headers['content-type'].toLowerCase()
)
) {
return response;
}
......
......@@ -49,7 +49,6 @@ class SystemShell {
...whiteList.split(','),
]
: process.env.VUE_APP_WHITE_LIST.split(','); // 不重定向白名单
console.log(allWhiteList);
store.dispatch('getWhiteList', allWhiteList);
configRoutePermission(router, store, routers, allWhiteList);
......
......@@ -12,10 +12,12 @@ import BaseData from '../components/input/BaseDataSelect/mixin';
import BeanType from '../components/input/BeanTypeSelect/mixin';
import OperatorOptions from '../components/input/OperatorSelect/mixin';
import ServiceType from '../components/input/ServiceTypeSelect/mixin';
import SearchBar from '../mixins/searchBar';
export default {
Dialog,
ListPage,
SearchBar,
CampusListPage,
Operator,
Admin,
......
......@@ -2,6 +2,9 @@ let allAasyncRouterMap = [
...customerManage.default,
...baseManage.default,
...systemManage.default,
...operateManage.default,
...statisticsManage.default,
...deviceManage.default,
];
const System = manageShell.default;
......
export default {
data() {
return {
showAllSearchBar: false,
searchBarDom: null,
height: 0,
};
},
mounted() {
let searchBarDom = document.querySelector('.left-box');
let filterItemDom = document.querySelector('.filter-item');
this.searchBarDom = searchBarDom;
let height =
(filterItemDom.clientHeight +
parseInt(window.getComputedStyle(filterItemDom)['margin-bottom'])) *
2;
this.height = height;
this.searchBarDom.style = `height: ${height}px;overflow: hidden;max-height: ${height}px`;
},
methods: {
showSearchBarHandle() {
if (this.showAllSearchBar) {
this.showAllSearchBar = !this.showAllSearchBar;
this.searchBarDom.style = `height: ${
this.height
}px;overflow: hidden;max-height: ${this.height}px`;
} else {
this.showAllSearchBar = !this.showAllSearchBar;
this.searchBarDom.style =
'height: auto;overflow: hidden;max-height: 500px';
}
},
},
};
import { mapActions, mapGetters } from 'vuex';
import { fetchUserAccount } from '../../api/base/customer';
import { serviceMap } from '@/config';
export default {
props: {
visible: { type: Boolean, default: false },
customerId: Number,
customerPhone: String,
showMoney: {
type: Boolean,
default: false,
},
},
data() {
return {
serviceList: [],
};
},
watch: {
visible(newVal) {
......@@ -12,6 +23,7 @@ export default {
this.fetchUserBaseInfo({
customerId: this.customerId,
});
this.getAllData();
}
},
customerId(newId) {
......@@ -19,6 +31,7 @@ export default {
this.fetchUserBaseInfo({
customerId: this.customerId,
});
this.getAllData();
}
},
customerPhone(newPhone) {
......@@ -26,6 +39,7 @@ export default {
this.fetchUserBaseInfoByPhone({
customerPhone: this.customerPhone,
});
this.getAllData();
}
},
},
......@@ -34,11 +48,13 @@ export default {
this.fetchUserBaseInfo({
customerId: this.customerId,
});
this.getAllData();
}
if (this.visible && !this.customerId && this.customerPhone) {
this.fetchUserBaseInfoByPhone({
customerPhone: this.customerPhone,
});
this.getAllData();
}
},
computed: {
......@@ -46,5 +62,29 @@ export default {
},
methods: {
...mapActions(['fetchUserBaseInfo', 'fetchUserBaseInfoByPhone']),
getAllData() {
// console.log('in getAllData', this.customerId, this.customerPhone);
if (this.showMoney) {
const entity = this.customerId
? {
customerId: this.customerId,
}
: {
customerPhone: this.customerPhone,
};
fetchUserAccount(entity)
.then(res => {
this.serviceList = res.data;
})
.catch(err => {
console.error(err);
});
}
},
getServiceName(id) {
let item = serviceMap.find(item => item.value === id);
return item ? item.label : id;
},
},
};
......@@ -15,6 +15,7 @@ const constantRouterMap = [
path: '/',
name: 'home',
meta: { title: '首页', icon: HomeIcon },
// component: _import('Home'),
component: { render: h => <router-view /> },
},
{
......
......@@ -35,7 +35,7 @@ const actions = {
return addCollect({
data: { ...entity, sortId: getters.collectList.length + 1 },
}).then(res => {
commit(ADD_COLLECT_LIST, entity.menuId);
commit(ADD_COLLECT_LIST, Number(entity.menuId));
});
},
delCollect({ commit }, entity) {
......
......@@ -40,6 +40,7 @@ const actions = {
commit(SET_TOKEN, token);
commit(UPDATE_USERINFO, userInfo);
dispatch('getAsyncRoute', userRoles);
return userRoles;
});
},
// token登录
......
......@@ -15,6 +15,7 @@ import UserCard from '../components/UserCard/UserCard.vue';
import UserInfo from '../components/UserCard/UserInfo.vue';
import UserDialog from '../components/Dialog/UserDialogWrap';
import DashboardArea from '../components/input/AreaDashboard/index';
import AreaSelect from '../components/input/AreaSelect/index';
import ServiceTypeSelect from '../components/input/ServiceTypeSelect/index';
import BaseDataSelect from '../components/input/BaseDataSelect/index';
......@@ -38,6 +39,7 @@ const extendVue = Vue => {
Vue.component(HeaderImg.name, HeaderImg);
// input
Vue.component(DashboardArea.name, DashboardArea);
Vue.component(AreaSelect.name, AreaSelect);
Vue.component(BaseDataSelect.name, BaseDataSelect);
Vue.component(ServiceTypeSelect.name, ServiceTypeSelect);
......
......@@ -82,3 +82,18 @@ export const getCollectMenu = (routeList, name) => {
}
return menuData;
};
export const getFilterMenu = (allRouterMap, id) => {
let menuData = null;
for (let index = 0; index < allRouterMap.length; index++) {
const element = allRouterMap[index];
if (element.childs && element.childs.length) {
menuData = getFilterMenu(element.childs, id);
if (menuData) break;
} else if (element.id === id) {
menuData = element;
break;
}
}
return menuData;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment