前端初始化

This commit is contained in:
zer0Black
2022-08-31 13:33:52 +08:00
commit 0a11097b80
108 changed files with 14283 additions and 0 deletions
+540
View File
@@ -0,0 +1,540 @@
<template>
<div id="app">
<i @click="closeLoading" class="custom-close el-icon-close" v-if="$store.state.isLoading"></i>
<router-view/>
</div>
</template>
<script>
import {loading} from "./utils/request";
export default {
name: "ReportManager",
data() {
return {}
},
methods: {
getQueryVariable(r, variable) {
if (r) {
var query = r.split('?');
if (query && query.length == 2) {
var vars = query[1].split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
}
}
},
closeLoading() {
loading.close();
this.$store.commit('saveIsLoading', false);
},
},
created() {
let _that = this
// var path = window.location.search
// var ticket = this.getQueryVariable(path, 'ticket')
// var loginType = this.getQueryVariable(path, 'loginType')
// if (loginType == 1) {
// window.open('http://10.12.1.78:9090/cas/login?service=http://192.168.144.22:9966/home', '_self');
// } else {
// // if (ticket) {
// // var params = {
// // service: 'http://localhost:8080/home',
// // ticket: ticket
// // }
// // this.$api.login.loginByTicket(params).then(res => {
// // if (res.respCode !== '0') {
// // // this.verifyCode();
// // return this.$message.error(res.data.message);
// // }
// // this.$message.success('登录成功');
// // _that.$store.commit('saveUserInfo', res.data);
// // _that.$router.push('/home');
// // }).catch(_ => {
// // // this.verifyCode();
// // this.$router.push('/');
// // })
// //
// // } else {
// // this.$router.push('/');
// // }
// }
}
}
</script>
<style lang="scss">
* {
margin: 0;
padding: 0;
text-decoration: none;
list-style: none;
box-sizing: border-box;
outline: none;
font-style: normal;
font-family: 'Helvetica Neue', Arial, sans-serif;
}
html, body {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
#app {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
min-width: 1200px;
}
}
img {
background-color: transparent !important;
}
/* =============================================== 多选select =============================================== */
.el-select {
.el-select__tags-text {
max-width: 40px;
}
}
.el-select-dropdown {
z-index: 7777 !important;
}
.el-cascader__tags .el-tag {
max-width: 40px !important;
}
.el-cascader .el-input .el-input__inner {
height: 24px !important;
}
/* =============================================== 页面加载 =============================================== */
.el-loading-mask.is-fullscreen {
z-index: 8888 !important;
}
.custom-close {
cursor: pointer;
position: absolute;
right: 20px;
top: 20px;
z-index: 9999;
font-size: 30px;
color: #6c6c6c;
}
/* =============================================== 页面最小高度 =============================================== */
.content-height {
min-height: calc(100vh - 60px - 20px);
box-shadow: 0 6px 11px 0 rgba(163, 163, 163, 0.2);
border-radius: 6px;
background: #FFFFFF;
}
/* =============================================== el-button =============================================== */
.el-button.del-btn {
color: #ED5C57 !important;
}
.el-button.el-button--primary:hover, .el-button.el-button--primary:focus {
border-color: #1890FF !important;
background-color: transparent !important;
}
.el-button.el-button--primary:hover,
.el-button.el-button--primary:focus {
border-color: #1890FF !important;
background-color: #1890FF !important;
color: #FFFFFF !important;
}
.el-button.el-button--primary:active {
color: #1890FF !important;
}
.el-button--text {
color: #1890FF !important;
border: 0 !important;
}
.el-button--text:hover, .el-button--text:focus {
border: 0 transparent !important;
}
.el-button--primary.is-plain,
.el-button--primary.is-plain:hover,
.el-button--primary.is-plain:focus {
background-color: transparent !important;
color: #1890FF !important;
border-color: #1890FF !important;
}
/* =============================================== input内容颜色 =============================================== */
.el-input__inner,
.el-textarea__inner {
font-weight: 400;
color: #434343;
}
/* =============================================== 虚拟滚动条 =============================================== */
.el-scrollbar {
.el-scrollbar__wrap {
overflow-x: hidden;
margin-bottom: 0 !important;
}
}
/* =============================================== vxetable header高度 =============================================== */
.vxe-header--row {
th.vxe-header--column {
height: 40px !important;
}
th.vxe-header--column.col--checkbox {
padding: 0 !important;
}
}
/* =============================================== vxetable滚动条 =============================================== */
/*滚动条整体部分*/
.vxe-table ::-webkit-scrollbar {
width: 10px;
height: 10px;
}
/*滚动条的轨道*/
.vxe-table ::-webkit-scrollbar-track {
background-color: #EAEAEA;
}
/*滚动条里面的小方块,能向上向下移动*/
.vxe-table ::-webkit-scrollbar-thumb {
background-color: #D8D8D8;
border-radius: 5px;
border: 1px solid #D8D8D8;
box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);
}
.vxe-table ::-webkit-scrollbar-thumb:hover {
background-color: #D8D8D8;
}
.vxe-table ::-webkit-scrollbar-thumb:active {
background-color: #D8D8D8;
}
/*边角,即两个滚动条的交汇处*/
.vxe-table ::-webkit-scrollbar-corner {
background-color: #EAEAEA;
}
/* =============================================== 分页基本样式 =============================================== */
.el-pagination {
text-align: right;
.el-pagination__total,
.el-pagination__sizes {
float: left;
color: #606266;
}
.el-input--mini .el-input__inner {
height: 28px;
line-height: 28px;
}
button {
padding: 0 !important;
text-align: center;
background-color: #FAFAFA !important;
color: #606266 !important;
}
.el-pager {
margin: 0 5px;
.number {
background-color: #FAFAFA !important;
margin: 0 5px;
font-weight: 400;
}
.number.active {
background-color: rgba(64, 158, 255, 0.1) !important;
}
}
}
/* =============================================== 弹窗 =============================================== */
.el-dialog {
position: absolute !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
margin: 0 !important;
min-width: 600px !important;
border-radius: 6px !important;
.el-dialog__header {
height: 52px;
line-height: 52px;
padding-bottom: 0;
margin: 0 18px 0 22px;
border-bottom: 1px solid #EBEEF5;
font-weight: 600;
color: #262626;
.el-dialog__headerbtn {
margin: 16px 24px 0 0;
.el-dialog__close {
font-size: 24px;
color: #6C6C6C;
font-weight: 500;
}
}
}
.el-dialog__body {
padding: 0;
}
}
/* =============================================== search-tag =============================================== */
.search-tag {
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0) !important;
&:hover {
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.25) !important;
}
}
.test {
width: auto!important;
padding: 0px !important;
}
.ql-snow .ql-tooltip[data-mode='link']::before {
content: '请输入链接地址:';
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: '保存';
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode='video']::before {
content: '请输入视频地址:';
}
.ql-snow .ql-picker.ql-size {
width: 70px!important;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='14px']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='14px']::before {
content: '14px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='16px']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='16px']::before {
content: '16px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='18px']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='18px']::before {
content: '18px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='20px']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='20px']::before {
content: '20px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='32px']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='32px']::before {
content: '32px';
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: '文本';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='1']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='1']::before {
content: '标题1';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='2']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='2']::before {
content: '标题2';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='3']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='3']::before {
content: '标题3';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='4']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='4']::before {
content: '标题4';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='5']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='5']::before {
content: '标题5';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='6']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='6']::before {
content: '标题6';
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: '标准字体';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='serif']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='serif']::before {
content: '衬线字体';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='monospace']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='monospace']::before {
content: '等宽字体';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-label::before {
content: '行高';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='initial']::before {
content: '默认';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='1']::before {
content: '1';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='1.5']::before {
content: '1.5';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='1.75']::before {
content: '1.75';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='2']::before {
content: '2';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='3']::before {
content: '3';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='4']::before {
content: '4';
}
.ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value='5']::before {
content: '5';
}
.ql-snow .ql-picker.ql-lineheight {
width: 70px;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimSun]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimSun]::before {
content: "宋体";
font-family: "SimSun";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before {
content: "黑体";
font-family: "SimHei";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before {
content: "微软雅黑";
font-family: "Microsoft YaHei";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before {
content: "楷体";
font-family: "KaiTi";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before {
content: "仿宋";
font-family: "FangSong";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before {
content: "Arial";
font-family: "Arial";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before {
content: "Times New Roman";
font-family: "Times New Roman";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before {
content: "sans-serif";
font-family: "sans-serif";
}
.ql-font-SimSun {
font-family: "SimSun";
}
.ql-font-SimHei {
font-family: "SimHei";
}
.ql-font-Microsoft-YaHei {
font-family: "Microsoft YaHei";
}
.ql-font-KaiTi {
font-family: "KaiTi";
}
.ql-font-FangSong {
font-family: "FangSong";
}
.ql-font-Arial {
font-family: "Arial";
}
.ql-font-Times-New-Roman {
font-family: "Times New Roman";
}
.ql-font-sans-serif {
font-family: "sans-serif";
}
</style>
+35
View File
@@ -0,0 +1,35 @@
import Vue from "vue";
/**
* 多层级的对象合并
* @param target 目标对象(需要合并到的对象)
* @param source 资源(拥有的对象)
* @returns {target} 合并后的对象
*/
function assignObj(target, source) {
if (typeof (target) !== 'object' || typeof (source) !== 'object') {
return source;
}
for (let key in source) {
target[key] = assignObj(target[key], source[key]);
}
return target;
}
/**
* 获取API
* @type {{install(): *|{}}} Vue.use默认执行的方法
*/
export default {
install() {
Vue.prototype.$api = {}
const requireComponents = require.context('./modules', true, /\.js/)
requireComponents.keys().forEach(file => {
const mod = requireComponents(file);
let fileName = file.replace(/\.\/|\.js/g, '');
fileName = fileName.split('/').map(item => item.replace(/\./g, '_')).reverse().reduce((p, c) => ({[c]: p}), mod.default);
Vue.prototype.$api = assignObj(Vue.prototype.$api, fileName)
})
return Vue.prototype.$api
}
};
+31
View File
@@ -0,0 +1,31 @@
import {instance as request} from "@/utils/request";
export default {
// 获取查询项
queryGetQuery(data) {
return request({
url: `/api/query/getQuery`,
method: 'GET',
params: data
})
},
// 获取品牌
queryGetBrand(data) {
return request({
url: `/api/query/getBrand`,
method: 'GET',
params: data
})
},
// 获取车型
marketSegmentsVehicleSeries(data) {
return request({
url: `/api/marketSegmentsCompete/vehicleSeries`,
method: 'POST',
params: data
})
},
}
+36
View File
@@ -0,0 +1,36 @@
import {instance as request} from "@/utils/request";
// 细分市场竞争格局
export default {
// 车型对比
chooseStyle(data) {
return request({
url: `/api/chooseStyle`,
method: 'GET',
params: data,
});
},
//配置查询
configQuery(data) {
return request({
url: `/api/configQuery`,
method: 'GET',
params: data,
});
},
//基础信息配置查询
configGradientTable(data) {
return request({
url: `/api/gradientContrast`,
method: 'GET',
params: data,
});
},
// 添加车型
chooseStyleAdd(data) {
return request({
url: `/api/chooseStyle/add`,
method: 'GET',
params: data,
});
},
}
+28
View File
@@ -0,0 +1,28 @@
import {instance as request} from "@/utils/request";
// 细分市场竞争格局
export default {
// 车型对比
chooseStyle(data) {
return request({
url: `/api/chooseStyle`,
method: 'GET',
params: data,
});
},
//配置查询
configQuery(data) {
return request({
url: `/api/configQuery`,
method: 'GET',
params: data,
});
},
//基础信息配置查询
configBaseQuery(data) {
return request({
url: `/api/configQuery/carBaseInfo`,
method: 'GET',
params: data,
});
},
}
+19
View File
@@ -0,0 +1,19 @@
import {instance as request} from "@/utils/request";
export default {
// 获取查询项
queryTableData(data) {
return request({
url: '/api/eatpContrast',
method: 'GET',
params: data
})
},
queryOtherData(data) {
return request({
url: '/api/eatpContrast/page',
method: 'GET',
params: data
})
},
}
+42
View File
@@ -0,0 +1,42 @@
import {instance as request} from "@/utils/request";
export default {
// 登录
login(data) {
return request({
url: `/api/login`,
method: 'post',
data
})
},
// 长按ticket登录
// loginByTicket(data) {
// return request({
// url: `/api/cas/validateLogin?service=`+data.service+'&ticket='+data.ticket,
// method: 'get'
// })
// },
pageLog(data) {
return request({
url: `/api/log/log/save?accessPage=`+data,
method: 'get'
})
},
// 获取验证码
verifyCode(data) {
return request({
url: `/api/verifyCode`,
method: 'get',
params: data,
responseType: 'arraybuffer'
})
},
// 退出登录
logout(data) {
return request({
url: `/api/logout`,
method: 'get',
param: data,
})
},
}
+51
View File
@@ -0,0 +1,51 @@
import {instance as request} from "@/utils/request";
export default {
// 删除
delSysRole(data){
return request({
url: `/api/sys/role/${data.id}`,
method: 'DELETE',
})
},
// 修改
putSysRole(data){
return request({
url: `/api/sys/role`,
method: 'PUT',
data
})
},
// 配置角色菜单
sysRoleSaveRoleMenu(data){
return request({
url: `/api/sys/role/saveRoleMenu`,
method: 'POST',
data
})
},
// 配置角色首页
sysRoleSaveRoleHome(data){
return request({
url: `/api/sys/role/saveRoleHome`,
method: 'POST',
data
})
},
// 获取角色首页
sysRoleGetRoleHome(data){
return request({
url: `/api/sys/role/getRoleHome`,
method: 'GET',
params: data
})
},
}
+45
View File
@@ -0,0 +1,45 @@
import {instance as request} from "@/utils/request";
export default {
// 查询菜单
sysMenuFindAllMenus(data) {
return request({
url: `/api/sys/menu/findAllMenus`,
method: 'GET',
params: data
})
},
// 新增
postSysMenu(data) {
return request({
url: `/api/sys/menu`,
method: 'POST',
data
})
},
// 删除
sysMenuDeleteId(data) {
return request({
url: `/api/sys/menu/${data.ids}`,
method: 'DELETE',
})
},
// 修改
putSysMenu(data) {
return request({
url: `/api/sys/menu`,
method: 'PUT',
data
})
},
// 角色对应的菜单
getSysMenu(data) {
return request({
url: `/api/sys/menu`,
method: 'GET',
params: data
})
},
}
+48
View File
@@ -0,0 +1,48 @@
import {instance as request} from "@/utils/request";
// 细分市场竞争格局
export default {
// 车型对比
modelContrastVehicleContrast(data) {
return request({
url: `/api/modelContrast/vehicleContrast`,
method: 'POST',
data
})
},
// 获取款型下拉框
modelContrastGetKxmcList(data) {
return request({
url: `/api/modelContrast/getKxmcList`,
method: 'POST',
data
})
},
// 一个对比组款型对比
modelContrastKxContrast(data) {
return request({
url: `/api/modelContrast/kxContrast`,
method: 'POST',
data
})
},
// 一个对比组的款型对比Execel导出
modelContrastKxExcel(data) {
return request({
url: `/api/modelContrast/kxExcel`,
method: 'POST',
data,
responseType: 'blob'
})
},
// 车型对比Execel导出
modelContrastVehicleExcel(data) {
return request({
url: `/api/modelContrast/vehicleExcel`,
method: 'POST',
data,
responseType: 'blob'
})
},
}
+34
View File
@@ -0,0 +1,34 @@
import {instance as request} from "@/utils/request";
// 车型竞争格局
export default {
// Excel导出
vehicleModelCompeteDownload(data) {
return request({
url: `/api/vehicleModelCompete/download`,
method: 'GET',
params: data,
responseType: 'blob'
})
},
// 主销TP
vehicleModelCompeteKingpinTP(data) {
return request({
url: `/api/vehicleModelCompete/kingpinTP`,
method: 'POST',
params: data
})
},
// 时间段加权TP
vehicleModelCompeteWeightedTP(data) {
return request({
url: `/api/vehicleModelCompete/weightedTP`,
method: 'POST',
params: data
})
},
}
+22
View File
@@ -0,0 +1,22 @@
import {instance as request} from "@/utils/request";
// 分价格段市占率
export default {
// 宽表基础数据
baseDataList(data) {
return request({
url: `/api/baseData/list`,
method: 'GET',
params: data
})
},
// Excel导出
baseDataDownload(data) {
return request({
url: `/api/baseData/download`,
method: 'GET',
params: data,
responseType: 'blob'
})
},
}
+21
View File
@@ -0,0 +1,21 @@
import {instance as request} from "@/utils/request";
// 分价格段市占率
export default {
// 车型趋势Execel导出
vehicleTrendVehicleTrendExcel(data) {
return request({
url: `/api/vehicleTrend/vehicleTrendExcel`,
method: 'POST',
data,
responseType: 'blob'
})
},
// 车型趋势
vehicleTrendVehicleTrendMap(data) {
return request({
url: `/api/vehicleTrend/vehicleTrendMap`,
method: 'POST',
data
})
},
}
+47
View File
@@ -0,0 +1,47 @@
import {instance as request} from "@/utils/request";
// 细分市场竞争格局
export default {
// 整体加权TP
marketSegmentsCompeteOverallWeightedTP(data) {
return request({
url: `/api/marketSegmentsCompete/overallWeightedTP`,
method: 'POST',
params: data
})
},
// 主销TP
marketSegmentsCompeteKingpinTP(data) {
return request({
url: `/api/marketSegmentsCompete/kingpinTP`,
method: 'POST',
params: data
})
},
// Excel导出
marketSegmentsCompeteDownload(data) {
return request({
url: `/api/marketSegmentsCompete/download`,
method: 'GET',
params: data,
responseType: 'blob'
})
},
// downloadPPT
pptDownload(data) {
return request({
url: `/api/pptDownload/download`,
method: 'POST',
data,
responseType: 'blob'
})
},
// downloadPPT
pptDownloads(data) {
return request({
url: `/api/pptDownload/downloads`,
method: 'POST',
data,
responseType: 'blob'
})
},
}
+64
View File
@@ -0,0 +1,64 @@
import {instance as request} from "@/utils/request";
// 分价格段市占率
export default {
// 计算分价格段占比-国别大类
priceGetCltPriceStatistic(data) {
return request({
url: `/api/price/getCltPriceStatistic`,
method: 'GET',
params: data
})
},
// 计算分价格段占比-细分大类
priceGetSltPriceStatistic(data) {
return request({
url: `/api/price/getSltPriceStatistic`,
method: 'GET',
params: data
})
},
// 计算分价格段占比-细分大类-图
getSltPriceStatisticChart(data) {
return request({
url: `/api/price/getSltPriceStatisticChart`,
method: 'GET',
params: data
})
},
// 计算分价格段占比-细分大类-表
getSltPriceStatisticTable(data) {
return request({
url: `/api/price/getSltPriceStatisticTable`,
method: 'GET',
params: data
})
},
// 计算分价格段占比-整体
priceGetToalPriceStatistic(data) {
return request({
url: `/api/price/getToalPriceStatistic`,
method: 'GET',
params: data
})
},
// priceType: tp msrp showType: 'MIX' type: 0 1 2 unit: 1元 2 万元
// excel导出
priceDownload(data) {
return request({
url: `/api/price/download/${data.type}`,
method: 'GET',
params: data,
responseType: 'blob'
})
},
// ppt导出 isUseGb
pricePpt(data) {
return request({
url: `/api/price/ppt`,
method: 'GET',
params: data,
responseType: 'blob'
})
},
}
+21
View File
@@ -0,0 +1,21 @@
import {instance as request} from "@/utils/request";
// 分价格段市占率
export default {
// 整体趋势Execel导出
wholeTrendWholeTrendExcel(data) {
return request({
url: `/api/wholeTrend/wholeTrendExcel`,
method: 'POST',
data,
responseType: 'blob'
})
},
// 整体趋势
wholeTrendWholeTrendMap(data) {
return request({
url: `/api/wholeTrend/wholeTrendMap`,
method: 'POST',
data
})
},
}
+132
View File
@@ -0,0 +1,132 @@
import {instance as request} from "@/utils/request";
export function reportUploadPicFile(data){
return request({
url: `/api/report/uploadPicFile`,
method: 'POST',
data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
}
export default {
// 日志列表
reportLogList(data){
return request({
url: `/api/reportLog/list`,
method: 'GET',
params: data
})
},
// 标签管理
labelAdd(data){
return request({
url: `/api/label/add`,
method: 'POST',
data
})
},
// 标签列表
labelList(data){
return request({
url: `/api/label/list`,
method: 'GET',
params: data
})
},
// 标签删除|单个
labelDeleteId(data){
return request({
url: `/api/label/delete/${data.id}`,
method: 'POST',
})
},
// 新增或编辑报告
reportAdd(data){
return request({
url: `/api/report/add`,
method: 'POST',
data
})
},
// 详情||上传文件
reportUploadFile(data){
return request({
url: `/api/report/uploadFile`,
method: 'POST',
data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
},
// 获取报告预览
reportGetReportHtmlId(data){
return request({
url: `/api/report/getReportHtml/${data.id}`,
method: 'GET',
})
},
// 删除报告
reportDelete(data){
return request({
url: `/api/report/delete`,
method: 'POST',
params: data,
})
},
// 报告列表
reportList(data){
return request({
url: `/api/report/list`,
method: 'POST',
data,
})
},
// 获取报告日期列表
reportDateList(data){
return request({
url: `/api/report/reportDateList`,
method: 'GET',
params: data,
})
},
// 标签批量保存
labelSave(data){
return request({
url: `/api/label/save`,
method: 'POST',
data,
})
},
// 下载文件
reportDownload(data){
return request({
url: `/api/report/download`,
method: 'GET',
params: data,
responseType: 'blob'
})
},
// 上传图片
reportUploadPicFile(data){
return request({
url: `/api/report/uploadPicFile`,
method: 'POST',
data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
},
// 标签顺序
labelMove(data){
return request({
url: `/api/label/move`,
method: 'POST',
params: data,
})
},
}
+67
View File
@@ -0,0 +1,67 @@
import {instance as request} from "@/utils/request";
export default {
// 列表
getSysRole(data){
return request({
url: `/api/sys/role`,
method: 'GET',
params: data
})
},
// 删除
delSysRole(data){
return request({
url: `/api/sys/role/${data.id}`,
method: 'DELETE',
})
},
// 新增
postSysRole(data){
return request({
url: `/api/sys/role`,
method: 'POST',
data
})
},
// 修改
putSysRole(data){
return request({
url: `/api/sys/role`,
method: 'PUT',
data
})
},
// 配置角色菜单
sysRoleSaveRoleMenu(data){
return request({
url: `/api/sys/role/saveRoleMenu`,
method: 'POST',
data
})
},
// 配置角色首页
sysRoleSaveRoleHome(data){
return request({
url: `/api/sys/role/saveRoleHome`,
method: 'POST',
data
})
},
// 获取角色首页
sysRoleGetRoleHome(data){
return request({
url: `/api/sys/role/getRoleHome`,
method: 'GET',
params: data
})
},
}
+42
View File
@@ -0,0 +1,42 @@
import {instance as request} from "@/utils/request";
export default {
// 新增|编辑
sysUserAddUser(data){
return request({
url: `/api/sys/user/addUser`,
method: 'POST',
data
})
},
// 用户启用或禁用
sysUserIsUse(data){
return request({
url: `/api/sys/user/isUse/${data.USID}/${data.type}`,
method: 'POST',
})
},
// 获取所有用户
sysUserList(data){
return request({
url: `/api/sys/user/list`,
method: 'GET',
params: data
})
},
// 获取所有用户
sysUserAllList(){
return request({
url: `/api/sys/user/allList`,
method: 'GET',
})
},
// 删除用户
sysUserDelete(data){
return request({
url: `/api/sys/user/delete`,
method: 'POST',
params: data
})
},
}
+32
View File
@@ -0,0 +1,32 @@
/* ElementUI */
$--color-primary: #1890FF;
$--button-primary-border-color: #1890FF;
$--button-mini-font-size: 14px;
$--button-mini-padding-vertical: 4px;
$--button-mini-padding-horizontal: 26px;
$--input-mini-height: 24px;
$--checkbox-checked-font-color: #1890FF;
$--checkbox-checked-icon-color: #1890FF;
$--checkbox-checked-background-color: #FFFFFF;
$--checkbox-font-weight: 400;
$--pagination-button-width: 30px;
$--pagination-button-height: 30px;
$--menu-item-font-size: 16px;
$--menu-item-font-color: #606266;
$--select-input-focus-border-color: #1890FF;
$--dialog-title-font-size: 16px;
$--dialog-padding-primary: 0;
/* VXE-Table */
$vxe-table-border-color: #EBEEF5;
$vxe-table-header-font-weight: 500;
$vxe-table-header-background-color: #F2F6FC;
$vxe-table-header-font-color: #262626;
$vxe-table-row-striped-background-color: #FAFAFA;
/* ElementUI 主题必需 */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "../../../node_modules/element-ui/packages/theme-chalk/src/index";
/* VXE-Table 主题必需*/
@import '../../../node_modules/vxe-table/styles/index.scss';
+11
View File
@@ -0,0 +1,11 @@
u {
text-decoration: underline;
}
em {
font-style: italic;
}
s, strike, del {
text-decoration: line-through
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 922 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 573 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 B

File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

+340
View File
@@ -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>
+308
View File
@@ -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>
+222
View File
@@ -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>
+194
View File
@@ -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>
+18
View File
@@ -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>
+256
View File
@@ -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>
+17
View File
@@ -0,0 +1,17 @@
import Vue from "vue";
/**
* 获取API
* @type {{install(): *|{}}} Vue.use默认执行的方法
*/
export default {
install() {
const requireComponents = require.context('./modules', false, /\.js/);
requireComponents.keys().forEach(file => {
const directives = requireComponents(file).default;
for (const directive in directives) {
Vue.directive(directive, directives[directive]);
}
});
}
};
@@ -0,0 +1,11 @@
import Vue from "vue";
export default {
tableMinHeight: {
// 指令的定义
inserted(el, binding, vnode) {
let dom = el.getElementsByClassName('vxe-table--body-wrapper body--wrapper').item(0);
dom.style.setProperty('min-height', binding.value, 'important')
},
}
}
+17
View File
@@ -0,0 +1,17 @@
import Vue from "vue";
/**
* 获取API
* @type {{install(): *|{}}} Vue.use默认执行的方法
*/
export default {
install() {
const requireComponents = require.context('./modules', false, /\.js/);
requireComponents.keys().forEach(file => {
const filters = requireComponents(file).default;
for (const filter in filters) {
Vue.filter(filter, filters[filter]);
}
});
}
};
+9
View File
@@ -0,0 +1,9 @@
export default {
formatDate: function (value) {
let date = new Date(value);
let y = date.getFullYear();
let m = date.getMonth() + 1;
let d = date.getDate();
return `${y}/${m}/${d}`;
}
}
+73
View File
@@ -0,0 +1,73 @@
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import config from "@/utils/config";
// VXETable
import 'xe-utils'
import VXETable from 'vxe-table'
import 'vxe-table/lib/style.css'
// ElementUI
import ElementUI from 'element-ui';
import './assets/css/element-variables.scss'
// ECharts
import 'echarts'
import ECharts from './components/ECharts';
// Api
import Api from './api'
// 自定义指令
import Directive from './directives'
// 自定义过滤器
import Filter from './filters'
// 加密函数
import JSEncrypt from '../src/assets/js/jsencrypt.min.js';
VXETable.setup({
table: {
resizable: true,
}
})
Vue.use(VXETable);
// 富文本引用
import VueQuillEditor from 'vue-quill-editor'
// require styles 引入样式
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
Vue.use(VueQuillEditor)
Vue.use(ElementUI, {size: 'mini', zIndex: 3000});
Vue.component('v-chart', ECharts);
Vue.use(Api);
Vue.use(Directive);
Vue.use(Filter);
Vue.prototype.$JSEncrypt = (data) => {
if(data === ''){
return '';
}
let encryptor = new JSEncrypt();
encryptor.setPublicKey(config.PUBLIC_KEY);
return encryptor.encrypt(data) || '';
}
VXETable.renderer.add('NotData', {
// 空内容模板
renderEmpty (h, renderOpts) {
return [
<span>
<img width="100" src={require('./assets/imgs/icon-nodata.png')}/>
<p style="margin-top: 10px;">暂无数据</p>
</span>
]
}
})
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
+81
View File
@@ -0,0 +1,81 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import store from '../store'
import login from '../api/modules/login'
import {BASE_URL} from "../utils/http"
Vue.use(VueRouter)
let routes = [];
const requireComponents = require.context('./modules', false, /\.js/);
requireComponents.keys().forEach(file => routes = [...routes, ...requireComponents(file).default]);
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes,
scrollBehavior(to, from, position) {
return position;
},
})
// 路由守卫
router.beforeEach((to, from, next) => {
/**
* 仅报告价格板块
* 报告板块 http://10.10.1.184:8080/#/report/list?id=XBFBR7UADZ
* 价格板块 http://10.10.1.184:8080/#/overall/opricetrend?id=SBME88VTUD
*/
// store.commit('saveUserInfo', {});
// store.commit('saveMenuData', menuTree);
// var url = BASE_URL.BASE_LOCAL + '/login?loginType=1'
// var loginUrl = BASE_URL.BASE_CHANGAN + "/login?service=" + url;
// var logoutUrl = BASE_URL.BASE_CHANGAN + "/logout?service=" + url
if (to.meta.crumb) {
var jumpStr = to.meta.crumb.join('/')
if(jumpStr){
if (jumpStr == 'urlIndex' && to.path != '/system/401Page') {
login.pageLog(store.state.menuName).then(res => {
}).catch(_ => {
})
}else{
login.pageLog(jumpStr).then(res => {
}).catch(_ => {
})
}
}
}
// debugger
// if (to.query.loginType) {
// if (to.query.loginType == 1 && to.query.ticket) {
// var params = {
// service: url,
// ticket: to.query.ticket
// }
// login.loginByTicket(params).then(res => {
// if (res.respCode !== '0') {
// // this.verifyCode();
// // return this.$message.error(res.data.message);
// }
// // this.$message.success('登录成功');
// store.commit('saveUserInfo', res.data);
// next('/home');
// }).catch(_ => {
// window.open(logoutUrl, '_self');
// })
// } else {
// window.open(loginUrl, '_self');
// }
// } else if (to.path.toLowerCase() !== '/login') {
// if (!store.state.userInfo) {
// window.open(logoutUrl, '_self');
// }
// next();
// } else {
next();
// }
})
export default router
+53
View File
@@ -0,0 +1,53 @@
const routes = [
{
path: '/system',
name: '',
component: () => import('../../views/Layout.vue'),
children: [
{
path: 'urlIndex',
name: 'urlIndex',
component: () => import('../../views/System/urlIndex.vue'),
meta: {
crumb: ['urlIndex'],
}
}]},
{
path: '/',
redirect: {
name: 'Login'
// path: '/report/list?id=XBFBR7UADZ'
}
},
// 登录
{
path: '/login',
name: 'Login',
component: () => import('../../views/Login.vue')
},
// // 注册
// {
// path: '/register',
// name: 'Register',
// component: () => import('../../views/Register.vue')
// },
// 首页
// {
// path: '/home',
// name: 'Home',
// component: () => import('../../views/Home.vue')
// },
{
path: '/layout',
name: 'LayoutBox',
component: () => import('../../views/Layout.vue')
},
// // Demo
// {
// path: '/demo',
// name: 'Demo',
// component: () => import('../../components/Demo.vue')
// },
];
export default routes;
+39
View File
@@ -0,0 +1,39 @@
const routes = [
// 报告管理
{
path: '/report',
name: 'Layout',
component: () => import('../../views/Layout.vue'),
children: [
// 报告列表
{
path: 'list',
name: 'ReportList',
component: () => import('../../views/Report/ReportList.vue'),
meta: {
crumb: ['报告列表'],
}
},
// 报告详情
{
path: 'detail',
name: 'ReportDetail',
component: () => import('../../views/Report/ReportDetail.vue'),
meta: {
crumb: ['报告详情'],
}
},
// 报告管理
{
path: '/report/manager',
name: 'ReportManager',
component: () => import('../../views/Report/ReportManager.vue'),
meta: {
crumb: ['报告管理'],
}
},
]
},
];
export default routes;
+65
View File
@@ -0,0 +1,65 @@
const routes = [
// 系统管理
{
path: '/system',
name: '',
component: () => import('../../views/Layout.vue'),
children: [
// 菜单管理
{
path: 'menu',
name: 'MenuManager',
component: () => import('../../views/System/MenuManager.vue'),
meta: {
crumb: ['菜单管理'],
}
},
// 用户管理
{
path: 'user',
name: 'User',
component: () => import('../../views/System/User.vue'),
meta: {
crumb: ['用户管理'],
}
},
// 角色管理
{
path: 'role',
name: 'Role',
component: () => import('../../views/System/Role.vue'),
meta: {
crumb: ['角色管理'],
}
},
// // 角色管理
// {
// path: 'mail',
// name: 'Mail',
// component: () => import('../../views/System/mail.vue'),
// meta: {
// crumb: ['邮件管理'],
// }
// },
// // 角色管理
// {
// path: 'notification',
// name: 'Notification',
// component: () => import('../../views/System/notification.vue'),
// meta: {
// crumb: ['通知管理'],
// }
// },
{
path: '401Page',
name: '401Page',
component: () => import('../../views/System/401Page.vue'),
meta: {
crumb: ['暂无权限'],
}
},
]
},
];
export default routes;
+43
View File
@@ -0,0 +1,43 @@
import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
userInfo: null,
isLoading: false,
rememberData: null,
menuData: [],
pathUrl: '',
menuName: '',
},
getters: {
menuData: (state) => state.menuData,
menuName: (state) => state.menuName,
},
mutations: {
saveUserInfo(state, data) {
state.userInfo = data;
},
saveIsLoading(state, data){
state.isLoading = data;
},
saveRememberData(state, data){
state.rememberData = data;
},
saveMenuData(state, data){
state.menuData = data;
},
savePathUrl(state, data){
state.pathUrl = data;
},
saveMenuName(state, data){
state.menuName = data;
},
},
actions: {},
modules: {},
plugins: [createPersistedState()]
})
+3
View File
@@ -0,0 +1,3 @@
export default {
PUBLIC_KEY: `MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKwvimHNGEiyV5L73llAeTv8O/3c9KLZLjNDpzNVOvzowk1MJySdSh6BiZPFXGLJ49Rrp/0U1L68ZCvC2Zv07YYTrr7Bd8o8lKB9HlUqcJo/seIHrLCLl2ePuLn+NYtIM4xxbbvAOdy5Ep/QbK4aWz8G7vsx8pctijLksYKNBQyQIDAQAB`,
}
+13
View File
@@ -0,0 +1,13 @@
import {fileType} from "./fileType";
export const downloadFile = (res) => {
let file_name = decodeURI(res.headers["content-disposition"]).split('=').pop();
let file_type = file_name.split('.').pop();
let blobData = new Blob([res.data], {type: fileType[file_type]});
let downloadUrl = window.URL.createObjectURL(blobData);
let anchor = document.createElement("a");
anchor.href = downloadUrl;
anchor.download = file_name;
anchor.click();
window.URL.revokeObjectURL(blobData);
}
+13
View File
@@ -0,0 +1,13 @@
export const fileType = {
pdf: 'application/pdf',
xls: 'application/vnd.ms-excel',
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
doc: 'application/msword',
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
ppt: 'application/vnd.ms-powerpoint',
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
png: 'image/png',
jpg: 'image/jpeg',
rar: 'application/x-rar',
zip: 'application/zip',
}
+15
View File
@@ -0,0 +1,15 @@
export const BASE_URL = {
// LOGIN_URL : "http://192.168.144.29:9090/cas/login?service=http://192.168.144.22:9966/login?loginType=1",
// LOGOUT_URL : "http://192.168.144.29:9090/cas/logout?service=http://192.168.144.22:9966/login?loginType=1",
//内部测试
// BASE_CHANGAN:'http://192.168.144.29:9090/cas',
BASE_LOCAL:'http://127.0.0.1:8080',
BASE_LOCAL_IMG:'http://127.0.0.1:8080',
// //企业测试
// BASE_CHANGAN:'https://caddmuat.changan.com.cn/cas',
// BASE_LOCAL:'https://caddmuat.changan.com.cn/mi',
// BASE_LOCAL_IMG:'https://caddmuat.changan.com.cn',
}
+13
View File
@@ -0,0 +1,13 @@
import Quill from "quill";
let Parchment = Quill.import("parchment");
class lineHeightAttributor extends Parchment.Attributor.Style {
}
const lineHeightStyle = new lineHeightAttributor("lineHeight", "line-height", {
scope: Parchment.Scope.INLINE,
whitelist: ["initial", "1", "1.5", "1.75", "2", "3", "4"]
});
export {lineHeightStyle};
+128
View File
@@ -0,0 +1,128 @@
[
{
"id": "37SSNVGSP9",
"parentId": "AVL9YSB7ZF",
"label": "菜单管理",
"href": "/system/menu",
"icon": "/api/home/pic//20211208163844522.png"
},
{
"id": "6F46UACEMG",
"parentId": "SBME88VTUD",
"label": "整体市场价格分析",
"href": "overall",
"icon": "/api/home/pic//20211209090648732.png"
},
{
"id": "KF8L94BZC4",
"parentId": "8SJZZFCZJS",
"label": "车型量价查询",
"href": "/models/modelsquery",
"icon": ""
},
{
"id": "PNK5Z3REGN",
"parentId": "6F46UACEMG",
"label": "价格趋势",
"href": "/overall/opricetrend",
"icon": ""
},
{
"id": "UZHN9Z835U",
"parentId": "XBFBR7UADZ",
"label": "报告列表",
"href": "/report/list",
"icon": "/api/home/pic//20211209090610575.png"
},
{
"id": "XBFBR7UADZ",
"parentId": "6f6fafb4a7",
"label": "报告板块",
"href": "/report/list",
"icon": "/api/home/pic//20211116142717856.png"
},
{
"id": "8SJZZFCZJS",
"parentId": "SBME88VTUD",
"label": "车型市场价格分析",
"href": "models",
"icon": "/api/home/pic//20211209090657836.png"
},
{
"id": "A5DMDVJFHF",
"parentId": "AVL9YSB7ZF",
"label": "角色管理",
"href": "/system/role",
"icon": "/api/home/pic//20211117143545387.png"
},
{
"id": "ASPYP4MLJZ",
"parentId": "XBFBR7UADZ",
"label": "报告管理",
"href": "/report/manager",
"icon": "/api/home/pic//20211209090620133.png"
},
{
"id": "AVL9YSB7ZF",
"parentId": "6f6fafb4a7",
"label": "系统管理",
"href": "/system/menu",
"icon": "/api/home/pic//20211117143522174.png"
},
{
"id": "JM54MJCN3X",
"parentId": "6F46UACEMG",
"label": "分价格段市占率",
"href": "/overall/occupancy",
"icon": ""
},
{
"id": "KTBEN9KFFW",
"parentId": "8SJZZFCZJS",
"label": "价格趋势",
"href": "/models/mpricetrend",
"icon": ""
},
{
"id": "5AFTKUQ2Q5",
"parentId": "8SJZZFCZJS",
"label": "车型对比分析",
"href": "/models/contrast",
"icon": ""
},
{
"id": "CC5ZS54PPK",
"parentId": "AVL9YSB7ZF",
"label": "用户管理",
"href": "/system/user",
"icon": "/api/home/pic//20211116145901232.png"
},
{
"id": "KFP3AXHFP9",
"parentId": "6F46UACEMG",
"label": "细分市场竞争格局",
"href": "/overall/marketpattern",
"icon": ""
},
{
"id": "SBME88VTUD",
"parentId": "6f6fafb4a7",
"label": "价格板块",
"href": "/overall/opricetrend",
"icon": "/api/home/pic//20211116153747821.png"
},
{
"id": "2EDDH5GWZJ",
"parentId": "8SJZZFCZJS",
"label": "车型竞争格局",
"href": "/models/modelspattern",
"icon": ""
},
{
"id": "6f6fafb4a7",
"parentId": "0",
"label": "顶级菜单",
"href": null,
"icon": null
}
]
+104
View File
@@ -0,0 +1,104 @@
import axios from 'axios';
import {Message, Loading} from 'element-ui';
import store from '../store';
import router from "../router";
import {BASE_URL} from "../utils/http";
// 记录请求个数、加载
let count = 0, loading = null;
// axios实例化
const instance = axios.create({
baseURL: '/library',
// timeout: 60000,
headers: {
'Cache-Control': 'no-cache',
'Pragma': 'no-cache'
}
});
// 添加请求拦截器
instance.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
loading = Loading.service(null);
count++;
store.commit('saveIsLoading', true);
return config;
}, function (error) {
// 对请求错误做些什么
count--;
if (count < 1) {
loading.close();
store.commit('saveIsLoading', false);
}
Message.error(error);
return Promise.reject(error);
});
// 添加响应拦截器
instance.interceptors.response.use(function (response) {
// 对响应数据做点什么
count--;
if (count < 1) {
loading.close();
store.commit('saveIsLoading', false);
}
// 登录超时
if (response.data.respCode === '401') {
store.commit('saveUserInfo', null);
router.push('/login');
Message.error('登录超时过期');
// var url = 'http://192.168.144.22:9966/login?loginType=1'
// // var url = 'http://10.64.23.30:7766/home'
//
// return window.open('http://192.168.144.29:9090/cas/login?service='+url, '_self');
// return window.open('https://caddmuat.changan.com.cn/cas/login?service='+url, '_self');
// window.open(BASE_URL.BASE_CHANGAN + "/logout?service=" + BASE_URL.BASE_LOCAL + "/login?loginType=1", '_self');
}
// 请求成功
if (response.status === 200) {
if (response.data.respCode === "0") {
return response.data;
} else if (response.data.respCode === "-1") {
Message.error(response.data.message);
return Promise.reject(response);
} else {
return response;
}
} else { // 请求失败
Message.error(response.data.message);
return Promise.reject(response);
}
}, function (error) {
// 对响应错误做点什么
count--;
if (count < 1) {
loading.close();
store.commit('saveIsLoading', false);
}
// 登录过期
if (error.response.status === 401) {
store.commit('saveUserInfo', null);
router.push('/login');
Message.error('登录超时过期');
// window.open(BASE_URL.BASE_CHANGAN + "/logout?service=" + BASE_URL.BASE_LOCAL + "/login?loginType=1", '_self');
// var url = 'http://192.168.144.22:9966/login?loginType=1'
// // var url = 'http://10.64.23.30:7766/home'
//
// return window.open('http://192.168.144.29:9090/cas/login?service='+url, '_self');
// // return window.open('https://caddmuat.changan.com.cn/cas/login?service='+url, '_self');
}
// 判断超时
if (error.code === "ECONNABORTED" && error.message.indexOf('timeout') !== -1 && !error.config._retry) {
Message.error(error.message);
} else {
Message.error(error.message);
}
return Promise.reject(error);
});
export {instance, loading};
+6444
View File
File diff suppressed because it is too large Load Diff
+173
View File
@@ -0,0 +1,173 @@
<template>
<el-container>
<el-header>
<Header></Header>
</el-header>
<el-container class="main-content">
<el-aside width="200px">
<el-scrollbar class="menu">
<Menu :menuData="menuData"></Menu>
</el-scrollbar>
</el-aside>
<el-main>
<el-scrollbar class="main main1">
<router-view/>
</el-scrollbar>
</el-main>
</el-container>
</el-container>
</template>
<script>
import Header from '@/components/Header';
import Menu from '@/components/Menu';
export default {
name: "Layout",
components: {
Header,
Menu
},
data() {
return {
menuData: []
}
},
watch: {
'$route.path': {
handler(val) {
this.getMenu();
},
deep: true
}
},
methods: {
handleTree(arr, parentId) {
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 === parentId; //返回第一层
})
},
addLevel(data, level) {
data.forEach(item => {
item.level = level;
if (item.children) {
this.addLevel(item.children, level + 1);
}
});
return data;
},
getMenu() {
if (!this.$route.query.id) {
return this.$router.push({path: '/report/list', query:{"id": "AEHJB8YNJ3"}});
}
let data = JSON.parse(JSON.stringify(this.$store.state.menuData));
let menu = data.filter(item => item.parentId === this.$route.query.id);
let menuData = [];
let menuFun = (menu) => {
menuData = [...menuData, ...menu];
let parentIds = menu.map(item => item.id);
if (parentIds.length) {
menuFun(data.filter(item => parentIds.find(el => el === item.parentId)))
}
};
menuFun(menu);
let treeData = this.handleTree(menuData, this.$route.query.id);
this.menuData = this.addLevel(treeData, 1);
},
getSysMenu() {
this.$api.role.sysRoleGetRoleHome({roleId: this.$store.state.userInfo.roleIdList[0]}).then(({data}) => {
if (data === null) {
data = []
}
data = data.sort((a, b) => a.sort - b.sort);
let menu = data;//.filter(item => item.belong);
let menuData = [];
let menuFun = (menu) => {
menuData = [...menuData, ...menu]
let parentIds = menu.map(item => item.parentId);
if (parentIds.length) {
menuFun(data.filter(item => parentIds.find(el => el === item.id)))
}
}
menuFun(menu);
let treeData = menuData.map(item => ({
id: item.id,
parentId: item.parentId,
label: item.name,
href: item.href,
icon: item.iconHref,
isCollage: true,
belong: item.belong,
isUrl: item.isUrl
}));
// 去重
let obj = {};
treeData.forEach(item => {
obj[item.id] = item;
})
this.$store.commit('saveMenuData', Object.values(obj));
this.getMenu();
});
}
},
created() {
// 判定菜单是否存在,存在则不加载
let menuData = this.$store.state.menuData;
if (menuData.length == 0) {
this.getSysMenu();
} else {
this.getMenu();
}
}
}
</script>
<style lang="scss" scoped>
.el-header {
background: url("../assets/imgs/bg-header.png") no-repeat center center;
background-size: cover;
padding: 0;
}
.main-content {
height: calc(100vh - 60px);
.el-aside {
background-color: #FFFFFF;
.menu {
width: 100%;
height: 100%;
}
}
.el-main {
background-color: #F8F8FA;
padding: 0;
::v-deep .main.el-scrollbar {
height: 100%;
.el-scrollbar__view {
padding: 10px 8px;
}
}
::v-deep .main1.el-scrollbar {
height: 100%;
.el-scrollbar__view {
height: 100% !important;
padding: 10px 8px;
}
}
}
}
</style>
+171
View File
@@ -0,0 +1,171 @@
<template>
<div class="login">
<div class="login-main">
<div class="login-box">
<el-form :model="form" label-position="top" label-width="80px">
<el-form-item>
<h1>长安汽车-科技长安智慧伙伴</h1>
</el-form-item>
<el-form-item label="用户名:">
<el-input v-model="form.username" prefix-icon="el-icon-user" size="small"
placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item label="密码:">
<el-input v-model="form.password" prefix-icon="el-icon-edit" type="password" size="small"
placeholder="请输入密码"></el-input>
</el-form-item>
<el-form-item label="验证码:">
<el-input v-model="form.verifyCode" prefix-icon="el-icon-edit-outline" size="small"
placeholder="请输入验证码">
<div slot="append" style="width: 100px;height: 30px;">
<el-image style="width: 100%; height: 100%" @click="verifyCode" :src="verifyImg"
fit="fill"></el-image>
</div>
</el-input>
</el-form-item>
<el-form-item>
<el-checkbox v-model="isChecked">记住密码</el-checkbox>
</el-form-item>
<el-form-item>
<el-button type="primary" size="small" style="width: 100%;" @click="login">登录</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</template>
<script>
import {Base64} from "js-base64";
export default {
name: "Login",
data() {
return {
form: {
username: '',
password: '',
verifyCode: '',
},
verifyImg: '',
isChecked: false,
}
},
created() {
this.init();
},
methods: {
getQueryVariable(r, variable) {
if (r) {
var query = r.split('?');
if (query && query.length == 2) {
var vars = query[1].split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
}
}
},
init() {
this.isChecked = !!this.$store.state.rememberData;
if (this.isChecked) {
this.form.username = this.$store.state.rememberData.username;
this.form.password = this.$store.state.rememberData.password;
}
this.verifyCode();
},
// 登录
login() {
if (!this.form.username) {
return this.$message.warning('请输入用户名')
}
if (!this.form.password) {
return this.$message.warning('请输入密码')
}
if (!this.form.verifyCode) {
return this.$message.warning('请输入验证码')
}
if (this.form.verifyCode.length !== 4) {
return this.$message.warning('请检查验证码')
}
this.$store.commit('saveRememberData', this.isChecked ? {
username: this.form.username,
password: this.form.password
} : null);
let data = JSON.parse(JSON.stringify(this.form));
data.username = this.$JSEncrypt(data.username);
data.password = this.$JSEncrypt(data.password);
let jsonData = JSON.stringify(data);
this.$api.login.login(Base64.encode(jsonData)).then(res => {
if (res.respCode !== '0') {
this.verifyCode();
return this.$message.error(res.data.message);
}
this.$message.success('登录成功');
this.$store.commit('saveUserInfo', res.data);
this.$router.push({path: '/report/list', query:{"id": "AEHJB8YNJ3"}});
}).catch(_ => {
this.verifyCode();
})
},
// 获取验证码
verifyCode() {
this.$api.login.verifyCode({})
.then(res => {
this.verifyImg = `data: image/jpeg;base64,${btoa(new Uint8Array(res.data).reduce((data, byte) => data + String.fromCharCode(byte), ''))}`
})
},
}
}
</script>
<style lang="scss" scoped>
.login {
width: 100%;
height: 100%;
background-color: #1fc8db;
background-image: linear-gradient(45deg, #9fb8ad 0%, #1fc8db 51%, #2cb5e8 75%);
position: relative;
.login-main {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
.login-box {
background-color: #fff;
width: 400px;
min-height: 200px;
margin-top: 20px;
border-radius: 5px;
box-shadow: 0 0 20px 0 rgb(0 0 0 / .2);
padding: 30px 20px;
h1 {
text-align: center;
color: #2b2b2b;
font-size: 18px;
}
::v-deep .el-form-item {
margin-bottom: 10px;
.el-form-item__label {
padding-bottom: 0;
}
.el-input-group__append {
padding: 0;
}
}
}
}
}
</style>
+15
View File
@@ -0,0 +1,15 @@
<template>
<div>
注册
</div>
</template>
<script>
export default {
name: "Register"
}
</script>
<style scoped>
</style>
+154
View File
@@ -0,0 +1,154 @@
<template>
<div class="content-height report-detail">
<div class="title">
<el-tooltip :content="row.name" placement="top-start">
<span>{{ row.name || '-' }}</span>
</el-tooltip>
</div>
<div class="desc">
<el-row>
<el-col :span="24" class="desc-item">
<label>关键词</label>
<div>{{ row.keyContent || '-' }}</div>
</el-col>
<el-col :span="24" class="desc-item">
<label>内容摘要</label>
<p>{{ row.mainContent || '-' }}</p>
</el-col>
<el-col :span="24" class="desc-item">
<label>所属部门</label>
<div>{{ row.department || '-' }}</div>
</el-col>
</el-row>
</div>
<div class="report-download">
<span>报告详情</span>
<el-button type="primary" @click="downloadRow(row)">报告下载</el-button>
</div>
<div class="preview-content" v-html="content"></div>
</div>
</template>
<script>
import {downloadFile} from "../../utils/downloadFile";
export default {
name: "ReportDetail",
data(){
return {
content: '',
row: {},
}
},
methods: {
// 预览
previewRow() {
if(!this.$route.query.row){
this.$router.push({path: '/report/list', query: {id: this.$route.query.id}});
return
}
this.row = JSON.parse(this.$route.query.row);
this.$api.report.reportGetReportHtmlId({id: this.row.id}).then(({data}) => {
this.content = data.content;
})
},
// 下载
downloadRow(row){
// this.$confirm('此操作将下载所选数据文件, 是否继续?', '提示', {
// confirmButtonText: '确定',
// cancelButtonText: '取消',
// type: 'warning'
// }).then(() => {
this.$api.report.reportDownload({fileId: row.fileId}).then(res => {
downloadFile(res);
})
// })
}
},
created() {
this.previewRow();
}
}
</script>
<style lang="scss" scoped>
.report-detail {
.title {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
border-bottom: 1px solid #EBEEF5;
height: 42px;
line-height: 42px;
margin: 0 18px 0 22px;
text-align: center;
span {
font-size: 16px;
font-weight: 600;
color: #262626;
}
}
.desc{
padding: 11px 26px 6px 48px;
.desc-item{
display: flex;
justify-content: flex-start;
align-items: flex-start;
margin-bottom: 12px;
label{
display: inline-block;
height: 19px;
line-height: 19px;
font-size: 14px;
font-weight: 400;
color: #595959;
width: 64px;
border-right: 1px solid #BFBFBF;
margin-right: 9px;
}
div,p{
flex: 1;
font-size: 14px;
font-weight: 400;
color: #434343;
}
p{
line-height: 20px;
text-align: justify;
}
}
}
.report-download {
height: 40px;
background: #F2F6FC;
border: 1px solid #EBEEF5;
margin: 0 14px 0 13px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 7px 0 9px;
span {
font-size: 16px;
font-weight: 500;
color: #262626;
}
}
.preview-content {
margin: 0 14px 0 13px;
padding-bottom: 11px;
img {
max-width: 100% !important;
}
table{
margin: 0 auto;
}
}
}
</style>
+552
View File
@@ -0,0 +1,552 @@
<template>
<div class="content-height report-list">
<div class="title">
<span>报告列表</span>
</div>
<div class="tag-search">
<el-row>
<el-col :span="24">
<div class="tag-item">
<label class="tag-title">报告年份</label>
<el-select v-model="q.year" multiple collapse-tags placeholder="请选择报告年份">
<template v-for="item in yearList">
<el-option :label="item" :value="item" :key="item"></el-option>
</template>
</el-select>
</div>
</el-col>
<el-col :span="24">
<div class="tag-item">
<el-tooltip :content="tagData[1].name" placement="top">
<label class="tag-title">{{ tagData[1].name }}</label>
</el-tooltip>
<div class="tag-show" :class="{'active': tagData[1].tagShow}">
<el-checkbox :indeterminate="tagData[1].isIndeterminate" v-model="tagData[1].checkAll"
@change="(val) => handleCheckAllChange(val, 1)">全部
</el-checkbox>
<el-checkbox-group v-model="q.labelOneId"
@change="(val) => handleCheckedTagsChange(val, 1)">
<template v-for="item in tagData[1].tags">
<el-checkbox :label="item.id" :key="item.id">{{ item.name }}</el-checkbox>
</template>
</el-checkbox-group>
<i @click="switchTagShow(1)"
:class="{'el-icon-arrow-down': !tagData[1].tagShow, 'el-icon-arrow-up': tagData[1].tagShow}"></i>
</div>
</div>
</el-col>
<el-col :span="24">
<div class="tag-item">
<el-tooltip :content="tagData[2].name" placement="top">
<label class="tag-title">{{ tagData[2].name }}</label>
</el-tooltip>
<div class="tag-show" :class="{'active': tagData[2].tagShow}">
<el-checkbox :indeterminate="tagData[2].isIndeterminate" v-model="tagData[2].checkAll"
@change="(val) => handleCheckAllChange(val, 2)">全部
</el-checkbox>
<el-checkbox-group v-model="q.labelTwoId"
@change="(val) => handleCheckedTagsChange(val, 2)">
<template v-for="item in tagData[2].tags">
<el-checkbox :label="item.id" :key="item.id">{{ item.name }}</el-checkbox>
</template>
</el-checkbox-group>
<i @click="switchTagShow(2)"
:class="{'el-icon-arrow-down': !tagData[2].tagShow, 'el-icon-arrow-up': tagData[2].tagShow}"></i>
</div>
</div>
</el-col>
<el-col :span="24">
<div class="tag-item">
<el-tooltip :content="tagData[3].name" placement="top">
<label class="tag-title">{{ tagData[3].name }}</label>
</el-tooltip>
<div class="tag-show" :class="{'active': tagData[3].tagShow}">
<el-checkbox :indeterminate="tagData[3].isIndeterminate" v-model="tagData[3].checkAll"
@change="(val) => handleCheckAllChange(val, 3)">全部
</el-checkbox>
<el-checkbox-group v-model="q.labelThreeId"
@change="(val) => handleCheckedTagsChange(val, 3)">
<template v-for="item in tagData[3].tags">
<el-checkbox :label="item.id" :key="item.id">{{ item.name }}</el-checkbox>
</template>
</el-checkbox-group>
<i @click="switchTagShow(3)"
:class="{'el-icon-arrow-down': !tagData[3].tagShow, 'el-icon-arrow-up': tagData[3].tagShow}"></i>
</div>
</div>
</el-col>
<el-col :span="12">
<div class="tag-item">
<label class="tag-title">搜索:</label>
<el-input v-model="q.keyContent" placeholder="请输入搜索内容"></el-input>
</div>
</el-col>
<el-col :span="12" align="right" class="tag-btns">
<el-button type="primary" @click="search">查询</el-button>
<el-button type="default" @click="reset">重置</el-button>
</el-col>
</el-row>
</div>
<div class="table">
<vxe-table :data="tableData" :empty-render="{name: 'NotData'}" align="center" border stripe v-table-min-height="'calc(100vh - 420px)'">
<vxe-column show-overflow show-header-overflow type="seq" title="序号" width="77">
<template #default="{ row, rowIndex }">
{{ rowIndex + (q.pageNo - 1) * q.pageSize + 1 }}
</template>
</vxe-column>
<vxe-column show-header-overflow field="name" title="报告名称">
<template #default="{ row, rowIndex }">
<div class="row-info">
<img v-if="row.fileType === '3'" class="icon-file-type" src="@/assets/imgs/icon-pdf.png" alt="">
<img v-if="row.fileType === '4'" class="icon-file-type" src="@/assets/imgs/icon-doc.png" alt="">
<img v-if="row.fileType === '1'" class="icon-file-type" src="@/assets/imgs/icon-ppt.png" alt="">
<img v-if="row.fileType === '2'" class="icon-file-type" src="@/assets/imgs/icon-excel.png" alt="">
<div class="row-text">
<label class="row-title" @click="goReportDetail(row)">
<el-tooltip :content="row.name" placement="top-start">
<span>{{row.name}}</span>
</el-tooltip>
</label>
<div class="tag-info">
<span class="icon-tag-item"><img src="@/assets/imgs/icon-time.png"
alt=""><span>{{row.year}}</span></span>
<span class="icon-tag-item"><img src="@/assets/imgs/icon-tag01.png"
alt=""><span>{{row.labelOneName}}</span></span>
<span class="icon-tag-item"><img src="@/assets/imgs/icon-tag02.png"
alt=""><span>{{row.labelTwoName}}</span></span>
<span class="icon-tag-item"><img src="@/assets/imgs/icon-tag03.png"
alt=""><span>{{row.labelThreeName}}</span></span>
<!--<span class="icon-tag-item"><span>{{(row.fileSize / 1024 / 1024).toFixed(2) }}MB</span></span>-->
</div>
</div>
</div>
</template>
</vxe-column>
<vxe-column show-overflow show-header-overflow title="操作" width="200" fixed="right">
<template #default="{ row }">
<el-button type="text" @click="previewRow(row)">预览</el-button>
<el-button type="text" @click="downloadRow(row)">下载</el-button>
</template>
</vxe-column>
</vxe-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="q.pageNo"
:page-sizes="[5, 10, 20]"
:page-size="q.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"/>
</div>
<!--预览-->
<el-dialog title="预览" :visible.sync="dialogPreview" width="1000px" :close-on-click-modal="false"
:close-on-press-escape="false" :fullscreen="fullscreen">
<div slot="title" class="dialog-title">
<span>预览</span>
<img v-if="!fullscreen" class="full-screen" src="@/assets/imgs/icon-full.png" alt="" @click="fullscreen = !fullscreen">
<img v-else class="full-screen" src="@/assets/imgs/icon-small.png" alt="" @click="fullscreen = !fullscreen">
</div>
<div class="preview-dialog-body" :class="{'active': fullscreen}">
<!-- <img v-if="!fullscreen" class="full-screen" src="@/assets/imgs/icon-full.png" alt="" @click="fullscreen = !fullscreen">
<img v-else class="full-screen" src="@/assets/imgs/icon-small.png" alt="" @click="fullscreen = !fullscreen"> -->
<el-scrollbar>
<div class="preview-content" v-html="content"></div>
</el-scrollbar>
</div>
</el-dialog>
</div>
</template>
<script>
import {downloadFile} from "../../utils/downloadFile";
export default {
name: "ReportList",
data() {
return {
fullscreen: false,
q: {
keyContent: '',
year: [],
labelOneId: [],
labelTwoId: [],
labelThreeId: [],
pageNo: 1,
pageSize: 10,
},
total: 0,
tableData: [],
yearList: [],
tagData: {
1: {
name: '',
tagShow: false,
tags: [],
isIndeterminate: true,
checkAll: false,
},
2: {
name: '',
tagShow: false,
tags: [],
isIndeterminate: true,
checkAll: false,
},
3: {
name: '',
tagShow: false,
tags: [],
isIndeterminate: true,
checkAll: false,
},
},
dialogPreview: false, // 预览
content: '',
}
},
methods: {
init() {
this.labelList();
this.reportDateList();
this.reportList();
},
// 标签列表
labelList() {
this.$api.report.labelList().then(({data}) => {
this.tagData[1].name = data.labelOne.name;
this.tagData[2].name = data.labelTwo.name;
this.tagData[3].name = data.labelThree.name;
this.tagData[1].tags = data.labelOne.childList;
this.tagData[2].tags = data.labelTwo.childList;
this.tagData[3].tags = data.labelThree.childList;
})
},
search(){
this.q.pageNo = 1;
this.reportList();
},
// 列表
reportList() {
this.$api.report.reportList(this.q).then(({data}) => {
this.tableData = data.records;
this.total = data.total;
this.q.pageNo = data.current;
this.q.pageSize = data.size;
if(!data.records.length && this.q.pageNo !== 1){
this.q.pageNo = 1;
this.reportList();
}
})
},
// 监听全选按钮
handleCheckAllChange(val, type) {
switch (type) {
case 1:
this.q.labelOneId = val ? this.tagData[type].tags.map(item => item.id) : [];
break;
case 2:
this.q.labelTwoId = val ? this.tagData[type].tags.map(item => item.id) : [];
break;
case 3:
this.q.labelThreeId = val ? this.tagData[type].tags.map(item => item.id) : [];
break;
}
this.tagData[type].isIndeterminate = !val;
},
// 监听group checkbox
handleCheckedTagsChange(val, type) {
this.tagData[type].checkAll = (val.length === this.tagData[type].tags.length);
this.tagData[type].isIndeterminate = val.length < this.tagData[type].tags.length;
},
// 切换展开隐藏
switchTagShow(type) {
this.tagData[type].tagShow = !this.tagData[type].tagShow;
},
// 日期列表
reportDateList() {
this.$api.report.reportDateList().then(({data}) => {
this.yearList = data.list;
})
},
// 单页数据量
handleSizeChange(val) {
this.q.pageSize = val;
this.q.pageNo = 1;
this.reportList();
},
// 第几页
handleCurrentChange(val) {
this.q.pageNo = val;
this.reportList();
},
// 预览
previewRow(row) {
this.fullscreen = false;
this.$api.report.reportGetReportHtmlId({id: row.id}).then(({data}) => {
this.content = data.content;
this.dialogPreview = true;
})
},
// 重置
reset() {
this.q = {
keyContent: '',
year: [],
labelOneId: [],
labelTwoId: [],
labelThreeId: [],
pageNo: 1,
pageSize: 10,
};
this.total = 0;
this.tableData = [];
this.tagData[1].checkAll = false;
this.tagData[1].isIndeterminate = true;
this.tagData[2].checkAll = false;
this.tagData[2].isIndeterminate = true;
this.tagData[3].checkAll = false;
this.tagData[3].isIndeterminate = true;
this.reportList();
},
// 下载
downloadRow(row) {
// this.$confirm('此操作将下载所选数据文件, 是否继续?', '提示', {
// confirmButtonText: '确定',
// cancelButtonText: '取消',
// type: 'warning'
// }).then(() => {
this.$api.report.reportDownload({fileId: row.fileId}).then(res => {
downloadFile(res);
})
// })
},
// 跳转到详情
goReportDetail(row) {
this.$router.push({path: '/report/detail', query: {id: this.$route.query.id, row: JSON.stringify(row)}});
}
},
created() {
this.init();
}
}
</script>
<style lang="scss" scoped>
.report-list {
.title {
border-bottom: 1px solid #EBEEF5;
height: 42px;
line-height: 42px;
margin: 0 18px 0 22px;
span {
font-size: 16px;
font-weight: 600;
color: #262626;
}
}
.tag-search {
padding-top: 9px;
::v-deep .el-date-picker,
::v-deep .el-input {
width: 240px;
}
.tag-item {
margin-bottom: 15px;
display: flex;
.year {
::v-deep .el-input__inner {
padding: 0 15px !important;
}
}
label.tag-title {
font-size: 14px;
font-weight: normal;
color: #646464;
display: inline-block;
width: 112px;
height: 19px;
line-height: 19px;
padding-left: 48px;
border-right: 1px solid #BFBFBF;
margin-right: 10px;
margin-top: 2.5px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.tag-show {
flex: 1;
margin-right: 28px;
height: 19px;
overflow: hidden;
position: relative;
&.active {
height: auto;
}
::v-deep .check-active{
.el-checkbox__label{
color: #434343;
}
}
::v-deep .el-checkbox {
margin-right: 15px;
color: #434343;
}
::v-deep .el-checkbox__label {
min-width: 80px;
}
::v-deep .el-checkbox-group {
display: inline;
}
.el-icon-arrow-down,
.el-icon-arrow-up {
color: #C0C4CC;
cursor: pointer;
position: absolute;
right: 0;
top: 2px;
}
}
}
.tag-btns {
padding-right: 15px;
}
}
.table {
margin: 0 14px 0 13px;
.row-info {
width: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
.icon-file-type {
width: 48px;
height: 48px;
margin-right: 21px;
}
.row-text {
width: calc(100% - 48px - 21px);
flex: 1;
display: flex;
flex-flow: column;
text-align: left;
.row-title {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
font-size: 14px;
font-weight: 500;
color: #262626;
cursor: pointer;
&:hover {
color: #1890FF;
}
}
.tag-info {
.icon-tag-item {
margin-left: 12px;
img {
width: 12px;
margin-right: 5px;
vertical-align: middle;
}
span {
display: inline-block;
min-width: 80px;
font-size: 12px;
color: #8C8C8C;
font-weight: 500;
vertical-align: middle;
}
}
}
}
}
::v-deep .el-pagination {
margin-top: 13px;
padding-left: 20px;
padding-bottom: 10px;
}
}
.dialog-title{
display: inline-flex;
justify-content: center;
align-items: center;
.full-screen{
cursor: pointer;
width: 24px;
height: 24px;
vertical-align: middle;
margin-left: 10px;
}
}
.preview-dialog-body {
padding: 9px 25px 17px 22px;
height: 60vh;
position: relative;
&.active{
height: calc(100vh - 52px);
}
.full-screen{
cursor: pointer;
position: absolute;
z-index: 10;
right: 35px;
top: 10px;
width: 24px;
height: 24px;
//&:hover{
// color: #199BFF;
//}
}
::v-deep .el-scrollbar {
height: 100%;
.el-scrollbar__wrap{
overflow-x: auto;
}
.el-scrollbar__view {
padding: 0 !important;
.preview-content{
img {
max-width: 100% !important;
}
table{
margin: 0 auto;
}
}
}
}
}
}
</style>
File diff suppressed because it is too large Load Diff
+18
View File
@@ -0,0 +1,18 @@
<template>
<div style="font-size: 14px">
您没有当前页面的权限请向管理员申请
</div>
</template>
<script>
export default {
name: 'Page401',
data() {
return {}
},
methods: {}
}
</script>
<style lang="scss" scoped>
</style>
+475
View File
@@ -0,0 +1,475 @@
<template>
<div class="content-height system-menu-manager">
<div class="title">
<span>菜单管理</span>
</div>
<div class="search">
<el-row>
<el-col :span="24">
<div class="operate-box">
<el-button @click="addMenu(null, 0)">新增菜单</el-button>
</div>
</el-col>
</el-row>
</div>
<div class="table">
<vxe-table :data="tableData" :empty-render="{name: 'NotData'}" align="left" border
:tree-config="{transform: true, rowField: 'id', parentField: 'parentId', expandAll: true }"
v-table-min-height="'calc(100vh - 320px + 44px + 42px)'">
<vxe-column show-overflow show-header-overflow type="seq" title="序号" width="77"></vxe-column>
<vxe-column show-overflow show-header-overflow title="名称" width="300" align="center" tree-node>
<template #default="{ row, level }">
<div class="menu-image">
<el-image v-if="level === 0 || level === 2" :src="row.iconHref"></el-image>
<span>{{row.name}}</span>
</div>
</template>
</vxe-column>
<vxe-column show-overflow show-header-overflow field="href" title="路径" align="center"></vxe-column>
<vxe-column show-overflow show-header-overflow field="sort" title="排序" width="60"
align="center"></vxe-column>
<vxe-column show-overflow show-header-overflow field="remarks" title="描述" align="center"></vxe-column>
<vxe-column show-overflow show-header-overflow title="操作" width="200" fixed="right" align="center">
<template #default="{ row, level }">
<el-button type="text" @click="addMenu(row, level)">添加子菜单</el-button>
<el-button type="text" @click="modifyRow(row, level)">编辑</el-button>
<el-button type="text" class="del-btn" @click="deleteRow(row)">删除</el-button>
</template>
</vxe-column>
</vxe-table>
</div>
<!-- 新增/编辑/查看 菜单 -->
<el-dialog :title="dialogTitle + '菜单'" :visible.sync="dialogMenu" width="750px" :close-on-click-modal="false"
:close-on-press-escape="false" modal-append-to-body append-to-body>
<div class="menu-form">
<el-form :model="form" label-width="186px" :disabled="mode === 'view'">
<el-form-item label="菜单名称:" required>
<el-input v-model="form.name" maxlength="20" placeholder="请输入菜单名称" show-word-limit></el-input>
</el-form-item>
<el-form-item label="菜单路径:">
<el-input v-model="form.href" placeholder="请输入菜单路径" show-word-limit></el-input>
<!--<el-select v-model="form.href" filterable placeholder="请选择菜单路径">-->
<!--<el-option label="-" value=""></el-option>-->
<!--<template v-for="item in pathList">-->
<!--<el-option :label="item" :value="item" :key="item"></el-option>-->
<!--</template>-->
<!--</el-select>-->
</el-form-item>
<el-form-item label="菜单图标:" class="icon-menu-item" v-if="level === 0 || level === 2">
<el-upload action="#" :http-request="(params)=>uploadFile(params)"
:show-file-list="false" :before-upload="beforeUploadFile">
<span class="icon-menu-text">
<img v-if="form.icon" :src="form.iconHref" alt="" class="icon-menu">
<i v-else class="el-icon-plus"></i>
</span>
</el-upload>
</el-form-item>
<el-form-item label="菜单排序:" required>
<el-input-number v-model="form.sort" controls-position="right" :min="1" :step="1"
step-strictly></el-input-number>
</el-form-item>
<el-form-item label="菜单描述:">
<el-input v-model="form.remarks" maxlength="500" type="textarea" placeholder="请填写"
show-word-limit></el-input>
</el-form-item>
<el-form-item label="跳转网页:" class="jumpClass">
<el-checkbox v-model="form.isUrl" true-label="1" false-label="0"></el-checkbox>
</el-form-item>
</el-form>
<div class="done">
<el-button v-if="mode !== 'view'" type="primary" @click="postOrPutSysMenu">确定</el-button>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import {fileType} from "@/utils/fileType";
export default {
name: "MenuManager",
data() {
return {
form: {
name: '', // 名称
href: '', // 路径
icon: '', // 图标
iconHref: '', // 图标路径
sort: '', // 排序
remarks: '', // 描述
id: '',
parentId: '',
isUrl: 0,
},
tableData: [],
dialogMenu: false,
mode: '',
pathList: [],
level: 0,
}
},
methods: {
init() {
this.sysMenuFindAllMenus();
this.getRouterPath();
},
// 菜单
sysMenuFindAllMenus() {
this.$api.menu.sysMenuFindAllMenus().then(({data}) => {
this.tableData = data.filter(item => item.id !== '6f6fafb4a7').sort((a, b) => {
return a.sort - b.sort;
});
})
},
// 新增弹窗
addMenu(row, level) {
this.mode = 'add';
this.level = level + 1;
this.form = {
name: '', // 名称
href: '', // 路径
icon: '', // 图标
iconHref: '', // 图标路径
sort: '', // 排序
remarks: '', // 描述
id: '',
parentId: '',
isUrl: 0,
};
this.form.parentId = row ? row.id : '6f6fafb4a7';
this.dialogMenu = true;
},
// 新增 修改
postOrPutSysMenu() {
if (!this.form.name) {
return this.$message.warning('请输入菜单名称');
}
if (this.level === 0 || this.level === 2) {
// if (!this.form.icon) {
// return this.$message.warning('请上传菜单图标');
// }
}
if (this.mode === 'add') {
this.$api.menu.postSysMenu(this.form).then(_ => {
this.$message.success('操作成功');
this.dialogMenu = false;
this.sysMenuFindAllMenus();
})
}
if (this.mode === 'modify') {
this.$api.menu.putSysMenu(this.form).then(_ => {
this.$message.success('操作成功');
this.dialogMenu = false;
this.sysMenuFindAllMenus();
})
}
},
// 图标上传
uploadFile(params) {
let fd = new FormData();
fd.append('file', params.file);
this.$api.report.reportUploadPicFile(fd).then(({data}) => {
this.form.icon = data.key;
this.form.iconHref = data.value;
})
},
beforeUploadFile(file) {
const isType = (file.type === fileType.png || file.type === fileType.jpg);
const isSize = file.size / 1024 / 1024 < 2;
if (!isType) {
this.$message.error('仅能上传 pngjpg 格式文件');
}
if (!isSize) {
this.$message.error('您最大可上传2M文件');
}
return isType && isSize;
},
// 删除
deleteRow(row) {
this.$confirm('此操作将删除所选数据, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$api.menu.sysMenuDeleteId({ids: row.id}).then(_ => {
this.$message.success('操作成功');
this.sysMenuFindAllMenus();
})
})
},
// 编辑
modifyRow(row, level) {
this.level = level;
this.mode = 'modify';
this.form = JSON.parse(JSON.stringify(row));
this.dialogMenu = true;
},
// 获取存在路径
getRouterPath() {
let pathList = [];
let pathFun = (data, url) => {
data.forEach(item => {
if (item.children) {
pathFun(item.children, item.path);
} else {
pathList.push(`${url ? (url + '/') : ''}${item.path}`);
}
})
}
pathFun(this.$router.options.routes);
this.pathList = pathList;
},
},
computed: {
dialogTitle() {
switch (this.mode) {
case 'add':
return '新增';
case 'modify':
return '编辑';
case 'view':
return '查看';
}
}
},
created() {
this.init();
}
}
</script>
<style lang="scss" scoped>
.jumpClass .el-checkbox {
line-height: 36px;
}
.system-menu-manager {
.title {
border-bottom: 1px solid #EBEEF5;
height: 42px;
line-height: 42px;
margin: 0 18px 0 22px;
span {
font-size: 16px;
font-weight: 600;
color: #262626;
}
}
.search {
.search-box-left {
padding-top: 20px;
display: flex;
justify-content: flex-start;
align-items: center;
label {
font-size: 14px;
font-weight: 400;
color: #595959;
margin-right: 5px;
padding-left: 22px;
}
.year {
::v-deep .el-input__inner {
padding: 0 15px !important;
}
}
::v-deep .el-input {
width: 167px;
margin-right: 5px;
}
@media screen and (max-width: 1366px) {
::v-deep .el-input {
width: 135px;
margin-right: 5px;
}
}
::v-deep .el-button {
float: right;
}
}
.search-box-right {
padding-top: 20px;
display: flex;
justify-content: flex-end;
align-items: center;
padding-right: 14px;
}
.operate-box {
padding-left: 13px;
padding-bottom: 11px;
padding-top: 18px;
}
}
.table {
margin: 0 14px 0 13px;
padding-bottom: 10px;
// ::v-deep .el-icon-circle-plus,
// ::v-deep .el-icon-remove{
// font-size: 18px;
// margin-top: -4px;
// margin-left: -1.5px;
// }
.menu-image {
display: flex;
align-items: center;
justify-content: flex-start;
position: relative;
z-index: 10;
::v-deep .el-image {
width: 30px;
height: 30px;
margin: 0 5px;
.el-image__error {
font-size: 12px;
line-height: 12px;
text-align: center;
}
}
}
::v-deep .el-pagination {
margin-top: 13px;
padding-left: 20px;
padding-bottom: 10px;
}
}
}
.menu-form {
padding-top: 26px;
::v-deep .el-form {
padding-right: 79px;
.icon-menu-item .el-form-item__content > div:first-child {
display: flex !important;
}
.el-form-item {
margin-bottom: 10px;
.el-form-item__label {
height: 36px;
line-height: 36px;
font-size: 14px;
font-weight: 500;
color: #262626;
}
.el-input__inner {
min-height: 36px;
}
.el-input__inner,
.el-textarea__inner {
font-size: 14px;
font-weight: 400;
color: #434343;
}
.el-select {
width: 100%;
}
.el-date-editor {
width: 100%;
.el-input__inner {
padding-left: 15px;
}
.el-input__suffix {
font-size: 16px;
margin-top: 2px;
}
}
.icon-auth {
.el-icon-arrow-up {
margin-top: 2px;
transform: rotateZ(0) !important;
}
.el-icon-arrow-up:before {
content: '';
background: url("../../assets/imgs/icon-user.png") no-repeat center center;
display: inline-block;
width: 12px;
height: 14px;
background-size: 100% 100%;
}
}
.el-input-number {
width: 100%;
input {
text-align: left;
}
.el-input-number__decrease,
.el-input-number__increase {
height: 18px;
line-height: 18px;
font-size: 14px;
width: 30px;
}
}
.icon-menu-text {
display: flex;
width: 36px;
height: 36px;
overflow: hidden;
border: 1px dashed #8C8C8C;
align-items: center;
justify-content: center;
color: #8C8C8C;
font-size: 18px;
.icon-menu {
width: 100%;
height: 100%;
}
}
.el-button {
width: 80px;
height: 36px;
padding: 0;
text-align: center;
}
}
}
.done {
text-align: center;
padding: 40px 0;
::v-deep .el-button {
width: 80px;
height: 36px;
padding: 0;
}
}
}
</style>
+459
View File
@@ -0,0 +1,459 @@
<template>
<div class="content-height system-role">
<div class="title">
<span>角色管理</span>
</div>
<div class="search">
<el-row>
<el-col :span="24">
<div class="operate-box">
<el-button @click="addRole">新增角色</el-button>
</div>
</el-col>
</el-row>
</div>
<div class="table">
<vxe-table :data="tableData" :empty-render="{name: 'NotData'}" align="center" border stripe
v-table-min-height="'calc(100vh - 320px + 44px + 42px)'">
<vxe-column show-overflow show-header-overflow type="seq" title="序号" width="77"></vxe-column>
<vxe-column show-overflow show-header-overflow field="rname" title="名称"></vxe-column>
<vxe-column show-overflow show-header-overflow field="rdesc" title="描述"></vxe-column>
<vxe-column show-overflow show-header-overflow title="操作" width="250" fixed="right">
<template #default="{ row }">
<el-button type="text" @click="modifyRow(row)">编辑</el-button>
<el-button type="text" @click="openPermission(row, 2)">角色权限</el-button>
<el-button type="text" @click="openPermission(row, 1)">首页权限</el-button>
<el-button type="text" class="del-btn" @click="delSysRole(row)">删除</el-button>
</template>
</vxe-column>
</vxe-table>
</div>
<!-- 新增/编辑 角色 -->
<el-dialog :title="dialogTitle + '角色'" :visible.sync="dialogRole" width="750px" :close-on-click-modal="false"
:close-on-press-escape="false" modal-append-to-body append-to-body>
<div class="role-form">
<el-form :model="form" label-width="186px" :disabled="mode === 'view'">
<el-form-item label="角色名称:" required>
<el-input v-model="form.rname" maxlength="10" placeholder="请输入角色名称" show-word-limit></el-input>
</el-form-item>
<el-form-item label="角色描述:">
<el-input v-model="form.rdesc" maxlength="500" type="textarea" placeholder="请输入角色描述" show-word-limit></el-input>
</el-form-item>
</el-form>
<div class="done">
<el-button v-if="mode !== 'view'" type="primary" @click="postOrPutSysRole">确定</el-button>
</div>
</div>
</el-dialog>
<!-- 角色权限 -->
<el-dialog :title="isHomePage === 2 ? '角色权限' : '首页权限'" :visible.sync="dialogPermission" width="750px" :close-on-click-modal="false"
:close-on-press-escape="false" modal-append-to-body append-to-body>
<div class="permission-form">
<vxe-table ref="rolePermission" :data="treeData" :empty-render="{name: 'NotData'}" align="left" border height="300px" row-id="id"
:tree-config="{transform: true, rowField: 'id', parentField: 'parentId', expandAll: true }"
:checkbox-config="checkboxConfig" :key="tableKey">
<vxe-column show-overflow type="checkbox" width="77" align="center"></vxe-column>
<vxe-column show-overflow show-header-overflow type="seq" title="序号" width="77"></vxe-column>
<vxe-column show-overflow show-header-overflow title="名称" tree-node>
<template #default="{ row, level }">
<div class="menu-image">
<el-image v-if="level === 0 || level === 1" :src="row.iconHref"></el-image>
<span>{{ row.name }}</span>
</div>
</template>
</vxe-column>
</vxe-table>
<div class="done">
<template v-if="isHomePage === 1">
<el-button type="primary" @click="sysRoleSaveRoleHome">确定</el-button>
<el-button @click="getSysHome(roleId)">重置</el-button>
</template>
<template v-if="isHomePage === 2">
<el-button type="primary" @click="sysRoleSaveRoleMenu">确定</el-button>
<el-button @click="getSysMenu(roleId)">重置</el-button>
</template>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import {v4 as uuidv4} from 'uuid';
export default {
name: "Role",
data() {
return {
tableData: [], // 角色列表
dialogRole: false,
mode: '',
form: {
rname: '',
rdesc: '',
rid: ''
},
dialogPermission: false,
treeData: [],
checkboxConfig: {
checkRowKeys: []
},
roleId: '',
tableKey: uuidv4(),
isHomePage: null, // 配置首页 1首页 2权限
}
},
methods: {
init() {
this.getSysRole();
this.sysMenuFindAllMenus();
},
/* =============================================== 角色列表 =============================================== */
// 角色列表
getSysRole() {
this.$api.role.getSysRole().then(({data}) => {
this.tableData = data;
})
},
// 删除角色
delSysRole(row) {
this.$confirm('此操作将删除所选角色, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$api.role.delSysRole({id: row.rid}).then(({data}) => {
this.$message.success('操作成功');
this.getSysRole();
})
})
},
/* =============================================== 角色弹窗 =============================================== */
// 新增角色
addRole() {
this.mode = 'add';
this.form = {
rname: '',
rdesc: '',
rid: ''
}
this.dialogRole = true;
},
// 编辑角色
modifyRow(row) {
this.mode = 'modify';
this.form = {
rname: row.rname,
rdesc: row.rdesc,
rid: row.rid
}
this.dialogRole = true;
},
// 新增 修改
postOrPutSysRole() {
if (!this.form.rname) {
return this.$message.warning('请输入角色名称');
}
if (this.mode === 'add') {
this.$api.role.postSysRole(this.form).then(_ => {
this.$message.success('操作成功');
this.dialogRole = false;
this.getSysRole();
})
}
if (this.mode === 'modify') {
this.$api.role.putSysRole(this.form).then(_ => {
this.$message.success('操作成功');
this.dialogRole = false;
this.getSysRole();
})
}
},
/* =============================================== 角色权限 =============================================== */
// 获取菜单
openPermission(row, type) {
this.roleId = row.rid;
this.isHomePage = type;
if(type === 2){
this.$api.menu.getSysMenu({roleId: row.rid}).then(({data}) => {
this.checkboxConfig.checkRowKeys = data.filter(item => item.belong === 1).map(item => item.id);
this.tableKey = uuidv4();
this.dialogPermission = true;
})
}else if(type === 1) {
this.$api.role.sysRoleGetRoleHome({roleId: row.rid}).then(({data}) => {
if(data === null){
data = []
}
this.checkboxConfig.checkRowKeys = data.filter(item => item.belong === 1).map(item => item.id);
this.tableKey = uuidv4();
this.dialogPermission = true;
})
}
},
// 获取权限
getSysMenu(roleId){
this.$api.menu.getSysMenu({roleId}).then(({data}) => {
this.checkboxConfig.checkRowKeys = data.filter(item => item.belong === 1).map(item => item.id);
this.tableKey = uuidv4();
})
},
// 获取首页
getSysHome(roleId){
this.$api.role.sysRoleGetRoleHome({roleId}).then(({data}) => {
if(data === null){
data = []
}
this.checkboxConfig.checkRowKeys = data.filter(item => item.belong === 1).map(item => item.id);
this.tableKey = uuidv4();
})
},
// 添加权限
sysRoleSaveRoleMenu() {
let ids = this.$refs.rolePermission.getCheckboxRecords().map(item => item.id);
let params = {
rid: this.roleId,
menusstr: ids
}
this.$api.role.sysRoleSaveRoleMenu(params).then(_ => {
this.$message.success('操作成功');
this.dialogPermission = false;
})
},
// 首页配置
sysRoleSaveRoleHome(){
let ids = this.$refs.rolePermission.getCheckboxRecords().map(item => item.id);
let params = {
rid: this.roleId,
menusstr: ids
}
this.$api.role.sysRoleSaveRoleHome(params).then(_ => {
this.$message.success('操作成功');
this.dialogPermission = false;
})
},
// 菜单
sysMenuFindAllMenus() {
this.$api.menu.sysMenuFindAllMenus().then(({data}) => {
this.treeData = data.filter(item => item.id !== '6f6fafb4a7').sort((a, b) => {
return a.sort - b.sort;
});
})
},
},
computed: {
dialogTitle() {
switch (this.mode) {
case 'add':
return '新增';
case 'modify':
return '编辑';
case 'view':
return '查看';
}
}
},
created() {
this.init();
}
}
</script>
<style lang="scss" scoped>
.system-role {
.title {
border-bottom: 1px solid #EBEEF5;
height: 42px;
line-height: 42px;
margin: 0 18px 0 22px;
span {
font-size: 16px;
font-weight: 600;
color: #262626;
}
}
.search {
.search-box-left {
padding-top: 20px;
display: flex;
justify-content: flex-start;
align-items: center;
label {
font-size: 14px;
font-weight: 400;
color: #595959;
margin-right: 5px;
padding-left: 22px;
}
.year {
::v-deep .el-input__inner {
padding: 0 15px !important;
}
}
::v-deep .el-input {
width: 167px;
margin-right: 5px;
}
@media screen and (max-width: 1366px) {
::v-deep .el-input {
width: 135px;
margin-right: 5px;
}
}
::v-deep .el-button {
float: right;
}
}
.search-box-right {
padding-top: 20px;
display: flex;
justify-content: flex-end;
align-items: center;
padding-right: 14px;
}
.operate-box {
padding-left: 13px;
padding-bottom: 11px;
padding-top: 18px;
}
}
.table {
margin: 0 14px 0 13px;
padding-bottom: 10px;
::v-deep .el-pagination {
margin-top: 13px;
padding-left: 20px;
padding-bottom: 10px;
}
}
}
.role-form {
padding-top: 26px;
::v-deep .el-form {
padding-right: 79px;
.el-form-item {
margin-bottom: 10px;
.el-form-item__label {
height: 36px;
line-height: 36px;
font-size: 14px;
font-weight: 500;
color: #262626;
}
.el-input__inner {
min-height: 36px;
}
.el-input__inner,
.el-textarea__inner {
font-size: 14px;
font-weight: 400;
color: #434343;
}
.el-select {
width: 100%;
}
.el-date-editor {
width: 100%;
.el-input__inner {
padding-left: 15px;
}
.el-input__suffix {
font-size: 16px;
margin-top: 2px;
}
}
.icon-auth {
.el-icon-arrow-up {
margin-top: 2px;
transform: rotateZ(0) !important;
}
.el-icon-arrow-up:before {
content: '';
background: url("../../assets/imgs/icon-user.png") no-repeat center center;
display: inline-block;
width: 12px;
height: 14px;
background-size: 100% 100%;
}
}
.el-button {
width: 80px;
height: 36px;
padding: 0;
text-align: center;
}
}
}
.done {
text-align: center;
padding: 40px 0;
::v-deep .el-button {
width: 80px;
height: 36px;
padding: 0;
}
}
}
.permission-form {
padding: 26px 33px 0 33px;
.menu-image {
display: flex;
align-items: center;
justify-content: flex-start;
position: relative;
z-index: 10;
::v-deep .el-image {
width: 30px;
height: 30px;
margin: 0 5px;
.el-image__error {
font-size: 12px;
line-height: 12px;
text-align: center;
}
}
}
.done {
text-align: center;
padding: 40px 0;
::v-deep .el-button {
width: 80px;
height: 36px;
padding: 0;
}
}
}
</style>
+525
View File
@@ -0,0 +1,525 @@
<template>
<div class="content-height system-user">
<div class="title">
<span>用户管理</span>
</div>
<div class="search">
<el-row>
<el-col :span="20">
<div class="search-box-left">
<label>用户名:</label>
<el-input v-model="q.account" placeholder="请输入用户名"></el-input>
<label>角色名:</label>
<el-select v-model="q.roleName" class="icon-auth" placeholder="请选择角色名">
<el-option label="全部" value=""></el-option>
<template v-for="item in roleList">
<el-option :label="item.rname" :value="item.rname" :key="item.rid"></el-option>
</template>
</el-select>
</div>
</el-col>
<el-col :span="4" align="right">
<div class="search-box-right">
<el-button type="primary" @click="search">查询</el-button>
<el-button @click="reset">重置</el-button>
</div>
</el-col>
<el-col :span="24">
<div class="operate-box">
<el-button @click="add">新增用户</el-button>
<el-button @click="getSelectUser">批量删除</el-button>
<el-button @click="downloadTemp">模板下载</el-button>
<el-upload
class="upload-demo"
action="/library/api/sys/user/import"
:show-file-list="false"
:on-success="uploadPDFSuccess"
style="display: inline-block;margin-right: 10px;margin-left: 10px;">
<el-button @click="newAddFunc">批量导入</el-button>
</el-upload>
</div>
</el-col>
</el-row>
</div>
<div class="table">
<vxe-table ref="userTable" :data="tableData" :empty-render="{name: 'NotData'}" align="center" border stripe
v-table-min-height="'calc(100vh - 320px)'">
<vxe-column show-overflow type="checkbox" width="77"></vxe-column>
<vxe-column show-overflow show-header-overflow type="seq" title="序号" width="77">
<template #default="{ row, rowIndex }">
{{ rowIndex + (q.pageNo - 1) * q.pageSize + 1 }}
</template>
</vxe-column>
<vxe-column show-overflow show-header-overflow field="ACCOUNT" title="用户名"></vxe-column>
<vxe-column show-overflow show-header-overflow field="CELLPHONE_NUMBER" title="手机号"></vxe-column>
<vxe-column show-overflow show-header-overflow field="CREATEDATE" title="创建时间"></vxe-column>
<vxe-column show-overflow show-header-overflow field="DEPARTMENT" title="部门"></vxe-column>
<vxe-column show-overflow show-header-overflow field="EMAIL" title="邮箱"></vxe-column>
<vxe-column show-overflow show-header-overflow field="ROLENAME" title="角色"></vxe-column>
<vxe-column show-overflow show-header-overflow field="USNAME" title="姓名"></vxe-column>
<vxe-column show-overflow show-header-overflow title="启用/禁用" width="100" fixed="right">
<template #default="{ row }">
<el-switch v-model="row.ISUSE" active-value="1" inactive-value="0"
@change="(val) => sysUserIsUse(val, row)"></el-switch>
</template>
</vxe-column>
<vxe-column show-overflow show-header-overflow title="操作" width="200" fixed="right">
<template #default="{ row }">
<el-button type="text" @click="openRowData('view', row)">查看</el-button>
<el-button type="text" @click="openRowData('modify', row)">编辑</el-button>
<el-button type="text" class="del-btn" @click="deleteRow(row)">删除</el-button>
</template>
</vxe-column>
</vxe-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="q.pageNo"
:page-sizes="[5, 10, 20]"
:page-size="q.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"/>
</div>
<!-- 新增/编辑/查看 用户 -->
<el-dialog :title="dialogTitle + '用户'" :visible.sync="dialogUser" width="750px" :close-on-click-modal="false"
:close-on-press-escape="false" modal-append-to-body append-to-body>
<div class="user-form">
<el-form :model="form" label-width="186px" :disabled="mode === 'view'">
<el-form-item label="用户名:" required>
<el-input v-model="form.account" maxlength="20" show-word-limit placeholder="请输入用户名"></el-input>
</el-form-item>
<!--<el-form-item label="密码:" :required="mode === 'add'" v-if="mode !== 'view'">-->
<!--<el-input v-model="form.password" maxlength="20" type="password" placeholder="请输入密码"></el-input>-->
<!--</el-form-item>-->
<!--<el-form-item label="确认密码:" :required="mode === 'add'" v-if="mode !== 'view'">-->
<!--<el-input v-model="repassword" maxlength="20" type="password" placeholder="请确认密码"></el-input>-->
<!--</el-form-item>-->
<el-form-item label="手机号:">
<el-input v-model="form.cellPhoneNumber" placeholder="请输入手机号"></el-input>
</el-form-item>
<el-form-item label="部门:">
<el-input v-model="form.department" maxlength="50" show-word-limit placeholder="请输入部门"></el-input>
</el-form-item>
<el-form-item label="邮箱:">
<el-input v-model="form.email" placeholder="请输入邮箱"></el-input>
</el-form-item>
<el-form-item label="角色:" required>
<el-select v-model="form.roleIdList[0]" class="icon-auth" placeholder="请选择角色">
<template v-for="item in roleList">
<el-option :label="item.rname" :value="item.rid" :key="item.rid"></el-option>
</template>
</el-select>
</el-form-item>
<el-form-item label="姓名:" required>
<el-input v-model="form.usname" maxlength="20" show-word-limit placeholder="请输入姓名"></el-input>
</el-form-item>
</el-form>
<div class="done">
<el-button v-if="mode !== 'view'" type="primary" @click="sysUserAddUser">确定</el-button>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import {Base64} from "js-base64";
export default {
name: "User",
data() {
return {
q: {
account: '', // 用户名
roleName: '', // 角色名称
pageNo: 1,
pageSize: 10,
},
total: 0,
tableData: [],
mode: '',
dialogUser: false,
form: {
account: '', // 用户名
cellPhoneNumber: '', // 手机号
department: '', // 部门
email: '', // 邮箱
password: '', // 密码
usid: '',
usname: '', // 姓名
roleIdList: [''], // 角色
},
repassword: '',
roleList: [],
}
},
methods: {
search(){
this.q.pageNo = 1;
this.sysUserList();
},
// 获取所有用户
sysUserList() {
this.$api.user.sysUserList(this.q).then(({data}) => {
this.tableData = data.records;
this.total = data.total;
this.q.pageNo = data.current;
this.q.pageSize = data.size;
if(!data.records.length && this.q.pageNo !== 1){
this.q.pageNo = 1;
this.sysUserList();
}
})
},
// 重置
reset() {
this.q = {
account: '', // 用户名
roleName: '', // 角色名称
pageNo: 1,
pageSize: 10,
};
this.total = 0;
this.tableData = [];
this.sysUserList();
},
// 单页数据量
handleSizeChange(val) {
this.q.pageSize = val;
this.q.pageNo = 1;
this.sysUserList();
},
// 第几页
handleCurrentChange(val) {
this.q.pageNo = val;
this.sysUserList();
},
// 新增
add() {
this.mode = 'add';
this.form = {
account: '', // 用户名
cellPhoneNumber: '', // 手机号
department: '', // 部门
email: '', // 邮箱
password: '', // 密码
usid: '',
usname: '', // 姓名
roleIdList: [''], // 角色
};
this.repassword = '';
this.dialogUser = true;
},
// 启用/禁用
sysUserIsUse(val, row) {
this.$confirm(val === '0' ? '此操作将禁用所选用户, 是否继续?' : '此操作将启用所选用户, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$api.user.sysUserIsUse({USID: row.USID, type: val}).then(_ => {
this.$message.success('操作成功');
this.sysUserList();
})
}).catch(() => {
row.ISUSE = val === '1' ? '0' : '1';
});
},
// 删除
deleteRow(row) {
this.deleteUser(row.USID);
},
// 验证
checkUserForm() {
if (this.mode === 'add') {
if (!this.form.account || !(/^[a-zA-Z0-9]*$/.test(this.form.account))) {
return this.$message.warning('用户名只能为纯数字、纯字母或字母数字组合') && false;
}
// // 密码
// if (!(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/.test(this.form.password))) {
// return this.$message.warning('密码至少8个字符,至少1个大写字母,1个小写字母,1个数字') && false;
// }
// if (this.repassword !== this.form.password) {
// return this.$message.warning('请检查密码') && false;
// }
}
if(this.mode === 'modify'){
// if (this.form.password || this.repassword) {
// // 密码
// if (!(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/.test(this.form.password))) {
// return this.$message.warning('密码至少8个字符,至少1个大写字母,1个小写字母,1个数字') && false;
// }
// if (this.repassword !== this.form.password) {
// return this.$message.warning('请检查密码') && false;
// }
// }
}
if (this.form.cellPhoneNumber && !(/^1[3|4|5|7|8|9][0-9]{9}$/.test(this.form.cellPhoneNumber))) {
return this.$message.warning('请检查手机号') && false;
}
if (this.form.email && !(/^[\w-.]+@[a-z\d-]+(\.[a-z\d-]+)*\.[a-z\d]{2,6}$/i.test(this.form.email))) {
return this.$message.warning('请检查邮箱') && false;
}
if (!this.form.roleIdList[0]) {
return this.$message.warning('请选择角色') && false;
}
if (!this.form.usname) {
return this.$message.warning('请输入姓名') && false;
}
return true;
},
// 新增用户
sysUserAddUser() {
if (!this.checkUserForm()) return;
let data = JSON.parse(JSON.stringify(this.form));
data.account = this.$JSEncrypt(data.account);
data.password = this.$JSEncrypt(data.password);
let jsonData = JSON.stringify(data);
this.$api.user.sysUserAddUser(Base64.encodeURI(jsonData)).then(_ => {
this.$message.success('操作成功');
this.dialogUser = false;
this.reset();
})
},
// 编辑查看用户
openRowData(mode, row) {
this.mode = mode;
this.form = {
account: row.ACCOUNT, // 用户名
cellPhoneNumber: row.CELLPHONE_NUMBER, // 手机号
department: row.DEPARTMENT, // 部门
email: row.EMAIL, // 邮箱
password: '', // 密码
usid: row.USID, // 用户ID
usname: row.USNAME, // 姓名
roleIdList: [row.ROLEID], // 角色
}
this.repassword = '';
this.dialogUser = true;
},
newAddFunc(){
},
uploadPDFSuccess(response, file, fileList) {
if (response.ok) {
this.$message.success('导入成功');
this.reset()
} else {
this.$message.error(response.message);
}
},
downloadTemp(){
window.open('/library/api/sys/user/template')
},
// 多选用户
getSelectUser() {
let users = this.$refs.userTable.getCheckboxRecords();
if (!users.length) {
return this.$message.warning('请选择数据后在进行操作');
}
let ids = users.map(item => item.USID).join(',');
this.deleteUser(ids);
},
// 删除用户
deleteUser(ids) {
this.$confirm('此操作将删除所选用户, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$api.user.sysUserDelete({ids}).then(_ => {
this.$message.success('操作成功');
this.sysUserList();
})
})
},
// 角色列表
getSysRole() {
this.$api.role.getSysRole().then(({data}) => {
this.roleList = data;
})
},
},
computed: {
dialogTitle() {
switch (this.mode) {
case 'add':
return '新增';
case 'modify':
return '编辑';
case 'view':
return '查看';
}
}
},
created() {
this.sysUserList();
this.getSysRole();
}
}
</script>
<style lang="scss" scoped>
.system-user {
.title {
border-bottom: 1px solid #EBEEF5;
height: 42px;
line-height: 42px;
margin: 0 18px 0 22px;
span {
font-size: 16px;
font-weight: 600;
color: #262626;
}
}
.search {
.search-box-left {
padding-top: 20px;
display: flex;
justify-content: flex-start;
align-items: center;
label {
font-size: 14px;
font-weight: 400;
color: #595959;
margin-right: 5px;
padding-left: 22px;
}
.year {
::v-deep .el-input__inner {
padding: 0 15px !important;
}
}
::v-deep .el-input {
width: 167px;
margin-right: 5px;
}
@media screen and (max-width: 1366px) {
::v-deep .el-input {
width: 135px;
margin-right: 5px;
}
}
::v-deep .el-button {
float: right;
}
}
.search-box-right {
padding-top: 20px;
display: flex;
justify-content: flex-end;
align-items: center;
padding-right: 14px;
}
.operate-box {
padding-left: 13px;
padding-bottom: 11px;
padding-top: 18px;
}
}
.table {
margin: 0 14px 0 13px;
::v-deep .el-pagination {
margin-top: 13px;
padding-left: 20px;
padding-bottom: 10px;
}
}
}
.user-form {
padding-top: 26px;
::v-deep .el-form {
padding-right: 79px;
.el-form-item {
margin-bottom: 10px;
.el-form-item__label {
height: 36px;
line-height: 36px;
font-size: 14px;
font-weight: 500;
color: #262626;
}
.el-input__inner {
min-height: 36px;
}
.el-input__inner,
.el-textarea__inner {
font-size: 14px;
font-weight: 400;
color: #434343;
}
.el-select {
width: 100%;
}
.el-date-editor {
width: 100%;
.el-input__inner {
padding-left: 15px;
}
.el-input__suffix {
font-size: 16px;
margin-top: 2px;
}
}
.icon-auth {
.el-icon-arrow-up {
margin-top: 2px;
transform: rotateZ(0) !important;
}
.el-icon-arrow-up:before {
content: '';
background: url("../../assets/imgs/icon-user.png") no-repeat center center;
display: inline-block;
width: 12px;
height: 14px;
background-size: 100% 100%;
}
}
.el-button {
width: 80px;
height: 36px;
padding: 0;
text-align: center;
}
}
}
.done {
text-align: center;
padding: 40px 0;
::v-deep .el-button {
width: 80px;
height: 36px;
padding: 0;
}
}
}
</style>
+266
View File
@@ -0,0 +1,266 @@
<template>
<div class="content-height system-menu-manager">
<iframe :src="this.$store.state.pathUrl" id="mobsf" frameborder="0" style="width: 100%"></iframe>
</div>
</template>
<script>
export default {
name: "MenuManager",
data() {
return {
url: ''
}
},
methods: {},
computed: {},
created() {
this.url = this.$store.state.pathUrl
},
mounted() {
/**
* iframe-宽高自适应显示
*/
function changeMobsfIframe() {
const mobsf = document.getElementById('mobsf');
const deviceWidth = document.body.clientWidth;
const deviceHeight = document.body.clientHeight;
mobsf.style.width = '100%'; //数字是页面布局宽度差值
mobsf.style.height = (Number(deviceHeight) - 86) + 'px'; //数字是页面布局高度差
}
changeMobsfIframe()
window.onresize = function () {
changeMobsfIframe()
}
}
}
</script>
<style lang="scss" scoped>
.jumpClass .el-checkbox {
line-height: 36px;
}
.system-menu-manager {
.title {
border-bottom: 1px solid #EBEEF5;
height: 42px;
line-height: 42px;
margin: 0 18px 0 22px;
span {
font-size: 16px;
font-weight: 600;
color: #262626;
}
}
.search {
.search-box-left {
padding-top: 20px;
display: flex;
justify-content: flex-start;
align-items: center;
label {
font-size: 14px;
font-weight: 400;
color: #595959;
margin-right: 5px;
padding-left: 22px;
}
.year {
::v-deep .el-input__inner {
padding: 0 15px !important;
}
}
::v-deep .el-input {
width: 167px;
margin-right: 5px;
}
@media screen and (max-width: 1366px) {
::v-deep .el-input {
width: 135px;
margin-right: 5px;
}
}
::v-deep .el-button {
float: right;
}
}
.search-box-right {
padding-top: 20px;
display: flex;
justify-content: flex-end;
align-items: center;
padding-right: 14px;
}
.operate-box {
padding-left: 13px;
padding-bottom: 11px;
padding-top: 18px;
}
}
.table {
margin: 0 14px 0 13px;
padding-bottom: 10px;
.menu-image {
display: flex;
align-items: center;
justify-content: flex-start;
position: relative;
z-index: 10;
::v-deep .el-image {
width: 30px;
height: 30px;
margin: 0 5px;
.el-image__error {
font-size: 12px;
line-height: 12px;
text-align: center;
}
}
}
::v-deep .el-pagination {
margin-top: 13px;
padding-left: 20px;
padding-bottom: 10px;
}
}
}
.menu-form {
padding-top: 26px;
::v-deep .el-form {
padding-right: 79px;
.icon-menu-item .el-form-item__content > div:first-child {
display: flex !important;
}
.el-form-item {
margin-bottom: 10px;
.el-form-item__label {
height: 36px;
line-height: 36px;
font-size: 14px;
font-weight: 500;
color: #262626;
}
.el-input__inner {
min-height: 36px;
}
.el-input__inner,
.el-textarea__inner {
font-size: 14px;
font-weight: 400;
color: #434343;
}
.el-select {
width: 100%;
}
.el-date-editor {
width: 100%;
.el-input__inner {
padding-left: 15px;
}
.el-input__suffix {
font-size: 16px;
margin-top: 2px;
}
}
.icon-auth {
.el-icon-arrow-up {
margin-top: 2px;
transform: rotateZ(0) !important;
}
.el-icon-arrow-up:before {
content: '';
background: url("../../assets/imgs/icon-user.png") no-repeat center center;
display: inline-block;
width: 12px;
height: 14px;
background-size: 100% 100%;
}
}
.el-input-number {
width: 100%;
input {
text-align: left;
}
.el-input-number__decrease,
.el-input-number__increase {
height: 18px;
line-height: 18px;
font-size: 14px;
width: 30px;
}
}
.icon-menu-text {
display: flex;
width: 36px;
height: 36px;
overflow: hidden;
border: 1px dashed #8C8C8C;
align-items: center;
justify-content: center;
color: #8C8C8C;
font-size: 18px;
.icon-menu {
width: 100%;
height: 100%;
}
}
.el-button {
width: 80px;
height: 36px;
padding: 0;
text-align: center;
}
}
}
.done {
text-align: center;
padding: 40px 0;
::v-deep .el-button {
width: 80px;
height: 36px;
padding: 0;
}
}
}
</style>