Commit f53f9ea3 authored by 王晓旭's avatar 王晓旭

Merge branch 'reg' of http://gitlab.scsmile.cn/zxf/smart_gov_platform into reg

parents 9dc7aab9 02cfd887
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
"secure-ls": "^1.2.6", "secure-ls": "^1.2.6",
"v-viewer": "^1.6.4", "v-viewer": "^1.6.4",
"viser-vue": "^2.4.8", "viser-vue": "^2.4.8",
"vue": "^2.6.11", "vue": "2.6.11",
"vue-i18n": "^8.18.2", "vue-i18n": "^8.18.2",
"vue-jsonp": "^2.0.0", "vue-jsonp": "^2.0.0",
"vue-quill-editor": "^3.0.6", "vue-quill-editor": "^3.0.6",
...@@ -76,7 +76,7 @@ ...@@ -76,7 +76,7 @@
"less-loader": "^6.1.1", "less-loader": "^6.1.1",
"style-resources-loader": "^1.3.2", "style-resources-loader": "^1.3.2",
"vue-cli-plugin-style-resources-loader": "^0.1.4", "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", "vuepress": "^1.5.2",
"webpack-theme-color-replacer": "1.3.18", "webpack-theme-color-replacer": "1.3.18",
"whatwg-fetch": "^3.0.0" "whatwg-fetch": "^3.0.0"
......
import {loadRoutes, loadGuards, setAppOptions} from '@/utils/routerUtil' // import {loadRoutes, loadGuards, setAppOptions} from '@/utils/routerUtil'
import {loadInterceptors} from '@/utils/request' import { loadInterceptors } from "@/utils/request";
import guards from '@/router/guards' // import guards from '@/router/guards'
import interceptors from '@/utils/axios-interceptors' import interceptors from "@/utils/axios-interceptors";
/** /**
* 启动引导方法 * 启动引导方法
...@@ -11,15 +11,15 @@ import interceptors from '@/utils/axios-interceptors' ...@@ -11,15 +11,15 @@ import interceptors from '@/utils/axios-interceptors'
* @param i18n 应用的 vue-i18n 实例 * @param i18n 应用的 vue-i18n 实例
* @param i18n 应用的 message 实例 * @param i18n 应用的 message 实例
*/ */
function bootstrap({router, store, i18n, message}) { function bootstrap({ router, store, i18n, message }) {
// 设置应用配置 // 设置应用配置
setAppOptions({router, store, i18n}) // setAppOptions({router, store, i18n})
// 加载 axios 拦截器 // 加载 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 @@ ...@@ -2,7 +2,7 @@
import store from "@/store/index"; import store from "@/store/index";
// 皮肤模板页面权限 // 皮肤模板页面权限
export const permission = { export const permission = {
inserted: function(el, binding) { inserted: function (el, binding) {
const { value } = binding; const { value } = binding;
// const roles = local.getLocal("baseUserInfo").id; // const roles = local.getLocal("baseUserInfo").id;
const roles = store.getters["site/userInfo"].id; const roles = store.getters["site/userInfo"].id;
...@@ -17,3 +17,25 @@ export const permission = { ...@@ -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> <template>
<div class="tableview viewbox"> <div class="tableview">
<div class="head b-b"> <div class="head" v-if="secondaryRoutes.length">
<router-link :to="item.fullPath" v-for="(item,index) in subMenu" :key="index"><a-icon :type="item.meta.icon" /> {{item.name}}</router-link> <router-link
</div> :to="item.path"
<router-view /> 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>
<div ref="outBox" class="out-box">
<router-view />
</div>
</div>
</template> </template>
<script> <script>
import {mapGetters} from 'vuex' import { mapState } from "vuex";
export default { export default {
computed:{ data() {
...mapGetters('setting', ['subMenu']), return {};
},
watch: {
"$route.path"() {
this.$refs.outBox.scrollTop = 0;
}, },
created(){ },
console.log(this.subMenu) computed: {
} ...mapState("site", ["secondaryRoutes"]),
} },
};
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.tableview{ .tableview {
border-radius: 8px; height: 100%;
overflow: hidden; border-radius: 8px;
.head{ display: flex;
padding:0 10px; flex-direction: column;
background: #fff; .out-box {
a{ flex: 1;
margin-right:30px; padding: 15px;
color: #202020; overflow-y: auto;
font-size: 14px; background: #fff;
padding: 10px 0; }
display: inline-block; .head {
} padding: 0 10px;
.router-link-active{ background: #fff;
color: #2681e8; border-bottom: 1px solid #d9d9d9;
position: relative; i {
&::after{ color: #2681e8;
content: ""; }
display: block; a {
border-bottom: 2px solid #2681e8; margin-right: 30px;
position: absolute; color: rgba(0, 0, 0, 0.65);
left: 0; font-size: 14px;
bottom: 0; padding: 10px 0;
right: 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> </style>
\ No newline at end of file
<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 @@ ...@@ -2,8 +2,20 @@
<div class="app-category"> <div class="app-category">
<div class="header flex aic jcb mb20 pdr6"> <div class="header flex aic jcb mb20 pdr6">
<a-space> <a-space>
<a-button type="primary" @click="handleAdd"> 新增主题 </a-button> <a-button
<a-button type="danger" @click="handleDelAll"> 批量移除 </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-space>
<a-input-search <a-input-search
style="width: 300px" style="width: 300px"
...@@ -52,10 +64,16 @@ ...@@ -52,10 +64,16 @@
<!-- 操作 --> <!-- 操作 -->
<template slot="action" slot-scope="{ record }"> <template slot="action" slot-scope="{ record }">
<a-space size="middle"> <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
> >
<span class="delete pointer" @click="handleDel(record.id)" <span
class="delete pointer"
v-hasPermi="['appmarket:appTheme:remove']"
@click="handleDel(record.id)"
>删除</span >删除</span
> >
</a-space> </a-space>
......
...@@ -4,7 +4,13 @@ ...@@ -4,7 +4,13 @@
<div class="header"> <div class="header">
<div class="titel">设备应用黑名单</div> <div class="titel">设备应用黑名单</div>
<div class="control pdr6"> <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"> <div class="business-control">
<a-space> <a-space>
<a-input-search <a-input-search
...@@ -38,7 +44,10 @@ ...@@ -38,7 +44,10 @@
(blackAppTable.page - 1) * blackAppTable.size + index + 1 (blackAppTable.page - 1) * blackAppTable.size + index + 1
}}</span> }}</span>
<template slot="action" slot-scope="{ record }"> <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 >移除</span
> >
</template> </template>
...@@ -113,7 +122,10 @@ ...@@ -113,7 +122,10 @@
<template slot="action" slot-scope="{ record }"> <template slot="action" slot-scope="{ record }">
<a-space size="middle"> <a-space size="middle">
<span class="primary pointer" @click="handleIn(record)" <span
class="primary pointer"
v-hasPermi="['appmarket:blackapp:join']"
@click="handleIn(record)"
>加入黑名单</span >加入黑名单</span
> >
</a-space> </a-space>
...@@ -136,7 +148,7 @@ import { ...@@ -136,7 +148,7 @@ import {
getBlackAppList, getBlackAppList,
deleteBlackapp, deleteBlackapp,
} from "@/services/market"; } from "@/services/market";
import {getProductList} from "@/services/surface"; import { getProductList } from "@/services/surface";
import local from "@/utils/local"; import local from "@/utils/local";
import DevToBlack from "../modal/DevToBlack.vue"; import DevToBlack from "../modal/DevToBlack.vue";
import YTable from "@/components/YTable.vue"; import YTable from "@/components/YTable.vue";
...@@ -243,12 +255,12 @@ export default { ...@@ -243,12 +255,12 @@ export default {
async getProductList() { async getProductList() {
let res = await getProductList({ let res = await getProductList({
siteId: this.siteId, siteId: this.siteId,
page:1, page: 1,
size:-1 size: -1,
}); });
if (res.data.code === 1) { if (res.data.code === 1) {
let { data } = res.data.data; let { data } = res.data.data;
this.productList = data this.productList = data;
} }
}, },
// 获取设备黑名单 // 获取设备黑名单
......
...@@ -2,9 +2,25 @@ ...@@ -2,9 +2,25 @@
<div class="terminal"> <div class="terminal">
<div class="header flex aic jcb mb20 pdr6"> <div class="header flex aic jcb mb20 pdr6">
<a-space> <a-space>
<a-button type="primary" @click="handleAdd"> 新增应用 </a-button> <a-button
<a-button type="primary" @click="handleClone"> 克隆 </a-button> type="primary"
<a-button type="primary" @click="handleTheme"> 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>
<a-button v-permission="[1]" type="danger" @click="handleDelAll"> <a-button v-permission="[1]" type="danger" @click="handleDelAll">
...@@ -84,13 +100,22 @@ ...@@ -84,13 +100,22 @@
<!-- 操作 --> <!-- 操作 -->
<template slot="action" slot-scope="{ record }"> <template slot="action" slot-scope="{ record }">
<a-space size="middle"> <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
> >
<span class="primary pointer" @click="handleEdit(record)" <span
class="primary pointer"
v-hasPermi="['appmarket:moveapp:edit']"
@click="handleEdit(record)"
>编辑</span >编辑</span
> >
<span class="primary pointer" @click="handleCheck(record.id)" <span
class="primary pointer"
v-hasPermi="['appmarket:moveapp:examine']"
@click="handleCheck(record.id)"
>查看</span >查看</span
> >
<span <span
......
...@@ -2,9 +2,25 @@ ...@@ -2,9 +2,25 @@
<div class="terminal"> <div class="terminal">
<div class="header flex aic jcb mb20 pdr6"> <div class="header flex aic jcb mb20 pdr6">
<a-space> <a-space>
<a-button type="primary" @click="handleAdd"> 新增应用 </a-button> <a-button
<a-button type="primary" @click="handleClone"> 克隆 </a-button> type="primary"
<a-button type="primary" @click="handleTheme"> 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>
<a-button v-permission="[1]" type="danger" @click="handleDelAll"> <a-button v-permission="[1]" type="danger" @click="handleDelAll">
...@@ -84,13 +100,22 @@ ...@@ -84,13 +100,22 @@
<!-- 操作 --> <!-- 操作 -->
<template slot="action" slot-scope="{ record }"> <template slot="action" slot-scope="{ record }">
<a-space size="middle"> <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
> >
<span class="primary pointer" @click="handleEdit(record)" <span
class="primary pointer"
v-hasPermi="['appmarket:terminalapp:edit']"
@click="handleEdit(record)"
>编辑</span >编辑</span
> >
<span class="primary pointer" @click="handleCheck(record.id)" <span
class="primary pointer"
v-hasPermi="['appmarket:terminalapp:examine']"
@click="handleCheck(record.id)"
>查看</span >查看</span
> >
<span <span
......
...@@ -147,9 +147,9 @@ ...@@ -147,9 +147,9 @@
<script> <script>
import YSwitch from "../../../../components/yswitch/YSwitch.vue"; import YSwitch from "../../../../components/yswitch/YSwitch.vue";
import { saveApp } from "@/services/market"; import { saveApp } from "@/services/market";
import { mapGetters } from "vuex";
import { checkCodeNumber } from "@/utils/validate"; import { checkCodeNumber } from "@/utils/validate";
import YUpload from "@/components/YUpload.vue"; import YUpload from "@/components/YUpload.vue";
import { getSiteTree } from "@/services/basicsetFun";
// import local from "@/utils/local"; // import local from "@/utils/local";
export default { export default {
components: { components: {
...@@ -176,6 +176,7 @@ export default { ...@@ -176,6 +176,7 @@ export default {
data() { data() {
return { return {
api: process.env.VUE_APP_API_BASE_URL + "/", api: process.env.VUE_APP_API_BASE_URL + "/",
SiteTree: [],
labelCol: { labelCol: {
span: 3, span: 3,
}, },
...@@ -252,10 +253,35 @@ export default { ...@@ -252,10 +253,35 @@ export default {
this.$emit("update:AddVisible", val); this.$emit("update:AddVisible", val);
}, },
}, },
...mapGetters("site", ["SiteTree"]),
}, },
created() {}, created() {
this.getSiteTree();
},
methods: { 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() { onClose() {
this.$refs.form.resetFields(); this.$refs.form.resetFields();
......
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
</template> </template>
<script> <script>
import { mapGetters } from "vuex";
import { cloneApp } from "@/services/market"; import { cloneApp } from "@/services/market";
import { getSiteTree } from "@/services/basicsetFun";
export default { export default {
props: { props: {
siteVisible: { siteVisible: {
...@@ -48,6 +48,7 @@ export default { ...@@ -48,6 +48,7 @@ export default {
data() { data() {
return { return {
siteIdList: [], // 站点id siteIdList: [], // 站点id
SiteTree: [],
replaceFields: { replaceFields: {
title: "label", title: "label",
key: "id", key: "id",
...@@ -64,9 +65,35 @@ export default { ...@@ -64,9 +65,35 @@ export default {
this.$emit("update:siteVisible", val); this.$emit("update:siteVisible", val);
}, },
}, },
...mapGetters("site", ["SiteTree"]), },
created() {
this.getSiteTree();
}, },
methods: { 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() { async handleOk() {
if (!this.siteIdList) { if (!this.siteIdList) {
this.$message.warning("请先选择站点"); this.$message.warning("请先选择站点");
...@@ -105,4 +132,4 @@ export default { ...@@ -105,4 +132,4 @@ export default {
.tips { .tips {
font-weight: 600 !important; font-weight: 600 !important;
} }
</style> </style>
\ No newline at end of file
...@@ -6,8 +6,18 @@ ...@@ -6,8 +6,18 @@
<div class="control pdr6"> <div class="control pdr6">
<div> <div>
<a-space size="middle"> <a-space size="middle">
<a-button type="primary" @click="showModal"> 新增业务 </a-button> <a-button
<a-button type="danger" @click="handleBatchDelSiteBusiness"> 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-button>
</a-space> </a-space>
...@@ -64,11 +74,13 @@ ...@@ -64,11 +74,13 @@
<a-space size="middle"> <a-space size="middle">
<span <span
class="primary pointer" class="primary pointer"
v-hasPermi="['business:businessmanage:editSiteBusiness']"
@click="handleEditSiteBusiness(record)" @click="handleEditSiteBusiness(record)"
>编辑</span >编辑</span
> >
<span <span
class="delete pointer" class="delete pointer"
v-hasPermi="['business:businessmanage:removeSiteBusiness']"
@click="handleDelSiteBusiness(record.id, record)" @click="handleDelSiteBusiness(record.id, record)"
>删除</span >删除</span
> >
...@@ -83,7 +95,11 @@ ...@@ -83,7 +95,11 @@
<div class="titel">一体化业务列表</div> <div class="titel">一体化业务列表</div>
<div class="control pdr6"> <div class="control pdr6">
<div> <div>
<a-button type="primary" @click="handleBatchJoin"> <a-button
type="primary"
v-hasPermi="['business:businessmanage:join']"
@click="handleBatchJoin"
>
批量加入 批量加入
</a-button> </a-button>
</div> </div>
...@@ -125,11 +141,15 @@ ...@@ -125,11 +141,15 @@
<template slot="action" slot-scope="{ record }"> <template slot="action" slot-scope="{ record }">
<a-space size="middle"> <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
> >
<span <span
class="delete pointer" class="delete pointer"
v-hasPermi="['business:businessmanage:remove']"
@click="handleDelBusiness(+record.id)" @click="handleDelBusiness(+record.id)"
>删除</span >删除</span
> >
...@@ -538,13 +558,14 @@ export default { ...@@ -538,13 +558,14 @@ export default {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex; display: flex;
position: relative;
&::after { &::after {
content: ""; content: "";
width: 1px; width: 1px;
height: 82vh; height: 100%;
position: absolute; position: absolute;
background-color: #eeeeee; background-color: #eeeeee;
top: 44px; top: 0px;
left: 50%; left: 50%;
} }
.left, .left,
......
...@@ -5,7 +5,11 @@ ...@@ -5,7 +5,11 @@
<div class="titel">站点事项列表</div> <div class="titel">站点事项列表</div>
<div class="header-bottom pdr6"> <div class="header-bottom pdr6">
<div class="left-btn"> <div class="left-btn">
<a-button type="danger" @click="handleBatchDelSiteMatter"> <a-button
type="danger"
v-hasPermi="['business:mattermanage:removeSiteMatter']"
@click="handleBatchDelSiteMatter"
>
批量移除 批量移除
</a-button> </a-button>
</div> </div>
...@@ -104,13 +108,17 @@ ...@@ -104,13 +108,17 @@
<span <span
v-if="record.source == 1" v-if="record.source == 1"
class="primary pointer" class="primary pointer"
v-hasPermi="['business:mattermanage:editSiteMatter']"
@click="handleSiteEdit(record)" @click="handleSiteEdit(record)"
>编辑</span >编辑</span
> >
<span href="javascript:;" style="visibility: hidden" v-else <span href="javascript:;" style="visibility: hidden" v-else
>编辑</span >编辑</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 >移除</span
> >
</a-space> </a-space>
...@@ -125,11 +133,27 @@ ...@@ -125,11 +133,27 @@
<div class="control pdr6"> <div class="control pdr6">
<div> <div>
<a-space size="middle"> <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>
<a-button type="primary" @click="addMatter"> 新增事项 </a-button> <a-button
<a-button type="primary" @click="handleImport"> 导入 </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> </a-space>
</div> </div>
<div> <div>
...@@ -218,14 +242,19 @@ ...@@ -218,14 +242,19 @@
v-if="record.source == 1" v-if="record.source == 1"
class="primary pointer" class="primary pointer"
@click="handleEdit(record.id)" @click="handleEdit(record.id)"
v-hasPermi="['business:mattermanage:edit']"
>编辑</span >编辑</span
> >
<span style="visibility: hidden" v-else>编辑</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
> >
<span <span
class="delete pointer" class="delete pointer"
v-hasPermi="['business:mattermanage:removeMatter']"
@click="handleDelBaseMatter(record.id)" @click="handleDelBaseMatter(record.id)"
>删除</span >删除</span
> >
...@@ -636,7 +665,7 @@ export default { ...@@ -636,7 +665,7 @@ export default {
let input = document.createElement("input"); let input = document.createElement("input");
input.type = "file"; input.type = "file";
input.accept = ".xlsx"; input.accept = ".xlsx";
input.style.display = 'none'; input.style.display = "none";
document.body.appendChild(input); document.body.appendChild(input);
input.click(); input.click();
input.onchange = async () => { input.onchange = async () => {
...@@ -662,13 +691,14 @@ export default { ...@@ -662,13 +691,14 @@ export default {
.basicset-tab2 { .basicset-tab2 {
width: 100%; width: 100%;
display: flex; display: flex;
position: relative;
&::after { &::after {
content: ""; content: "";
width: 1px; width: 1px;
height: 82vh; height: 100%;
position: absolute; position: absolute;
background-color: #eeeeee; background-color: #eeeeee;
top: 44px; top: 0;
left: 45%; left: 45%;
} }
.left, .left,
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
type="danger" type="danger"
@click="batchDelSiteBusiness" @click="batchDelSiteBusiness"
:loading="delSiteBusinessLoading" :loading="delSiteBusinessLoading"
v-hasPermi="['business:businessinmanage:remove']"
> >
批量解除 批量解除
</a-button> </a-button>
...@@ -50,11 +51,13 @@ ...@@ -50,11 +51,13 @@
<a-space> <a-space>
<span <span
class="primary pointer" class="primary pointer"
v-hasPermi="['business:businessinmanage:info']"
@click="handleisUnbound(true, record)" @click="handleisUnbound(true, record)"
>关联详情</span >关联详情</span
> >
<span <span
class="delete pointer" class="delete pointer"
v-hasPermi="['business:businessinmanage:remove']"
@click="handleisUnbound(false, record)" @click="handleisUnbound(false, record)"
>解除</span >解除</span
> >
...@@ -69,7 +72,13 @@ ...@@ -69,7 +72,13 @@
<div class="titel">站点事项列表</div> <div class="titel">站点事项列表</div>
<div class="control pdr6"> <div class="control pdr6">
<div> <div>
<a-button type="primary" @click="handleAddAll"> 批量关联 </a-button> <a-button
type="primary"
@click="handleAddAll"
v-hasPermi="['business:businessinmanage:correlation']"
>
批量关联
</a-button>
</div> </div>
<div> <div>
<a-space> <a-space>
...@@ -135,7 +144,12 @@ ...@@ -135,7 +144,12 @@
</template> </template>
<!-- 操作 --> <!-- 操作 -->
<template slot="action" slot-scope="{ record }"> <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> </template>
</y-table> </y-table>
</div> </div>
...@@ -701,13 +715,14 @@ export default { ...@@ -701,13 +715,14 @@ export default {
.basicset-tab3 { .basicset-tab3 {
width: 100%; width: 100%;
display: flex; display: flex;
position: relative;
&::after { &::after {
content: ""; content: "";
width: 1px; width: 1px;
height: 82vh; height: 100%;
position: absolute; position: absolute;
background-color: #eeeeee; background-color: #eeeeee;
top: 44px; top: 0;
left: 50%; left: 50%;
} }
.left, .left,
......
...@@ -117,6 +117,7 @@ ...@@ -117,6 +117,7 @@
<a-space size="middle"> <a-space size="middle">
<div <div
class="workguide_btn" class="workguide_btn"
v-hasPermi="['business:workguide:hot']"
:style="{ color: record.hot == 1 ? '#03d76f' : '#1890FF' }" :style="{ color: record.hot == 1 ? '#03d76f' : '#1890FF' }"
@click="handleSiteEdit(record, 'hot')" @click="handleSiteEdit(record, 'hot')"
> >
...@@ -125,6 +126,7 @@ ...@@ -125,6 +126,7 @@
<div <div
class="workguide_btn" class="workguide_btn"
style="width: 60px" style="width: 60px"
v-hasPermi="['business:workguide:show']"
@click="handleSiteEdit(record, 'display')" @click="handleSiteEdit(record, 'display')"
> >
{{ record.display == 1 ? "取消展示" : "展示" }} {{ record.display == 1 ? "取消展示" : "展示" }}
......
...@@ -3,8 +3,20 @@ ...@@ -3,8 +3,20 @@
<div class="flex aic jcb mb20"> <div class="flex aic jcb mb20">
<div> <div>
<a-space> <a-space>
<a-button type="primary" @click="handleAdd"> 新增 </a-button> <a-button
<a-button type="danger" @click="handleDelAll"> 批量删除 </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> </a-space>
</div> </div>
<a-space> <a-space>
...@@ -75,10 +87,18 @@ ...@@ -75,10 +87,18 @@
<!-- 操作 --> <!-- 操作 -->
<template slot="action" slot-scope="{ record }"> <template slot="action" slot-scope="{ record }">
<a-space size="middle"> <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
> >
<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
> >
</a-space> </a-space>
......
...@@ -3,10 +3,19 @@ ...@@ -3,10 +3,19 @@
<div class="flex1 auto-scroll-y"> <div class="flex1 auto-scroll-y">
<div class="control pdr6"> <div class="control pdr6">
<div> <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
> >
<a-button type="danger" @click="handleDelAll">批量删除模块</a-button> <a-button
type="danger"
v-hasPermi="['deploy:manage:remove']"
@click="handleDelAll"
>批量删除模块</a-button
>
</div> </div>
<div class="search-box"> <div class="search-box">
<a-input-search <a-input-search
...@@ -67,10 +76,16 @@ ...@@ -67,10 +76,16 @@
<!-- <span class="primary pointer" @click="statementManage(record)" <!-- <span class="primary pointer" @click="statementManage(record)"
>配置报表</span >配置报表</span
> --> > -->
<span class="primary pointer" @click="handleEdit(record)" <span
class="primary pointer"
v-hasPermi="['deploy:manage:edit']"
@click="handleEdit(record)"
>编辑</span >编辑</span
> >
<span class="delete pointer" @click="handleDel(record.id)" <span
class="delete pointer"
v-hasPermi="['deploy:manage:remove']"
@click="handleDel(record.id)"
>删除</span >删除</span
> >
</a-space> </a-space>
......
...@@ -8,7 +8,11 @@ ...@@ -8,7 +8,11 @@
</TabHeader> </TabHeader>
<div class="department_on flex aic"> <div class="department_on flex aic">
<!-- <div class="department_manage">部门管理({{ deptTotal }}</div> --> <!-- <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-button
> >
<a-input-search <a-input-search
...@@ -37,7 +41,7 @@ ...@@ -37,7 +41,7 @@
</a-tooltip> </a-tooltip>
</div> </div>
<div class="department_icon_edit"> <div class="department_icon_edit">
<a-tooltip> <a-tooltip v-hasPermi="['department:editDept']">
<template slot="title"> 查看编辑 </template> <template slot="title"> 查看编辑 </template>
<a-icon <a-icon
type="edit" type="edit"
...@@ -46,7 +50,7 @@ ...@@ -46,7 +50,7 @@
@click.stop="showModal(v)" @click.stop="showModal(v)"
/> />
</a-tooltip> </a-tooltip>
<a-tooltip> <a-tooltip v-hasPermi="['department:removeDept']">
<template slot="title"> 删除 </template> <template slot="title"> 删除 </template>
<a-icon <a-icon
...@@ -78,8 +82,13 @@ ...@@ -78,8 +82,13 @@
<div class="department_right_add"> <div class="department_right_add">
<div class="flex aic jcb pdr6"> <div class="flex aic jcb pdr6">
<a-space> <a-space>
<a-button type="primary" @click="addModal">新增窗口</a-button> <a-button
<a-dropdown> type="primary"
@click="addModal"
v-hasPermi="['department:addWindow']"
>新增窗口</a-button
>
<a-dropdown v-hasPermi="['department:more']">
<a-menu slot="overlay"> <a-menu slot="overlay">
<a-menu-item key="1"> <a-menu-item key="1">
<a-upload <a-upload
...@@ -153,16 +162,28 @@ ...@@ -153,16 +162,28 @@
<!-- 操作 --> <!-- 操作 -->
<div slot="action" slot-scope="{ record }"> <div slot="action" slot-scope="{ record }">
<div class="flex jcb flexwrap"> <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
> >
<span class="primary pointer" @click="addWindowMatter(record)" <span
class="primary pointer"
v-hasPermi="['department:matter']"
@click="addWindowMatter(record)"
>事项</span >事项</span
> >
<span class="primary pointer" @click="editModal(record)" <span
class="primary pointer"
v-hasPermi="['department:editWindow']"
@click="editModal(record)"
>编辑</span >编辑</span
> >
<span class="delete pointer" @click="delWindow(record.id)" <span
class="delete pointer"
v-hasPermi="['department:removeWindow']"
@click="delWindow(record.id)"
>删除</span >删除</span
> >
</div> </div>
......
...@@ -2,8 +2,18 @@ ...@@ -2,8 +2,18 @@
<div class="hall-manage"> <div class="hall-manage">
<div class="control flex aic jcb mb20 pdr6"> <div class="control flex aic jcb mb20 pdr6">
<a-space size="middle"> <a-space size="middle">
<a-button type="primary" @click="handleAdd">新增大厅</a-button> <a-button
<a-button type="danger" @click="handleDelAll">批量删除</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> </a-space>
<div class="search-box"> <div class="search-box">
<a-input-search <a-input-search
...@@ -42,10 +52,16 @@ ...@@ -42,10 +52,16 @@
<!-- 操作 --> <!-- 操作 -->
<template slot="action" slot-scope="{ record }"> <template slot="action" slot-scope="{ record }">
<a-space size="middle"> <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
> >
<span class="delete pointer" @click="handleDel(record.id)" <span
class="delete pointer"
v-hasPermi="['hall:hallmanage:remove']"
@click="handleDel(record.id)"
>删除</span >删除</span
> >
</a-space> </a-space>
......
...@@ -4,7 +4,15 @@ ...@@ -4,7 +4,15 @@
<div class="header"> <div class="header">
<div class="titel">大厅窗口</div> <div class="titel">大厅窗口</div>
<div class="control pdr6"> <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"> <div class="business-control">
<a-space> <a-space>
<a-select <a-select
...@@ -58,7 +66,10 @@ ...@@ -58,7 +66,10 @@
}}</span> }}</span>
<template slot="action" slot-scope="{ record }"> <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 >移除</span
> >
</template> </template>
...@@ -71,7 +82,13 @@ ...@@ -71,7 +82,13 @@
<div class="titel">站点窗口</div> <div class="titel">站点窗口</div>
<div class="control pdr6"> <div class="control pdr6">
<div> <div>
<a-button type="primary" @click="handleAddAll"> 批量加入 </a-button> <a-button
type="primary"
@click="handleAddAll"
v-hasPermi="['hall:hallwindow:join']"
>
批量加入
</a-button>
</div> </div>
<div class="business-control"> <div class="business-control">
<a-space> <a-space>
...@@ -126,7 +143,10 @@ ...@@ -126,7 +143,10 @@
<template slot="action" slot-scope="{ record }"> <template slot="action" slot-scope="{ record }">
<a-space size="middle"> <a-space size="middle">
<span class="primary pointer" @click="handleIn([record])" <span
class="primary pointer"
v-hasPermi="['hall:hallwindow:join']"
@click="handleIn([record])"
>加入大厅</span >加入大厅</span
> >
</a-space> </a-space>
......
...@@ -4,9 +4,15 @@ ...@@ -4,9 +4,15 @@
<div class="pd15 flex1 auto-scroll-y"> <div class="pd15 flex1 auto-scroll-y">
<div class="btn-box pdr6"> <div class="btn-box pdr6">
<!-- 新增按钮 --> <!-- 新增按钮 -->
<a-button type="primary" @click="showModal" class="skins_btn_1" <div>
>新增节日</a-button <a-button
> type="primary"
@click="showModal"
v-hasPermi="['festival:add']"
class="skins_btn_1"
>新增节日</a-button
>
</div>
<div> <div>
<a-space> <a-space>
<a-select <a-select
...@@ -67,8 +73,18 @@ ...@@ -67,8 +73,18 @@
<!-- 操作 --> <!-- 操作 -->
<template slot="action" slot-scope="{ record }"> <template slot="action" slot-scope="{ record }">
<a-space size="middle"> <a-space size="middle">
<a @click="handleEdit(record)" class="primary">编辑</a> <a
<a class="delete" @click="handleDel(record.id)">删除</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> </a-space>
</template> </template>
</y-table> </y-table>
......
...@@ -7,7 +7,9 @@ ...@@ -7,7 +7,9 @@
<script> <script>
import local from "@/utils/local"; import local from "@/utils/local";
import { mapMutations } from "vuex"; 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 { export default {
data() { data() {
return {}; return {};
...@@ -24,18 +26,15 @@ export default { ...@@ -24,18 +26,15 @@ export default {
"SET_sysName", "SET_sysName",
"SET_sysLogo", "SET_sysLogo",
"SET_path", "SET_path",
"SET_permissions",
"SET_routes",
"SET_menusList",
"SET_secondaryRoutes",
]), ]),
// 获取token // 获取token
getToken() { getToken() {
let { let { token, userInfo, siteid, siteName, sysName, sysLogo, path } =
token, this.$route.query;
userInfo,
siteid,
siteName,
sysName,
sysLogo,
path,
} = this.$route.query;
if (token && userInfo) { if (token && userInfo) {
userInfo = JSON.parse(userInfo); userInfo = JSON.parse(userInfo);
this.SET_userInfo(userInfo); this.SET_userInfo(userInfo);
...@@ -47,9 +46,7 @@ export default { ...@@ -47,9 +46,7 @@ export default {
this.SET_path(path); this.SET_path(path);
local.setLocal("siteId", siteid); local.setLocal("siteId", siteid);
local.setLocal("siteName", siteName); local.setLocal("siteName", siteName);
// 动态菜单 this.getMenuTree();
createMenus();
this.$router.push("/website");
} else { } else {
this.$message.warning("跳转失败,请重新登录"); this.$message.warning("跳转失败,请重新登录");
setTimeout(() => { setTimeout(() => {
...@@ -57,6 +54,36 @@ export default { ...@@ -57,6 +54,36 @@ export default {
}, 2000); }, 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> </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 @@ ...@@ -11,19 +11,19 @@
<div class="btn-box"> <div class="btn-box">
<a-space size="middle" v-if="siteData.length"> <a-space size="middle" v-if="siteData.length">
<a-button <a-button
v-permission="[1]" v-hasPermi="['website:Sync']"
type="primary" type="primary"
@click="handleSync(siteData[0].id)" @click="handleSync(siteData[0].id)"
>同步数据</a-button >同步数据</a-button
> >
<a-button <a-button
v-permission="[1]" v-hasPermi="['website:edit']"
type="primary" type="primary"
@click="editSiteInfo(siteData[0])" @click="editSiteInfo(siteData[0])"
>编辑</a-button >编辑</a-button
> >
<a-button <a-button
v-permission="[1]" v-hasPermi="['website:remove']"
type="danger" type="danger"
@click="deleteSite(siteData[0].id, 0)" @click="deleteSite(siteData[0].id, 0)"
>删除</a-button >删除</a-button
...@@ -199,7 +199,11 @@ ...@@ -199,7 +199,11 @@
<a-empty description="暂无站点" /> <a-empty description="暂无站点" />
<div class="btn_box"> <div class="btn_box">
<div style="width: 200px"> <div style="width: 200px">
<a-button block size="large" @click="addSiteAll" <a-button
block
size="large"
v-hasPermi="['website:add']"
@click="addSiteAll"
>新增站点</a-button >新增站点</a-button
> >
</div> </div>
......
<template> <template>
<div class="configurat"> <div class="configurat">
<div class="title">短信全局配置</div> <div class="title">短信全局配置</div>
<div class="des"> <div class="des">全局配置,一键控制</div>
全局配置,一键控制 <div class="des">轻松管理政务短信通知的全局设置,确保信息的准确传递</div>
</div>
<div class="des">
轻松管理政务短信通知的全局设置,确保信息的准确传递
</div>
<div class="tag-list"> <div class="tag-list">
<div class="tag-item" v-for="v in tagList" :key="v"> <div class="tag-item" v-for="v in tagList" :key="v">
{{ v }} {{ v }}
</div> </div>
</div> </div>
<a-tooltip> <a-tooltip v-hasPermi="['configurat:switch']">
<template slot="title"> <template slot="title">
当前状态:{{ setInfo.messageoff ? "开启" : "关闭" }} 当前状态:{{ setInfo.messageoff ? "开启" : "关闭" }}
</template> </template>
......
...@@ -8,10 +8,16 @@ ...@@ -8,10 +8,16 @@
<a-button <a-button
type="primary" type="primary"
style="margin-right: 10px" style="margin-right: 10px"
v-hasPermi="['social:add']"
@click="handleAdd" @click="handleAdd"
>新增</a-button >新增</a-button
> >
<a-button type="danger" @click="handleDelAll">批量删除</a-button> <a-button
type="danger"
v-hasPermi="['social:remove']"
@click="handleDelAll"
>批量删除</a-button
>
</div> </div>
</a-space> </a-space>
</div> </div>
...@@ -31,10 +37,16 @@ ...@@ -31,10 +37,16 @@
> >
<template slot="action" slot-scope="{ record }"> <template slot="action" slot-scope="{ record }">
<a-space size="middle"> <a-space size="middle">
<span class="primary pointer" @click="handleEdit(record)" <span
class="primary pointer"
v-hasPermi="['social:edit']"
@click="handleEdit(record)"
>编辑</span >编辑</span
> >
<span class="delete pointer" @click="handleDel(record.id)" <span
class="delete pointer"
v-hasPermi="['social:remove']"
@click="handleDel(record.id)"
>删除</span >删除</span
> >
</a-space> </a-space>
......
...@@ -35,10 +35,16 @@ ...@@ -35,10 +35,16 @@
</div> </div>
</a-spin> </a-spin>
<div class="preview-btn"> <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
> >
<a-button @click="editClassify">编辑分类</a-button> <a-button @click="editClassify" v-hasPermi="['surface:editClassify']"
>编辑分类</a-button
>
</div> </div>
</div> </div>
</template> </template>
......
...@@ -24,8 +24,16 @@ ...@@ -24,8 +24,16 @@
</div> </div>
<div class="show-btn flex aic jcc"> <div class="show-btn flex aic jcc">
<a-space size="middle"> <a-space size="middle">
<a-button type="primary" @click="editSurface">修改皮肤参数</a-button> <a-button
<a-button type="danger" @click="handleClose(curSkin.id)" 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-button
> >
</a-space> </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 @@ ...@@ -25,6 +25,12 @@
维度管理 维度管理
</span> </span>
</a-tab-pane> --> </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"> <a-tab-pane key="/system/parameter">
<span slot="tab"> <span slot="tab">
<a-icon type="container" /> <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> <template>
<div class="parameter"> <div class="parameter">
<div class="control flex aic jcb mb15 pdr6"> <div class="control flex aic jcb mb15 pdr6">
<div> <a-space>
<a-button type="primary" style="margin-right: 10px" @click="handleAdd" <a-button
type="primary"
v-hasPermi="['system:parameter:add']"
@click="handleAdd"
>新增</a-button >新增</a-button
> >
<a-button type="danger" @click="handleDelAll">批量删除</a-button> <a-button
</div> type="danger"
v-hasPermi="['system:parameter:remove']"
@click="handleDelAll"
>批量删除</a-button
>
</a-space>
<div class="search-box"> <div class="search-box">
<a-space> <a-space>
<a-input <a-input
...@@ -56,14 +64,14 @@ ...@@ -56,14 +64,14 @@
<template slot="action" slot-scope="{ record }"> <template slot="action" slot-scope="{ record }">
<a-space size="middle"> <a-space size="middle">
<span <span
href="javascript:;"
class="primary pointer" class="primary pointer"
v-hasPermi="['system:parameter:edit']"
@click="handleEdit(record)" @click="handleEdit(record)"
>编辑</span >编辑</span
> >
<span <span
href="javascript:;"
class="delete pointer" class="delete pointer"
v-hasPermi="['system:parameter:remove']"
@click="handleDel(record.id)" @click="handleDel(record.id)"
>删除</span >删除</span
> >
......
<template> <template>
<div class="resource-container"> <div class="resoure-page">
<div class="control flex aic jcb mb15 pdr6"> <div class="control flex aic jcb mb15 pdr6">
<a-space> <a-space>
<a-button type="primary" @click="handleAdd">新增</a-button>
<a-button <a-button
v-permission="[1]"
type="primary" 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" class="addclass"
@click="refSresource" @click="refSresource"
>刷新资源</a-button >刷新资源</a-button
> >
<a-button type="danger" @click="handleDelAll">批量删除</a-button>
</a-space> </a-space>
<div class="search-box"> <a-space>
<a-input-search <a-input placeholder="请输入资源名称搜索" v-model="name" />
placeholder="请输入资源名搜索" <a-button type="primary" @click="handleSearch">搜索</a-button>
enter-button="搜索" <a-button @click="handleResetSearch">重置</a-button>
v-model="searchValue" </a-space>
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> </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 <AddResurce
ref="AddResurce" ref="AddResurce"
:title="title"
:visible.sync="addVisible"
:dict="dict" :dict="dict"
@add="getResourceList" :title="title"
:show.sync="show"
@success="getResourceList"
></AddResurce> ></AddResurce>
</div> </div>
</template> </template>
<script> <script>
import YTable from "@/components/YTable.vue";
import AddResurce from "./modal/AddResurce.vue";
import { import {
getResourceList, getResourceList,
refreshResource,
delResource, delResource,
refreshResource,
} from "@/services/system"; } from "@/services/system";
import { pageSizeOptions } from "@/config/pageConfig.js";
import AddResurce from "./modal/AddResurce.vue";
export default { export default {
components: { AddResurce }, components: {
YTable,
AddResurce,
},
data() { data() {
const columns = [ return {
{ loading: false,
title: "序号", show: false,
dataIndex: "num", title: "新增",
width: "65px", columns: [
scopedSlots: { {
customRender: "num", title: "序号",
width: "65px",
customRender: (text, record, index) => {
return (this.page - 1) * this.size + index + 1;
},
}, },
}, {
{ title: "所属分组",
title: "名称", dataIndex: "groupName",
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: "名称",
title: "认证类型", dataIndex: "name",
width: 200,
dataIndex: "authType",
customRender: (text) => {
return this.dict.authType[text];
}, },
}, {
{ title: "资源路径",
title: "操作", dataIndex: "url",
width: "120px", customRender: (text) => {
scopedSlots: { customRender: "action" }, if (text) {
}, return text.split(",").map((v) => {
]; return <a-tag>{v}</a-tag>;
return { });
columns, }
loading: false, },
current: 1, },
{
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, size: 10,
total: 0, total: 0,
pageSizeOptions, tableData: [], // 表格数据
searchValue: "", // 搜索 dict: {},
tableData: [],
selectedRowKeys: [], selectedRowKeys: [],
dict: {}, // 字典
addVisible: false,
title: "新增",
}; };
}, },
created() { created() {
this.getResourceList(); this.getResourceList();
}, },
methods: { methods: {
// 获取资源列表
async getResourceList() { async getResourceList() {
this.loading = true; this.loading = true;
let res = await getResourceList({ const res = await getResourceList({
page: this.current, name: `%${this.name}%`,
page: this.page,
size: this.size, size: this.size,
name: `%${this.searchValue}%`,
}); });
this.loading = false; this.loading = false;
if (res.data.code == 1) { if (res.data.code === 1) {
let { data, total, dict } = res.data.data; let { data, total, dict } = res.data.data;
if (!data.length && this.current > 1) { if (!data.length && this.page > 1) {
this.current -= 1; this.page -= 1;
this.getResourceList(); this.getResourceList();
} }
this.dict = dict;
this.tableData = data; this.tableData = data;
this.total = total; this.total = total;
this.dict = dict;
} }
}, },
// 新增
handleAdd() { handleSearch() {
this.title = "新增"; this.page = 1;
this.$refs.AddResurce.onAdd();
this.addVisible = true;
},
// 搜索
onSearch() {
this.current = 1;
this.getResourceList(); this.getResourceList();
}, },
// 分页 handleResetSearch() {
handleChange(num) { this.name = "";
this.current = num; this.page = 1;
this.getResourceList(); this.getResourceList();
}, },
// 改变每页显示数量 handleAdd() {
showSizeChange(current, size) { this.title = "新增";
this.current = current; this.$refs.AddResurce.onAdd();
this.size = size; this.show = true;
this.getResourceList(); },
handleEdit(row) {
this.title = "编辑";
this.$refs.AddResurce.onEdit(row);
this.show = true;
}, },
// 选择 selectChange(keys) {
onSelectChange(keys) {
this.selectedRowKeys = keys; this.selectedRowKeys = keys;
}, },
// 批量删除 handleBatchDel() {
handleDelAll() {
if (!this.selectedRowKeys.length) { if (!this.selectedRowKeys.length) {
this.$message.warn("请先勾选数据"); this.$message.warning("请先勾选数据");
return; return;
} }
let ids = this.selectedRowKeys.join(","); let ids = this.selectedRowKeys.join(",");
this.handleDel(ids); this.handleDel(ids);
}, },
// 编辑
handleEdit(row) {
this.title = "编辑";
this.$refs.AddResurce.onEdit(row);
this.addVisible = true;
},
// 删除 // 删除
handleDel(id) { handleDel(id) {
let _this = this;
this.$confirm({ this.$confirm({
title: "系统提示", title: "系统提示:",
content: "删除不可恢复,确定要删除吗?", content: "删除不可恢复,是否继续?",
okText: "确定",
okType: "danger", okType: "danger",
cancelText: "取消", cancelText: "取消",
centered: true, centered: true,
icon: "exclamation-circle",
maskClosable: true, maskClosable: true,
async onOk() { icon: "exclamation-circle",
onOk: async () => {
let res = await delResource({ id }); let res = await delResource({ id });
if (res.data.code == 1) { let { code, msg } = res.data;
let { msg } = res.data; if (code === 1) {
_this.$message.success(msg); this.$message.success(msg);
_this.getResourceList(); this.getResourceList();
} }
}, },
onCancel() { onCancel() {},
console.log("Cancel");
},
}); });
}, },
apportion(row) {
console.log("🚀 ~ apportion ~ row:", row);
},
// 刷新资源 // 刷新资源
async refSresource() { async refSresource() {
let _this = this; let _this = this;
...@@ -264,9 +248,4 @@ export default { ...@@ -264,9 +248,4 @@ export default {
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped></style>
.resource-container {
width: 100%;
height: 100%;
}
</style>
...@@ -88,7 +88,7 @@ export default { ...@@ -88,7 +88,7 @@ export default {
type: String, type: String,
default: "新增资源", default: "新增资源",
}, },
visible: { show: {
required: true, required: true,
type: Boolean, type: Boolean,
default: false, default: false,
...@@ -123,10 +123,10 @@ export default { ...@@ -123,10 +123,10 @@ export default {
computed: { computed: {
Visible: { Visible: {
get() { get() {
return this.visible; return this.show;
}, },
set(val) { set(val) {
this.$emit("update:visible", val); this.$emit("update:show", val);
}, },
}, },
}, },
...@@ -161,7 +161,7 @@ export default { ...@@ -161,7 +161,7 @@ export default {
this.loading = false; this.loading = false;
if (code == 1) { if (code == 1) {
this.$message.success(msg); this.$message.success(msg);
this.$emit("add"); this.$emit("success");
this.handleCancel(); this.handleCancel();
} }
} }
...@@ -225,6 +225,9 @@ export default { ...@@ -225,6 +225,9 @@ export default {
} }
} }
/deep/.url-params { /deep/.url-params {
.ant-form-item-control-wrapper {
width: 100%;
}
.ant-form-item-children { .ant-form-item-children {
display: flex; display: flex;
align-items: center; align-items: center;
......
<template> <template>
<div class="role-container"> <div class="role-page">
<div class="control flex aic jcb mb15 pdr6"> <div class="control flex aic jcb mb15 pdr6">
<div> <a-space>
<a-button type="primary" style="margin-right: 10px" @click="handleAdd" <a-button
type="primary"
v-hasPermi="['system:role:add']"
@click="handleAddRole"
>新增</a-button >新增</a-button
> >
<a-button type="danger" @click="handleDelAll">批量删除</a-button> <a-button
</div> type="danger"
<div class="search-box"> v-hasPermi="['system:role:remove']"
<a-input-search @click="handleBatchDel"
placeholder="请输入角色名搜索" >批量删除</a-button
enter-button="搜索" >
v-model="searchValue" </a-space>
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-space slot="search">
<template slot="action" slot-scope="text"> <a-input placeholder="请输入角色名称搜索" v-model="name" />
<a-space size="middle"> <a-button type="primary" @click="handleSearch">搜索</a-button>
<span class="primary pointer" @click="apportion(text)" <a-button @click="handleResetSearch">重置</a-button>
>分配资源</span </a-space>
>
<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> </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 <AddRole
ref="AddRole" ref="AddRole"
:show.sync="showAddRole"
:title="title" :title="title"
:addVisible.sync="addVisible" @success="getRoleList"
@addSuccess="getRoleList"
></AddRole> ></AddRole>
<!-- 分配菜单 -->
<ApportionMenu
ref="ApportionMenu"
:show.sync="menuShow"
:roleInfo="roleInfo"
:menuList="menuList"
></ApportionMenu>
<!-- 分配资源 --> <!-- 分配资源 -->
<ApportionRes ref="ApportionRes" :visible.sync="resVisible"></ApportionRes> <ApportionRes ref="ApportionRes" :show.sync="resShow"></ApportionRes>
<!-- 资源规则 -->
<ResDimList ref="ResDimList" :visible.sync="resDimListVisible"></ResDimList>
</div> </div>
</template> </template>
<script> <script>
import { getRoleList, delRole } from "@/services/system"; import YTable from "@/components/YTable.vue";
import { pageSizeOptions } from "@/config/pageConfig.js"; import ApportionMenu from "./modal/ApportionMenu.vue";
import AddRole from "./modal/AddRole.vue";
import ApportionRes from "./modal/ApportionRes.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 { export default {
components: { AddRole, ApportionRes, ResDimList }, components: {
YTable,
AddRole,
ApportionMenu,
ApportionRes,
},
data() { data() {
const columns = [
{
title: "序号",
dataIndex: "num",
width: "65px",
scopedSlots: {
customRender: "num",
},
},
{
title: "角色名称",
dataIndex: "name",
},
{
title: "备注",
dataIndex: "remark",
},
{
title: "操作",
width: "20% ",
scopedSlots: { customRender: "action" },
},
];
return { return {
columns,
loading: false, 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, size: 10,
total: 0, total: 0,
pageSizeOptions, tableData: [], // 表格数据
searchValue: "", // 搜索
tableData: [],
selectedRowKeys: [], selectedRowKeys: [],
dict: {}, // 字典 menuShow: false,
addVisible: false, roleInfo: {},
resVisible: false, menuList: [],
resDimListVisible: false, resShow: false,
title: "新增角色",
}; };
}, },
created() { created() {
this.getMenuList();
this.getRoleList(); this.getRoleList();
}, },
methods: { 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() { async getRoleList() {
this.loading = true; this.loading = true;
let res = await getRoleList({ const res = await getRoleList({
current: this.current, name: this.name,
page: this.page,
size: this.size, size: this.size,
name: this.searchValue,
}); });
this.loading = false; this.loading = false;
if (res.data.code == 1) { if (res.data.code === 1) {
let { data, total } = res.data.data; let { data, total } = res.data.data;
if (!data.length && this.current > 1) { if (!data.length && this.page > 1) {
this.current -= 1; this.page -= 1;
this.getRoleList(); this.getRoleList();
} }
this.tableData = data; this.tableData = data;
this.total = total; this.total = total;
} }
}, },
// 新增
handleAdd() { handleSearch() {
this.title = "新增角色"; this.page = 1;
this.$refs.AddRole.onAdd();
this.addVisible = true;
},
// 搜索
onSearch() {
this.current = 1;
this.getRoleList(); this.getRoleList();
}, },
// 分页 handleResetSearch() {
handleChange(num) { this.name = "";
this.current = num; this.page = 1;
this.getRoleList(); this.getRoleList();
}, },
// 改变每页显示数量 handleAddRole() {
showSizeChange(current, size) { this.title = "新增";
this.current = current; this.$refs.AddRole.onAdd();
this.size = size; this.showAddRole = true;
this.getRoleList();
}, },
// 选择 handleEdit(row) {
onSelectChange(keys) { this.title = "编辑";
this.selectedRowKeys = keys; this.$refs.AddRole.onEdit(row);
this.showAddRole = true;
}, },
// 批量删除
handleDelAll() { handleBatchDel() {
if (!this.selectedRowKeys.length) { if (!this.selectedRowKeys.length) {
this.$message.warn("请先勾选数据"); this.$message.warning("请先勾选数据");
return; return;
} }
let ids = this.selectedRowKeys.join(","); let ids = this.selectedRowKeys.join(",");
this.handleDel(ids); this.handleDel(ids);
}, },
// 编辑 onSelectChange(keys) {
handleEdit(row) { this.selectedRowKeys = keys;
this.title = "编辑角色";
this.$refs.AddRole.onEdit(row);
this.addVisible = true;
}, },
// 删除 // 删除
handleDel(id) { handleDel(id) {
let _this = this;
this.$confirm({ this.$confirm({
title: "系统提示", title: "系统提示:",
content: "删除不可恢复,确定要删除吗?", content: "删除不可恢复,是否继续?",
okText: "确定",
okType: "danger", okType: "danger",
cancelText: "取消", cancelText: "取消",
centered: true, centered: true,
icon: "exclamation-circle",
maskClosable: true, maskClosable: true,
async onOk() { icon: "exclamation-circle",
onOk: async () => {
let res = await delRole({ id }); let res = await delRole({ id });
if (res.data.code == 1) { let { code } = res.data;
_this.$message.success(res.data.msg); if (code === 1) {
_this.getRoleList(); this.$message.success("删除成功");
this.getRoleList();
} }
}, },
onCancel() { onCancel() {},
console.log("Cancel");
},
}); });
}, },
// 分配资源
apportion(row) { apportion(row) {
this.$refs.ApportionRes.onAdd(row.id); this.$refs.ApportionRes.onAdd(row.id);
this.resVisible = true; this.resShow = true;
}, },
// 资源维度 apportionMenu(row) {
handleResDim(row) { this.roleInfo = row;
this.$refs.ResDimList.getRoleInfo(row); this.$refs.ApportionMenu.onAdd(row);
this.resDimListVisible = true; this.menuShow = true;
}, },
}, },
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped></style>
.role-container {
width: 100%;
height: 100%;
}
</style>
...@@ -41,7 +41,7 @@ import { saveRole } from "@/services/system"; ...@@ -41,7 +41,7 @@ import { saveRole } from "@/services/system";
export default { export default {
components: {}, components: {},
props: { props: {
addVisible: { show: {
required: true, required: true,
type: Boolean, type: Boolean,
default: false, default: false,
...@@ -68,10 +68,10 @@ export default { ...@@ -68,10 +68,10 @@ export default {
computed: { computed: {
Visible: { Visible: {
get() { get() {
return this.addVisible; return this.show;
}, },
set(val) { set(val) {
this.$emit("update:addVisible", val); this.$emit("update:show", val);
}, },
}, },
}, },
...@@ -98,7 +98,7 @@ export default { ...@@ -98,7 +98,7 @@ export default {
this.loading = false; this.loading = false;
if (code == 1) { if (code == 1) {
this.$message.success(msg); this.$message.success(msg);
this.$emit("addSuccess"); this.$emit("success");
this.handleCancel(); 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 @@ ...@@ -20,7 +20,7 @@
</a-checkbox> </a-checkbox>
</div> </div>
<a-checkbox-group <a-checkbox-group
style="width:100%" style="width: 100%"
:value="form.resourceIdList" :value="form.resourceIdList"
@change="onChange($event, v)" @change="onChange($event, v)"
> >
...@@ -52,7 +52,7 @@ import { ...@@ -52,7 +52,7 @@ import {
} from "@/services/system"; } from "@/services/system";
export default { export default {
props: { props: {
visible: { show: {
required: true, required: true,
type: Boolean, type: Boolean,
default: false, default: false,
...@@ -72,10 +72,10 @@ export default { ...@@ -72,10 +72,10 @@ export default {
computed: { computed: {
Visible: { Visible: {
get() { get() {
return this.visible; return this.show;
}, },
set(val) { set(val) {
this.$emit("update:visible", val); this.$emit("update:show", val);
}, },
}, },
}, },
...@@ -109,7 +109,7 @@ export default { ...@@ -109,7 +109,7 @@ export default {
groupByAuth(list) { groupByAuth(list) {
let group = {}; let group = {};
list.forEach((item) => { list.forEach((item) => {
let name = item.name.split("-")[0]; let name = item.groupName;
if (!group[name]) { if (!group[name]) {
group[name] = { group[name] = {
indeterminate: false, indeterminate: false,
......
...@@ -83,7 +83,7 @@ export default { ...@@ -83,7 +83,7 @@ export default {
return { return {
columns, columns,
loading: false, loading: false,
current: 1, page: 1,
size: 10, size: 10,
total: 0, total: 0,
pageSizeOptions, pageSizeOptions,
...@@ -99,7 +99,7 @@ export default { ...@@ -99,7 +99,7 @@ export default {
async getSystemLogsList() { async getSystemLogsList() {
this.loading = true; this.loading = true;
let res = await getSystemLogsList({ let res = await getSystemLogsList({
page: this.current, page: this.page,
size: this.size, size: this.size,
requestUrl: this.searchValue, requestUrl: this.searchValue,
}); });
...@@ -112,7 +112,7 @@ export default { ...@@ -112,7 +112,7 @@ export default {
}, },
// 搜索 // 搜索
onSearch() { onSearch() {
this.current = 1; this.page = 1;
this.getSystemLogsList(); this.getSystemLogsList();
}, },
}, },
......
<template> <template>
<div class="task-set"> <div class="task-set">
<div class="control flex aic jcb mb15 pdr6"> <div class="control flex aic jcb mb15 pdr6">
<div> <a-space>
<a-button type="primary" style="margin-right: 10px" @click="handleAdd" <a-button
type="primary"
v-hasPermi="['system:task:add']"
@click="handleAdd"
>新增</a-button >新增</a-button
> >
<a-button type="danger" @click="handleDelAll">批量删除</a-button> <a-button
</div> type="danger"
v-hasPermi="['system:task:remove']"
@click="handleDelAll"
>批量删除</a-button
>
</a-space>
<div class="search-box"> <div class="search-box">
<a-input-search <a-input-search
placeholder="请输入任务名搜索" placeholder="请输入任务名搜索"
...@@ -53,13 +61,13 @@ ...@@ -53,13 +61,13 @@
<template slot="action" slot-scope="{ record }"> <template slot="action" slot-scope="{ record }">
<a-space size="middle"> <a-space size="middle">
<span <span
href="javascript:;" v-hasPermi="['system:task:edit']"
class="primary pointer" class="primary pointer"
@click="handleEdit(record)" @click="handleEdit(record)"
>编辑</span >编辑</span
> >
<span <span
href="javascript:;" v-hasPermi="['system:task:remove']"
class="delete pointer" class="delete pointer"
@click="handleDel(record.id)" @click="handleDel(record.id)"
>删除</span >删除</span
......
<template> <template>
<div class="user-container"> <div class="user-page">
<div class="control flex aic jcb mb15 pdr6"> <div class="control flex aic jcb mb15 pdr6">
<div> <div></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>
<!-- 操作 --> <a-space>
<template slot="action" slot-scope="text"> <a-select style="width: 120px" placeholder="请选择" v-model="type">
<a-space size="middle"> <a-select-option v-for="(v, key) in typeDict" :key="key" :value="key">
<span class="primary pointer" @click="changeRole(text)" {{ v }}
>分配角色</span </a-select-option>
> </a-select>
</a-space> <a-input placeholder="请输入关键字" v-model="keyWord" />
</template> <a-button type="primary" @click="handleSearch">搜索</a-button>
</a-table> <a-button @click="handleResetSearch">重置</a-button>
</a-space>
</div> </div>
<y-table
:columns="columns"
:data="tableData"
:pageSize.sync="size"
:page.sync="page"
:total="total"
:loading="loading"
@changePagination="getUserList"
>
</y-table>
<!-- 分配角色 --> <!-- 分配角色 -->
<AddUserRole <AddUserRole
ref="AddUserRole" ref="AddUserRole"
:addVisible.sync="addVisible"
:roleList="roleList" :roleList="roleList"
@addSuccess="getUserList" :show.sync="show"
:dict="dict"
@success="getUserList"
></AddUserRole> ></AddUserRole>
</div> </div>
</template> </template>
<script> <script>
import { getUserList, getRoleList } from "@/services/system"; import YTable from "@/components/YTable.vue";
import { pageSizeOptions } from "@/config/pageConfig.js";
import AddUserRole from "./modal/AddUserRole.vue"; import AddUserRole from "./modal/AddUserRole.vue";
import { mapState } from "vuex"; import { getUserList } from "@/services/system";
let typeDict = {
loginName: "按登录名",
realName: "按用户姓名",
mobile: "按手机号码",
};
export default { export default {
components: { AddUserRole }, components: { YTable, AddUserRole },
data() { data() {
const columns = [ return {
{ typeDict,
title: "序号", loading: false,
dataIndex: "num", show: false,
width: "65px", columns: [
scopedSlots: { {
customRender: "num", title: "序号",
dataIndex: "num",
width: "65px",
customRender: (text, record, index) => {
return (this.page - 1) * this.size + index + 1;
},
}, },
}, {
{ title: "登录名",
title: "登录名", dataIndex: "loginName",
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: "realName",
title: "状态",
dataIndex: "status",
customRender: (text) => {
return <a-tag>{this.dict.status[text]}</a-tag>;
}, },
}, {
title: "手机号码",
{ dataIndex: "mobile",
title: "操作", },
width: "120px", {
scopedSlots: { customRender: "action" }, title: "所属角色",
}, dataIndex: "roleIds",
]; customRender: (text) => {
return { if (text) {
columns, return text.split(",").map((v) => {
loading: false, return (
current: 1, <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, size: 10,
total: 0, total: 0,
pageSizeOptions, tableData: [], // 表格数据
searchForm: { dict: {},
loginName: "", roleList: [],
realName: "",
},
tableData: [],
roleList: [], // 角色列表
selectedRowKeys: [],
dict: {}, // 字典
addVisible: false,
title: "新增",
loginNames: ["admin", "administrator1", "Administrator"],
}; };
}, },
computed: {
...mapState("site", ["userInfo"]),
},
created() { created() {
this.getRoleList();
this.getUserList(); this.getUserList();
}, },
methods: { 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() { async getUserList() {
this.loading = true; this.loading = true;
let res = await getUserList({ let obj = {
page: this.current, page: this.page,
size: this.size, size: this.size,
...this.searchForm, };
}); obj[this.type] = this.keyWord;
const res = await getUserList(obj);
this.loading = false; this.loading = false;
if (res.data.code == 1) { if (res.data.code === 1) {
let { data, total, dict } = res.data.data; let {
if (!data.length && this.current > 1) { dict,
this.current -= 1; data: { data, total },
this.getUserList(); } = res.data;
}
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; this.dict = dict;
this.tableData = data;
this.total = total;
} }
}, },
// 新增
handleAdd() { handleSearch() {
this.title = "新增"; this.page = 1;
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(); this.getUserList();
}, },
// 改变每页显示数量 handleResetSearch() {
showSizeChange(current, size) { this.type = "loginName";
this.current = current; this.keyWord = "";
this.size = size; this.page = 1;
this.getUserList(); this.getUserList();
}, },
// 分配角色 apportion(row) {
changeRole(row) { this.show = true;
this.$refs.AddUserRole.onEdit(row); this.$refs.AddUserRole.onEdit(row);
this.addVisible = true;
}, },
}, },
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.user-container { .user-page {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
......
...@@ -27,9 +27,12 @@ ...@@ -27,9 +27,12 @@
v-model="form.roleIds" v-model="form.roleIds"
placeholder="请选择角色" placeholder="请选择角色"
> >
<a-select-option v-for="v in roleList" :key="v.id" :value="v.id">{{ <a-select-option
v.name v-for="(v, key) in dict.roleIds"
}}</a-select-option> :key="key"
:value="key"
>{{ v }}</a-select-option
>
</a-select> </a-select>
</a-form-model-item> </a-form-model-item>
</a-form-model> </a-form-model>
...@@ -43,15 +46,15 @@ import { saveUser } from "@/services/system"; ...@@ -43,15 +46,15 @@ import { saveUser } from "@/services/system";
export default { export default {
components: {}, components: {},
props: { props: {
addVisible: { show: {
required: true, required: true,
type: Boolean, type: Boolean,
default: false, default: false,
}, },
roleList: { dict: {
required: true, required: true,
type: Array, type: Object,
default: () => [], default: () => {},
}, },
}, },
data() { data() {
...@@ -68,10 +71,10 @@ export default { ...@@ -68,10 +71,10 @@ export default {
computed: { computed: {
Visible: { Visible: {
get() { get() {
return this.addVisible; return this.show;
}, },
set(val) { set(val) {
this.$emit("update:addVisible", val); this.$emit("update:show", val);
}, },
}, },
}, },
...@@ -87,7 +90,7 @@ export default { ...@@ -87,7 +90,7 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
this.form = { ...row }; this.form = { ...row };
if (this.form.roleIds) { if (this.form.roleIds) {
this.form.roleIds = this.form.roleIds.split(",").map(Number); this.form.roleIds = this.form.roleIds.split(",");
} else { } else {
this.form.roleIds = []; this.form.roleIds = [];
} }
...@@ -109,7 +112,7 @@ export default { ...@@ -109,7 +112,7 @@ export default {
let { code, msg } = res.data; let { code, msg } = res.data;
if (code == 1) { if (code == 1) {
this.$message.success(msg); this.$message.success(msg);
this.$emit("addSuccess"); this.$emit("success");
this.handleCancel(); this.handleCancel();
} }
} }
......
...@@ -128,8 +128,13 @@ ...@@ -128,8 +128,13 @@
</div> </div>
<div class="on btn pdr6"> <div class="on btn pdr6">
<div> <div>
<a-button type="primary" @click="showModal">新增人员</a-button> <a-button
<a-dropdown> type="primary"
v-hasPermi="['personnel:add']"
@click="showModal"
>新增人员</a-button
>
<a-dropdown v-hasPermi="['personnel:more']">
<a-menu slot="overlay"> <a-menu slot="overlay">
<a-menu-item key="1"> <a-menu-item key="1">
<a-upload <a-upload
...@@ -258,13 +263,22 @@ ...@@ -258,13 +263,22 @@
<!-- 操作 --> <!-- 操作 -->
<span slot="action" slot-scope="{ record }"> <span slot="action" slot-scope="{ record }">
<a-space> <a-space>
<span class="primary pointer" @click="editModal(record)" <span
class="primary pointer"
v-hasPermi="['personnel:edit']"
@click="editModal(record)"
>编辑</span >编辑</span
> >
<span class="primary pointer" @click="changePwd(record)" <span
class="primary pointer"
v-hasPermi="['personnel:editPwd']"
@click="changePwd(record)"
>修改密码</span >修改密码</span
> >
<span class="delete pointer" @click="handleDel(record.id)" <span
class="delete pointer"
v-hasPermi="['personnel:remove']"
@click="handleDel(record.id)"
>删除</span >删除</span
> >
</a-space> </a-space>
......
<template> <template>
<exception-page <exception-page
home-route="/website" :home-route="homeRoute"
:style="`min-height: ${minHeight}`" :style="`min-height: ${minHeight}`"
type="404" type="404"
/> />
...@@ -14,12 +14,15 @@ export default { ...@@ -14,12 +14,15 @@ export default {
components: { ExceptionPage }, components: { ExceptionPage },
computed: { computed: {
...mapState("setting", ["pageMinHeight"]), ...mapState("setting", ["pageMinHeight"]),
...mapState("site", ["menus"]),
minHeight() { minHeight() {
return this.pageMinHeight ? this.pageMinHeight + "px" : "100vh"; return this.pageMinHeight ? this.pageMinHeight + "px" : "100vh";
}, },
homeRoute() {
return this.menus[0].path;
},
}, },
}; };
</script> </script>
<style scoped lang="less"> <style scoped lang="less"></style>
</style>
// import TabsView from "@/layouts/tabs/TabsView"; // import TabsView from "@/layouts/tabs/TabsView";
// import BlankView from "@/layouts/BlankView"; // import BlankView from "@/layouts/BlankView";
import Layouts from "@/layouts/Layouts"; // import Layouts from "@/layouts/Layouts";
// import PageView from '@/layouts/PageView' // import PageView from '@/layouts/PageView'
import NewPageLayout from "@/layouts/NewPageLayout";
// 路由配置 // 路由配置
const options = { const options = {
...@@ -13,376 +14,415 @@ const options = { ...@@ -13,376 +14,415 @@ const options = {
}, },
{ {
path: "/", path: "/",
name: "首页", name: "/",
component: Layouts, component: NewPageLayout,
redirect: "/website", redirect: "/jump",
children: [ children: [
{ {
path: "/website", path: "/appmarket/appdetails",
name: "站点管理", name: "appdetails",
meta: { component: () => import("@/pages/basicset/appmarket/AppDetails"),
icon: "bank", redirect: "/appmarket/appdetails/appdetailspage",
},
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: [ children: [
{ {
path: "manage", path: "appdetailspage",
name: "模块管理", component: () =>
component: () => import("@/pages/basicset/deploy/deploy"), import("@/pages/basicset/appmarket/components/AppDetailsPage"),
meta: { meta:{
invisible: true, activeMenu:'/appmarket'
},
},
{
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", path: "dataupdate",
name: "",
component: () => component: () =>
import("@/pages/basicset/hall/hallmanage/HallManage.vue"), import("@/pages/basicset/appmarket/components/DataUpdate"),
meta: { meta:{
invisible: true, activeMenu:'/appmarket'
}, },
}, },
{ {
path: "hallwindow", path: "fieldconfig",
name: "大厅窗口管理",
meta: {
invisible: true,
},
component: () => 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", // path: "/website",
component: () => import("@/pages/basicset/appmarket/Index"), // name: "站点管理",
meta: { // meta: {
icon: "shop", // icon: "bank",
}, // },
children: [ // component: () => import("@/pages/basicset/site/website"),
{ // },
path: "", // {
name: "应用集市", // path: "/business",
component: () => import("@/pages/basicset/appmarket/AppMarket"), // meta: {
meta: { invisible: true }, // icon: "book",
redirect: "/appmarket/terminalapp", // },
children: [ // component: () => import("@/pages/basicset/business/Index"),
{ // children: [
path: "terminalapp", // {
component: () => // path: "",
import("@/pages/basicset/appmarket/components/TerminalApp"), // name: "业务事项管理",
meta: { // meta: {
invisible: true, // icon: "book",
// keepAlive: true, // invisible: true,
}, // },
}, // component: () => import("@/pages/basicset/business/business"),
{ // redirect: "/business/businessmanage",
path: "moveapp", // children: [
component: () => // // 业务管理
import("@/pages/basicset/appmarket/components/MoveApp"), // {
meta: { // path: "businessmanage",
invisible: true, // meta: {
// keepAlive: true, // invisible: true,
}, // },
}, // component: () =>
{ // import(
path: "blackapp", // "@/pages/basicset/business/components/businessTabs1"
component: () => // ),
import("@/pages/basicset/appmarket/components/BlackApp"), // },
meta: { // // 事项管理
invisible: true, // {
}, // path: "mattermanage",
}, // meta: {
{ // invisible: true,
path: "appTheme", // },
component: () => // component: () =>
import("@/pages/basicset/appmarket/components/AppTheme"), // import(
meta: { // "@/pages/basicset/business/components/businessTabs2"
invisible: true, // ),
}, // },
}, // // 业务事项关联
], // {
}, // path: "businessinmanage",
{ // meta: {
path: "appdetails", // invisible: true,
name: "应用详情", // },
component: () => import("@/pages/basicset/appmarket/AppDetails"), // component: () =>
meta: { invisible: true }, // import(
redirect: "/appmarket/appdetails/appdetailspage", // "@/pages/basicset/business/components/businessTabs3"
children: [ // ),
{ // },
path: "appdetailspage", // // 办事指南事项管理
component: () => // {
import( // path: "workguide",
"@/pages/basicset/appmarket/components/AppDetailsPage" // meta: {
), // invisible: true,
meta: { // },
invisible: true, // component: () =>
}, // import(
}, // "@/pages/basicset/business/components/businessTabs4"
{ // ),
path: "dataupdate", // },
component: () => // ],
import("@/pages/basicset/appmarket/components/DataUpdate"), // },
meta: { // {
invisible: true, // path: "addmatter",
}, // name: "新增事项",
}, // component: () => import("@/pages/basicset/addmatter/AddMatter"),
{ // meta: { invisible: true },
path: "fieldconfig", // },
component: () => // {
import("@/pages/basicset/appmarket/components/FieldConfig"), // path: "synopsis",
meta: { // name: "事项概要",
invisible: true, // component: () => import("@/pages/basicset/addmatter/Synopsis"),
}, // meta: { invisible: true },
}, // },
], // ],
}, // },
], // {
}, // path: "/department",
{ // meta: {
path: "/system", // icon: "audit",
name: "系统设置", // },
component: () => import("@/pages/basicset/system/System"), // component: () => import("@/pages/basicset/dept/Index"),
meta: { // children: [
icon: "global", // {
}, // path: "",
redirect: "system/parameter", // name: "部门及窗口管理",
children: [ // component: () => import("@/pages/basicset/dept/department"),
{ // meta: { invisible: true, keepAlive: true },
path: "user", // },
name: "用户管理", // {
component: () => import("@/pages/basicset/system/user/User"), // path: "adddepartment",
meta: { invisible: true }, // name: "新增窗口事项",
}, // meta: {
{ // invisible: true,
path: "role", // },
name: "角色管理", // component: () => import("@/pages/basicset/dept/addWindowMatter"),
component: () => import("@/pages/basicset/system/role/Role"), // },
meta: { invisible: true }, // ],
}, // },
{ // {
path: "resource", // path: "/personnel",
name: "资源管理", // name: "工作人员管理",
component: () => // meta: {
import("@/pages/basicset/system/resourceManage/Resource"), // icon: "idcard",
meta: { invisible: true }, // },
}, // component: () => import("@/pages/basicset/workman/personnel"),
{ // },
path: "dimension", // {
name: "维度管理", // path: "/festival",
component: () => // name: "节假日管理",
import("@/pages/basicset/system/dimension/Dimension"), // meta: {
meta: { invisible: true }, // icon: "carry-out",
}, // },
{ // component: () => import("@/pages/basicset/holiday/festival"),
path: "parameter", // },
name: "系统参数", // {
component: () => // path: "/deploy",
import("@/pages/basicset/system/parameter/Parameter"), // name: "部署模块管理",
meta: { invisible: true }, // meta: {
}, // icon: "appstore",
{ // roles: ["admin"],
path: "task", // },
name: "任务信息", // component: () => import("@/pages/basicset/deploy/Index"),
component: () => import("@/pages/basicset/system/task/TaskSet"), // redirect: "/deploy/manage",
meta: { invisible: true }, // children: [
}, // {
{ // path: "manage",
path: "systemlogs", // name: "模块管理",
name: "操作日志", // component: () => import("@/pages/basicset/deploy/deploy"),
component: () => // meta: {
import("@/pages/basicset/system/systemlogs/SystemLogs"), // invisible: true,
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 Vue from "vue";
import VueRouter from "vue-router"; import VueRouter from "vue-router";
import { formatRoutes } from "@/utils/routerUtil"; import { formatRoutes } from "@/utils/routerUtil";
import { i18n } from "@/utils/i18n"; // import { i18n } from "@/utils/i18n";
import store from "@/store"; 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); Vue.use(VueRouter);
//解决重复路由报错 //解决重复路由报错
const originalPush = VueRouter.prototype.push; const originalPush = VueRouter.prototype.push;
...@@ -31,7 +33,7 @@ const routes = [ ...@@ -31,7 +33,7 @@ const routes = [
]; ];
formatRoutes(routes); formatRoutes(routes);
const router = new VueRouter({ const router = new VueRouter({
routes, routes: [...routes, ...options.routes],
}); });
// 不需要登录拦截的路由配置 // 不需要登录拦截的路由配置
...@@ -62,47 +64,74 @@ function initRouter() { ...@@ -62,47 +64,74 @@ function initRouter() {
} }
// 判断权限 // 判断权限
function permission(router, role) { // function permission(router, role) {
if (router.meta && router.meta.roles) { // if (router.meta && router.meta.roles) {
return router.meta.roles.includes(role); // return router.meta.roles.includes(role);
} else { // } else {
return true; // return true;
} // }
} // }
// 计算动态路由 // 计算动态路由
function calcRouters(dynamicRouter, role) { // function calcRouters(dynamicRouter, role) {
// 过滤 // // 过滤
let res = dynamicRouter.filter((v) => { // let res = dynamicRouter.filter((v) => {
// 判断是否有权限访问此路由 // // 判断是否有权限访问此路由
if (permission(v, role)) { // 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) { if (v.children) {
// 递归 v.children = menusFilter(v.children);
v.children = calcRouters(v.children, role);
} }
return true; return v;
} else {
return false;
} }
}); });
return res; return router;
} }
// 动态菜单 // 动态菜单
function createMenus() { export function calcMenu() {
let role = store.getters["site/userInfo"].name; let menusList = store.getters["site/menusList"];
if (!role) return; let dynamicRouter = generateRoutes(menusList);
let options = initRouter(); dynamicRouter.forEach((v) => {
let routesArr = calcRouters(options.routes, role); router.addRoute("/", v);
const rootRoute = routesArr.find((item) => item.path === "/"); });
const menuRoutes = rootRoute && rootRoute.children;
mergeI18nFromRoutes(i18n, menuRoutes); let menus = menusFilter(dynamicRouter);
if (menuRoutes) { store.commit("site/SET_menus", menus);
routesArr.forEach((v) => {
router.addRoute(v);
});
store.commit("setting/setMenuData", menuRoutes);
}
} }
createMenus(); calcMenu();
export { loginIgnore, initRouter, createMenus, router };
export { loginIgnore, initRouter, router };
...@@ -382,6 +382,8 @@ module.exports = { ...@@ -382,6 +382,8 @@ module.exports = {
delete: `${BASE_URL}/base/role/delete`, delete: `${BASE_URL}/base/role/delete`,
authList: `${BASE_URL}/base/role/auth/list`, authList: `${BASE_URL}/base/role/auth/list`,
distributionSource: `${BASE_URL}/base/role/auth/distributionSource`, distributionSource: `${BASE_URL}/base/role/auth/distributionSource`,
editMenu: `${BASE_URL}/base/role/auth/editMenu`,
distributionMenu: `${BASE_URL}/base/role/auth/distributionMenu`,
}, },
// 资源 // 资源
resource: { resource: {
...@@ -390,6 +392,17 @@ module.exports = { ...@@ -390,6 +392,17 @@ module.exports = {
save: `${BASE_URL}/base/resource/save`, save: `${BASE_URL}/base/resource/save`,
delete: `${BASE_URL}/base/resource/delete`, delete: `${BASE_URL}/base/resource/delete`,
refreshUrl: `${BASE_URL}/base/resource/refreshUrl`, 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) { ...@@ -94,6 +94,15 @@ export async function getRoleResourceList(data) {
export async function saveRoleResource(data) { export async function saveRoleResource(data) {
return request(system.role.distributionSource, METHOD.POST, 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) { ...@@ -117,6 +126,10 @@ export async function delResource(data) {
export async function refreshResource(data) { export async function refreshResource(data) {
return request(system.resource.refreshUrl, METHOD.POST, 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) { ...@@ -155,3 +168,28 @@ export async function saveDimRes(data) {
export async function delDimRes(data) { export async function delDimRes(data) {
return request(system.dimensionResource.delete, METHOD.GET, 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 { ...@@ -16,6 +16,13 @@ export default {
curSkin: {}, // 当前选中预览皮肤 curSkin: {}, // 当前选中预览皮肤
curSkinIndex: 0, // 当前选中皮肤索引 curSkinIndex: 0, // 当前选中皮肤索引
curProduct: {}, // 皮肤设置当前选中产品 curProduct: {}, // 皮肤设置当前选中产品
siteInfo: {}, // 站点信息
permissions: [], // 按钮权限
menusList: [], // 原始菜单列表
menus: [], // 格式化菜单列表
routes: [], // 路由列表
secondaryRoutes: [], // 二级路由
activatedFirst: "", // 当前激活的一级菜单
}, },
getters: { getters: {
SiteTree(state) { SiteTree(state) {
...@@ -42,8 +49,28 @@ export default { ...@@ -42,8 +49,28 @@ export default {
imageResolutions(state) { imageResolutions(state) {
return state.imageResolution; return state.imageResolution;
}, },
menusList(state) {
return state.menusList;
},
permissions(state) {
return state.permissions;
},
}, },
mutations: { 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) { SET_path(state, path) {
state.path = path; state.path = path;
}, },
......
...@@ -22,10 +22,10 @@ export function isRegExp(v) { ...@@ -22,10 +22,10 @@ export function isRegExp(v) {
export function enquireScreen(call) { export function enquireScreen(call) {
const handler = { const handler = {
match: function() { match: function () {
call && call(true); call && call(true);
}, },
unmatch: function() { unmatch: function () {
call && call(false); call && call(false);
}, },
}; };
...@@ -48,7 +48,7 @@ export const extractTree = (arrs, childs, attrArr) => { ...@@ -48,7 +48,7 @@ export const extractTree = (arrs, childs, attrArr) => {
} }
let list = []; let list = [];
const getObj = (arr) => { const getObj = (arr) => {
arr.forEach(function(row) { arr.forEach(function (row) {
let obj = {}; let obj = {};
attrList.forEach((item) => { attrList.forEach((item) => {
obj[item] = row[item]; obj[item] = row[item];
...@@ -111,3 +111,150 @@ export class SessionCrypto { ...@@ -111,3 +111,150 @@ export class SessionCrypto {
window.sessionStorage.removeItem(key); 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: ...@@ -6319,7 +6319,7 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2:
dependencies: dependencies:
function-bind "^1.1.2" 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" version "1.2.0"
resolved "https://registry.npmmirror.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" resolved "https://registry.npmmirror.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
...@@ -11518,7 +11518,15 @@ vue-style-loader@^4.1.0, vue-style-loader@^4.1.2: ...@@ -11518,7 +11518,15 @@ vue-style-loader@^4.1.0, vue-style-loader@^4.1.2:
hash-sum "^1.0.2" hash-sum "^1.0.2"
loader-utils "^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" version "2.7.16"
resolved "https://registry.npmmirror.com/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz#c81b2d47753264c77ac03b9966a46637482bb03b" resolved "https://registry.npmmirror.com/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz#c81b2d47753264c77ac03b9966a46637482bb03b"
integrity sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ== integrity sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==
...@@ -11531,7 +11539,12 @@ vue-template-es2015-compiler@^1.9.0: ...@@ -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" resolved "https://registry.npmmirror.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== 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" version "2.7.16"
resolved "https://registry.npmmirror.com/vue/-/vue-2.7.16.tgz#98c60de9def99c0e3da8dae59b304ead43b967c9" resolved "https://registry.npmmirror.com/vue/-/vue-2.7.16.tgz#98c60de9def99c0e3da8dae59b304ead43b967c9"
integrity sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw== integrity sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==
......
import http from "../request/http";
let baseURL = process.env.VUE_APP_API_BASE_URL;
// 获取消息任务列表
export function getMsgTaskList(params) {
return http.post(`${baseURL}/zwfw/message/task/list`, params);
}
// 删除消息任务
export function deleteMsgTask(params) {
return http.get(`${baseURL}/zwfw/message/task/delete`, params);
}
// 查询消息配置列表
export function getMsgConfigList(params) {
return http.post(`${baseURL}/zwfw/message/config/list`, params);
}
// 查看消息配置
export function getMsgConfig(params) {
return http.get(`${baseURL}/zwfw/message/config/info`, params);
}
// 保存消息配置
export function saveMsgConfig(params) {
return http.post(`${baseURL}/zwfw/message/config/save`, params);
}
// 删除消息配置
export function deleteMsgConfig(params) {
return http.get(`${baseURL}/zwfw/message/config/delete`, params);
}
...@@ -557,7 +557,7 @@ img { ...@@ -557,7 +557,7 @@ img {
white-space: nowrap; white-space: nowrap;
} }
.addclass,.ant-btn-primary { .addclass,.ant-btn-primary:not(.ant-btn-background-ghost) {
background: linear-gradient(90deg, #5ab6ff 0%, #2e9aff 100%) !important; background: linear-gradient(90deg, #5ab6ff 0%, #2e9aff 100%) !important;
color: #fff !important; color: #fff !important;
border: none !important; border: none !important;
......
...@@ -54,6 +54,12 @@ ...@@ -54,6 +54,12 @@
<div class="content unicode" style="display: block;"> <div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe617;</span>
<div class="name">notice</div>
<div class="code-name">&amp;#xe617;</div>
</li>
<li class="dib"> <li class="dib">
<span class="icon iconfont">&#xe901;</span> <span class="icon iconfont">&#xe901;</span>
<div class="name">闭眼睛</div> <div class="name">闭眼睛</div>
...@@ -102,9 +108,9 @@ ...@@ -102,9 +108,9 @@
<pre><code class="language-css" <pre><code class="language-css"
>@font-face { >@font-face {
font-family: 'iconfont'; font-family: 'iconfont';
src: url('iconfont.woff2?t=1693536528455') format('woff2'), src: url('iconfont.woff2?t=1744101949457') format('woff2'),
url('iconfont.woff?t=1693536528455') format('woff'), url('iconfont.woff?t=1744101949457') format('woff'),
url('iconfont.ttf?t=1693536528455') format('truetype'); url('iconfont.ttf?t=1744101949457') format('truetype');
} }
</code></pre> </code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3> <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
...@@ -130,6 +136,15 @@ ...@@ -130,6 +136,15 @@
<div class="content font-class"> <div class="content font-class">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-notice"></span>
<div class="name">
notice
</div>
<div class="code-name">.icon-notice
</div>
</li>
<li class="dib"> <li class="dib">
<span class="icon iconfont icon-hidden"></span> <span class="icon iconfont icon-hidden"></span>
<div class="name"> <div class="name">
...@@ -202,6 +217,14 @@ ...@@ -202,6 +217,14 @@
<div class="content symbol"> <div class="content symbol">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-notice"></use>
</svg>
<div class="name">notice</div>
<div class="code-name">#icon-notice</div>
</li>
<li class="dib"> <li class="dib">
<svg class="icon svg-icon" aria-hidden="true"> <svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-hidden"></use> <use xlink:href="#icon-hidden"></use>
......
@font-face { @font-face {
font-family: "iconfont"; /* Project id 4222008 */ font-family: "iconfont"; /* Project id 4222008 */
src: url('iconfont.woff2?t=1693536528455') format('woff2'), src: url('iconfont.woff2?t=1744101949457') format('woff2'),
url('iconfont.woff?t=1693536528455') format('woff'), url('iconfont.woff?t=1744101949457') format('woff'),
url('iconfont.ttf?t=1693536528455') format('truetype'); url('iconfont.ttf?t=1744101949457') format('truetype');
} }
.iconfont { .iconfont {
...@@ -13,6 +13,10 @@ ...@@ -13,6 +13,10 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-notice:before {
content: "\e617";
}
.icon-hidden:before { .icon-hidden:before {
content: "\e901"; content: "\e901";
} }
......
window._iconfont_svg_string_4222008='<svg><symbol id="icon-hidden" viewBox="0 0 1024 1024"><path d="M469.333333 681.386667c-36.053333-2.432-71.253333-8.533333-104.96-17.92l-69.802666 149.674666a42.368 42.368 0 0 1-56.533334 20.266667 42.666667 42.666667 0 0 1-20.821333-56.32l66.986667-143.658667a451.712 451.712 0 0 1-148.906667-112.682666 388.693333 388.693333 0 0 1-70.570667-119.338667 42.666667 42.666667 0 1 1 80.128-29.354667 303.445333 303.445333 0 0 0 55.210667 93.098667C270.634667 547.413333 383.018667 597.333333 505.728 597.333333c122.752 0 235.136-49.962667 305.706667-132.181333a303.445333 303.445333 0 0 0 55.210666-93.098667 42.666667 42.666667 0 0 1 80.128 29.354667 388.693333 388.693333 0 0 1-70.570666 119.338667 423.68 423.68 0 0 1-18.773334 20.48l104.362667 104.362666a42.666667 42.666667 0 0 1-0.298667 60.032 42.368 42.368 0 0 1-60.032 0.298667l-109.653333-109.653333c-20.48 14.08-42.24 26.581333-65.024 37.418666l66.901333 143.36a42.666667 42.666667 0 0 1-20.821333 56.362667 42.368 42.368 0 0 1-56.533333-20.266667l-69.717334-149.546666a520.533333 520.533333 0 0 1-91.946666 16.810666v130.645334A42.666667 42.666667 0 0 1 512 853.333333c-23.722667 0-42.666667-18.944-42.666667-42.24v-129.706666z" fill="#3D3D3D" ></path><path d="M176.128 524.373333a42.368 42.368 0 0 1 60.032 0.256 42.666667 42.666667 0 0 1 0.298667 60.074667l-121.216 121.216a42.368 42.368 0 0 1-60.074667-0.298667 42.666667 42.666667 0 0 1-0.298667-60.032l121.258667-121.258666z" fill="#3D3D3D" ></path></symbol><symbol id="icon-dot" viewBox="0 0 1024 1024"><path d="M512 320a192.064 192.064 0 0 1 0 384 192 192 0 0 1 0-384z" fill="" ></path></symbol><symbol id="icon-pwd" viewBox="0 0 1024 1024"><path d="M725.4 928.3H299.7c-88 0-159.6-71.6-159.6-159.6V555.8c0-88 71.6-159.6 159.6-159.6h425.7c88 0 159.6 71.6 159.6 159.6v212.8c0 88.1-71.6 159.7-159.6 159.7zM299.7 460c-52.8 0-95.8 43-95.8 95.8v212.8c0 52.8 43 95.8 95.8 95.8h425.7c52.8 0 95.8-43 95.8-95.8V555.8c0-52.8-43-95.8-95.8-95.8H299.7z" fill="#A1A0A5" ></path><path d="M778.6 406.8h-63.9c0-110.9-90.2-244.8-202.2-244.8S310.3 296 310.3 406.8h-63.9c0-142.7 116.2-308.6 266.1-308.6s266.1 165.9 266.1 308.6z" fill="#A1A0A5" ></path></symbol><symbol id="icon-show" viewBox="0 0 1024 1024"><path d="M678.976 586.24c0 92.224-74.752 166.976-166.976 166.976S345.024 678.464 345.024 586.24 419.776 419.2 512 419.2s166.976 74.816 166.976 167.04z" fill="#666666" ></path><path d="M512 266.112C229.248 266.112 0 586.24 0 586.24s229.248 320.128 512 320.128 512-320.128 512-320.128-229.248-320.128-512-320.128z m0 532.992c-117.568 0-212.864-95.296-212.864-212.864 0-117.568 95.296-212.864 212.864-212.864s212.864 95.296 212.864 212.864c0 117.568-95.296 212.864-212.864 212.864z" fill="#666666" ></path><path d="M678.976 586.24c0 92.224-74.752 166.976-166.976 166.976S345.024 678.464 345.024 586.24 419.776 419.2 512 419.2s166.976 74.816 166.976 167.04z" fill="#666666" ></path><path d="M678.976 586.24c0 92.224-74.752 166.976-166.976 166.976S345.024 678.464 345.024 586.24 419.776 419.2 512 419.2s166.976 74.816 166.976 167.04z" fill="#666666" ></path></symbol><symbol id="icon-user" viewBox="0 0 1024 1024"><path d="M602.08 960.576H423.488c-169.408 0-303.2 0-303.2-87.872v-17.568c0-164.672 136.032-298.624 303.2-298.624H602.08c167.168 0 303.2 133.952 303.2 298.624v17.568c-0.032 87.872-140.544 87.872-303.2 87.872zM423.456 609.184c-138.112 0-250.496 110.304-250.496 245.92v17.568c0 35.168 144.768 35.168 250.496 35.168h178.592c87.52 0 250.496 0 250.496-35.168v-17.568c0-135.616-112.384-245.92-250.496-245.92H423.456z m80.384-70.304c-132.736 0-240.672-106.4-240.672-237.184S371.104 64.544 503.84 64.544s240.672 106.368 240.672 237.152S636.544 538.88 503.84 538.88zM315.872 301.696c0 101.696 84.32 184.48 187.968 184.48s187.968-82.752 187.968-184.48-84.32-184.448-187.968-184.448S315.872 200 315.872 301.696z" ></path></symbol></svg>',function(n){var t=(t=document.getElementsByTagName("script"))[t.length-1],e=t.getAttribute("data-injectcss"),t=t.getAttribute("data-disable-injectsvg");if(!t){var i,o,c,l,a,d=function(t,e){e.parentNode.insertBefore(t,e)};if(e&&!n.__iconfont__svg__cssinject__){n.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>")}catch(t){console&&console.log(t)}}i=function(){var t,e=document.createElement("div");e.innerHTML=n._iconfont_svg_string_4222008,(e=e.getElementsByTagName("svg")[0])&&(e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.width=0,e.style.height=0,e.style.overflow="hidden",e=e,(t=document.body).firstChild?d(e,t.firstChild):t.appendChild(e))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(i,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),i()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(c=i,l=n.document,a=!1,h(),l.onreadystatechange=function(){"complete"==l.readyState&&(l.onreadystatechange=null,s())})}function s(){a||(a=!0,c())}function h(){try{l.documentElement.doScroll("left")}catch(t){return void setTimeout(h,50)}s()}}(window); window._iconfont_svg_string_4222008='<svg><symbol id="icon-notice" viewBox="0 0 1024 1024"><path d="M192 736V416c0-154.816 109.952-283.936 256-313.6V64c0-35.36 28.64-64 64-64s64 28.64 64 64v38.4C722.048 132.064 832 261.184 832 416v320h32.096C899.392 736 928 764.416 928 800c0 35.36-28.64 64-63.904 64H159.904C124.608 864 96 835.584 96 800c0-35.36 28.64-64 63.904-64H192z m416 192c0 53.024-42.976 96-96 96s-96-42.976-96-96h192z" fill="#333333" ></path></symbol><symbol id="icon-hidden" viewBox="0 0 1024 1024"><path d="M469.333333 681.386667c-36.053333-2.432-71.253333-8.533333-104.96-17.92l-69.802666 149.674666a42.368 42.368 0 0 1-56.533334 20.266667 42.666667 42.666667 0 0 1-20.821333-56.32l66.986667-143.658667a451.712 451.712 0 0 1-148.906667-112.682666 388.693333 388.693333 0 0 1-70.570667-119.338667 42.666667 42.666667 0 1 1 80.128-29.354667 303.445333 303.445333 0 0 0 55.210667 93.098667C270.634667 547.413333 383.018667 597.333333 505.728 597.333333c122.752 0 235.136-49.962667 305.706667-132.181333a303.445333 303.445333 0 0 0 55.210666-93.098667 42.666667 42.666667 0 0 1 80.128 29.354667 388.693333 388.693333 0 0 1-70.570666 119.338667 423.68 423.68 0 0 1-18.773334 20.48l104.362667 104.362666a42.666667 42.666667 0 0 1-0.298667 60.032 42.368 42.368 0 0 1-60.032 0.298667l-109.653333-109.653333c-20.48 14.08-42.24 26.581333-65.024 37.418666l66.901333 143.36a42.666667 42.666667 0 0 1-20.821333 56.362667 42.368 42.368 0 0 1-56.533333-20.266667l-69.717334-149.546666a520.533333 520.533333 0 0 1-91.946666 16.810666v130.645334A42.666667 42.666667 0 0 1 512 853.333333c-23.722667 0-42.666667-18.944-42.666667-42.24v-129.706666z" fill="#3D3D3D" ></path><path d="M176.128 524.373333a42.368 42.368 0 0 1 60.032 0.256 42.666667 42.666667 0 0 1 0.298667 60.074667l-121.216 121.216a42.368 42.368 0 0 1-60.074667-0.298667 42.666667 42.666667 0 0 1-0.298667-60.032l121.258667-121.258666z" fill="#3D3D3D" ></path></symbol><symbol id="icon-dot" viewBox="0 0 1024 1024"><path d="M512 320a192.064 192.064 0 0 1 0 384 192 192 0 0 1 0-384z" fill="" ></path></symbol><symbol id="icon-pwd" viewBox="0 0 1024 1024"><path d="M725.4 928.3H299.7c-88 0-159.6-71.6-159.6-159.6V555.8c0-88 71.6-159.6 159.6-159.6h425.7c88 0 159.6 71.6 159.6 159.6v212.8c0 88.1-71.6 159.7-159.6 159.7zM299.7 460c-52.8 0-95.8 43-95.8 95.8v212.8c0 52.8 43 95.8 95.8 95.8h425.7c52.8 0 95.8-43 95.8-95.8V555.8c0-52.8-43-95.8-95.8-95.8H299.7z" fill="#A1A0A5" ></path><path d="M778.6 406.8h-63.9c0-110.9-90.2-244.8-202.2-244.8S310.3 296 310.3 406.8h-63.9c0-142.7 116.2-308.6 266.1-308.6s266.1 165.9 266.1 308.6z" fill="#A1A0A5" ></path></symbol><symbol id="icon-show" viewBox="0 0 1024 1024"><path d="M678.976 586.24c0 92.224-74.752 166.976-166.976 166.976S345.024 678.464 345.024 586.24 419.776 419.2 512 419.2s166.976 74.816 166.976 167.04z" fill="#666666" ></path><path d="M512 266.112C229.248 266.112 0 586.24 0 586.24s229.248 320.128 512 320.128 512-320.128 512-320.128-229.248-320.128-512-320.128z m0 532.992c-117.568 0-212.864-95.296-212.864-212.864 0-117.568 95.296-212.864 212.864-212.864s212.864 95.296 212.864 212.864c0 117.568-95.296 212.864-212.864 212.864z" fill="#666666" ></path><path d="M678.976 586.24c0 92.224-74.752 166.976-166.976 166.976S345.024 678.464 345.024 586.24 419.776 419.2 512 419.2s166.976 74.816 166.976 167.04z" fill="#666666" ></path><path d="M678.976 586.24c0 92.224-74.752 166.976-166.976 166.976S345.024 678.464 345.024 586.24 419.776 419.2 512 419.2s166.976 74.816 166.976 167.04z" fill="#666666" ></path></symbol><symbol id="icon-user" viewBox="0 0 1024 1024"><path d="M602.08 960.576H423.488c-169.408 0-303.2 0-303.2-87.872v-17.568c0-164.672 136.032-298.624 303.2-298.624H602.08c167.168 0 303.2 133.952 303.2 298.624v17.568c-0.032 87.872-140.544 87.872-303.2 87.872zM423.456 609.184c-138.112 0-250.496 110.304-250.496 245.92v17.568c0 35.168 144.768 35.168 250.496 35.168h178.592c87.52 0 250.496 0 250.496-35.168v-17.568c0-135.616-112.384-245.92-250.496-245.92H423.456z m80.384-70.304c-132.736 0-240.672-106.4-240.672-237.184S371.104 64.544 503.84 64.544s240.672 106.368 240.672 237.152S636.544 538.88 503.84 538.88zM315.872 301.696c0 101.696 84.32 184.48 187.968 184.48s187.968-82.752 187.968-184.48-84.32-184.448-187.968-184.448S315.872 200 315.872 301.696z" ></path></symbol></svg>',(i=>{var t=(e=(e=document.getElementsByTagName("script"))[e.length-1]).getAttribute("data-injectcss"),e=e.getAttribute("data-disable-injectsvg");if(!e){var c,n,o,l,a,d=function(t,e){e.parentNode.insertBefore(t,e)};if(t&&!i.__iconfont__svg__cssinject__){i.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>")}catch(t){console&&console.log(t)}}c=function(){var t,e=document.createElement("div");e.innerHTML=i._iconfont_svg_string_4222008,(e=e.getElementsByTagName("svg")[0])&&(e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.width=0,e.style.height=0,e.style.overflow="hidden",e=e,(t=document.body).firstChild?d(e,t.firstChild):t.appendChild(e))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(c,0):(n=function(){document.removeEventListener("DOMContentLoaded",n,!1),c()},document.addEventListener("DOMContentLoaded",n,!1)):document.attachEvent&&(o=c,l=i.document,a=!1,h(),l.onreadystatechange=function(){"complete"==l.readyState&&(l.onreadystatechange=null,s())})}function s(){a||(a=!0,o())}function h(){try{l.documentElement.doScroll("left")}catch(t){return void setTimeout(h,50)}s()}})(window);
\ No newline at end of file \ No newline at end of file
...@@ -5,6 +5,13 @@ ...@@ -5,6 +5,13 @@
"css_prefix_text": "icon-", "css_prefix_text": "icon-",
"description": "", "description": "",
"glyphs": [ "glyphs": [
{
"icon_id": "13071212",
"name": "notice",
"font_class": "notice",
"unicode": "e617",
"unicode_decimal": 58903
},
{ {
"icon_id": "4354835", "icon_id": "4354835",
"name": "闭眼睛", "name": "闭眼睛",
......
<template>
<div>
<a-drawer
:zIndex="2000"
title="消息详情"
placement="right"
width="600px"
:visible="Visible"
@close="onClose"
>
<a-descriptions :column="1">
<a-descriptions-item label="消息类型">
{{ detailsInfo.messageType }}
</a-descriptions-item>
<a-descriptions-item label="消息内容">
{{ detailsInfo.content }}
</a-descriptions-item>
<a-descriptions-item label="消息来源">
{{ detailsInfo.appName }}
</a-descriptions-item>
<a-descriptions-item label="系统提醒时间">
{{ detailsInfo.alarmTime }}
</a-descriptions-item>
<a-descriptions-item label="发送状态">
{{ detailsInfo.sendStatus }}
</a-descriptions-item>
<a-descriptions-item label="接收人">
{{ detailsInfo.msgRecipients }}
</a-descriptions-item>
<a-descriptions-item label="短信提醒时间">
{{ detailsInfo.sendTime }}
</a-descriptions-item>
</a-descriptions>
</a-drawer>
</div>
</template>
<script>
export default {
props: {
show: {
type: Boolean,
required: true,
default: false,
},
detailsInfo: {
type: Object,
required: true,
default: () => {
return {};
},
},
},
data() {
return {};
},
computed: {
Visible: {
get() {
return this.show;
},
set(val) {
this.$emit("update:show", val);
},
},
},
methods: {
onClose() {
this.Visible = false;
},
},
};
</script>
<style lang="less" scoped></style>
<template>
<div>
<!-- <a-checkbox @change="onChange" :checked="value"> Checkbox </a-checkbox> -->
<a-switch
:checked-children="checkedChildren"
:un-checked-children="unCheckedChildren"
:disabled="disabled"
:checked="value"
@change="onChange"
v-bind="$attrs"
/>
</div>
</template>
<script>
export default {
model: {
prop: "checked",
event: "change",
},
props: {
checkedChildren: {
default: "",
},
unCheckedChildren: {
default: "",
},
checked: {
required: true,
},
disabled: {
type: Boolean,
required: false,
default: false,
},
},
computed: {
value() {
return this.checked === 1 || this.checked === "1";
},
},
methods: {
onChange(checked) {
this.$emit("change", checked ? 1 : 0);
this.$emit("onChange", checked ? 1 : 0);
},
},
};
</script>
<style lang="less" scoped></style>
...@@ -366,7 +366,6 @@ const routes = [ ...@@ -366,7 +366,6 @@ const routes = [
}, },
}, },
{ {
path: "windowLeft", path: "windowLeft",
name: "windowLeft", name: "windowLeft",
...@@ -832,6 +831,36 @@ const routes = [ ...@@ -832,6 +831,36 @@ const routes = [
}, },
], ],
}, },
{
path: "messageManage",
name: "messageManage",
redirect: "/home/thePlatformIsSet/messageManage/messageList",
component: () =>
import(
/* webpackChunkName: "menuManagement" */ "@/views/thePlatformIsSet/components/messageManage/MessageManage.vue"
),
meta: { title: "消息服务" },
children: [
{
path: "messageList",
name: "messageList",
component: () =>
import(
/* webpackChunkName: "menuMgmt" */ "@/views/thePlatformIsSet/components/messageManage/MessageList.vue"
),
meta: { title: "消息列表" },
},
{
path: "messageSet",
name: "messageSet",
component: () =>
import(
/* webpackChunkName: "menuMgmt" */ "@/views/thePlatformIsSet/components/messageManage/MessageSet.vue"
),
meta: { title: "消息配置" },
},
],
},
{ {
path: "logService", path: "logService",
name: "logService", name: "logService",
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1500, x: 1500,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1000, x: 1000,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
<Details ref="Details" :visible.sync="visible" :msg="fromData"></Details> <Details ref="Details" :visible.sync="visible" :msg="fromData"></Details>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import storage from "@/utils/js/Storage"; import storage from "@/utils/js/Storage";
import Details from "./components/Details.vue"; import Details from "./components/Details.vue";
...@@ -338,6 +338,5 @@ export default { ...@@ -338,6 +338,5 @@ export default {
}, },
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped></style>
</style>
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1500, x: 1500,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
<FormDetails ref="FormDetails" :visible.sync="visible"></FormDetails> <FormDetails ref="FormDetails" :visible.sync="visible"></FormDetails>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import storage from "@/utils/js/Storage"; import storage from "@/utils/js/Storage";
import FormDetails from "./components/FormDetails.vue"; import FormDetails from "./components/FormDetails.vue";
...@@ -323,6 +323,5 @@ export default { ...@@ -323,6 +323,5 @@ export default {
}, },
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped></style>
</style>
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1000, x: 1000,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
/> />
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import storage from "@/utils/js/Storage"; import storage from "@/utils/js/Storage";
...@@ -364,6 +364,5 @@ export default { ...@@ -364,6 +364,5 @@ export default {
}, },
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped></style>
</style>
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1500, x: 1500,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1500, x: 1500,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:data-source="tableData" :data-source="tableData"
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1500, x: 1500,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:data-source="tableData" :data-source="tableData"
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1500, x: 1500,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
...@@ -55,8 +55,8 @@ ...@@ -55,8 +55,8 @@
</a-table> </a-table>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import storage from "@/utils/js/Storage"; import storage from "@/utils/js/Storage";
import { export2Excel } from "@/utils/js/exportExcel"; import { export2Excel } from "@/utils/js/exportExcel";
...@@ -339,6 +339,5 @@ export default { ...@@ -339,6 +339,5 @@ export default {
}, },
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped></style>
</style>
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1500, x: 1500,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1000, x: 1000,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
...@@ -44,8 +44,8 @@ ...@@ -44,8 +44,8 @@
<FormDetails :userInfo="detailsInfo" :visible.sync="visible"></FormDetails> <FormDetails :userInfo="detailsInfo" :visible.sync="visible"></FormDetails>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import storage from "@/utils/js/Storage"; import storage from "@/utils/js/Storage";
import { export2Excel } from "@/utils/js/exportExcel"; import { export2Excel } from "@/utils/js/exportExcel";
...@@ -315,6 +315,5 @@ export default { ...@@ -315,6 +315,5 @@ export default {
}, },
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped></style>
</style>
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1000, x: 1000,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
...@@ -26,8 +26,8 @@ ...@@ -26,8 +26,8 @@
</a-table> </a-table>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import storage from "@/utils/js/Storage"; import storage from "@/utils/js/Storage";
import { export2Excel } from "@/utils/js/exportExcel"; import { export2Excel } from "@/utils/js/exportExcel";
...@@ -222,6 +222,5 @@ export default { ...@@ -222,6 +222,5 @@ export default {
}, },
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped></style>
</style>
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1500, x: 1500,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
></FormDetails> ></FormDetails>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import storage from "@/utils/js/Storage"; import storage from "@/utils/js/Storage";
...@@ -378,6 +378,5 @@ export default { ...@@ -378,6 +378,5 @@ export default {
}, },
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped></style>
</style>
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1500, x: 1500,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1500, x: 1500,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
...@@ -145,7 +145,10 @@ export default { ...@@ -145,7 +145,10 @@ export default {
title: "有效期限", title: "有效期限",
width: 150, width: 150,
customRender: (text, record) => { customRender: (text, record) => {
return `${record.idcard_UserLifeBegin}-${record.idcard_UserLifeEnd}` || "--"; return (
`${record.idcard_UserLifeBegin}-${record.idcard_UserLifeEnd}` ||
"--"
);
}, },
}, },
{ {
...@@ -180,9 +183,9 @@ export default { ...@@ -180,9 +183,9 @@ export default {
size: 10, size: 10,
total: 0, total: 0,
searchForm: { searchForm: {
name: "", name: "",
idcard: "", idcard: "",
phone: "", phone: "",
}, },
loading: false, loading: false,
selectedRowKeys: [], // 表格选中的key selectedRowKeys: [], // 表格选中的key
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1000, x: 1000,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
...@@ -37,8 +37,8 @@ ...@@ -37,8 +37,8 @@
</a-table> </a-table>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import storage from "@/utils/js/Storage"; import storage from "@/utils/js/Storage";
import { export2Excel } from "@/utils/js/exportExcel"; import { export2Excel } from "@/utils/js/exportExcel";
...@@ -297,6 +297,5 @@ export default { ...@@ -297,6 +297,5 @@ export default {
}, },
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped></style>
</style>
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1000, x: 1000,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1500, x: 1500,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
...@@ -26,8 +26,8 @@ ...@@ -26,8 +26,8 @@
</a-table> </a-table>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import storage from "@/utils/js/Storage"; import storage from "@/utils/js/Storage";
import { export2Excel } from "@/utils/js/exportExcel"; import { export2Excel } from "@/utils/js/exportExcel";
...@@ -305,6 +305,5 @@ export default { ...@@ -305,6 +305,5 @@ export default {
}, },
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped></style>
</style>
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1500, x: 1500,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
...@@ -524,5 +524,4 @@ export default { ...@@ -524,5 +524,4 @@ export default {
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped></style>
</style>
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1500, x: 1500,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1500, x: 1500,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
:loading="loading" :loading="loading"
:scroll="{ :scroll="{
x: 1000, x: 1000,
y: 490, y: 460,
}" }"
:row-selection="{ :row-selection="{
selectedRowKeys: selectedRowKeys, selectedRowKeys: selectedRowKeys,
...@@ -57,8 +57,8 @@ ...@@ -57,8 +57,8 @@
</a-table> </a-table>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import storage from "@/utils/js/Storage"; import storage from "@/utils/js/Storage";
import { export2Excel } from "@/utils/js/exportExcel"; import { export2Excel } from "@/utils/js/exportExcel";
...@@ -287,6 +287,5 @@ export default { ...@@ -287,6 +287,5 @@ export default {
}, },
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped></style>
</style>
\ No newline at end of file
...@@ -143,8 +143,9 @@ export default { ...@@ -143,8 +143,9 @@ export default {
this.siteName = siteObj ? siteObj.label : "请选择站点"; this.siteName = siteObj ? siteObj.label : "请选择站点";
}, },
clickSite(obj) { clickSite(obj) {
storage.set(2, "siteId", obj.id); storage.set(2, "siteId", Number(obj.id));
storage.set(2, "siteName", obj.label); storage.set(2, "siteName", obj.label);
storage.set(2, "siteCode", obj.siteCode);
this.show = false; this.show = false;
if (location.href.search(/token/gi) >= 0) { if (location.href.search(/token/gi) >= 0) {
this.$router.push({ path: "/resource/advimg" }); this.$router.push({ path: "/resource/advimg" });
......
...@@ -74,6 +74,73 @@ ...@@ -74,6 +74,73 @@
</a-menu> </a-menu>
</a-dropdown> </a-dropdown>
</div> </div>
<div class="line" v-if="hasMessagePage"></div>
<a-popover
v-if="hasMessagePage"
arrowPointAtCenter
trigger="click"
:overlayStyle="{ width: '300px' }"
overlayClassName="message-popover"
placement="bottomRight"
>
<div slot="title" class="text-[16px]">{{ messageTotal }}条消息</div>
<div slot="content" class="message-content">
<div class="message-list">
<template v-if="messageList.length">
<div
v-for="(v, i) in messageList"
:key="v.id"
@click="changeMessageInfo(v)"
>
<div
class="flex justify-between items-start gap-[6px] cursor-pointer"
>
<div class="flex gap-[6px]">
<div
class="w-[50px] h-[50px] rounded-full flex justify-center items-center text-white hint flex-shrink-0"
>
预警
</div>
<div class="flex flex-col justify-between">
<div>
{{ v.messageType }}
</div>
<div>{{ v.alarmTime }}</div>
</div>
</div>
<a-tag color="blue"> {{ v.appName }} </a-tag>
</div>
<a-divider dashed v-if="i < messageList.length - 1" />
</div>
</template>
<a-empty
v-else
:image="require('@/assets/images/no_data.png')"
:image-style="{
height: '100px',
}"
>
<span slot="description"> 暂无数据 </span>
</a-empty>
<MessageInfo
:show.sync="showMessageInfo"
:detailsInfo="messageInfo"
></MessageInfo>
</div>
<div
class="message-footer"
@click="
$router.push('/home/thePlatformIsSet/messageManage/messageList')
"
>
查看更多 >
</div>
</div>
<a-badge :count="messageTotal" :overflow-count="999">
<i class="iconfont icon-notice cursor-pointer"></i>
</a-badge>
</a-popover>
</div> </div>
<changePassword :visibleEditPwd.sync="visibleEditPwd"></changePassword> <changePassword :visibleEditPwd.sync="visibleEditPwd"></changePassword>
</div> </div>
...@@ -84,17 +151,21 @@ ...@@ -84,17 +151,21 @@
<script> <script>
import { mapState, mapMutations, mapGetters } from "vuex"; import { mapState, mapMutations, mapGetters } from "vuex";
import { LogoutInterface } from "@/api/user"; import { LogoutInterface } from "@/api/user";
import { getMsgTaskList } from "@/api/message";
import changePassword from "./components/changePassword.vue"; import changePassword from "./components/changePassword.vue";
import HeaderSite from "./components/HeaderSite.vue"; import HeaderSite from "./components/HeaderSite.vue";
import MessageInfo from "@/components/MessageInfo.vue";
import storage from "@/utils/js/Storage"; import storage from "@/utils/js/Storage";
export default { export default {
components: { components: {
changePassword, changePassword,
HeaderSite, HeaderSite,
MessageInfo,
}, },
data() { data() {
return { return {
sysName: process.env.VUE_APP_systemName, sysName: process.env.VUE_APP_systemName,
siteId: storage.get(2, "siteId") ? storage.get(2, "siteId") : "",
siteInfo: { siteInfo: {
key: storage.get(2, "siteId"), key: storage.get(2, "siteId"),
}, },
...@@ -102,12 +173,19 @@ export default { ...@@ -102,12 +173,19 @@ export default {
nowDay: "", nowDay: "",
nowWeek: "", nowWeek: "",
visibleEditPwd: false, visibleEditPwd: false,
showMessageInfo: false,
messageInfo: {},
homePage: [ homePage: [
"/home/dataManagement", "/home/dataManagement",
"/home/siteArrange", "/home/siteArrange",
"/home/dataActuary", "/home/dataActuary",
"/home/thePlatformIsSet/setPlatformes", "/home/thePlatformIsSet/setPlatformes",
], ],
// 消息列表
messageList: [],
messageTotal: 0,
timer: null,
timer2: null,
}; };
}, },
computed: { computed: {
...@@ -126,12 +204,70 @@ export default { ...@@ -126,12 +204,70 @@ export default {
let curParent = this.$route.matched[1]?.path; let curParent = this.$route.matched[1]?.path;
return this.homePage.includes(cur) || this.homePage.includes(curParent); return this.homePage.includes(cur) || this.homePage.includes(curParent);
}, },
hasMessagePage() {
let { menuList } = this.userData;
if (menuList && !menuList.length) return false;
let platform = menuList.find(
(v) =>
v.name === "平台设置" ||
v.url === "/home/thePlatformIsSet/setPlatformes"
);
if (platform && platform.childList.length) {
let bol = platform.childList.some(
(v) => v.url === "/home/thePlatformIsSet/messageManage"
);
return bol;
} else {
return false;
}
},
}, },
created() { created() {
this.setMoment(); this.setMoment();
this.getMsgTaskList();
this.autoUpdate();
this.$bus.$off("updateMessageList");
this.$bus.$on("updateMessageList", () => {
this.getMsgTaskList();
});
}, },
methods: { methods: {
...mapMutations("user", ["reset"]), ...mapMutations("user", ["reset"]),
// 获取消息任务列表
async getMsgTaskList() {
if (!this.hasMessagePage) return;
let res = await getMsgTaskList({
page: 1,
size: 5,
siteId: this.siteId,
createTimeStart: this.$moment().format("YYYY-MM-DD"),
createTimeEnd: this.$moment().format("YYYY-MM-DD"),
});
if (res.code === 1) {
let { data, total, dict } = res.data;
data.forEach((v) => {
v.alarmTime = this.$moment(v.alarmTime).format("YYYY-MM-DD HH:mm:ss");
v.sendTime = v.sendTime
? this.$moment(v.sendTime).format("YYYY-MM-DD HH:mm:ss")
: "";
v.sendStatus = dict.sendStatus && dict.sendStatus[v.sendStatus];
});
this.messageList = data;
this.messageTotal = total;
}
},
// 自动更新消息
autoUpdate() {
this.timer2 = setInterval(() => {
if (!this.hasMessagePage) {
clearInterval(this.timer2);
return;
}
this.getMsgTaskList();
}, 1000 * 60);
},
handleChange(info) { handleChange(info) {
storage.set(2, "siteId", info.key); storage.set(2, "siteId", info.key);
storage.set(2, "siteName", info.label); storage.set(2, "siteName", info.label);
...@@ -184,15 +320,28 @@ export default { ...@@ -184,15 +320,28 @@ export default {
storage.set(1, "routeInfo", route.key); storage.set(1, "routeInfo", route.key);
this.$router.push(route.key); this.$router.push(route.key);
}, },
changeMessageInfo(row) {
this.messageInfo = row;
this.showMessageInfo = true;
},
}, },
beforeDestroy() { beforeDestroy() {
clearInterval(this.timer); clearInterval(this.timer);
clearInterval(this.timer2);
}, },
}; };
</script> </script>
<style lang="less">
.message-popover {
.ant-popover-inner-content {
padding: 0px;
}
}
</style>
<style lang="less" scoped> <style lang="less" scoped>
@headerHeight: 72px; @headerHeight: 72px;
.route-view { .route-view {
position: relative; position: relative;
} }
...@@ -293,4 +442,22 @@ export default { ...@@ -293,4 +442,22 @@ export default {
.inside { .inside {
background: linear-gradient(90deg, #1845c6 0%, #2999ff 100%) !important; background: linear-gradient(90deg, #1845c6 0%, #2999ff 100%) !important;
} }
:deep(.ant-badge-count) {
box-shadow: none;
}
.icon-notice {
font-size: 24px;
}
.hint {
background: linear-gradient(to right, #68a1fc 0%, #387dfd 100%);
}
.message-list {
padding: 12px 16px;
}
.message-footer {
padding: 12px;
border: 1px solid #e8e8e8;
text-align: center;
cursor: pointer;
}
</style> </style>
...@@ -431,8 +431,10 @@ export default { ...@@ -431,8 +431,10 @@ export default {
let siteId = siteIds.split(",")[0]; let siteId = siteIds.split(",")[0];
let firstSite = findSitesById(siteList, siteId); let firstSite = findSitesById(siteList, siteId);
let siteName = firstSite.label; let siteName = firstSite.label;
storage.set(2, "siteId", siteId); let siteCode = firstSite.siteCode;
storage.set(2, "siteId", Number(siteId));
storage.set(2, "siteName", siteName); storage.set(2, "siteName", siteName);
storage.set(2, "siteCode", siteCode);
} }
setTimeout(() => { setTimeout(() => {
this.$router.push("/home"); this.$router.push("/home");
......
<template>
<div>
<div class="flex items-center justify-between mb-[20px]">
<a-space>
<!-- <a-button type="danger" @click="handBatchDel">批量删除</a-button> -->
发送消息总量:<span class="primary font-bold">{{ total }}</span>
</a-space>
<a-space>
<a-select v-model="searchform.messageType">
<a-select-option value=""> 全部类型 </a-select-option>
<a-select-option
v-for="(v, key) in messageSetDict.messageType"
:key="key"
:value="key"
>
{{ v }}
</a-select-option>
</a-select>
<a-select v-model="searchform.appName">
<a-select-option value=""> 全部来源 </a-select-option>
<a-select-option v-for="(v, i) in appNameList" :key="i" :value="v">
{{ v }}
</a-select-option>
</a-select>
<a-select v-model="searchform.sendStatus">
<a-select-option value=""> 全部状态 </a-select-option>
<a-select-option
v-for="(v, key) in dict.sendStatus"
:key="key"
:value="key"
>
{{ v }}
</a-select-option>
</a-select>
<a-range-picker
:allowClear="false"
valueFormat="YYYY-MM-DD"
v-model="searchform.BegindAndEndTime"
/>
<a-button type="primary" @click="handSearch">搜索</a-button>
<a-button @click="resetSearch">重置</a-button>
</a-space>
</div>
<a-table
size="small"
bordered
:scroll="{ y: 590 }"
:row-key="(record) => record.id"
:pagination="{
showTotal: (total) => `共 ${total} 条`,
current: current,
total: total,
pageSize: size,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: pageSizeOptions,
}"
:columns="columns"
:data-source="tableData"
:loading="loading"
:rowSelection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectChange,
}"
@change="changePagination"
>
<template slot="action" slot-scope="text, record">
<a-space>
<span class="cursor-pointer primary" @click="handleInfo(record)"
>查看详情</span
>
<!-- <span class="cursor-pointer delete" @click="handleDel(record.id)"
>删除</span
> -->
</a-space>
</template>
</a-table>
<MessageInfo
ref="MessageInfo"
:show.sync="showMessageInfo"
:detailsInfo="info"
/>
</div>
</template>
<script>
import MessageInfo from "@/components/MessageInfo.vue";
import storage from "@/utils/js/Storage";
import { getMsgTaskList, deleteMsgTask, getMsgConfigList } from "@/api/message";
let appNameList = ["排号系统", "评价系统"];
export default {
components: { MessageInfo },
data() {
return {
appNameList,
loading: false,
columns: [
{
width: "60px",
title: "序号",
align: "center",
customRender: (text, record, index) => {
return (this.current - 1) * this.size + index + 1;
},
},
{
title: "消息类型",
align: "center",
dataIndex: "messageType",
},
{
title: "消息来源",
align: "center",
dataIndex: "appName",
},
{
title: "系统提醒时间",
align: "center",
dataIndex: "alarmTime",
},
{
title: "接收人",
align: "center",
dataIndex: "msgRecipients",
},
{
title: "接收人手机号码",
align: "center",
dataIndex: "recipient",
},
{
title: "发送状态",
align: "center",
dataIndex: "sendStatus",
customRender: (text) => {
return <a-tag>{{ text }}</a-tag>;
},
},
{
title: "短信提醒时间",
align: "center",
dataIndex: "sendTime",
},
{
title: "操作",
align: "center",
width: 150,
scopedSlots: { customRender: "action" },
},
],
tableData: [],
siteId: storage.get(2, "siteId") ? storage.get(2, "siteId") : "",
searchName: "",
pageSizeOptions: ["10", "30", "50", "100"],
current: 1,
size: 10,
total: 0,
dict: {}, // 日志字典
info: {},
searchform: {
sendStatus: "",
messageType: "",
appName: "",
BegindAndEndTime: [
this.$moment().format("YYYY-MM-DD"),
this.$moment().format("YYYY-MM-DD"),
],
},
selectedRowKeys: [],
showMessageInfo: false,
messageSetDict: {}, // 配置字典
};
},
created() {
this.getMsgConfigList();
this.getMsgTaskList();
},
methods: {
async getMsgConfigList() {
let res = await getMsgConfigList({
page: 1,
size: 1,
});
if (res.code === 1) {
let { dict } = res.data;
this.messageSetDict = dict;
}
},
// 获取消息任务列表
async getMsgTaskList() {
this.loading = true;
let res = await getMsgTaskList({
page: this.current,
size: this.size,
siteId: this.siteId,
sendStatus: this.searchform.sendStatus,
messageType: this.searchform.messageType,
appName: this.searchform.appName,
createTimeStart: this.searchform.BegindAndEndTime[0],
createTimeEnd: this.searchform.BegindAndEndTime[1],
});
this.loading = false;
if (res.code === 1) {
let { data, total, dict } = res.data;
if (!data.length && this.current > 1) {
this.current -= 1;
this.getMsgTaskList();
}
data.forEach((v) => {
v.alarmTime = this.$moment(v.alarmTime).format("YYYY-MM-DD HH:mm:ss");
v.sendTime = v.sendTime
? this.$moment(v.sendTime).format("YYYY-MM-DD HH:mm:ss")
: "";
v.sendStatus = dict.sendStatus && dict.sendStatus[v.sendStatus];
});
this.tableData = data;
this.total = total;
this.dict = dict;
}
},
changePagination({ current, pageSize }) {
this.current = current;
this.size = pageSize;
this.getMsgTaskList();
},
handleInfo(row) {
this.info = row;
this.showMessageInfo = true;
},
handSearch() {
this.current = 1;
this.selectedRowKeys = [];
this.getMsgTaskList();
},
resetSearch() {
this.searchform.BegindAndEndTime = [
this.$moment().format("YYYY-MM-DD"),
this.$moment().format("YYYY-MM-DD"),
];
this.selectedRowKeys = [];
this.searchform.sendStatus = "";
this.searchform.messageType = "";
this.searchform.appName = "";
this.current = 1;
this.getMsgTaskList();
},
onSelectChange(keys) {
this.selectedRowKeys = keys;
},
handBatchDel() {
if (!this.selectedRowKeys.length) {
this.$message.warning("请选勾选数据");
return;
}
let ids = this.selectedRowKeys.join(",");
this.handleDel(ids);
},
handleDel(id) {
this.$confirm({
okType: "danger",
title: "系统提示",
content: "删除不可恢复,是否继续?",
okText: "",
cancelText: "",
centered: true,
onOk: async () => {
let res = await deleteMsgTask({ id });
if (res.code === 1) {
this.$message.success(res.msg);
this.selectedRowKeys = [];
this.getMsgTaskList();
this.$bus.$emit("updateMessageList");
}
},
});
},
},
};
</script>
<style lang="less" scoped>
/deep/.ant-spin-container {
display: block;
}
</style>
<template>
<div class="Container">
<div class="main">
<a-tabs v-model="tabsActive" @change="tabsChange" :forceRender="false">
<a-button
style="margin-right: 16px"
slot="tabBarExtraContent"
@click="$router.push('/home/thePlatformIsSet/setPlatformes')"
>返回上一级</a-button
>
<a-tab-pane
:key="item.path"
v-for="item of tabsList['children']"
:tab="item['meta']['title']"
>
</a-tab-pane>
</a-tabs>
<router-view style="padding: 0 1rem" />
</div>
</div>
</template>
<script>
import { getItemData } from "@/utils/js/common.js";
import common from "@/mixins/common";
export default {
name: "PortalAdminVueMessageManagement",
mixins: [common],
data() {
return {
tabsActive: undefined,
};
},
computed: {
tabsList() {
return getItemData(this.$router.options.routes, "name", "messageManage");
},
},
mounted() {
this.$nextTick(() => {
this.tabsActive = this.$route.path.substr(
this.$route.path.lastIndexOf("/") + 1
);
});
},
methods: {
tabsChange(val) {
this.$router.push({
path: `/home/thePlatformIsSet/messageManage/${val}`,
// query: { testoption: "test001" },
});
},
},
};
</script>
<style lang="less" scoped>
@headerH: 4.5rem;
.Container {
width: 100%;
height: 100% !important;
// background: #fac;
background: #f5f5f5;
display: flex;
flex-direction: column;
.main {
// background: #afc;
background: #ffffff;
border-radius: 6px;
flex: 1;
overflow-y: auto;
overflow-x: hidden;
margin: 1.2rem 2rem;
}
&::before {
content: "";
display: block;
width: 100%;
height: @headerH;
background: rgb(59, 135, 255);
background: -moz-linear-gradient(
174deg,
rgba(59, 135, 255, 1) 24%,
rgba(108, 53, 247, 1) 85%
);
background: -webkit-linear-gradient(
174deg,
rgba(59, 135, 255, 1) 24%,
rgba(108, 53, 247, 1) 85%
);
background: linear-gradient(
174deg,
rgba(59, 135, 255, 1) 24%,
rgba(108, 53, 247, 1) 85%
);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#3b87ff",endColorstr="#6c35f7",GradientType=1);
}
.ant-tabs-nav {
.ant-tabs-tab {
margin: 0 !important;
}
}
.ant-tabs-tab {
font-size: 1rem !important;
& + .ant-tabs-tab {
margin: 0 !important;
margin-left: 0.7rem !important;
}
}
}
</style>
<template>
<div>
<div class="flex items-center justify-between mb-[20px]">
<a-space>
<a-button type="primary" @click="handleAdd">新增</a-button>
</a-space>
</div>
<a-table
size="small"
bordered
:scroll="{ y: 590 }"
:row-key="(record) => record.id"
:pagination="{
showTotal: (total) => `共 ${total} 条`,
current: current,
total: total,
pageSize: size,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: pageSizeOptions,
}"
:columns="columns"
:data-source="tableData"
:loading="loading"
@change="changePagination"
>
<template slot="enabled" slot-scope="text, record">
<YSwitch v-model="record.enabled" @onChange="handleSwitch(record)" />
</template>
<template slot="action" slot-scope="text, record">
<a-space>
<span class="cursor-pointer primary" @click="handleEdit(record)"
>编辑</span
>
<!-- <span class="cursor-pointer delete" @click="handleDel(record.id)"
>删除</span
> -->
</a-space>
</template>
</a-table>
<!-- 新增 -->
<AddMessageSet
ref="AddMessageSet"
:show.sync="show"
:title="title"
:dict="dict"
@success="getMsgConfigList"
></AddMessageSet>
</div>
</template>
<script>
import AddMessageSet from "./components/AddMessageSet.vue";
import YSwitch from "@/components/YSwitch.vue";
import storage from "@/utils/js/Storage";
import {
getMsgConfigList,
deleteMsgConfig,
saveMsgConfig,
} from "@/api/message";
export default {
components: { AddMessageSet, YSwitch },
data() {
return {
loading: false,
columns: [
{
width: "60px",
title: "序号",
align: "center",
customRender: (text, record, index) => {
return (this.current - 1) * this.size + index + 1;
},
},
{
title: "短信消息模板ID",
align: "center",
dataIndex: "templateId",
},
{
title: "消息类型",
align: "center",
dataIndex: "messageType",
},
{
title: "应用平台标识",
align: "center",
dataIndex: "appName",
},
{
title: "接收人",
align: "center",
dataIndex: "msgRecipients",
},
{
title: "接收人手机号码",
align: "center",
dataIndex: "recipient",
},
{
title: "启用",
align: "center",
dataIndex: "enabled",
width: 200,
scopedSlots: { customRender: "enabled" },
},
{
title: "操作",
align: "center",
width: 120,
scopedSlots: { customRender: "action" },
},
],
tableData: [],
siteId: storage.get(2, "siteId") ? storage.get(2, "siteId") : "",
pageSizeOptions: ["10", "30", "50", "100"],
current: 1,
size: 10,
total: 0,
dict: {}, // 日志字典
title: "新增",
show: false,
};
},
created() {
this.getMsgConfigList();
},
methods: {
// 获取消息任务列表
async getMsgConfigList() {
this.loading = true;
let res = await getMsgConfigList({
page: this.current,
size: this.size,
siteId: this.siteId,
});
this.loading = false;
if (res.code === 1) {
let { data, total, dict } = res.data;
if (!data.length && this.current > 1) {
this.current -= 1;
this.getMsgConfigList();
}
this.tableData = data;
this.total = total;
this.dict = dict;
}
},
changePagination({ current, pageSize }) {
this.current = current;
this.size = pageSize;
this.getMsgConfigList();
},
handleAdd() {
this.title = "新增";
this.show = true;
this.$refs.AddMessageSet.onAdd();
},
handleEdit(row) {
this.title = "编辑";
this.show = true;
this.$refs.AddMessageSet.onEdit(row);
},
handleDel(id) {
this.$confirm({
okType: "danger",
title: "系统提示",
content: "删除不可恢复,是否继续?",
okText: "",
cancelText: "",
centered: true,
onOk: async () => {
let res = await deleteMsgConfig({ id });
if (res.code === 1) {
this.$message.success(res.msg);
this.getMsgConfigList();
}
},
});
},
async handleSwitch(row) {
let res = await saveMsgConfig(row);
if (res.code === 1) {
this.$message.success("修改成功");
}
this.getMsgConfigList();
},
},
};
</script>
<style lang="less" scoped>
/deep/.ant-spin-container {
display: block;
}
</style>
<template>
<div class="flex items-center gap-6">
<a-card :title="title" style="width: 300px">
<YSwitch slot="extra" v-model="value"></YSwitch>
<div class="flex items-center justify-between mb-4">
<div>消息内容:</div>
<div class="primary">等待时长超时</div>
</div>
<div class="flex items-center justify-between">
<div>消息来源:</div>
<div class="primary">排队系统</div>
</div>
<a-divider dashed />
<div class="flex items-center justify-between mb-4">
<div>接收人:</div>
<div class="primary">张三</div>
</div>
<div class="flex items-center justify-between">
<div>手机号码:</div>
<div class="primary">16608319500</div>
</div>
<a-divider dashed />
<div class="flex justify-end">
<a-button type="primary" ghost> 编辑 </a-button>
<!-- <span class="primary cursor-pointer"><a-icon type="edit" /> 编辑</span> -->
</div>
</a-card>
<a-card :title="title" style="width: 300px">
<YSwitch slot="extra" v-model="value"></YSwitch>
<div class="flex items-center justify-between mb-4">
<div>消息内容:</div>
<div class="primary">办理时长超时</div>
</div>
<div class="flex items-center justify-between">
<div>消息来源:</div>
<div class="primary">排队系统</div>
</div>
<a-divider dashed />
<div class="flex items-center justify-between mb-4">
<div>接收人:</div>
<div class="primary">张三</div>
</div>
<div class="flex items-center justify-between">
<div>手机号码:</div>
<div class="primary">16608319500</div>
</div>
</a-card>
<a-card :title="title" style="width: 300px">
<YSwitch slot="extra" v-model="value"></YSwitch>
<div class="flex items-center justify-between mb-4">
<div>消息内容:</div>
<div class="primary">差评</div>
</div>
<div class="flex items-center justify-between">
<div>消息来源:</div>
<div class="primary">评价系统</div>
</div>
<a-divider dashed />
<div class="flex items-center justify-between mb-4">
<div>接收人:</div>
<div class="primary">张三</div>
</div>
<div class="flex items-center justify-between">
<div>手机号码:</div>
<div class="primary">16608319500</div>
</div>
</a-card>
<AddReceive :show.sync="show"></AddReceive>
</div>
</template>
<script>
import YSwitch from "@/components/YSwitch.vue";
import AddReceive from "./components/AddReceive.vue";
export default {
components: {
YSwitch,
AddReceive,
},
data() {
return {
title: "预警消息",
value: 1,
show: false,
};
},
created() {},
methods: {
handleSwitch() {
this.show = true;
},
},
};
</script>
<style lang="less" scoped>
/deep/.ant-spin-container {
display: block;
}
</style>
<template>
<div>
<div class="flex items-center justify-between mb-[20px]">
<a-space>
<a-button type="primary" @click="handleAdd">新增</a-button>
</a-space>
</div>
<a-table
size="small"
bordered
:scroll="{ y: 590 }"
:row-key="(record) => record.id"
:pagination="{
showTotal: (total) => `共 ${total} 条`,
current: current,
total: total,
pageSize: size,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: pageSizeOptions,
}"
:columns="columns"
:data-source="tableData"
:loading="loading"
@change="changePagination"
>
<template slot="enabled" slot-scope="text, record">
<YSwitch v-model="record.enabled" @onChange="handleSwitch(record)" />
</template>
<template slot="action" slot-scope="text, record">
<a-space>
<span class="cursor-pointer primary" @click="handleEdit(record)"
>编辑</span
>
<!-- <span class="cursor-pointer delete" @click="handleDel(record.id)"
>删除</span
> -->
</a-space>
</template>
</a-table>
<!-- 新增 -->
<AddMessageSet
ref="AddMessageSet"
:show.sync="show"
:title="title"
:dict="dict"
@success="getMsgConfigList"
></AddMessageSet>
</div>
</template>
<script>
import AddMessageSet from "./components/AddMessageSet.vue";
import YSwitch from "@/components/YSwitch.vue";
import storage from "@/utils/js/Storage";
import {
getMsgConfigList,
deleteMsgConfig,
saveMsgConfig,
} from "@/api/message";
export default {
components: { AddMessageSet, YSwitch },
data() {
return {
loading: false,
columns: [
{
width: "60px",
title: "序号",
align: "center",
customRender: (text, record, index) => {
return (this.current - 1) * this.size + index + 1;
},
},
{
title: "短信消息模板ID",
align: "center",
dataIndex: "templateId",
},
{
title: "消息类型",
align: "center",
dataIndex: "messageType",
},
{
title: "应用平台标识",
align: "center",
dataIndex: "appName",
},
{
title: "接收人",
align: "center",
dataIndex: "msgRecipients",
},
{
title: "接收人手机号码",
align: "center",
dataIndex: "recipient",
},
{
title: "启用",
align: "center",
dataIndex: "enabled",
width: 200,
scopedSlots: { customRender: "enabled" },
},
{
title: "操作",
align: "center",
width: 120,
scopedSlots: { customRender: "action" },
},
],
tableData: [],
siteId: storage.get(2, "siteId") ? storage.get(2, "siteId") : "",
pageSizeOptions: ["10", "30", "50", "100"],
current: 1,
size: 10,
total: 0,
dict: {}, // 日志字典
title: "新增",
show: false,
};
},
created() {
this.getMsgConfigList();
},
methods: {
// 获取消息任务列表
async getMsgConfigList() {
this.loading = true;
let res = await getMsgConfigList({
page: this.current,
size: this.size,
siteId: this.siteId,
});
this.loading = false;
if (res.code === 1) {
let { data, total, dict } = res.data;
if (!data.length && this.current > 1) {
this.current -= 1;
this.getMsgConfigList();
}
this.tableData = data;
this.total = total;
this.dict = dict;
}
},
changePagination({ current, pageSize }) {
this.current = current;
this.size = pageSize;
this.getMsgConfigList();
},
handleAdd() {
this.title = "新增";
this.show = true;
this.$refs.AddMessageSet.onAdd();
},
handleEdit(row) {
this.title = "编辑";
this.show = true;
this.$refs.AddMessageSet.onEdit(row);
},
handleDel(id) {
this.$confirm({
okType: "danger",
title: "系统提示",
content: "删除不可恢复,是否继续?",
okText: "",
cancelText: "",
centered: true,
onOk: async () => {
let res = await deleteMsgConfig({ id });
if (res.code === 1) {
this.$message.success(res.msg);
this.getMsgConfigList();
}
},
});
},
async handleSwitch(row) {
let res = await saveMsgConfig(row);
if (res.code === 1) {
this.$message.success("修改成功");
}
this.getMsgConfigList();
},
},
};
</script>
<style lang="less" scoped>
/deep/.ant-spin-container {
display: block;
}
</style>
<template>
<div class="roleEditModal_box" ref="roleEditModal_box">
<a-modal
:title="title"
:visible="Visible"
@cancel="handleCancel"
width="30%"
>
<a-form-model
:label-col="{
span: 6,
}"
:wrapper-col="{
span: 18,
}"
ref="form"
:model="form"
:rules="rules"
>
<a-form-model-item label="消息类型" prop="messageType">
<a-select v-model="form.messageType" placeholder="请选择消息类型">
<a-select-option
v-for="(v, key) in dict.messageType"
:key="key"
:value="key"
>{{ v }}</a-select-option
>
</a-select>
</a-form-model-item>
<!-- <a-form-model-item label="应用平台标识" prop="appName">
<a-input
placeholder="请输入应用平台标识"
allowClear
v-model="form.appName"
/>
</a-form-model-item> -->
<a-form-model-item label="短信消息模板ID" prop="templateId">
<a-input
placeholder="请输入短信消息模板ID"
allowClear
v-model.number="form.templateId"
/>
</a-form-model-item>
<a-form-model-item label="接收人" prop="msgRecipients">
<a-input
placeholder="请输入接收人姓名"
allowClear
v-model="form.msgRecipients"
/>
</a-form-model-item>
<a-form-model-item label="接收人手机号码" prop="recipient">
<a-input
placeholder="请输入接收人手机号码"
allowClear
v-model="form.recipient"
/>
</a-form-model-item>
<a-form-model-item label="启用" prop="enabled">
<YSwitch v-model="form.enabled"></YSwitch>
</a-form-model-item>
<a-form-model-item label="备注" prop="remark">
<a-input
type="textarea"
placeholder="请输入备注"
allowClear
v-model="form.remark"
/>
</a-form-model-item>
</a-form-model>
<template slot="footer">
<a-button @click="resetForm">重置</a-button>
<a-button type="primary" :loading="loading" @click="handleOk"
>确定</a-button
>
</template>
</a-modal>
</div>
</template>
<script>
import storage from "@/utils/js/Storage";
import YSwitch from "@/components/YSwitch.vue";
import { saveMsgConfig } from "@/api/message";
export default {
components: {
YSwitch,
},
props: {
title: {
required: true,
type: String,
default: "新增",
},
show: {
required: true,
type: Boolean,
default: false,
},
dict: {
required: true,
type: Object,
default: () => {},
},
},
data() {
const changePhone = (rule, value, callback) => {
if (!value) {
callback(new Error("请输入手机号"));
callback();
} else if (!/^1[3-9]\d{9}$/.test(value)) {
callback(new Error("手机号码格式不正确"));
} else {
callback();
}
};
return {
loading: false,
form: {
siteId: storage.get(2, "siteId") ? storage.get(2, "siteId") : "", // 站点id
siteName: storage.get(2, "siteName") ? storage.get(2, "siteName") : "", // 站点名称
siteCode: storage.get(2, "siteCode") ? storage.get(2, "siteCode") : "", // 站点编码
templateId: "", // 短信消息模板ID
// appName: "", // 应用平台标识
messageType: undefined, // 消息类型(等待超时预警,办理超时预警,差评预警)
recipient: "", // 手机号
msgRecipients: "", // 消息发送对象
channel: "SMS", // 消息发送渠道,SMS(短信)、EMAIL(邮件)、PUSH(推送通知)
enabled: 1, // 是否启用该发送服务(0.否,1.是)
remark: "", //备注
},
rules: {
messageType: [
{ required: true, message: "请选择消息类型", trigger: "change" },
],
msgRecipients: [
{
required: true,
message: "请输入接收人姓名",
trigger: "msgRecipients",
},
],
templateId: [
{ required: true, message: "请输入短信消息模板ID", trigger: "blur" },
],
recipient: [
{ required: true, validator: changePhone, trigger: "blur" },
],
},
};
},
computed: {
Visible: {
get() {
return this.show;
},
set(val) {
this.$emit("update:show", 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 };
}, 10);
},
handleCancel() {
this.resetForm();
this.loading = false;
this.Visible = false;
},
resetForm() {
this.$refs.form.resetFields();
},
handleOk() {
this.$refs.form.validate(async (valid) => {
if (valid) {
this.loading = true;
let res = await saveMsgConfig(this.form);
this.loading = false;
if (res.code === 1) {
let { msg } = res;
this.$message.success(msg);
this.$emit("success");
this.handleCancel();
}
}
});
},
},
};
</script>
<style lang="less" scoped></style>
<template>
<div class="roleEditModal_box" ref="roleEditModal_box">
<a-modal
title="短信提醒"
:visible="Visible"
@cancel="handleCancel"
width="30%"
>
<a-form-model
:label-col="{
span: 4,
}"
:wrapper-col="{
span: 20,
}"
ref="form"
:model="form"
>
<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="remark">
<a-input
placeholder="请输入手机号码"
allowClear
v-model="form.name"
/>
</a-form-model-item>
</a-form-model>
<template slot="footer">
<a-button @click="resetForm">重置</a-button>
<a-button type="primary" class="addclass" @click="handleOk"
>确定</a-button
>
</template>
</a-modal>
</div>
</template>
<script>
export default {
props: {
show: {
required: true,
type: Boolean,
default: false,
},
},
data() {
return {
loading: false,
form: {
name: "", //姓名
remark: "", //描述
}, //页面表单信息
};
},
computed: {
Visible: {
get() {
return this.show;
},
set(val) {
this.$emit("update:show", 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 };
}, 10);
},
handleCancel() {
this.resetForm();
this.Visible = false;
},
resetForm() {
this.$refs.form.resetFields();
},
handleOk() {},
},
};
</script>
<style lang="less" scoped></style>
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