Commit 02cfd887 authored by “yiyousong”'s avatar “yiyousong”

feat: 添加权限

parent f89e13db
......@@ -44,7 +44,7 @@
"secure-ls": "^1.2.6",
"v-viewer": "^1.6.4",
"viser-vue": "^2.4.8",
"vue": "^2.6.11",
"vue": "2.6.11",
"vue-i18n": "^8.18.2",
"vue-jsonp": "^2.0.0",
"vue-quill-editor": "^3.0.6",
......@@ -76,7 +76,7 @@
"less-loader": "^6.1.1",
"style-resources-loader": "^1.3.2",
"vue-cli-plugin-style-resources-loader": "^0.1.4",
"vue-template-compiler": "^2.6.11",
"vue-template-compiler": "2.6.11",
"vuepress": "^1.5.2",
"webpack-theme-color-replacer": "1.3.18",
"whatwg-fetch": "^3.0.0"
......
import {loadRoutes, loadGuards, setAppOptions} from '@/utils/routerUtil'
import {loadInterceptors} from '@/utils/request'
import guards from '@/router/guards'
import interceptors from '@/utils/axios-interceptors'
// import {loadRoutes, loadGuards, setAppOptions} from '@/utils/routerUtil'
import { loadInterceptors } from "@/utils/request";
// import guards from '@/router/guards'
import interceptors from "@/utils/axios-interceptors";
/**
* 启动引导方法
......@@ -11,15 +11,15 @@ import interceptors from '@/utils/axios-interceptors'
* @param i18n 应用的 vue-i18n 实例
* @param i18n 应用的 message 实例
*/
function bootstrap({router, store, i18n, message}) {
function bootstrap({ router, store, i18n, message }) {
// 设置应用配置
setAppOptions({router, store, i18n})
// setAppOptions({router, store, i18n})
// 加载 axios 拦截器
loadInterceptors(interceptors, {router, store, i18n, message})
loadInterceptors(interceptors, { router, store, i18n, message });
// 加载路由
loadRoutes()
// loadRoutes()
// 加载路由守卫
loadGuards(guards, {router, store, i18n, message})
// loadGuards(guards, {router, store, i18n, message})
}
export default bootstrap
export default bootstrap;
......@@ -2,7 +2,7 @@
import store from "@/store/index";
// 皮肤模板页面权限
export const permission = {
inserted: function(el, binding) {
inserted: function (el, binding) {
const { value } = binding;
// const roles = local.getLocal("baseUserInfo").id;
const roles = store.getters["site/userInfo"].id;
......@@ -17,3 +17,25 @@ export const permission = {
}
},
};
// 按钮鉴权
export const hasPermi = {
inserted: function (el, binding) {
const { value } = binding;
const permissions = store.getters["site/permissions"];
if (value && value instanceof Array && value.length > 0) {
const permissionFlag = value;
const hasPermissions = permissions.some((permission) => {
return permissionFlag.includes(permission);
});
if (!hasPermissions) {
el.remove();
}
} else {
throw new Error(`请设置操作权限标签值`);
}
},
};
<template>
<div class="new-page-layout">
<a-layout>
<NewPageHerder></NewPageHerder>
<a-layout>
<SideBar v-if="layout === 'side'"></SideBar>
<a-layout-content>
<keep-alive>
<!-- 需要缓存的视图组件 -->
<router-view v-if="$route.meta.keepAlive" class="layout-page">
</router-view>
</keep-alive>
<!-- 不需要缓存的视图组件 -->
<router-view class="layout-page" v-if="!$route.meta.keepAlive">
</router-view>
</a-layout-content>
</a-layout>
</a-layout>
</div>
</template>
<script>
import { mapState } from "vuex";
import NewPageHerder from "./header/NewPageHerder.vue";
import SideBar from "./side/SideBar.vue";
export default {
components: {
NewPageHerder,
SideBar,
},
data() {
return {};
},
computed: {
...mapState("setting", ["layout"]),
},
};
</script>
<style lang="less" scoped>
.new-page-layout {
width: 100vw;
height: 100vh;
}
/deep/.ant-layout {
width: 100%;
height: 100%;
.ant-layout-content {
width: 100%;
// height: calc(100% - 64px);
padding: 20px;
}
}
.layout-page {
background: #fff;
}
</style>
<template>
<div class="tableview viewbox">
<div class="head b-b">
<router-link :to="item.fullPath" v-for="(item,index) in subMenu" :key="index"><a-icon :type="item.meta.icon" /> {{item.name}}</router-link>
</div>
<router-view />
<div class="tableview">
<div class="head" v-if="secondaryRoutes.length">
<router-link
:to="item.path"
v-for="(item, index) in secondaryRoutes"
:key="index"
>
<a-icon v-if="item.meta.icon" :type="item.meta.icon" />
{{ item.meta && item.meta.title }}</router-link
>
</div>
<div ref="outBox" class="out-box">
<router-view />
</div>
</div>
</template>
<script>
import {mapGetters} from 'vuex'
import { mapState } from "vuex";
export default {
computed:{
...mapGetters('setting', ['subMenu']),
data() {
return {};
},
watch: {
"$route.path"() {
this.$refs.outBox.scrollTop = 0;
},
created(){
console.log(this.subMenu)
}
}
},
computed: {
...mapState("site", ["secondaryRoutes"]),
},
};
</script>
<style lang="less" scoped>
.tableview{
border-radius: 8px;
overflow: hidden;
.head{
padding:0 10px;
background: #fff;
a{
margin-right:30px;
color: #202020;
font-size: 14px;
padding: 10px 0;
display: inline-block;
}
.router-link-active{
color: #2681e8;
position: relative;
&::after{
content: "";
display: block;
border-bottom: 2px solid #2681e8;
position: absolute;
left: 0;
bottom: 0;
right: 0;
}
}
.tableview {
height: 100%;
border-radius: 8px;
display: flex;
flex-direction: column;
.out-box {
flex: 1;
padding: 15px;
overflow-y: auto;
background: #fff;
}
.head {
padding: 0 10px;
background: #fff;
border-bottom: 1px solid #d9d9d9;
i {
color: #2681e8;
}
a {
margin-right: 30px;
color: rgba(0, 0, 0, 0.65);
font-size: 14px;
padding: 10px 0;
display: inline-block;
font-weight: bold;
}
.router-link-active {
color: #2681e8;
position: relative;
&::after {
content: "";
display: block;
border-bottom: 2px solid #2681e8;
position: absolute;
left: 0;
bottom: 0;
right: 0;
}
}
}
}
</style>
\ No newline at end of file
</style>
<template>
<a-menu
:selectedKeys="current"
:mode="mode"
:theme="theme"
@click="changeMenu"
>
<template v-for="item in menus">
<a-sub-menu
v-if="!item.hideChildrenInMenu && item.children && item.children.length"
:key="item.path"
>
<span slot="title" class="submenu-title-wrapper"
><a-icon v-if="item.meta.icon" :type="item.meta.icon" />{{
item.meta && item.meta.title
}}</span
>
<a-menu-item v-for="v in item.children" :key="v.path">
{{ v.meta && v.meta.title }}
</a-menu-item>
</a-sub-menu>
<template v-else>
<a-menu-item :key="item.path">
<a-icon v-if="item.meta.icon" :type="item.meta.icon" />{{
item.meta && item.meta.title
}}
</a-menu-item>
</template>
</template>
</a-menu>
</template>
<script>
import { mapState, mapMutations } from "vuex";
export default {
props: {
mode: {
type: String,
default: "horizontal",
},
theme: {
type: String,
default: "light",
},
},
computed: {
...mapState("site", ["sysName", "sysLogo", "path", "menus"]),
...mapState("setting", ["layout"]),
current() {
const route = this.$route;
const { meta, matched } = route;
if (meta.activeMenu) {
return [meta.activeMenu];
}
return matched
.filter((item) => item.path)
.map((item) => item.path && item.path);
},
},
created() {},
methods: {
...mapMutations("site", ["SET_secondaryRoutes"]),
changeMenu({ key }) {
this.SET_secondaryRoutes(key);
this.$router.push({ path: key });
},
},
};
</script>
<style lang="less" scoped>
.ant-menu-horizontal {
min-width: 200px;
height: 64px;
line-height: 64px;
// vertical-align: middle;
box-shadow: none;
background: #0000;
border: none;
.ant-menu-item,
/deep/.ant-menu-submenu-title {
top: 0;
color: rgba(254, 254, 254, 0.65);
border: none;
&:hover {
color: #fff;
border: none;
}
}
/deep/.ant-menu-submenu-horizontal {
border: none;
}
/deep/.ant-menu-item-selected {
background: #1890ff !important;
color: #fff;
}
}
</style>
<template>
<a-layout-header class="new-page-herder">
<div class="logo-box">
<img
class="logo"
:src="sysLogo ? sysLogo : require('@/assets/img/logo.png')"
/>
<h1 class="title">
{{ sysName ? sysName : systemName }}
</h1>
<HeaderSite></HeaderSite>
</div>
<MenuBar v-if="layout === 'head'"></MenuBar>
<a-space size="middle">
<InitArea :visibleInit.sync="visibleInit"></InitArea>
<a v-permission="[1]" @click="visibleInit = true">
<a-icon type="redo" />
初始化区域数据
</a>
<a-tooltip title="返回门户" placement="bottom">
<a class="header-item" :href="portalUrl + (path ? path : '')">
<a-icon type="home" /> 返回门户
</a>
</a-tooltip>
<!-- 初始化区域数据弹窗 -->
</a-space>
</a-layout-header>
</template>
<script>
import { mapState, mapMutations } from "vuex";
import HeaderSite from "./HeaderSite.vue";
import MenuBar from "../components/MenuBar.vue";
import InitArea from "@/components/initarea/InitArea.vue";
export default {
components: { HeaderSite, MenuBar, InitArea },
data() {
return {
api: process.env.VUE_APP_API_basics_URL + "/",
systemName: process.env.VUE_APP_sysName,
searchActive: false,
value: undefined,
treeData: [],
visibleInit: false,
portalUrl: process.env.VUE_APP_API_portal_URL + "/#", // 门户地址
};
},
computed: {
...mapState("site", ["sysName", "sysLogo", "path", "menus"]),
...mapState("setting", ["layout"]),
current() {
const route = this.$route;
const { meta, matched } = route;
if (meta.activeMenu) {
return [meta.activeMenu];
}
return matched
.filter((item) => item.path)
.map((item) => item.path && item.path);
},
},
created() {
document.title = this.sysName ? this.sysName : this.systemName; // 设置项目标题
},
methods: {
...mapMutations("site", ["SET_secondaryRoutes"]),
changeMenu({ key }) {
this.SET_secondaryRoutes(key);
this.$router.push({ path: key });
},
},
};
</script>
<style lang="less" scoped>
.new-page-herder {
flex-shrink: 0;
padding: 0px 20px;
background: linear-gradient(90deg, #1845c6 0%, #2999ff 100%);
color: #fff;
display: flex;
justify-content: space-between;
align-items: center;
a {
color: #fff;
}
.logo-box {
display: flex;
align-items: center;
}
.logo {
height: 32px;
margin-right: 8px;
}
.title {
margin: 0px;
margin-right: 34px;
font-weight: bold;
font-size: 18px;
color: #fff;
cursor: pointer;
}
.ant-menu-horizontal {
min-width: 200px;
height: 64px;
line-height: 64px;
// vertical-align: middle;
box-shadow: none;
background: #0000;
border: none;
.ant-menu-item,
/deep/.ant-menu-submenu-title {
top: 0;
color: rgba(254, 254, 254, 0.65);
border: none;
&:hover {
color: #fff;
}
}
/deep/.ant-menu-submenu-horizontal {
border: none;
}
/deep/.ant-menu-item-selected {
background: #1890ff !important;
color: #fff;
}
}
.header-item {
color: #fff;
}
}
</style>
<template>
<a-layout-sider>
<MenuBar mode="inline"></MenuBar>
</a-layout-sider>
</template>
<script>
import MenuBar from "../components/MenuBar.vue";
export default {
components: { MenuBar },
};
</script>
<style lang="less" scoped>
.ant-layout-sider {
background: #fff;
}
</style>
......@@ -2,8 +2,20 @@
<div class="app-category">
<div class="header flex aic jcb mb20 pdr6">
<a-space>
<a-button type="primary" @click="handleAdd"> 新增主题 </a-button>
<a-button type="danger" @click="handleDelAll"> 批量移除 </a-button>
<a-button
type="primary"
v-hasPermi="['appmarket:appTheme:add']"
@click="handleAdd"
>
新增主题
</a-button>
<a-button
type="danger"
v-hasPermi="['appmarket:appTheme:remove']"
@click="handleDelAll"
>
批量移除
</a-button>
</a-space>
<a-input-search
style="width: 300px"
......@@ -52,10 +64,16 @@
<!-- 操作 -->
<template slot="action" slot-scope="{ record }">
<a-space size="middle">
<span class="primary pointer" @click="handleEdit(record)"
<span
class="primary pointer"
v-hasPermi="['appmarket:appTheme:edit']"
@click="handleEdit(record)"
>编辑</span
>
<span class="delete pointer" @click="handleDel(record.id)"
<span
class="delete pointer"
v-hasPermi="['appmarket:appTheme:remove']"
@click="handleDel(record.id)"
>删除</span
>
</a-space>
......
......@@ -4,7 +4,13 @@
<div class="header">
<div class="titel">设备应用黑名单</div>
<div class="control pdr6">
<a-button type="danger" @click="handleDelAll"> 批量移除 </a-button>
<a-button
type="danger"
v-hasPermi="['appmarket:blackapp:remove']"
@click="handleDelAll"
>
批量移除
</a-button>
<div class="business-control">
<a-space>
<a-input-search
......@@ -38,7 +44,10 @@
(blackAppTable.page - 1) * blackAppTable.size + index + 1
}}</span>
<template slot="action" slot-scope="{ record }">
<span class="delete pointer" @click="handleDel(record.id)"
<span
class="delete pointer"
v-hasPermi="['appmarket:blackapp:remove']"
@click="handleDel(record.id)"
>移除</span
>
</template>
......@@ -113,7 +122,10 @@
<template slot="action" slot-scope="{ record }">
<a-space size="middle">
<span class="primary pointer" @click="handleIn(record)"
<span
class="primary pointer"
v-hasPermi="['appmarket:blackapp:join']"
@click="handleIn(record)"
>加入黑名单</span
>
</a-space>
......@@ -136,7 +148,7 @@ import {
getBlackAppList,
deleteBlackapp,
} from "@/services/market";
import {getProductList} from "@/services/surface";
import { getProductList } from "@/services/surface";
import local from "@/utils/local";
import DevToBlack from "../modal/DevToBlack.vue";
import YTable from "@/components/YTable.vue";
......@@ -243,12 +255,12 @@ export default {
async getProductList() {
let res = await getProductList({
siteId: this.siteId,
page:1,
size:-1
page: 1,
size: -1,
});
if (res.data.code === 1) {
let { data } = res.data.data;
this.productList = data
this.productList = data;
}
},
// 获取设备黑名单
......
......@@ -2,9 +2,25 @@
<div class="terminal">
<div class="header flex aic jcb mb20 pdr6">
<a-space>
<a-button type="primary" @click="handleAdd"> 新增应用 </a-button>
<a-button type="primary" @click="handleClone"> 克隆 </a-button>
<a-button type="primary" @click="handleTheme">
<a-button
type="primary"
v-hasPermi="['appmarket:moveapp:add']"
@click="handleAdd"
>
新增应用
</a-button>
<a-button
type="primary"
v-hasPermi="['appmarket:moveapp:clone']"
@click="handleClone"
>
克隆
</a-button>
<a-button
type="primary"
v-hasPermi="['appmarket:moveapp:theme']"
@click="handleTheme"
>
批量关联应用主题
</a-button>
<a-button v-permission="[1]" type="danger" @click="handleDelAll">
......@@ -84,13 +100,22 @@
<!-- 操作 -->
<template slot="action" slot-scope="{ record }">
<a-space size="middle">
<span class="primary pointer" @click="handleCloneAppData(record)"
<span
class="primary pointer"
v-hasPermi="['appmarket:moveapp:cloneData']"
@click="handleCloneAppData(record)"
>克隆数据</span
>
<span class="primary pointer" @click="handleEdit(record)"
<span
class="primary pointer"
v-hasPermi="['appmarket:moveapp:edit']"
@click="handleEdit(record)"
>编辑</span
>
<span class="primary pointer" @click="handleCheck(record.id)"
<span
class="primary pointer"
v-hasPermi="['appmarket:moveapp:examine']"
@click="handleCheck(record.id)"
>查看</span
>
<span
......
......@@ -2,9 +2,25 @@
<div class="terminal">
<div class="header flex aic jcb mb20 pdr6">
<a-space>
<a-button type="primary" @click="handleAdd"> 新增应用 </a-button>
<a-button type="primary" @click="handleClone"> 克隆 </a-button>
<a-button type="primary" @click="handleTheme">
<a-button
type="primary"
v-hasPermi="['appmarket:terminalapp:add']"
@click="handleAdd"
>
新增应用
</a-button>
<a-button
type="primary"
v-hasPermi="['appmarket:terminalapp:clone']"
@click="handleClone"
>
克隆
</a-button>
<a-button
type="primary"
v-hasPermi="['appmarket:terminalapp:theme']"
@click="handleTheme"
>
批量关联应用主题
</a-button>
<a-button v-permission="[1]" type="danger" @click="handleDelAll">
......@@ -84,13 +100,22 @@
<!-- 操作 -->
<template slot="action" slot-scope="{ record }">
<a-space size="middle">
<span class="primary pointer" @click="handleCloneAppData(record)"
<span
class="primary pointer"
v-hasPermi="['appmarket:terminalapp:cloneData']"
@click="handleCloneAppData(record)"
>克隆数据</span
>
<span class="primary pointer" @click="handleEdit(record)"
<span
class="primary pointer"
v-hasPermi="['appmarket:terminalapp:edit']"
@click="handleEdit(record)"
>编辑</span
>
<span class="primary pointer" @click="handleCheck(record.id)"
<span
class="primary pointer"
v-hasPermi="['appmarket:terminalapp:examine']"
@click="handleCheck(record.id)"
>查看</span
>
<span
......
......@@ -147,9 +147,9 @@
<script>
import YSwitch from "../../../../components/yswitch/YSwitch.vue";
import { saveApp } from "@/services/market";
import { mapGetters } from "vuex";
import { checkCodeNumber } from "@/utils/validate";
import YUpload from "@/components/YUpload.vue";
import { getSiteTree } from "@/services/basicsetFun";
// import local from "@/utils/local";
export default {
components: {
......@@ -176,6 +176,7 @@ export default {
data() {
return {
api: process.env.VUE_APP_API_BASE_URL + "/",
SiteTree: [],
labelCol: {
span: 3,
},
......@@ -252,10 +253,35 @@ export default {
this.$emit("update:AddVisible", val);
},
},
...mapGetters("site", ["SiteTree"]),
},
created() {},
created() {
this.getSiteTree();
},
methods: {
// 区域不能选择
editSelectable(arr) {
return arr.map((v) => {
if (v.children && v.children.length > 0) {
this.editSelectable(v.children);
}
if (v.type === "area") {
v.selectable = false;
v.checkable = false;
} else {
v.selectable = true;
v.checkable = true;
}
return v;
});
},
// 获取站点树
async getSiteTree() {
let res = await getSiteTree({});
let { siteTree } = res.data.data;
siteTree = this.editSelectable(siteTree);
this.SiteTree = siteTree;
},
// 关闭
onClose() {
this.$refs.form.resetFields();
......
......@@ -28,8 +28,8 @@
</template>
<script>
import { mapGetters } from "vuex";
import { cloneApp } from "@/services/market";
import { getSiteTree } from "@/services/basicsetFun";
export default {
props: {
siteVisible: {
......@@ -48,6 +48,7 @@ export default {
data() {
return {
siteIdList: [], // 站点id
SiteTree: [],
replaceFields: {
title: "label",
key: "id",
......@@ -64,9 +65,35 @@ export default {
this.$emit("update:siteVisible", val);
},
},
...mapGetters("site", ["SiteTree"]),
},
created() {
this.getSiteTree();
},
methods: {
// 区域不能选择
editSelectable(arr) {
return arr.map((v) => {
if (v.children && v.children.length > 0) {
this.editSelectable(v.children);
}
if (v.type === "area") {
v.selectable = false;
v.checkable = false;
} else {
v.selectable = true;
v.checkable = true;
}
return v;
});
},
// 获取站点树
async getSiteTree() {
let res = await getSiteTree({});
let { siteTree } = res.data.data;
siteTree = this.editSelectable(siteTree);
this.SiteTree = siteTree;
},
async handleOk() {
if (!this.siteIdList) {
this.$message.warning("请先选择站点");
......@@ -105,4 +132,4 @@ export default {
.tips {
font-weight: 600 !important;
}
</style>
\ No newline at end of file
</style>
......@@ -6,8 +6,18 @@
<div class="control pdr6">
<div>
<a-space size="middle">
<a-button type="primary" @click="showModal"> 新增业务 </a-button>
<a-button type="danger" @click="handleBatchDelSiteBusiness">
<a-button
type="primary"
v-hasPermi="['business:businessmanage:addSiteBusiness']"
@click="showModal"
>
新增业务
</a-button>
<a-button
type="danger"
v-hasPermi="['business:businessmanage:removeSiteBusiness']"
@click="handleBatchDelSiteBusiness"
>
批量移除
</a-button>
</a-space>
......@@ -64,11 +74,13 @@
<a-space size="middle">
<span
class="primary pointer"
v-hasPermi="['business:businessmanage:editSiteBusiness']"
@click="handleEditSiteBusiness(record)"
>编辑</span
>
<span
class="delete pointer"
v-hasPermi="['business:businessmanage:removeSiteBusiness']"
@click="handleDelSiteBusiness(record.id, record)"
>删除</span
>
......@@ -83,7 +95,11 @@
<div class="titel">一体化业务列表</div>
<div class="control pdr6">
<div>
<a-button type="primary" @click="handleBatchJoin">
<a-button
type="primary"
v-hasPermi="['business:businessmanage:join']"
@click="handleBatchJoin"
>
批量加入
</a-button>
</div>
......@@ -125,11 +141,15 @@
<template slot="action" slot-scope="{ record }">
<a-space size="middle">
<span class="primary pointer" @click="handleIn(record.id)"
<span
class="primary pointer"
v-hasPermi="['business:businessmanage:join']"
@click="handleIn(record.id)"
>加入</span
>
<span
class="delete pointer"
v-hasPermi="['business:businessmanage:remove']"
@click="handleDelBusiness(+record.id)"
>删除</span
>
......@@ -538,13 +558,14 @@ export default {
width: 100%;
height: 100%;
display: flex;
position: relative;
&::after {
content: "";
width: 1px;
height: 82vh;
height: 100%;
position: absolute;
background-color: #eeeeee;
top: 44px;
top: 0px;
left: 50%;
}
.left,
......
......@@ -5,7 +5,11 @@
<div class="titel">站点事项列表</div>
<div class="header-bottom pdr6">
<div class="left-btn">
<a-button type="danger" @click="handleBatchDelSiteMatter">
<a-button
type="danger"
v-hasPermi="['business:mattermanage:removeSiteMatter']"
@click="handleBatchDelSiteMatter"
>
批量移除
</a-button>
</div>
......@@ -104,13 +108,17 @@
<span
v-if="record.source == 1"
class="primary pointer"
v-hasPermi="['business:mattermanage:editSiteMatter']"
@click="handleSiteEdit(record)"
>编辑</span
>
<span href="javascript:;" style="visibility: hidden" v-else
>编辑</span
>
<span class="delete pointer" @click="handleDel(record.id, record)"
<span
class="delete pointer"
v-hasPermi="['business:mattermanage:removeSiteMatter']"
@click="handleDel(record.id, record)"
>移除</span
>
</a-space>
......@@ -125,11 +133,27 @@
<div class="control pdr6">
<div>
<a-space size="middle">
<a-button type="primary" @click="handleAddAll">
<a-button
type="primary"
v-hasPermi="['business:mattermanage:join']"
@click="handleAddAll"
>
批量加入
</a-button>
<a-button type="primary" @click="addMatter"> 新增事项 </a-button>
<a-button type="primary" @click="handleImport"> 导入 </a-button>
<a-button
type="primary"
v-hasPermi="['business:mattermanage:addMatter']"
@click="addMatter"
>
新增事项
</a-button>
<a-button
type="primary"
v-hasPermi="['business:mattermanage:import']"
@click="handleImport"
>
导入
</a-button>
</a-space>
</div>
<div>
......@@ -218,14 +242,19 @@
v-if="record.source == 1"
class="primary pointer"
@click="handleEdit(record.id)"
v-hasPermi="['business:mattermanage:edit']"
>编辑</span
>
<span style="visibility: hidden" v-else>编辑</span>
<span class="primary pointer" @click="handleIn(record.id)"
<span
class="primary pointer"
v-hasPermi="['business:mattermanage:join']"
@click="handleIn(record.id)"
>加入</span
>
<span
class="delete pointer"
v-hasPermi="['business:mattermanage:removeMatter']"
@click="handleDelBaseMatter(record.id)"
>删除</span
>
......@@ -636,7 +665,7 @@ export default {
let input = document.createElement("input");
input.type = "file";
input.accept = ".xlsx";
input.style.display = 'none';
input.style.display = "none";
document.body.appendChild(input);
input.click();
input.onchange = async () => {
......@@ -662,13 +691,14 @@ export default {
.basicset-tab2 {
width: 100%;
display: flex;
position: relative;
&::after {
content: "";
width: 1px;
height: 82vh;
height: 100%;
position: absolute;
background-color: #eeeeee;
top: 44px;
top: 0;
left: 45%;
}
.left,
......
......@@ -9,6 +9,7 @@
type="danger"
@click="batchDelSiteBusiness"
:loading="delSiteBusinessLoading"
v-hasPermi="['business:businessinmanage:remove']"
>
批量解除
</a-button>
......@@ -50,11 +51,13 @@
<a-space>
<span
class="primary pointer"
v-hasPermi="['business:businessinmanage:info']"
@click="handleisUnbound(true, record)"
>关联详情</span
>
<span
class="delete pointer"
v-hasPermi="['business:businessinmanage:remove']"
@click="handleisUnbound(false, record)"
>解除</span
>
......@@ -69,7 +72,13 @@
<div class="titel">站点事项列表</div>
<div class="control pdr6">
<div>
<a-button type="primary" @click="handleAddAll"> 批量关联 </a-button>
<a-button
type="primary"
@click="handleAddAll"
v-hasPermi="['business:businessinmanage:correlation']"
>
批量关联
</a-button>
</div>
<div>
<a-space>
......@@ -135,7 +144,12 @@
</template>
<!-- 操作 -->
<template slot="action" slot-scope="{ record }">
<span class="primary pointer" @click="handleIn(record)">关联</span>
<span
class="primary pointer"
v-hasPermi="['business:businessinmanage:correlation']"
@click="handleIn(record)"
>关联</span
>
</template>
</y-table>
</div>
......@@ -701,13 +715,14 @@ export default {
.basicset-tab3 {
width: 100%;
display: flex;
position: relative;
&::after {
content: "";
width: 1px;
height: 82vh;
height: 100%;
position: absolute;
background-color: #eeeeee;
top: 44px;
top: 0;
left: 50%;
}
.left,
......
......@@ -117,6 +117,7 @@
<a-space size="middle">
<div
class="workguide_btn"
v-hasPermi="['business:workguide:hot']"
:style="{ color: record.hot == 1 ? '#03d76f' : '#1890FF' }"
@click="handleSiteEdit(record, 'hot')"
>
......@@ -125,6 +126,7 @@
<div
class="workguide_btn"
style="width: 60px"
v-hasPermi="['business:workguide:show']"
@click="handleSiteEdit(record, 'display')"
>
{{ record.display == 1 ? "取消展示" : "展示" }}
......
......@@ -3,8 +3,20 @@
<div class="flex aic jcb mb20">
<div>
<a-space>
<a-button type="primary" @click="handleAdd"> 新增 </a-button>
<a-button type="danger" @click="handleDelAll"> 批量删除 </a-button>
<a-button
type="primary"
v-hasPermi="['deploy:statement:add']"
@click="handleAdd"
>
新增
</a-button>
<a-button
type="danger"
v-hasPermi="['deploy:statement:remove']"
@click="handleDelAll"
>
批量删除
</a-button>
</a-space>
</div>
<a-space>
......@@ -75,10 +87,18 @@
<!-- 操作 -->
<template slot="action" slot-scope="{ record }">
<a-space size="middle">
<a href="javascript:;" class="primary" @click="handleEdit(record)"
<a
href="javascript:;"
class="primary"
v-hasPermi="['deploy:statement:edit']"
@click="handleEdit(record)"
>编辑</a
>
<a href="javascript:;" class="delete" @click="handleDel(record.id)"
<a
href="javascript:;"
class="delete"
v-hasPermi="['deploy:statement:remove']"
@click="handleDel(record.id)"
>删除</a
>
</a-space>
......
......@@ -3,10 +3,19 @@
<div class="flex1 auto-scroll-y">
<div class="control pdr6">
<div>
<a-button type="primary" style="margin-right: 10px" @click="handleAdd"
<a-button
type="primary"
style="margin-right: 10px"
v-hasPermi="['deploy:manage:add']"
@click="handleAdd"
>新增模块</a-button
>
<a-button type="danger" @click="handleDelAll">批量删除模块</a-button>
<a-button
type="danger"
v-hasPermi="['deploy:manage:remove']"
@click="handleDelAll"
>批量删除模块</a-button
>
</div>
<div class="search-box">
<a-input-search
......@@ -67,10 +76,16 @@
<!-- <span class="primary pointer" @click="statementManage(record)"
>配置报表</span
> -->
<span class="primary pointer" @click="handleEdit(record)"
<span
class="primary pointer"
v-hasPermi="['deploy:manage:edit']"
@click="handleEdit(record)"
>编辑</span
>
<span class="delete pointer" @click="handleDel(record.id)"
<span
class="delete pointer"
v-hasPermi="['deploy:manage:remove']"
@click="handleDel(record.id)"
>删除</span
>
</a-space>
......
......@@ -8,7 +8,11 @@
</TabHeader>
<div class="department_on flex aic">
<!-- <div class="department_manage">部门管理({{ deptTotal }}</div> -->
<a-button type="primary" @click="showModalAdd" class="department_add"
<a-button
type="primary"
v-hasPermi="['department:addDept']"
@click="showModalAdd"
class="department_add"
>新增部门</a-button
>
<a-input-search
......@@ -37,7 +41,7 @@
</a-tooltip>
</div>
<div class="department_icon_edit">
<a-tooltip>
<a-tooltip v-hasPermi="['department:editDept']">
<template slot="title"> 查看编辑 </template>
<a-icon
type="edit"
......@@ -46,7 +50,7 @@
@click.stop="showModal(v)"
/>
</a-tooltip>
<a-tooltip>
<a-tooltip v-hasPermi="['department:removeDept']">
<template slot="title"> 删除 </template>
<a-icon
......@@ -78,8 +82,13 @@
<div class="department_right_add">
<div class="flex aic jcb pdr6">
<a-space>
<a-button type="primary" @click="addModal">新增窗口</a-button>
<a-dropdown>
<a-button
type="primary"
@click="addModal"
v-hasPermi="['department:addWindow']"
>新增窗口</a-button
>
<a-dropdown v-hasPermi="['department:more']">
<a-menu slot="overlay">
<a-menu-item key="1">
<a-upload
......@@ -153,16 +162,28 @@
<!-- 操作 -->
<div slot="action" slot-scope="{ record }">
<div class="flex jcb flexwrap">
<span class="primary pointer" @click="workModal(record)"
<span
class="primary pointer"
v-hasPermi="['department:business']"
@click="workModal(record)"
>业务</span
>
<span class="primary pointer" @click="addWindowMatter(record)"
<span
class="primary pointer"
v-hasPermi="['department:matter']"
@click="addWindowMatter(record)"
>事项</span
>
<span class="primary pointer" @click="editModal(record)"
<span
class="primary pointer"
v-hasPermi="['department:editWindow']"
@click="editModal(record)"
>编辑</span
>
<span class="delete pointer" @click="delWindow(record.id)"
<span
class="delete pointer"
v-hasPermi="['department:removeWindow']"
@click="delWindow(record.id)"
>删除</span
>
</div>
......
......@@ -2,8 +2,18 @@
<div class="hall-manage">
<div class="control flex aic jcb mb20 pdr6">
<a-space size="middle">
<a-button type="primary" @click="handleAdd">新增大厅</a-button>
<a-button type="danger" @click="handleDelAll">批量删除</a-button>
<a-button
type="primary"
v-hasPermi="['hall:hallmanage:add']"
@click="handleAdd"
>新增大厅</a-button
>
<a-button
type="danger"
v-hasPermi="['hall:hallmanage:remove']"
@click="handleDelAll"
>批量删除</a-button
>
</a-space>
<div class="search-box">
<a-input-search
......@@ -42,10 +52,16 @@
<!-- 操作 -->
<template slot="action" slot-scope="{ record }">
<a-space size="middle">
<span class="primary pointer" @click="handleEdit(record)"
<span
class="primary pointer"
v-hasPermi="['hall:hallmanage:edit']"
@click="handleEdit(record)"
>编辑</span
>
<span class="delete pointer" @click="handleDel(record.id)"
<span
class="delete pointer"
v-hasPermi="['hall:hallmanage:remove']"
@click="handleDel(record.id)"
>删除</span
>
</a-space>
......
......@@ -4,7 +4,15 @@
<div class="header">
<div class="titel">大厅窗口</div>
<div class="control pdr6">
<a-button type="danger" @click="handleDelAll"> 批量移除 </a-button>
<div>
<a-button
type="danger"
@click="handleDelAll"
v-hasPermi="['hall:hallwindow:remove']"
>
批量移除
</a-button>
</div>
<div class="business-control">
<a-space>
<a-select
......@@ -58,7 +66,10 @@
}}</span>
<template slot="action" slot-scope="{ record }">
<span class="delete pointer" @click="handleDel(record.id)"
<span
class="delete pointer"
v-hasPermi="['hall:hallwindow:remove']"
@click="handleDel(record.id)"
>移除</span
>
</template>
......@@ -71,7 +82,13 @@
<div class="titel">站点窗口</div>
<div class="control pdr6">
<div>
<a-button type="primary" @click="handleAddAll"> 批量加入 </a-button>
<a-button
type="primary"
@click="handleAddAll"
v-hasPermi="['hall:hallwindow:join']"
>
批量加入
</a-button>
</div>
<div class="business-control">
<a-space>
......@@ -126,7 +143,10 @@
<template slot="action" slot-scope="{ record }">
<a-space size="middle">
<span class="primary pointer" @click="handleIn([record])"
<span
class="primary pointer"
v-hasPermi="['hall:hallwindow:join']"
@click="handleIn([record])"
>加入大厅</span
>
</a-space>
......
......@@ -4,9 +4,15 @@
<div class="pd15 flex1 auto-scroll-y">
<div class="btn-box pdr6">
<!-- 新增按钮 -->
<a-button type="primary" @click="showModal" class="skins_btn_1"
>新增节日</a-button
>
<div>
<a-button
type="primary"
@click="showModal"
v-hasPermi="['festival:add']"
class="skins_btn_1"
>新增节日</a-button
>
</div>
<div>
<a-space>
<a-select
......@@ -67,8 +73,18 @@
<!-- 操作 -->
<template slot="action" slot-scope="{ record }">
<a-space size="middle">
<a @click="handleEdit(record)" class="primary">编辑</a>
<a class="delete" @click="handleDel(record.id)">删除</a>
<a
@click="handleEdit(record)"
v-hasPermi="['festival:edit']"
class="primary"
>编辑</a
>
<a
class="delete"
v-hasPermi="['festival:remove']"
@click="handleDel(record.id)"
>删除</a
>
</a-space>
</template>
</y-table>
......
......@@ -7,7 +7,9 @@
<script>
import local from "@/utils/local";
import { mapMutations } from "vuex";
import { createMenus } from "@/router";
import { calcMenu, menusFilter } from "@/router";
import { getMenuIndex } from "@/services/system";
import { generateRoutes, filterBtn } from "@/utils/util";
export default {
data() {
return {};
......@@ -24,18 +26,15 @@ export default {
"SET_sysName",
"SET_sysLogo",
"SET_path",
"SET_permissions",
"SET_routes",
"SET_menusList",
"SET_secondaryRoutes",
]),
// 获取token
getToken() {
let {
token,
userInfo,
siteid,
siteName,
sysName,
sysLogo,
path,
} = this.$route.query;
let { token, userInfo, siteid, siteName, sysName, sysLogo, path } =
this.$route.query;
if (token && userInfo) {
userInfo = JSON.parse(userInfo);
this.SET_userInfo(userInfo);
......@@ -47,9 +46,7 @@ export default {
this.SET_path(path);
local.setLocal("siteId", siteid);
local.setLocal("siteName", siteName);
// 动态菜单
createMenus();
this.$router.push("/website");
this.getMenuTree();
} else {
this.$message.warning("跳转失败,请重新登录");
setTimeout(() => {
......@@ -57,6 +54,36 @@ export default {
}, 2000);
}
},
// 获取用户菜单
async getMenuTree() {
let res = await getMenuIndex();
if (res.data.code === 1) {
let {
data: { menuList },
} = res.data;
// 过滤掉按钮
let menus = filterBtn(menuList, false);
let routes = generateRoutes(menus);
routes = menusFilter(routes);
this.SET_menusList(menus);
this.setBtnPermissions(menuList);
calcMenu();
if (routes.length) {
let path = routes[0].path;
this.SET_secondaryRoutes(path);
this.$router.push(path);
} else {
this.$message.warning("暂无页面权限,请联系管理员!");
}
}
},
// 添加按钮权限字符
setBtnPermissions(menuList) {
let btnPermissions = filterBtn(menuList)
.filter((v) => v.perms)
.map((v) => v.perms);
this.SET_permissions(btnPermissions);
},
},
};
</script>
......
<template>
<div class="ff">
<Standardtable
:columns="tablecolumns"
:dataSource="tabledataSource"
:bordered="true"
:selectedRows="selectedRows"
:columnsSearch="columnsSearch"
@selectedRowChange="selectedRowChange"
></Standardtable>
<show ref="pageshow" />
</div>
</template>
<script>
import table from "@/mixins/table"
import show from "./show"
export default {
mixins: [table],
data () {
return {
tablecolumns: [
{
title: "序号",
width: "70px",
customRender: this.RenderIndex
},
{
title: "菜单名称",
dataIndex: "name",
},
{
title: "操作",
width: "200px",
customRender: (text, record) => <tableActive record={record} onEdit={this.OnTableEdit} onDel={this.OnTableDel} />
},
],//表头数据
tabledataSource: [
{ id: 1, name: "测试" },
{ id: 2, name: "测试2", children: [{ id: 3, name: "2.1" }] }
],
columnsSearch: [
{ type: 'select', dataIndex: 'type', span: 5, dictionaries: [{ label: '全部', value: '' }, { label: '选项1', value: 1 }, { label: '选项2', value: 2 }], placeholder: "请选择" },
{ type: 'text', dataIndex: 'name', span: 12, width: 150, placeholder: "请输入搜索名称" }
]//表格查询条件
}
},
components: {
show
}
}
</script>
\ No newline at end of file
<template>
<a-modal
:title="title"
:visible="formVisible"
@cancel="formVisible = false"
>
<div slot="footer">
<a-button @click="resetForm">重置</a-button>
<a-button type="primary" :loading="formConfirmLoading" @click="handleOk">确定</a-button>
</div>
<slot>
<a-form-model
ref="ruleForm"
:model="formInfo"
:rules="formRules"
:label-col="{span:labelCol}"
:wrapper-col="{span: wrapperCol}"
>
<a-form-model-item label="菜单名称" prop="grade">
<w-input v-model="formInfo.grade" placeholder="请输入菜单名称"/>
</a-form-model-item>
<a-form-model-item label="菜单图标">
<w-input v-model="formInfo.name" placeholder="请输入菜单名称"/>
</a-form-model-item>
</a-form-model>
</slot>
</a-modal>
</template>
<script>
import form from "@/mixins/form"
export default {
mixins:[form],
props:{
labelCol:{
type:Number,
default:5,
},
wrapperCol:{
type:Number,
default:16,
}
},
data(){
return{
formInfo:{
grade:"",//菜单名称
},//表单提交数据
formRules:{
grade:[{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
},//表单验证
title:"提示"
}
},
methods:{
// 保存
handleOk(){
this.formSave()
},
// 新增
onAdd(){
this.title = "新增菜单"
this.formVisible = true
},
// 编辑
onEdit(row){
this.title = "编辑菜单"
this.formVisible = true
console.log(row)
}
}
}
</script>
\ No newline at end of file
......@@ -11,19 +11,19 @@
<div class="btn-box">
<a-space size="middle" v-if="siteData.length">
<a-button
v-permission="[1]"
v-hasPermi="['website:Sync']"
type="primary"
@click="handleSync(siteData[0].id)"
>同步数据</a-button
>
<a-button
v-permission="[1]"
v-hasPermi="['website:edit']"
type="primary"
@click="editSiteInfo(siteData[0])"
>编辑</a-button
>
<a-button
v-permission="[1]"
v-hasPermi="['website:remove']"
type="danger"
@click="deleteSite(siteData[0].id, 0)"
>删除</a-button
......@@ -199,7 +199,11 @@
<a-empty description="暂无站点" />
<div class="btn_box">
<div style="width: 200px">
<a-button block size="large" @click="addSiteAll"
<a-button
block
size="large"
v-hasPermi="['website:add']"
@click="addSiteAll"
>新增站点</a-button
>
</div>
......
<template>
<div class="configurat">
<div class="title">短信全局配置</div>
<div class="des">
全局配置,一键控制
</div>
<div class="des">
轻松管理政务短信通知的全局设置,确保信息的准确传递
</div>
<div class="des">全局配置,一键控制</div>
<div class="des">轻松管理政务短信通知的全局设置,确保信息的准确传递</div>
<div class="tag-list">
<div class="tag-item" v-for="v in tagList" :key="v">
{{ v }}
</div>
</div>
<a-tooltip>
<a-tooltip v-hasPermi="['configurat:switch']">
<template slot="title">
当前状态:{{ setInfo.messageoff ? "开启" : "关闭" }}
</template>
......
......@@ -8,10 +8,16 @@
<a-button
type="primary"
style="margin-right: 10px"
v-hasPermi="['social:add']"
@click="handleAdd"
>新增</a-button
>
<a-button type="danger" @click="handleDelAll">批量删除</a-button>
<a-button
type="danger"
v-hasPermi="['social:remove']"
@click="handleDelAll"
>批量删除</a-button
>
</div>
</a-space>
</div>
......@@ -31,10 +37,16 @@
>
<template slot="action" slot-scope="{ record }">
<a-space size="middle">
<span class="primary pointer" @click="handleEdit(record)"
<span
class="primary pointer"
v-hasPermi="['social:edit']"
@click="handleEdit(record)"
>编辑</span
>
<span class="delete pointer" @click="handleDel(record.id)"
<span
class="delete pointer"
v-hasPermi="['social:remove']"
@click="handleDel(record.id)"
>删除</span
>
</a-space>
......
......@@ -35,10 +35,16 @@
</div>
</a-spin>
<div class="preview-btn">
<a-button type="primary" style="margin-bottom: 10px" @click="AddSurface"
<a-button
type="primary"
v-hasPermi="['surface:addSkin']"
style="margin-bottom: 10px"
@click="AddSurface"
>新增皮肤</a-button
>
<a-button @click="editClassify">编辑分类</a-button>
<a-button @click="editClassify" v-hasPermi="['surface:editClassify']"
>编辑分类</a-button
>
</div>
</div>
</template>
......
......@@ -24,8 +24,16 @@
</div>
<div class="show-btn flex aic jcc">
<a-space size="middle">
<a-button type="primary" @click="editSurface">修改皮肤参数</a-button>
<a-button type="danger" @click="handleClose(curSkin.id)"
<a-button
type="primary"
v-hasPermi="['surface:editSkin']"
@click="editSurface"
>修改皮肤参数</a-button
>
<a-button
type="danger"
v-hasPermi="['surface:removeSkin']"
@click="handleClose(curSkin.id)"
>删除皮肤</a-button
>
</a-space>
......
<template>
<div class="system flex flexc">
<a-tabs :activeKey="activeKey" @change="changeRouter">
<!-- <a-tab-pane key="/system/user">
<span slot="tab">
<a-icon type="user" />
用户管理
</span>
</a-tab-pane>
<a-tab-pane key="/system/role">
<span slot="tab">
<a-icon type="idcard" />
角色管理
</span>
</a-tab-pane>
<a-tab-pane key="/system/resource">
<span slot="tab">
<a-icon type="cloud-sync" />
资源管理
</span>
</a-tab-pane>
<a-tab-pane key="/system/dimension">
<span slot="tab">
<a-icon type="deployment-unit" />
维度管理
</span>
</a-tab-pane> -->
<a-tab-pane key="/system/parameter">
<span slot="tab">
<a-icon type="container" />
系统参数
</span>
</a-tab-pane>
<a-tab-pane key="/system/task">
<span slot="tab">
<a-icon type="compass" />
任务信息
</span>
</a-tab-pane>
<a-tab-pane key="/system/systemlogs">
<span slot="tab">
<a-icon type="cloud-server" />
操作日志
</span>
</a-tab-pane>
</a-tabs>
<div class="system-out-box flex1">
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
computed: {
activeKey() {
return this.$route.path;
},
},
methods: {
changeRouter(path) {
this.$router.push(path);
},
},
};
</script>
<style lang="less" scoped>
.system {
width: 100%;
height: 100%;
.system-out-box {
padding: 0px 15px 15px 15px;
overflow-y: auto;
}
/deep/.ant-tabs-nav-container {
border-bottom: 1px solid #f0f0f0 !important;
}
}
</style>
<template>
<div class="dimension-container">
<div class="control flex aic jcb mb15 pdr6">
<div>
<a-button type="primary" style="margin-right: 10px" @click="handleAdd"
>新增</a-button
>
<a-button type="danger" @click="handleDelAll">批量删除</a-button>
</div>
<div class="search-box">
<a-input-search
placeholder="请输入维度名搜索"
enter-button="搜索"
v-model="searchValue"
allowClear
@search="onSearch"
/>
</div>
</div>
<!-- 表格 -->
<div class="table-content">
<a-table
:row-selection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectChange,
}"
:loading="loading"
bordered
:scroll="{ y: 590 }"
:columns="columns"
:pagination="{
showTotal: (total) => `共 ${total} 条`,
current: current,
total: total,
pageSize: size,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: pageSizeOptions,
onChange: handleChange,
onShowSizeChange: showSizeChange,
}"
:data-source="tableData"
:rowKey="(record) => record.id"
>
<!-- 序号 -->
<span slot="num" slot-scope="text, record, index">{{
(current - 1) * size + index + 1
}}</span>
<!-- 操作 -->
<template slot="action" slot-scope="text">
<a-space size="middle">
<span
href="javascript:;"
class="primary pointer"
@click="handleEdit(text)"
>编辑</span
>
<span
href="javascript:;"
class="delete pointer"
@click="handleDel(text.id)"
>删除</span
>
</a-space>
</template>
</a-table>
</div>
<!-- 新增 -->
<AddDimension
ref="AddDimension"
:addVisible.sync="addVisible"
:title="title"
:dict="dict"
@addSuccess="getDimensionList"
></AddDimension>
</div>
</template>
<script>
import { getDimensionList, delDimension } from "@/services/system";
import { pageSizeOptions } from "@/config/pageConfig.js";
import AddDimension from "./modal/AddDimension";
export default {
components: { AddDimension },
data() {
const columns = [
{
title: "序号",
dataIndex: "num",
width: "65px",
scopedSlots: {
customRender: "num",
},
},
{
title: "名称",
dataIndex: "dimensionName",
},
{
title: "编码",
dataIndex: "dimensionCode",
},
{
title: "类型",
dataIndex: "dimensionType",
customRender: (text) => {
return this.dict.dimensionType[text];
},
},
{
title: "维度值",
dataIndex: "dimensionValue",
},
{
title: "创建时间",
dataIndex: "createTime",
customRender: (text) => {
return this.$moment(text).format("YYYY-MM-DD HH:mm:ss");
},
},
{
title: "操作",
width: "120px",
scopedSlots: { customRender: "action" },
},
];
return {
columns,
loading: false,
current: 1,
size: 10,
total: 0,
pageSizeOptions,
searchValue: "", // 搜索
tableData: [],
selectedRowKeys: [],
dict: {}, // 字典
addVisible: false,
title: "新增",
};
},
created() {
this.getDimensionList();
},
methods: {
// 获取列表
async getDimensionList() {
this.loading = true;
let res = await getDimensionList({
page: this.current,
size: this.size,
dimensionName: this.searchValue,
});
this.loading = false;
if (res.data.code == 1) {
let { data, total, dict } = res.data.data;
if (!data.length && this.current > 1) {
this.current -= 1;
this.getDimensionList();
}
this.tableData = data;
this.total = total;
this.dict = dict;
}
},
// 新增
handleAdd() {
this.title = "新增";
this.$refs.AddDimension.onAdd();
this.addVisible = true;
},
// 搜索
onSearch() {
this.current = 1;
},
// 分页
handleChange(num) {
this.current = num;
},
// 改变每页显示数量
showSizeChange(current, size) {
this.current = current;
this.size = size;
},
// 选择
onSelectChange(keys) {
this.selectedRowKeys = keys;
},
// 批量删除
handleDelAll() {
if (!this.selectedRowKeys.length) {
this.$message.warn("请先勾选数据");
return;
}
let ids = this.selectedRowKeys.join(",");
this.handleDel(ids);
},
// 编辑
handleEdit(row) {
this.title = "编辑";
this.$refs.AddDimension.onEdit(row);
this.addVisible = true;
},
// 删除
handleDel(id) {
let _this = this;
this.$confirm({
title: "系统提示",
content: "删除不可恢复,确定要删除吗?",
okText: "确定",
okType: "danger",
cancelText: "取消",
centered: true,
icon: "exclamation-circle",
maskClosable: true,
async onOk() {
let res = await delDimension({ id });
if (res.data.code == 1) {
_this.$message.success(res.data.msg);
_this.getDimensionList();
}
console.log(id);
},
onCancel() {
console.log("Cancel");
},
});
},
},
};
</script>
<style lang="less" scoped>
.dimension-container {
width: 100%;
height: 100%;
}
</style>
<template>
<div>
<a-modal
:title="title"
:visible="Visible"
@cancel="handleCancel"
:maskClosable="false"
>
<a-button slot="footer" @click="handleReset">重置</a-button>
<a-button
slot="footer"
type="primary"
:loading="loading"
@click="handleOk"
>确定</a-button
>
<a-form-model
:model="form"
ref="form"
:rules="rules"
:label-col="{ span: 5 }"
:wrapper-col="{ span: 19 }"
>
<a-form-model-item label="名称" prop="dimensionName">
<a-input
v-model="form.dimensionName"
placeholder="请输入维度名称"
></a-input>
</a-form-model-item>
<a-form-model-item label="编号" prop="dimensionCode">
<a-input
v-model="form.dimensionCode"
placeholder="请输入维度编号"
></a-input>
</a-form-model-item>
<a-form-model-item label="类型" prop="dimensionType">
<a-select v-model="form.dimensionType" placeholder="请选择维度类型">
<a-select-option
v-for="(v, key) in dict.dimensionType"
:key="key"
:value="Number(key)"
>{{ v }}</a-select-option
>
</a-select>
</a-form-model-item>
<a-form-model-item label="维度值" prop="dimensionValue">
<a-input
v-model="form.dimensionValue"
placeholder="请输入维度值"
></a-input>
</a-form-model-item>
</a-form-model>
</a-modal>
</div>
</template>
<script>
import { saveDimension } from "@/services/system";
export default {
components: {},
props: {
addVisible: {
required: true,
type: Boolean,
default: false,
},
title: {
required: true,
type: String,
default: "",
},
dict: {
required: true,
type: Object,
default: () => {},
},
},
data() {
return {
loading: false,
form: {
dimensionName: "", // 维度名称
dimensionCode: "", // 维度编码
dimensionValue: "", // 维度值
dimensionType: undefined, // 维度类型
},
rules: {
dimensionName: [
{ required: true, message: "请输入维度名称", trigger: "blur" },
],
dimensionCode: [
{ required: true, message: "请输入维度编码", trigger: "blur" },
],
dimensionValue: [
{ required: true, message: "请输入维度值", trigger: "blur" },
],
dimensionType: [
{ required: true, message: "请选择维度类型", trigger: "change" },
],
},
};
},
computed: {
Visible: {
get() {
return this.addVisible;
},
set(val) {
this.$emit("update:addVisible", val);
},
},
},
created() {},
methods: {
// 新增
onAdd() {
Object.assign(this.form, this.$options.data().form);
this.form.id && this.$delete(this.form, "id");
},
// 编辑
onEdit(row) {
this.$nextTick(() => {
this.form = { ...row };
});
},
// 保存
handleOk() {
this.$refs.form.validate(async (valid) => {
if (valid) {
this.loading = true;
let res = await saveDimension(this.form);
let { code, msg } = res.data;
this.loading = false;
if (code == 1) {
this.$message.success(msg);
this.$emit("addSuccess");
this.handleCancel();
}
}
});
},
// 重置
handleReset() {
this.$refs.form.resetFields();
},
// 关闭
handleCancel() {
this.$refs.form.resetFields();
this.Visible = false;
},
},
};
</script>
<style lang="less" scoped></style>
<template>
<div class="parameter">
<div class="control flex aic jcb mb15 pdr6">
<div>
<a-button type="primary" style="margin-right: 10px" @click="handleAdd"
>新增</a-button
>
<a-button type="danger" @click="handleDelAll">批量删除</a-button>
</div>
<div class="search-box">
<a-space>
<a-input
placeholder="请输入参数名搜索"
v-model="searchForm.name"
allowClear
/>
<a-button type="primary" @click="onSearch">搜索</a-button>
<a-button @click="resetSearch">重置</a-button>
</a-space>
</div>
</div>
<!-- 表格 -->
<div class="table-content">
<y-table
:columns="columns"
:data="tableData"
:pageSize.sync="size"
:page.sync="page"
:total="total"
:loading="loading"
:scroll="{ y: 560 }"
:row-selection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectChange,
}"
@changePagination="getSystemParameterList"
>
<span slot="index" slot-scope="{ index }">{{
(page - 1) * size + index + 1
}}</span>
<!-- 有效状态 -->
<template slot="validStatus" slot-scope="{ record }">
<a-tag>{{ dict.validStatus[record.validStatus] }} </a-tag>
</template>
<!-- 修改状态 -->
<template slot="modStatus" slot-scope="{ record }">
<a-tag>{{ dict.modStatus[record.modStatus] }} </a-tag>
</template>
<!-- 展现类型 -->
<template slot="displayType" slot-scope="{ record }">
<!-- {{ text.displayType || "--" }} -->
<a-tag>{{ dict.displayType[record.displayType] }} </a-tag>
</template>
<!-- 操作 -->
<template slot="action" slot-scope="{ record }">
<a-space size="middle">
<span
href="javascript:;"
class="primary pointer"
@click="handleEdit(record)"
>编辑</span
>
<span
href="javascript:;"
class="delete pointer"
@click="handleDel(record.id)"
>删除</span
>
</a-space>
</template>
</y-table>
</div>
<!-- 新增 -->
<AddParameter
ref="AddParameter"
:addVisible.sync="addVisible"
:title="title"
:dict="dict"
@addSuccess="getSystemParameterList"
></AddParameter>
</div>
</template>
<script>
import { getSystemParameterList, delSystemParameter } from "@/services/system";
import { pageSizeOptions } from "@/config/pageConfig.js";
import AddParameter from "./modal/AddParameter.vue";
import YTable from "@/components/YTable.vue";
export default {
components: {
AddParameter,
YTable,
},
data() {
const columns = [
{
title: "序号",
dataIndex: "num",
width: "65px",
scopedSlots: {
customRender: "index",
},
},
{
title: "参数名称",
dataIndex: "name",
},
{
title: "一级组织",
// dataIndex: "firstOrganize",
customRender: (text) => {
return text.firstOrganize || "--";
},
},
{
title: "二级组织",
// dataIndex: "secondOrganize",
customRender: (text) => {
return text.secondOrganize || "--";
},
},
{
title: "参数键",
dataIndex: "paramKey",
},
{
title: "参数值",
dataIndex: "paramValue",
},
{
title: "有效状态",
// dataIndex: "validStatus",
scopedSlots: {
customRender: "validStatus",
},
// customRender: (text) => {
// return this.filterItems(text.validStatus, this.dict.validStatus);
// },
},
{
title: "修改状态",
scopedSlots: {
customRender: "modStatus",
},
},
{
title: "展现类型",
scopedSlots: {
customRender: "displayType",
},
},
{
title: "备注",
// dataIndex: "remark",
customRender: (text) => {
return text.remark || "--";
},
},
{
title: "操作",
width: "120px",
scopedSlots: { customRender: "action" },
},
];
return {
columns,
loading: false,
page: 1,
size: 10,
total: 0,
pageSizeOptions,
searchValue: "", // 搜索
searchForm: {
name: "",
},
tableData: [],
selectedRowKeys: [],
dict: {}, // 字典
addVisible: false,
title: "新增",
};
},
created() {
this.getSystemParameterList();
},
methods: {
// 获取参数列表
async getSystemParameterList() {
this.loading = true;
let res = await getSystemParameterList({
page: this.page,
size: this.size,
name: `%${this.searchForm.name}%`,
});
this.loading = false;
if (res.data.code == 1) {
let { total, data, dict } = res.data.data;
this.dict = dict;
if (!data.length && this.page > 1) {
this.page -= 1;
this.getSystemParameterList();
}
this.total = total;
this.tableData = data;
}
},
// 新增
handleAdd() {
this.title = "新增";
this.$refs.AddParameter.onAdd();
this.addVisible = true;
},
// 搜索
onSearch() {
this.page = 1;
this.selectedRowKeys = [];
this.getSystemParameterList();
},
// 重置搜索
resetSearch() {
this.page = 1;
this.selectedRowKeys = [];
Object.assign(this.searchForm, this.$options.data().searchForm);
this.getSystemParameterList();
},
// 选择
onSelectChange(keys) {
this.selectedRowKeys = keys;
},
// 批量删除
handleDelAll() {
if (!this.selectedRowKeys.length) {
this.$message.warn("请先勾选数据");
return;
}
let ids = this.selectedRowKeys.join(",");
this.handleDel(ids);
},
// 编辑
handleEdit(row) {
this.title = "编辑";
this.$refs.AddParameter.onEdit(row);
this.addVisible = true;
},
// 删除
handleDel(id) {
let _this = this;
this.$confirm({
title: "系统提示",
content: "删除不可恢复,确定要删除吗?",
okText: "确定",
okType: "danger",
cancelText: "取消",
centered: true,
icon: "exclamation-circle",
maskClosable: true,
async onOk() {
let res = await delSystemParameter({ id });
let { code, msg } = res.data;
if (code == 1) {
_this.$message.success(msg);
_this.selectedRowKeys = [];
_this.getSystemParameterList();
}
},
onCancel() {
console.log("Cancel");
},
});
},
},
};
</script>
<style lang="less" scoped>
.parameter {
width: 100%;
height: 100%;
}
</style>
<template>
<div>
<a-modal
:title="title"
:visible="Visible"
@cancel="handleCancel"
:maskClosable="false"
>
<template slot="footer">
<a-space>
<a-button @click="handleReset">重置</a-button>
<a-upload
name="file"
:show-upload-list="false"
:action="api + 'base/file/commonupload'"
@change="handleUpload"
>
<a-button type="primary">文件上传</a-button>
</a-upload>
<a-button type="primary" @click="handleOk">确定</a-button>
</a-space>
</template>
<a-form-model
:model="form"
ref="form"
:rules="rules"
:label-col="{ span: 5 }"
:wrapper-col="{ span: 19 }"
>
<a-form-model-item label="参数名称" prop="name">
<a-input v-model="form.name" placeholder="请输入参数名称" />
</a-form-model-item>
<a-form-model-item label="一级组织" prop="firstOrganize">
<a-input v-model="form.firstOrganize" placeholder="请输入一级组织" />
</a-form-model-item>
<a-form-model-item label="二级组织" prop="secondOrganize">
<a-input v-model="form.secondOrganize" placeholder="请输入二级组织" />
</a-form-model-item>
<a-form-model-item label="参数键" prop="paramKey">
<a-input v-model="form.paramKey" placeholder="请输入参数键" />
</a-form-model-item>
<a-form-model-item label="参数值" prop="paramValue">
<a-input v-model="form.paramValue" placeholder="请输入参数值" />
</a-form-model-item>
<a-form-model-item label="参数修改状态" prop="modStatus">
<a-select v-model="form.modStatus" placeholder="请选择参数修改状态">
<a-select-option
v-for="(v, key) in dict.modStatus"
:key="key"
:value="Number(key)"
>{{ v }}</a-select-option
>
</a-select>
</a-form-model-item>
<a-form-model-item label="展现类型" prop="displayType">
<!-- <a-input v-model="form.displayType" placeholder="请输入排序" /> -->
<a-select v-model="form.displayType" placeholder="请选择展现类型">
<a-select-option
v-for="(v, key) in dict.displayType"
:key="key"
:value="Number(key)"
>{{ v }}</a-select-option
>
</a-select>
</a-form-model-item>
<a-form-model-item label="参数有效状态" prop="validStatus">
<a-radio-group v-model="form.validStatus">
<a-radio
v-for="(v, key) in dict.validStatus"
:value="Number(key)"
:key="key"
>{{ v }}</a-radio
>
</a-radio-group>
</a-form-model-item>
<a-form-model-item label="备注" prop="remark">
<a-textarea
:autoSize="{ minRows: 4, maxRows: 4 }"
v-model="form.remark"
placeholder="请输入备注"
allow-clear
/>
</a-form-model-item>
</a-form-model>
</a-modal>
</div>
</template>
<script>
import { saveSystemParameter } from "@/services/system";
export default {
components: {},
props: {
addVisible: {
required: true,
type: Boolean,
default: false,
},
title: {
required: true,
type: String,
default: "",
},
dict: {
required: true,
type: Object,
default: () => {
return {};
},
},
},
data() {
return {
api: process.env.VUE_APP_API_BASE_URL + "/",
form: {
name: "", // 参数名称
firstOrganize: "", // 一级组织
secondOrganize: "", // 二级组织
paramKey: "", // 参数键
paramValue: "", // 参数值
modStatus: undefined, // 参数修改状态
displayType: undefined, // 展现类型
validStatus: "", // 参数有效状态
remark: "", // 备注
},
rules: {
name: [{ required: true, message: "请输入参数名称", trigger: "blur" }],
paramKey: [
{ required: true, message: "请输入参数键", trigger: "blur" },
],
paramValue: [
{ required: true, message: "请输入参数值", trigger: "blur" },
],
},
};
},
computed: {
Visible: {
get() {
return this.addVisible;
},
set(val) {
this.$emit("update:addVisible", val);
},
},
},
methods: {
// 关闭弹窗
handleCancel() {
this.$refs.form.resetFields();
this.Visible = false;
},
// 重置
handleReset() {
this.$refs.form.resetFields();
},
// 新增
onAdd() {
Object.assign(this.form, this.$options.data().form);
this.form.id && this.$delete(this.form, "id");
},
// 编辑
onEdit(row) {
this.$nextTick(() => {
this.form = { ...row };
});
},
// 保存
handleOk() {
this.$refs.form.validate(async (valid) => {
if (valid) {
let res = await saveSystemParameter(this.form);
let { code, msg } = res.data;
if (code == 1) {
this.$message.success(msg);
this.$emit("addSuccess");
this.handleCancel();
}
}
});
},
// 文件上传
handleUpload({ file }) {
if (file.status === "done") {
let { code, url, msg } = file.response;
if (code == 1) {
this.form.paramValue = url;
} else {
this.$message.error(msg);
}
}
},
},
};
</script>
<style lang="less" scoped></style>
<template>
<div class="resource-container">
<div class="control flex aic jcb mb15 pdr6">
<a-space>
<a-button type="primary" @click="handleAdd">新增</a-button>
<a-button
v-permission="[1]"
type="primary"
class="addclass"
@click="refSresource"
>刷新资源</a-button
>
<a-button type="danger" @click="handleDelAll">批量删除</a-button>
</a-space>
<div class="search-box">
<a-input-search
placeholder="请输入资源名搜索"
enter-button="搜索"
v-model="searchValue"
allowClear
@search="onSearch"
/>
</div>
</div>
<!-- 表格 -->
<div class="table-content">
<a-table
:row-selection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectChange,
}"
:loading="loading"
bordered
:scroll="{ y: 590 }"
:columns="columns"
:pagination="{
showTotal: (total) => `共 ${total} 条`,
current: current,
total: total,
pageSize: size,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: pageSizeOptions,
onChange: handleChange,
onShowSizeChange: showSizeChange,
}"
:data-source="tableData"
:rowKey="(record) => record.id"
>
<!-- 序号 -->
<span slot="num" slot-scope="text, record, index">{{
(current - 1) * size + index + 1
}}</span>
<!-- 操作 -->
<template slot="action" slot-scope="text">
<a-space size="middle">
<span
href="javascript:;"
class="primary pointer"
@click="handleEdit(text)"
>编辑</span
>
<span
href="javascript:;"
class="delete pointer"
@click="handleDel(text.id)"
>删除</span
>
</a-space>
</template>
</a-table>
</div>
<!-- 新增、编辑 -->
<AddResurce
ref="AddResurce"
:title="title"
:visible.sync="addVisible"
:dict="dict"
@add="getResourceList"
></AddResurce>
</div>
</template>
<script>
import {
getResourceList,
refreshResource,
delResource,
} from "@/services/system";
import { pageSizeOptions } from "@/config/pageConfig.js";
import AddResurce from "./modal/AddResurce.vue";
export default {
components: { AddResurce },
data() {
const columns = [
{
title: "序号",
dataIndex: "num",
width: "65px",
scopedSlots: {
customRender: "num",
},
},
{
title: "名称",
width: 400,
dataIndex: "name",
},
{
title: "资源",
dataIndex: "url",
customRender: (text) => {
if (text) {
return text.split(",").map((v) => {
return (
<a-tag style="margin-bottom:4px" color="blue">
{v}
</a-tag>
);
});
}
},
},
{
title: "认证类型",
width: 200,
dataIndex: "authType",
customRender: (text) => {
return this.dict.authType[text];
},
},
{
title: "操作",
width: "120px",
scopedSlots: { customRender: "action" },
},
];
return {
columns,
loading: false,
current: 1,
size: 10,
total: 0,
pageSizeOptions,
searchValue: "", // 搜索
tableData: [],
selectedRowKeys: [],
dict: {}, // 字典
addVisible: false,
title: "新增",
};
},
created() {
this.getResourceList();
},
methods: {
// 获取资源列表
async getResourceList() {
this.loading = true;
let res = await getResourceList({
page: this.current,
size: this.size,
name: `%${this.searchValue}%`,
});
this.loading = false;
if (res.data.code == 1) {
let { data, total, dict } = res.data.data;
if (!data.length && this.current > 1) {
this.current -= 1;
this.getResourceList();
}
this.tableData = data;
this.total = total;
this.dict = dict;
}
},
// 新增
handleAdd() {
this.title = "新增";
this.$refs.AddResurce.onAdd();
this.addVisible = true;
},
// 搜索
onSearch() {
this.current = 1;
this.getResourceList();
},
// 分页
handleChange(num) {
this.current = num;
this.getResourceList();
},
// 改变每页显示数量
showSizeChange(current, size) {
this.current = current;
this.size = size;
this.getResourceList();
},
// 选择
onSelectChange(keys) {
this.selectedRowKeys = keys;
},
// 批量删除
handleDelAll() {
if (!this.selectedRowKeys.length) {
this.$message.warn("请先勾选数据");
return;
}
let ids = this.selectedRowKeys.join(",");
this.handleDel(ids);
},
// 编辑
handleEdit(row) {
this.title = "编辑";
this.$refs.AddResurce.onEdit(row);
this.addVisible = true;
},
// 删除
handleDel(id) {
let _this = this;
this.$confirm({
title: "系统提示",
content: "删除不可恢复,确定要删除吗?",
okText: "确定",
okType: "danger",
cancelText: "取消",
centered: true,
icon: "exclamation-circle",
maskClosable: true,
async onOk() {
let res = await delResource({ id });
if (res.data.code == 1) {
let { msg } = res.data;
_this.$message.success(msg);
_this.getResourceList();
}
},
onCancel() {
console.log("Cancel");
},
});
},
// 刷新资源
async refSresource() {
let _this = this;
this.$confirm({
title: "系统提示",
content: "确定要刷新资源吗?",
okText: "",
cancelText: "",
centered: true,
async onOk() {
let res = await refreshResource();
if (res.data.code == 1) {
_this.$message.success(res.data.msg);
_this.getResourceList();
}
},
});
},
},
};
</script>
<style lang="less" scoped>
.resource-container {
width: 100%;
height: 100%;
}
</style>
<template>
<div class="add-resurce">
<a-modal
:title="title"
:centered="true"
:visible="Visible"
@cancel="handleCancel"
width="30%"
:maskClosable="false"
>
<a-form-model
:label-col="{
span: 5,
}"
:wrapper-col="{
span: 19,
}"
ref="form"
:model="form"
:rules="rules"
>
<a-form-model-item label="资源名称" prop="name">
<a-input
placeholder="请输入资源名称"
allowClear
v-model="form.name"
/>
</a-form-model-item>
<a-form-model-item label="权限类型" prop="authType">
<a-select v-model="form.authType" placeholder="请选择权限类型">
<a-select-option
v-for="(v, key) in dict.authType"
:key="key"
:value="Number(key)"
>{{ v }}</a-select-option
>
</a-select>
</a-form-model-item>
<a-form-model-item class="url-params-box" label="链接地址">
<a-form-model-item
class="url-params"
v-for="(v, i) in form.urls"
:key="i"
:prop="`urls.${i}.value`"
:rules="[
{ required: true, validator: validatorUrl, trigger: 'blur' },
]"
>
<a-input
class="mr10"
v-model="v.value"
placeholder="请输入链接地址"
/>
<a-space>
<a-button type="primary" @click="changeParams(i, 'add')"
><a-icon type="plus"
/></a-button>
<a-button
type="danger"
v-if="i > 0"
@click="changeParams(i, 'remove')"
><a-icon type="minus"
/></a-button>
</a-space>
</a-form-model-item>
</a-form-model-item>
</a-form-model>
<template slot="footer">
<a-button @click="resetForm">重置</a-button>
<a-button
type="primary"
class="addclass"
:loading="loading"
@click="subForm"
>确定</a-button
>
</template>
</a-modal>
</div>
</template>
<script>
import { saveResource } from "@/services/system";
export default {
props: {
title: {
required: true,
type: String,
default: "新增资源",
},
visible: {
required: true,
type: Boolean,
default: false,
},
dict: {
required: true,
type: Object,
default: () => {},
},
},
data() {
return {
loading: false,
form: {
name: "",
authType: undefined,
url: "",
urls: [
{
value: "",
},
],
},
rules: {
name: [{ required: true, message: "请输入资源名称", trigger: "blur" }],
authType: [
{ required: true, message: "请输选择权限类型", trigger: "change" },
],
},
};
},
computed: {
Visible: {
get() {
return this.visible;
},
set(val) {
this.$emit("update:visible", val);
},
},
},
methods: {
onAdd() {
Object.assign(this.form, this.$options.data().form);
this.form.id && this.$delete(this.form, "id");
},
onEdit(row) {
setTimeout(() => {
this.form = { ...row };
let arr = [];
if (this.form.url) {
arr = this.form.url.split(",").map((v) => {
return {
value: v,
};
});
}
this.$set(this.form, "urls", arr);
}, 10);
},
subForm() {
this.$refs.form.validate(async (valid) => {
if (valid) {
this.loading = true;
let res = await saveResource({
...this.form,
url: this.form.urls.map((v) => v.value).join(","),
});
let { code, msg } = res.data;
this.loading = false;
if (code == 1) {
this.$message.success(msg);
this.$emit("add");
this.handleCancel();
}
}
});
},
// 判断是否存在链接
isRepeat(val) {
return this.form.urls.filter((v) => v.value == val).length > 1;
},
// 校验链接地址
validatorUrl(rule, value, callback) {
if (!value) {
callback(new Error("请输入链接"));
} else if (this.isRepeat(value)) {
callback(new Error("重复的链接地址"));
} else {
callback();
}
},
changeParams(index, type) {
if (type == "add") {
let obj = {
value: "",
};
if (this.form.urls.some((v) => !v.value)) {
this.$message.warning("请先完成前面地址的填写");
return;
}
this.form.urls.splice(index + 1, 0, obj);
} else {
this.form.urls.splice(index, 1);
}
// this.$forceUpdate();
},
resetForm() {
// 重置还原表单信息内容
this.$refs.form.resetFields();
this.$set(this.form, "urls", [{ value: "" }]);
},
handleCancel() {
this.resetForm();
this.Visible = false;
},
},
};
</script>
<style lang="less" scoped>
/deep/.ant-modal-body {
max-height: 600px;
overflow-y: auto;
}
/deep/.url-params-box {
display: block !important;
.ant-form-item-children {
display: block;
}
}
/deep/.url-params {
.ant-form-item-children {
display: flex;
align-items: center;
}
}
</style>
<template>
<div class="role-container">
<div class="control flex aic jcb mb15 pdr6">
<div>
<a-button type="primary" style="margin-right: 10px" @click="handleAdd"
>新增</a-button
>
<a-button type="danger" @click="handleDelAll">批量删除</a-button>
</div>
<div class="search-box">
<a-input-search
placeholder="请输入角色名搜索"
enter-button="搜索"
v-model="searchValue"
allowClear
@search="onSearch"
/>
</div>
</div>
<!-- 表格 -->
<div class="table-content">
<a-table
:row-selection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectChange,
}"
:loading="loading"
bordered
:scroll="{ y: 590 }"
:columns="columns"
:pagination="{
showTotal: (total) => `共 ${total} 条`,
current: current,
total: total,
pageSize: size,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: pageSizeOptions,
onChange: handleChange,
onShowSizeChange: showSizeChange,
}"
:data-source="tableData"
:rowKey="(record) => record.id"
>
<!-- 序号 -->
<span slot="num" slot-scope="text, record, index">{{
(current - 1) * size + index + 1
}}</span>
<!-- 操作 -->
<template slot="action" slot-scope="text">
<a-space size="middle">
<span class="primary pointer" @click="apportion(text)"
>分配资源</span
>
<span class="primary pointer" @click="handleResDim(text)"
>资源规则</span
>
<span class="primary pointer" @click="handleEdit(text)">编辑</span>
<span class="delete pointer" @click="handleDel(text.id)">删除</span>
</a-space>
</template>
</a-table>
</div>
<!-- 新增 -->
<AddRole
ref="AddRole"
:title="title"
:addVisible.sync="addVisible"
@addSuccess="getRoleList"
></AddRole>
<!-- 分配资源 -->
<ApportionRes ref="ApportionRes" :visible.sync="resVisible"></ApportionRes>
<!-- 资源规则 -->
<ResDimList ref="ResDimList" :visible.sync="resDimListVisible"></ResDimList>
</div>
</template>
<script>
import { getRoleList, delRole } from "@/services/system";
import { pageSizeOptions } from "@/config/pageConfig.js";
import AddRole from "./modal/AddRole.vue";
import ApportionRes from "./modal/ApportionRes.vue";
import ResDimList from "./modal/ResDimList.vue";
export default {
components: { AddRole, ApportionRes, ResDimList },
data() {
const columns = [
{
title: "序号",
dataIndex: "num",
width: "65px",
scopedSlots: {
customRender: "num",
},
},
{
title: "角色名称",
dataIndex: "name",
},
{
title: "备注",
dataIndex: "remark",
},
{
title: "操作",
width: "20% ",
scopedSlots: { customRender: "action" },
},
];
return {
columns,
loading: false,
current: 1,
size: 10,
total: 0,
pageSizeOptions,
searchValue: "", // 搜索
tableData: [],
selectedRowKeys: [],
dict: {}, // 字典
addVisible: false,
resVisible: false,
resDimListVisible: false,
title: "新增角色",
};
},
created() {
this.getRoleList();
},
methods: {
// 获取角色列表
async getRoleList() {
this.loading = true;
let res = await getRoleList({
current: this.current,
size: this.size,
name: this.searchValue,
});
this.loading = false;
if (res.data.code == 1) {
let { data, total } = res.data.data;
if (!data.length && this.current > 1) {
this.current -= 1;
this.getRoleList();
}
this.tableData = data;
this.total = total;
}
},
// 新增
handleAdd() {
this.title = "新增角色";
this.$refs.AddRole.onAdd();
this.addVisible = true;
},
// 搜索
onSearch() {
this.current = 1;
this.getRoleList();
},
// 分页
handleChange(num) {
this.current = num;
this.getRoleList();
},
// 改变每页显示数量
showSizeChange(current, size) {
this.current = current;
this.size = size;
this.getRoleList();
},
// 选择
onSelectChange(keys) {
this.selectedRowKeys = keys;
},
// 批量删除
handleDelAll() {
if (!this.selectedRowKeys.length) {
this.$message.warn("请先勾选数据");
return;
}
let ids = this.selectedRowKeys.join(",");
this.handleDel(ids);
},
// 编辑
handleEdit(row) {
this.title = "编辑角色";
this.$refs.AddRole.onEdit(row);
this.addVisible = true;
},
// 删除
handleDel(id) {
let _this = this;
this.$confirm({
title: "系统提示",
content: "删除不可恢复,确定要删除吗?",
okText: "确定",
okType: "danger",
cancelText: "取消",
centered: true,
icon: "exclamation-circle",
maskClosable: true,
async onOk() {
let res = await delRole({ id });
if (res.data.code == 1) {
_this.$message.success(res.data.msg);
_this.getRoleList();
}
},
onCancel() {
console.log("Cancel");
},
});
},
// 分配资源
apportion(row) {
this.$refs.ApportionRes.onAdd(row.id);
this.resVisible = true;
},
// 资源维度
handleResDim(row) {
this.$refs.ResDimList.getRoleInfo(row);
this.resDimListVisible = true;
},
},
};
</script>
<style lang="less" scoped>
.role-container {
width: 100%;
height: 100%;
}
</style>
<template>
<div>
<a-modal
:title="title"
:visible="Visible"
@cancel="handleCancel"
:maskClosable="false"
:zIndex="1001"
>
<a-form-model
:model="form"
ref="form"
:rules="rules"
:label-col="{ span: 5 }"
:wrapper-col="{ span: 19 }"
>
<a-form-model-item label="所属资源" prop="resourceId">
<a-cascader
:options="resourceList"
v-model="resource"
placeholder="请选择资源"
@change="changeRes"
/>
</a-form-model-item>
<a-form-model-item label="所属维度" prop="ruleCode">
<a-select
allowClear
v-model="form.ruleCode"
@change="changeDim"
placeholder="请选择所属维度"
>
<a-select-option
v-for="v in dimensionList"
:key="v.id"
:value="v.dimensionCode"
:dataset-row="v"
>
{{ v.dimensionName }}
</a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item label="规则条件" prop="ruleCondition">
<a-select
allowClear
v-model="form.ruleCondition"
placeholder="请选择规则条件"
>
<a-select-option
v-for="(v, key) in dict.ruleCondition"
:key="key"
:value="key"
>
{{ v }}
</a-select-option>
</a-select>
</a-form-model-item>
</a-form-model>
<a-button slot="footer" @click="handleReset">重置</a-button>
<a-button
slot="footer"
type="primary"
:loading="loading"
@click="handleOk"
>确定</a-button
>
</a-modal>
</div>
</template>
<script>
import {
getDimensionList,
getResourceList,
saveDimRes,
} from "@/services/system";
export default {
components: {},
props: {
addVisible: {
required: true,
type: Boolean,
default: false,
},
title: {
required: true,
type: String,
default: "",
},
dict: {
required: true,
type: Object,
default: () => {},
},
},
data() {
return {
loading: false,
resource: [],
dimensionList: [], // 维度列表
resourceList: [], // 资源列表
form: {
roleId: "", // 角色id
resourceId: "", // 资源id
ruleCode: undefined, // 维度编码
ruleName: "", // 维度名称
ruleCondition: undefined, // 规则条件
ruleValue: "", // 维度值
ruleType: "", // 维度类型
roleName: "", // 角色名称
resourceName: "", // 资源名称
},
rules: {
resourceId: [
{ required: true, message: "请选择资源", trigger: "change" },
],
ruleCode: [
{ required: true, message: "请选择维度", trigger: "change" },
],
ruleCondition: [
{ required: true, message: "请选择规则条件", trigger: "change" },
],
},
};
},
computed: {
Visible: {
get() {
return this.addVisible;
},
set(val) {
this.$emit("update:addVisible", val);
},
},
},
created() {
this.getDimensionList();
this.getResourceList();
},
methods: {
// 获取维度列表
async getDimensionList() {
let res = await getDimensionList({
page: 1,
size: -1,
});
if (res.data.code == 1) {
let { data } = res.data.data;
this.dimensionList = data;
}
},
// 获取资源列表
async getResourceList() {
let res = await getResourceList({
page: 1,
size: -1,
});
if (res.data.code == 1) {
let { data } = res.data.data;
this.resourceList = this.groupByAuth(data);
}
},
// 资源分组
groupByAuth(list) {
let group = {};
let groupList = [];
list.forEach((item) => {
let name = item.name.split("-")[0];
if (!group[name]) {
group[name] = {
indeterminate: false,
checkAll: false,
list: [],
};
}
group[name].list.push(item);
});
groupList = Object.keys(group).map((key) => {
return {
label: key,
value: key,
children: group[key].list.map((v) => {
return {
label: v.name,
value: v.id,
};
}),
};
});
return groupList;
},
// 选择资源
changeRes(val, selectedOptions) {
if (selectedOptions.length) {
this.form.resourceId = selectedOptions[1].value;
this.form.resourceName = selectedOptions[1].label;
} else {
this.form.resourceId = "";
this.form.resourceName = "";
}
},
// 选择维度
changeDim(val, e) {
if (val && e) {
let { dimensionName, dimensionType, dimensionValue } = e.data.attrs[
"dataset-row"
];
this.form.ruleName = dimensionName;
this.form.ruleType = dimensionType;
this.form.ruleValue = dimensionValue;
} else {
this.form.ruleName = "";
this.form.ruleType = "";
this.form.ruleValue = "";
}
},
// 新增
onAdd(roleInfo) {
Object.assign(this.form, this.$options.data().form);
this.form.id && this.$delete(this.form, "id");
this.form.roleId = roleInfo.id;
this.form.roleName = roleInfo.name;
},
// 编辑
onEdit(row) {
this.$nextTick(() => {
this.form = { ...row };
let resName = this.form.resourceName.split("-")[0];
this.resource = [resName, this.form.resourceId];
});
},
// 保存
handleOk() {
this.$refs.form.validate(async (valid) => {
if (valid) {
this.loading = true;
let res = await saveDimRes(this.form);
let { code, msg } = res.data;
this.loading = false;
if (code == 1) {
this.$message.success(msg);
this.$emit("addSuccess");
this.handleCancel();
}
}
});
},
// 重置
handleReset() {
this.$refs.form.resetFields();
this.form.ruleName = "";
this.form.ruleType = "";
this.form.ruleValue = "";
this.form.resourceId = "";
this.form.resourceName = "";
this.resource = [];
},
// 关闭
handleCancel() {
this.handleReset();
this.Visible = false;
},
},
};
</script>
<style lang="less" scoped></style>
<template>
<div>
<a-modal
:title="title"
:visible="Visible"
@cancel="handleCancel"
:maskClosable="false"
>
<a-button slot="footer" @click="handleReset">重置</a-button>
<a-button
slot="footer"
type="primary"
:loading="loading"
@click="handleOk"
>确定</a-button
>
<a-form-model
:model="form"
ref="form"
:rules="rules"
:label-col="{ span: 5 }"
:wrapper-col="{ span: 19 }"
>
<a-form-model-item label="名称" prop="name">
<a-input v-model="form.name" placeholder="请输入角色名称"></a-input>
</a-form-model-item>
<a-form-model-item label="备注" prop="remark">
<a-textarea
v-model="form.remark"
placeholder="请输入备注"
></a-textarea>
</a-form-model-item>
</a-form-model>
</a-modal>
</div>
</template>
<script>
import { saveRole } from "@/services/system";
export default {
components: {},
props: {
addVisible: {
required: true,
type: Boolean,
default: false,
},
title: {
required: true,
type: String,
default: "",
},
},
data() {
return {
loading: false,
form: {
name: "",
remark: "",
roleType: 2,
},
rules: {
name: [{ required: true, message: "请输入角色名称", trigger: "blur" }],
},
};
},
computed: {
Visible: {
get() {
return this.addVisible;
},
set(val) {
this.$emit("update:addVisible", val);
},
},
},
created() {},
methods: {
// 新增
onAdd() {
Object.assign(this.form, this.$options.data().form);
this.form.id && this.$delete(this.form, "id");
},
// 编辑
onEdit(row) {
this.$nextTick(() => {
this.form = { ...row };
});
},
// 保存
handleOk() {
this.$refs.form.validate(async (valid) => {
if (valid) {
this.loading = true;
let res = await saveRole(this.form);
let { code, msg } = res.data;
this.loading = false;
if (code == 1) {
this.$message.success(msg);
this.$emit("addSuccess");
this.handleCancel();
}
}
});
},
// 重置
handleReset() {
this.$refs.form.resetFields();
},
// 关闭
handleCancel() {
this.$refs.form.resetFields();
this.Visible = false;
},
},
};
</script>
<style lang="less" scoped></style>
<template>
<div class="apportion-res">
<a-modal
title="分配资源"
:centered="true"
:visible="Visible"
@cancel="handleCancel"
width="40%"
:maskClosable="false"
>
<div class="mb10" v-for="(v, key) in resourceList" :key="key">
<div class="mb10" :style="{ borderBottom: '1px solid #E9E9E9' }">
<span class="title">{{ key }}</span>
<a-checkbox
:indeterminate="v.indeterminate"
:checked="v.checkAll"
@change="onCheckAllChange($event, v)"
>
全选
</a-checkbox>
</div>
<a-checkbox-group
style="width:100%"
:value="form.resourceIdList"
@change="onChange($event, v)"
>
<a-row>
<a-col :span="12" v-for="item in v.list" :key="item.id">
<a-checkbox :value="item.id">
{{ item.name }}
</a-checkbox>
</a-col>
</a-row>
</a-checkbox-group>
</div>
<template slot="footer">
<a-button @click="resetForm">重置</a-button>
<a-button type="primary" class="addclass" @click="subForm"
>确定</a-button
>
</template>
</a-modal>
</div>
</template>
<script>
import {
getRoleResourceList,
getResourceList,
saveRoleResource,
} from "@/services/system";
export default {
props: {
visible: {
required: true,
type: Boolean,
default: false,
},
},
data() {
return {
form: {
resourceIdList: [],
roleId: "",
},
rules: {},
resourceList: {}, // 资源列表
userResourceList: [], // 用户资源列表
};
},
computed: {
Visible: {
get() {
return this.visible;
},
set(val) {
this.$emit("update:visible", val);
},
},
},
methods: {
// 获取资源列表
async getResourceList() {
let res = await getResourceList({
page: 1,
size: -1,
});
if (res.data.code == 1) {
let { data } = res.data.data;
this.resourceList = this.groupByAuth(data);
}
},
// 获取角色资源权限列表
async getRoleResourceList(roleId) {
let res = await getRoleResourceList({
size: -1,
page: 1,
roleId,
});
if (res.data.code == 1) {
let { data } = res.data.data;
let arr = data.filter((v) => v.resourceId);
this.form.resourceIdList = arr.map((v) => v.resourceId);
}
},
// 权限分组
groupByAuth(list) {
let group = {};
list.forEach((item) => {
let name = item.name.split("-")[0];
if (!group[name]) {
group[name] = {
indeterminate: false,
checkAll: false,
list: [],
};
}
group[name].list.push(item);
});
return group;
},
// 控制全选
onCheckAllChange(e, row) {
let rowIds = row.list.map((v) => v.id);
let checked = e.target.checked;
row.indeterminate = false;
row.checkAll = checked;
if (checked) {
this.form.resourceIdList = [
...new Set([...this.form.resourceIdList, ...rowIds]),
];
} else {
this.form.resourceIdList = this.form.resourceIdList.filter((v) => {
return !rowIds.includes(v);
});
}
},
// 控制单选
onChange(checkedList, row) {
let rowIds = row.list.map((v) => v.id);
this.form.resourceIdList = this.form.resourceIdList.filter((v) => {
return !rowIds.includes(v);
});
this.form.resourceIdList = [
...new Set([...this.form.resourceIdList, ...checkedList]),
];
row.indeterminate =
!!checkedList.length && checkedList.length < rowIds.length;
row.checkAll = checkedList.length === rowIds.length;
},
onAdd(roleId) {
Object.assign(this.form, this.$options.data().form);
this.form.roleId = roleId;
this.getResourceList();
this.getRoleResourceList(roleId);
},
async subForm() {
let res = await saveRoleResource(this.form);
if (res.data.code == 1) {
this.$message.success("添加成功");
this.handleCancel();
}
},
resetForm() {
this.form.resourceIdList = [];
Object.keys(this.resourceList).forEach((key) => {
this.resourceList[key].checkAll = false;
this.resourceList[key].indeterminate = false;
});
// 重置还原表单信息内容
// this.$refs.form.resetFields();
},
handleCancel() {
this.resetForm();
this.Visible = false;
},
},
};
</script>
<style lang="less" scoped>
/deep/.ant-modal-body {
max-height: 700px;
overflow-y: auto;
}
.title {
margin-right: 1em;
font-size: 18px;
font-weight: bold;
}
</style>
<template>
<div>
<a-drawer
title="资源规则"
:visible="Visible"
@close="onClose"
:maskClosable="false"
:destroyOnClose="true"
width="50%"
>
<div class="mb10">
角色名称:<span class="primary">{{ roleInfo.name }}</span>
</div>
<div class="search-box flex aic jcb mb20">
<div>
<a-space>
<a-button type="primary" @click="handleAdd"> 新增 </a-button>
<a-button type="danger" @click="handleDelAll"> 批量删除 </a-button>
</a-space>
</div>
<a-input-search
style="width: 300px"
placeholder="请输入维度名称搜索"
enter-button="搜索"
v-model="searchVal"
allowClear
@search="onSearch"
/>
</div>
<!-- 表格 -->
<div class="table-content">
<a-table
:row-selection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectChange,
}"
size="small"
:loading="loading"
bordered
:scroll="{ y: 460 }"
:columns="columns"
:pagination="{
showTotal: (total) => `共 ${total} 条`,
current: current,
total: total,
pageSize: size,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: pageSizeOptions,
onChange: handleChange,
onShowSizeChange: showSizeChange,
}"
:data-source="tableData"
:rowKey="(record) => record.id"
>
<!-- 序号 -->
<span slot="num" slot-scope="text, record, index">{{
(current - 1) * size + index + 1
}}</span>
<!-- 操作 -->
<template slot="action" slot-scope="text">
<a-space>
<a href="javascript:;" class="edit" @click="handleEdit(text)"
>编辑</a
>
<a href="javascript:;" class="delete" @click="handleDel(text.id)"
>删除</a
>
</a-space>
</template>
</a-table>
</div>
<AddResDim
ref="AddResDim"
:addVisible.sync="addVisible"
:title="title"
:dict="dict"
@addSuccess="getDimResList"
></AddResDim>
</a-drawer>
</div>
</template>
<script>
import { pageSizeOptions } from "@/config/pageConfig.js";
import { getDimResList, delDimRes } from "@/services/system";
import AddResDim from "./AddResDim.vue";
export default {
props: {
visible: {
type: Boolean,
require: true,
default: false,
},
},
components: { AddResDim },
data() {
const columns = [
{
title: "序号",
dataIndex: "num",
width: "65px",
scopedSlots: {
customRender: "num",
},
},
{
title: "维度名称",
dataIndex: "ruleName",
},
{
title: "维度编码",
dataIndex: "ruleCode",
},
{
title: "维度类型",
dataIndex: "ruleType",
},
{
title: "维度值",
dataIndex: "ruleValue",
},
{
title: "所属资源",
dataIndex: "resourceName",
},
{
title: "规则条件",
dataIndex: "ruleCondition",
customRender: (text) => {
return this.dict.ruleCondition[text];
},
},
{
title: "创建时间",
dataIndex: "createTime",
customRender: (text) => {
return this.$moment(text).format("YYYY-MM-DD HH:mm:ss");
},
},
{
title: "操作",
width: "100px",
scopedSlots: { customRender: "action" },
},
];
return {
columns,
roleInfo: {}, // 模块信息
loading: false,
total: 0,
size: 10,
current: 1,
pageSizeOptions,
selectedRowKeys: [],
tableData: [],
addVisible: false,
title: "新增",
searchVal: "",
dict: {}, // 字典
};
},
computed: {
Visible: {
get() {
return this.visible;
},
set(val) {
this.$emit("update:visible", val);
},
},
},
methods: {
// 获取模块信息
getRoleInfo(roleInfo) {
this.roleInfo = roleInfo;
this.getDimResList();
},
// 获取列表
async getDimResList() {
this.loading = true;
let res = await getDimResList({
current: this.current,
size: this.size,
roleId: this.roleInfo.id,
ruleName: `%${this.searchVal}%`,
});
this.loading = false;
if (res.data.code == 1) {
let { data, total, dict } = res.data.data;
if (!data.length && this.current > 1) {
this.current -= 1;
this.getDimResList();
}
this.total = total;
this.tableData = data;
this.dict = dict;
}
},
handleAdd() {
this.title = "新增";
this.addVisible = true;
this.$refs.AddResDim.onAdd(this.roleInfo);
},
handleDelAll() {
if (!this.selectedRowKeys.length) {
this.$message.warning("请先勾选数据");
return;
}
let ids = this.selectedRowKeys.join(",");
this.handleDel(ids);
},
// 关闭抽屉
onClose() {
this.searchVal = "";
this.selectedRowKeys = [];
this.Visible = false;
},
// 搜索
onSearch() {
this.current = 1;
this.getDimResList();
},
// 编辑
handleEdit(row) {
this.title = "编辑";
this.addVisible = true;
this.$refs.AddResDim.onEdit(row);
},
// 翻页
handleChange(cur) {
this.current = cur;
this.getDimResList();
},
// 改变每页显示数量
showSizeChange(current, size) {
this.current = current;
this.size = size;
this.getDimResList();
},
// 删除
handleDel(id) {
let _this = this;
this.$confirm({
title: "系统提示",
content: "删除不可恢复,确定要删除吗?",
okText: "确定",
okType: "danger",
cancelText: "取消",
centered: true,
icon: "exclamation-circle",
maskClosable: true,
async onOk() {
let res = await delDimRes({ id });
if (res.data.code == 1) {
_this.$message.success(res.data.msg);
_this.getDimResList();
}
},
});
},
// 选中
onSelectChange(keys) {
this.selectedRowKeys = keys;
},
},
};
</script>
<style lang="less" scoped></style>
<template>
<!-- 系统日志 -->
<div class="system-logs">
<div class="control pdr6">
<div class="search-box">
<a-input-search
placeholder="请输入请求地址搜索"
enter-button="搜索"
v-model="searchValue"
allowClear
@search="onSearch"
/>
</div>
</div>
<!-- 表格 -->
<div class="table-content">
<y-table
:columns="columns"
:data="tableData"
:pageSize.sync="size"
:page.sync="page"
:total="total"
:loading="loading"
:scroll="{ y: 560 }"
@changePagination="getSystemLogsList"
>
<span slot="index" slot-scope="{ index }">{{
(page - 1) * size + index + 1
}}</span>
<!-- 操作时间 -->
<template slot="logDate" slot-scope="{ record }">
{{ record.logDate | dateFormat }}
</template>
</y-table>
</div>
</div>
</template>
<script>
import { getSystemLogsList } from "@/services/system";
import { pageSizeOptions } from "@/config/pageConfig.js";
import YTable from "@/components/YTable.vue";
const columns = [
{
title: "序号",
width: "65px",
scopedSlots: {
customRender: "index",
},
},
{
title: "用户名称",
dataIndex: "userName",
},
{
title: "登录名称",
dataIndex: "loginName",
},
{
title: "请求地址",
dataIndex: "requestUrl",
},
{
title: "操作内容",
dataIndex: "content",
},
{
title: "操作IP地址",
dataIndex: "ip",
},
{
title: "操作时间",
scopedSlots: {
customRender: "logDate",
},
},
];
export default {
components: {
YTable,
},
data() {
return {
columns,
loading: false,
current: 1,
size: 10,
total: 0,
pageSizeOptions,
searchValue: "", // 搜索
tableData: [],
};
},
created() {
this.getSystemLogsList();
},
methods: {
// 获取日志列表
async getSystemLogsList() {
this.loading = true;
let res = await getSystemLogsList({
page: this.current,
size: this.size,
requestUrl: this.searchValue,
});
this.loading = false;
if (res.data.code == 1) {
let { data, total } = res.data.data;
this.tableData = data;
this.total = total;
}
},
// 搜索
onSearch() {
this.current = 1;
this.getSystemLogsList();
},
},
};
</script>
<style lang="less" scoped>
.system-logs {
width: 100%;
height: 100%;
.control {
display: flex;
justify-content: flex-end;
margin-bottom: 15px;
}
}
</style>
<template>
<div class="task-set">
<div class="control flex aic jcb mb15 pdr6">
<div>
<a-button type="primary" style="margin-right: 10px" @click="handleAdd"
>新增</a-button
>
<a-button type="danger" @click="handleDelAll">批量删除</a-button>
</div>
<div class="search-box">
<a-input-search
placeholder="请输入任务名搜索"
enter-button="搜索"
v-model="searchValue"
allowClear
@search="onSearch"
/>
</div>
</div>
<!-- 表格 -->
<div class="table-content">
<y-table
:columns="columns"
:data="tableData"
:pageSize.sync="size"
:page.sync="page"
:total="total"
:loading="loading"
:scroll="{ y: 560 }"
:row-selection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectChange,
}"
@changePagination="getSystemTaskList"
>
<span slot="index" slot-scope="{ index }">{{
(page - 1) * size + index + 1
}}</span>
<!-- 执行策略 -->
<template slot="excuteStrategy" slot-scope="{ record }">
<a-tag>{{ dict.excuteStrategy[record.excuteStrategy] }} </a-tag>
</template>
<!-- 最后执行时间 -->
<template slot="lastExcuteTime" slot-scope="{ record }">
{{ record.lastExcuteTime | dateFormat }}
</template>
<!-- 任务状态 -->
<template slot="status" slot-scope="{ record }">
<a-tag>{{ dict.status[record.status] }} </a-tag>
</template>
<!-- 操作 -->
<template slot="action" slot-scope="{ record }">
<a-space size="middle">
<span
href="javascript:;"
class="primary pointer"
@click="handleEdit(record)"
>编辑</span
>
<span
href="javascript:;"
class="delete pointer"
@click="handleDel(record.id)"
>删除</span
>
</a-space>
</template>
</y-table>
</div>
<!-- 新增 -->
<AddTask
ref="AddTask"
:addVisible.sync="addVisible"
:title="title"
:dict="dict"
@addSuccess="getSystemTaskList"
></AddTask>
</div>
</template>
<script>
import { getSystemTaskList, delSystemTask } from "@/services/system";
import { pageSizeOptions } from "@/config/pageConfig.js";
import AddTask from "./modal/AddTask.vue";
import YTable from "@/components/YTable.vue";
export default {
components: {
AddTask,
YTable,
},
data() {
const columns = [
{
title: "序号",
width: "65px",
scopedSlots: {
customRender: "index",
},
},
{
title: "任务名称",
dataIndex: "name",
},
{
title: "执行主机",
customRender: (text) => {
return text.excuteHost || "--";
},
},
{
title: "执行关键字",
customRender: (text) => {
return text.taskKey || "--";
},
},
{
title: "执行策略",
scopedSlots: {
customRender: "excuteStrategy",
},
},
{
title: "最后执行主机",
customRender: (text) => {
return text.lastExcuteHost || "--";
},
},
{
title: "最后执行时间",
scopedSlots: {
customRender: "lastExcuteTime",
},
},
{
title: "任务状态",
scopedSlots: {
customRender: "status",
},
},
{
title: "操作",
width: "120px",
scopedSlots: { customRender: "action" },
},
];
return {
columns,
loading: false,
page: 1,
size: 10,
total: 0,
pageSizeOptions,
searchValue: "", // 搜索
tableData: [],
selectedRowKeys: [],
dict: {}, // 字典
addVisible: false,
title: "新增",
};
},
created() {
this.getSystemTaskList();
},
methods: {
// 获取参数列表
async getSystemTaskList() {
this.loading = true;
let res = await getSystemTaskList({
page: this.page,
size: this.size,
name: `%${this.searchValue}%`,
});
this.loading = false;
if (res.data.code == 1) {
let { total, data, dict } = res.data.data;
this.dict = dict;
if (!data.length && this.page > 1) {
this.page -= 1;
this.getSystemTaskList();
}
this.total = total;
this.tableData = data;
}
},
// 新增
handleAdd() {
this.title = "新增";
this.$refs.AddTask.onAdd();
this.addVisible = true;
},
// 搜索
onSearch() {
this.page = 1;
this.selectedRowKeys = [];
this.getSystemTaskList();
},
// 选择
onSelectChange(keys) {
this.selectedRowKeys = keys;
},
// 批量删除
handleDelAll() {
if (!this.selectedRowKeys.length) {
this.$message.warn("请先勾选数据");
return;
}
let ids = this.selectedRowKeys.join(",");
this.handleDel(ids);
},
// 编辑
handleEdit(row) {
console.log(row);
this.title = "编辑";
this.$refs.AddTask.onEdit(row);
this.addVisible = true;
},
// 删除
handleDel(id) {
let _this = this;
this.$confirm({
title: "系统提示",
content: "删除不可恢复,确定要删除吗?",
okText: "确定",
okType: "danger",
cancelText: "取消",
centered: true,
icon: "exclamation-circle",
maskClosable: true,
async onOk() {
let res = await delSystemTask({ id });
let { code, msg } = res.data;
if (code == 1) {
_this.$message.success(msg);
_this.selectedRowKeys = [];
_this.getSystemTaskList();
}
},
onCancel() {
console.log("Cancel");
},
});
},
},
};
</script>
<style lang="less" scoped>
.task-set {
width: 100%;
height: 100%;
}
</style>
<template>
<div>
<a-modal
:title="title"
:visible="Visible"
@cancel="handleCancel"
:maskClosable="false"
>
<a-button slot="footer" @click="handleReset">重置</a-button>
<a-button slot="footer" type="primary" @click="handleOk">确定</a-button>
<a-form-model
:model="form"
ref="form"
:rules="rules"
:label-col="{ span: 5 }"
:wrapper-col="{ span: 19 }"
>
<a-form-model-item label="任务名称" prop="name">
<a-input v-model="form.name" placeholder="请输入参数名称" />
</a-form-model-item>
<a-form-model-item label="关键字" prop="taskKey">
<a-input v-model="form.taskKey" placeholder="请输入关键字" />
</a-form-model-item>
<a-form-model-item label="执行服务" prop="excuteService">
<a-input v-model="form.excuteService" placeholder="请输入执行服务" />
</a-form-model-item>
<a-form-model-item label="执行策略" prop="excuteStrategy">
<a-select
v-model="form.excuteStrategy"
@change="changeExcuteStrategy"
placeholder="请选择执行策略"
>
<a-select-option
v-for="(v, key) in dict.excuteStrategy"
:key="key"
:value="Number(key)"
>{{ v }}</a-select-option
>
</a-select>
</a-form-model-item>
<a-form-model-item
label="执行日期"
v-if="form.excuteStrategy != 4"
prop="excuteDate"
>
<a-input
v-if="form.excuteStrategy == 1"
disabled
value="每天"
placeholder="请输入执行日期"
/>
<a-select
placeholder="请选择执行日期"
v-model.number="form.excuteDate"
v-else-if="form.excuteStrategy == 2"
>
<a-select-option
v-for="(v, key) in weeks"
:key="key"
:value="Number(key)"
>
{{ v }}
</a-select-option>
</a-select>
<a-select
placeholder="请选择执行日期"
v-else-if="form.excuteStrategy == 3"
v-model="form.excuteDate"
>
<a-select-option
v-for="(v, key) in days"
:key="key"
:value="Number(key)"
>
{{ v }}
</a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item label="执行间隔时间" prop="excuteDate" v-else>
<a-input
placeholder="执行间隔时间"
v-model.number="form.excuteDate"
suffix="秒"
/>
</a-form-model-item>
<a-form-model-item
label="执行时间"
v-if="form.excuteStrategy != 4"
prop="excuteTime"
>
<a-time-picker
valueFormat="HH:mm"
format="HH:mm"
v-model="form.excuteTime"
/>
</a-form-model-item>
<a-form-model-item label="执行主机" prop="excuteHost">
<a-input v-model="form.excuteHost" placeholder="请输入执行主机" />
</a-form-model-item>
<a-form-model-item label="执行参数" prop="excuteParam">
<a-input v-model="form.excuteParam" placeholder="请输入执行参数" />
</a-form-model-item>
<a-form-model-item label="备注" prop="remark">
<a-textarea
:autoSize="{ minRows: 4, maxRows: 4 }"
v-model="form.remark"
placeholder="请输入备注"
allow-clear
/>
</a-form-model-item>
</a-form-model>
</a-modal>
</div>
</template>
<script>
import { saveSystemTask } from "@/services/system";
export default {
components: {},
props: {
addVisible: {
required: true,
type: Boolean,
default: false,
},
title: {
required: true,
type: String,
default: "",
},
dict: {
required: true,
type: Object,
default: () => {
return {};
},
},
},
data() {
return {
days: {}, // 号数
weeks: {}, // 周
form: {
name: "", // 任务名称
taskKey: "", // 关键字
excuteService: "", // 执行服务
excuteStrategy: 1, // 执行策略
excuteDate: 0, // 执行日期
excuteTime: "", // 执行时间
excuteHost: "", // 执行主机
excuteParam: "", // 执行参数
remark: "", // 备注
},
rules: {
name: [{ required: true, message: "请输入任务名称", trigger: "blur" }],
taskKey: [{ required: true, message: "请输入关键字", trigger: "blur" }],
excuteService: [
{ required: true, message: "请输入执行服务", trigger: "blur" },
],
},
};
},
computed: {
Visible: {
get() {
return this.addVisible;
},
set(val) {
this.$emit("update:addVisible", val);
},
},
},
created() {
for (let i = 1; i <= 31; i++) {
this.days[i] = i + "";
}
let numArr = ["", "", "", "", "", "", ""];
for (let i = 1; i <= 7; i++) {
this.weeks[i] = "星期" + numArr[i - 1];
}
},
methods: {
// 切换执行策略
changeExcuteStrategy(val) {
if (val == 1) {
this.form.excuteDate = 0;
} else {
this.form.excuteDate = undefined;
}
if (val == 4) {
this.form.excuteTime = "";
}
},
// 关闭弹窗
handleCancel() {
this.$refs.form.resetFields();
this.Visible = false;
},
// 重置
handleReset() {
this.$refs.form.resetFields();
},
// 新增
onAdd() {
Object.assign(this.form, this.$options.data().form);
this.form.id && this.$delete(this.form, "id");
},
// 编辑
onEdit(row) {
this.$nextTick(() => {
this.form = { ...row };
});
},
// 保存
handleOk() {
this.$refs.form.validate(async (valid) => {
if (valid) {
let res = await saveSystemTask(this.form);
let { code, msg } = res.data;
if (code == 1) {
this.$message.success(msg);
this.$emit("addSuccess");
this.handleCancel();
}
}
});
},
},
};
</script>
<style lang="less" scoped></style>
<template>
<div class="user-container">
<div class="control flex aic jcb mb15 pdr6">
<div>
<!-- <a-button type="primary" style="margin-right: 10px" @click="handleAdd"
>新增</a-button
>
<a-button type="danger" @click="handleDelAll">批量删除</a-button> -->
</div>
<div class="search-box">
<a-space>
<a-input
placeholder="请输入登录名搜索"
v-model="searchForm.loginName"
allowClear
/>
<a-input
placeholder="请输入用户姓名搜索"
v-model="searchForm.realName"
allowClear
/>
<a-button type="primary" @click="onSearch">搜索</a-button>
<a-button @click="resetSearch">重置</a-button>
</a-space>
</div>
</div>
<!-- 表格 -->
<div class="table-content">
<a-table
:loading="loading"
bordered
:scroll="{ y: 590 }"
:columns="columns"
:pagination="{
showTotal: (total) => `共 ${total} 条`,
current: current,
total: total,
pageSize: size,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: pageSizeOptions,
onChange: handleChange,
onShowSizeChange: showSizeChange,
}"
:data-source="tableData"
:rowKey="(record) => record.id"
>
<!-- 序号 -->
<span slot="num" slot-scope="text, record, index">{{
(current - 1) * size + index + 1
}}</span>
<!-- 操作 -->
<template slot="action" slot-scope="text">
<a-space size="middle">
<span class="primary pointer" @click="changeRole(text)"
>分配角色</span
>
</a-space>
</template>
</a-table>
</div>
<!-- 分配角色 -->
<AddUserRole
ref="AddUserRole"
:addVisible.sync="addVisible"
:roleList="roleList"
@addSuccess="getUserList"
></AddUserRole>
</div>
</template>
<script>
import { getUserList, getRoleList } from "@/services/system";
import { pageSizeOptions } from "@/config/pageConfig.js";
import AddUserRole from "./modal/AddUserRole.vue";
import { mapState } from "vuex";
export default {
components: { AddUserRole },
data() {
const columns = [
{
title: "序号",
dataIndex: "num",
width: "65px",
scopedSlots: {
customRender: "num",
},
},
{
title: "登录名",
dataIndex: "loginName",
},
{
title: "用户姓名",
dataIndex: "realName",
},
{
title: "所属角色",
dataIndex: "roleIds",
customRender: (text) => {
if (text && this.roleList.length) {
let obj = {};
this.roleList.forEach((v) => {
obj[v.id] = v.name;
});
let roleIds = text.split(",");
return roleIds.map((v) => {
return <a-tag>{obj[v]}</a-tag>;
});
}
},
},
{
title: "状态",
dataIndex: "status",
customRender: (text) => {
return <a-tag>{this.dict.status[text]}</a-tag>;
},
},
{
title: "操作",
width: "120px",
scopedSlots: { customRender: "action" },
},
];
return {
columns,
loading: false,
current: 1,
size: 10,
total: 0,
pageSizeOptions,
searchForm: {
loginName: "",
realName: "",
},
tableData: [],
roleList: [], // 角色列表
selectedRowKeys: [],
dict: {}, // 字典
addVisible: false,
title: "新增",
loginNames: ["admin", "administrator1", "Administrator"],
};
},
computed: {
...mapState("site", ["userInfo"]),
},
created() {
this.getRoleList();
this.getUserList();
},
methods: {
// 获取角色列表
async getRoleList() {
let res = await getRoleList({
page: 1,
size: -1,
});
if (res.data.code == 1) {
let { data } = res.data.data;
this.roleList = data;
}
},
// 获取用户列表
async getUserList() {
this.loading = true;
let res = await getUserList({
page: this.current,
size: this.size,
...this.searchForm,
});
this.loading = false;
if (res.data.code == 1) {
let { data, total, dict } = res.data.data;
if (!data.length && this.current > 1) {
this.current -= 1;
this.getUserList();
}
let { name } = this.userInfo;
if (this.loginNames.includes(name)) {
this.tableData = data;
this.total = total;
} else {
this.tableData = data.filter((v) => {
return !this.loginNames.includes(v.loginName);
});
this.total = total - this.loginNames.length;
}
this.dict = dict;
}
},
// 新增
handleAdd() {
this.title = "新增";
this.$refs.AddParameter.onAdd();
this.addVisible = true;
},
// 搜索
onSearch() {
this.current = 1;
this.getUserList();
},
resetSearch() {
this.current = 1;
Object.assign(this.searchForm, this.$options.data().searchForm);
this.getUserList();
},
// 分页
handleChange(num) {
this.current = num;
this.getUserList();
},
// 改变每页显示数量
showSizeChange(current, size) {
this.current = current;
this.size = size;
this.getUserList();
},
// 分配角色
changeRole(row) {
this.$refs.AddUserRole.onEdit(row);
this.addVisible = true;
},
},
};
</script>
<style lang="less" scoped>
.user-container {
width: 100%;
height: 100%;
}
</style>
<template>
<div>
<a-modal
title="分配角色"
:visible="Visible"
@cancel="handleCancel"
:maskClosable="false"
>
<a-button slot="footer" @click="handleReset">重置</a-button>
<a-button
slot="footer"
type="primary"
:loading="loading"
@click="handleOk"
>确定</a-button
>
<a-form-model
:model="form"
ref="form"
:rules="rules"
:label-col="{ span: 5 }"
:wrapper-col="{ span: 19 }"
>
<a-form-model-item label="选择角色" prop="roleIds">
<a-select
mode="multiple"
v-model="form.roleIds"
placeholder="请选择角色"
>
<a-select-option v-for="v in roleList" :key="v.id" :value="v.id">{{
v.name
}}</a-select-option>
</a-select>
</a-form-model-item>
</a-form-model>
</a-modal>
</div>
</template>
<script>
import { saveUser } from "@/services/system";
export default {
components: {},
props: {
addVisible: {
required: true,
type: Boolean,
default: false,
},
roleList: {
required: true,
type: Array,
default: () => [],
},
},
data() {
return {
loading: false,
form: {
roleIds: [],
},
rules: {
roleIds: [{ required: true, message: "请选择角色", trigger: "change" }],
},
};
},
computed: {
Visible: {
get() {
return this.addVisible;
},
set(val) {
this.$emit("update:addVisible", val);
},
},
},
created() {},
methods: {
// 新增
onAdd() {
Object.assign(this.form, this.$options.data().form);
this.form.id && this.$delete(this.form, "id");
},
// 编辑
onEdit(row) {
this.$nextTick(() => {
this.form = { ...row };
if (this.form.roleIds) {
this.form.roleIds = this.form.roleIds.split(",").map(Number);
} else {
this.form.roleIds = [];
}
});
},
// 保存
handleOk() {
this.$refs.form.validate(async (valid) => {
if (valid) {
this.loading = true;
let { id, roleIds, lastLoginAddress, mobile } = this.form;
let res = await saveUser({
id,
lastLoginAddress,
mobile,
roleIds: roleIds.join(","),
});
this.loading = false;
let { code, msg } = res.data;
if (code == 1) {
this.$message.success(msg);
this.$emit("addSuccess");
this.handleCancel();
}
}
});
},
// 重置
handleReset() {
this.$refs.form.resetFields();
},
// 关闭
handleCancel() {
this.$refs.form.resetFields();
this.Visible = false;
},
},
};
</script>
<style lang="less" scoped></style>
......@@ -25,6 +25,12 @@
维度管理
</span>
</a-tab-pane> -->
<a-tab-pane key="/system/menu">
<span slot="tab">
<a-icon type="deployment-unit" />
菜单管理
</span>
</a-tab-pane>
<a-tab-pane key="/system/parameter">
<span slot="tab">
<a-icon type="container" />
......
<template>
<div class="menu-page">
<div class="control flex aic jcb mb15 pdr6">
<a-space>
<a-button
type="primary"
v-hasPermi="['system:menu:add']"
@click="handleAdd"
>新增</a-button
>
</a-space>
</div>
<y-table
:scroll="{ y: 560 }"
:columns="columns"
:data="tableData"
:pageSize.sync="size"
:page.sync="page"
:total="total"
:loading="loading"
:pagination="{
showSizeChanger: false,
showQuickJumper: false,
}"
@changePagination="getMenuList"
>
</y-table>
<!-- 新增菜单 -->
<AddMenu
ref="AddMenu"
:show.sync="show"
:title="title"
:dict="dict"
:menuData="tableData"
@success="getMenuList"
></AddMenu>
</div>
</template>
<script>
import YTable from "@/components/YTable.vue";
import YSwitch from "@/components/yswitch/YSwitch.vue";
import AddMenu from "./modal/AddMenu.vue";
import { buildTree } from "@/utils/util";
import {
getMenuList,
delMenu,
saveMenu,
saveMenuSort,
} from "@/services/system";
export default {
components: {
YTable,
AddMenu,
},
data() {
return {
loading: false,
show: false,
title: "新增",
columns: [
{
title: "菜单名称",
align: "left",
dataIndex: "name",
},
// {
// title: "ID",
// dataIndex: "id",
// },
{
title: "图标",
dataIndex: "imgPath",
customRender: (text) => {
if (text) {
return <a-icon type={text} />;
} else {
return "--";
}
},
},
// {
// title: "父ID",
// dataIndex: "parentId",
// },
{
title: "地址",
dataIndex: "url",
},
{
title: "类型",
dataIndex: "menuType",
customRender: (text) => {
if (text == 0) {
return <a-tag color="purple">{this.dict.menuType[text]}</a-tag>;
} else if (text == 1) {
return <a-tag color="cyan">{this.dict.menuType[text]}</a-tag>;
} else if (text == 2) {
return <a-tag color="blue">{this.dict.menuType[text]}</a-tag>;
}
},
},
{
title: "权限字符",
dataIndex: "perms",
},
{
title: "状态",
dataIndex: "status",
customRender: (text, record) => {
return (
<YSwitch
checked={text}
onchange={(val) => this.changeStatus(val, record)}
></YSwitch>
);
},
},
{
title: "操作",
width: "150px",
customRender: (text, record) => {
return (
<a-space>
<a-icon
type="arrow-up"
v-hasPermi={["system:menu:sort"]}
onClick={() => this.changeMenuSort(record.id, 0)}
/>
<a-icon
type="arrow-down"
v-hasPermi={["system:menu:sort"]}
onClick={() => this.changeMenuSort(record.id, 1)}
/>
<span
class="primary pointer"
v-hasPermi={["system:menu:edit"]}
onClick={() => this.handleEdit(record)}
>
编辑
</span>
<span
class="delete pointer"
v-hasPermi={["system:menu:remove"]}
onClick={() => this.handleDel(record.id)}
>
删除
</span>
</a-space>
);
},
},
],
page: 1,
size: 1000,
total: 0,
tableData: [], // 表格数据
dict: {},
selectedRowKeys: [],
};
},
created() {
this.getMenuList();
},
methods: {
async getMenuList() {
this.loading = true;
const res = await getMenuList({
groupName: this.groupName,
name: this.name,
page: this.page,
size: this.size,
});
this.loading = false;
if (res.data.code === 1) {
let {
data: { data, total },
dict,
} = res.data;
this.dict = dict;
this.tableData = buildTree(data);
this.total = total;
}
},
handleAdd() {
this.title = "新增";
this.$refs.AddMenu.onAdd();
this.show = true;
},
handleEdit(row) {
this.title = "编辑";
this.$refs.AddMenu.onEdit(row);
this.show = true;
},
selectChange(keys) {
this.selectedRowKeys = keys;
},
handleBatchDel() {
if (!this.selectedRowKeys.length) {
this.$message.warning("请先勾选数据");
return;
}
let ids = this.selectedRowKeys.join(",");
this.handleDel(ids);
},
// 删除
handleDel(id) {
this.$confirm({
title: "系统提示:",
content: "删除不可恢复,是否继续?",
okType: "danger",
cancelText: "取消",
centered: true,
maskClosable: true,
icon: "exclamation-circle",
onOk: async () => {
let res = await delMenu({ id });
let { code, msg } = res.data;
if (code === 1) {
this.$message.success(msg);
this.getMenuList();
}
},
onCancel() {},
});
},
async changeStatus(status, row) {
row.status = status;
let res = await saveMenu(row);
if (res.data.code === 1) {
this.$message.success("修改成功");
}
this.getMenuList();
},
// 改变菜单排序
async changeMenuSort(id, type) {
let res = await saveMenuSort({ id, type });
if (res.data.code == 1) {
this.$message.success("更改排序成功");
this.getMenuList();
}
},
},
};
</script>
<style lang="less" scoped>
.anticon {
font-size: 16px;
}
.anticon-arrow-up,
.anticon-arrow-down {
cursor: pointer;
color: #1890ff;
}
</style>
<template>
<div>
<a-modal
:title="title"
:visible="Visible"
@cancel="handleCancel"
:maskClosable="false"
width="650px"
>
<a-button slot="footer" @click="handleReset">重置</a-button>
<a-button
slot="footer"
type="primary"
:loading="loading"
@click="handleOk"
>确定</a-button
>
<a-form-model
:model="form"
ref="form"
:rules="rules"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
>
<a-form-model-item label="父级菜单" prop="parentId">
<a-tree-select
v-model="form.parentId"
style="width: 100%"
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
placeholder="请选择父级菜单"
:replaceFields="replaceFields"
:treeData="menuTree"
>
</a-tree-select>
</a-form-model-item>
<a-form-model-item label="菜单类型" prop="menuType">
<a-radio-group v-model="form.menuType">
<a-radio
v-for="(v, key) in dict.menuType"
:key="key"
:value="Number(key)"
>
{{ v }}
</a-radio>
</a-radio-group>
</a-form-model-item>
<a-form-model-item label="菜单名称" prop="name">
<a-input v-model="form.name" placeholder="请输入菜单名称"></a-input>
</a-form-model-item>
<template v-if="form.menuType != 2">
<a-form-model-item label="菜单图标" prop="imgPath">
<IconSelect v-model="form.imgPath"></IconSelect>
</a-form-model-item>
</template>
<template v-if="form.menuType != 2">
<a-form-model-item prop="url">
<span slot="label">
<a-tooltip title="访问的路由地址,如:`system`">
<a-icon type="question-circle" theme="filled" />
</a-tooltip>
路由地址
</span>
<a-input v-model="form.url" placeholder="请输入路由地址"></a-input>
</a-form-model-item>
</template>
<a-form-model-item prop="component" v-if="form.menuType != 2">
<span slot="label">
<a-tooltip
title="访问的组件路径,如:`pages/system/menu/Menu`,默认在`src`目录下"
>
<a-icon type="question-circle" theme="filled" />
</a-tooltip>
组件路径
</span>
<a-input
v-model="form.component"
placeholder="请输入组件路径"
></a-input>
</a-form-model-item>
<a-form-model-item prop="activeDir" v-if="form.menuType != 2">
<span slot="label">
<a-tooltip title="顶部菜单栏激活路由">
<a-icon type="question-circle" theme="filled" />
</a-tooltip>
激活菜单
</span>
<a-input
v-model="form.activeDir"
placeholder="请输入激活菜单地址"
></a-input>
</a-form-model-item>
<a-form-model-item prop="perms" v-if="form.menuType == 2">
<span slot="label">
<a-tooltip title="控制器中定义的权限字符,如:'system:menu:add'">
<a-icon type="question-circle" theme="filled" />
</a-tooltip>
权限字符
</span>
<a-input v-model="form.perms" placeholder="请输入权限字符"></a-input>
</a-form-model-item>
<a-row>
<a-col :span="12" v-if="form.menuType != 2"
><a-form-model-item
:label-col="{ span: 12 }"
:wrapper-col="{ span: 12 }"
prop="visible"
>
<span slot="label">
<a-tooltip title="控制路由和子路由是否显示在菜单栏">
<a-icon type="question-circle" theme="filled" />
</a-tooltip>
显示状态
</span>
<a-radio-group v-model="form.visible">
<a-radio
v-for="(v, key) in dict.visible"
:key="key"
:value="Number(key)"
>
{{ v }}
</a-radio>
</a-radio-group>
</a-form-model-item></a-col
>
<a-col :span="12" v-if="form.menuType != 2">
<a-form-model-item
:label-col="{ span: 12 }"
:wrapper-col="{ span: 12 }"
prop="cache"
>
<span slot="label">
<a-tooltip title="选择是则会被`keep-alive`缓存">
<a-icon type="question-circle" theme="filled" />
</a-tooltip>
是否缓存
</span>
<a-radio-group v-model="form.cache">
<a-radio :value="1">
</a-radio>
<a-radio :value="0">
</a-radio>
</a-radio-group>
</a-form-model-item></a-col
>
</a-row>
<a-row>
<a-col :span="12" v-if="form.menuType != 2">
<a-form-model-item
:label-col="{ span: 12 }"
:wrapper-col="{ span: 12 }"
prop="hideChildrenInMenu"
>
<span slot="label">
<a-tooltip title="强制菜单显示为Item而不是SubItem">
<a-icon type="question-circle" theme="filled" />
</a-tooltip>
是否隐藏子菜单
</span>
<a-radio-group v-model="form.hideChildrenInMenu">
<a-radio :value="1">
</a-radio>
<a-radio :value="0">
</a-radio>
</a-radio-group>
</a-form-model-item></a-col
>
<a-col :span="12">
<a-form-model-item
:label-col="{ span: 12 }"
:wrapper-col="{ span: 12 }"
label="菜单状态"
prop="status"
>
<a-radio-group v-model="form.status">
<a-radio
v-for="(v, key) in dict.status"
:key="key"
:value="Number(key)"
>
{{ v }}
</a-radio>
</a-radio-group>
</a-form-model-item></a-col
>
</a-row>
<!-- <a-form-model-item label="资源类型" prop="resourceType">
<a-radio-group v-model="form.resourceType">
<a-radio :value="1">
从资源列表获取
</a-radio>
<a-radio :value="2">
自定义资源地址
</a-radio>
</a-radio-group>
</a-form-model-item> -->
<a-row>
<a-col :span="24" v-show="form.resourceType == 1">
<a-form-model-item label="资源" prop="resourceUrl">
<SelectRes mode="multiple" v-model="form.resourceUrl"></SelectRes>
</a-form-model-item>
</a-col>
<!-- <a-col :span="24" v-show="form.resourceType == 2">
<a-form-model-item class="url-params-box" label="资源">
<a-form-model-item
class="url-params"
v-for="(v, i) in form.urls"
:key="i"
:prop="`urls.${i}.value`"
:rules="[
{ required: false, validator: validatorUrl, trigger: 'blur' },
]"
>
<a-input
style="width:100%; margin-right: 10px;"
v-model="v.value"
placeholder="请输入链接地址"
/>
<a-space>
<a-button type="primary" @click="changeParams(i, 'add')"
><a-icon type="plus"
/></a-button>
<a-button
type="danger"
v-if="i > 0"
@click="changeParams(i, 'remove')"
><a-icon type="minus"
/></a-button>
</a-space>
</a-form-model-item>
</a-form-model-item>
</a-col> -->
</a-row>
</a-form-model>
</a-modal>
</div>
</template>
<script>
import SelectRes from "./SelectRes.vue";
import IconSelect from "./IconSelect.vue";
import { saveMenu } from "@/services/system";
export default {
components: { SelectRes, IconSelect },
props: {
show: {
required: true,
type: Boolean,
default: false,
},
title: {
required: true,
type: String,
default: "",
},
dict: {
required: true,
type: Object,
default: () => {},
},
menuData: {
required: true,
type: Array,
default: () => [],
},
},
data() {
return {
loading: false,
replaceFields: {
title: "name",
value: "id",
},
form: {
name: "", // 菜单名称
url: "", // 路由地址
ancestors: "", // 当前节点父id路径,“,”分割
parentId: 0, // 父菜单ID,一级菜单的该字段值为-1
linkType: 0, // 链接方式 (0.普通,1.弹出,2.脚本)
imgPath: "", // 主菜单图标,主菜单图标的css样式名
buttonImgPath: "", // 按钮图标,按钮图标的css样式名
imgCommPath: "", // 常用菜单图标,常用菜单图标的css样式名
commMenu: 1, // 是否常用菜单 (0.非常用,1.常用)
component: "", // vue组件路径
menuType: 0, // 菜单类型 (0.目录,1.菜单,2.按钮)
authType: 0, // 权限类型 (0.无限制,1.无需登录查看,2.需要登录查看,3.需要角色权限查看)
visible: 0, // 菜单显示状态 (0.显示,1.隐藏)
perms: "", // 权限标识,多个逗号分割
remark: "", // 备注信息
orderId: "", // 排序编号
status: 1, // 菜单状态 (0.停用,1.启用)
cache: 0, // 是否缓存
activeDir: "", // 激活菜单
resourceType: 1, // 资源类型 (1.按资源id,1.链接地址)
resourceUrl: [], // 资源id或者路径
hideChildrenInMenu: 1, // 是否隐藏子菜单
urls: [
{
value: "",
},
],
},
rules: {
name: [{ required: true, message: "请输入菜单名称", trigger: "blur" }],
url: [
{ required: true, message: "请输入菜单访问地址", trigger: "blur" },
],
component: [
{ required: true, message: "请输入组件路径", trigger: "blur" },
],
// authType: [{ required: true, message: '请输入选择权限类型', trigger: 'change' }]
},
};
},
computed: {
Visible: {
get() {
return this.show;
},
set(val) {
this.$emit("update:show", val);
},
},
menuTree() {
let top = {
id: 0,
name: "",
};
return [top, ...this.menuData];
},
},
created() {},
methods: {
// 新增
onAdd() {
Object.assign(this.form, this.$options.data().form);
this.form.id && this.$delete(this.form, "id");
},
// 编辑
onEdit(row) {
this.$nextTick(() => {
this.form = { ...row };
this.$set(this.form, "resourceType", 1);
this.$set(this.form, "urls", [{ value: "" }]);
this.form.resourceUrl = [];
if (row.resourceUrl) {
let arr = row.resourceUrl.split(",");
if (this.isUrl(row.resourceUrl)) {
this.form.urls = arr.map((v) => {
return {
value: v,
};
});
this.form.resourceType = 2;
this.form.resourceUrl = arr;
} else {
this.form.resourceUrl = arr.map(Number);
}
}
});
},
// 保存
handleOk() {
this.$refs.form.validate(async (valid) => {
if (valid) {
this.loading = true;
let resourceUrl;
let form = { ...this.form };
if (this.form.resourceType === 1) {
resourceUrl = this.form.resourceUrl.join(",");
} else {
resourceUrl = this.form.urls
.map((v) => {
return v.value.startsWith("/") ? v.value : "/" + v.value;
})
.join(",");
}
this.$delete(form, "resourceType");
this.$delete(form, "urls");
let res = await saveMenu({
...form,
resourceUrl,
});
let { code, msg } = res.data;
if (code === 1) {
this.$message.success(msg);
this.$emit("success");
this.handleCancel();
}
this.loading = false;
}
});
},
// 重置
handleReset() {
this.$refs.form.resetFields();
},
// 关闭
handleCancel() {
this.$refs.form.resetFields();
this.loading = false;
this.Visible = false;
},
// 判断资源是否是链接
isUrl(val) {
return val.startsWith("/");
},
/** 转换菜单数据结构 */
normalizer(node) {
if (node.childList && !node.childList.length) {
delete node.childList;
}
return {
id: node.id,
label: node.name,
children: node.childList,
};
},
// 判断是否存在链接
isRepeat(val) {
return this.form.urls.filter((v) => v.value == val).length > 1;
},
// 校验链接地址
validatorUrl(rule, value, callback) {
if (!value) {
if (rule.required) {
callback(new Error("请输入链接"));
} else {
callback();
}
} else if (this.isRepeat(value)) {
callback(new Error("重复的链接地址"));
} else {
callback();
}
},
changeParams(index, type) {
if (type == "add") {
let obj = {
value: "",
};
if (this.form.urls.some((v) => !v.value)) {
this.$message.warning("请先完成前面地址的填写");
return;
}
this.form.urls.splice(index + 1, 0, obj);
} else {
this.form.urls.splice(index, 1);
}
// this.$forceUpdate();
},
},
};
</script>
<style lang="less" scoped>
/deep/.ant-modal-body {
max-height: 650px;
overflow: auto;
}
/deep/.url-params-box {
display: block !important;
.ant-form-item-children {
display: block;
}
}
/deep/.url-params {
.ant-form-item-control-wrapper {
width: 100%;
}
.ant-form-item-children {
display: flex;
align-items: center;
}
}
</style>
<template>
<a-popover placement="bottomLeft" trigger="click" width="100%">
<div slot="content" class="content ">
<div
:class="['item', { active: value === '' }]"
@click="handleChange('')"
>
<span>无图标</span>
</div>
<div v-for="(v, i) in iconJson" :key="i">
<div
:class="['item', { active: v === value }]"
@click="handleChange(v)"
>
<a-icon :type="v" />
<span>{{ v }}</span>
</div>
</div>
</div>
<a-input :value="value" :placeholder="placeholder" readOnly>
<a-icon v-if="value" slot="prefix" :type="value" />
<a-icon v-else slot="prefix" type="search" />
</a-input>
</a-popover>
</template>
<script>
import iconJson from "./icon.json";
export default {
model: {
prop: "value",
event: "change",
},
props: {
value: {
type: String,
default: "",
},
placeholder: {
type: String,
default: "点击选择图标",
},
},
data() {
return {
iconJson,
};
},
methods: {
handleChange(v) {
this.$emit("change", v);
},
},
};
</script>
<style lang="less" scoped>
.content {
width: 100%;
max-height: 300px;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 8px 16px;
overflow: auto;
&::-webkit-scrollbar {
width: 6px;
height: 6px;
overflow-y: auto;
}
&::-webkit-scrollbar-thumb {
border-radius: 6px;
background-color: rgba(144, 147, 153, 0.5);
}
&::-webkit-scrollbar-track {
border-radius: 6px;
background: rbga(0, 0, 0, 0);
}
.active {
color: #1890ff;
}
}
.item {
display: flex;
align-items: center;
gap: 16px;
cursor: pointer;
}
</style>
<template>
<div style="width: 100%">
<a-select
showSearch
optionFilterProp="label"
style="width: 100%"
allowClear
:value="value"
placeholder="请选择资源"
v-bind="$attrs"
v-on="$listeners"
@change="handleChange"
>
<a-select-opt-group v-for="v in resourceList" :key="v.id" :label="v.name">
<a-select-option
v-for="item in v.children"
:key="item.id"
:value="item.id"
:label="item.name"
>
{{ item.name }}
</a-select-option>
</a-select-opt-group>
</a-select>
</div>
</template>
<script>
import { getResourceGroupTree } from "@/services/system";
export default {
model: {
prop: "value",
event: "change",
},
props: {
value: {
default: "",
},
dict: {
type: Object,
default: () => {},
},
form: {
type: Object,
default: () => {},
},
},
data() {
return {
resourceList: [], // 资源列表
};
},
created() {
this.getResourceGroupTree();
},
methods: {
// 获取资源列表
async getResourceGroupTree() {
let res = await getResourceGroupTree({
page: 1,
size: -1,
});
if (res.data.code == 1) {
let { data } = res.data.data;
this.resourceList = this.formatGroup(data);
}
},
// 格式化分组
formatGroup(data) {
let arr = [];
Object.keys(data).forEach((key, index) => {
let group = {};
group = {
name: key,
id: -index,
children: [],
};
group.children.push(...data[key]);
arr.push(group);
});
return arr;
},
handleChange(value) {
this.$emit("change", value);
},
displayRender({ labels }) {
return labels[labels.length - 1];
},
filter(inputValue, path) {
return path.some(
(option) =>
option.name.toLowerCase().indexOf(inputValue.toLowerCase()) > -1
);
},
},
};
</script>
<style lang="less" scoped></style>
[
"step-backward",
"step-forward",
"fast-backward",
"fast-forward",
"shrink",
"arrows-alt",
"down",
"up",
"left",
"right",
"caret-up",
"caret-down",
"caret-left",
"caret-right",
"up-circle",
"down-circle",
"left-circle",
"right-circle",
"double-right",
"double-left",
"vertical-left",
"vertical-right",
"vertical-align-top",
"vertical-align-middle",
"vertical-align-bottom",
"forward",
"backward",
"rollback",
"enter",
"retweet",
"swap",
"swap-left",
"swap-right",
"arrow-up",
"arrow-down",
"arrow-left",
"arrow-right",
"play-circle",
"up-square",
"down-square",
"left-square",
"right-square",
"login",
"logout",
"menu-fold",
"menu-unfold",
"border-bottom",
"border-horizontal",
"border-inner",
"border-outer",
"border-left",
"border-right",
"border-top",
"border-verticle",
"pic-center",
"pic-left",
"pic-right",
"radius-bottomleft",
"radius-bottomright",
"radius-upleft",
"radius-upright",
"fullscreen",
"fullscreen-exit",
"question",
"question-circle",
"plus",
"plus-circle",
"pause",
"pause-circle",
"minus",
"minus-circle",
"plus-square",
"minus-square",
"info",
"info-circle",
"exclamation",
"exclamation-circle",
"close",
"close-circle",
"close-square",
"check",
"check-circle",
"check-square",
"clock-circle",
"warning",
"issues-close",
"stop",
"edit",
"form",
"copy",
"scissor",
"delete",
"snippets",
"diff",
"highlight",
"align-center",
"align-left",
"align-right",
"bg-colors",
"bold",
"italic",
"underline",
"strikethrough",
"redo",
"undo",
"zoom-in",
"zoom-out",
"font-colors",
"font-size",
"line-height",
"dash",
"small-dash",
"sort-ascending",
"sort-descending",
"drag",
"ordered-list",
"unordered-list",
"radius-setting",
"column-width",
"column-height",
"area-chart",
"pie-chart",
"bar-chart",
"dot-chart",
"line-chart",
"radar-chart",
"heat-map",
"fall",
"rise",
"stock",
"box-plot",
"fund",
"sliders",
"android",
"apple",
"windows",
"ie",
"chrome",
"github",
"aliwangwang",
"dingding",
"weibo-square",
"weibo-circle",
"taobao-circle",
"html5",
"weibo",
"twitter",
"wechat",
"youtube",
"alipay-circle",
"taobao",
"skype",
"qq",
"medium-workmark",
"gitlab",
"medium",
"linkedin",
"google-plus",
"dropbox",
"facebook",
"codepen",
"code-sandbox",
"amazon",
"google",
"codepen-circle",
"alipay",
"ant-design",
"ant-cloud",
"aliyun",
"zhihu",
"slack",
"slack-square",
"behance",
"behance-square",
"dribbble",
"dribbble-square",
"instagram",
"yuque",
"alibaba",
"yahoo",
"reddit",
"sketch",
"account-book",
"alert",
"api",
"appstore",
"audio",
"bank",
"bell",
"book",
"bug",
"bulb",
"calculator",
"build",
"calendar",
"camera",
"car",
"carry-out",
"cloud",
"code",
"compass",
"contacts",
"container",
"control",
"credit-card",
"crown",
"customer-service",
"dashboard",
"database",
"dislike",
"environment",
"experiment",
"eye-invisible",
"eye",
"file-add",
"file-excel",
"file-exclamation",
"file-image",
"file-markdown",
"file-pdf",
"file-ppt",
"file-text",
"file-unknown",
"file-word",
"file-zip",
"file",
"filter",
"fire",
"flag",
"folder-add",
"folder",
"folder-open",
"frown",
"funnel-plot",
"gift",
"hdd",
"heart",
"home",
"hourglass",
"idcard",
"insurance",
"interaction",
"layout",
"like",
"lock",
"mail",
"medicine-box",
"meh",
"message",
"mobile",
"money-collect",
"pay-circle",
"notification",
"phone",
"picture",
"play-square",
"printer",
"profile",
"project",
"pushpin",
"property-safety",
"read",
"reconciliation",
"red-envelope",
"rest",
"rocket",
"safety-certificate",
"save",
"schedule",
"security-scan",
"setting",
"shop",
"shopping",
"skin",
"smile",
"sound",
"star",
"switcher",
"tablet",
"tag",
"tags",
"tool",
"thunderbolt",
"trophy",
"unlock",
"usb",
"video-camera",
"wallet",
"apartment",
"audit",
"barcode",
"bars",
"block",
"border",
"branches",
"ci",
"cloud-download",
"cloud-server",
"cloud-sync",
"cloud-upload",
"cluster",
"coffee",
"copyright",
"deployment-unit",
"desktop",
"disconnect",
"dollar",
"download",
"ellipsis",
"euro",
"exception",
"export",
"file-done",
"file-jpg",
"file-protect",
"file-sync",
"file-search",
"fork",
"gateway",
"global",
"gold",
"history",
"import",
"inbox",
"key",
"laptop",
"link",
"line",
"loading-3-quarters",
"loading",
"man",
"menu",
"monitor",
"more",
"number",
"percentage",
"paper-clip",
"pound",
"poweroff",
"pull-request",
"qrcode",
"reload",
"safety",
"robot",
"scan",
"search",
"select",
"shake",
"share-alt",
"shopping-cart",
"solution",
"sync",
"table",
"team",
"to-top",
"trademark",
"transaction",
"upload",
"user-add",
"user-delete",
"usergroup-add",
"user",
"usergroup-delete",
"wifi",
"woman"
]
\ No newline at end of file
<template>
<div class="parameter">
<div class="control flex aic jcb mb15 pdr6">
<div>
<a-button type="primary" style="margin-right: 10px" @click="handleAdd"
<a-space>
<a-button
type="primary"
v-hasPermi="['system:parameter:add']"
@click="handleAdd"
>新增</a-button
>
<a-button type="danger" @click="handleDelAll">批量删除</a-button>
</div>
<a-button
type="danger"
v-hasPermi="['system:parameter:remove']"
@click="handleDelAll"
>批量删除</a-button
>
</a-space>
<div class="search-box">
<a-space>
<a-input
......@@ -56,14 +64,14 @@
<template slot="action" slot-scope="{ record }">
<a-space size="middle">
<span
href="javascript:;"
class="primary pointer"
v-hasPermi="['system:parameter:edit']"
@click="handleEdit(record)"
>编辑</span
>
<span
href="javascript:;"
class="delete pointer"
v-hasPermi="['system:parameter:remove']"
@click="handleDel(record.id)"
>删除</span
>
......
<template>
<div class="resource-container">
<div class="resoure-page">
<div class="control flex aic jcb mb15 pdr6">
<a-space>
<a-button type="primary" @click="handleAdd">新增</a-button>
<a-button
v-permission="[1]"
type="primary"
v-hasPermi="['system:resourceManage:add']"
@click="handleAdd"
>新增</a-button
>
<a-button
type="danger"
v-hasPermi="['system:resourceManage:remove']"
@click="handleBatchDel"
>批量删除</a-button
>
<a-button
type="primary"
v-hasPermi="['system:resourceManage:update']"
class="addclass"
@click="refSresource"
>刷新资源</a-button
>
<a-button type="danger" @click="handleDelAll">批量删除</a-button>
</a-space>
<div class="search-box">
<a-input-search
placeholder="请输入资源名搜索"
enter-button="搜索"
v-model="searchValue"
allowClear
@search="onSearch"
/>
</div>
</div>
<!-- 表格 -->
<div class="table-content">
<a-table
:row-selection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectChange,
}"
:loading="loading"
bordered
:scroll="{ y: 590 }"
:columns="columns"
:pagination="{
showTotal: (total) => `共 ${total} 条`,
current: current,
total: total,
pageSize: size,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: pageSizeOptions,
onChange: handleChange,
onShowSizeChange: showSizeChange,
}"
:data-source="tableData"
:rowKey="(record) => record.id"
>
<!-- 序号 -->
<span slot="num" slot-scope="text, record, index">{{
(current - 1) * size + index + 1
}}</span>
<!-- 操作 -->
<template slot="action" slot-scope="text">
<a-space size="middle">
<span
href="javascript:;"
class="primary pointer"
@click="handleEdit(text)"
>编辑</span
>
<span
href="javascript:;"
class="delete pointer"
@click="handleDel(text.id)"
>删除</span
>
</a-space>
</template>
</a-table>
<a-space>
<a-input placeholder="请输入资源名称搜索" v-model="name" />
<a-button type="primary" @click="handleSearch">搜索</a-button>
<a-button @click="handleResetSearch">重置</a-button>
</a-space>
</div>
<!-- 新增、编辑 -->
<y-table
:scroll="{ y: 560 }"
:columns="columns"
:data="tableData"
:pageSize.sync="size"
:page.sync="page"
:total="total"
:loading="loading"
@changePagination="getResourceList"
:row-selection="{
selectedRowKeys: selectedRowKeys,
onChange: selectChange,
}"
>
</y-table>
<!-- 新增资源 -->
<AddResurce
ref="AddResurce"
:title="title"
:visible.sync="addVisible"
:dict="dict"
@add="getResourceList"
:title="title"
:show.sync="show"
@success="getResourceList"
></AddResurce>
</div>
</template>
<script>
import YTable from "@/components/YTable.vue";
import AddResurce from "./modal/AddResurce.vue";
import {
getResourceList,
refreshResource,
delResource,
refreshResource,
} from "@/services/system";
import { pageSizeOptions } from "@/config/pageConfig.js";
import AddResurce from "./modal/AddResurce.vue";
export default {
components: { AddResurce },
components: {
YTable,
AddResurce,
},
data() {
const columns = [
{
title: "序号",
dataIndex: "num",
width: "65px",
scopedSlots: {
customRender: "num",
return {
loading: false,
show: false,
title: "新增",
columns: [
{
title: "序号",
width: "65px",
customRender: (text, record, index) => {
return (this.page - 1) * this.size + index + 1;
},
},
},
{
title: "名称",
width: 400,
dataIndex: "name",
},
{
title: "资源",
dataIndex: "url",
customRender: (text) => {
if (text) {
return text.split(",").map((v) => {
return (
<a-tag style="margin-bottom:4px" color="blue">
{v}
</a-tag>
);
});
}
{
title: "所属分组",
dataIndex: "groupName",
},
},
{
title: "认证类型",
width: 200,
dataIndex: "authType",
customRender: (text) => {
return this.dict.authType[text];
{
title: "名称",
dataIndex: "name",
},
},
{
title: "操作",
width: "120px",
scopedSlots: { customRender: "action" },
},
];
return {
columns,
loading: false,
current: 1,
{
title: "资源路径",
dataIndex: "url",
customRender: (text) => {
if (text) {
return text.split(",").map((v) => {
return <a-tag>{v}</a-tag>;
});
}
},
},
{
title: "认证类型",
dataIndex: "authType",
customRender: (text) => {
if (this.dict.authType) {
return this.dict.authType[text];
}
},
},
{
title: "创建时间",
dataIndex: "createTime",
},
{
title: "操作",
width: "120px",
customRender: (text, record) => {
return (
<a-space>
<span
class="primary pointer"
v-hasPermi={["system:resourceManage:edit"]}
onClick={() => this.handleEdit(record)}
>
编辑
</span>
<span
class="delete pointer"
v-hasPermi={["system:resourceManage:remove"]}
onClick={() => this.handleDel(record.id)}
>
删除
</span>
</a-space>
);
},
},
],
groupName: "",
name: "",
page: 1,
size: 10,
total: 0,
pageSizeOptions,
searchValue: "", // 搜索
tableData: [],
tableData: [], // 表格数据
dict: {},
selectedRowKeys: [],
dict: {}, // 字典
addVisible: false,
title: "新增",
};
},
created() {
this.getResourceList();
},
methods: {
// 获取资源列表
async getResourceList() {
this.loading = true;
let res = await getResourceList({
page: this.current,
const res = await getResourceList({
name: `%${this.name}%`,
page: this.page,
size: this.size,
name: `%${this.searchValue}%`,
});
this.loading = false;
if (res.data.code == 1) {
if (res.data.code === 1) {
let { data, total, dict } = res.data.data;
if (!data.length && this.current > 1) {
this.current -= 1;
if (!data.length && this.page > 1) {
this.page -= 1;
this.getResourceList();
}
this.dict = dict;
this.tableData = data;
this.total = total;
this.dict = dict;
}
},
// 新增
handleAdd() {
this.title = "新增";
this.$refs.AddResurce.onAdd();
this.addVisible = true;
},
// 搜索
onSearch() {
this.current = 1;
handleSearch() {
this.page = 1;
this.getResourceList();
},
// 分页
handleChange(num) {
this.current = num;
handleResetSearch() {
this.name = "";
this.page = 1;
this.getResourceList();
},
// 改变每页显示数量
showSizeChange(current, size) {
this.current = current;
this.size = size;
this.getResourceList();
handleAdd() {
this.title = "新增";
this.$refs.AddResurce.onAdd();
this.show = true;
},
handleEdit(row) {
this.title = "编辑";
this.$refs.AddResurce.onEdit(row);
this.show = true;
},
// 选择
onSelectChange(keys) {
selectChange(keys) {
this.selectedRowKeys = keys;
},
// 批量删除
handleDelAll() {
handleBatchDel() {
if (!this.selectedRowKeys.length) {
this.$message.warn("请先勾选数据");
this.$message.warning("请先勾选数据");
return;
}
let ids = this.selectedRowKeys.join(",");
this.handleDel(ids);
},
// 编辑
handleEdit(row) {
this.title = "编辑";
this.$refs.AddResurce.onEdit(row);
this.addVisible = true;
},
// 删除
handleDel(id) {
let _this = this;
this.$confirm({
title: "系统提示",
content: "删除不可恢复,确定要删除吗?",
okText: "确定",
title: "系统提示:",
content: "删除不可恢复,是否继续?",
okType: "danger",
cancelText: "取消",
centered: true,
icon: "exclamation-circle",
maskClosable: true,
async onOk() {
icon: "exclamation-circle",
onOk: async () => {
let res = await delResource({ id });
if (res.data.code == 1) {
let { msg } = res.data;
_this.$message.success(msg);
_this.getResourceList();
let { code, msg } = res.data;
if (code === 1) {
this.$message.success(msg);
this.getResourceList();
}
},
onCancel() {
console.log("Cancel");
},
onCancel() {},
});
},
apportion(row) {
console.log("🚀 ~ apportion ~ row:", row);
},
// 刷新资源
async refSresource() {
let _this = this;
......@@ -264,9 +248,4 @@ export default {
};
</script>
<style lang="less" scoped>
.resource-container {
width: 100%;
height: 100%;
}
</style>
<style lang="less" scoped></style>
......@@ -88,7 +88,7 @@ export default {
type: String,
default: "新增资源",
},
visible: {
show: {
required: true,
type: Boolean,
default: false,
......@@ -123,10 +123,10 @@ export default {
computed: {
Visible: {
get() {
return this.visible;
return this.show;
},
set(val) {
this.$emit("update:visible", val);
this.$emit("update:show", val);
},
},
},
......@@ -161,7 +161,7 @@ export default {
this.loading = false;
if (code == 1) {
this.$message.success(msg);
this.$emit("add");
this.$emit("success");
this.handleCancel();
}
}
......@@ -225,6 +225,9 @@ export default {
}
}
/deep/.url-params {
.ant-form-item-control-wrapper {
width: 100%;
}
.ant-form-item-children {
display: flex;
align-items: center;
......
<template>
<div class="role-container">
<div class="role-page">
<div class="control flex aic jcb mb15 pdr6">
<div>
<a-button type="primary" style="margin-right: 10px" @click="handleAdd"
<a-space>
<a-button
type="primary"
v-hasPermi="['system:role:add']"
@click="handleAddRole"
>新增</a-button
>
<a-button type="danger" @click="handleDelAll">批量删除</a-button>
</div>
<div class="search-box">
<a-input-search
placeholder="请输入角色名搜索"
enter-button="搜索"
v-model="searchValue"
allowClear
@search="onSearch"
/>
</div>
</div>
<!-- 表格 -->
<div class="table-content">
<a-table
:row-selection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectChange,
}"
:loading="loading"
bordered
:scroll="{ y: 590 }"
:columns="columns"
:pagination="{
showTotal: (total) => `共 ${total} 条`,
current: current,
total: total,
pageSize: size,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: pageSizeOptions,
onChange: handleChange,
onShowSizeChange: showSizeChange,
}"
:data-source="tableData"
:rowKey="(record) => record.id"
>
<!-- 序号 -->
<span slot="num" slot-scope="text, record, index">{{
(current - 1) * size + index + 1
}}</span>
<a-button
type="danger"
v-hasPermi="['system:role:remove']"
@click="handleBatchDel"
>批量删除</a-button
>
</a-space>
<!-- 操作 -->
<template slot="action" slot-scope="text">
<a-space size="middle">
<span class="primary pointer" @click="apportion(text)"
>分配资源</span
>
<span class="primary pointer" @click="handleResDim(text)"
>资源规则</span
>
<span class="primary pointer" @click="handleEdit(text)">编辑</span>
<span class="delete pointer" @click="handleDel(text.id)">删除</span>
</a-space>
</template>
</a-table>
<a-space slot="search">
<a-input placeholder="请输入角色名称搜索" v-model="name" />
<a-button type="primary" @click="handleSearch">搜索</a-button>
<a-button @click="handleResetSearch">重置</a-button>
</a-space>
</div>
<!-- 新增 -->
<y-table
:scroll="{ y: 560 }"
:columns="columns"
:data="tableData"
:pageSize.sync="size"
:page.sync="page"
:total="total"
:loading="loading"
@changePagination="getRoleList"
:rowSelection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectChange,
}"
>
</y-table>
<!-- 新增角色 -->
<AddRole
ref="AddRole"
:show.sync="showAddRole"
:title="title"
:addVisible.sync="addVisible"
@addSuccess="getRoleList"
@success="getRoleList"
></AddRole>
<!-- 分配菜单 -->
<ApportionMenu
ref="ApportionMenu"
:show.sync="menuShow"
:roleInfo="roleInfo"
:menuList="menuList"
></ApportionMenu>
<!-- 分配资源 -->
<ApportionRes ref="ApportionRes" :visible.sync="resVisible"></ApportionRes>
<!-- 资源规则 -->
<ResDimList ref="ResDimList" :visible.sync="resDimListVisible"></ResDimList>
<ApportionRes ref="ApportionRes" :show.sync="resShow"></ApportionRes>
</div>
</template>
<script>
import { getRoleList, delRole } from "@/services/system";
import { pageSizeOptions } from "@/config/pageConfig.js";
import AddRole from "./modal/AddRole.vue";
import YTable from "@/components/YTable.vue";
import ApportionMenu from "./modal/ApportionMenu.vue";
import ApportionRes from "./modal/ApportionRes.vue";
import ResDimList from "./modal/ResDimList.vue";
import { getRoleList, delRole, getMenuList } from "@/services/system";
import AddRole from "./modal/AddRole.vue";
export default {
components: { AddRole, ApportionRes, ResDimList },
components: {
YTable,
AddRole,
ApportionMenu,
ApportionRes,
},
data() {
const columns = [
{
title: "序号",
dataIndex: "num",
width: "65px",
scopedSlots: {
customRender: "num",
},
},
{
title: "角色名称",
dataIndex: "name",
},
{
title: "备注",
dataIndex: "remark",
},
{
title: "操作",
width: "20% ",
scopedSlots: { customRender: "action" },
},
];
return {
columns,
loading: false,
current: 1,
showAddRole: false,
title: "新增",
columns: [
{
title: "序号",
dataIndex: "num",
width: "65px",
customRender: (text, record, index) => {
return (this.page - 1) * this.size + index + 1;
},
},
{
title: "角色名称",
dataIndex: "name",
},
{
title: "备注",
dataIndex: "remark",
},
{
title: "创建时间",
dataIndex: "createTime",
},
// <span
// class="primary pointer"
// v-hasPermi={["system:role:resource"]}
// onClick={() => this.apportion(record)}
// >
// 分配资源
// </span>
{
title: "操作",
width: "250px",
customRender: (text, record) => {
return (
<a-space>
<span
class="primary pointer"
v-hasPermi={["system:role:resource"]}
onClick={() => this.apportion(record)}
>
分配资源
</span>
<span
class="primary pointer"
v-hasPermi={["system:role:menu"]}
onClick={() => this.apportionMenu(record)}
>
分配菜单
</span>
<span
class="primary pointer"
v-hasPermi={["system:role:edit"]}
onClick={() => this.handleEdit(record)}
>
编辑
</span>
<span
class="delete pointer"
v-hasPermi={["system:role:remove"]}
onClick={() => this.handleDel(record.id)}
>
删除
</span>
</a-space>
);
},
},
],
name: "",
page: 1,
size: 10,
total: 0,
pageSizeOptions,
searchValue: "", // 搜索
tableData: [],
tableData: [], // 表格数据
selectedRowKeys: [],
dict: {}, // 字典
addVisible: false,
resVisible: false,
resDimListVisible: false,
title: "新增角色",
menuShow: false,
roleInfo: {},
menuList: [],
resShow: false,
};
},
created() {
this.getMenuList();
this.getRoleList();
},
methods: {
// 获取角色列表
async getMenuList() {
const res = await getMenuList({
page: 1,
size: -1,
});
if (res.data.code === 1) {
let { data } = res.data.data;
this.menuList = data;
}
},
async getRoleList() {
this.loading = true;
let res = await getRoleList({
current: this.current,
const res = await getRoleList({
name: this.name,
page: this.page,
size: this.size,
name: this.searchValue,
});
this.loading = false;
if (res.data.code == 1) {
if (res.data.code === 1) {
let { data, total } = res.data.data;
if (!data.length && this.current > 1) {
this.current -= 1;
if (!data.length && this.page > 1) {
this.page -= 1;
this.getRoleList();
}
this.tableData = data;
this.total = total;
}
},
// 新增
handleAdd() {
this.title = "新增角色";
this.$refs.AddRole.onAdd();
this.addVisible = true;
},
// 搜索
onSearch() {
this.current = 1;
handleSearch() {
this.page = 1;
this.getRoleList();
},
// 分页
handleChange(num) {
this.current = num;
handleResetSearch() {
this.name = "";
this.page = 1;
this.getRoleList();
},
// 改变每页显示数量
showSizeChange(current, size) {
this.current = current;
this.size = size;
this.getRoleList();
handleAddRole() {
this.title = "新增";
this.$refs.AddRole.onAdd();
this.showAddRole = true;
},
// 选择
onSelectChange(keys) {
this.selectedRowKeys = keys;
handleEdit(row) {
this.title = "编辑";
this.$refs.AddRole.onEdit(row);
this.showAddRole = true;
},
// 批量删除
handleDelAll() {
handleBatchDel() {
if (!this.selectedRowKeys.length) {
this.$message.warn("请先勾选数据");
this.$message.warning("请先勾选数据");
return;
}
let ids = this.selectedRowKeys.join(",");
this.handleDel(ids);
},
// 编辑
handleEdit(row) {
this.title = "编辑角色";
this.$refs.AddRole.onEdit(row);
this.addVisible = true;
onSelectChange(keys) {
this.selectedRowKeys = keys;
},
// 删除
handleDel(id) {
let _this = this;
this.$confirm({
title: "系统提示",
content: "删除不可恢复,确定要删除吗?",
okText: "确定",
title: "系统提示:",
content: "删除不可恢复,是否继续?",
okType: "danger",
cancelText: "取消",
centered: true,
icon: "exclamation-circle",
maskClosable: true,
async onOk() {
icon: "exclamation-circle",
onOk: async () => {
let res = await delRole({ id });
if (res.data.code == 1) {
_this.$message.success(res.data.msg);
_this.getRoleList();
let { code } = res.data;
if (code === 1) {
this.$message.success("删除成功");
this.getRoleList();
}
},
onCancel() {
console.log("Cancel");
},
onCancel() {},
});
},
// 分配资源
apportion(row) {
this.$refs.ApportionRes.onAdd(row.id);
this.resVisible = true;
this.resShow = true;
},
// 资源维度
handleResDim(row) {
this.$refs.ResDimList.getRoleInfo(row);
this.resDimListVisible = true;
apportionMenu(row) {
this.roleInfo = row;
this.$refs.ApportionMenu.onAdd(row);
this.menuShow = true;
},
},
};
</script>
<style lang="less" scoped>
.role-container {
width: 100%;
height: 100%;
}
</style>
<style lang="less" scoped></style>
......@@ -41,7 +41,7 @@ import { saveRole } from "@/services/system";
export default {
components: {},
props: {
addVisible: {
show: {
required: true,
type: Boolean,
default: false,
......@@ -68,10 +68,10 @@ export default {
computed: {
Visible: {
get() {
return this.addVisible;
return this.show;
},
set(val) {
this.$emit("update:addVisible", val);
this.$emit("update:show", val);
},
},
},
......@@ -98,7 +98,7 @@ export default {
this.loading = false;
if (code == 1) {
this.$message.success(msg);
this.$emit("addSuccess");
this.$emit("success");
this.handleCancel();
}
}
......
<template>
<div>
<a-modal
title="分配角色菜单"
:visible="Visible"
@cancel="handleCancel"
:maskClosable="false"
>
<a-button slot="footer" @click="handleReset">重置</a-button>
<a-button
slot="footer"
type="primary"
:loading="loading"
@click="handleOk"
>确定</a-button
>
<a-form-model
:model="form"
ref="form"
:rules="rules"
:label-col="{ span: 5 }"
:wrapper-col="{ span: 19 }"
>
<a-form-model-item label="角色名称">
<a-input
readOnly
:value="roleInfo.name"
placeholder="请输入角色名称"
></a-input>
</a-form-model-item>
<a-form-model-item class="menu-box" label="菜单权限">
<div>
<a-checkbox v-model="isExpand" @change="onChangeIsExpand">
展开/折叠
</a-checkbox>
<a-checkbox v-model="isNodeAll" @change="onChangeIsNodeAll">
全选/全不选
</a-checkbox>
<a-checkbox v-model="checkStrictly"> 父子联动 </a-checkbox>
<a-tree
ref="tree"
class="tree-border"
:checkedKeys="{
checked: this.form.menuIdList,
}"
:selectable="false"
:replaceFields="replaceFields"
:checkStrictly="true"
:tree-data="menuTree"
:expandedKeys.sync="expandedKeys"
checkable
@check="checkTree"
/>
</div>
</a-form-model-item>
</a-form-model>
</a-modal>
</div>
</template>
<script>
import { saveRoleMenu, getRoleMenu } from "@/services/system";
import { buildTree, getSubtreeIdsById } from "@/utils/util";
export default {
components: {},
props: {
show: {
required: true,
type: Boolean,
default: false,
},
roleInfo: {
type: Object,
required: true,
default: () => {},
},
menuList: {
type: Array,
required: true,
default: () => [],
},
},
data() {
return {
replaceFields: {
children: "children",
title: "name",
key: "id",
},
expandedKeys: [],
loading: false,
isExpand: false, // 折叠、展开
isNodeAll: false, // 全选、全不选
checkStrictly: true, // 父子联动
plainOptions: [
{
label: "展开/折叠",
value: "1",
},
{
label: "全选/全不选",
value: "2",
},
{
label: "父子联动",
value: "3",
},
],
form: {
menuIdList: [],
roleId: "",
},
rules: {},
};
},
computed: {
Visible: {
get() {
return this.show;
},
set(val) {
this.$emit("update:show", val);
},
},
menuTree() {
return buildTree(this.menuList) || [];
},
},
created() {},
methods: {
async getRoleMenu() {
let res = await getRoleMenu({
page: 1,
size: -1,
roleId: this.form.roleId,
});
if (res.data.code === 1) {
let { data } = res.data;
let ids = this.getRoleMenuIdList(data);
this.form.menuIdList = ids;
}
},
// 获取角色菜单id列表
getRoleMenuIdList(data) {
let result = [];
let getData = (list) => {
list.forEach((item) => {
item.checked && result.push(item.id);
if (item.children && item.children.length > 0) {
getData(item.children);
}
});
};
getData(data);
return result;
},
// 新增
onAdd(row) {
Object.assign(this.form, this.$options.data().form);
// this.form.id && this.$delete(this.form, "id");
this.form.roleId = row.id;
this.getRoleMenu();
},
// 编辑
onEdit(row) {
this.$nextTick(() => {
this.form = { ...row };
});
},
// 保存
handleOk() {
this.$refs.form.validate(async (valid) => {
if (valid) {
this.loading = true;
let res = await saveRoleMenu(this.form);
let { code, msg } = res.data;
this.loading = false;
if (code == 1) {
this.$message.success(msg);
this.$emit("success");
this.handleCancel();
}
}
});
},
// 重置
handleReset() {
this.$refs.form.resetFields();
},
// 关闭
handleCancel() {
this.$refs.form.resetFields();
this.isExpand = false; // 折叠、展开
this.isNodeAll = false; // 全选、全不选
this.checkStrictly = true; // 父子联动
this.Visible = false;
},
// 手动控制父子联动
checkTree({ checked }, e) {
let parentIdKeys = [];
let childrendKeys = [];
this.form.menuIdList = checked;
let isChecked = e.checked;
let curKey = e.node.eventKey;
if (this.checkStrictly) {
parentIdKeys = this.getTreeParentIds(curKey);
childrendKeys = getSubtreeIdsById(this.menuTree, curKey);
let allKeys = [...new Set([...parentIdKeys, ...childrendKeys])];
if (isChecked) {
this.form.menuIdList = [
...new Set([...this.form.menuIdList, ...allKeys]),
];
} else {
this.form.menuIdList = this.form.menuIdList.filter(
(v) => !allKeys.includes(v)
);
}
} else {
if (isChecked) {
this.form.menuIdList.push(curKey);
} else {
this.form.menuIdList = this.form.menuIdList.filter(
(v) => v != curKey
);
}
}
},
onChangeIsExpand() {
if (this.isExpand) {
this.expandedKeys = this.getParentIds(this.menuTree);
} else {
this.expandedKeys = [];
}
},
onChangeIsNodeAll() {
if (this.isNodeAll) {
let ids = this.menuList.map((v) => v.id);
this.$set(this.form, "menuIdList", ids || []);
} else {
this.$set(this.form, "menuIdList", []);
}
},
getParentIds(arr) {
const ids = [];
function traverse(nodes) {
nodes.forEach((node) => {
if (node.children && node.children.length > 0) {
ids.push(node.id);
traverse(node.children);
}
});
}
traverse(arr);
return ids;
},
getTreeParentIds(id) {
const ids = [];
let item = this.menuList.find((v) => v.id == id);
if (!item) return ids;
let traverse = (parentId) => {
let parentItem = this.menuList.find((v) => v.id == parentId);
if (parentItem) {
ids.push(parentItem.id);
traverse(parentItem.parentId);
}
};
traverse(item.parentId);
return ids;
},
},
};
</script>
<style lang="less" scoped>
/deep/.ant-modal-body {
max-height: 600px;
overflow: auto;
}
.menu-box {
align-items: flex-start !important;
}
.tree-border {
margin-top: 5px;
border: 1px solid #e5e6e7;
background: #fff none;
border-radius: 4px;
}
</style>
......@@ -20,7 +20,7 @@
</a-checkbox>
</div>
<a-checkbox-group
style="width:100%"
style="width: 100%"
:value="form.resourceIdList"
@change="onChange($event, v)"
>
......@@ -52,7 +52,7 @@ import {
} from "@/services/system";
export default {
props: {
visible: {
show: {
required: true,
type: Boolean,
default: false,
......@@ -72,10 +72,10 @@ export default {
computed: {
Visible: {
get() {
return this.visible;
return this.show;
},
set(val) {
this.$emit("update:visible", val);
this.$emit("update:show", val);
},
},
},
......@@ -109,7 +109,7 @@ export default {
groupByAuth(list) {
let group = {};
list.forEach((item) => {
let name = item.name.split("-")[0];
let name = item.groupName;
if (!group[name]) {
group[name] = {
indeterminate: false,
......
......@@ -83,7 +83,7 @@ export default {
return {
columns,
loading: false,
current: 1,
page: 1,
size: 10,
total: 0,
pageSizeOptions,
......@@ -99,7 +99,7 @@ export default {
async getSystemLogsList() {
this.loading = true;
let res = await getSystemLogsList({
page: this.current,
page: this.page,
size: this.size,
requestUrl: this.searchValue,
});
......@@ -112,7 +112,7 @@ export default {
},
// 搜索
onSearch() {
this.current = 1;
this.page = 1;
this.getSystemLogsList();
},
},
......
<template>
<div class="task-set">
<div class="control flex aic jcb mb15 pdr6">
<div>
<a-button type="primary" style="margin-right: 10px" @click="handleAdd"
<a-space>
<a-button
type="primary"
v-hasPermi="['system:task:add']"
@click="handleAdd"
>新增</a-button
>
<a-button type="danger" @click="handleDelAll">批量删除</a-button>
</div>
<a-button
type="danger"
v-hasPermi="['system:task:remove']"
@click="handleDelAll"
>批量删除</a-button
>
</a-space>
<div class="search-box">
<a-input-search
placeholder="请输入任务名搜索"
......@@ -53,13 +61,13 @@
<template slot="action" slot-scope="{ record }">
<a-space size="middle">
<span
href="javascript:;"
v-hasPermi="['system:task:edit']"
class="primary pointer"
@click="handleEdit(record)"
>编辑</span
>
<span
href="javascript:;"
v-hasPermi="['system:task:remove']"
class="delete pointer"
@click="handleDel(record.id)"
>删除</span
......
<template>
<div class="user-container">
<div class="user-page">
<div class="control flex aic jcb mb15 pdr6">
<div>
<!-- <a-button type="primary" style="margin-right: 10px" @click="handleAdd"
>新增</a-button
>
<a-button type="danger" @click="handleDelAll">批量删除</a-button> -->
</div>
<div class="search-box">
<a-space>
<a-input
placeholder="请输入登录名搜索"
v-model="searchForm.loginName"
allowClear
/>
<a-input
placeholder="请输入用户姓名搜索"
v-model="searchForm.realName"
allowClear
/>
<a-button type="primary" @click="onSearch">搜索</a-button>
<a-button @click="resetSearch">重置</a-button>
</a-space>
</div>
</div>
<!-- 表格 -->
<div class="table-content">
<a-table
:loading="loading"
bordered
:scroll="{ y: 590 }"
:columns="columns"
:pagination="{
showTotal: (total) => `共 ${total} 条`,
current: current,
total: total,
pageSize: size,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: pageSizeOptions,
onChange: handleChange,
onShowSizeChange: showSizeChange,
}"
:data-source="tableData"
:rowKey="(record) => record.id"
>
<!-- 序号 -->
<span slot="num" slot-scope="text, record, index">{{
(current - 1) * size + index + 1
}}</span>
<div></div>
<!-- 操作 -->
<template slot="action" slot-scope="text">
<a-space size="middle">
<span class="primary pointer" @click="changeRole(text)"
>分配角色</span
>
</a-space>
</template>
</a-table>
<a-space>
<a-select style="width: 120px" placeholder="请选择" v-model="type">
<a-select-option v-for="(v, key) in typeDict" :key="key" :value="key">
{{ v }}
</a-select-option>
</a-select>
<a-input placeholder="请输入关键字" v-model="keyWord" />
<a-button type="primary" @click="handleSearch">搜索</a-button>
<a-button @click="handleResetSearch">重置</a-button>
</a-space>
</div>
<y-table
:columns="columns"
:data="tableData"
:pageSize.sync="size"
:page.sync="page"
:total="total"
:loading="loading"
@changePagination="getUserList"
>
</y-table>
<!-- 分配角色 -->
<AddUserRole
ref="AddUserRole"
:addVisible.sync="addVisible"
:roleList="roleList"
@addSuccess="getUserList"
:show.sync="show"
:dict="dict"
@success="getUserList"
></AddUserRole>
</div>
</template>
<script>
import { getUserList, getRoleList } from "@/services/system";
import { pageSizeOptions } from "@/config/pageConfig.js";
import YTable from "@/components/YTable.vue";
import AddUserRole from "./modal/AddUserRole.vue";
import { mapState } from "vuex";
import { getUserList } from "@/services/system";
let typeDict = {
loginName: "按登录名",
realName: "按用户姓名",
mobile: "按手机号码",
};
export default {
components: { AddUserRole },
components: { YTable, AddUserRole },
data() {
const columns = [
{
title: "序号",
dataIndex: "num",
width: "65px",
scopedSlots: {
customRender: "num",
return {
typeDict,
loading: false,
show: false,
columns: [
{
title: "序号",
dataIndex: "num",
width: "65px",
customRender: (text, record, index) => {
return (this.page - 1) * this.size + index + 1;
},
},
},
{
title: "登录名",
dataIndex: "loginName",
},
{
title: "用户姓名",
dataIndex: "realName",
},
{
title: "所属角色",
dataIndex: "roleIds",
customRender: (text) => {
if (text && this.roleList.length) {
let obj = {};
this.roleList.forEach((v) => {
obj[v.id] = v.name;
});
let roleIds = text.split(",");
return roleIds.map((v) => {
return <a-tag>{obj[v]}</a-tag>;
});
}
{
title: "登录名",
dataIndex: "loginName",
},
},
{
title: "状态",
dataIndex: "status",
customRender: (text) => {
return <a-tag>{this.dict.status[text]}</a-tag>;
{
title: "用户姓名",
dataIndex: "realName",
},
},
{
title: "操作",
width: "120px",
scopedSlots: { customRender: "action" },
},
];
return {
columns,
loading: false,
current: 1,
{
title: "手机号码",
dataIndex: "mobile",
},
{
title: "所属角色",
dataIndex: "roleIds",
customRender: (text) => {
if (text) {
return text.split(",").map((v) => {
return (
<a-tag style="margin-right:4px;margin-bottom:4px">
{this.dict.roleIds[v]}
</a-tag>
);
});
}
},
},
{
title: "状态",
dataIndex: "status",
customRender: (text) => {
if (this.dict.status) {
return this.dict.status[text];
}
},
},
{
title: "创建时间",
dataIndex: "createTime",
},
{
title: "操作",
width: "100px",
customRender: (text, record) => {
return (
<span
class="primary pointer"
v-hasPermi={["system:user:role"]}
onClick={() => this.apportion(record)}
>
分配角色
</span>
);
},
},
],
type: "loginName",
keyWord: "",
page: 1,
size: 10,
total: 0,
pageSizeOptions,
searchForm: {
loginName: "",
realName: "",
},
tableData: [],
roleList: [], // 角色列表
selectedRowKeys: [],
dict: {}, // 字典
addVisible: false,
title: "新增",
loginNames: ["admin", "administrator1", "Administrator"],
tableData: [], // 表格数据
dict: {},
roleList: [],
};
},
computed: {
...mapState("site", ["userInfo"]),
},
created() {
this.getRoleList();
this.getUserList();
},
methods: {
// 获取角色列表
async getRoleList() {
let res = await getRoleList({
page: 1,
size: -1,
});
if (res.data.code == 1) {
let { data } = res.data.data;
this.roleList = data;
}
},
// 获取用户列表
async getUserList() {
this.loading = true;
let res = await getUserList({
page: this.current,
let obj = {
page: this.page,
size: this.size,
...this.searchForm,
});
};
obj[this.type] = this.keyWord;
const res = await getUserList(obj);
this.loading = false;
if (res.data.code == 1) {
let { data, total, dict } = res.data.data;
if (!data.length && this.current > 1) {
this.current -= 1;
this.getUserList();
}
let { name } = this.userInfo;
if (this.loginNames.includes(name)) {
this.tableData = data;
this.total = total;
} else {
this.tableData = data.filter((v) => {
return !this.loginNames.includes(v.loginName);
});
this.total = total - this.loginNames.length;
}
if (res.data.code === 1) {
let {
dict,
data: { data, total },
} = res.data;
this.dict = dict;
this.tableData = data;
this.total = total;
}
},
// 新增
handleAdd() {
this.title = "新增";
this.$refs.AddParameter.onAdd();
this.addVisible = true;
},
// 搜索
onSearch() {
this.current = 1;
this.getUserList();
},
resetSearch() {
this.current = 1;
Object.assign(this.searchForm, this.$options.data().searchForm);
this.getUserList();
},
// 分页
handleChange(num) {
this.current = num;
handleSearch() {
this.page = 1;
this.getUserList();
},
// 改变每页显示数量
showSizeChange(current, size) {
this.current = current;
this.size = size;
handleResetSearch() {
this.type = "loginName";
this.keyWord = "";
this.page = 1;
this.getUserList();
},
// 分配角色
changeRole(row) {
apportion(row) {
this.show = true;
this.$refs.AddUserRole.onEdit(row);
this.addVisible = true;
},
},
};
</script>
<style lang="less" scoped>
.user-container {
.user-page {
width: 100%;
height: 100%;
}
......
......@@ -27,9 +27,12 @@
v-model="form.roleIds"
placeholder="请选择角色"
>
<a-select-option v-for="v in roleList" :key="v.id" :value="v.id">{{
v.name
}}</a-select-option>
<a-select-option
v-for="(v, key) in dict.roleIds"
:key="key"
:value="key"
>{{ v }}</a-select-option
>
</a-select>
</a-form-model-item>
</a-form-model>
......@@ -43,15 +46,15 @@ import { saveUser } from "@/services/system";
export default {
components: {},
props: {
addVisible: {
show: {
required: true,
type: Boolean,
default: false,
},
roleList: {
dict: {
required: true,
type: Array,
default: () => [],
type: Object,
default: () => {},
},
},
data() {
......@@ -68,10 +71,10 @@ export default {
computed: {
Visible: {
get() {
return this.addVisible;
return this.show;
},
set(val) {
this.$emit("update:addVisible", val);
this.$emit("update:show", val);
},
},
},
......@@ -87,7 +90,7 @@ export default {
this.$nextTick(() => {
this.form = { ...row };
if (this.form.roleIds) {
this.form.roleIds = this.form.roleIds.split(",").map(Number);
this.form.roleIds = this.form.roleIds.split(",");
} else {
this.form.roleIds = [];
}
......@@ -109,7 +112,7 @@ export default {
let { code, msg } = res.data;
if (code == 1) {
this.$message.success(msg);
this.$emit("addSuccess");
this.$emit("success");
this.handleCancel();
}
}
......
......@@ -128,8 +128,13 @@
</div>
<div class="on btn pdr6">
<div>
<a-button type="primary" @click="showModal">新增人员</a-button>
<a-dropdown>
<a-button
type="primary"
v-hasPermi="['personnel:add']"
@click="showModal"
>新增人员</a-button
>
<a-dropdown v-hasPermi="['personnel:more']">
<a-menu slot="overlay">
<a-menu-item key="1">
<a-upload
......@@ -258,13 +263,22 @@
<!-- 操作 -->
<span slot="action" slot-scope="{ record }">
<a-space>
<span class="primary pointer" @click="editModal(record)"
<span
class="primary pointer"
v-hasPermi="['personnel:edit']"
@click="editModal(record)"
>编辑</span
>
<span class="primary pointer" @click="changePwd(record)"
<span
class="primary pointer"
v-hasPermi="['personnel:editPwd']"
@click="changePwd(record)"
>修改密码</span
>
<span class="delete pointer" @click="handleDel(record.id)"
<span
class="delete pointer"
v-hasPermi="['personnel:remove']"
@click="handleDel(record.id)"
>删除</span
>
</a-space>
......
<template>
<exception-page
home-route="/website"
:home-route="homeRoute"
:style="`min-height: ${minHeight}`"
type="404"
/>
......@@ -14,12 +14,15 @@ export default {
components: { ExceptionPage },
computed: {
...mapState("setting", ["pageMinHeight"]),
...mapState("site", ["menus"]),
minHeight() {
return this.pageMinHeight ? this.pageMinHeight + "px" : "100vh";
},
homeRoute() {
return this.menus[0].path;
},
},
};
</script>
<style scoped lang="less">
</style>
<style scoped lang="less"></style>
// import TabsView from "@/layouts/tabs/TabsView";
// import BlankView from "@/layouts/BlankView";
import Layouts from "@/layouts/Layouts";
// import Layouts from "@/layouts/Layouts";
// import PageView from '@/layouts/PageView'
import NewPageLayout from "@/layouts/NewPageLayout";
// 路由配置
const options = {
......@@ -13,376 +14,415 @@ const options = {
},
{
path: "/",
name: "首页",
component: Layouts,
redirect: "/website",
name: "/",
component: NewPageLayout,
redirect: "/jump",
children: [
{
path: "/website",
name: "站点管理",
meta: {
icon: "bank",
},
component: () => import("@/pages/basicset/site/website"),
},
{
path: "/business",
meta: {
icon: "book",
},
component: () => import("@/pages/basicset/business/Index"),
children: [
{
path: "",
name: "业务事项管理",
meta: {
icon: "book",
invisible: true,
},
component: () => import("@/pages/basicset/business/business"),
redirect: "/business/businessmanage",
children: [
// 业务管理
{
path: "businessmanage",
meta: {
invisible: true,
},
component: () =>
import(
"@/pages/basicset/business/components/businessTabs1"
),
},
// 事项管理
{
path: "mattermanage",
meta: {
invisible: true,
},
component: () =>
import(
"@/pages/basicset/business/components/businessTabs2"
),
},
// 业务事项关联
{
path: "businessinmanage",
meta: {
invisible: true,
},
component: () =>
import(
"@/pages/basicset/business/components/businessTabs3"
),
},
// 办事指南事项管理
{
path: "workguide",
meta: {
invisible: true,
},
component: () =>
import(
"@/pages/basicset/business/components/businessTabs4"
),
},
],
},
{
path: "addmatter",
name: "新增事项",
component: () => import("@/pages/basicset/addmatter/AddMatter"),
meta: { invisible: true },
},
{
path: "synopsis",
name: "事项概要",
component: () => import("@/pages/basicset/addmatter/Synopsis"),
meta: { invisible: true },
},
],
},
{
path: "/department",
meta: {
icon: "audit",
},
component: () => import("@/pages/basicset/dept/Index"),
children: [
{
path: "",
name: "部门及窗口管理",
component: () => import("@/pages/basicset/dept/department"),
meta: { invisible: true, keepAlive: true },
},
{
path: "adddepartment",
name: "新增窗口事项",
meta: {
invisible: true,
},
component: () => import("@/pages/basicset/dept/addWindowMatter"),
},
],
},
{
path: "/personnel",
name: "工作人员管理",
meta: {
icon: "idcard",
},
component: () => import("@/pages/basicset/workman/personnel"),
},
{
path: "/festival",
name: "节假日管理",
meta: {
icon: "carry-out",
},
component: () => import("@/pages/basicset/holiday/festival"),
},
{
path: "/deploy",
name: "部署模块管理",
meta: {
icon: "appstore",
roles: ["admin"],
},
component: () => import("@/pages/basicset/deploy/Index"),
redirect: "/deploy/manage",
path: "/appmarket/appdetails",
name: "appdetails",
component: () => import("@/pages/basicset/appmarket/AppDetails"),
redirect: "/appmarket/appdetails/appdetailspage",
children: [
{
path: "manage",
name: "模块管理",
component: () => import("@/pages/basicset/deploy/deploy"),
meta: {
invisible: true,
},
},
{
path: "statement",
name: "报表管理",
meta: {
invisible: true,
path: "appdetailspage",
component: () =>
import("@/pages/basicset/appmarket/components/AppDetailsPage"),
meta:{
activeMenu:'/appmarket'
},
component: () => import("@/pages/basicset/deploy/Statement"),
},
],
},
{
path: "/hall",
name: "大厅管理",
meta: {
icon: "gateway",
},
component: () => import("@/pages/basicset/hall/Hall"),
redirect: "/hall/hallmanage",
children: [
{
path: "hallmanage",
name: "",
path: "dataupdate",
component: () =>
import("@/pages/basicset/hall/hallmanage/HallManage.vue"),
meta: {
invisible: true,
import("@/pages/basicset/appmarket/components/DataUpdate"),
meta:{
activeMenu:'/appmarket'
},
},
{
path: "hallwindow",
name: "大厅窗口管理",
meta: {
invisible: true,
},
path: "fieldconfig",
component: () =>
import("@/pages/basicset/hall/hallwindow/HallWindow.vue"),
import("@/pages/basicset/appmarket/components/FieldConfig"),
meta:{
activeMenu:'/appmarket'
},
},
],
},
{
path: "/surface",
component: () => import("@/pages/basicset/surface/index"),
meta: {
icon: "skin",
},
children: [
{
path: "",
name: "皮肤管理",
component: () => import("@/pages/basicset/surface/surface"),
meta: { invisible: true },
},
{
path: "addsurfacetemplate",
name: "新增皮肤模板",
component: () =>
import("@/pages/basicset/surface/AddSurfaceTemplate"),
meta: { invisible: true },
},
],
},
{
path: "/configurat",
name: "短信配置",
meta: {
icon: "mail",
},
component: () => import("@/pages/basicset/sms/configurat"),
},
{
path: "/social",
name: "社保配置",
meta: {
icon: "contacts",
},
component: () => import("@/pages/basicset/social/Social"),
},
{
path: "/appmarket",
component: () => import("@/pages/basicset/appmarket/Index"),
meta: {
icon: "shop",
},
children: [
{
path: "",
name: "应用集市",
component: () => import("@/pages/basicset/appmarket/AppMarket"),
meta: { invisible: true },
redirect: "/appmarket/terminalapp",
children: [
{
path: "terminalapp",
component: () =>
import("@/pages/basicset/appmarket/components/TerminalApp"),
meta: {
invisible: true,
// keepAlive: true,
},
},
{
path: "moveapp",
component: () =>
import("@/pages/basicset/appmarket/components/MoveApp"),
meta: {
invisible: true,
// keepAlive: true,
},
},
{
path: "blackapp",
component: () =>
import("@/pages/basicset/appmarket/components/BlackApp"),
meta: {
invisible: true,
},
},
{
path: "appTheme",
component: () =>
import("@/pages/basicset/appmarket/components/AppTheme"),
meta: {
invisible: true,
},
},
],
},
{
path: "appdetails",
name: "应用详情",
component: () => import("@/pages/basicset/appmarket/AppDetails"),
meta: { invisible: true },
redirect: "/appmarket/appdetails/appdetailspage",
children: [
{
path: "appdetailspage",
component: () =>
import(
"@/pages/basicset/appmarket/components/AppDetailsPage"
),
meta: {
invisible: true,
},
},
{
path: "dataupdate",
component: () =>
import("@/pages/basicset/appmarket/components/DataUpdate"),
meta: {
invisible: true,
},
},
{
path: "fieldconfig",
component: () =>
import("@/pages/basicset/appmarket/components/FieldConfig"),
meta: {
invisible: true,
},
},
],
},
],
},
{
path: "/system",
name: "系统设置",
component: () => import("@/pages/basicset/system/System"),
meta: {
icon: "global",
},
redirect: "system/parameter",
children: [
{
path: "user",
name: "用户管理",
component: () => import("@/pages/basicset/system/user/User"),
meta: { invisible: true },
},
{
path: "role",
name: "角色管理",
component: () => import("@/pages/basicset/system/role/Role"),
meta: { invisible: true },
},
{
path: "resource",
name: "资源管理",
component: () =>
import("@/pages/basicset/system/resourceManage/Resource"),
meta: { invisible: true },
},
{
path: "dimension",
name: "维度管理",
component: () =>
import("@/pages/basicset/system/dimension/Dimension"),
meta: { invisible: true },
},
{
path: "parameter",
name: "系统参数",
component: () =>
import("@/pages/basicset/system/parameter/Parameter"),
meta: { invisible: true },
},
{
path: "task",
name: "任务信息",
component: () => import("@/pages/basicset/system/task/TaskSet"),
meta: { invisible: true },
},
{
path: "systemlogs",
name: "操作日志",
component: () =>
import("@/pages/basicset/system/systemlogs/SystemLogs"),
meta: { invisible: true },
},
],
},
// {
// path: "/website",
// name: "站点管理",
// meta: {
// icon: "bank",
// },
// component: () => import("@/pages/basicset/site/website"),
// },
// {
// path: "/business",
// meta: {
// icon: "book",
// },
// component: () => import("@/pages/basicset/business/Index"),
// children: [
// {
// path: "",
// name: "业务事项管理",
// meta: {
// icon: "book",
// invisible: true,
// },
// component: () => import("@/pages/basicset/business/business"),
// redirect: "/business/businessmanage",
// children: [
// // 业务管理
// {
// path: "businessmanage",
// meta: {
// invisible: true,
// },
// component: () =>
// import(
// "@/pages/basicset/business/components/businessTabs1"
// ),
// },
// // 事项管理
// {
// path: "mattermanage",
// meta: {
// invisible: true,
// },
// component: () =>
// import(
// "@/pages/basicset/business/components/businessTabs2"
// ),
// },
// // 业务事项关联
// {
// path: "businessinmanage",
// meta: {
// invisible: true,
// },
// component: () =>
// import(
// "@/pages/basicset/business/components/businessTabs3"
// ),
// },
// // 办事指南事项管理
// {
// path: "workguide",
// meta: {
// invisible: true,
// },
// component: () =>
// import(
// "@/pages/basicset/business/components/businessTabs4"
// ),
// },
// ],
// },
// {
// path: "addmatter",
// name: "新增事项",
// component: () => import("@/pages/basicset/addmatter/AddMatter"),
// meta: { invisible: true },
// },
// {
// path: "synopsis",
// name: "事项概要",
// component: () => import("@/pages/basicset/addmatter/Synopsis"),
// meta: { invisible: true },
// },
// ],
// },
// {
// path: "/department",
// meta: {
// icon: "audit",
// },
// component: () => import("@/pages/basicset/dept/Index"),
// children: [
// {
// path: "",
// name: "部门及窗口管理",
// component: () => import("@/pages/basicset/dept/department"),
// meta: { invisible: true, keepAlive: true },
// },
// {
// path: "adddepartment",
// name: "新增窗口事项",
// meta: {
// invisible: true,
// },
// component: () => import("@/pages/basicset/dept/addWindowMatter"),
// },
// ],
// },
// {
// path: "/personnel",
// name: "工作人员管理",
// meta: {
// icon: "idcard",
// },
// component: () => import("@/pages/basicset/workman/personnel"),
// },
// {
// path: "/festival",
// name: "节假日管理",
// meta: {
// icon: "carry-out",
// },
// component: () => import("@/pages/basicset/holiday/festival"),
// },
// {
// path: "/deploy",
// name: "部署模块管理",
// meta: {
// icon: "appstore",
// roles: ["admin"],
// },
// component: () => import("@/pages/basicset/deploy/Index"),
// redirect: "/deploy/manage",
// children: [
// {
// path: "manage",
// name: "模块管理",
// component: () => import("@/pages/basicset/deploy/deploy"),
// meta: {
// invisible: true,
// },
// },
// {
// path: "statement",
// name: "报表管理",
// meta: {
// invisible: true,
// },
// component: () => import("@/pages/basicset/deploy/Statement"),
// },
// ],
// },
// {
// path: "/hall",
// name: "大厅管理",
// meta: {
// icon: "gateway",
// },
// component: () => import("@/pages/basicset/hall/Hall"),
// redirect: "/hall/hallmanage",
// children: [
// {
// path: "hallmanage",
// name: "",
// component: () =>
// import("@/pages/basicset/hall/hallmanage/HallManage.vue"),
// meta: {
// invisible: true,
// },
// },
// {
// path: "hallwindow",
// name: "大厅窗口管理",
// meta: {
// invisible: true,
// },
// component: () =>
// import("@/pages/basicset/hall/hallwindow/HallWindow.vue"),
// },
// ],
// },
// {
// path: "/surface",
// component: () => import("@/pages/basicset/surface/index"),
// meta: {
// icon: "skin",
// },
// children: [
// {
// path: "",
// name: "皮肤管理",
// component: () => import("@/pages/basicset/surface/surface"),
// meta: { invisible: true },
// },
// {
// path: "addsurfacetemplate",
// name: "新增皮肤模板",
// component: () =>
// import("@/pages/basicset/surface/AddSurfaceTemplate"),
// meta: { invisible: true },
// },
// ],
// },
// {
// path: "/configurat",
// name: "短信配置",
// meta: {
// icon: "mail",
// },
// component: () => import("@/pages/basicset/sms/configurat"),
// },
// {
// path: "/social",
// name: "社保配置",
// meta: {
// icon: "contacts",
// },
// component: () => import("@/pages/basicset/social/Social"),
// },
// {
// path: "/appmarket",
// component: () => import("@/pages/basicset/appmarket/Index"),
// meta: {
// icon: "shop",
// },
// children: [
// {
// path: "",
// name: "应用集市",
// component: () => import("@/pages/basicset/appmarket/AppMarket"),
// meta: { invisible: true },
// redirect: "/appmarket/terminalapp",
// children: [
// {
// path: "terminalapp",
// component: () =>
// import("@/pages/basicset/appmarket/components/TerminalApp"),
// meta: {
// invisible: true,
// // keepAlive: true,
// },
// },
// {
// path: "moveapp",
// component: () =>
// import("@/pages/basicset/appmarket/components/MoveApp"),
// meta: {
// invisible: true,
// // keepAlive: true,
// },
// },
// {
// path: "blackapp",
// component: () =>
// import("@/pages/basicset/appmarket/components/BlackApp"),
// meta: {
// invisible: true,
// },
// },
// {
// path: "appTheme",
// component: () =>
// import("@/pages/basicset/appmarket/components/AppTheme"),
// meta: {
// invisible: true,
// },
// },
// ],
// },
// {
// path: "appdetails",
// name: "应用详情",
// component: () => import("@/pages/basicset/appmarket/AppDetails"),
// meta: { invisible: true },
// redirect: "/appmarket/appdetails/appdetailspage",
// children: [
// {
// path: "appdetailspage",
// component: () =>
// import(
// "@/pages/basicset/appmarket/components/AppDetailsPage"
// ),
// meta: {
// invisible: true,
// },
// },
// {
// path: "dataupdate",
// component: () =>
// import("@/pages/basicset/appmarket/components/DataUpdate"),
// meta: {
// invisible: true,
// },
// },
// {
// path: "fieldconfig",
// component: () =>
// import("@/pages/basicset/appmarket/components/FieldConfig"),
// meta: {
// invisible: true,
// },
// },
// ],
// },
// ],
// },
// {
// path: "/system",
// name: "系统设置",
// component: () => import("@/pages/basicset/system/System"),
// meta: {
// icon: "global",
// },
// redirect: "system/parameter",
// children: [
// {
// path: "user",
// name: "用户管理",
// component: () => import("@/pages/basicset/system/user/User"),
// meta: { invisible: true },
// },
// {
// path: "role",
// name: "角色管理",
// component: () => import("@/pages/basicset/system/role/Role"),
// meta: { invisible: true },
// },
// {
// path: "resource",
// name: "资源管理",
// component: () =>
// import("@/pages/basicset/system/resourceManage/Resource"),
// meta: { invisible: true },
// },
// {
// path: "dimension",
// name: "维度管理",
// component: () =>
// import("@/pages/basicset/system/dimension/Dimension"),
// meta: { invisible: true },
// },
// {
// path: "/system/menu",
// name: "菜单管理",
// component: () => import("@/pages/basicset/system/menu/Menu.vue"),
// meta: {
// icon: "sound",
// },
// },
// {
// path: "parameter",
// name: "系统参数",
// component: () =>
// import("@/pages/basicset/system/parameter/Parameter"),
// meta: { invisible: true },
// },
// {
// path: "task",
// name: "任务信息",
// component: () => import("@/pages/basicset/system/task/TaskSet"),
// meta: { invisible: true },
// },
// {
// path: "systemlogs",
// name: "操作日志",
// component: () =>
// import("@/pages/basicset/system/systemlogs/SystemLogs"),
// meta: { invisible: true },
// },
// ],
// },
],
},
],
......
import Vue from "vue";
import VueRouter from "vue-router";
import { formatRoutes } from "@/utils/routerUtil";
import { i18n } from "@/utils/i18n";
// import { i18n } from "@/utils/i18n";
import store from "@/store";
import { mergeI18nFromRoutes } from "@/utils/i18n";
import options from "./config";
import { generateRoutes } from "@/utils/util";
// import { mergeI18nFromRoutes } from "@/utils/i18n";
Vue.use(VueRouter);
//解决重复路由报错
const originalPush = VueRouter.prototype.push;
......@@ -31,7 +33,7 @@ const routes = [
];
formatRoutes(routes);
const router = new VueRouter({
routes,
routes: [...routes, ...options.routes],
});
// 不需要登录拦截的路由配置
......@@ -62,47 +64,74 @@ function initRouter() {
}
// 判断权限
function permission(router, role) {
if (router.meta && router.meta.roles) {
return router.meta.roles.includes(role);
} else {
return true;
}
}
// function permission(router, role) {
// if (router.meta && router.meta.roles) {
// return router.meta.roles.includes(role);
// } else {
// return true;
// }
// }
// 计算动态路由
function calcRouters(dynamicRouter, role) {
// 过滤
let res = dynamicRouter.filter((v) => {
// 判断是否有权限访问此路由
if (permission(v, role)) {
// 判断有没有子路由
// function calcRouters(dynamicRouter, role) {
// // 过滤
// let res = dynamicRouter.filter((v) => {
// // 判断是否有权限访问此路由
// if (permission(v, role)) {
// // 判断有没有子路由
// if (v.children) {
// // 递归
// v.children = calcRouters(v.children, role);
// }
// return true;
// } else {
// return false;
// }
// });
// return res;
// }
// 动态菜单
// function createMenus() {
// let role = store.getters["site/userInfo"].name;
// if (!role) return;
// let options = initRouter();
// let routesArr = calcRouters(options.routes, role);
// const rootRoute = routesArr.find((item) => item.path === "/");
// const menuRoutes = rootRoute && rootRoute.children;
// mergeI18nFromRoutes(i18n, menuRoutes);
// if (menuRoutes) {
// routesArr.forEach((v) => {
// router.addRoute(v);
// });
// store.commit("setting/setMenuData", menuRoutes);
// }
// }
// createMenus();
// 过滤菜单
export function menusFilter(arr) {
let router = arr.filter((v) => {
if (!v.hidden) {
if (v.children) {
// 递归
v.children = calcRouters(v.children, role);
v.children = menusFilter(v.children);
}
return true;
} else {
return false;
return v;
}
});
return res;
return router;
}
// 动态菜单
function createMenus() {
let role = store.getters["site/userInfo"].name;
if (!role) return;
let options = initRouter();
let routesArr = calcRouters(options.routes, role);
const rootRoute = routesArr.find((item) => item.path === "/");
const menuRoutes = rootRoute && rootRoute.children;
mergeI18nFromRoutes(i18n, menuRoutes);
if (menuRoutes) {
routesArr.forEach((v) => {
router.addRoute(v);
});
store.commit("setting/setMenuData", menuRoutes);
}
export function calcMenu() {
let menusList = store.getters["site/menusList"];
let dynamicRouter = generateRoutes(menusList);
dynamicRouter.forEach((v) => {
router.addRoute("/", v);
});
let menus = menusFilter(dynamicRouter);
store.commit("site/SET_menus", menus);
}
createMenus();
export { loginIgnore, initRouter, createMenus, router };
calcMenu();
export { loginIgnore, initRouter, router };
......@@ -382,6 +382,8 @@ module.exports = {
delete: `${BASE_URL}/base/role/delete`,
authList: `${BASE_URL}/base/role/auth/list`,
distributionSource: `${BASE_URL}/base/role/auth/distributionSource`,
editMenu: `${BASE_URL}/base/role/auth/editMenu`,
distributionMenu: `${BASE_URL}/base/role/auth/distributionMenu`,
},
// 资源
resource: {
......@@ -390,6 +392,17 @@ module.exports = {
save: `${BASE_URL}/base/resource/save`,
delete: `${BASE_URL}/base/resource/delete`,
refreshUrl: `${BASE_URL}/base/resource/refreshUrl`,
group: `${BASE_URL}/base//resource/group`,
},
// 菜单
menu: {
list: `${BASE_URL}/base/menu/list`,
info: `${BASE_URL}/base/menu/info`,
save: `${BASE_URL}/base/menu/save`,
delete: `${BASE_URL}/base/menu/delete`,
upOrDown: `${BASE_URL}/base/menu/upOrDown`,
treeselect: `${BASE_URL}/base/menu/treeselect`,
index: `${BASE_URL}/base/login/index`,
},
},
// 站点大厅
......
......@@ -94,6 +94,15 @@ export async function getRoleResourceList(data) {
export async function saveRoleResource(data) {
return request(system.role.distributionSource, METHOD.POST, data);
}
// 角色分配菜单
export async function saveRoleMenu(data) {
return request(system.role.distributionMenu, METHOD.POST, data);
}
// 获取角色菜单
export async function getRoleMenu(data) {
return request(system.role.editMenu, METHOD.POST, data);
}
/*
* 资源管理
*/
......@@ -117,6 +126,10 @@ export async function delResource(data) {
export async function refreshResource(data) {
return request(system.resource.refreshUrl, METHOD.POST, data);
}
// 获取资源分组
export async function getResourceGroupTree(data) {
return request(system.resource.group, METHOD.POST, data);
}
/*
* 维度管理
......@@ -155,3 +168,28 @@ export async function saveDimRes(data) {
export async function delDimRes(data) {
return request(system.dimensionResource.delete, METHOD.GET, data);
}
// 获取菜单列表
export function getMenuList(data) {
return request(system.menu.list, METHOD.POST, data);
}
// 新增菜单
export function saveMenu(data) {
return request(system.menu.save, METHOD.POST, data);
}
// 菜单排序
export function saveMenuSort(data) {
return request(system.menu.upOrDown, METHOD.POST, data);
}
// 删除菜单
export function delMenu(data) {
return request(system.menu.delete, METHOD.GET, data);
}
// 获取用户树形菜单
export function getMenuTree(data) {
return request(system.menu.treeselect, METHOD.POST, data);
}
// 获取用户登录树形菜单
export function getMenuIndex(data) {
return request(system.menu.index, METHOD.POST, data);
}
......@@ -16,6 +16,13 @@ export default {
curSkin: {}, // 当前选中预览皮肤
curSkinIndex: 0, // 当前选中皮肤索引
curProduct: {}, // 皮肤设置当前选中产品
siteInfo: {}, // 站点信息
permissions: [], // 按钮权限
menusList: [], // 原始菜单列表
menus: [], // 格式化菜单列表
routes: [], // 路由列表
secondaryRoutes: [], // 二级路由
activatedFirst: "", // 当前激活的一级菜单
},
getters: {
SiteTree(state) {
......@@ -42,8 +49,28 @@ export default {
imageResolutions(state) {
return state.imageResolution;
},
menusList(state) {
return state.menusList;
},
permissions(state) {
return state.permissions;
},
},
mutations: {
SET_menus(state, meuns) {
state.menus = meuns;
},
SET_secondaryRoutes(state, activatedFirst) {
const current = state.menus.find((menu) => menu.path === activatedFirst);
let arr = current?.children;
state.secondaryRoutes = arr || [];
},
SET_menusList(state, menusList) {
state.menusList = menusList;
},
SET_permissions(state, permissions) {
state.permissions = permissions;
},
SET_path(state, path) {
state.path = path;
},
......
......@@ -22,10 +22,10 @@ export function isRegExp(v) {
export function enquireScreen(call) {
const handler = {
match: function() {
match: function () {
call && call(true);
},
unmatch: function() {
unmatch: function () {
call && call(false);
},
};
......@@ -48,7 +48,7 @@ export const extractTree = (arrs, childs, attrArr) => {
}
let list = [];
const getObj = (arr) => {
arr.forEach(function(row) {
arr.forEach(function (row) {
let obj = {};
attrList.forEach((item) => {
obj[item] = row[item];
......@@ -111,3 +111,150 @@ export class SessionCrypto {
window.sessionStorage.removeItem(key);
}
}
// 构建树形数据
export function buildTree(data, idField = "id", parentIdField = "parentId") {
const idToItem = {};
data.forEach((item) => {
idToItem[item[idField]] = { ...item, children: [] };
});
const tree = [];
data.forEach((item) => {
const parentId = item[parentIdField];
if (parentId === null || parentId === 0) {
tree.push(idToItem[item[idField]]);
} else {
const parent = idToItem[parentId];
if (parent) {
// parent.children = [];
parent.children.push(idToItem[item[idField]]);
} else {
tree.push(idToItem[item[idField]]);
}
}
});
// 递归移除空的 children 数组
const removeEmptyChildren = (node) => {
if (node.children.length === 0) {
delete node.children;
} else {
node.children.forEach(removeEmptyChildren);
}
};
tree.forEach(removeEmptyChildren);
return tree;
}
// 生成路由
export const generateRoutes = (menuList) => {
let routers = menuList.map((item) => {
// 构造符合要求的结构
let path = item.url.charAt(0) === "/" ? item.url : "/" + item.url;
let name = item.url.replace(/^\//, "");
let activeMenu = item.activeDir
? "/" + item.activeDir.replace(/^\//, "")
: "";
let component = item.component ? item.component.replace(/^\//, "") : null;
const newItem = {
path,
name,
hidden: !!item.visible,
hideChildrenInMenu: !!item.hideChildrenInMenu,
component: () => import(`@/${component}`),
meta: {
title: item.name,
icon: item.imgPath,
keepAlive: !!item.cache,
activeMenu,
},
};
// 递归处理子节点
if (item.children && item.children.length > 0) {
newItem.children = generateRoutes(item.children);
// 如果存在子路由,默认重定向到第一个不是在菜单栏隐藏的子路由
let firstChild = newItem.children.find((v) => !v.hidden);
if (firstChild) {
newItem.redirect = firstChild.path;
}
}
return newItem;
});
return routers;
};
/**
* 过滤菜单按钮项并提取 menuType = 2 的项
* @param {Array} menuList - 菜单列表
* @param {Boolean} menuType - true 获取 menuType = 2 的项并返回为一维数组, false 剔除 menuType = 2 的项
* @param {Array} btnItems - 用于存储 menuType = 2 的项(递归使用)
* @returns {Array} - 返回提取到的 menuType = 2 的项(如果 menuType 为 true)或剔除 menuType = 2 的菜单
*/
export const filterBtn = (menuList, menuType = true, btnItems = []) => {
const result = menuList
.map((menu) => {
// 深拷贝对象,避免修改原数据
const newMenu = { ...menu };
if (newMenu.children && newMenu.children.length > 0) {
newMenu.children = filterBtn(newMenu.children, menuType, btnItems);
}
const btnItem = newMenu.menuType == 2;
if (menuType) {
if (btnItem) {
btnItems.push(newMenu);
}
return newMenu;
} else {
// 剔除 menuType = 2 的项
return !btnItem ? newMenu : null;
}
})
.filter((menu) => menu !== null); // 过滤掉 null 项
return menuType ? btnItems : result;
};
/**
* 从树形数据中查找指定 id 的节点
* @param {Array} tree 树形数据数组
* @param {number|string} targetId 要查找的 id 值
* @returns {Object|null} 找到的节点对象或 null
*/
export function findNodeById(tree, targetId) {
for (const node of tree) {
if (node.id === targetId) {
return node;
}
if (node.children && node.children.length > 0) {
const result = findNodeById(node.children, targetId);
if (result) {
return result;
}
}
}
return null;
}
/**
* 获取树形节点及其所有子节点的 id 列表
* @param {Object} node 树中的某个节点对象
* @returns {Array} 所有子节点的 id(包含当前节点)
*/
export function getAllChildIds(node) {
let ids = [node.id];
if (node.children && node.children.length > 0) {
for (const child of node.children) {
ids = ids.concat(getAllChildIds(child));
}
}
return ids;
}
// 找出树中某个节点及其所有子节点的 id
export function getSubtreeIdsById(tree, targetId) {
const targetNode = findNodeById(tree, targetId);
return targetNode ? getAllChildIds(targetNode) : [];
}
......@@ -6319,7 +6319,7 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2:
dependencies:
function-bind "^1.1.2"
he@1.2.x, he@^1.2.0:
he@1.2.x, he@^1.1.0, he@^1.2.0:
version "1.2.0"
resolved "https://registry.npmmirror.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
......@@ -11518,7 +11518,15 @@ vue-style-loader@^4.1.0, vue-style-loader@^4.1.2:
hash-sum "^1.0.2"
loader-utils "^1.0.2"
vue-template-compiler@^2.6.10, vue-template-compiler@^2.6.11:
vue-template-compiler@2.6.11:
version "2.6.11"
resolved "https://registry.npmmirror.com/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz#c04704ef8f498b153130018993e56309d4698080"
integrity sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA==
dependencies:
de-indent "^1.0.2"
he "^1.1.0"
vue-template-compiler@^2.6.10:
version "2.7.16"
resolved "https://registry.npmmirror.com/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz#c81b2d47753264c77ac03b9966a46637482bb03b"
integrity sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==
......@@ -11531,7 +11539,12 @@ vue-template-es2015-compiler@^1.9.0:
resolved "https://registry.npmmirror.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
vue@^2.5.3, vue@^2.6.10, vue@^2.6.11:
vue@2.6.11:
version "2.6.11"
resolved "https://registry.npmmirror.com/vue/-/vue-2.6.11.tgz#76594d877d4b12234406e84e35275c6d514125c5"
integrity sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ==
vue@^2.5.3, vue@^2.6.10:
version "2.7.16"
resolved "https://registry.npmmirror.com/vue/-/vue-2.7.16.tgz#98c60de9def99c0e3da8dae59b304ead43b967c9"
integrity sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment