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>
......@@ -73,11 +73,8 @@ export default {
};
},
computed: {
visitedViews: {
get() {
return this.$store.state.tagsView.visitedViews;
},
set() { }
visitedViews() {
return this.$store.state.tagsView.visitedViews;
},
iconName() {
return function (val) {
......@@ -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() {
this.initTags();
this.addTags();
// this.getviews()
created() {
this.$nextTick(() => {
this.initTags();
this.addTags();
});
},
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: '/' })
})
})
store.dispatch('LogOut').then(() => {
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);
}
}
};
This diff is collapsed.
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>
......@@ -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: {
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);
}
},
// 渲染方法
render(createElement) {
}
}
</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">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<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>
......@@ -143,10 +102,10 @@ export default {
getList() {
this.loading = true;
allocatedUserList(this.queryParams).then(response => {
this.userList = response.rows;
this.total = response.total;
this.loading = false;
}
this.userList = response.rows;
this.total = response.total;
this.loading = false;
}
);
},
// 返回按钮
......@@ -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.getList();
this.$modal.msgSuccess("取消授权成功");
}).catch(() => {});
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("取消授权成功");
} 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.getList();
this.$modal.msgSuccess("取消授权成功");
}).catch(() => {});
this.$modal.confirm('是否取消选中用户授权数据项?').then(async () => {
try {
const result = await authUserCancelAll({ roleId: roleId, userIds: userIds });
if (result.code == 200) {
this.getList();
this.$modal.msgSuccess("取消授权成功");
} else {
this.$message.error(`${result.msg}账号下仅有一个角色,取消授权失败`);
}
} catch (error) {
}
}).catch(() => { });
}
}
};
......
......@@ -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',
......@@ -100,10 +109,10 @@ module.exports = {
.plugin('ScriptExtHtmlWebpackPlugin')
.after('html')
.use('script-ext-html-webpack-plugin', [{
// `runtime` must same as runtimeChunk name. default is `runtime`
// `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: './' //到根目录下
}
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