Commit 6aafc207 by 姜雷

Merge branch 'develop' into test

parents c7b510ff 6b6448a2
const removeConsolePlugin = [];
if (process.env.NODE_ENV === 'production') {
removeConsolePlugin.push('transform-remove-console');
}
module.exports = {
presets: ['@vue/app'],
plugins: removeConsolePlugin,
};
......@@ -7,7 +7,7 @@
"scripts": {
"dev": "vue-cli-service serve --port 8891",
"dev:local": "vue-cli-service serve ./src/dev-local/develop.js --port 8891",
"start": "npm run dev",
"start": "npm run dev:local",
"lint": "eslint --ext .js,.vue src",
"build": "vue-cli-service build --modern",
"build:dev": "cross-env npm run buildapp:dev && npm run buildlib:dev",
......@@ -23,7 +23,9 @@
"analyz": "cross-env NODE_ENV=production npm_config_report=true npm run build"
},
"dependencies": {
"@antv/data-set": "^0.10.2",
"@antv/g2": "^3.5.1",
"@antv/g2-plugin-slider": "^2.1.1",
"axios": "^0.18.0",
"blueimp-md5": "^2.10.0",
"js-cookie": "^2.2.0",
......@@ -44,6 +46,7 @@
"@vue/eslint-config-prettier": "^4.0.1",
"babel-eslint": "^10.0.1",
"babel-plugin-component": "^1.1.1",
"babel-plugin-transform-remove-console": "^6.9.4",
"cross-env": "^5.2.0",
"eslint": "^5.8.0",
"eslint-plugin-vue": "^5.0.0",
......
......@@ -8,10 +8,10 @@
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/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>
<script src="<%= VUE_APP_LIB_MANAGER %><%= VUE_APP_LIB_BASE_URL %>lib/manageShell.umd.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/customerManage/lib/customerManage.umd.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/baseManage/lib/baseManage.umd.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/systemManage/lib/systemManage.umd.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"
......
......@@ -31,6 +31,13 @@ export const fetchOperatorList = req =>
method: 'get',
...req,
});
// 获取权限运营商
export const fetchAccessOperatorList = req =>
fetch({
url: path + '/dcxy/baseOperator/queryAccessOper',
method: 'get',
...req,
});
// 获取豆类型
export const fetchBeansList = req =>
fetch({
......
......@@ -23,7 +23,7 @@ const createBaseFetch = config => {
},
error => {
// Do something with request error
console.log(error); // for debug
console.error(error); // for debug
Promise.reject(error);
}
);
......@@ -70,7 +70,7 @@ const createBaseFetch = config => {
});
})
.catch(err => {
console.log(err);
console.error(err);
logout = false;
});
}
......
......@@ -5,6 +5,7 @@ const path = process.env.VUE_APP_CUSTOMER_SERVER_URL;
export const fetchConsumeList = req =>
fetch({
url: path + '/dcxy/reportInfo/queryConsumeList',
method: 'POST',
timeout: 30000,
...req,
});
......@@ -18,3 +19,20 @@ export const fetchTitleList = req =>
url: path + '/dcxy/reportInfo/queryTitleList',
...req,
});
export const getRechargeOrderList = req =>
fetch({
url: path + '/dcxy/reportInfo/queryRechargeOrderList',
method: 'POST',
...req,
});
export const getConsumeOrderList = req =>
fetch({
url: path + '/dcxy/reportInfo/queryConsumeOrderList',
method: 'POST',
...req,
});
export const getFeedbackList = req =>
fetch({
url: path + '/dcxy/reportInfo/queryFeedbackList',
...req,
});
......@@ -39,7 +39,7 @@ service.interceptors.request.use(
},
error => {
// Do something with request error
console.log(error); // for debug
console.error(error); // for debug
Promise.reject(error);
}
);
......@@ -85,7 +85,7 @@ service.interceptors.response.use(response => {
});
})
.catch(err => {
console.log(err);
console.error(err);
logout = false;
});
}
......
......@@ -27,7 +27,7 @@ export const validateCode = res => {
};
export const errorHandle = error => {
console.log('err' + error); // for debug
console.error('err' + error); // for debug
store.dispatch('fetchDone');
if (error.message && /timeout/.test(error.message)) {
Message({
......
......@@ -5,8 +5,8 @@ $--color-primary: #1459fc;
$--color-danger: #ff3333;
/* 改变 icon 字体路径变量,必需 */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import '~element-ui/packages/theme-chalk/src/index';
// $--font-path: '~element-ui/lib/theme-chalk/fonts';
// @import '~element-ui/packages/theme-chalk/src/index';
#app {
.el-checkbox__input.is-checked + .el-checkbox__label {
......
......@@ -64,11 +64,11 @@ export default {
insert(this.IMG_URL + response.key);
};
let _error = err => {
console.log(err);
console.error(err);
if (err.isRequestError && err.code == 401) {
this.getImgToken(true);
} else {
console.log(err);
console.error(err);
this.$refs.input.value = '';
}
};
......
<template>
<search-item
label="赠送类型"
:size="size"
>
<el-select
clearable
filterable
:value="value"
@change="changeHandle"
>
<el-option
v-for="(item, index) in giveTypeList"
:key="index"
:value="item.value"
:label="item.name"
></el-option>
</el-select>
</search-item>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'give-select',
props: {
size: {
type: String,
default: '',
},
value: {
type: String,
default: '',
},
},
mounted() {
if (!this.giveTypeList.length) {
this.fetchGiveTypeList();
}
},
computed: {
...mapGetters(['giveTypeList']),
},
methods: {
...mapActions(['fetchGiveTypeList']),
changeHandle(val) {
this.$emit('input', val);
},
getTypeName(val){
let item = this.giveTypeList.find(({value}) => val === value);
return item?item.name: '';
}
},
};
</script>
......@@ -172,14 +172,14 @@ export default {
});
})
.catch(err => {
console.log('删除错误:' + err.msg);
console.error('删除错误:' + err.msg);
});
},
_error(err) {
if (err.isRequestError && err.code == '401') {
this.getImgToken(true);
} else {
console.log(err);
console.error(err);
this.$refs.input.value = '';
}
},
......
......@@ -6,7 +6,7 @@
@change="changeHandle"
>
<el-option
v-for="(item, index) in operatorOptionList"
v-for="(item, index) in optionsList"
:key="index"
:value="item.id"
:label="item.operateName"
......@@ -29,6 +29,12 @@ export default {
default: null,
},
},
computed: {
optionsList() {
return this[`operatorOptionList${this.accessType}`];
},
},
mixins: [operatorMixin],
methods: {
changeHandle(val) {
......
import { fetchOperatorList } from '@/api/base/index';
import { fetchOperatorList, fetchAccessOperatorList } from '@/api/base/index';
import typeMapping from './typeMapping';
const FETCH_OPERATOR_LIST = 'FETCH_OPERATOR_LIST';
const FETCH_STATE = 'FETCH_STATE';
const FETCH_END = 'FETCH_END';
const state = () => ({
list: [],
fetching: false,
});
const getters = {
operatorOptionList: state => state.list,
const state = () => {
let operatorState = {};
typeMapping.map(type => {
operatorState[`list${type.value}`] = [];
operatorState[`fetching${type.value}`] = false;
});
return operatorState;
};
const initGetters = () => {
let getters = {};
typeMapping.map(type => {
getters[`operatorOptionList${type.value}`] = state =>
state[`list${type.value}`];
});
return getters;
};
const getters = initGetters();
const actions = {
fetchOperatorList({ state, commit }) {
if (state.fetching) return;
commit(FETCH_STATE, true);
return fetchOperatorList().then(res => {
const list = res.data;
commit(FETCH_OPERATOR_LIST, list);
commit(FETCH_STATE, false);
});
},
const initAction = () => {
let actions = {};
typeMapping.map(type => {
actions[`fetchOperatorList${type.value}`] = ({ state, commit }) => {
if (state[`fetching${type.value}`]) return;
commit(FETCH_STATE, type.value);
let fetchHandle = null;
if (type.value == 0) {
fetchHandle = fetchOperatorList;
} else {
fetchHandle = fetchAccessOperatorList;
}
return fetchHandle().then(res => {
const list = res.data;
commit(FETCH_OPERATOR_LIST, { type: type.value, list });
commit(FETCH_END, type.value);
});
};
});
return actions;
};
const actions = initAction();
const mutations = {
[FETCH_OPERATOR_LIST](state, list) {
state.list = list;
[FETCH_OPERATOR_LIST](state, { type, list }) {
state[`list${type}`] = list;
},
[FETCH_STATE](state, type) {
state[`fetching${type}`] = true;
},
[FETCH_STATE](state, fetching) {
state.fetching = fetching;
[FETCH_END](state, type) {
state[`fetching${type}`] = false;
},
};
......
import { mapGetters, mapActions } from 'vuex';
import store from './store';
import typeMapping from './typeMapping';
const getterList = typeMapping.map(type => `operatorOptionList${type.value}`);
const actionsList = typeMapping.map(type => `fetchOperatorList${type.value}`);
export default {
props: {
accessType: {
type: Number,
default: 0, // 0 全部 1 权限
},
},
created() {
store.install(this.$store);
},
mounted() {
if (!this.operatorOptionList.length) {
this.fetchOperatorList();
if (
this[`operatorOptionList${this.accessType}`] &&
!this[`operatorOptionList${this.accessType}`].length
) {
this[`fetchOperatorList${this.accessType}`]();
}
},
computed: {
...mapGetters('OperatoerOption', ['operatorOptionList']),
...mapGetters('OperatoerOption', getterList),
},
methods: {
...mapActions('OperatoerOption', ['fetchOperatorList']),
...mapActions('OperatoerOption', actionsList),
getOperatorName(id) {
let item = this.operatorOptionList.find(
let item = this[`operatorOptionList${this.accessType}`].find(
ServiceType => ServiceType.id === id
);
if (item) {
......
const typeMapping = [{ value: 0, label: '全部' }, { value: 1, label: '权限' }];
export default typeMapping;
<template>
<div class="Dashboard-DataCard">
<div class="Dashboard-SearchBar">
<search-item label="运营商">
<operator-select
:accessType="1"
:value="filters.operatorId"
@input="val => fetchConsumeList({ operatorId: val })"
/>
</search-item>
<el-radio-group
class="Dashboard-Radio"
:value="filters.timeType"
@input="val => fetchConsumeList({ 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>
<CampusRankChart
:data="campusRankList"
:changeCampusHandle="changeCampusHandle"
/>
</div>
</template>
<script>
import CampusRankChart from './CampusRankChart';
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'CampusRank',
components: { CampusRankChart },
computed: {
...mapGetters('Dashboard', ['campusRankList', 'filters']),
},
methods: {
...mapActions('Dashboard', ['fetchConsumeList']),
changeCampusHandle(data) {
this.fetchConsumeList({
areaId: data.areaId,
updatePercentList: true,
});
},
},
};
</script>
<template>
<div class="CampusRank">
<div id="CampusRank"></div>
<div class="CampusRank-title">截至到{{ today }},前十校区消费汇总数据</div>
</div>
</template>
<script>
import chartMixin from '../chartMixin';
import { mapActions } from 'vuex';
export default {
name: 'CampusRank',
......@@ -31,6 +31,7 @@ export default {
this.initChart();
},
methods: {
...mapActions('Dashboard', ['updateCampusName']),
initChart() {
this.chart = new G2.Chart({
container: 'CampusRank',
......@@ -65,7 +66,7 @@ export default {
></i>
<span>其他校区<br/>汇总数据</span>
</li>
`
`
: `<li
class="g2-legend-list-item item-noshow item-${index} ${checked}"
data-value="${value}"
......@@ -147,6 +148,7 @@ export default {
}
},
changeSelected(data) {
this.updateCampusName(data.areaName);
this.percentDom = document.querySelector('.CampusRank-percent');
this.areaNameDom = document.querySelector('.CampusRank-areaName');
if (this.percentDom) {
......@@ -167,6 +169,7 @@ export default {
.CampusRank-title {
font-size: 16px;
text-align: center;
padding-bottom: 12px;
}
}
</style>
<template>
<div class="Dashboard-DataCard">
<div class="Dashboard-SearchBar">
<search-item label="运营商">
<operator-select
:accessType="1"
:value="filters.operatorId"
@input="val => getRechargeOrderList({operatorId: val})"
/>
</search-item>
<search-item label="区域">
<area-select
:value="filters.areaId"
@input="val => getRechargeOrderList({areaId: val})"
type="user"
/>
</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>
<Chart
:data="consumeList"
:consumeCount="consumeCount"
/>
</div>
</template>
<script>
import Chart from './chart';
import { mapActions, mapGetters } from 'vuex';
export default {
name: 'CustomerConsumption',
components: {
Chart,
},
computed: {
...mapGetters('Dashboard/customerConsumption', [
'consumeList',
'consumeCount',
'filters',
]),
},
created() {
this.initData();
},
methods: {
...mapActions('Dashboard/customerConsumption', [
'updateFilters',
'getConsumeOrderList',
]),
initData() {
this.getConsumeOrderList();
},
},
};
</script>
import { getConsumeOrderList } from '@/api/dashboard/dashboard';
import initFiltersStore from '@/store/modules/filters';
import { getFilters, formatDate } from '@/utils/index';
const FETCH_CONSUME_LIST = 'FETCH_CONSUME_LIST';
const initFilters = () => ({
operatorId: undefined,
areaId: undefined,
timeType: 0, // 0 本日,1 本月, 2 本年
});
const filtersStore = initFiltersStore(initFilters);
const nowTime = new Date();
const state = () => ({
list: [],
consumeCountVo: {
payMen: 0,
payableMoney: 0,
},
});
const getters = {
consumeList: state => state.list,
consumeCount: state => state.consumeCountVo,
};
const actions = {
getConsumeOrderList({ commit, getters, dispatch }, data) {
if (data) {
dispatch('updateFilters', data);
}
let entity = getFilters(getters.filters);
switch (entity.timeType) {
case 1:
entity.month = formatDate(nowTime, 'yyyy-MM');
break;
case 2:
entity.year = formatDate(nowTime, 'yyyy');
break;
case 0:
default:
entity.date = formatDate(nowTime, 'yyyy-MM-dd');
break;
}
return getConsumeOrderList({
data: entity,
}).then(res => {
const { data, consumeCountVo } = res;
commit(FETCH_CONSUME_LIST, { list: data, consumeCountVo });
});
},
};
const mutations = {
[FETCH_CONSUME_LIST](state, data) {
state.list = data.list;
state.consumeCountVo = data.consumeCountVo;
},
};
export default {
namespaced: true,
modules: { filtersStore },
state,
getters,
actions,
mutations,
};
<template>
<div id='CustomerConsumptionChart'></div>
</template>
<script>
import G2 from '@antv/g2';
import chartMixin from '../chartMixin';
export default {
name: 'CustomerConsumptionChart',
mixins: [chartMixin],
props: {
consumeCount: {
type: Object,
},
},
data() {
return {
totalDom: null,
countDom: null,
};
},
mounted() {
this.initChart();
},
methods: {
initChart() {
this.chart = new G2.Chart({
container: 'CustomerConsumptionChart',
forceFit: true,
height: this.height,
padding: [100, 50, 50, 100],
});
this.chart.source(this.data);
this.chart
.axis('payableMoney')
.coord()
.transpose();
// 图例
this.chart.tooltip(false).legend(false);
// 坐标系及着色
this.chartGeom = this.chart
.interval()
.position('serviceName*payableMoney')
.color('serviceName', ['#4e82fb', '#fb774e', '#ffc934', '#41bf52'])
.label('payableMoney', {
offset: 10,
});
let money =
this.consumeCount && this.consumeCount.payableMoney
? this.consumeCount.payableMoney
: '0.00';
let menCount =
this.consumeCount && this.consumeCount.payMen
? this.consumeCount.payMen
: '0';
// 辅助元素
this.chart.guide().html({
position: ['0%', '0%'],
htmlContent: `<div style="color:#333;font-size:14px;text-align: center;">
合计消费总金额:<span class="CustomerConsumption-total" style="color:#f00;">0.00元</span>
合计消费人数:<span class="CustomerConsumption-count" style="color:#f00;">0人</span>
</div>`,
alignX: 'left',
alignY: 'top',
offsetX: -40,
offsetY: -40,
});
this.chart.render();
this.chart.guide().text({
top: true,
position: ['100%', '100%'],
content: '(元)',
offsetX: 20,
offsetY: 8,
});
},
updateData() {
this.totalDom = document.querySelector('.CustomerConsumption-total');
this.countDom = document.querySelector('.CustomerConsumption-count');
if (this.totalDom && this.countDom) {
let money =
this.consumeCount && this.consumeCount.payableMoney
? this.consumeCount.payableMoney
: '0.00';
let menCount =
this.consumeCount && this.consumeCount.payMen
? this.consumeCount.payMen
: '0';
this.totalDom.innerHTML = money + '元';
this.countDom.innerHTML = menCount + '人';
}
},
},
};
</script>
<template>
<div
class="CustomerFeedback"
@mousewheel.stop=""
>
<div class="Dashboard-SearchBar">
<div class="CustomerFeedbackTitle">
<span class="CustomerFeedback-icon"><img src="@/assets/images/dashboard/feedback.jpg"></span>
<span class="CustomerFeedback-text">反馈未处理-</span>
<span class="red">{{count}}</span>
</div>
</div>
<div class="CustomerFeedback-List">
<div
class="CustomerFeedback-Item"
v-for="(item, index) in feedbackList"
:key="index"
>
<span class="CustomerFeedback-ItemNum">{{item.count}}</span>
<span class="CustomerFeedback-ItemName">{{item.areaName}}</span>
</div>
</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'CustomerFeedback',
computed: {
...mapGetters('Dashboard/customerFeedback', ['feedbackList', 'count']),
},
created() {
this.initData();
},
methods: {
...mapActions('Dashboard/customerFeedback', ['getFeedbackList']),
initData() {
this.getFeedbackList();
},
},
};
</script>
<style lang="scss">
@import '@/assets/styles/variables.scss';
.CustomerFeedback {
display: flex;
flex-direction: column;
.CustomerFeedbackTitle {
width: 100%;
display: flex;
align-items: center;
padding: 0 20px;
line-height: 34px;
font-size: 18px;
.CustomerFeedback-icon {
width: 27px;
height: 27px;
}
.CustomerFeedback-text {
margin-left: 10px;
margin-right: 5px;
}
.red {
color: #ff0000;
}
}
.CustomerFeedback-List {
flex: 1;
overflow-y: auto;
}
.CustomerFeedback-Item {
display: flex;
align-items: center;
height: 60px;
font-size: 18px;
.CustomerFeedback-ItemNum {
width: 70px;
margin-right: 22px;
text-align: right;
color: #ff0000;
}
.CustomerFeedback-ItemName {
flex: 1;
padding-right: 20px;
line-height: 28px;
}
}
}
@media screen and (max-width: $bigScreenWidth) {
.CustomerFeedback {
.CustomerFeedback-Item {
height: 40px;
font-size: 14px;
.CustomerFeedback-ItemNum {
width: 70px;
margin-right: 22px;
}
.CustomerFeedback-ItemName {
padding-right: 20px;
line-height: 28px;
}
}
}
}
</style>
import { getFeedbackList } from '@/api/dashboard/dashboard';
const FETCH_FFEDBACK_LIST = 'FETCH_FFEDBACK_LIST';
const state = () => ({
list: [],
count: 0,
});
const getters = {
feedbackList: state => state.list,
count: state => state.count,
};
const actions = {
getFeedbackList({ commit }) {
return getFeedbackList().then(res => {
const { data, count } = res;
commit(FETCH_FFEDBACK_LIST, { list: data, count });
});
},
};
const mutations = {
[FETCH_FFEDBACK_LIST](state, data) {
state.list = data.list;
state.count = data.count;
},
};
export default {
namespaced: true,
state,
getters,
actions,
mutations,
};
<template>
<div class="Dashboard-DataCard">
<div class="Dashboard-SearchBar">
<search-item label="运营商">
<operator-select
:accessType="1"
:value="filters.operatorId"
@input="val => getRechargeOrderList({operatorId: 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>
<Chart
:data="rechargeList"
:rechargeCount="rechargeCount"
/>
</div>
</template>
<script>
import Chart from './chart';
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'CustomerRechange',
components: {
Chart,
},
computed: {
...mapGetters('Dashboard/customerRecharge', [
'rechargeList',
'rechargeCount',
'filters',
]),
},
created() {
this.initData();
},
methods: {
...mapActions('Dashboard/customerRecharge', [
'updateFilters',
'getRechargeOrderList',
]),
initData() {
this.getRechargeOrderList();
},
},
};
</script>
import { getRechargeOrderList } from '@/api/dashboard/dashboard';
import initFiltersStore from '@/store/modules/filters';
import { getFilters, formatDate } from '@/utils';
const FETCH_RECHARGE_LIST = 'FETCH_RECHARGE_LIST';
const initFilters = () => ({
operatorId: undefined,
timeType: 0, // 0 本日,1 本月, 2 本年
});
const filtersStore = initFiltersStore(initFilters);
const nowTime = new Date();
const state = () => ({
list: [],
rechargeOrderCountVo: {
rechargeMen: 0,
rechargeMoney: 0,
},
});
const getters = {
rechargeList: state => state.list,
rechargeCount: state => state.rechargeOrderCountVo,
};
const actions = {
getRechargeOrderList({ commit, getters, dispatch }, data) {
if (data) {
dispatch('updateFilters', data);
}
let entity = getFilters(getters.filters);
switch (entity.timeType) {
case 1:
entity.month = formatDate(nowTime, 'yyyy-MM');
break;
case 2:
entity.year = formatDate(nowTime, 'yyyy');
break;
case 0:
default:
entity.date = formatDate(nowTime, 'yyyy-MM-dd');
break;
}
return getRechargeOrderList({
data: entity,
}).then(res => {
const { data, rechargeOrderCountVo } = res;
commit(FETCH_RECHARGE_LIST, { list: data, rechargeOrderCountVo });
});
},
};
const mutations = {
[FETCH_RECHARGE_LIST](state, data) {
state.list = data.list;
state.rechargeOrderCountVo = data.rechargeOrderCountVo;
},
};
export default {
namespaced: true,
modules: { filtersStore },
state,
getters,
actions,
mutations,
};
<template>
<div class="CustomerRechangeChart">
<div class="CustomerRechangeChart-tip">
<span
class="CustomerRechange-tooltip"
style="background-color:#4e82fb;"
></span> 累计充值:
<span style="color:#f00;">{{ rechargeCount && rechargeCount.rechargeMoney ? (rechargeCount.rechargeMoney).toFixed(2) : '0.00' }}</span>
<span
class="CustomerRechange-tooltip"
style="background-color:#26c9a8;"
></span> 充值人数:
<span style="color:#f00;">{{ rechargeCount && rechargeCount.rechargeMen ? rechargeCount.rechargeMen : 0 }}</span>
</div>
<div id='CustomerRechangeChart'></div>
<div id='CustomerRechangeSlider'></div>
</div>
</template>
<script>
import G2 from '@antv/g2';
import Slider from '@antv/g2-plugin-slider';
import chartMixin from '../chartMixin';
import DataSet from '@antv/data-set';
import _ from 'lodash';
export default {
name: 'CustomerRechangeChart',
mixins: [chartMixin],
props: {
rechargeCount: {
type: Object,
},
},
data() {
return {
demoList: [
{ areaName: 'bvs', rechargeMoney: 13.45 },
{ areaName: 'gsn', rechargeMoney: 23.45 },
{ areaName: 'dsf', rechargeMoney: 12.45 },
{ areaName: 'bzx', rechargeMoney: 45.45 },
{ areaName: 'bvmf', rechargeMoney: 3213.454 },
{ areaName: 'swer', rechargeMoney: 256 },
{ areaName: 'cvsdf', rechargeMoney: 541 },
{ areaName: 'cvsdf', rechargeMoney: 10.15 },
],
slider: null,
sliderDom: null,
ds: null,
dv: null,
SelectedDataIndex: null,
};
},
methods: {
initData() {
this.ds = new DataSet({
state: {
startRadio: 0,
endRadio: 0.2,
},
});
const dv = this.ds.createView().source(this.data);
this.dv = dv;
dv.transform({
type: 'fold',
fields: ['rechargeMoney', 'rechargeMen'], // 展开字段集
key: 'key', // key字段
value: 'value', // value字段
retains: ['areaName'],
}).transform({
type: 'map',
callback(row) {
if (row.key === 'rechargeMoney') {
row.key = '充值金额';
}
if (row.key === 'rechargeMen') {
row.key = '充值人数';
}
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;
return (
currentRadio >= this.ds.state.startRadio &&
currentRadio <= this.ds.state.endRadio
);
},
});
this.chart = new G2.Chart({
container: 'CustomerRechangeChart',
forceFit: true,
height: this.height,
padding: [100, 50, 50, 120],
});
this.chart.source(dv);
this.chart.axis('areaName', {
label: {
offset: 5,
},
});
this.chart.axis('value');
this.chart.coord().transpose();
this.chart.legend(false);
// 坐标系及着色
this.chartGeom = this.chart
.interval()
.position('areaName*value')
.color('key', ['#4e82fb', '#26c9a8'])
.adjust([
{
type: 'dodge',
marginRatio: 0.2,
},
]);
this.chart.render();
this.initSlider();
},
initSlider() {
// const arrLength = this.data.length;
// let spanNum = 4 / arrLength;
this.sliderDom = document.getElementById('CustomerRechangeSlider');
this.slider = new Slider({
container: this.sliderDom, // dom 容器 id 或者 dom 容器对象
width: 26, // slider 的宽度,默认为 'auto',即自适应宽度
height: 300, // slider 的高度,默认为 '26px'
xAxis: 'value', // 背景图的横轴对应字段,同时为数据筛选的字段
yAxis: 'areaName', // 背景图的纵轴对应字段
startRadio: this.ds.state.startRadio, // 新增
endRadio: this.ds.state.endRadio, // 新增
data: this.data, // slider 的数据源
textStyle: {
display: 'none',
},
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);
}, // 更新数据状态量的回调函数
});
this.slider.layout = 'vertical';
this.slider.render(); // 渲染
},
updateSlider() {
let dom = this.sliderDom;
dom.innerHTML = '';
const arrLength = this.data.length;
if (arrLength) {
// let spanNum = 4 / arrLength;
this.slider = new Slider({
container: this.sliderDom,
width: 26,
height: 300,
xAxis: 'value',
yAxis: 'areaName',
startRadio: this.ds.state.startRadio,
endRadio: this.ds.state.endRadio,
data: this.data,
// minSpan: spanNum,
// maxSpan: spanNum,
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);
},
});
this.slider.layout = 'vertical';
this.slider.render();
}
},
refreshData() {
if (this.chart) {
this.dv.source(this.data);
console.log(this.slider);
this.updateSlider();
this.updateData();
} else {
this.initData();
this.initSlider();
}
},
},
};
</script>
<style lang="scss">
.CustomerRechangeChart {
position: relative;
#CustomerRechangeSlider {
margin-left: -30px;
width: 100%;
height: 300px;
transform: translate(100%, -100%);
}
.CustomerRechangeChart-tip {
position: absolute;
left: 80px;
top: 60px;
color: #333;
font-size: 14px;
text-align: center;
}
.CustomerRechange-tooltip {
display: inline-block;
width: 10px;
height: 5px;
margin-bottom: 2px;
margin-left: 20px;
}
}
</style>
<template>
<div class="Dashboard-Row Dashboard-DataCard">
<div class="Dashboard-SearchBar">
<search-item label="年份">
<el-date-picker
v-model.trim="campusFilters.year"
@change="changeReportYearHandle"
type="year"
value-format="yyyy"
placeholder="请选择"
>
</el-date-picker>
</search-item>
<search-item label="校区">
<area-select
v-model.trim="campusFilters.areaId"
@change="changeReportAreaHandle"
type="user"
/>
</search-item>
</div>
<div class="Dashboard-CampusData">
<div class="Dashboard-CampusItem">
<div class="Dashboard-title">{{ reportYear }}年每月注册数据</div>
<RegisterByMonth :data="registePerMonth"></RegisterByMonth>
</div>
<div class="Dashboard-CampusItem">
<div class="Dashboard-title">
{{ reportYear }}{{ reportMonth }}月注册数据
</div>
<RegisterByDay :data="registePerDay" />
</div>
<div class="Dashboard-CampusItem">
<div class="Dashboard-title">{{ reportYear }}年每月活跃数据</div>
<ActiveUserByMonth :data="activeUser" />
</div>
</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
import RegisterByMonth from './components/RegisterByMonth';
import RegisterByDay from './components/RegisterByDay';
import ActiveUserByMonth from './components/ActiveUserByMonth';
export default {
name: 'CustomerRegister',
components: {
RegisterByMonth,
RegisterByDay,
ActiveUserByMonth,
},
data() {
return {
campusFilters: {},
};
},
computed: {
...mapGetters('Dashboard', [
'reportYear',
'reportMonth',
'registePerDay',
'registePerMonth',
'activeUser',
]),
},
methods: {
...mapActions('Dashboard', ['fetchReportList']),
changeReportYearHandle(val) {
if (val) {
let areaId = this.campusFilters.areaId;
this.fetchReportList({
year: val,
areaId: areaId ? areaId : null,
});
}
},
changeReportAreaHandle(val) {
if (val && this.campusFilters.year) {
this.fetchReportList({
year: this.campusFilters.year,
areaId: val,
});
}
},
},
};
</script>
......@@ -4,7 +4,7 @@
<script>
import G2 from '@antv/g2';
import chartMixin from '../chartMixin';
import chartMixin from '../../chartMixin';
export default {
name: 'ActiveUserByMonth',
......
......@@ -4,7 +4,7 @@
<script>
import G2 from '@antv/g2';
import chartMixin from '../chartMixin';
import chartMixin from '../../chartMixin';
export default {
name: 'RegisterByDay',
......
......@@ -3,7 +3,7 @@
</template>
<script>
import G2 from '@antv/g2';
import chartMixin from '../chartMixin';
import chartMixin from '../../chartMixin';
export default {
name: 'RegisterByMonth',
......
......@@ -3,15 +3,30 @@ import {
fetchReportList,
fetchTitleList,
} from '@/api/dashboard/dashboard';
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';
const GET_CONSUME_DATA = 'GET_CONSUME_DATA';
const GET_REPORT_DATA = 'GET_REPORT_DATA';
const GET_TITLE_DATA = 'GET_TITLE_DATA';
const GET_PERCENT_DATA = 'GET_PERCENT_DATA';
const GET_EUIPMENT_DATA = 'GET_EUIPMENT_DATA';
const GET_CAMPUS_DATA = 'GET_CAMPUS_DATA';
const initFilters = () => ({
operatorId: undefined,
timeType: 0, // 0 本日,1 本月, 2 本年
});
const filtersStore = initFiltersStore(initFilters);
const nowTime = new Date();
const state = () => ({
consume: {
areaName: '',
consumeAfterVos: [],
consumeHardVos: [],
list: [],
percentList: [],
......@@ -37,24 +52,50 @@ const getters = {
registePerMonth: state => state.report.registePerMonth,
activeUser: state => state.report.activeUser,
titleData: state => state.title,
areaName: state => state.consume.areaName,
consumeAfterVos: state => state.consume.consumeAfterVos,
consumeHardVos: state => state.consume.consumeHardVos,
campusRankList: state => state.consume.list,
seviceRatioList: state => state.consume.percentList,
};
const actions = {
fetchConsumeList({ commit }, entity) {
fetchConsumeList({ commit, dispatch, getters }, data) {
if (data) {
const { timeType, operatorId } = data;
(timeType || timeType == 0) &&
dispatch('updateFilters', {
timeType: timeType,
});
operatorId &&
dispatch('updateFilters', {
operatorId,
});
}
let entity = getFilters(getters.filters);
switch (entity.timeType) {
case 1:
entity.month = formatDate(nowTime, 'yyyy-MM');
break;
case 2:
entity.year = formatDate(nowTime, 'yyyy');
break;
case 0:
default:
entity.date = formatDate(nowTime, 'yyyy-MM-dd');
break;
}
return fetchConsumeList({
params: {
data: {
...entity,
},
}).then(res => {
let list = res.data;
if (entity && entity.updatePercentList) {
if (data && data.updatePercentList) {
commit(GET_PERCENT_DATA, list);
return;
}
if (entity && entity.updateEuipmentList) {
if (data && data.updateEuipmentList) {
commit(GET_EUIPMENT_DATA, list);
return;
}
......@@ -77,19 +118,28 @@ const actions = {
commit(GET_TITLE_DATA, data);
});
},
updateCampusName({ commit }, name) {
commit(GET_CAMPUS_DATA, name);
},
};
const mutations = {
[GET_CONSUME_DATA]: (state, data) => {
state.consume.consumeHardVos = data.consumeHardVos;
state.consume.list = data.list;
state.consume.percentList = data.percentList;
state.consume.consumeHardVos = data.consumeHardVos
? data.consumeHardVos
: [];
state.consume.consumeAfterVos = data.consumeAfterVos
? data.consumeAfterVos
: [];
state.consume.list = data.list ? data.list : [];
state.consume.percentList = data.percentList ? data.percentList : [];
},
[GET_PERCENT_DATA]: (state, data) => {
state.consume.percentList = data.percentList;
},
[GET_EUIPMENT_DATA]: (state, data) => {
state.consume.consumeHardVos = data.consumeHardVos;
state.consume.consumeAfterVos = data.consumeAfterVos;
},
[GET_REPORT_DATA]: (state, data) => {
state.report.year = data.year;
......@@ -107,10 +157,19 @@ const mutations = {
[GET_TITLE_DATA](state, data) {
state.title = data;
},
[GET_CAMPUS_DATA](state, name) {
state.consume.areaName = name;
},
};
export default {
namespaced: true,
modules: {
filtersStore,
customerRecharge,
customerConsumption,
customerFeedback,
},
state,
getters,
actions,
......
<template>
<div class="Dashboard">
<div class="Dashboard-DataCard">
<div class="Dashboard-SearchBar">
<search-item label="年份">
<el-date-picker
v-model.trim="campusFilters.year"
@change="changeReportYearHandle"
type="year"
value-format="yyyy"
placeholder="请选择"
>
</el-date-picker>
</search-item>
<search-item label="校区">
<area-select
v-model.trim="campusFilters.areaId"
@change="changeReportAreaHandle"
type="user"
/>
</search-item>
<div>
<div class="Dashboard">
<div class="Dashboard-Row Dashboard-CustomerData">
<CustomerRecharge class="Dashboard-DataCard" />
<CustomerConsumption class="Dashboard-DataCard" />
<CustomerFeedback class="Dashboard-DataCard" />
</div>
<div class="Dashboard-CampusData">
<div class="Dashboard-CampusItem">
<div class="Dashboard-title">{{ reportYear }}年每月注册数据</div>
<RegisterByMonth :data="registePerMonth"></RegisterByMonth>
</div>
<div class="Dashboard-CampusItem">
<div class="Dashboard-title">
{{ reportYear }}{{ reportMonth }}月注册数据
</div>
<RegisterByDay :data="registePerDay" />
</div>
<div class="Dashboard-CampusItem">
<div class="Dashboard-title">{{ reportYear }}年每月活跃数据</div>
<ActiveUserByMonth :data="activeUser" />
</div>
</div>
</div>
<div class="Dashboard-OperatorData">
<div class="Dashboard-DataCard">
<div class="Dashboard-SearchBar">
<search-item label="年份">
<el-date-picker
v-model.trim="operatorFilters.year"
@change="changeConsumeYearHandle"
type="year"
value-format="yyyy"
placeholder="请选择"
></el-date-picker>
</search-item>
<search-item label="月份">
<el-date-picker
v-model.trim="operatorFilters.month"
@change="changeConsumeMouthHandle"
type="month"
value-format="MM"
format="MM"
:picker-options="monthRange"
placeholder="请选择"
></el-date-picker>
</search-item>
<search-item label="运营商">
<operator-select
v-model.trim="operatorFilters.operatorId"
@input="changeConsumeOperatorHandle"
/>
</search-item>
</div>
<CampusRank
:data="campusRankList"
:changeCampusHandle="changeCampusHandle"
/>
</div>
<div class="Dashboard-DataCard">
<div class="Dashboard-title">
<div class="Dashboard-title-icon service">
<img src="@/assets/images/dashboard/icon_zhanbi@2x.png" />
</div>
<div class="Dashboard-title-text">各服务消费占比</div>
<div class="Dashboard-title-top">TOP1</div>
</div>
<SeviceRatio
:data="seviceRatioList"
:changeServiceHandle="changeServiceHandle"
/>
</div>
<div class="Dashboard-DataCard">
<div class="Dashboard-title">
<div class="Dashboard-title-icon equipment">
<img src="@/assets/images/dashboard/icon_paiming@2x.png" />
</div>
<div class="Dashboard-title-text">各设备消费排名</div>
<div class="Dashboard-title-top">TOP1-5</div>
</div>
<EquipmentList :data="consumeHardVos" />
<div class="Dashboard-Row Dashboard-OperatorData">
<CampusRank class="Dashboard-DataCard" />
<SeviceRatio class="Dashboard-DataCard" />
<EquipmentList class="Dashboard-DataCard" />
</div>
<CustomerRegister class="Dashboard-Row Dashboard-DataCard" />
</div>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
import RegisterByMonth from './components/RegisterByMonth';
import RegisterByDay from './components/RegisterByDay';
import SeviceRatio from './components/SeviceRatio';
import CampusRank from './components/CampusRank';
import ActiveUserByMonth from './components/ActiveUserByMonth';
import EquipmentList from './components/EquipmentList';
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';
export default {
name: 'Dashboard',
components: {
RegisterByMonth,
RegisterByDay,
ActiveUserByMonth,
CustomerRegister,
CustomerRecharge,
CustomerConsumption,
CustomerFeedback,
SeviceRatio,
CampusRank,
EquipmentList,
},
data() {
return {
campusFilters: {
year: undefined,
areaId: undefined,
},
operatorFilters: {
year: undefined,
month: undefined,
operateId: undefined,
},
monthRange: {
disabledDate: time => {
return this.operatorFilters.year
? time.getTime() < new Date(this.operatorFilters.year) ||
time.getTime() > new Date(this.operatorFilters.year + '-12-31')
: true;
},
},
};
},
computed: {
...mapGetters('Dashboard', [
'reportYear',
'reportMonth',
'registePerDay',
'registePerMonth',
'activeUser',
'campusRankList',
'seviceRatioList',
'consumeHardVos',
]),
},
created() {
this.initData();
},
......@@ -165,78 +51,6 @@ export default {
this.fetchConsumeList();
this.fetchTitleList();
},
changeReportYearHandle(val) {
if (val) {
let areaId = this.campusFilters.areaId;
this.fetchReportList({
year: val,
areaId: areaId ? areaId : null,
});
}
},
changeReportAreaHandle(val) {
if (val && this.campusFilters.year) {
this.fetchReportList({
year: this.campusFilters.year,
areaId: val,
});
}
},
changeConsumeYearHandle(val) {
if (val) {
let month = this.operatorFilters.month;
let operateId = this.operatorFilters.operateId;
this.fetchConsumeList({
year: val,
month: month ? month : null,
operateId: operateId ? operateId : null,
});
}
},
changeConsumeMouthHandle(val) {
if (val && this.operatorFilters.year) {
let operateId = this.operatorFilters.operateId;
this.fetchConsumeList({
year: this.operatorFilters.year,
month: val,
operateId: operateId ? operateId : null,
});
}
},
changeConsumeOperatorHandle(val) {
if (val && this.operatorFilters.year) {
let month = this.operatorFilters.month;
this.fetchConsumeList({
year: this.operatorFilters.year,
month: month ? month : null,
operateId: val,
});
}
},
changeCampusHandle(data) {
let operateId = this.operatorFilters.operateId;
let year = this.operatorFilters.year;
let month = this.operatorFilters.month;
this.fetchConsumeList({
year: year ? year : null,
month: month ? month : null,
operateId: operateId ? operateId : null,
areaId: data.areaId,
updatePercentList: true,
});
},
changeServiceHandle(data) {
let operateId = this.operatorFilters.operateId;
let year = this.operatorFilters.year;
let month = this.operatorFilters.month;
this.fetchConsumeList({
year: year ? year : null,
month: month ? month : null,
operateId: operateId ? operateId : null,
serviceId: data.serviceId,
updateEuipmentList: true,
});
},
},
};
</script>
......@@ -244,19 +58,28 @@ export default {
<style lang="scss">
@import '@/assets/styles/variables.scss';
.Dashboard {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
background-color: #eee;
padding: 0 34px;
padding: 0 34px 38px;
overflow-y: scroll;
.Dashboard-Row {
height: calc(50% + (38px / 2 - 8px));
margin-top: 8px;
overflow: hidden;
}
.Dashboard-title {
font-size: 20px;
color: #333;
font-weight: 700;
}
.Dashboard-DataCard {
margin-top: 12px;
background-color: #fff;
border-radius: 8px;
margin-right: 8px;
&:last-child {
margin-right: 0;
}
}
.Dashboard-SearchBar {
display: flex;
......@@ -274,11 +97,51 @@ export default {
.filter-item-label {
width: auto;
}
.Dashboard-Radio {
display: flex;
align-items: center;
justify-self: flex-end;
.Dashboard-Radio-item {
margin: 0 10px;
}
}
}
.Dashboard-CustomerData {
display: flex;
.Dashboard-SearchBar {
justify-content: space-between;
border-bottom: 1px solid #f1f1f1;
.filter-item {
margin: 0 0 0 10px;
}
}
.Dashboard-DataCard {
flex: 2;
&:nth-child(2) {
flex: 2.3;
}
&:last-child {
flex: 1.2;
}
}
.Dashboard-title {
position: relative;
padding: 20px 0 0;
margin: 0 20px;
}
.Dashboard-title::before {
content: '';
position: absolute;
bottom: -12px;
left: 0;
width: 32px;
height: 4px;
background-color: #4e82fb;
}
}
.Dashboard-CampusData {
display: flex;
padding: 0 15px;
.Dashboard-title {
position: relative;
}
......@@ -299,15 +162,14 @@ export default {
}
}
.Dashboard-OperatorData {
flex: 1;
// flex: 1;
display: flex;
padding-bottom: 12px;
// padding-bottom: 12px;
// height: 400px;
.Dashboard-SearchBar {
align-items: center;
justify-content: center;
justify-content: space-around;
padding: 0;
min-width: 480px;
height: 70px;
border-bottom: 1px solid #f1f1f1;
.filter-item {
......@@ -346,7 +208,6 @@ export default {
flex: 2;
&:nth-child(2) {
flex: 1.5;
margin: 12px 12px 0;
}
}
}
......
<template>
<div class="Dashboard-DataCard">
<div class="Dashboard-title">
<div class="Dashboard-title-icon equipment">
<img src="@/assets/images/dashboard/icon_paiming@2x.png" />
</div>
<div class="Dashboard-title-text">各设备消费排名</div>
<el-radio-group v-model="showTopFive">
<el-radio-button :label="true">前五名</el-radio-button>
<el-radio-button :label="false">后五名</el-radio-button>
</el-radio-group>
</div>
<EquipmentListChart :data="showTopFive?consumeHardVos:consumeAfterVos" />
</div>
</template>
<script>
import EquipmentListChart from './EquipmentListChart';
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'EquipmentList',
components: {
EquipmentListChart,
},
data() {
return {
showTopFive: true,
};
},
computed: {
...mapGetters('Dashboard', ['consumeHardVos', 'consumeAfterVos']),
},
methods: {
...mapActions('Dashboard', ['fetchConsumeList']),
},
};
</script>
<template>
<div class="Dashboard-DataCard">
<div class="Dashboard-title">
<div class="Dashboard-title-icon service">
<img src="@/assets/images/dashboard/icon_zhanbi@2x.png" />
</div>
<div class="Dashboard-title-text">各服务消费占比</div>
<div class="Dashboard-title-top">TOP1</div>
</div>
<SeviceRatioChart
:data="seviceRatioList"
:changeServiceHandle="changeServiceHandle"
/>
<div class="SeviceRatio-title">{{areaName}}</div>
</div>
</template>
<script>
import SeviceRatioChart from './SeviceRatioChart';
import { mapActions, mapGetters } from 'vuex';
export default {
name: 'SeviceRatio',
components: { SeviceRatioChart },
computed: {
...mapGetters('Dashboard', ['seviceRatioList', 'areaName']),
},
methods: {
...mapActions('Dashboard', ['fetchConsumeList']),
changeServiceHandle(data) {
this.fetchConsumeList({
serviceId: data.serviceId,
updateEuipmentList: true,
});
},
},
};
</script>
<style lang="scss">
.SeviceRatio-title {
font-size: 16px;
text-align: center;
padding-bottom: 12px;
}
</style>
<template>
<div class="SeviceRatio">
<div id="SeviceRatio"></div>
<div class="SeviceRatio-title">成都师范学院</div>
</div>
<div id="SeviceRatio"></div>
</template>
<script>
......@@ -61,7 +58,7 @@ export default {
class="g2-legend-list-item item-${index} ${checked}"
data-value="${value}"
data-color=${color}
style="cursor: pointer;font-size:14px;"
style="cursor: pointer;font-size:14px;width:100%;"
>
<i
class="g2-legend-marker"
......@@ -103,20 +100,14 @@ export default {
alignY: 'middle',
});
this.chart.render();
this.chart.on('plotclick', this.clickHandle);
this.chart.on('interval:click', this.clickHandle);
},
updateData() {
if (this.data.length) {
this.totle = this.data.reduce((count, item) => count + item.count, 0);
let data = this.SelectedDataIndex;
if (data) {
this.changeSelected(data);
this.chartGeom.setSelected(data);
} else {
this.chartGeom.setSelected(this.data[0]);
this.changeSelected(this.data[0]);
this.SelectedDataIndex = this.data[0];
}
this.chartGeom.setSelected(this.data[0]);
this.changeSelected(this.data[0]);
this.SelectedDataIndex = this.data[0];
}
},
clickHandle(ev) {
......@@ -143,10 +134,3 @@ export default {
},
};
</script>
<style lang="scss">
.SeviceRatio-title {
font-size: 16px;
text-align: center;
}
</style>
......@@ -21,7 +21,7 @@ export default {
const innerWidth = window.innerWidth;
const innerHeight = window.innerHeight;
if (innerWidth < 1600) {
this.height = (innerHeight - 250) / 2;
this.height = (innerHeight - 270) / 2;
}
this.initData();
},
......
......@@ -137,9 +137,9 @@ export default {
height: auto;
}
.Submenu-title {
height: 46px;
line-height: 46px;
font-size: 18px;
height: 30px;
line-height: 30px;
font-size: 14px;
color: #78fcf3;
.like-icon {
margin-left: 10px;
......@@ -152,9 +152,9 @@ export default {
.Submenu-link {
display: inline-block;
min-width: 140px;
height: 40px;
line-height: 40px;
font-size: 18px;
height: 28px;
line-height: 28px;
font-size: 14px;
color: #fff;
}
.like-icon {
......@@ -163,8 +163,8 @@ export default {
}
.like-icon {
display: inline-block;
width: 16px;
height: 16px;
width: 12px;
height: 12px;
}
.like-icon,
.Submenu-link-text {
......@@ -188,6 +188,22 @@ export default {
}
.SubmenuBox {
top: 80px;
.Submenu-title {
height: 46px;
line-height: 46px;
font-size: 18px;
}
.Submenu-list {
.Submenu-link {
height: 40px;
line-height: 40px;
font-size: 18px;
}
}
.like-icon {
width: 16px;
height: 16px;
}
}
}
}
......
......@@ -448,7 +448,7 @@ export default {
this.cancelUserinfoUpdate();
})
.catch(err => {
console.log(err);
console.error(err);
});
}
},
......@@ -489,7 +489,7 @@ export default {
this.cancelCellphoneUpdate();
})
.catch(err => {
console.log(err);
console.error(err);
});
}
},
......@@ -532,17 +532,17 @@ export default {
width: 148px;
background-color: #68aaff;
border-radius: 8px;
font-size: 18px;
font-size: 14px;
overflow: hidden;
.UserMenus-Link {
cursor: pointer;
height: 46px;
line-height: 46px;
height: 30px;
line-height: 30px;
display: flex;
align-items: center;
.UserMenus-Link-icon {
width: 16px;
height: 16px;
width: 12px;
height: 12px;
margin: 0 10px 0;
}
}
......@@ -627,7 +627,16 @@ export default {
line-height: 30px;
font-size: 24px;
.UserMenus {
font-size: 18px;
top: 35px;
.UserMenus-Link {
height: 46px;
line-height: 46px;
.UserMenus-Link-icon {
width: 16px;
height: 16px;
}
}
}
}
.avatar-quit {
......
......@@ -149,7 +149,7 @@ export default {
this.$router.push({ path: '/' });
})
.catch(err => {
console.log(err);
console.error(err);
this.loading = false;
});
}
......@@ -168,7 +168,7 @@ export default {
})
.catch(err => {
this.$message.error('获取验证码失败!');
console.log(err);
console.error(err);
});
},
},
......
......@@ -20,9 +20,9 @@
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
<script src="<%= VUE_APP_LIB_MANAGER %>/customerManage/lib/customerManage.umd.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/baseManage/lib/baseManage.umd.js"></script>
<script src="<%= VUE_APP_LIB_MANAGER %>/systemManage/lib/systemManage.umd.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="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>
......
......@@ -40,7 +40,7 @@ const createBaseFetch = config => {
},
error => {
// Do something with request error
console.log(error); // for debug
console.error(error); // for debug
Promise.reject(error);
}
);
......@@ -86,7 +86,7 @@ const createBaseFetch = config => {
});
})
.catch(err => {
console.log(err);
console.error(err);
logout = false;
});
}
......
......@@ -42,7 +42,7 @@ const configRoutePermission = (router, store, allAasyncRouterMap) => {
next({ ...to, replace: true });
})
.catch(err => {
console.log(err);
console.error(err);
store.dispatch('FedLogOut').then(() => {
next({ path: '/login' });
});
......
......@@ -26,7 +26,7 @@ const actions = {
return res;
})
.catch(err => {
console.log(err);
console.error(err);
fetch--;
});
......
......@@ -33,7 +33,7 @@ const actions = {
}
})
.catch(err => {
console.log(err);
console.error(err);
commit(GET_CUSTOMER_BASEINFO, state());
});
},
......@@ -48,7 +48,7 @@ const actions = {
}
})
.catch(err => {
console.log(err);
console.error(err);
commit(GET_CUSTOMER_BASEINFO, state());
});
},
......
const UPDATE_FILTERS = 'UPDATE_FILTERS';
const RESET_FILTERS = 'RESET_FILTERS';
const initFiltersStore = (
initState = {},
initState = () => ({}),
otherGetters = {},
otherActions = {},
otherMutations = {}
) => {
const state = () => ({
filters: initState,
filters: initState(),
});
const getters = {
filters: state => state.filters,
......@@ -17,6 +18,9 @@ const initFiltersStore = (
updateFilters({ commit }, filters) {
commit(UPDATE_FILTERS, filters);
},
resetFilters({ commit }) {
commit(RESET_FILTERS);
},
...otherActions,
};
const mutations = {
......@@ -26,6 +30,9 @@ const initFiltersStore = (
...filters,
};
},
[RESET_FILTERS](state) {
state.filters = initState();
},
...otherMutations,
};
......
import { UPDATE_PAGINATION } from '../mutation-types';
const UPDATE_PAGINATION = 'UPDATE_PAGINATION';
const RESET_PAGINATION = 'RESET_PAGINATION';
const state = () => ({
pageNum: 1, // 当前分页
......@@ -17,6 +18,9 @@ const actions = {
updatePagination({ commit }, pagination) {
commit(UPDATE_PAGINATION, pagination);
},
resetPagination({ commit }) {
commit(RESET_PAGINATION);
},
};
const mutations = {
......@@ -25,6 +29,14 @@ const mutations = {
...pagination,
});
},
[RESET_PAGINATION](state) {
state = Object.assign(state, {
pageNum: 1, // 当前分页
pageSize: 10, // 分页大小
total: 0,
pages: 0,
});
},
};
export default {
......
export const USER_LOGIN = 'USER_LOGIN';
export const FETCH_PRODUCT_LIST = 'FETCH_PRODUCT_LIST';
// pagination
export const UPDATE_PAGINATION = 'UPDATE_PAGINATION';
\ No newline at end of file
......@@ -17,7 +17,6 @@ import UserDialog from '../components/Dialog/UserDialogWrap';
import AreaSelect from '../components/input/AreaSelect/index';
import ServiceTypeSelect from '../components/input/ServiceTypeSelect/index';
import GiveTypeSelect from '../components/input/GiveTypeSelect.vue';
import BaseDataSelect from '../components/input/BaseDataSelect/index';
import OperatorSelect from '../components/input/OperatorSelect/index';
import BeansSelect from '../components/input/BeanTypeSelect/index';
......@@ -42,7 +41,6 @@ const extendVue = Vue => {
Vue.component(AreaSelect.name, AreaSelect);
Vue.component(BaseDataSelect.name, BaseDataSelect);
Vue.component(ServiceTypeSelect.name, ServiceTypeSelect);
Vue.component(GiveTypeSelect.name, GiveTypeSelect);
Vue.component(OperatorSelect.name, OperatorSelect);
Vue.component(BeansSelect.name, BeansSelect);
Vue.component(ImageUploader.name, ImageUploader);
......
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