前端初始化
This commit is contained in:
@@ -0,0 +1,340 @@
|
||||
<template>
|
||||
<el-scrollbar class="demo-content">
|
||||
<el-divider>表格</el-divider>
|
||||
<vxe-table class="tree-data" :data="treeData" :empty-render="{name: 'NotData'}" align="center" border height="800px" row-id="id"
|
||||
:tree-config="{transform: true, rowField: 'id', parentField: 'parentId', expandAll: false }">
|
||||
<vxe-column show-overflow show-header-overflow field="date" title="时间" align="left" width="200" tree-node>
|
||||
<template #header>
|
||||
<div class="first-col">
|
||||
<div class="first-col-top">名称</div>
|
||||
<div class="first-col-bottom">类型</div>
|
||||
</div>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<template v-for="item in tableHeader">
|
||||
<vxe-column show-overflow show-header-overflow :field="item.field" :title="item.title"></vxe-column>
|
||||
</template>
|
||||
</vxe-table>
|
||||
|
||||
<el-divider>修改echarts横坐标顺序</el-divider>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<v-chart style="height: 300px;" :options="option1" autoresize theme="dark"></v-chart>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<div class="sort-data">
|
||||
<vuedraggable v-model="sortData">
|
||||
<transition-group>
|
||||
<template v-for="item in sortData">
|
||||
<el-button type="primary" :key="item.id">{{item.name}}</el-button>
|
||||
</template>
|
||||
</transition-group>
|
||||
</vuedraggable>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-divider>周选择器</el-divider>
|
||||
|
||||
<el-date-picker v-model="week" type="week" format="yyyy 第 WW 周" placeholder="选择周" :picker-options="{firstDayOfWeek: 1}"
|
||||
@change="handleWeekChange"/>
|
||||
{{ startDate }}~{{ endDate }} | {{ year_week }}
|
||||
|
||||
<el-divider>自定义ElementUI主题样式</el-divider>
|
||||
<el-button type="primary" size="mini">按钮</el-button>
|
||||
<el-button type="primary" size="small">按钮</el-button>
|
||||
<el-button type="primary" size="medium">按钮</el-button>
|
||||
<el-button type="primary" size="default">按钮</el-button>
|
||||
|
||||
<!--<el-divider>全局指令(获取当前标签的DOM)</el-divider>-->
|
||||
<!--<div v-dom>获取当前标签的DOM</div>-->
|
||||
|
||||
<el-divider>全局过滤器(格式化时间)</el-divider>
|
||||
<div>{{ new Date() | formatDate }}</div>
|
||||
|
||||
<el-divider>全局调用Api(使用请求拦截器)</el-divider>
|
||||
<el-button @click="exFun">Request</el-button>
|
||||
|
||||
<el-divider>vue-echarts</el-divider>
|
||||
<el-button style="margin-bottom: 10px;" @click="changeOption">修改</el-button>
|
||||
<v-chart style="height: 300px;" :options="option" autoresize theme="dark"></v-chart>
|
||||
|
||||
<el-divider>el-scrollbar</el-divider>
|
||||
<p>{{ max }} {{ value }}</p>
|
||||
<el-scrollbar ref="scrollbar" style="height: 200px;border: 1px solid #333;">
|
||||
<p v-for="item in 20" :key="item"
|
||||
style="text-align: center;background: #99a9bf;margin: 10px;line-height: 30px;">{{ item }}</p>
|
||||
</el-scrollbar>
|
||||
<el-slider v-model="value" :max="max" :format-tooltip="formatTooltip"></el-slider>
|
||||
|
||||
<el-divider>VXETable(表格与分页)</el-divider>
|
||||
<vxe-table :empty-render="{name: 'NotData'}" border show-overflow highlight-hover-row ref="xTable" height="200"
|
||||
:sort-config="{trigger: 'cell'}">
|
||||
<vxe-column show-overflow type="seq" width="100"></vxe-column>
|
||||
<vxe-column show-overflow field="name" title="Name" sortable></vxe-column>
|
||||
<vxe-column show-overflow field="sex" title="Sex"></vxe-column>
|
||||
<vxe-column show-overflow field="age" title="Age"></vxe-column>
|
||||
<vxe-column show-overflow field="address" title="Address" show-overflow></vxe-column>
|
||||
</vxe-table>
|
||||
<vxe-pager align="left" :current-page.sync="q.page" :page-size.sync="q.size" :total="q.total"></vxe-pager>
|
||||
|
||||
<el-divider>vuex-persistedstate</el-divider>
|
||||
<el-button @click="saveUserInfo">vuex-persistedstate: {{ $store.state.userInfo }}</el-button>
|
||||
|
||||
<el-divider>uuid</el-divider>
|
||||
<p>uuid: {{ uuid }}</p>
|
||||
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {v4 as uuidv4} from "uuid";
|
||||
import vuedraggable from 'vuedraggable'
|
||||
|
||||
export default {
|
||||
name: "Demo",
|
||||
components: {
|
||||
vuedraggable
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
option1: {
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: [],
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: [],
|
||||
type: "scatter",
|
||||
symbolSize: function (data) {
|
||||
return data[1] / 2.5;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
sortData: [
|
||||
{id: uuidv4(), name: 'Mon', value: 150},
|
||||
{id: uuidv4(), name: 'Tue', value: 230},
|
||||
{id: uuidv4(), name: 'Wed', value: 224},
|
||||
{id: uuidv4(), name: 'Thu', value: 218},
|
||||
{id: uuidv4(), name: 'Fri', value: 135},
|
||||
{id: uuidv4(), name: 'Sat', value: 147},
|
||||
{id: uuidv4(), name: 'Sun', value: 260},
|
||||
],
|
||||
week: "",
|
||||
year_week: "",
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
option: {
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: [150, 230, 224, 218, 135, 147, 260],
|
||||
type: "line",
|
||||
},
|
||||
],
|
||||
},
|
||||
max: 0,
|
||||
value: 0,
|
||||
q: {
|
||||
page: 1,
|
||||
size: 20,
|
||||
total: 200,
|
||||
},
|
||||
uuid: uuidv4(),
|
||||
tableHeader: [
|
||||
{ field: 'a', title: '2020-01'},
|
||||
{ field: 'b', title: '2020-02'},
|
||||
{ field: 'c', title: '2020-03'},
|
||||
{ field: 'd', title: '2020-04'},
|
||||
],
|
||||
treeData: [
|
||||
{ id: 10000, parentId: null, a: 'Test1', b: '1111', c: '222', d: '3333' },
|
||||
{ id: 10001, parentId: 10000, a: 'Test1', b: '1111', c: '222', d: '3333' },
|
||||
{ id: 10002, parentId: 10000, a: 'Test1', b: '1111', c: '222', d: '3333' },
|
||||
{ id: 10003, parentId: 10000, a: 'Test1', b: '1111', c: '222', d: '3333' },
|
||||
{ id: 20000, parentId: null, a: 'Test2', b: '1111', c: '222', d: '3333' },
|
||||
{ id: 20001, parentId: 20000, a: 'Test2', b: '1111', c: '222', d: '3333' },
|
||||
{ id: 20002, parentId: 20000, a: 'Test2', b: '1111', c: '222', d: '3333' },
|
||||
{ id: 20003, parentId: 20000, a: 'Test2', b: '1111', c: '222', d: '3333' },
|
||||
{ id: 20004, parentId: 20000, a: 'Test2', b: '1111', c: '222', d: '3333' },
|
||||
{ id: 30000, parentId: null, a: 'Test3', b: '1111', c: '222', d: '3333' },
|
||||
{ id: 30001, parentId: 30000, a: 'Test3', b: '1111', c: '222', d: '3333' },
|
||||
{ id: 40000, parentId: null, a: 'Test4', b: '1111', c: '222', d: '3333' },
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleTree(arr){
|
||||
let cloneData = JSON.parse(JSON.stringify(arr)) // 对源数据深度克隆
|
||||
return cloneData.filter((father) => {
|
||||
let branchArr = cloneData.filter(child => father.id == child.parentId); //返回每一项的子级数组
|
||||
father.children = branchArr.length > 0 ? branchArr : null; //如果存在子级,则给父级添加一个children属性,并赋值
|
||||
return father.parentId == -1; //返回第一层
|
||||
})
|
||||
},
|
||||
|
||||
handleWeekChange(val) {
|
||||
let date = `${new Date(val).getFullYear()}-${new Date(val).getMonth() + 1}-${new Date(val).getDate()}`;
|
||||
|
||||
let firstTime = new Date(date).getTime() - 24 * 60 * 60 * 1000;
|
||||
this.startDate = `${new Date(firstTime).getFullYear()}-${new Date(firstTime).getMonth() + 1}-${new Date(firstTime).getDate()}`;
|
||||
|
||||
let lastTime = new Date(date).getTime() + 5 * 24 * 60 * 60 * 1000;
|
||||
this.endDate = `${new Date(lastTime).getFullYear()}-${new Date(lastTime).getMonth() + 1}-${new Date(lastTime).getDate()}`;
|
||||
|
||||
let year = require("moment")(val).utcOffset("+08:00").format("yyyy");
|
||||
let week = require("moment")(val).utcOffset("+08:00").format("WW");
|
||||
this.year_week = `${year} 第 ${week} 周`;
|
||||
},
|
||||
// Api
|
||||
exFun() {
|
||||
console.log(require("moment"));
|
||||
this.$api.ex
|
||||
.exFun()
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
},
|
||||
|
||||
// vue-echarts
|
||||
changeOption() {
|
||||
this.option.series[0].type = "bar";
|
||||
},
|
||||
|
||||
// el-scrollbar
|
||||
scrollChange() {
|
||||
this.max =
|
||||
this.$refs.scrollbar.wrap.scrollHeight -
|
||||
this.$refs.scrollbar.wrap.clientHeight;
|
||||
this.$refs.scrollbar.wrap.onscroll = (e) => {
|
||||
this.value = e.target.scrollTop;
|
||||
};
|
||||
},
|
||||
formatTooltip(value) {
|
||||
this.$refs.scrollbar.wrap.scrollTop = value;
|
||||
},
|
||||
|
||||
// VXETable
|
||||
getTableData() {
|
||||
this.$nextTick(() => {
|
||||
const $table = this.$refs.xTable;
|
||||
const list = [];
|
||||
for (let index = 0; index < 50; index++) {
|
||||
list.push({
|
||||
name: `名称${index}`,
|
||||
sex: "0",
|
||||
num: 123,
|
||||
age: 18,
|
||||
num2: 234,
|
||||
rate: 3,
|
||||
address: "shenzhen",
|
||||
});
|
||||
}
|
||||
$table.loadData(list);
|
||||
});
|
||||
},
|
||||
|
||||
// vuex-persistedstate
|
||||
saveUserInfo() {
|
||||
// this.$store.commit("saveUserInfo", {name: "Lee"});
|
||||
},
|
||||
},
|
||||
created() {
|
||||
console.log("created");
|
||||
},
|
||||
mounted() {
|
||||
this.scrollChange();
|
||||
this.getTableData();
|
||||
console.log("mounted");
|
||||
},
|
||||
updated(){
|
||||
// 修改统计顺序
|
||||
this.option1.xAxis.data = this.sortData.map(item => item.name);
|
||||
this.option1.series[0].data = this.sortData.map(item => [item.name, item.value]);
|
||||
},
|
||||
// 进入组件执行 仅在keep-alive时起作用
|
||||
activated() {
|
||||
this.$refs.scrollbar.wrap.scrollTop = this.value;
|
||||
console.log("activated");
|
||||
},
|
||||
// 离开组件执行 仅在keep-alive时起作用
|
||||
deactivated() {
|
||||
console.log("deactivated");
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.demo-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 20px;
|
||||
background-color: #FAFAFA;
|
||||
.sort-data{
|
||||
padding: 5px 10px;
|
||||
background-color: #333333;
|
||||
>div>span{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.el-button{
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.tree-data{
|
||||
::v-deep .vxe-header--column.col--ellipsis > .vxe-cell:first-child{
|
||||
padding: 0;
|
||||
.first-col {
|
||||
position: relative;
|
||||
height: 40px;
|
||||
width: 200px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
&:before{
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: -2px;
|
||||
top: 20px;
|
||||
width: 204px;
|
||||
height: 1px;
|
||||
transform: rotate(11deg);
|
||||
background-color: #e8eaec;
|
||||
}
|
||||
.first-col-top {
|
||||
flex: 1;
|
||||
text-align: left;
|
||||
padding: 10px 0 0 10px;
|
||||
}
|
||||
.first-col-bottom{
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
padding: 0 10px 10px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
::v-deep .vxe-table--body .vxe-body--row>td:first-child{
|
||||
background-color: #F2F6FC;
|
||||
|
||||
}
|
||||
::v-deep .vxe-table--body tbody> tr:nth-child(2n) td{
|
||||
background-color: #FAFAFA;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,308 @@
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as echarts from 'echarts/lib/echarts'
|
||||
import debounce from 'lodash/debounce'
|
||||
import {addListener, removeListener} from 'resize-detector'
|
||||
|
||||
// enumerating ECharts events for now
|
||||
const EVENTS = [
|
||||
'legendselectchanged',
|
||||
'legendselected',
|
||||
'legendunselected',
|
||||
'legendscroll',
|
||||
'datazoom',
|
||||
'datarangeselected',
|
||||
'timelinechanged',
|
||||
'timelineplaychanged',
|
||||
'restore',
|
||||
'dataviewchanged',
|
||||
'magictypechanged',
|
||||
'geoselectchanged',
|
||||
'geoselected',
|
||||
'geounselected',
|
||||
'pieselectchanged',
|
||||
'pieselected',
|
||||
'pieunselected',
|
||||
'mapselectchanged',
|
||||
'mapselected',
|
||||
'mapunselected',
|
||||
'axisareaselected',
|
||||
'focusnodeadjacency',
|
||||
'unfocusnodeadjacency',
|
||||
'brush',
|
||||
'brushselected',
|
||||
'rendered',
|
||||
'finished',
|
||||
'click',
|
||||
'dblclick',
|
||||
'mouseover',
|
||||
'mouseout',
|
||||
'mousemove',
|
||||
'mousedown',
|
||||
'mouseup',
|
||||
'globalout',
|
||||
'contextmenu'
|
||||
]
|
||||
|
||||
const ZR_EVENTS = [
|
||||
'click',
|
||||
'mousedown',
|
||||
'mouseup',
|
||||
'mousewheel',
|
||||
'dblclick',
|
||||
'contextmenu'
|
||||
]
|
||||
|
||||
const INIT_TRIGGERS = ['theme', 'initOptions', 'autoresize']
|
||||
const REWATCH_TRIGGERS = ['manualUpdate', 'watchShallow']
|
||||
|
||||
export default {
|
||||
props: {
|
||||
options: Object,
|
||||
theme: [String, Object],
|
||||
initOptions: Object,
|
||||
group: String,
|
||||
autoresize: Boolean,
|
||||
watchShallow: Boolean,
|
||||
manualUpdate: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
lastArea: 0
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
group(group) {
|
||||
this.chart.group = group
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// provide an explicit merge option method
|
||||
mergeOptions(options, notMerge, lazyUpdate) {
|
||||
if (this.manualUpdate) {
|
||||
this.manualOptions = options
|
||||
}
|
||||
|
||||
if (!this.chart) {
|
||||
this.init(options)
|
||||
} else {
|
||||
this.delegateMethod('setOption', options, notMerge, lazyUpdate)
|
||||
}
|
||||
},
|
||||
// just delegates ECharts methods to Vue component
|
||||
// use explicit params to reduce transpiled size for now
|
||||
appendData(params) {
|
||||
this.delegateMethod('appendData', params)
|
||||
},
|
||||
resize(options) {
|
||||
this.delegateMethod('resize', options)
|
||||
},
|
||||
dispatchAction(payload) {
|
||||
this.delegateMethod('dispatchAction', payload)
|
||||
},
|
||||
convertToPixel(finder, value) {
|
||||
return this.delegateMethod('convertToPixel', finder, value)
|
||||
},
|
||||
convertFromPixel(finder, value) {
|
||||
return this.delegateMethod('convertFromPixel', finder, value)
|
||||
},
|
||||
containPixel(finder, value) {
|
||||
return this.delegateMethod('containPixel', finder, value)
|
||||
},
|
||||
showLoading(type, options) {
|
||||
this.delegateMethod('showLoading', type, options)
|
||||
},
|
||||
hideLoading() {
|
||||
this.delegateMethod('hideLoading')
|
||||
},
|
||||
getDataURL(options) {
|
||||
return this.delegateMethod('getDataURL', options)
|
||||
},
|
||||
getConnectedDataURL(options) {
|
||||
return this.delegateMethod('getConnectedDataURL', options)
|
||||
},
|
||||
clear() {
|
||||
this.delegateMethod('clear')
|
||||
},
|
||||
dispose() {
|
||||
this.delegateMethod('dispose')
|
||||
},
|
||||
delegateMethod(name, ...args) {
|
||||
if (!this.chart) {
|
||||
this.init()
|
||||
}
|
||||
return this.chart[name](...args)
|
||||
},
|
||||
delegateGet(methodName) {
|
||||
if (!this.chart) {
|
||||
this.init()
|
||||
}
|
||||
return this.chart[methodName]()
|
||||
},
|
||||
getArea() {
|
||||
return this.$el.offsetWidth * this.$el.offsetHeight
|
||||
},
|
||||
init(options) {
|
||||
if (this.chart) {
|
||||
return
|
||||
}
|
||||
|
||||
let chart = echarts.init(this.$el, this.theme, this.initOptions)
|
||||
|
||||
if (this.group) {
|
||||
chart.group = this.group
|
||||
}
|
||||
|
||||
chart.setOption(options || this.manualOptions || this.options || {}, true)
|
||||
|
||||
// expose ECharts events as custom events
|
||||
EVENTS.forEach(event => {
|
||||
chart.on(event, params => {
|
||||
this.$emit(event, params)
|
||||
})
|
||||
})
|
||||
|
||||
ZR_EVENTS.forEach(event => {
|
||||
chart.getZr().on(event, params => {
|
||||
this.$emit(`zr:${event}`, params)
|
||||
})
|
||||
})
|
||||
|
||||
if (this.autoresize) {
|
||||
this.lastArea = this.getArea()
|
||||
this.__resizeHandler = debounce(() => {
|
||||
if (this.lastArea === 0) {
|
||||
// emulate initial render for initially hidden charts
|
||||
this.mergeOptions({}, true)
|
||||
this.resize()
|
||||
this.mergeOptions(this.options || this.manualOptions || {}, true)
|
||||
} else {
|
||||
this.resize()
|
||||
}
|
||||
this.lastArea = this.getArea()
|
||||
}, 100, {leading: true})
|
||||
addListener(this.$el, this.__resizeHandler)
|
||||
}
|
||||
|
||||
Object.defineProperties(this, {
|
||||
// Only recalculated when accessed from JavaScript.
|
||||
// Won't update DOM on value change because getters
|
||||
// don't depend on reactive values
|
||||
width: {
|
||||
configurable: true,
|
||||
get: () => {
|
||||
return this.delegateGet('getWidth')
|
||||
}
|
||||
},
|
||||
height: {
|
||||
configurable: true,
|
||||
get: () => {
|
||||
return this.delegateGet('getHeight')
|
||||
}
|
||||
},
|
||||
isDisposed: {
|
||||
configurable: true,
|
||||
get: () => {
|
||||
return !!this.delegateGet('isDisposed')
|
||||
}
|
||||
},
|
||||
computedOptions: {
|
||||
configurable: true,
|
||||
get: () => {
|
||||
return this.delegateGet('getOption')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
this.chart = chart
|
||||
},
|
||||
initOptionsWatcher() {
|
||||
if (this.__unwatchOptions) {
|
||||
this.__unwatchOptions()
|
||||
this.__unwatchOptions = null
|
||||
}
|
||||
|
||||
if (!this.manualUpdate) {
|
||||
this.__unwatchOptions = this.$watch('options', (val, oldVal) => {
|
||||
if (!this.chart && val) {
|
||||
this.init()
|
||||
} else {
|
||||
// mutating `options` will lead to merging
|
||||
// replacing it with new reference will lead to not merging
|
||||
// eg.
|
||||
// `this.options = Object.assign({}, this.options, { ... })`
|
||||
// will trigger `this.chart.setOption(val, true)
|
||||
// `this.options.title.text = 'Trends'`
|
||||
// will trigger `this.chart.setOption(val, false)`
|
||||
this.chart.setOption(val, val !== oldVal)
|
||||
}
|
||||
}, {deep: !this.watchShallow})
|
||||
}
|
||||
},
|
||||
destroy() {
|
||||
if (this.autoresize) {
|
||||
removeListener(this.$el, this.__resizeHandler)
|
||||
}
|
||||
this.dispose()
|
||||
this.chart = null
|
||||
},
|
||||
refresh() {
|
||||
if (this.chart) {
|
||||
this.destroy()
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.initOptionsWatcher()
|
||||
|
||||
INIT_TRIGGERS.forEach(prop => {
|
||||
this.$watch(prop, () => {
|
||||
this.refresh()
|
||||
}, {deep: true})
|
||||
})
|
||||
|
||||
REWATCH_TRIGGERS.forEach(prop => {
|
||||
this.$watch(prop, () => {
|
||||
this.initOptionsWatcher()
|
||||
this.refresh()
|
||||
})
|
||||
})
|
||||
},
|
||||
mounted() {
|
||||
// auto init if `options` is already provided
|
||||
if (this.options) {
|
||||
this.init()
|
||||
}
|
||||
},
|
||||
activated() {
|
||||
if (this.autoresize) {
|
||||
this.chart && this.chart.resize()
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
if (this.chart) {
|
||||
this.destroy()
|
||||
}
|
||||
},
|
||||
connect(group) {
|
||||
if (typeof group !== 'string') {
|
||||
group = group.map(chart => chart.chart)
|
||||
}
|
||||
echarts.connect(group)
|
||||
},
|
||||
disconnect(group) {
|
||||
echarts.disConnect(group)
|
||||
},
|
||||
registerMap(mapName, geoJSON, specialAreas) {
|
||||
echarts.registerMap(mapName, geoJSON, specialAreas)
|
||||
},
|
||||
registerTheme(name, theme) {
|
||||
echarts.registerTheme(name, theme)
|
||||
},
|
||||
graphic: echarts.graphic
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,222 @@
|
||||
<template>
|
||||
<div class="header">
|
||||
<div class="logo">
|
||||
<img src="@/assets/imgs/logo.jpg" alt="">
|
||||
</div>
|
||||
<div class="breadcrumb">
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item :to="{ path: '/report/list', query: {showId: $route.query.id } }"><img
|
||||
src="@/assets/imgs/icon-home.png" alt=""><span>首页</span></el-breadcrumb-item>
|
||||
<el-breadcrumb-item v-if="this.$route.path == '/system/urlIndex'">{{this.$store.state.menuName}}</el-breadcrumb-item>
|
||||
<el-breadcrumb-item v-else-if="this.$route.path == '/system/401Page'">{{this.$store.state.menuName}}</el-breadcrumb-item>
|
||||
<template v-else v-for="item in $route.meta.crumb">
|
||||
<el-breadcrumb-item>{{ item }}</el-breadcrumb-item>
|
||||
</template>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
|
||||
<div style="display: flex;margin-left: auto">
|
||||
<div class="setsys-menu" @click="goSystemPage" v-if="isSystemManager">
|
||||
<img src="../assets/imgs/icon-setting.png" alt="" width="14" height="14">
|
||||
<span>系统设置</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<el-popover v-model="popoverValue" trigger="click" transition="">
|
||||
<div class="user-operate">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-button type="text" @click="logout">退出系统</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="user" slot="reference">
|
||||
<img src="@/assets/imgs/avatar.png" alt="">
|
||||
<span>你好,{{$store.state.userInfo.usname}}</span>
|
||||
<i v-if="!popoverValue" class="el-icon-arrow-down"></i>
|
||||
<i v-else class="el-icon-arrow-up"></i>
|
||||
</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters} from 'vuex';
|
||||
import {BASE_URL} from "../utils/http";
|
||||
|
||||
export default {
|
||||
name: "Header",
|
||||
data() {
|
||||
return {
|
||||
popoverValue: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
menuData: 'menuData',
|
||||
}),
|
||||
isSystemManager() {
|
||||
return this.menuData.some(menu => menu.id === 'AVL9YSB7ZF');
|
||||
},
|
||||
isSystemManagerBelong() {
|
||||
return this.menuData.some(menu => menu.id === 'AVL9YSB7ZF' && menu.belong == 1);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 退出系统
|
||||
logout() {
|
||||
this.$confirm('确定退出系统?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$api.login.logout().then(_ => {
|
||||
this.$message.success('退出成功');
|
||||
this.$store.commit('saveUserInfo', null);
|
||||
|
||||
// var sevice = "http://"+window.location.host+"/";
|
||||
// var serviceUrl = encodeURIComponent(sevice);
|
||||
//正式
|
||||
// window.open("https://caddmuat.changan.com.cn/cas/logout?service=http://10.64.23.30:7766/home", '_self');
|
||||
//测试
|
||||
// window.open(BASE_URL.BASE_CHANGAN + "/logout?service=" + BASE_URL.BASE_LOCAL + "/login?loginType=1", '_self');
|
||||
this.$router.push('/login');
|
||||
})
|
||||
})
|
||||
},
|
||||
goSystemPage() {
|
||||
if(this.isSystemManagerBelong){
|
||||
if (this.$route.path === '/system/menu') return;
|
||||
this.$store.commit('savePathUrl', '/system/menu');
|
||||
this.$router.push({path: '/system/menu', query: {id: 'AVL9YSB7ZF'}});
|
||||
}else{
|
||||
if(this.$route.path == '/system/401Page'){
|
||||
|
||||
}else{
|
||||
this.$router.replace({name: '401Page', query: {id: 'AVL9YSB7ZF'}});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
background: rgb(4, 71, 155);
|
||||
|
||||
.logo {
|
||||
width: 200px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
width: auto !important;
|
||||
height: 40px !important;
|
||||
// width: 172px;
|
||||
// height: 26px;
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
padding-left: 30px;
|
||||
height: 100%;
|
||||
|
||||
::v-deep .el-breadcrumb {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
.el-breadcrumb__item {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
.el-breadcrumb__inner {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin-right: 3px;
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #FFFFFF;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.el-breadcrumb__separator {
|
||||
margin: 0 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.setsys-menu {
|
||||
margin-right: 10px;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
/*position: absolute;*/
|
||||
/*right: 225px;*/
|
||||
cursor: pointer;
|
||||
|
||||
span {
|
||||
color: #FFFFFF;
|
||||
margin-left: 5px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.user {
|
||||
/*position: absolute;*/
|
||||
/*top: 0;*/
|
||||
/*right: 0;*/
|
||||
/*bottom: 0;*/
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 16px;
|
||||
color: #FFFFFF;
|
||||
margin-right: 19px;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 17px;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.user-operate {
|
||||
::v-deep .el-button {
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<div class="menu-submenu" :class="{'submenu-active': $route.path.indexOf(path) !== -1}">
|
||||
<!-- 遍历菜单数据 -->
|
||||
<MenuItem :key="item.id" v-for="(item, index) in menuData" :menuItemData="item">
|
||||
<!-- 没有children的子菜单 -->
|
||||
<template v-if="!item.children">
|
||||
<div class="menu-content" :class="{'active': item.href.indexOf($route.path) !== -1 || (item.href==$store.state.pathUrl)}">
|
||||
<div class="menu-data" @click="handleRouter(item)"
|
||||
:style="{'padding-left': item.level >= 2 ? '30px' : '10px'}">
|
||||
<div class="menu-data-flex">
|
||||
<img class="menu-icon" v-if="item.icon" :src="item.icon" alt="">
|
||||
<span> <i class="icon-level2" v-if="item.level===3"></i> {{ item.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 有children的子菜单 -->
|
||||
<template v-else>
|
||||
<div class="menu-content"
|
||||
:class="{'active': item.href.indexOf($route.path) !== -1 || (item.href==$store.state.pathUrl), 'is-collage': !item.isCollage}"
|
||||
@click="collageMenu(item)">
|
||||
<div class="menu-data"
|
||||
:class="item.level === 1 ? 'bor-b' : ''"
|
||||
:style="{'padding-left': item.level >= 2 ? '30px' : '10px'}">
|
||||
<div class="menu-data-flex">
|
||||
<img class="menu-icon" v-if="item.icon" :src="item.icon" alt="">
|
||||
<span>{{ item.label }}</span>
|
||||
</div>
|
||||
<template v-if="item.level === 1">
|
||||
<i v-if="!item.isCollage" class="el-icon-arrow-right" style="margin-right: 12px;"></i>
|
||||
<i v-else class="el-icon-arrow-down" style="margin-right: 12px;"></i>
|
||||
</template>
|
||||
<template v-else>
|
||||
<i v-if="!item.isCollage" class="el-icon-plus" style="margin-right: 12px;"></i>
|
||||
<i v-else class="el-icon-minus" style="margin-right: 12px;"></i>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 递归操作 -->
|
||||
<Menu :menuData="item.children" :path="item.href"></Menu>
|
||||
</template>
|
||||
</MenuItem>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {createLogger} from 'vuex';
|
||||
import MenuItem from "./MenuItem";
|
||||
import login from '../api/modules/login'
|
||||
import store from '../store'
|
||||
export default {
|
||||
name: "Menu",
|
||||
props: ["menuData", "path"],
|
||||
components: {
|
||||
MenuItem
|
||||
},
|
||||
methods: {
|
||||
handleRouter(item) {
|
||||
if(item.belong == 0){
|
||||
this.$store.commit('saveMenuName', item.label);
|
||||
if(this.$route.path == '/system/401Page'){
|
||||
|
||||
}else{
|
||||
this.$router.push({name: '401Page', query: this.$route.query});
|
||||
}
|
||||
}else{
|
||||
this.$store.commit('savePathUrl', item.href);
|
||||
if (item.isUrl && Number(item.isUrl || 0)) {
|
||||
var param = this.$route.query
|
||||
// delete(this.$route.query.itemHref)
|
||||
|
||||
// param.itemHref = item.href
|
||||
if(this.$route.path == '/system/urlIndex'){
|
||||
this.$store.commit('saveMenuName', item.label);
|
||||
login.pageLog(this.$store.state.menuName).then(res => {
|
||||
}).catch(_ => {
|
||||
})
|
||||
}else{
|
||||
this.$store.commit('saveMenuName', item.label);
|
||||
this.$router.push({name: 'urlIndex', query: param});
|
||||
}
|
||||
} else {
|
||||
if (this.$route.path === item.href) return;
|
||||
// delete(this.$route.query.itemHref)
|
||||
this.$router.push({path: item.href, query: this.$route.query});
|
||||
}
|
||||
}
|
||||
},
|
||||
collageMenu(item) {
|
||||
item.isCollage = !item.isCollage;
|
||||
console.log(item.isCollage);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.menu-submenu {
|
||||
background-color: #f3f6fd;
|
||||
|
||||
&.submenu-active {
|
||||
// background-color: #f3f6fd;
|
||||
|
||||
}
|
||||
|
||||
.menu-content {
|
||||
overflow: hidden;
|
||||
height: 48px;
|
||||
|
||||
&.active {
|
||||
.menu-data {
|
||||
position: relative;
|
||||
// background-color: rgba(216, 230, 246, 1);
|
||||
background-color: #c7d0dd;
|
||||
// border-radius: 100px 0 0 100px;
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 4px;
|
||||
background-color: #168fe3;
|
||||
}
|
||||
|
||||
span {
|
||||
// color: rgba(24, 144, 255, 1);
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-collage + .menu-submenu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.menu-data {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
/*justify-content: space-between;*/
|
||||
align-items: center;
|
||||
padding-left: 21px;
|
||||
// margin-top: 6px;
|
||||
height: 100%;
|
||||
// background-color: #EDEDED;
|
||||
|
||||
.menu-data-flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 5px;
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
color: #262626;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
/*white-space: nowrap;*/
|
||||
}
|
||||
}
|
||||
|
||||
.menu-submenu {
|
||||
.menu-data {
|
||||
span {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.icon-level2 {
|
||||
display: inline-block;
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
background-color: #333;
|
||||
// background-color: rgba(183, 191, 195, 1);
|
||||
border-radius: 50%;
|
||||
margin-right: 3px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.bor-b {
|
||||
border-top: 1px solid #e3e8f3;
|
||||
border-bottom: 1px solid #e3e8f3;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<div class="menu-item" :class="{'active': (menuItemData.href.indexOf($route.path) !== -1) || (menuItemData.href == $store.state.pathUrl)}"><slot/></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "MenuItem",
|
||||
props: ['menuItemData']
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.menu-item{
|
||||
&.active{
|
||||
// background: #F8F8FA;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="品牌->车型->款型"
|
||||
style=";font-family: auto"
|
||||
class="my-dialog"
|
||||
:visible.sync="dialogVisible">
|
||||
<div class="AZClass">
|
||||
<div class="word-list" ref="letterList">
|
||||
<div class="letterClass" :class="{hoverClass: clicked == item}"
|
||||
v-for="item in wordList"
|
||||
:key="item"
|
||||
@click="goIndex(item)">
|
||||
{{ item }}
|
||||
</div>
|
||||
</div>
|
||||
<el-cascader-panel style="height:638px" :props="{multiple:false}" ref="groupRef" :options="options"
|
||||
@change="selectFun">
|
||||
<template slot-scope="{ node, data }" :class="{hoverClass: data.level != 3}">
|
||||
<div v-if="data.level != 3">
|
||||
<span v-if="wordList.indexOf(data.label) != -1">{{ data.label }}</span>
|
||||
<span v-else>{{ data.label }}</span>
|
||||
</div>
|
||||
<div v-else style="display: inline-flex;width: 100%;padding-bottom: 5px">
|
||||
<span style="display: inline-block;width: 66%;white-space: break-spaces;line-height: 17px">{{data.data.kxmc}}</span>
|
||||
<span style="display: inline-block;width: 17%;line-height: 17px;position: absolute;left: 66%">{{data.data.msrpw ? (data.data.msrpw + '万') : '-'}}</span>
|
||||
<span style="display: inline-block;width: 17%;line-height: 17px;position: absolute;left: 83%">{{data.data.mix && data.data.mix!='-' ? data.data.mix : '0.00%'}}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-cascader-panel>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
clicked: '',
|
||||
options: [],
|
||||
wordList: [
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
'D',
|
||||
'E',
|
||||
'F',
|
||||
'G',
|
||||
'H',
|
||||
'I',
|
||||
'J',
|
||||
'K',
|
||||
'L',
|
||||
'M',
|
||||
'N',
|
||||
'O',
|
||||
'P',
|
||||
'Q',
|
||||
'R',
|
||||
'S',
|
||||
'T',
|
||||
'U',
|
||||
'V',
|
||||
'W',
|
||||
'X',
|
||||
'Y',
|
||||
'Z'
|
||||
],
|
||||
dialogVisible: false
|
||||
}
|
||||
},
|
||||
props: ['callback'],
|
||||
mounted() {
|
||||
this.getList()
|
||||
this.clicked = ''
|
||||
},
|
||||
methods: {
|
||||
changeOpen() {
|
||||
this.dialogVisible = !this.dialogVisible
|
||||
},
|
||||
selectFun(item) {
|
||||
if (this.callback && item.length == 3) {
|
||||
this.callback(item)
|
||||
this.dialogVisible = false
|
||||
}
|
||||
},
|
||||
getList() {
|
||||
this.options = []
|
||||
this.$api.config.gradient.chooseStyleAdd().then(res => {
|
||||
this.options = this.formatDataFirst(res.data)
|
||||
// Object.keys(res.data).forEach(key => {
|
||||
// // tag
|
||||
// let d = {
|
||||
// value:key,
|
||||
// label:key
|
||||
// }
|
||||
// this.options.push(d)
|
||||
// // info
|
||||
// let info = res.data[key]
|
||||
// Object.keys(info).forEach(newkey => {
|
||||
// debugger
|
||||
// let ib = {
|
||||
// value:newkey,
|
||||
// label:newkey,
|
||||
// children:info[newkey]
|
||||
// }
|
||||
// this.options.push(ib)
|
||||
// })
|
||||
|
||||
// });
|
||||
//
|
||||
})
|
||||
},
|
||||
formatDataFirst(data) {
|
||||
let list = []
|
||||
Object.keys(data).forEach(key => {
|
||||
// tag
|
||||
let d = {
|
||||
level: 1,
|
||||
value: key,
|
||||
label: key
|
||||
}
|
||||
list.push(d)
|
||||
// info
|
||||
let info = data[key]
|
||||
Object.keys(info).forEach(newkey => {
|
||||
let ib = {
|
||||
level: 1,
|
||||
value: newkey,
|
||||
label: newkey,
|
||||
children: []
|
||||
}
|
||||
ib.children = this.formatData(info[newkey])
|
||||
list.push(ib)
|
||||
})
|
||||
|
||||
});
|
||||
return list
|
||||
},
|
||||
formatData(data) {
|
||||
let list = []
|
||||
Object.keys(data).forEach(key => {
|
||||
let id = data[key]
|
||||
let d = {
|
||||
level: 2,
|
||||
value: key,
|
||||
label: key,
|
||||
children: []
|
||||
}
|
||||
id.forEach(newdata => {
|
||||
let ib = {
|
||||
level: 3,
|
||||
value: newdata,
|
||||
label: newdata['kxmc'] + (newdata['msrpw'] ? (" " + newdata['msrpw']) : '') + " " + newdata['mix'],
|
||||
data: newdata
|
||||
}
|
||||
d.children.push(ib)
|
||||
})
|
||||
// debugger
|
||||
list.push(d)
|
||||
})
|
||||
|
||||
return list
|
||||
},
|
||||
goIndex(params) {
|
||||
const groupRef = this.$refs.groupRef.$children[0].$children[0].$refs.resize
|
||||
const titleRef = this.$refs.groupRef.$children[0].$children[0].$refs.resize.childNodes
|
||||
this.clicked = params
|
||||
titleRef.forEach((item) => {
|
||||
if (item.innerText === params) {
|
||||
// debugger
|
||||
groupRef.parentElement.scrollTo({
|
||||
top: item.offsetTop,
|
||||
behavior: 'smooth' // 平滑移动
|
||||
})
|
||||
}
|
||||
})
|
||||
// groupRef.scrollTop = offsetTop
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AZClass {
|
||||
// background: #fff;
|
||||
display: flex;
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// z-index: 999;
|
||||
}
|
||||
|
||||
.word-list {
|
||||
color: #fff;
|
||||
background-color: #1f69c3;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
padding: 6px;
|
||||
text-align: center;
|
||||
width: 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.letterClass {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.letterClass:hover {
|
||||
font-size: 16px;
|
||||
font-weight: bolder;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.hoverClass {
|
||||
font-size: 16px;
|
||||
font-weight: bolder;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.el-scrollbar ::v-deep .el-scrollbar__wrap {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.my-dialog {
|
||||
height: 1000px
|
||||
}
|
||||
|
||||
.el-dialog__title {
|
||||
font-family: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.AZClass .el-cascader-menu .el-cascader-menu__wrap {
|
||||
height: 630px !important;
|
||||
}
|
||||
|
||||
.my-dialog .el-dialog {
|
||||
width: 930px;
|
||||
}
|
||||
|
||||
.my-dialog .el-cascader-menu {
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.my-dialog .el-cascader-menu:last-child {
|
||||
width: 420px;
|
||||
}
|
||||
|
||||
.my-dialog .el-cascader-menu:nth-child(3) .el-cascader-node {
|
||||
height: auto;
|
||||
line-height: 17px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user