前端初始化

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
+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>