Commit 71e5d68e authored by tianhongyang's avatar tianhongyang

2023/11/15需求迭代

parent f51e3fe9
......@@ -39,6 +39,7 @@
"dependencies": {
"@cell-x/el-table-sticky": "^1.0.2",
"@riophae/vue-treeselect": "0.4.0",
"@vue/composition-api": "^1.7.2",
"axios": "0.24.0",
"clipboard": "2.0.8",
"core-js": "^3.32.2",
......@@ -56,6 +57,7 @@
"js-cookie": "3.0.1",
"js-md5": "^0.7.3",
"jsencrypt": "3.0.0-rc.1",
"json-editor-vue": "^0.11.0",
"nprogress": "0.2.0",
"quill": "1.3.7",
"screenfull": "5.0.2",
......
import request from '@/utils/request'
import request from '@/utils/request';
//新增租户套餐
export function addTenantPackage(param) {
return request({
url: '/system/tenant/package',
method: 'POST',
data: param
})
});
}
//修改租户套餐
export function saveTenantPackage(param) {
......@@ -13,21 +13,21 @@ export function saveTenantPackage(param) {
url: '/system/tenant/package/',
method: 'PUT',
data: param
})
});
}
//获取租户套餐
export function detailTenantPackage(packageId) {
return request({
url: '/system/tenant/package/'+packageId,
url: '/system/tenant/package/' + packageId,
method: 'get',
})
});
}
//删除租户套餐
export function deleteTenantPackage(packageId) {
return request({
url: '/system/tenant/package/'+packageId,
url: '/system/tenant/package/' + packageId,
method: 'DELETE',
})
});
}
//租户套餐列表
export function getTenantPackage(param) {
......@@ -35,7 +35,7 @@ export function getTenantPackage(param) {
url: '/system/tenant/package/list',
method: 'get',
params: param
})
});
}
//同步企业方案
export function syncTenantPackage(param) {
......@@ -43,7 +43,7 @@ export function syncTenantPackage(param) {
url: '/system/tenant/syncTenantPackage',
method: 'get',
params: param
})
});
}
//租户列表
......@@ -52,15 +52,15 @@ export function getTenantList(param) {
url: '/system/tenant/list',
method: 'get',
params: param
})
});
}
//获取租户详情
export function getTenant(id) {
return request({
url: '/system/tenant/'+id,
url: '/system/tenant/' + id,
method: 'get',
})
});
}
//修改租户
......@@ -68,31 +68,52 @@ export function editTenant(data) {
return request({
url: '/system/tenant/',
method: 'PUT',
data:data,
})
data: data,
});
}
//新增租户
export function saveTenant(data) {
return request({
url: '/system/tenant/',
method: 'POST',
data:data,
})
data: data,
});
}
//删除租户
export function deleteTenant(ids) {
return request({
url: '/system/tenant/'+ids,
url: '/system/tenant/' + ids,
method: 'Delete',
})
});
}
//租户请求企业套餐下拉
export function selectTenant(ids) {
return request({
url: '/system/tenant/package/selectList',
method: 'Get',
})
});
}
/**
* 企业管理新增账号
* @param {object} data
* @returns
*/
export const enterpriseAddAccountApi = (data) => request({
url: "/system/tenant/addTenantAdmin",
method: "post",
data
});
/**
* 租户ID查询大司空超管or租户管理员为其创建的企业管理员和管理员账号数量
* @param {*} tenantId
* @returns
*/
export const getEnterpriseAddAccountCountApi = (tenantId) => request({
url: `/system/user/queryTenantAdminNumCreatedByDSK/${tenantId}`,
method: "get"
})
......@@ -26,6 +26,16 @@
opacity: 0;
}
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter,
.list-leave-to {
opacity: 0;
transform: translateX(50px);
}
.el-message {
z-index: 3000 !important;
}
<template>
<div class="dsk-json-editor">
<json-editor-vue class="dsk-json-editor-ins" v-model="modelValue" ref="dskJsonEditor" :mode.sync="mode" :readOnly="readOnly"
@input="jsonChange"></json-editor-vue>
</div>
</template>
<script>
import JsonEditorVue from 'json-editor-vue';
import { jsonEscape, jsonTraversal } from "@/utils";
export default {
name: "dskJsonEditor",
components: {
JsonEditorVue
},
props: {
jsonValue: {
required: true,
type: [Object, String],
default: ""
},
defaultMode: {
required: true,
type: [String],
default: "text"
},
jsonReadOnly: {
required: true,
type: [Boolean],
default: false
}
},
watch: {
jsonValue: {
handler(newValue) {
this.modelValue = newValue;
},
deep: true
}
},
data() {
return {
modelValue: this.jsonValue,
mode: this.defaultMode,
readOnly: this.jsonReadOnly
};
},
//可访问data属性
created() {
},
//计算集
computed: {
},
//方法集
methods: {
validateJson() {
return new Promise((resolve, reject) => {
try {
let isPass = false;
// 验证通过
if (!this.$refs["dskJsonEditor"].jsonEditor.validate()) {
isPass = true;
let jsonText = this.modelValue;
// 初始默认对象
if (Object.prototype.toString.call(jsonText) == "[object Object]") {
// 对象转为json字符串
jsonText = JSON.stringify(jsonText);
}
// 转换字符串 去除空格 换行符
jsonText = jsonEscape(jsonText);
// 特殊字符识别编码
jsonText = JSON.stringify(jsonTraversal(JSON.parse(jsonText)));
console.log(jsonText);
return resolve({ isPass, value: jsonText });
}
resolve({ isPass });
} catch (error) {
console.log(error);
reject(error);
}
});
},
jsonChange(e) {
try {
this.$emit("jsonChange", e);
} catch (error) {
console.log(error);
}
}
},
}
</script>
<style lang="scss" scoped>
.dsk-json-editor {
width: 100%;
height: 100%;
box-sizing: border-box;
::v-deep .dsk-json-editor-ins {
width: 100%;
height: 100%;
.jsoneditor-vue {
width: 100%;
height: 100%;
}
.jsoneditor-poweredBy {
display: none;
}
}
}
</style>
......@@ -3,7 +3,7 @@
<!-- 展开 -->
<template v-if="!isCollapse">
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path,onlyOneChild.query)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
<item :icon="sideIcon(item, onlyOneChild)" :title="onlyOneChild.meta.title" />
</el-menu-item>
......@@ -13,31 +13,20 @@
<template slot="title">
<item v-if="item.meta" :icon="sideIcon(item)" :title="item.meta.title" />
</template>
<sidebar-item
v-for="child in item.children"
:key="child.path"
:is-nest="true"
:item="child"
:base-path="resolvePath(child.path)"
:active-menu="activeMenu"
class="nest-menu"
/>
<sidebar-item v-for="child in item.children" :key="child.path" :is-nest="true" :item="child" :base-path="resolvePath(child.path,child.query)"
:active-menu="activeMenu" class="nest-menu" />
</el-submenu>
</template>
<!-- 收起 -->
<template v-else>
<div v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow" class="side-retract">
<el-popover
placement="right-start"
popper-class="side-popover side-one-popover"
:visible-arrow="true"
trigger="hover"
:disabled="onlyOneChild.meta||item.meta?false:true"
>
<div v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow"
class="side-retract">
<el-popover placement="right-start" popper-class="side-popover side-one-popover" :visible-arrow="true" trigger="hover"
:disabled="onlyOneChild.meta||item.meta?false:true">
<div class="side-container">
<div class="side-title">
<!--<app-link v-if="onlyOneChild.meta || item.meta" :to="resolvePath(onlyOneChild.path || item.path)">-->
<app-link :to="resolvePath(onlyOneChild.path || item.path)">
<app-link :to="resolvePath(onlyOneChild.path || item.path,onlyOneChild.query)">
{{ onlyOneChild.meta.title || item.meta.title }}
</app-link>
......@@ -47,18 +36,12 @@
</el-popover>
</div>
<div v-else class="side-retract">
<el-popover
placement="right-start"
popper-class="side-popover"
:visible-arrow="true"
trigger="hover"
:disabled="item.meta?false:true"
>
<el-popover placement="right-start" popper-class="side-popover" :visible-arrow="true" trigger="hover" :disabled="item.meta?false:true">
<div class="side-container">
<div class="side-title">{{ item.meta.title }}</div>
<ul class="side-list">
<li v-for="child in item.children" :key="child.path">
<app-link v-if="child.meta" :to="resolvePath(child.path)">
<app-link v-if="child.meta" :to="resolvePath(child.path,child.query)">
{{ child.meta.title }}
</app-link>
</li>
......@@ -72,11 +55,11 @@
</template>
<script>
import path from 'path'
import { isExternal } from '@/utils/validate'
import Item from './Item'
import AppLink from './Link'
import FixiOSBug from './FixiOSBug'
import path from 'path';
import { isExternal } from '@/utils/validate';
import Item from './Item';
import AppLink from './Link';
import FixiOSBug from './FixiOSBug';
export default {
name: 'SidebarItem',
......@@ -106,42 +89,42 @@ export default {
}
},
data() {
this.onlyOneChild = null
return {}
this.onlyOneChild = null;
return {};
},
computed: {
sideIcon() {
return function(item, onlyOneChild) {
let icon = ''
return function (item, onlyOneChild) {
let icon = '';
if (onlyOneChild) {
if(onlyOneChild.meta.icon || (item.meta && item.meta.icon&&item.meta.icon!='#')){
icon = onlyOneChild.meta.icon || (item.meta && item.meta.icon)
if (onlyOneChild.meta.icon || (item.meta && item.meta.icon && item.meta.icon != '#')) {
icon = onlyOneChild.meta.icon || (item.meta && item.meta.icon);
}
let tempPath = ''
let tempPath = '';
if (onlyOneChild.path) {
tempPath = this.resolvePath(onlyOneChild.path)
tempPath = this.resolvePath(onlyOneChild.path);
if (this.activeMenu === tempPath&&onlyOneChild.meta.icon!='#') {
icon = onlyOneChild.meta.icon+'s'
if (this.activeMenu === tempPath && onlyOneChild.meta.icon != '#') {
icon = onlyOneChild.meta.icon + 's';
}
} else {
tempPath = this.resolvePath(item.path).substring(0, this.resolvePath(item.path).lastIndexOf('/'))
if (this.activeMenu === tempPath&&item.meta.icon!='#') {
icon = item.meta.icon+'s'
tempPath = this.resolvePath(item.path).substring(0, this.resolvePath(item.path).lastIndexOf('/'));
if (this.activeMenu === tempPath && item.meta.icon != '#') {
icon = item.meta.icon + 's';
}
}
} else {
if(item.meta && item.meta.icon&&item.meta.icon!='#'){
icon = item.meta.icon
if (item.meta && item.meta.icon && item.meta.icon != '#') {
icon = item.meta.icon;
}
const tempPath = this.activeMenu.substring(0, this.activeMenu.indexOf('/', this.activeMenu.indexOf('/') + 1))
if (this.resolvePath(item.path) === tempPath&&item.meta.icon!='#') {
icon = item.meta.icon+'s'
const tempPath = this.activeMenu.substring(0, this.activeMenu.indexOf('/', this.activeMenu.indexOf('/') + 1));
if (this.resolvePath(item.path) === tempPath && item.meta.icon != '#') {
icon = item.meta.icon + 's';
}
}
return icon
}
return icon;
};
}
},
methods: {
......@@ -151,48 +134,52 @@ export default {
}
const showingChildren = children.filter(item => {
if (item.hidden) {
return false
return false;
} else {
// Temp set(will be used if only has one showing child)
this.onlyOneChild = item
return true
this.onlyOneChild = item;
return true;
}
})
});
// When there is only one child router, the child router is displayed by default
if (showingChildren.length === 1) {
return true
return true;
}
// Show parent if there are no child router to display
if (showingChildren.length === 0) {
this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
return true
this.onlyOneChild = { ...parent, path: '', noShowingChildren: true };
return true;
}
return false
return false;
},
resolvePath(routePath, routeQuery) {
if (isExternal(routePath)) {
return routePath
return routePath;
}
if (isExternal(this.basePath)) {
return this.basePath
return this.basePath;
}
if (routeQuery) {
let query = JSON.parse(routeQuery);
return { path: path.resolve(this.basePath, routePath), query: query }
let query = routeQuery;
for (const key in query) {
if (query.hasOwnProperty(key)) {
Object.prototype.toString.call(query[key]) == "[object Object]" ? query[key] = JSON.stringify(query[key]) : null;
}
}
return { path: path.resolve(this.basePath, routePath), query: query };
}
return path.resolve(this.basePath, routePath)
return path.resolve(this.basePath, routePath);
}
}
}
</script>
<style lang="scss">
.side-popover.el-popper {
.popper__arrow{
.side-popover.el-popper {
.popper__arrow {
display: block !important;
}
}
}
</style>
......@@ -73,12 +73,9 @@ export default {
};
},
computed: {
visitedViews: {
get() {
visitedViews() {
return this.$store.state.tagsView.visitedViews;
},
set() { }
},
iconName() {
return function (val) {
let svgIcon = val.meta && val.meta.icon, currentIcon = '';
......@@ -105,7 +102,6 @@ export default {
},
watch: {
$route() {
// console.log(this.$route);
this.addTags();
this.moveToCurrentTag();
this.getviews();
......@@ -118,10 +114,11 @@ export default {
}
},
},
mounted() {
created() {
this.$nextTick(() => {
this.initTags();
this.addTags();
// this.getviews()
});
},
methods: {
getviews() {
......
import Vue from 'vue';
import VCA from '@vue/composition-api' //composition APi
import Cookies from 'js-cookie';
......@@ -8,6 +9,7 @@ import './assets/styles/element-variables.scss';
import "@/assets/styles/common.css";
import '@/assets/styles/index.scss'; // global css
import '@/assets/styles/ruoyi.scss'; // ruoyi css
import App from './App';
import store from './store';
import router from './router';
......@@ -22,6 +24,7 @@ import './permission'; // permission control
import { getDicts } from "@/api/system/dict/data";
import { getConfigKey } from "@/api/system/config";
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi";
// 分页组件
import Pagination from "@/components/Pagination";
// 自定义表格工具组件
......@@ -61,6 +64,7 @@ Vue.component('FileUpload', FileUpload);
Vue.component('ImageUpload', ImageUpload);
Vue.component('ImagePreview', ImagePreview);
Vue.use(VCA);
Vue.use(horizontalScroll);
Vue.use(elTableSticky);
Vue.use(directive);
......
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
import { isRelogin } from '@/utils/request'
import router from './router';
import store from './store';
import { Message } from 'element-ui';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import { getToken } from '@/utils/auth';
import { isRelogin } from '@/utils/request';
NProgress.configure({ showSpinner: false })
NProgress.configure({ showSpinner: false });
const whiteList = ['/login', '/register']
const whiteList = ['/login', '/register'];
router.beforeEach((to, from, next) => {
NProgress.start()
NProgress.start();
if (getToken()) {
to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
// tab页签title
const { tabTitle, url } = to.query;
if (tabTitle) to.meta.title = decodeURIComponent(tabTitle);
if (!tabTitle && to.meta.isSubSystem && url) to.meta.title = decodeURIComponent(url);
to.meta.title && store.dispatch('settings/setTitle', to.meta.title);
/* has token*/
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
next({ path: '/' });
NProgress.done();
} else {
if (store.getters.roles.length === 0) {
isRelogin.show = true
isRelogin.show = true;
// 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(() => {
isRelogin.show = false
isRelogin.show = false;
store.dispatch('GenerateRoutes').then(accessRoutes => {
// 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
router.addRoutes(accessRoutes); // 动态添加可访问路由表
next({ ...to, replace: true }); // hack方法 确保addRoutes已完成
});
}).catch(err => {
store.dispatch('LogOut').then(() => {
Message.error(err)
sessionStorage.removeItem('views')
next({ path: '/' })
})
})
Message.error(err);
sessionStorage.removeItem('views');
next({ path: '/' });
});
});
} else {
next()
next();
}
}
} else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入
next()
next();
} else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
NProgress.done()
next(`/login?redirect=${to.fullPath}`); // 否则全部重定向到登录页
NProgress.done();
}
}
})
});
router.afterEach(() => {
NProgress.done()
})
NProgress.done();
});
import store from '@/store'
import store from '@/store';
import router from '@/router';
import { paramsToQuery } from "@/utils/";
export default {
// 刷新当前tab页签
......@@ -15,12 +16,12 @@ export default {
});
}
return store.dispatch('tagsView/delCachedView', obj).then(() => {
const { path, query } = obj
const { path, query } = obj;
router.replace({
path: '/redirect' + path,
query: query
})
})
});
});
},
// 关闭当前tab页签,打开新页签
closeOpenPage(obj) {
......@@ -33,9 +34,9 @@ export default {
closePage(obj) {
if (obj === undefined) {
return store.dispatch('tagsView/delView', router.currentRoute).then(({ visitedViews }) => {
const latestView = visitedViews.slice(-1)[0]
const latestView = visitedViews.slice(-1)[0];
if (latestView) {
return router.push(latestView.fullPath)
return router.push(latestView.fullPath);
}
return router.push('/');
});
......@@ -59,13 +60,16 @@ export default {
return store.dispatch('tagsView/delOthersViews', obj || router.currentRoute);
},
// 添加tab页签
openPage(title, url, params) {
var obj = { path: url, meta: { title: title } }
store.dispatch('tagsView/addView', obj);
async openPage(title, url, params) {
const obj = { path: url, fullPath: url, query: params, meta: { title: title } };
if (params && Object.keys(params).length) {
obj.fullPath = `${obj.path}${paramsToQuery(params) ? "?" + paramsToQuery(params) : ""}`;
}
await store.dispatch('tagsView/addView', obj);
return router.push({ path: url, query: params });
},
// 修改tab页签
updatePage(obj) {
return store.dispatch('tagsView/updateVisitedView', obj);
}
}
};
import Vue from 'vue'
import Router from 'vue-router'
import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router)
Vue.use(Router);
/* Layout */
import Layout from '@/layout'
import Layout from '@/layout';
/**
* Note: 路由配置项
......@@ -70,7 +70,7 @@ export const constantRoutes = [
path: 'index',
component: () => import('@/views/index'),
name: 'Index',
meta: { title: '首页', icon: 'index', noCache: true}
meta: { title: '首页', icon: 'index', noCache: true }
}
]
},
......@@ -303,6 +303,7 @@ export const constantRoutes = [
path: '/gzsc/:id',
component: () => import('@/views/detail'),
name: 'detail-gzsc',
meta: { title: "公招市场详情" }
}
]
},
......@@ -552,7 +553,7 @@ export const constantRoutes = [
path: '/biddetail/:id(\\d+)',
component: () => import('@/views/detail/biddetail/index'),
name: 'Biddetail',
meta: { title: '中标业绩详情',icon: 'enterprise'}
meta: { title: '中标业绩详情', icon: 'enterprise' }
}
]
},
......@@ -566,7 +567,7 @@ export const constantRoutes = [
path: '/macro/financing/details/:id(\\d+)',
component: () => import('@/views/macro/financing/details'),
name: 'financingDetails',
meta: { title: '区域专项债详情',icon: 'radar'}
meta: { title: '区域专项债详情', icon: 'radar' }
}
]
},
......@@ -688,8 +689,28 @@ export const constantRoutes = [
}
]
},
]
// 子系统
// {
// path: '',
// redirect: '/subsystem',
// component: Layout,
// hidden: false,
// children: [
// {
// path: 'subsystem',
// hidden: false,
// component: () => import('@/views/subsystem/index'),
// name: 'Subsystem',
// meta: {
// title: '子系统',
// icon: 'index',
// noCache: true,
// isSubSystem: true
// },
// }
// ]
// },
];
// 动态路由,基于用户权限动态去加载
export const dynamicRoutes = [
......@@ -777,22 +798,22 @@ export const dynamicRoutes = [
}
]
}
]
];
// 防止连续点击多次路由报错
let routerPush = Router.prototype.push;
let routerReplace = Router.prototype.replace;
// push
Router.prototype.push = function push(location) {
return routerPush.call(this, location).catch(err => err)
}
return routerPush.call(this, location).catch(err => err);
};
// replace
Router.prototype.replace = function push(location) {
return routerReplace.call(this, location).catch(err => err)
}
return routerReplace.call(this, location).catch(err => err);
};
export default new Router({
mode: 'history', // 去掉url中的#
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
});
import auth from '@/plugins/auth'
import router, { constantRoutes, dynamicRoutes } from '@/router'
import { getRouters } from '@/api/menu'
import Layout from '@/layout/index'
import ParentView from '@/components/ParentView'
import InnerLink from '@/layout/components/InnerLink'
import auth from '@/plugins/auth';
import router, { constantRoutes, dynamicRoutes } from '@/router';
import { getRouters } from '@/api/menu';
import Layout from '@/layout/index';
import ParentView from '@/components/ParentView';
import InnerLink from '@/layout/components/InnerLink';
const permission = {
state: {
......@@ -15,17 +15,17 @@ const permission = {
},
mutations: {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
state.addRoutes = routes;
state.routes = constantRoutes.concat(routes);
},
SET_DEFAULT_ROUTES: (state, routes) => {
state.defaultRoutes = constantRoutes.concat(routes)
state.defaultRoutes = constantRoutes.concat(routes);
},
SET_TOPBAR_ROUTES: (state, routes) => {
state.topbarRouters = routes
state.topbarRouters = routes;
},
SET_SIDEBAR_ROUTERS: (state, routes) => {
state.sidebarRouters = routes
state.sidebarRouters = routes;
},
},
actions: {
......@@ -34,100 +34,108 @@ const permission = {
return new Promise(resolve => {
// 向后端请求路由数据
getRouters().then(res => {
const sdata = JSON.parse(JSON.stringify(res.data))
const rdata = JSON.parse(JSON.stringify(res.data))
const sidebarRoutes = filterAsyncRouter(sdata)
const rewriteRoutes = filterAsyncRouter(rdata, false, true)
const sdata = JSON.parse(JSON.stringify(res.data));
const rdata = JSON.parse(JSON.stringify(res.data));
const sidebarRoutes = filterAsyncRouter(sdata);
const rewriteRoutes = filterAsyncRouter(rdata, false, true);
const asyncRoutes = filterDynamicRoutes(dynamicRoutes);
rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true });
router.addRoutes(asyncRoutes);
commit('SET_ROUTES', rewriteRoutes)
commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes))
commit('SET_DEFAULT_ROUTES', sidebarRoutes)
commit('SET_TOPBAR_ROUTES', sidebarRoutes)
resolve(rewriteRoutes)
})
})
commit('SET_ROUTES', rewriteRoutes);
commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes));
commit('SET_DEFAULT_ROUTES', sidebarRoutes);
commit('SET_TOPBAR_ROUTES', sidebarRoutes);
resolve(rewriteRoutes);
});
});
}
}
}
};
// 遍历后台传来的路由字符串,转换为组件对象
function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
return asyncRouterMap.filter(route => {
if (type && route.children) {
route.children = filterChildren(route.children)
route.children = filterChildren(route.children);
}
// query默认参数转换
if (route.query) {
try {
route.query = JSON.parse(route.query);
} catch (error) {
}
}
if (route.component) {
// Layout ParentView 组件特殊处理
if (route.component === 'Layout') {
route.component = Layout
route.component = Layout;
} else if (route.component === 'ParentView') {
route.component = ParentView
route.component = ParentView;
} else if (route.component === 'InnerLink') {
route.component = InnerLink
route.component = InnerLink;
} else {
route.component = loadView(route.component)
route.component = loadView(route.component);
}
}
if (route.children != null && route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, route, type)
route.children = filterAsyncRouter(route.children, route, type);
} else {
delete route['children']
delete route['redirect']
delete route['children'];
delete route['redirect'];
}
return true
})
return true;
});
}
function filterChildren(childrenMap, lastRouter = false) {
var children = []
var children = [];
childrenMap.forEach((el, index) => {
if (el.children && el.children.length) {
if (el.component === 'ParentView' && !lastRouter) {
el.children.forEach(c => {
c.path = el.path + '/' + c.path
c.path = el.path + '/' + c.path;
if (c.children && c.children.length) {
children = children.concat(filterChildren(c.children, c))
return
children = children.concat(filterChildren(c.children, c));
return;
}
children.push(c)
})
return
children.push(c);
});
return;
}
}
if (lastRouter) {
el.path = lastRouter.path + '/' + el.path
el.path = lastRouter.path + '/' + el.path;
}
children = children.concat(el)
})
return children
children = children.concat(el);
});
return children;
}
// 动态路由遍历,验证是否具备权限
export function filterDynamicRoutes(routes) {
const res = []
const res = [];
routes.forEach(route => {
if (route.permissions) {
if (auth.hasPermiOr(route.permissions)) {
res.push(route)
res.push(route);
}
} else if (route.roles) {
if (auth.hasRoleOr(route.roles)) {
res.push(route)
res.push(route);
}
}
})
return res
});
return res;
}
export const loadView = (view) => {
if (process.env.NODE_ENV === 'development') {
return (resolve) => require([`@/views/${view}`], resolve)
return (resolve) => require([`@/views/${view}`], resolve);
} else {
// 使用 import 实现生产环境的路由懒加载
return () => import(`@/views/${view}`)
return () => import(`@/views/${view}`);
}
}
};
export default permission
export default permission;
......@@ -3,227 +3,227 @@ const state = {
visitedViews: [],
cachedViews: [],
iframeViews: []
}
};
const mutations = {
ADD_IFRAME_VIEW: (state, view) => {
if (state.iframeViews.some(v => v.fullPath === view.fullPath)) return
if (state.iframeViews.some(v => v.fullPath === view.fullPath)) return;
state.iframeViews.push(
Object.assign({}, view, {
title: view.meta.title || 'no-name'
})
)
);
},
ADD_VISITED_VIEW: (state, view) => {
if (state.visitedViews.some(v => v.fullPath === view.fullPath)) return
if (state.visitedViews.some(v => v.fullPath === view.fullPath)) return;
state.visitedViews.push(
Object.assign({}, view, {
title: view.meta.title || 'no-name'
})
)
);
},
ADD_CACHED_VIEW: (state, view) => {
if (state.cachedViews.includes(view.name)) return
if (state.cachedViews.includes(view.name)) return;
if (view.meta && !view.meta.noCache) {
state.cachedViews.push(view.name)
state.cachedViews.push(view.name);
}
},
DEL_VISITED_VIEW: (state, view) => {
for (const [i, v] of state.visitedViews.entries()) {
if (v.fullPath === view.fullPath) {
state.visitedViews.splice(i, 1)
break
state.visitedViews.splice(i, 1);
break;
}
}
state.iframeViews = state.iframeViews.filter(item => item.fullPath !== view.fullPath)
state.iframeViews = state.iframeViews.filter(item => item.fullPath !== view.fullPath);
},
DEL_IFRAME_VIEW: (state, view) => {
state.iframeViews = state.iframeViews.filter(item => item.fullPath !== view.fullPath)
state.iframeViews = state.iframeViews.filter(item => item.fullPath !== view.fullPath);
},
DEL_CACHED_VIEW: (state, view) => {
const index = state.cachedViews.indexOf(view.name)
index > -1 && state.cachedViews.splice(index, 1)
const index = state.cachedViews.indexOf(view.name);
index > -1 && state.cachedViews.splice(index, 1);
},
DEL_OTHERS_VISITED_VIEWS: (state, view) => {
state.visitedViews = state.visitedViews.filter(v => {
return v.meta.affix || v.fullPath === view.fullPath
})
state.iframeViews = state.iframeViews.filter(item => item.fullPath === view.fullPath)
return v.meta.affix || v.fullPath === view.fullPath;
});
state.iframeViews = state.iframeViews.filter(item => item.fullPath === view.fullPath);
},
DEL_OTHERS_CACHED_VIEWS: (state, view) => {
const index = state.cachedViews.indexOf(view.name)
const index = state.cachedViews.indexOf(view.name);
if (index > -1) {
state.cachedViews = state.cachedViews.slice(index, index + 1)
state.cachedViews = state.cachedViews.slice(index, index + 1);
} else {
state.cachedViews = []
state.cachedViews = [];
}
},
DEL_ALL_VISITED_VIEWS: state => {
// keep affix tags
const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
state.visitedViews = affixTags
state.iframeViews = []
const affixTags = state.visitedViews.filter(tag => tag.meta.affix);
state.visitedViews = affixTags;
state.iframeViews = [];
},
DEL_ALL_CACHED_VIEWS: state => {
state.cachedViews = []
state.cachedViews = [];
},
UPDATE_VISITED_VIEW: (state, view) => {
for (let v of state.visitedViews) {
if (v.fullPath === view.fullPath) {
v = Object.assign(v, view)
break
v = Object.assign(v, view);
break;
}
}
},
DEL_RIGHT_VIEWS: (state, view) => {
const index = state.visitedViews.findIndex(v => v.fullPath === view.fullPath)
const index = state.visitedViews.findIndex(v => v.fullPath === view.fullPath);
if (index === -1) {
return
return;
}
state.visitedViews = state.visitedViews.filter((item, idx) => {
if (idx <= index || (item.meta && item.meta.affix)) {
return true
return true;
}
const i = state.cachedViews.indexOf(item.name)
const i = state.cachedViews.indexOf(item.name);
if (i > -1) {
state.cachedViews.splice(i, 1)
state.cachedViews.splice(i, 1);
}
if(item.meta.link) {
const fi = state.iframeViews.findIndex(v => v.fullPath === item.fullPath)
state.iframeViews.splice(fi, 1)
if (item.meta.link) {
const fi = state.iframeViews.findIndex(v => v.fullPath === item.fullPath);
state.iframeViews.splice(fi, 1);
}
return false
})
return false;
});
},
DEL_LEFT_VIEWS: (state, view) => {
const index = state.visitedViews.findIndex(v => v.fullPath === view.fullPath)
const index = state.visitedViews.findIndex(v => v.fullPath === view.fullPath);
if (index === -1) {
return
return;
}
state.visitedViews = state.visitedViews.filter((item, idx) => {
if (idx >= index || (item.meta && item.meta.affix)) {
return true
return true;
}
const i = state.cachedViews.indexOf(item.name)
const i = state.cachedViews.indexOf(item.name);
if (i > -1) {
state.cachedViews.splice(i, 1)
state.cachedViews.splice(i, 1);
}
if(item.meta.link) {
const fi = state.iframeViews.findIndex(v => v.fullPath === item.fullPath)
state.iframeViews.splice(fi, 1)
if (item.meta.link) {
const fi = state.iframeViews.findIndex(v => v.fullPath === item.fullPath);
state.iframeViews.splice(fi, 1);
}
return false
})
return false;
});
}
}
};
const actions = {
addView({ dispatch }, view) {
dispatch('addVisitedView', view)
dispatch('addCachedView', view)
dispatch('addVisitedView', view);
dispatch('addCachedView', view);
},
addIframeView({ commit }, view) {
commit('ADD_IFRAME_VIEW', view)
commit('ADD_IFRAME_VIEW', view);
},
addVisitedView({ commit }, view) {
commit('ADD_VISITED_VIEW', view)
commit('ADD_VISITED_VIEW', view);
},
addCachedView({ commit }, view) {
commit('ADD_CACHED_VIEW', view)
commit('ADD_CACHED_VIEW', view);
},
delView({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delVisitedView', view)
dispatch('delCachedView', view)
dispatch('delVisitedView', view);
dispatch('delCachedView', view);
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
});
});
},
delVisitedView({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_VISITED_VIEW', view)
resolve([...state.visitedViews])
})
commit('DEL_VISITED_VIEW', view);
resolve([...state.visitedViews]);
});
},
delIframeView({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_IFRAME_VIEW', view)
resolve([...state.iframeViews])
})
commit('DEL_IFRAME_VIEW', view);
resolve([...state.iframeViews]);
});
},
delCachedView({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_CACHED_VIEW', view)
resolve([...state.cachedViews])
})
commit('DEL_CACHED_VIEW', view);
resolve([...state.cachedViews]);
});
},
delOthersViews({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delOthersVisitedViews', view)
dispatch('delOthersCachedViews', view)
dispatch('delOthersVisitedViews', view);
dispatch('delOthersCachedViews', view);
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
});
});
},
delOthersVisitedViews({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_OTHERS_VISITED_VIEWS', view)
resolve([...state.visitedViews])
})
commit('DEL_OTHERS_VISITED_VIEWS', view);
resolve([...state.visitedViews]);
});
},
delOthersCachedViews({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_OTHERS_CACHED_VIEWS', view)
resolve([...state.cachedViews])
})
commit('DEL_OTHERS_CACHED_VIEWS', view);
resolve([...state.cachedViews]);
});
},
delAllViews({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delAllVisitedViews', view)
dispatch('delAllCachedViews', view)
dispatch('delAllVisitedViews', view);
dispatch('delAllCachedViews', view);
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
});
});
},
delAllVisitedViews({ commit, state }) {
return new Promise(resolve => {
commit('DEL_ALL_VISITED_VIEWS')
resolve([...state.visitedViews])
})
commit('DEL_ALL_VISITED_VIEWS');
resolve([...state.visitedViews]);
});
},
delAllCachedViews({ commit, state }) {
return new Promise(resolve => {
commit('DEL_ALL_CACHED_VIEWS')
resolve([...state.cachedViews])
})
commit('DEL_ALL_CACHED_VIEWS');
resolve([...state.cachedViews]);
});
},
updateVisitedView({ commit }, view) {
commit('UPDATE_VISITED_VIEW', view)
commit('UPDATE_VISITED_VIEW', view);
},
delRightTags({ commit }, view) {
return new Promise(resolve => {
commit('DEL_RIGHT_VIEWS', view)
resolve([...state.visitedViews])
})
commit('DEL_RIGHT_VIEWS', view);
resolve([...state.visitedViews]);
});
},
delLeftTags({ commit }, view) {
return new Promise(resolve => {
commit('DEL_LEFT_VIEWS', view)
resolve([...state.visitedViews])
})
commit('DEL_LEFT_VIEWS', view);
resolve([...state.visitedViews]);
});
},
}
};
export default {
namespaced: true,
state,
mutations,
actions
}
};
/*
* @Author: thy
* @Date: 2023-11-08 09:28:17
* @LastEditors: thy
* @LastEditTime: 2023-11-14 13:56:59
* @Description: file content
* @FilePath: \dsk-operate-ui\src\utils\iframeTools.js
*/
import { dskAccessToken } from '@/api/common';
import { getUrlSearchQuery, isUrl, paramsToQuery } from "@/utils/";
import { Message } from "element-ui";
/**
* iframe嵌入参数处理
*/
class IframeTools {
queryParams = {};
pluginDomain = "";
subSystemIframe = null;
refreshTimer = null;
count = 0;
authToken = "";
origin = location.origin;
/**
* 插件域名地址
* @param {string} pluginDomain 默认当前环境变量VUE_APP_SUB_SYSTEM_ADDRESS
* @param {HTMLIFrameElement} subSystemIframe 子系统iframe dom节点
* @returns
*/
constructor(subSystemIframe, pluginDomain = process.env.VUE_APP_SUB_SYSTEM_ADDRESS) {
try {
const query = getUrlSearchQuery();
if (!query.url) return Message.warning("缺少子系统目标地址");
// 传入的iframeUrl不是一个合法地址
if (!isUrl(pluginDomain)) return Message.warning("子系统源地址不合法");
// 未获取到子系统节点
if (!subSystemIframe) return Message.warning("未获取到子系统节点");
this.queryParams = query;
this.pluginDomain = pluginDomain;
this.subSystemIframe = subSystemIframe;
// 是一个合法地址 初始化 先替换域名地址 再获取令牌并 拼接
this.init();
} catch (error) {
throw new Error(error);
}
}
/**
* 初始化类
*/
async init() {
try {
// 不是合法url的情况下需要拼接完整路径 例如path /xxxx/xxx
!isUrl(this.queryParams.url) ? this.queryParams.url = `${this.pluginDomain}${this.queryParams.url}` : null;
// 获取到子系统加载地址query参数
const subSystemParams = getUrlSearchQuery(this.queryParams.url);
// 获取子系统path
const subSystemUrl = new URL(this.queryParams.url);
// 以环境文件地址为准 拼接子系统查询参数
let url = `${this.pluginDomain}${subSystemUrl.pathname == "/" ? "" : subSystemUrl.pathname}`;
// 子系统地址带有查询参数 处理
Object.keys(subSystemParams).length ? url = `${url}?${paramsToQuery(subSystemParams)}` : null;
// 获取授权 token
const { accessToken, expire } = await this.getSubSystemToken();
// 拼接授权地址
if (accessToken) {
this.authToken = accessToken;
const query = {
initTime: new Date().valueOf(),
ak: accessToken,
uid: accessToken,
origin: this.origin
};
url = `${url}${paramsToQuery(query) ? "?" + paramsToQuery(query) : ""}`;
this.queryParams.url = url;
// 倒计时刷新token 正常误差10s 提前获取
this.setTokenRefresh(expire * 1000 - 1000 * 10);
}
} catch (error) {
console.log(error);
Message.warning(error.message ? error.message : (typeof error == "string") ? error : "子系统初始化错误");
}
}
/**
* 获取子系统token
*/
async getSubSystemToken() {
try {
const result = await dskAccessToken();
if (result.code == 200) {
return result.data;
}
throw new Error("子系统获取授权失败");
} catch (error) {
throw error;
}
}
/**
* 根据服务端返回过期时间刷新token有效期
*/
setTokenRefresh(expire) {
if (!expire) throw new Error("令牌无有效的刷新时间");
return new Promise((resolve, reject) => {
// 只允许出现一个定时器实例状态
this.clearRefreshTimer();
this.refreshTimer = setTimeout(async () => {
const result = await this.getSubSystemToken();
if (result.accessToken) {
this.count = 0;
this.authToken = result.accessToken;
this.setTokenRefresh(result.expire);
resolve(result);
} else {
// 请求失败进行重试 清理定时器
this.clearRefreshTimer();
// 尝试最多3次刷新 重新调取接口
while (this.count < 3) {
// 重试次数大于等于三次 停止刷新
if (this.count >= 3) {
return reject("子系统令牌刷新失败,请稍后重试");
}
this.count++;
Message.warning(`授权失败,正在尝试第 ${this.count} 次刷新令牌,请勿进行操作`);
const refreshAuth = await this.getSubSystemToken();
if (refreshAuth.accessToken) {
this.count = 0;
this.authToken = refreshAuth.accessToken;
this.setTokenRefresh(refreshAuth.expire);
resolve(refreshAuth);
}
}
}
}, expire);
});
}
clearRefreshTimer() {
clearTimeout(this.refreshTimer);
this.refreshTimer = null;
}
}
export default IframeTools;
\ No newline at end of file
import { Message } from "element-ui";
import { parseTime } from './ruoyi';
/**
......@@ -431,8 +432,7 @@ export const paramsToQuery = (query) => {
searchStrArray.push(`${key}=${decodeURIComponent(value)}`);
}
});
searchStrArray = searchStrArray.join("&");
return searchStr;
return searchStrArray.join("&");
} catch (error) {
console.log(error);
}
......@@ -457,6 +457,114 @@ export const searchTextToQuery = (text) => {
}
};
/**
* 验证链接是否是url
* @param {string} url
* @returns
*/
export function isUrl(url) {
return /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*[\u4e00-\u9fa5\w]*)$/.test(url);
}
// 对查询关键字中的特殊字符进行编码
export function encodeSearchKey(key) {
const encodeArr = [{
code: '%',
encode: '%25'
}, {
code: '?',
encode: '%3F'
}, {
code: '#',
encode: '%23'
}, {
code: '&',
encode: '%26'
}, {
code: '=',
encode: '%3D'
}];
return key.replace(/[%?#&=]/g, ($, index, str) => {
for (const k of encodeArr) {
if (k.code === $) {
return k.encode;
}
}
});
}
/**
* 去除json 换行空格符号
* @param {string} str
* @returns
*/
export function jsonEscape(str) {
return str.replace(/(\r\n|\n|\r)/gm, "");
}
/**
* json递归特殊参数处理
* @param {object} target
*/
export function jsonTraversal(target, decode = false) {
try {
if (Object.prototype.toString.call(target) != "[object Object]") throw new Error("传入参数不是一个对象");
for (const key in target) {
// 传入指定key 或者 key数组长度未0 默认全编码
if (Object.prototype.toString.call(target[key]) == "[object Object]") {
target[key] = jsonTraversal(target[key], decode);
} else {
if (decode) {
isencodingStr(target[key]) ? target[key] = decodeURIComponent(target[key]) : null;
} else {
needEncodeComponent(target[key]) ? target[key] = encodeURIComponent(target[key]) : null;
}
}
}
return target;
} catch (error) {
console.log(error);
}
}
/**
* url查询参数中需要编码的特殊字符
* @param {string} componentStr
* @returns
*/
export function needEncodeComponent(componentStr) {
const reg = /[^a-zA-Z0-9\-_.!~*'()]/gim;
return reg.test(componentStr);
}
/**
* 字符串是否被编码过
* @param {string} checkStr
* @returns
*/
export function isencodingStr(checkStr) {
const reg = /%[0-9A-Fa-f]{2}/gim;
return reg.test(checkStr);
}
let messageSingleton = null;
/**
* element message 弹窗单例模式
* @param {string} type
* @param {string} messgage
*/
export async function elementMessageSingleton(type = "success", messgage = "") {
try {
if (messageSingleton) {
messageSingleton.close();
}
} catch (error) {
console.log(error);
} finally {
messageSingleton = Message[type](messgage);
}
}
// 甲方详情左侧菜单映射
export const detailSideBar = new Map([
// 企业速览
......
......@@ -37,33 +37,33 @@ service.interceptors.request.use(config => {
config.params = {};
config.url = url;
}
cancelPending(config)
config.cancelToken = new CancelToken(res => {
pending.push({'UrlPath': config.url, 'Cancel': res})
})
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
time: new Date().getTime()
}
const sessionObj = cache.session.getJSON('sessionObj')
if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
cache.session.setJSON('sessionObj', requestObj)
} else {
const s_url = sessionObj.url; // 请求地址
const s_data = sessionObj.data; // 请求数据
const s_time = sessionObj.time; // 请求时间
const interval = 200; // 间隔时间(ms),小于此时间视为重复提交
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
const message = '数据正在处理,请勿重复提交';
console.warn(`[${s_url}]: ` + message)
return Promise.reject(new Error(message))
} else {
cache.session.setJSON('sessionObj', requestObj)
}
}
}
// cancelPending(config)
// config.cancelToken = new CancelToken(res => {
// pending.push({'UrlPath': config.url, 'Cancel': res})
// })
// if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
// const requestObj = {
// url: config.url,
// data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
// time: new Date().getTime()
// }
// const sessionObj = cache.session.getJSON('sessionObj')
// if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
// cache.session.setJSON('sessionObj', requestObj)
// } else {
// const s_url = sessionObj.url; // 请求地址
// const s_data = sessionObj.data; // 请求数据
// const s_time = sessionObj.time; // 请求时间
// const interval = 200; // 间隔时间(ms),小于此时间视为重复提交
// if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
// const message = '数据正在处理,请勿重复提交';
// console.warn(`[${s_url}]: ` + message)
// return Promise.reject(new Error(message))
// } else {
// cache.session.setJSON('sessionObj', requestObj)
// }
// }
// }
return config
}, error => {
console.log(error)
......@@ -125,10 +125,11 @@ service.interceptors.response.use(res => {
Notification.error({ title: msg })
return Promise.reject('error')
} else {
cancelPending(res.config)
// cancelPending(res.config)
return res.data
}
},error => {
console.log(error);
console.log('err' + error)
let { message } = error;
/*if (message == "Network Error") {
......
......@@ -3,7 +3,7 @@
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
return /^(https?:|mailto:|tel:)/.test(path);
}
/**
......@@ -11,8 +11,8 @@ export function isExternal(path) {
* @returns {Boolean}
*/
export function validUsername(str) {
const valid_map = ['admin', 'editor']
return valid_map.indexOf(str.trim()) >= 0
const valid_map = ['admin', 'editor'];
return valid_map.indexOf(str.trim()) >= 0;
}
/**
......@@ -20,8 +20,8 @@ export function validUsername(str) {
* @returns {Boolean}
*/
export function validURL(url) {
const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
return reg.test(url)
const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/;
return reg.test(url);
}
/**
......@@ -29,8 +29,8 @@ export function validURL(url) {
* @returns {Boolean}
*/
export function validLowerCase(str) {
const reg = /^[a-z]+$/
return reg.test(str)
const reg = /^[a-z]+$/;
return reg.test(str);
}
/**
......@@ -38,8 +38,8 @@ export function validLowerCase(str) {
* @returns {Boolean}
*/
export function validUpperCase(str) {
const reg = /^[A-Z]+$/
return reg.test(str)
const reg = /^[A-Z]+$/;
return reg.test(str);
}
/**
......@@ -47,8 +47,8 @@ export function validUpperCase(str) {
* @returns {Boolean}
*/
export function validAlphabets(str) {
const reg = /^[A-Za-z]+$/
return reg.test(str)
const reg = /^[A-Za-z]+$/;
return reg.test(str);
}
/**
......@@ -56,8 +56,8 @@ export function validAlphabets(str) {
* @returns {Boolean}
*/
export function validEmail(email) {
const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return reg.test(email)
const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return reg.test(email);
}
/**
......@@ -66,9 +66,9 @@ export function validEmail(email) {
*/
export function isString(str) {
if (typeof str === 'string' || str instanceof String) {
return true
return true;
}
return false
return false;
}
/**
......@@ -77,7 +77,34 @@ export function isString(str) {
*/
export function isArray(arg) {
if (typeof Array.isArray === 'undefined') {
return Object.prototype.toString.call(arg) === '[object Array]'
return Object.prototype.toString.call(arg) === '[object Array]';
}
return Array.isArray(arg)
return Array.isArray(arg);
}
/**
* 电话号码验证
* @param {object} rule
* @param {string} value
* @param {Function} callback
* @returns
*/
export function phoneNumberValidator(rule, value, callback) {
const phoneReg = /^1[3-9]\d{9}$/;
if (!value && !value?.toString()?.trim()) {
return callback(new Error(`请输入手机号码`));
}
if (value && !phoneReg.test(value)) {
return callback(new Error(`请输入正确的手机号码`));
}
return callback();
}
export function requiredStrLengthValidator(target) {
return function (rule, value, callback) {
if (!value && !value?.toString()?.trim()) {
return callback(new Error(`请输入${target}`));
}
return callback();
};
};
......@@ -278,13 +278,13 @@ export default {
this.sideRoute[2].children[7].disabled = true;
}
break;
case 'customer':
case 'customerV1':
if (arr[i][j] < 1) {
this.sideRoute[3].children[0].disabled = true;
}
break;
case 'supplier':
case 'supplierV1':
if (arr[i][j] < 1) {
this.sideRoute[3].children[1].disabled = true;
}
......
......@@ -184,7 +184,7 @@ export default {
showMore: false,
showState: false,
graphList: [
{ id: 1, name: '业务往来', isShow: true, intro: [{ id: 101, name: '客户', val: 0, category: 'global', field: 'customer' }, { id: 102, name: '供应商', val: 0, category: 'global', field: 'supplier' }], ico: require('@/assets/images/detail/overview/company_ywwl.png') },
{ id: 1, name: '业务往来', isShow: true, intro: [{ id: 101, name: '客户', val: 0, category: 'global', field: 'customerV1' }, { id: 102, name: '供应商', val: 0, category: 'global', field: 'supplierV1' }], ico: require('@/assets/images/detail/overview/company_ywwl.png') },
{ id: 2, name: '商机线索', isShow: true, intro: [{ id: 201, name: '专项债项目', val: 0, category: 'performance', field: 'specialDebt' }, { id: 202, name: '招标计划', val: 0, category: 'performance', field: 'bidPlan' }], ico: require('@/assets/images/detail/overview/company_sjxs.png') },
{ id: 3, name: '城投拿地', isShow: true, intro: [{ id: 301, name: '土地交易', val: 0, category: 'global', field: 'landInfo' }, { id: 302, name: '行政许可', val: 0, category: 'business', field: 'adminLicensing' }], ico: require('@/assets/images/detail/overview/company_ctnd.png') },
{ id: 4, name: '对外投资', isShow: true, intro: [{ id: 401, name: '企业经营实力展现' }], ico: require('@/assets/images/detail/overview/company_dwtz.png') },
......
<template>
<el-dialog title="添加账号" :visible.sync="dialogStatus" width="800px" @close="dialogClose" @open="dialogOpen" class="enterprise-add-account"
custom-class="enterprise-add-account-dialog" :close-on-click-modal="false">
<div class="enterprise-add-account-inner">
<el-form :model="accountForm" ref="accountForm" :rules="rules">
<transition-group tag="div" class="enterprise-add-account-list" name="list" appear>
<div class="enterprise-add-account-item" v-for="(item,index) of accountForm.accountList" :key="item.uid">
<div class="account-nickname">
<el-form-item label="用户名称" :prop="`accountList[${index}].nickName`" :rules="rules.nickName">
<el-input v-model="accountForm.accountList[index].nickName" placeholder="请输入用户名称" size="normal" clearable></el-input>
</el-form-item>
</div>
<div class="account-phone">
<el-form-item label="手机号码" :prop="`accountList[${index}].phonenumber`" :rules="rules.phonenumber">
<el-input v-model="accountForm.accountList[index].phonenumber" placeholder="请输入手机号码" size="normal" clearable></el-input>
</el-form-item>
</div>
<div class="remove-account-item" @click="removeAccount(item.uid)" v-if="accountForm.accountList.length > 1"><i class="el-icon-delete"></i>
</div>
</div>
</transition-group>
<!-- 添加按钮 -->
<div class="add-account-btn" @click="addAccount">
<i class="el-icon-plus"></i>
<span>增加账号</span>
</div>
</el-form>
</div>
<template slot="footer">
<!-- 底部提交 取消按钮 -->
<div class="add-account-footer">
<el-button type="primary" size="medium" @click="submitAdd">确定</el-button>
<el-button size="medium" @click="dialogClose">取消</el-button>
</div>
</template>
</el-dialog>
</template>
<script>
import { Loading } from 'element-ui';
import { enterpriseAddAccountApi } from "@/api/enterpriseManagement/enterpriseManagement";
import { phoneNumberValidator, requiredStrLengthValidator } from "@/utils/validate";
import { elementMessageSingleton } from "@/utils/";
import { v4 } from 'uuid';
export default {
name: "enterpriseAddAccount",
props: {
openStatus: {
type: Boolean,
default: false
},
enterpriseInfo: {
type: Object,
default: () => ({})
},
addAccountCount: {
type: [String, Number],
default: 1
}
},
watch: {
openStatus(newValue) {
this.dialogStatus = newValue;
},
addAccountCount(newValue) {
this.comAddAccountCount = newValue;
},
enterpriseInfo: {
handler(newValue) {
this.comEnterpriseInfo = newValue;
},
deep: true
}
},
data() {
return {
dialogStatus: this.openStatus,
comEnterpriseInfo: this.enterpriseInfo,
comAddAccountCount: this.addAccountCount,
accountForm: {
accountList: []
},
rules: {
nickName: [{ required: true, trigger: ["blur"], validator: requiredStrLengthValidator("用户名称") }],
phonenumber: [{ required: true, trigger: ["blur", "change"], validator: phoneNumberValidator }]
}
};
},
//可访问data属性
created() {
},
//计算集
computed: {
},
//方法集
methods: {
dialogOpen() {
this.addAccount();
},
dialogClose() {
this.accountForm = this.$options.data.call(this).accountForm;
this.$emit("dialogClose");
},
removeAccount(uid) {
const index = this.accountForm.accountList.findIndex(item => item.uid == uid);
if (index > -1) {
this.accountForm.accountList.splice(index, 1);
}
},
addAccount() {
if (this.comAddAccountCount >= 6) return elementMessageSingleton("warning", "该租户下已经添加了五个账号");
const remaining = 6 - this.comAddAccountCount;
const len = this.accountForm?.accountList?.length;
if (len >= remaining) return elementMessageSingleton("warning", `该租户下剩余可添加账号个数为 ${remaining} 个,现已添加 ${len} 个`);
this.accountForm.accountList.push({
nickName: "",
phonenumber: "",
uid: v4()
});
},
submitAdd() {
this.$refs["accountForm"].validate(async flag => {
if (!flag) return;
const loadingService = Loading.service({
target: ".enterprise-add-account-dialog",
lock: true,
text: "正在添加账号,请勿关闭窗口"
});
let successCount = 0;
try {
// 验证通过提交信息
const array = (JSON.parse(JSON.stringify(this.accountForm.accountList))).map(({ nickName, phonenumber }) => ({ nickName, phonenumber }));
let len = array.length;
let count = 0;
while (count < len) {
try {
const result = await enterpriseAddAccountApi({
tenantId: this.comEnterpriseInfo.tenantId,
packageId: this.comEnterpriseInfo.packageId,
nickName: array[count].nickName,
phonenumber: array[count].phonenumber,
});
if (result.code == 200) {
successCount++;
// 进度加载
} else {
elementMessageSingleton("error", result.msg);
}
} catch (error) {
console.log(error);
} finally {
count++;
}
}
this.dialogClose();
} catch (error) {
console.log(error);
} finally {
loadingService.close();
successCount > 0 ? this.$message.success("添加账号成功") : null;
}
});
}
},
}
</script>
<style lang="scss" scoped>
.enterprise-add-account {
::v-deep .enterprise-add-account-dialog {
.el-dialog__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 20px;
border-bottom: 1px solid #eee;
box-sizing: border-box;
.el-dialog__title {
font-size: 16px;
}
.el-dialog__headerbtn {
position: static;
display: flex;
align-items: center;
}
}
.el-dialog__body {
padding: 20px;
box-sizing: border-box;
.enterprise-add-account-inner {
.el-form {
display: flex;
justify-content: space-between;
.enterprise-add-account-list {
display: flex;
flex-direction: column;
position: relative;
& > .enterprise-add-account-item:first-of-type {
margin-top: 0px;
}
.enterprise-add-account-item {
display: flex;
align-items: center;
margin-top: 15px;
&:hover {
.remove-account-item {
opacity: 1;
& > i {
cursor: pointer;
}
}
}
.account-phone {
margin-left: 30px;
}
.el-form-item {
display: flex;
margin-bottom: 0px;
.el-form-item__content,
.el-form-item__label {
line-height: 32px;
}
.el-input {
.el-input__inner {
line-height: 32px;
height: 32px;
&::placeholder {
color: #c0c4cc !important;
font-weight: 400 !important;
font-size: 12px;
}
}
.el-input__suffix {
display: flex;
align-items: center;
.el-input__icon {
line-height: 32px;
}
}
}
.el-form-item__error {
padding-top: 2px;
}
}
.remove-account-item {
display: flex;
align-items: center;
margin-left: 15px;
opacity: 0;
transition: opacity 0.3s;
& > i {
font-size: 16px;
&:hover {
color: #f56c6c;
}
}
}
}
}
.add-account-btn {
line-height: 32px;
align-self: flex-start;
cursor: pointer;
color: #1890ff;
font-size: 14px;
span {
margin-left: 5px;
}
}
}
}
}
.el-dialog__footer {
padding: 0px;
.add-account-footer {
display: flex;
align-items: center;
justify-content: flex-end;
padding: 20px;
border-top: 1px solid #eee;
box-sizing: border-box;
.el-button {
height: 32px;
line-height: 32px;
padding: 0px 20px;
box-sizing: border-box;
}
}
}
}
}
</style>
<template>
<div class="app-container">
<div class="app-container enterprise-management-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="企业名称" prop="companyName">
<el-input
v-model="queryParams.companyName"
placeholder="请输入企业名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.companyName" placeholder="请输入企业名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="用户名称" prop="contactUserName">
<el-input
v-model="queryParams.contactUserName"
placeholder="请输入用户名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.contactUserName" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="手机号码" prop="contactPhone">
<el-input
v-model="queryParams.contactPhone"
placeholder="请输入手机号码"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.contactPhone" placeholder="请输入手机号码" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="账号状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="角色状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in dict.type.sys_user_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
<el-select v-model="queryParams.status" placeholder="角色状态" clearable style="width: 240px">
<el-option v-for="dict in dict.type.sys_user_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
......@@ -51,23 +23,10 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
>批量删除</el-button>
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete">批量删除</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
......@@ -87,7 +46,7 @@
<el-table-column label="续约结束时间" prop="expireTime" />
<el-table-column label="账号状态" align="center" width="100">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_user_status" :value="scope.row.status"/>
<dict-tag :options="dict.type.sys_user_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
......@@ -95,43 +54,18 @@
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="300">
<template slot-scope="scope" v-if="scope.row.roleId !== 1">
<el-button
size="mini"
type="text"
icon="el-icon-refresh"
@click="handleSync(scope.row)"
>同步</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-zoom-in"
@click="handleLook(scope.row)"
>查看</el-button>
<el-button size="mini" type="text" icon="el-icon-refresh" @click="handleSync(scope.row)">同步</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
<el-button size="mini" type="text" icon="el-icon-user" @click="handleAddAccount(scope.row)">添加账号</el-button>
<el-button size="mini" type="text" icon="el-icon-zoom-in" @click="handleLook(scope.row)">查看</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改对话框 -->
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
......@@ -139,56 +73,40 @@
<el-row>
<el-col :span="12">
<el-form-item label="企业名称" prop="companyName">
<el-input :disabled="disabled" v-model="form.companyName" placeholder="请输入企业名称"/>
<el-input :disabled="disabled" v-model="form.companyName" placeholder="请输入企业名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="用户名称" prop="contactUserName">
<el-input :disabled="disabled" v-model="form.contactUserName" placeholder="请输入用户名称"/>
<el-input :disabled="disabled" v-model="form.contactUserName" placeholder="请输入用户名称" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="续约时间" prop="dateRange">
<el-date-picker :disabled="disabled"
v-model="form.dateRange"
style="width: 240px"
value-format="yyyy-MM-dd HH:mm:ss"
type="datetimerange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-date-picker :disabled="disabled" v-model="form.dateRange" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss"
type="datetimerange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手机号码" prop="contactPhone">
<el-input :disabled="disabled" v-model="form.contactPhone" placeholder="请输手机号码"/>
<el-input :disabled="disabled" v-model="form.contactPhone" placeholder="请输手机号码" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="企业方案" prop="packageId">
<el-select :disabled="disabled"
v-model="form.packageId"
placeholder="企业方案"
clearable
style="width: 240px"
>
<el-option
v-for="dict in packageList"
:key="dict.packageId"
:label="dict.packageName"
:value="dict.packageId"
/>
<el-select :disabled="disabled" v-model="form.packageId" placeholder="企业方案" clearable style="width: 240px">
<el-option v-for="dict in packageList" :key="dict.packageId" :label="dict.packageName" :value="dict.packageId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="企业规模" prop="accountCount">
<el-input onkeyup="this.value=this.value.replace(/[^0-9]/g,'')" :disabled="disabled" v-model="form.accountCount" placeholder="请输入企业规模"/>
<el-input onkeyup="this.value=this.value.replace(/[^0-9]/g,'')" :disabled="disabled" v-model="form.accountCount"
placeholder="请输入企业规模" />
</el-form-item>
</el-col>
</el-row>
......@@ -196,11 +114,7 @@
<el-col :span="12">
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status" :disabled="disabled">
<el-radio
v-for="dict in dict.type.sys_user_status"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
<el-radio v-for="dict in dict.type.sys_user_status" :key="dict.value" :label="dict.value">{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
......@@ -212,11 +126,7 @@
</div>
</el-dialog>
<el-dialog
title="权限同步"
:visible.sync="dialogVisible1"
custom-class="sync"
width="400px">
<el-dialog title="权限同步" :visible.sync="dialogVisible1" custom-class="sync" width="400px">
<p style="font-size: 16px;"><i class="el-icon-warning-outline" style="margin-right: 8px;"></i>是否确认同步?</p>
<p>温馨提示:此操作可能会影响正在使用的用户,建议合理安排同步时间</p>
<div slot="footer" class="dialog-footer">
......@@ -224,26 +134,37 @@
<el-button type="primary" @click="handleConfirm()" :loading="state">同步</el-button>
</div>
</el-dialog>
<!-- 添加账号 -->
<enterprise-add-account :openStatus="addAccountDialog" :enterpriseInfo="addAccountEnterpriseInfo" @dialogClose="enterpriseDialogClose"
:addAccountCount="addAccountCount"></enterprise-add-account>
</div>
</template>
<script>
import {
import {
deleteTenant,
editTenant,
getTenant,
getTenantList,
saveTenant,
selectTenant,
syncTenantPackage
} from '@/api/enterpriseManagement/enterpriseManagement'
syncTenantPackage,
getEnterpriseAddAccountCountApi
} from '@/api/enterpriseManagement/enterpriseManagement';
import EnterpriseAddAccount from "./components/EnterpriseAddAccount";
export default {
export default {
name: "EnterpriseManagement",
dicts: ['sys_user_status'],
components: {
EnterpriseAddAccount
},
data() {
return {
disabled:false,
disabled: false,
// 遮罩层
loading: true,
// 选中数组
......@@ -276,7 +197,7 @@
form: {},
// 表单校验
rules: {
contactPhone : [
contactPhone: [
{ required: true, message: "手机号码不能为空", trigger: "blur" },
{
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
......@@ -304,20 +225,48 @@
],
},
//企业方案列表
packageList:[],
syncItem:{},
state:false,
packageList: [],
syncItem: {},
state: false,
// 添加账号弹窗
addAccountDialog: false,
// 企业信息
addAccountEnterpriseInfo: {},
// 该租户下已经创建账号数量
addAccountCount: 1
};
},
created() {
this.getList();
},
methods: {
enterpriseDialogClose() {
this.addAccountDialog = false;
this.addAccountEnterpriseInfo = this.$options.data.call(this).addAccountEnterpriseInfo;
this.addAccountCount = this.$options.data.call(this).addAccountCount;
},
// 新增用户账号
async handleAddAccount(row) {
try {
if (!row.tenantId) return this.$message.warning("缺少租户ID");
const countResult = await getEnterpriseAddAccountCountApi(row.tenantId);
if (countResult.code == 200) {
if (countResult.data >= 6) {
this.addAccountCount = countResult.data;
return this.$message.warning("该租户下已经添加过五个账号");
}
this.addAccountEnterpriseInfo = row;
this.addAccountDialog = true;
}
} catch (error) {
}
},
//获取企业方案列表
getpack(){
selectTenant().then(res=>{
if(res.code = 200){
this.packageList = res.data
getpack() {
selectTenant().then(res => {
if (res.code = 200) {
this.packageList = res.data;
// this.packageList.forEach(item=>{
// if(item.status == '0'){
// item.disabled = false
......@@ -326,7 +275,7 @@
// }
// })
}
})
});
},
/** 查询角色列表 */
getList() {
......@@ -371,56 +320,56 @@
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!=1
this.multiple = !selection.length
this.ids = selection.map(item => item.id);
this.single = selection.length != 1;
this.multiple = !selection.length;
},
/** 新增按钮操作 */
handleAdd() {
this.disabled = false
this.disabled = false;
this.reset();
this.open = true;
this.title = "添加企业";
this.getpack()
this.getpack();
},
/** 同步弹窗显示 */
handleSync(row) {
this.dialogVisible1=true;
this.syncItem=row;
this.dialogVisible1 = true;
this.syncItem = row;
},
/** 同步按钮操作 */
handleConfirm() {
let _this = this
this.state=true
syncTenantPackage({tenantId:this.syncItem.tenantId,packageId:this.syncItem.packageId}).then(res => {
if(res.code === 200){
this.state=false
let _this = this;
this.state = true;
syncTenantPackage({ tenantId: this.syncItem.tenantId, packageId: this.syncItem.packageId }).then(res => {
if (res.code === 200) {
this.state = false;
_this.$message.success(res.msg);
this.dialogVisible1=false;
this.dialogVisible1 = false;
}
});
},
/** 修改按钮操作 */
handleUpdate(row) {
this.disabled = false
this.disabled = false;
this.reset();
const id = row.id
this.getpack()
const id = row.id;
this.getpack();
getTenant(id).then(response => {
this.form = response.data;
this.form.dateRange = [response.data.startTime,response.data.expireTime]
this.form.dateRange = [response.data.startTime, response.data.expireTime];
this.open = true;
this.title = this.disabled == true?'查看企业':"修改企业";
this.title = this.disabled == true ? '查看企业' : "修改企业";
});
},
//查看
handleLook(row){
this.handleUpdate(row)
this.disabled = true
handleLook(row) {
this.handleUpdate(row);
this.disabled = true;
},
/** 提交按钮 */
submitForm: function() {
submitForm: function () {
this.$refs["form"].validate(valid => {
if (valid) {
const loading = this.$loading({
......@@ -429,41 +378,41 @@
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.form.startTime = this.form.dateRange[0]
this.form.expireTime = this.form.dateRange[1]
let thistime = new Date(this.form.expireTime).getTime()
if(thistime < new Date().getTime()){
this.$message.error('不能选择过去时间!')
return false
this.form.startTime = this.form.dateRange[0];
this.form.expireTime = this.form.dateRange[1];
let thistime = new Date(this.form.expireTime).getTime();
if (thistime < new Date().getTime()) {
this.$message.error('不能选择过去时间!');
return false;
}
if (this.form.id != undefined) {
editTenant(this.form).then(response => {
if (response.code == 200) {
this.$modal.msgSuccess('修改成功')
this.open = false
this.getList()
loading.close()
this.$modal.msgSuccess('修改成功');
this.open = false;
this.getList();
loading.close();
} else {
this.$modal.msgError(response.msg)
this.$modal.msgError(response.msg);
loading.close();
}
}).catch(response => {
this.$modal.msgError(response.msg)
this.$modal.msgError(response.msg);
loading.close();
});
} else {
saveTenant(this.form).then(response => {
if (response.code == 200){
if (response.code == 200) {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
loading.close();
}else{
this.$modal.msgError(response.msg)
} else {
this.$modal.msgError(response.msg);
loading.close();
}
}).catch(response => {
this.$modal.msgError(response.msg)
this.$modal.msgError(response.msg);
loading.close();
});
}
......@@ -473,29 +422,41 @@
/** 删除按钮操作 */
handleDelete(row) {
const Ids = row.id || this.ids;
let _this = this
this.$modal.confirm('是否确认删除选中的企业数据项?').then(function() {
deleteTenant(Ids).then(res=>{
if(res.code == 200){
let _this = this;
this.$modal.confirm('是否确认删除选中的企业数据项?').then(function () {
deleteTenant(Ids).then(res => {
if (res.code == 200) {
_this.getList();
_this.$message.success("删除成功");
}else{
} else {
_this.$message.error(res.msg);
}
});
}).catch(() => {});
}).catch(() => { });
},
}
};
};
</script>
<style lang="scss" scoped>
::v-deep .sync{
.el-dialog__header{
::v-deep .sync {
.el-dialog__header {
border-bottom: 1px solid #eee;
}
.el-dialog__body{
padding: 15px 20px
}
.el-dialog__body {
padding: 15px 20px;
}
}
.enterprise-management-container {
width: 100%;
height: 100%;
margin: 0px;
padding: 16px 24px;
box-sizing: border-box;
position: absolute;
top: 0;
left: 0;
overflow: auto;
}
</style>
......@@ -24,7 +24,6 @@
<el-form-item prop="captchaCode" v-if="captchaEnabled">
<el-input
v-model="dxform.captchaCode"
@focus="getCode"
auto-complete="off"
placeholder="请输入图形验证码"
style="width: 196px;float: left;"
......@@ -93,7 +92,6 @@
v-model="loginForm.code"
auto-complete="off"
placeholder="请输入图形验证码"
@focus="getCode"
style="width: 196px;float: left;"
@keyup.enter.native="handleLogin"
>
......
......@@ -57,7 +57,8 @@ export default {
},
methods: {
linkListener(event) {
let { data } = event;
let { data, origin } = event;
if (origin != this.domain) return;
if (data.id) {
getUipIdByCid([data.id]).then(res => {
if (res.code == 200) {
......@@ -73,9 +74,7 @@ export default {
});
} else {
if (data.url) {
this.$tab.openPage(data.title, data.url).then(() => {
// 执行结束的逻辑
});
this.$tab.openPage(data.title, data.url);
}
}
},
......
<template>
<div class="iframe-com-ins" :style="stylesTransform(containerStyles)">
<iframe :src="url" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" width="100%"
:style="stylesTransform(iframeInsStyles)"></iframe>
</div>
</template>
<script>
export default {
name: "iframeComIns",
props: {
// 容器样式
styles: {
type: [Object, String],
default: () => ("")
},
// iframe样式
iframeStyles: {
type: [Object, String],
default: () => ("")
},
// 子系统链接地址
url: {
type: String,
default: ""
}
},
watch: {
"styles": {
handler(newValue) {
this.containerStyles = newValue;
},
deep: true
},
"iframeStyles": {
handler(newValue) {
console.log(newValue);
this.iframeInsStyles = newValue;
},
deep: true
},
},
data() {
return {
containerStyles: this.styles,
iframeInsStyles: this.iframeStyles
};
},
//可访问data属性
created() {
},
//计算集
computed: {
},
//方法集
methods: {
stylesTransform(stylesStr) {
try {
const styles = typeof stylesStr == "string" ? JSON.parse(stylesStr) : stylesStr;
return styles ? styles : {};
} catch (error) {
return {};
}
}
},
}
</script>
<style lang="scss" scoped>
.iframe-com-ins {
width: 100%;
height: 100%;
box-sizing: border-box;
}
</style>
<template>
<div class="subsystem-iframe-container">
<div @click="$router.push({path : '/subsystem',query : ({id:1})})">11</div>
<iframe-com-ins ref="subsystemIframeContainer" :iframeStyles="urlQueryParams.iframeStyles" :styles="urlQueryParams.styles"
:url="urlQueryParams.url"></iframe-com-ins>
</div>
</template>
<script>
import { getUrlSearchQuery } from "@/utils/";
import IframeComIns from "./components/IframeComIns";
import IframeTools from "@/utils/iframeTools";
export default {
name: "subsystemIframeContainer",
components: {
IframeComIns
},
data() {
return {
urlQueryParams: {},
iframeToolsIns: {}
};
},
//可访问data属性
created() {
console.log(this.$route);
console.log(getUrlSearchQuery());
this.Init();
},
beforeDestroy() {
if (this.iframeToolsIns) {
this.iframeToolsIns.clearRefreshTimer ? this.iframeToolsIns.clearRefreshTimer() : null;
}
},
//计算集
computed: {
......@@ -23,12 +33,15 @@ export default {
},
//方法集
methods: {
},
// 渲染方法
render(createElement) {
async Init() {
await this.$nextTick();
const dom = this.$refs["subsystemIframeContainer"].$el.querySelector("iframe");
const iframeTools = new IframeTools(dom);
this.iframeToolsIns = iframeTools;
this.urlQueryParams = iframeTools.queryParams;
console.log(this.urlQueryParams);
}
},
}
</script>
<style lang="scss" scoped>
......@@ -38,7 +51,6 @@ export default {
left: 0;
width: 100%;
height: 100%;
padding: 16px 24px;
box-sizing: border-box;
}
</style>
<template>
<div class="app-container">
<div class="app-container menu-manage-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="菜单名称" prop="menuName">
<el-input
v-model="queryParams.menuName"
placeholder="请输入菜单名称"
clearable
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.menuName" placeholder="请输入菜单名称" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="菜单状态" clearable>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
<el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
......@@ -27,35 +17,16 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['system:menu:add']"
>新增</el-button>
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:menu:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="el-icon-sort"
size="mini"
@click="toggleExpandAll"
>展开/折叠</el-button>
<el-button type="info" plain icon="el-icon-sort" size="mini" @click="toggleExpandAll">展开/折叠</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table
v-if="refreshTable"
v-loading="loading"
:data="menuList"
row-key="menuId"
:default-expand-all="isExpandAll"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
>
<el-table v-if="refreshTable" v-loading="loading" :data="menuList" row-key="menuId" :default-expand-all="isExpandAll"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}">
<el-table-column prop="menuName" label="菜单名称" :show-overflow-tooltip="true" width="160"></el-table-column>
<el-table-column prop="icon" label="图标" align="center" width="100">
<template slot-scope="scope">
......@@ -67,7 +38,7 @@
<el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="status" label="状态" width="80">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime">
......@@ -77,27 +48,9 @@
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['system:menu:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-plus"
@click="handleAdd(scope.row)"
v-hasPermi="['system:menu:add']"
>新增</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['system:menu:remove']"
>删除</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:menu:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-plus" @click="handleAdd(scope.row)" v-hasPermi="['system:menu:add']">新增</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:menu:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
......@@ -108,13 +61,7 @@
<el-row>
<el-col :span="24">
<el-form-item label="上级菜单" prop="parentId">
<treeselect
v-model="form.parentId"
:options="menuOptions"
:normalizer="normalizer"
:show-count="true"
placeholder="选择上级菜单"
/>
<treeselect v-model="form.parentId" :options="menuOptions" :normalizer="normalizer" :show-count="true" placeholder="选择上级菜单" />
</el-form-item>
</el-col>
<el-col :span="24">
......@@ -128,20 +75,10 @@
</el-col>
<el-col :span="24" v-if="form.menuType != 'F'">
<el-form-item label="菜单图标" prop="icon">
<el-popover
placement="bottom-start"
width="460"
trigger="click"
@show="$refs['iconSelect'].reset()"
>
<el-popover placement="bottom-start" width="460" trigger="click" @show="$refs['iconSelect'].reset()">
<IconSelect ref="iconSelect" @selected="selected" :active-icon="form.icon" />
<el-input slot="reference" v-model="form.icon" placeholder="点击选择图标" readonly>
<svg-icon
v-if="form.icon"
slot="prefix"
:icon-class="form.icon"
style="width: 25px;"
/>
<svg-icon v-if="form.icon" slot="prefix" :icon-class="form.icon" style="width: 25px;" />
<i v-else slot="prefix" class="el-icon-search el-input__icon" />
</el-input>
</el-popover>
......@@ -206,7 +143,8 @@
</el-col>
<el-col :span="12" v-if="form.menuType == 'C'">
<el-form-item prop="queryParam">
<el-input v-model="form.queryParam" placeholder="请输入路由参数" maxlength="255" />
<!-- <el-input v-model="form.queryParam" placeholder="请输入路由参数" maxlength="255" /> -->
<el-button type="primary" size="mini" @click="editJsonValue">编辑路由参数</el-button>
<span slot="label">
<el-tooltip content='访问路由的默认传递参数,如:`{"id": 1, "name": "ry"}`' placement="top">
<i class="el-icon-question"></i>
......@@ -238,11 +176,7 @@
显示状态
</span>
<el-radio-group v-model="form.visible">
<el-radio
v-for="dict in dict.type.sys_show_hide"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
<el-radio v-for="dict in dict.type.sys_show_hide" :key="dict.value" :label="dict.value">{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
......@@ -255,11 +189,7 @@
菜单状态
</span>
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
<el-radio v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.value">{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
......@@ -270,6 +200,20 @@
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
<!-- json编辑器 -->
<el-dialog title="路由参数编辑" :visible.sync="jsonDialog" width="700px" custom-class="json-editor-dialog" :close-on-click-modal="false"
@close="jsonDialogClose" :destroy-on-close="true">
<div class="json-editor-dialog-inner">
<dsk-json-editor :jsonValue="jsonValue" :defaultMode="defaultMode" :jsonReadOnly="jsonReadOnly" ref="dskJsonEditorContainer"
@jsonChange="jsonChange"></dsk-json-editor>
</div>
<div class="tool-bar">
<el-button type="primary" size="small" @click="saveJson">保存</el-button>
<el-button type="info" size="small" @click="jsonDialog = false">取消</el-button>
</div>
</el-dialog>
</div>
</template>
......@@ -278,11 +222,13 @@ import { listMenu, getMenu, delMenu, addMenu, updateMenu } from "@/api/system/me
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import IconSelect from "@/components/IconSelect";
import DskJsonEditor from "@/components/DskJsonEditor/";
import { jsonTraversal } from "@/utils";
export default {
name: "Menu",
dicts: ['sys_show_hide', 'sys_normal_disable'],
components: { Treeselect, IconSelect },
components: { Treeselect, IconSelect, DskJsonEditor },
data() {
return {
// 遮罩层
......@@ -306,7 +252,7 @@ export default {
menuName: undefined,
visible: undefined
},
// 表单参数
// 表单参数 查询参数字段值 保持 json编码转义后的字符串
form: {},
// 表单校验
rules: {
......@@ -319,13 +265,49 @@ export default {
path: [
{ required: true, message: "路由地址不能为空", trigger: "blur" }
]
}
},
// json编辑器值
jsonValue: {},
// 默认展示模式
defaultMode: "text",
// 是否只读
jsonReadOnly: false,
// json编辑器弹窗
jsonDialog: false,
};
},
created() {
this.getList();
},
methods: {
editJsonValue() {
this.jsonValue = this.form.queryParam ? jsonTraversal(JSON.parse(this.form.queryParam), true) : {};
this.jsonDialog = true;
},
// json编辑器弹窗关闭
jsonDialogClose() {
// 重置jsonValue值
this.jsonValue = this.$options.data.call(this).jsonValue;
},
// json编辑器值改变
jsonChange(value) {
this.jsonValue = value;
},
// 保存json数据
async saveJson() {
try {
// 验证格式是否正确
const validatorResult = await this.$refs["dskJsonEditorContainer"].validateJson();
// 通过验证
if (validatorResult.isPass) {
this.form.queryParam = validatorResult.value;
// 关闭弹窗
this.jsonDialog = false;
}
} catch (error) {
console.log(error);
}
},
// 选择图标
selected(name) {
this.form.icon = name;
......@@ -413,23 +395,37 @@ export default {
this.reset();
this.getTreeselect();
getMenu(row.menuId).then(response => {
this.form = response.data;
const data = response.data;
if (data.queryParam) {
const query = JSON.parse(data.queryParam);
// 转换为对象
const queryResult = jsonTraversal(JSON.parse(JSON.stringify(query)), true);
this.jsonValue = queryResult;
}
this.form = data;
this.open = true;
this.title = "修改菜单";
});
},
/** 提交按钮 */
submitForm: function() {
submitForm: function () {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.menuId != undefined) {
updateMenu(this.form).then(response => {
const params = JSON.parse(JSON.stringify(this.form));
if (params.queryParam) {
const query = JSON.parse(params.queryParam);
let queryResult = jsonTraversal(JSON.parse(JSON.stringify(query)), true);
queryResult = jsonTraversal(JSON.parse(JSON.stringify(queryResult)));
params.queryParam = JSON.stringify(queryResult);
}
if (params.menuId != undefined) {
updateMenu(params).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addMenu(this.form).then(response => {
addMenu(params).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
......@@ -440,13 +436,39 @@ export default {
},
/** 删除按钮操作 */
handleDelete(row) {
this.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?').then(function() {
this.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?').then(function () {
return delMenu(row.menuId);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
}).catch(() => { });
}
}
};
</script>
<style lang="scss" scoped>
.menu-manage-container {
::v-deep .json-editor-dialog {
height: 80%;
.el-dialog__header,
.el-dialog__body {
padding: 16px;
box-sizing: border-box;
}
.el-dialog__body {
height: calc(100% - 56px);
}
.json-editor-dialog-inner {
width: 100%;
height: calc(100% - 44px);
}
.tool-bar {
width: 100%;
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 12px;
}
}
}
</style>
......@@ -2,22 +2,10 @@
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="用户名称" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入用户名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input
v-model="queryParams.phonenumber"
placeholder="请输入手机号码"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
......@@ -27,47 +15,29 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="openSelectUser"
v-hasPermi="['system:role:add']"
>添加用户</el-button>
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="openSelectUser" v-hasPermi="['system:role:add']">添加用户</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-circle-close"
size="mini"
:disabled="multiple"
@click="cancelAuthUserAll"
v-hasPermi="['system:role:remove']"
>批量取消授权</el-button>
<el-button type="danger" plain icon="el-icon-circle-close" size="mini" :disabled="multiple" @click="cancelAuthUserAll"
v-hasPermi="['system:role:remove']">批量取消授权</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-close"
size="mini"
@click="handleClose"
>关闭</el-button>
<el-button type="warning" plain icon="el-icon-close" size="mini" @click="handleClose">关闭</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
<el-table-column label="用户编号" align="center" prop="userId" />
<!-- <el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" /> -->
<el-table-column label="用户名称" prop="nickName" align="center" :show-overflow-tooltip="true" />
<el-table-column label="组织" align="center" prop="dept.deptName" :show-overflow-tooltip="true" />
<!-- <el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" /> -->
<el-table-column label="手机" prop="phonenumber" align="center" :show-overflow-tooltip="true" />
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
......@@ -77,24 +47,13 @@
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-circle-close"
@click="cancelAuthUser(scope.row)"
v-hasPermi="['system:role:remove']"
>取消授权</el-button>
<el-button size="mini" type="text" icon="el-icon-circle-close" @click="cancelAuthUser(scope.row)"
v-hasPermi="['system:role:remove']">取消授权</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<select-user ref="select" :roleId="queryParams.roleId" @ok="handleQuery" />
</div>
</template>
......@@ -166,8 +125,8 @@ export default {
},
// 多选框选中数据
handleSelectionChange(selection) {
this.userIds = selection.map(item => item.userId)
this.multiple = !selection.length
this.userIds = selection.map(item => item.userId);
this.multiple = !selection.length;
},
/** 打开授权用户表弹窗 */
openSelectUser() {
......@@ -176,23 +135,37 @@ export default {
/** 取消授权按钮操作 */
cancelAuthUser(row) {
const roleId = this.queryParams.roleId;
this.$modal.confirm('确认要取消该用户"' + row.userName + '"角色吗?').then(function() {
return authUserCancel({ userId: row.userId, roleId: roleId });
}).then(() => {
this.$modal.confirm('确认要取消该用户"' + row.userName + '"角色吗?').then(async () => {
try {
const result = await authUserCancel({ userId: row.userId, roleId: roleId });
if (result.code == 200) {
this.getList();
this.$modal.msgSuccess("取消授权成功");
}).catch(() => {});
} else {
this.$message.error(result.msg);
}
} catch (error) {
}
}).catch(() => { });
},
/** 批量取消授权按钮操作 */
cancelAuthUserAll(row) {
const roleId = this.queryParams.roleId;
const userIds = this.userIds.join(",");
this.$modal.confirm('是否取消选中用户授权数据项?').then(function() {
return authUserCancelAll({ roleId: roleId, userIds: userIds });
}).then(() => {
this.$modal.confirm('是否取消选中用户授权数据项?').then(async () => {
try {
const result = await authUserCancelAll({ roleId: roleId, userIds: userIds });
if (result.code == 200) {
this.getList();
this.$modal.msgSuccess("取消授权成功");
}).catch(() => {});
} else {
this.$message.error(`${result.msg}账号下仅有一个角色,取消授权失败`);
}
} catch (error) {
}
}).catch(() => { });
}
}
};
......
......@@ -2,48 +2,19 @@
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="角色名称" prop="roleName">
<el-input
v-model="queryParams.roleName"
placeholder="请输入角色名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.roleName" placeholder="请输入角色名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="权限字符" prop="roleKey">
<el-input
v-model="queryParams.roleKey"
placeholder="请输入权限字符"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.roleKey" placeholder="请输入权限字符" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="角色状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
<el-select v-model="queryParams.status" placeholder="角色状态" clearable style="width: 240px">
<el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
......@@ -53,64 +24,31 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['system:role:add']"
>新增</el-button>
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:role:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['system:role:edit']"
>修改</el-button>
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
v-hasPermi="['system:role:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['system:role:remove']"
>删除</el-button>
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
v-hasPermi="['system:role:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['system:role:export']"
>导出</el-button>
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['system:role:export']">导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="roleList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="角色编号" prop="roleId" width="120" />
<!-- <el-table-column label="角色编号" prop="roleId" width="120" /> -->
<el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" />
<el-table-column label="权限字符" prop="roleKey" :show-overflow-tooltip="true" width="150" />
<el-table-column label="显示顺序" prop="roleSort" width="100" />
<el-table-column label="显示顺序" align="center" prop="roleSort" width="100" />
<el-table-column label="状态" align="center" width="100">
<template slot-scope="scope">
<el-switch
v-model="scope.row.status"
active-value="0"
inactive-value="1"
@change="handleStatusChange(scope.row)"
></el-switch>
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
......@@ -120,34 +58,12 @@
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope" v-if="scope.row.roleId !== 1">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['system:role:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['system:role:remove']"
>删除</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-check"
@click="handleDataScope(scope.row)"
v-hasPermi="['system:role:edit']"
>数据权限</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-user"
@click="handleAuthUser(scope.row)"
v-hasPermi="['system:role:edit']"
>分配用户</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:role:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-if="canDelete(scope.row.roleKey)"
v-hasPermi="['system:role:remove']">删除</el-button>
<el-button size="mini" type="text" icon="el-icon-check" @click="handleDataScope(scope.row)"
v-hasPermi="['system:role:edit']">数据权限</el-button>
<el-button size="mini" type="text" icon="el-icon-user" @click="handleAuthUser(scope.row)" v-hasPermi="['system:role:edit']">分配用户</el-button>
<!--<el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:role:edit']">-->
<!--<el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>-->
<!--<el-dropdown-menu slot="dropdown">-->
......@@ -161,13 +77,7 @@
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 添加或修改角色配置对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
......@@ -175,41 +85,30 @@
<el-form-item label="角色名称" prop="roleName">
<el-input v-model="form.roleName" placeholder="请输入角色名称" />
</el-form-item>
<el-form-item prop="roleKey">
<el-form-item prop="roleKey" :rules="!roleArray.includes('superadmin') ? {} : rules.roleKey">
<span slot="label">
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasRole('admin')`)" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
权限字符
</span>
<el-input v-model="form.roleKey" placeholder="请输入权限字符" />
<el-input v-model="form.roleKey" :placeholder="!roleArray.includes('superadmin') ? '权限字符自动生成' : '请输入权限字符'"
:disabled="!roleArray.includes('superadmin')" />
</el-form-item>
<el-form-item label="角色顺序" prop="roleSort">
<el-input-number v-model="form.roleSort" controls-position="right" :min="0" />
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
<el-radio v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.value">{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="菜单权限">
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
<el-tree
class="tree-border"
:data="menuOptions"
show-checkbox
ref="menu"
node-key="id"
:check-strictly="!form.menuCheckStrictly"
empty-text="加载中,请稍候"
:props="defaultProps"
></el-tree>
<el-tree class="tree-border" :data="menuOptions" show-checkbox ref="menu" node-key="id" :check-strictly="!form.menuCheckStrictly"
empty-text="加载中,请稍候" :props="defaultProps"></el-tree>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
......@@ -232,29 +131,15 @@
</el-form-item>
<el-form-item label="权限范围">
<el-select v-model="form.dataScope" @change="dataScopeSelectChange">
<el-option
v-for="item in dataScopeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
<el-option v-for="item in dataScopeOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="数据权限" v-show="form.dataScope == 2">
<el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
<el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
<el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
<el-tree
class="tree-border"
:data="deptOptions"
show-checkbox
default-expand-all
ref="dept"
node-key="id"
:check-strictly="!form.deptCheckStrictly"
empty-text="加载中,请稍候"
:props="defaultProps"
></el-tree>
<el-tree class="tree-border" :data="deptOptions" show-checkbox default-expand-all ref="dept" node-key="id"
:check-strictly="!form.deptCheckStrictly" empty-text="加载中,请稍候" :props="defaultProps"></el-tree>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
......@@ -268,6 +153,7 @@
<script>
import { listRole, getRole, delRole, addRole, updateRole, dataScope, changeRoleStatus, deptTreeSelect } from "@/api/system/role";
import { treeselect as menuTreeselect, roleMenuTreeselect } from "@/api/system/menu";
import { mapGetters } from 'vuex';
export default {
name: "Role",
......@@ -358,7 +244,15 @@ export default {
created() {
this.getList();
},
computed: {
...mapGetters({
roleArray: "roles"
}),
},
methods: {
canDelete(role) {
return role != "tenantSuperAdmin" || (this.roleArray.includes("superadmin") && role == "tenantSuperAdmin");
},
/** 查询角色列表 */
getList() {
this.loading = true;
......@@ -410,11 +304,11 @@ export default {
// 角色状态修改
handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用";
this.$modal.confirm('确认要"' + text + '""' + row.roleName + '"角色吗?').then(function() {
this.$modal.confirm('确认要"' + text + '""' + row.roleName + '"角色吗?').then(function () {
return changeRoleStatus(row.roleId, row.status);
}).then(() => {
this.$modal.msgSuccess(text + "成功");
}).catch(function() {
}).catch(function () {
row.status = row.status === "0" ? "1" : "0";
});
},
......@@ -464,9 +358,9 @@ export default {
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.roleId)
this.single = selection.length!=1
this.multiple = !selection.length
this.ids = selection.map(item => item.roleId);
this.single = selection.length != 1;
this.multiple = !selection.length;
},
// 更多操作触发
handleCommand(command, row) {
......@@ -498,17 +392,17 @@ export default {
// 树权限(全选/全不选)
handleCheckedTreeNodeAll(value, type) {
if (type == 'menu') {
this.$refs.menu.setCheckedNodes(value ? this.menuOptions: []);
this.$refs.menu.setCheckedNodes(value ? this.menuOptions : []);
} else if (type == 'dept') {
this.$refs.dept.setCheckedNodes(value ? this.deptOptions: []);
this.$refs.dept.setCheckedNodes(value ? this.deptOptions : []);
}
},
// 树权限(父子联动)
handleCheckedTreeConnect(value, type) {
if (type == 'menu') {
this.form.menuCheckStrictly = value ? true: false;
this.form.menuCheckStrictly = value ? true : false;
} else if (type == 'dept') {
this.form.deptCheckStrictly = value ? true: false;
this.form.deptCheckStrictly = value ? true : false;
}
},
/** 新增按钮操作 */
......@@ -521,19 +415,19 @@ export default {
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const roleId = row.roleId || this.ids
const roleId = row.roleId || this.ids;
const roleMenu = this.getRoleMenuTreeselect(roleId);
getRole(roleId).then(response => {
this.form = response.data;
this.open = true;
this.$nextTick(() => {
roleMenu.then(res => {
let checkedKeys = res.checkedKeys
let checkedKeys = res.checkedKeys;
checkedKeys.forEach((v) => {
this.$nextTick(()=>{
this.$refs.menu.setChecked(v, true ,false);
})
})
this.$nextTick(() => {
this.$refs.menu.setChecked(v, true, false);
});
});
});
});
this.title = "修改角色";
......@@ -541,7 +435,7 @@ export default {
},
/** 选择角色权限范围触发 */
dataScopeSelectChange(value) {
if(value !== '2') {
if (value !== '2') {
this.$refs.dept.setCheckedKeys([]);
}
},
......@@ -561,12 +455,12 @@ export default {
});
},
/** 分配用户操作 */
handleAuthUser: function(row) {
handleAuthUser: function (row) {
const roleId = row.roleId;
this.$router.push("/system/role-auth/user/" + roleId);
},
/** 提交按钮 */
submitForm: function() {
submitForm: function () {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.roleId != undefined) {
......@@ -588,7 +482,7 @@ export default {
});
},
/** 提交按钮(数据权限) */
submitDataScope: function() {
submitDataScope: function () {
if (this.form.roleId != undefined) {
this.form.deptIds = this.getDeptAllCheckedKeys();
dataScope(this.form).then(response => {
......@@ -601,18 +495,25 @@ export default {
/** 删除按钮操作 */
handleDelete(row) {
const roleIds = row.roleId || this.ids;
this.$modal.confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?').then(function() {
return delRole(roleIds);
}).then(() => {
this.$modal.confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?').then(async () => {
try {
const result = await delRole(roleIds);
if (result.code == 200) {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
} else {
this.$message.error(result.msg);
}
} catch (error) {
}
}).catch(() => { });
},
/** 导出按钮操作 */
handleExport() {
this.download('system/role/export', {
...this.queryParams
}, `role_${new Date().getTime()}.xlsx`)
}, `role_${new Date().getTime()}.xlsx`);
}
}
};
......
......@@ -26,9 +26,11 @@
<el-row>
<el-table @row-click="clickRow" ref="table" :data="userList" @selection-change="handleSelectionChange" height="260px">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
<!-- <el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" /> -->
<el-table-column label="用户编号" align="center" prop="userId" />
<el-table-column label="用户名称" prop="nickName" align="center" :show-overflow-tooltip="true" />
<el-table-column label="组织" align="center" prop="dept.deptName" :show-overflow-tooltip="true" />
<!-- <el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" /> -->
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
......
'use strict'
const path = require('path')
'use strict';
const path = require('path');
function resolve(dir) {
return path.join(__dirname, dir)
return path.join(__dirname, dir);
}
const CompressionPlugin = require('compression-webpack-plugin')
const CompressionPlugin = require('compression-webpack-plugin');
const name = process.env.VUE_APP_TITLE || '数字化经营履约全生命链路管理系统' // 网页标题
const name = process.env.VUE_APP_TITLE || '数字化经营履约全生命链路管理系统'; // 网页标题
const port = process.env.port || process.env.npm_config_port || 80 // 端口
const port = process.env.port || process.env.npm_config_port || 80; // 端口
// vue.config.js 配置说明
//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
// 这里只列一部分,具体配置参考文档
module.exports = {
transpileDependencies: ['json-editor-vue'],
// 部署生产环境和开发环境下的URL。
// 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上
// 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
......@@ -34,10 +35,10 @@ module.exports = {
proxy: {
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: {
target: `http://47.104.91.229:9099/prod-api`,//测试
// target: `http://47.104.91.229:9099/prod-api`,//测试
// target: `https://szhapi.jiansheku.com`,//线上
// target: `http://122.9.160.122:9011`, //线上
// target: `http://192.168.0.165:9098`,//施
target: `http://192.168.60.46:9098`,//施
// target: `http://192.168.60.6:9098`,//谭
changeOrigin: true,
pathRewrite: {
......@@ -73,14 +74,14 @@ module.exports = {
],
},
chainWebpack(config) {
config.plugins.delete('preload') // TODO: need test
config.plugins.delete('prefetch') // TODO: need test
config.plugins.delete('preload'); // TODO: need test
config.plugins.delete('prefetch'); // TODO: need test
// set svg-sprite-loader
config.module
.rule('svg')
.exclude.add(resolve('src/assets/icons'))
.end()
.end();
config.module
.rule('icons')
.test(/\.svg$/)
......@@ -91,7 +92,15 @@ module.exports = {
.options({
symbolId: 'icon-[name]'
})
.end();
config.module
.rule("mjs")
.test(/\.mjs$/)
.include.add(/node_modules/)
.end()
.type("javascript/auto");
config
.when(process.env.NODE_ENV !== 'development',
......@@ -103,7 +112,7 @@ module.exports = {
// `runtime` must same as runtimeChunk name. default is `runtime`
inline: /runtime\..*\.js$/
}])
.end()
.end();
config
.optimization.splitChunks({
chunks: 'all',
......@@ -127,13 +136,13 @@ module.exports = {
reuseExistingChunk: true
}
}
})
});
config.optimization.runtimeChunk('single'),
{
from: path.resolve(__dirname, './public/robots.txt'), //防爬虫文件
to: './' //到根目录下
};
}
);
}
)
}
}
};
\ No newline at end of file
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