af23ea49 by renchao@pashanhoo.com

feat:集成cas

1 parent 731e47d8
......@@ -10,4 +10,4 @@ NODE_ENV=development
VUE_APP_BASE_API = '/api'
# 开发环境
VUE_APP_API_BASE_URL = 'http://192.168.2.38:8026'
VUE_APP_API_BASE_URL = 'http://192.168.2.38:8008'
......
{
"TITLE": "汉中市数据上报系统",
"CODE": "BDCSBPT",
"CODE": "BDCSJSB",
"AREARMAP": "610702",
"XZQ": "汉中市",
"SERVERAPI": "/bdcsjsb",
"calcHeight": 160,
"echartTextColor": "#4A4A4A",
"MANAGEMENTAPI": "http://192.168.2.38:8090/management",
"IPCONFIG": "http://192.168.2.38:8027"
"ip": "http://192.168.2.38:8027"
}
\ No newline at end of file
......
{
"TITLE": "玉树州数据上报系统",
"CODE": "BDCSBPT",
"CODE": "BDCSJSB",
"AREARMAP": "632701",
"XZQ": "玉树州",
"SERVERAPI": "/bdcsjsb",
"calcHeight": 160,
"echartTextColor": "#4A4A4A",
"MANAGEMENTAPI": "http://192.168.2.38:8090/management",
"IPCONFIG": "http://192.168.2.38:8027"
"ip": "http://192.168.2.38:8027"
}
\ No newline at end of file
......
{
"TITLE": "汉中市数据上报系统",
"CODE": "BDCSBPT",
"CODE": "BDCSJSB",
"AREARMAP": "610702",
"XZQ": "汉中市",
"SERVERAPI": "/bdcsjsb",
"SERVERAPI": "/bdcsjsb1234",
"calcHeight": 160,
"echartTextColor": "#4A4A4A",
"MANAGEMENTAPI": "http://192.168.2.38:8090/management",
"IPCONFIG": "http://192.168.2.38:8026"
"ip": "http://192.168.2.38"
}
\ No newline at end of file
......
<!--
* @Description: 引入配置文件
* @Autor: renchao
* @LastEditTime: 2023-05-08 15:02:53
* @LastEditTime: 2023-06-02 10:57:01
-->
<!DOCTYPE html>
<html>
......@@ -18,6 +18,20 @@
</title>
</head>
<script>
window._config = {
// 是否微服务模式,业务系统根据需要读取
cloudEnable: false,
baseUrl: location.origin || location.protocol + '//' + location.host,
// 是否启用单点登录
casEnable: true,
// cas 基地址
casBaseURL: 'http://192.168.2.38/cas',
services: {
// 配置到 contextPath 前一级
management: 'http://192.168.2.38',
business: 'http://localhost:7001'
}
}
fetch('<%= BASE_URL %>config.json')
.then(response => response.json())
.then(config => {
......@@ -29,10 +43,4 @@
<div id="app"></div>
</body>
</html>
<script>
window.baseUrl = location.origin || location.protocol + '//' + location.host
window.timeout = 5000
window.authorization = "bearer AT-4-MxSrO29Coe7VTazx8uuixtqqgO-hvCB6"
</script>
\ No newline at end of file
</html>
\ No newline at end of file
......
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1686204771033" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1398" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M889.898667 98.730667c16.170667 0 29.269333 13.098667 29.269333 29.269333v719.232a114.602667 114.602667 0 0 1-114.602667 114.602667H128a71.936 71.936 0 0 1-71.936-71.936V213.333333A114.602667 114.602667 0 0 1 170.666667 98.730667z m-29.269334 58.496H170.666667c-30.976 0-56.064 25.173333-56.064 56.106666v676.565334c0 7.424 5.973333 13.397333 13.397333 13.397333h676.565333c30.976 0 56.064-25.088 56.064-56.064V157.226667zM597.333333 457.173333a146.304 146.304 0 0 1 134.826667 203.093334l68.693333 68.778666a29.269333 29.269333 0 0 1-37.717333 44.458667l-3.626667-3.114667-61.184-61.141333A146.304 146.304 0 1 1 597.333333 457.130667z m-219.434666 244.992a29.269333 29.269333 0 0 1 4.309333 58.197334l-4.266667 0.341333h-146.346666a29.269333 29.269333 0 0 1-4.266667-58.197333l4.266667-0.341334h146.346666zM597.333333 515.669333a87.765333 87.765333 0 1 0 0 175.530667 87.765333 87.765333 0 0 0 0-175.530667z m-219.434666 3.626667a29.269333 29.269333 0 0 1 4.309333 58.197333l-4.266667 0.341334h-146.346666a29.269333 29.269333 0 0 1-4.266667-58.197334l4.266667-0.341333h146.346666zM743.68 299.946667a29.269333 29.269333 0 0 1 4.266667 58.197333l-4.266667 0.298667h-512a29.269333 29.269333 0 0 1-4.352-58.197334l4.352-0.298666h512z" p-id="1399"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1686204663773" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1252" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M779.008 56.064c14.72 0 26.88 10.837333 28.970667 24.96l0.298666 4.309333v692.181334c0 14.72-10.837333 26.88-24.917333 28.970666l-4.352 0.298667H229.632a29.269333 29.269333 0 0 1-4.352-58.197333l4.352-0.298667 520.106667-0.042667V114.56H170.666667c-29.013333 0-52.906667 22.101333-55.808 50.346667L114.602667 170.666667l-0.042667 689.962666H810.666667c29.013333 0 52.906667-22.058667 55.808-50.346666l0.256-5.717334V262.528a29.269333 29.269333 0 0 1 58.197333-4.309333l0.341333 4.309333v542.037333a114.602667 114.602667 0 0 1-107.349333 114.346667l-7.253333 0.256H85.333333a29.269333 29.269333 0 0 1-28.928-24.96l-0.341333-4.266667V170.666667A114.602667 114.602667 0 0 1 163.413333 56.32L170.666667 56.064h608.341333z m-236.544 219.434667c10.112 0 19.456 5.205333 24.832 13.738666l91.434667 146.304a29.269333 29.269333 0 0 1 0 31.018667l-91.434667 146.261333a29.269333 29.269333 0 0 1-24.832 13.781334H359.68a29.269333 29.269333 0 0 1-24.832-13.781334l-91.434667-146.261333a29.269333 29.269333 0 0 1 0-31.018667l91.434667-146.304a29.269333 29.269333 0 0 1 24.832-13.738666z m-16.213333 58.496H375.893333l-73.173333 117.034666 73.173333 117.034667h150.357334l73.173333-117.034667-73.173333-117.034666z" p-id="1253"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1686204514003" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1106" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M822.869333 519.296c10.624 0 20.394667 5.76 25.6 15.061333l91.392 164.565334a29.269333 29.269333 0 0 1 0 28.416l-91.434666 164.565333a29.269333 29.269333 0 0 1-25.6 15.061333H640a29.269333 29.269333 0 0 1-25.6-15.061333l-91.392-164.565333a29.269333 29.269333 0 0 1 0-28.416l91.434667-164.565334a29.269333 29.269333 0 0 1 25.557333-15.061333z m36.565334-420.565333c14.677333 0 26.88 10.837333 28.928 24.96L888.746667 128v267.093333a29.269333 29.269333 0 0 1-58.197334 4.309334l-0.341333-4.309334V157.226667H213.333333c-29.013333 0-52.906667 22.101333-55.808 50.346666L157.269333 213.333333l-0.042666 397.397334h272.298666a29.44 29.44 0 0 1 4.693334 0.384 29.269333 29.269333 0 0 1 33.578666 24.576l0.298667 4.309333v208.426667h62.208a29.269333 29.269333 0 0 1 4.266667 58.24l-4.266667 0.298666h-256a29.269333 29.269333 0 0 1-4.352-58.197333l4.352-0.298667h135.253333v-179.2H128a29.269333 29.269333 0 0 1-28.928-24.96L98.730667 640V213.333333A114.602667 114.602667 0 0 1 206.08 98.986667L213.333333 98.730667h646.101334z m-53.76 479.061333h-148.437334l-75.178666 135.296 75.178666 135.338667h148.48l75.136-135.338667-75.178666-135.253333z" p-id="1107"></path></svg>
\ No newline at end of file
<!--
* @Description :面包屑
* @Autor : miaofang
* @LastEditTime : 2023-05-17 14:35:47
* @LastEditTime: 2023-06-08 14:16:53
-->
<template>
<el-breadcrumb class="app-breadcrumb" separator="/">
......@@ -9,9 +9,8 @@
<el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
<span class="no-redirect">当前位置></span>
<!-- <svg-icon v-if="item.meta.icon" :icon-class="item.meta.icon" class="breadcrumbIcon" /> -->
<span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{
item.meta.title
}}</span>
<span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">
{{ item.meta.title }}</span>
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
</el-breadcrumb-item>
</transition-group>
......@@ -19,80 +18,80 @@
</template>
<script>
import pathToRegexp from 'path-to-regexp'
import pathToRegexp from 'path-to-regexp'
export default {
data () {
return {
levelList: null
}
},
watch: {
$route (route) {
// if you go to the redirect page, do not update the breadcrumbs
if (route.path.startsWith('/redirect/')) {
return
}
this.getBreadcrumb()
}
},
created () {
this.getBreadcrumb()
},
methods: {
getBreadcrumb () {
// only show routes with meta.title
let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
const first = matched[0]
if (!this.isDashboard(first)) {
matched = matched
export default {
data () {
return {
levelList: null
}
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
},
isDashboard (route) {
const name = route && route.name
if (!name) {
return false
watch: {
$route (route) {
// if you go to the redirect page, do not update the breadcrumbs
if (route.path.startsWith('/redirect/')) {
return
}
this.getBreadcrumb()
}
return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
},
pathCompile (path) {
const { params } = this.$route
var toPath = pathToRegexp.compile(path)
return toPath(params)
created () {
this.getBreadcrumb()
},
handleLink (item) {
const { redirect, path } = item
if (redirect) {
this.$router.push(redirect)
return
methods: {
getBreadcrumb () {
// only show routes with meta.title
let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
const first = matched[0]
if (!this.isDashboard(first)) {
matched = matched
}
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
},
isDashboard (route) {
const name = route && route.name
if (!name) {
return false
}
return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
},
pathCompile (path) {
const { params } = this.$route
var toPath = pathToRegexp.compile(path)
return toPath(params)
},
handleLink (item) {
const { redirect, path } = item
if (redirect) {
this.$router.push(redirect)
return
}
this.$router.push(this.pathCompile(path))
}
this.$router.push(this.pathCompile(path))
}
}
}
</script>
<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 50px;
margin-left: 8px;
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 50px;
margin-left: 8px;
.no-redirect {
color: #ffffff;
cursor: text;
font-size: 16px;
}
.no-redirect {
color: #ffffff;
cursor: text;
font-size: 16px;
}
.breadcrumbIcon {
color: #ffffff;
margin-right: 5px;
width: 16px;
height: 16px;
.breadcrumbIcon {
color: #ffffff;
margin-right: 5px;
width: 16px;
height: 16px;
}
}
}
</style>
......
......@@ -17,9 +17,10 @@
</div>
</template>
<script>
import axios from 'axios'
import Cookies from 'js-cookie'
import { mapGetters } from 'vuex'
import Breadcrumb from './Breadcrumb'
import { logout } from "@/api/login.js";
export default {
components: {
Breadcrumb
......@@ -39,18 +40,24 @@
this.$store.dispatch('app/updateTheme', val)
},
onCancel () {
logout()
.then((res) => {
sessionStorage.removeItem("token");
this.$store.dispatch("user/resetState");
this.$store.dispatch("permission/resetRoutes");
this.$router.replace({
path: "/login"
axios.post(this.BASE_API.ip + "/management/logout").then(() => {
if (process.env.NODE_ENV === 'development') {
localStorage.removeItem('token')
} else {
Cookies.remove('token')
}
if (window._config.casEnable) {
window.location.href = window._config.casBaseURL + '/logout?service=' + encodeURIComponent(window.location.href);
} else {
this.$router.push({
path: '/login',
replace: true,
query: {
redirect: router.currentRoute.value.fullPath
}
})
})
.catch((error) => {
// console.dir(error);
})
}
})
}
}
}
......
<!--
* @Description:
* @Autor: renchao
* @LastEditTime: 2023-03-30 10:39:40
* @LastEditTime: 2023-06-08 14:01:11
-->
<template>
<div v-if="!item.hidden">
......@@ -26,70 +26,70 @@
</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',
components: { Item, AppLink },
mixins: [FixiOSBug],
props: {
// route object
item: {
type: Object,
required: true
export default {
name: 'SidebarItem',
components: { Item, AppLink },
mixins: [FixiOSBug],
props: {
// route object
item: {
type: Object,
required: true
},
isNest: {
type: Boolean,
default: false
},
basePath: {
type: String,
default: ''
}
},
isNest: {
type: Boolean,
default: false
data () {
// To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
// TODO: refactor with render function
this.onlyOneChild = null
return {}
},
basePath: {
type: String,
default: ''
}
},
data () {
// To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
// TODO: refactor with render function
this.onlyOneChild = null
return {}
},
methods: {
hasOneShowingChild (children = [], parent) {
const showingChildren = children.filter(item => {
if (item.hidden) {
return false
} else {
// Temp set(will be used if only has one showing child)
this.onlyOneChild = item
methods: {
hasOneShowingChild (children = [], parent) {
const showingChildren = children.filter(item => {
if (item.hidden) {
return false
} else {
// Temp set(will be used if only has one showing child)
this.onlyOneChild = item
return true
}
})
// When there is only one child router, the child router is displayed by default
if (showingChildren.length >= 1 && (showingChildren[0].path == 'qxjr')) {
return true
}
})
// When there is only one child router, the child router is displayed by default
if (showingChildren.length >= 1 && (showingChildren[0].path == 'ywjr' || showingChildren[0].path == "sbbwcx" || showingChildren[0].path == "dbrzcx")) {
return true
}
// Show parent if there are no child router to display
if (showingChildren.length === 0) {
this.onlyOneChild = { ...parent, path: '', noShowingChildren: 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
}
return false
},
resolvePath (routePath) {
if (isExternal(routePath)) {
return routePath
}
if (isExternal(this.basePath)) {
return this.basePath
return false
},
resolvePath (routePath) {
if (isExternal(routePath)) {
return routePath
}
if (isExternal(this.basePath)) {
return this.basePath
}
return path.resolve(this.basePath, routePath)
}
return path.resolve(this.basePath, routePath)
}
}
}
</script>
......
<!--
* @Description:
* @Autor: renchao
* @LastEditTime: 2023-05-11 16:38:29
* @LastEditTime: 2023-06-08 11:05:54
-->
<template>
<div>
......@@ -9,7 +9,7 @@
<el-menu router :default-active="activeMenu" :background-color="variables.menuBg" :text-color="variables.menuText"
:unique-opened="true" :active-text-color="variables.menuActiveText" :collapse-transition="false" mode="vertical">
<!-- 权限菜单 -->
<sidebar-item v-for="route in permission_routes.slice(4)" :key="route.path" :item="route"
<sidebar-item v-for="route in permission_routes" :key="route.path" :item="route"
:base-path="route.path" />
<!-- 菜单全部展示 -->
<!-- <sidebar-item v-for="route in asyncRoutes" :key="route.path" :item="route" :base-path="route.path" /> -->
......
......@@ -60,8 +60,6 @@ axios.get("./config.json")
.then((res) => {
Vue.prototype.BASE_API = res.data
localStorage.setItem('ApiUrl', JSON.stringify(res.data));
process.env.TITLE = res.data.TITLE
process.env.IPCONFIG = res.data.IPCONFIG
require('./permission')
new Vue({
el: '#app',
......
/*
* @Description:
* @Autor: renchao
* @LastEditTime: 2023-05-12 10:46:51
* @LastEditTime: 2023-06-08 10:48:43
*/
import Vue from 'vue'
import router from "./router";
import axios from 'axios'
import store from "./store";
import router from "./router";
import { getMenuInfo } from "@/api/user";
import { getUrlParam } from '@/utils/operation';
import NProgress from "nprogress"; // progress bar
import "nprogress/nprogress.css"; // progress bar style
import getPageTitle from "@/utils/get-page-title";
......@@ -20,15 +22,45 @@ router.beforeEach(async (to, from, next) => {
let hasAddDict = store.state.dict.addDict;
let hasUser = store.state.user.hasUser;
let hasAddRoute = store.state.permission.addRoutes;
if (to.path == "/login") {
localStorage.removeItem("token");
next();
} else {
let code = Vue.prototype.BASE_API.CODE
//判断token是否存在
const hasToken = localStorage.getItem("token");
if (hasToken) {
//请求用户信息
// cas操作
const token = localStorage.getItem("token") || Cookies.get('token');
if (to.path === '/login') {
if (token) {
next('/')
} else {
next()
}
return
}
if (window._config.casEnable === true) {
let locationUrl = window.location.protocol + '//' + window.location.host + window.location.pathname;
if (!token) {
let ticket = getUrlParam('ticket');
if (ticket) {
axios.get(Vue.prototype.BASE_API.ip + "/management/cas/validate", {
params: {
'ticket': ticket,
'service': locationUrl
}
}).then(async (res) => {
if (process.env.NODE_ENV === 'development') {
localStorage.setItem('token', res.data.content.accessToken)
} else {
Cookies.set('token', res.data.content.accessToken)
}
window.location.href = localStorage.getItem('location')
}).catch(e => {
console.log(e)
})
} else {
localStorage.setItem("location", window.location.href)
window.location.href = window._config.casBaseURL + '/login?service=' + encodeURIComponent(locationUrl);
}
} else {
permission()
}
async function permission () {
if (!hasUser) {
store.dispatch("user/getUserInfo");
if (!hasAddDict) {
......@@ -39,25 +71,40 @@ router.beforeEach(async (to, from, next) => {
next();
} else {
//请求菜单
const { result: getMenuData } = (await getMenuInfo(code)) || [];
const { result: getMenuData } = (await getMenuInfo(Vue.prototype.BASE_API.CODE)) || [];
const accessRoutes = await store.dispatch(
"permission/generateRoutes",
getMenuData
);
let path = JSON.parse(getMenuData[0].metadata)?.path + JSON.parse(getMenuData[0].children[0].metadata)?.path
router.addRoutes([
...accessRoutes,
{ path: "*", redirect: "/404", hidden: true },
]);
const routeTo = Cookies.get("routerTo");
if (routeTo && routeTo !== "/" && routeTo !== "/login") {
if (routeTo && routeTo !== "/") {
next({ ...to, replace: true });
} else {
next()
next(path)
}
}
} else {
next('/login')
}
} else {
if (!token) {
const redirectData = {
path: '/login',
replace: true,
}
if (to.path) {
redirectData.query = {
...redirectData.query,
redirect: to.path,
};
}
next(redirectData)
return
}
next()
}
NProgress.done()
});
......
/*
* @Description :路由配置
* @Autor : miaofang
* @LastEditTime : 2023-05-17 14:55:00
* @LastEditTime: 2023-06-08 14:24:36
*/
import Vue from 'vue'
import Router from 'vue-router'
......@@ -22,32 +22,6 @@ export const constantRoutes = [
meta: { title: '404' }
}
]
},
//登录
{
path: "/login",
name: "login",
component: () => import("@/views/login/index.vue"),
},
{
path: '/',
redirect: to => {
return { path: '/login' }
},
},
// 监管首页
{
path: '/home',
component: Layout,
meta: { title: '首页' },
children: [
{
path: '',
component: () => import('@/views/home/index'),
name: 'home',
meta: { title: '工作台', icon: 'workbench', affix: true }
}
]
}
]
/**
......@@ -57,15 +31,11 @@ export const constantRoutes = [
export const asyncRoutes = [
// 区县接入
{
path: '/jsbwcx',
path: '/',
redirect: '/qxjr',
meta: { title: '区县接入', icon: 'qxjr' },
component: Layout,
children: [
// {
// path: 'xxcx',
// component: () => import('@/views/gbxxcx/index'),
// name: 'xxcx',
// meta: { title: '信息查询', icon: 'xxcx' }
// },
{
path: 'qxjr',
component: () => import('@/views/jsbwcx/index'),
......@@ -77,6 +47,7 @@ export const asyncRoutes = [
// 省厅汇交
{
path: '/sthj',
meta: { title: '省厅汇交', icon: 'sthj' },
component: Layout,
children: [
{
......@@ -102,33 +73,33 @@ export const asyncRoutes = [
{
path: 'ywltj',
component: () => import('@/views/jktj/ywltj/index'),
name: 'jktj',
name: 'ywltj',
meta: { title: '业务量统计', icon: 'zhcx' }
},
{
path: 'bsxljk',
component: () => import('@/views/jktj/bsxljk/index'),
name: 'jktj',
name: 'bsxljk',
meta: { title: '办事效率监控', icon: 'zhcx' }
},
{
path: 'dataReceiveQuality',
component: () => import('@/views/jktj/dataReceiveQuality/index'),
name: 'dataReceiveQuality',
meta: { title: '接入质量评价表', icon: 'dataReceiveQuality' }
},
{
path: 'nullTermRatio',
component: () => import('@/views/jktj/nullTermRatio/index'),
name: 'nullTermRatio',
meta: { title: '相关字段空置率统计', icon: 'nullTermRatio' }
},
{
path: 'registerBookQuality',
component: () => import('@/views/jktj/registerBookQuality/index'),
name: 'registerBookQuality',
meta: { title: '登簿质量评价表', icon: 'registerBookQuality' }
}
// {
// path: 'dataReceiveQuality',
// component: () => import('@/views/jktj/dataReceiveQuality/index'),
// name: 'dataReceiveQuality',
// meta: { title: '接入质量评价表', icon: 'dataReceiveQuality' }
// },
// {
// path: 'nullTermRatio',
// component: () => import('@/views/jktj/nullTermRatio/index'),
// name: 'nullTermRatio',
// meta: { title: '相关字段空置率统计', icon: 'nullTermRatio' }
// },
// {
// path: 'registerBookQuality',
// component: () => import('@/views/jktj/registerBookQuality/index'),
// name: 'registerBookQuality',
// meta: { title: '登簿质量评价表', icon: 'registerBookQuality' }
// }
]
},
// 接入业务信息-不动产数据
......@@ -258,24 +229,6 @@ export const asyncRoutes = [
component: () => import('@/views/system/timedTask/index'),
name: 'timedTask',
meta: { title: '定时任务' }
},
{
path: 'menus',
component: () => import('@/views/system/menus/index'),
name: 'menus',
meta: { title: '菜单管理' }
},
{
path: 'users',
component: () => import('@/views/system/users/index'),
name: 'users',
meta: { title: '人员管理' }
},
{
path: 'roles',
component: () => import('@/views/system/roles/index'),
name: 'roles',
meta: { title: '角色管理' }
}
]
}
......
......@@ -141,3 +141,26 @@ export function getFirstDayOfSeason (d) {
date.setDate(1);
return timeFormat(date);
}
export function getUrlParam (paraName) {
let url = document.location.toString();
let arrObj = url.split('?');
if (arrObj.length > 1) {
let arrPara = arrObj[1].split('&');
let arr;
for (let i = 0; i < arrPara.length; i++) {
arr = arrPara[i].split('=');
if (arr != null && arr[0] === paraName) {
const index = arr[1].indexOf("#");
return arr[1].substring(0, index);
}
}
return '';
} else {
return '';
}
}
......
/*
* @Description: 此文件主要创建 axios 实例,然后添加请求拦截器和响应拦截器
* @Autor: renchao
* @LastEditTime: 2023-05-25 14:52:20
* @LastEditTime: 2023-06-08 09:02:53
*/
import Vue from 'vue'
import axios from "axios";
import { Message } from "element-ui";
import { endLoadingSubCount } from "./requestLoading";
import router from "../router";
import axios from 'axios'
import Router from '@/router'
import Cookies from 'js-cookie'
import { Message } from 'element-ui'
import { endLoadingSubCount } from './requestLoading'
// create an axios instance
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
withCredentials: true, //是否允许跨域
headers: {
"Content-Type": "application/json; charset=utf-8",
},
timeout: 15000,
});
baseURL:
process.env.NODE_ENV == "development"
? process.env.VUE_APP_BASE_API
: window._config.baseUrl + "/",
withCredentials: true, //是否允许跨域
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
timeout: 15000
})
// request interceptor
service.interceptors.request.use(
(config) => {
//调用登录接口时无token,也不需要传token,其他接口都传入token
config.headers.Authorization = localStorage.getItem("token") || "";
config.headers.Accept = "application/json";
return config;
},
(error) => {
Message.error("请求超时!");
return Promise.reject(error);
}
);
window.tokenValid = true
config => {
if (process.env.NODE_ENV === 'development') {
const token = localStorage.getItem('token')
// 添加请求头
if (token) {
config.headers['Authorization'] = 'Bearer ' + token
} else {
config.headers.delete('Authorization')
}
} else {
const token = Cookies.get('token')
// 添加请求头
if (token) {
config.headers['Authorization'] = 'Bearer ' + token
} else {
config.headers.delete('Authorization')
}
}
return config
},
error => {
// do something with request error
console.log(error); // for debug
return Promise.reject(error);
}
)
window.__isNeedLogin = true
// response interceptor
service.interceptors.response.use(
(response) => {
/**
* 对响应数据判断:
* 如果成功返回数据,就通过return把数据返出去
* 如果请求不成功,就在拦截器这里统一处理(组件的代码就不用关注错误的情况了)
*/
if (response.status == 200) {
return response.data;
} else {
// 对响应错误做点什么
Message({
message: "请求失败",
type: "error",
duration: 5 * 1000,
});
response => {
/**
* 对响应数据判断:
* 如果成功返回数据,就通过return把数据返出去
* 如果请求不成功,就在拦截器这里统一处理(组件的代码就不用关注错误的情况了)
*/
if (response.status == 200) {
return response.data;
} else {
handleErrorData(response.data);
}
return response;
},
error => {
endLoadingSubCount()
if (error.response.status === 401) {
//todo: 需要解决 一个页面多个请求,刷新后此处会触发多次
if (window.__isNeedLogin) {
window.__isNeedLogin = false
Message.error('token失效,请重新登录');
let locationUrl = window.location.protocol + '//' + window.location.host + window.location.pathname;
if (process.env.NODE_ENV === 'development') {
localStorage.removeItem('token')
} else {
Cookies.remove('token')
}
if (window._config.casEnable) {
window.location.href = window._config.casBaseURL + '/logout?service=' + encodeURIComponent(locationUrl);
} else {
Router.replace({
path: '/login',
query: {
redirect: Router.currentRoute.value.fullPath
}
})
return false
}
}
} else {
// 对响应错误做点什么
Message({
message: '服务器异常,请联系管理员',
type: 'error',
duration: 5 * 1000,
customClass: 'messageIndex'
})
}
return Promise.reject(error);
}
return response;
},
(error) => {
handleErrorData(error.response.status);
endLoadingSubCount();
return Promise.reject(error);
}
);
)
//对错误信息的处理函数
function handleErrorData (status) {
switch (status) {
case 401:
// 多个请求不重复提示错误信息
if (window.tokenValid) {
window.tokenValid = false;
Message.error("由于长时间未操作,请重新登录!");
localStorage.removeItem("token");
router.replace({
path: "/login",
query: {
redirect: router.history.current.fullPath,
}
})
}
break;
case 404:
Message.error("很抱歉,资源未找到!");
break;
case 500:
Message.error("服务器错误!");
break;
default:
Message.error("服务正在联调中,请稍后!");
break;
}
function handleErrorData (errMes) {
if (errMes.message) {
Message.error(errMes.message);
} else {
switch (errMes.code) {
case 401:
Message.error("未授权,请重新登录!");
break;
case 403:
Message.error("拒绝访问");
break;
case 404:
Message.error("很抱歉,资源未找到!");
break;
case 500:
Message.error("服务器错误!");
break;
default:
Message.error("服务正在联调中,请稍后!");
break;
}
}
}
export default service;
export default service
......
<!--
* @Description :接收报文查询
* @Autor : miaofang
* @LastEditTime : 2023-05-17 15:36:17
* @LastEditTime: 2023-06-08 14:15:38
-->
<template>
<!-- 接收报文查询 -->
......@@ -9,9 +9,6 @@
<!-- 头部搜索 -->
<div class="from-clues-header">
<el-form ref="ruleForm" :model="form" label-width="100px">
<el-form-item v-if="BASE_API.THEME == 'jg'">
<Breadcrumb />
</el-form-item>
<el-row class="mb-5">
<el-col :span="6">
<el-form-item label="行政区" prop="qxdm">
......
<!--
* @Description :登录
* @Autor : miaofang
* @LastEditTime : 2023-05-17 15:36:30
-->
<template>
<div class="bg">
<div class="title">
<img src="../../image/bdclogo.png" alt="">
<h2>{{ BASE_API.TITLE }}</h2>
</div>
<div class="login-inner-bg login">
<div class="user_style">
<h3>用户登录</h3>
<el-form :model="user" :rules="rules" ref="user" id="loginform" class="demo-ruleForm">
<el-form-item prop="account">
<el-input class="username" v-model="user.account" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input type="password" class="password" @keyup.enter.native="login('user')" v-model="user.password"
placeholder="请输入密码" show-password></el-input>
</el-form-item>
<!-- <el-form-item prop="yz">
<div class="flex-container">
<div class="flex-input">
<el-input class="yz" @keyup.native="login('user')" v-model="user.yz" placeholder="请输入验证码"></el-input>
</div>
<div class="flex-line"></div>
<div class="flex-img"><canvas id="s-canvas" ref="s-canvas"></canvas></div>
<div class="flex-renovate">
<font id="renovate" @click="verification">换一批</font>
</div>
</div>
</el-form-item> -->
<el-form-item class="login-btn">
<el-button type="primary" style="width: 100%" @click="login('user')">登录</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</template>
<script>
import { getMenuInfo } from "@/api/user";
import { loginIn } from "@/api/login.js";
export default {
name: "sbLogin",
data () {
return {
user: {
account: "",
password: "",
yz: "",
checkStatus: false,
},
productName: "",
rules: {
account: [{ required: true, message: "请填写帐号", trigger: "blur" }],
password: [{ required: true, message: "请填写密码", trigger: "blur" }],
},
};
},
methods: {
verification () {
let str = '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ', code = '', i = 0;
for (; i++ < 4;) code += str[Math.floor(Math.random() * (str.length - 0) + 0)];
setTimeout(() => {
let canvas = document.getElementById("s-canvas"), ctx = canvas.getContext("2d");
canvas.width = 80;
canvas.height = 28;
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, 80, 28);
for (i = 0; i < code.length; i++) { this.drawText(ctx, code[i], i); }
}, 0);
},
drawText (ctx, txt, i) {
ctx.fillStyle = this.randomColor(50, 160);
ctx.font = "18px SimHei";
let x = (i + 1) * (80 / (4 + 1)), y = this.randomNum(18, 28 - 5);
ctx.translate(x, y);
ctx.fillText(txt, 0, 0);
ctx.rotate((-0 * Math.PI) / 180);
ctx.translate(-x, -y);
},
randomColor (min, max) {
let r = this.randomNum(min, max);
let g = this.randomNum(min, max);
let b = this.randomNum(min, max);
return "rgb(" + r + "," + g + "," + b + ")";
},
randomNum (min, max) {
return Math.floor(Math.random() * (max - min) + min);
},
//记住用户名
checkUserName: function (flag) {
this.user.checkStatus = flag;
if (this.user.checkStatus) {
localStorage.setItem("accountId", this.user.account);
let name = localStorage.getItem("accountId");
if (name === "") {
return;
} else {
this.user.account = name;
}
} else {
this.user.account = localStorage.getItem("accountId");
}
},
login (user) {
var self = this
this.$refs[user].validate(async (valid) => {
if (valid) {
let res = await loginIn(self.user.account, self.user.password)
if (res.status == 1) {
let code = this.BASE_API.CODE;
localStorage.setItem("token", `Bearer ${res.content}`);
const { result: getMenuData } = (await getMenuInfo(code)) || [];
let path1 = JSON.parse(getMenuData[0].metadata)?.path + '/' + JSON.parse(getMenuData[0].children[0].metadata)?.path
console.log(getMenuData, path1, 'path1path1path1path1path1');
//登录成功后需判断有无重定向,没有重定向则跳转首页
const accessRoutes = await this.$store.dispatch(
"permission/generateRoutes",
getMenuData
);
this.$router.addRoutes([
...accessRoutes,
{ path: "*", redirect: "/404", hidden: true },
]);
this.$router.replace(this.$route.query.redirect || path1);
} else {
this.$message.error(res.message);
}
}
})
}
}
}
</script>
<style scoped lang="scss">
.username,
.password,
.yz {
position: relative;
&:before {
content: "";
display: block;
width: 16px;
height: 16px;
position: absolute;
left: 10px;
top: 7px;
background-size: 100% 100%;
}
/deep/ .el-input__inner {
color: #000 !important;
text-indent: 24px;
}
}
.flex-container {
position: relative;
display: -webkit-flex;
display: flex;
}
.flex-input {
width: 100%;
}
.flex-line {
position: absolute;
width: 1px;
height: 64%;
margin: 5px;
right: 36%;
background-color: #cccccc;
}
.flex-img {
position: absolute;
margin: 2px;
right: 16%;
}
.flex-renovate {
position: absolute;
margin: 1px;
right: 3%;
}
#renovate {
color: #3f8fea;
font-size: 16px;
font-weight: 700;
cursor: pointer;
}
.username::before {
background-image: url(../../image/userlogo.png);
}
.password::before {
background-image: url(../../image/passlogo.png);
}
.yz::before {
background-image: url(../../image/yzlogo.png);
}
.bg {
width: 100%;
height: 100%;
min-width: 1440px;
min-height: 560px;
background: url(../../image/loginBoxsb.png) no-repeat;
background-size: 100% 100%;
overflow: hidden;
position: relative;
}
.title {
width: 24%;
height: 6%;
top: 20%;
right: 38%;
position: absolute;
img {
width: 60px;
height: 60px;
top: 0%;
left: 2%;
position: absolute;
}
h2 {
top: 25%;
left: 22%;
position: absolute;
width: 383px;
height: 42px;
font-size: 28px;
font-weight: 600;
color: #ffffff;
text-shadow: 0px 4px 4px #002c95;
}
}
.login-inner-bg {
background: white;
width: 24.6%;
min-width: 360px;
top: 30%;
right: 38%;
position: absolute;
background-size: 100% 100%;
box-sizing: border-box;
padding: 56px;
}
.login {
.user_style {
h3 {
font-weight: normal;
text-align: center;
margin: -10px auto 28px;
font-weight: 400;
width: 125px;
height: 29px;
font-size: 20px;
font-family: Source Han Sans CN;
font-weight: 400;
color: #333333;
}
}
.btn {
width: 100%;
height: 6vh;
background-color: #00c2de;
border-radius: 5px;
font-size: 1.4vw;
color: #000;
}
.btn:hover {
cursor: pointer;
background-color: #2d8cf0;
}
}
.login #loginform {
.el-form-item {
margin-bottom: 24px !important;
}
.login-btn {
margin-top: 30px !important;
}
.el-button {
font-size: 18px;
border-radius: 0;
background: #4162d8 !important;
color: #ffffff !important;
cursor: pointer !important;
}
.el-input__inner {
width: 100% !important;
}
.el-checkbox__label {
color: #fff;
}
}
.inputUser .ivu-input {
padding: 6px 24px !important;
border: 1px solid #9f9f9f !important;
}
</style>
......@@ -4,10 +4,6 @@
<!-- 头部搜索 -->
<div class="from-clues-header">
<el-form ref="ruleForm" :model="form" label-width="100px">
<!-- 判断进入监管还是上报系统 -->
<el-form-item v-if="BASE_API.THEME == 'jg'">
<Breadcrumb />
</el-form-item>
<el-row class="mb-5">
<el-col :span="6">
<el-form-item label="行政区" prop="qxdm">
......@@ -141,8 +137,8 @@
pageSize: 10,
current: 1
},
// 表格数据
tableData: {
// 表格数据
tableData: {
// 表头数据
columns: [
{
......
<template>
<div>
<i class="el-icon-s-management icon" :title="title" @click="openDialog" />
<el-dialog
class="configuration"
:key="key"
:title="title"
:inner-dialog="true"
:visible.sync="dialogVisible"
width="600px"
:close-on-click-modal="false"
append-to-body
@cancel="cancel">
<vue-json-editor
id="minejson"
v-model="resultInfo"
:mode="'code'"
lang="zh"
@json-change="onJsonChange"
@json-save="onJsonSave"
@has-error="onError" />
<el-tooltip
content="全屏缩放"
effect="dark"
placement="bottom"
fullscreen
class="fullScreen">
<i class="el-icon-full-screen" @click="enLarge" />
</el-tooltip>
<template slot="footer">
<div class="dialog-footer flex flex-pack-center">
<btn nativeType="cx" @click="onJsonSave">保存</btn>
<btn nativeType="cx" @click="cancel">关闭</btn>
</div>
</template>
</el-dialog>
</div>
</template>
<script>
import vueJsonEditor from 'vue-json-editor'
export default {
components: {
vueJsonEditor
},
props: {
title: {
type: String,
default: '配置参数'
},
resultInfos: {
type: String,
default: ''
}
},
data () {
return {
activeNames: [],
resultInfo: {},
tmpResultInfo: {},
dialogVisible: false,
hasJsonFlag: true,
key: 0,
isEnlarge: false
}
},
watch: {
resultInfos: {
handler: function (val) {
++this.key
this.resultInfo =
this.resultInfos === '' ? {} : JSON.parse(this.resultInfos)
this.tmpResultInfo = this.resultInfo
},
deep: true,
immediate: true
}
},
mounted () {
this.resultInfo =
this.resultInfos === '' ? {} : JSON.parse(this.resultInfos)
},
methods: {
onJsonChange (value) {
// 只有在格式正确的时候进入此事件
this.hasJsonFlag = true
},
onJsonSave () {
const value = this.resultInfo
if (this.hasJsonFlag === false) {
this.$message.error({ message: 'json格式验证失败', showClose: true })
// alert("json验证失败")
return false
} else {
this.dialogVisible = false
this.$emit('getJsonString', JSON.stringify(value))
return true
}
},
onError (value) {
this.hasJsonFlag = false
},
openDialog () {
this.dialogVisible = true
},
cancel () {
this.resultInfo = this.tmpResultInfo
this.dialogVisible = false
},
// 放大
enLarge () {
const fullarea = document.getElementById('minejson')
if (fullarea.requestFullscreen) {
fullarea.requestFullscreen()
} else if (fullarea.webkitRequestFullScreen) {
fullarea.webkitRequestFullScreen() // webkit内核(chrome、safari、Opera等)
} else if (fullarea.mozRequestFullScreen) {
fullarea.mozRequestFullScreen() // moz内核(firefox)
} else if (fullarea.msRequestFullscreen) {
fullarea.msRequestFullscreen() // IE11、edge
}
this.isEnlarge = true
}
}
}
</script>
<style scoped lang="scss">
/* jsoneditor右上角默认有一个链接,加css去掉了 */
.icon {
color: #349af3;
}
</style>
import filter from '@/utils/filter.js'
class data extends filter {
constructor() {
super()
}
columns () {
return [
{
prop: "name",
label: "菜单名称",
align: 'left',
width: 300
},
{
prop: "code",
label: "菜单代码"
},
{
prop: "uri",
width: 260,
label: "链接路径"
},
]
}
}
export default new data()
<template>
<!-- 菜单添加编辑弹框 -->
<dialogBox class="PersonnelDialog" :isMain="true" width="40%" :title="title" @closeDialog="close" @submitForm="submitForm"
v-model="myValue">
<div class="dialogCon">
<el-form ref="form" :model="form" :rules="rules">
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="菜单名称:" prop="name" label-width="124px">
<el-input v-model="form.name" placeholder="请输入菜单名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="图标:" label-width="54px">
<el-input v-model="form.icon" placeholder="请选择图标" :prefix-icon="form.icon" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="上级菜单:" label-width="124px">
<el-cascader :key="menuKey" v-model="form.parentId" :options="parentMenuList" :props="setProps"
placeholder="请选择上级菜单" clearable @change="handleChange" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="23">
<el-col :span="23">
<el-form-item label="代码:" prop="code" label-width="124px">
<el-input v-model="codeComputed" placeholder="请输入菜单代码" :disabled="type === 1" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="23">
<el-col :span="23">
<el-form-item label="链接路径:" label-width="124px">
<el-input v-model="form.uri" placeholder="请输入链接路径" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="24">
<el-form-item label="浏览器跳转模式:" label-width="124px">
<el-select v-model="form.jumpMode" placeholder="请选择浏览器跳转模式">
<el-option v-for="item in jumpModeList" :key="item.value" :label="item.name" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="24">
<el-form-item label="配置参数:" label-width="124px" class="form-item-mb0">
<!-- 配置参数 -->
<JsonEditor class="JsonEditors" :result-infos="form.metadata" @getJsonString="getJsonString" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- 图标列表 -->
<!-- <IconList ref="iconList" @iconName="getIconName" /> -->
</div>
</dialogBox>
</template>
<script>
import { getParentMenuListAction } from '@/api/authorityManage'
import JsonEditor from './JsonEditors/index.vue'
import { validateCode } from '@/utils/validate';
import { api, httpAction } from '@/api/manageApi'
export default {
name: 'MenuModal',
components: {
JsonEditor,
},
props: {
value: { type: Boolean, default: false },
productId: {
type: String,
default: ''
}
},
data () {
return {
myValue: this.value,
form: {
icon: '',
code: ''
},
rules: {
name: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
code: [
{ required: true, message: '必填', trigger: 'blur' },
{ validator: validateCode, trigger: 'blur' }
]
},
title: '',
type: '',
visible: false,
parentMenuList: [],
menuKey: 0,
jumpModeList: [
{ name: '在当前页面显示', value: 1 },
{ name: '跳转到新页面', value: 2 }
],
setProps: {
value: 'id',
label: 'name',
children: 'children',
expandTrigger: 'hover',
checkStrictly: true, // 可取消关联,选择任意一级选项
emitPath: false
},
dataUrl: api.menus
}
},
computed: {
codeComputed: {
get: function () {
return this.form.code
},
set: function (val) {
this.form.code = val.toUpperCase()
}
}
},
watch: {
value (val) {
this.myValue = val
}
},
methods: {
// 获取父级菜单
getParentMenuList (id) {
getParentMenuListAction(id).then((res) => {
if (res.status === 1) {
const list = this.$dealArrChildren(res.content)
if (id) {
this.parentMenuList = this.$dealArrDisabled(
this.$deepCopy(list),
id
)
this.menuKey++
} else {
this.parentMenuList = list
}
} else {
this.$message.error({ message: res.message, showClose: true })
}
})
},
// 配置参数
getJsonString (data) {
this.form.metadata = data
},
// 新增菜单
add () {
this.getParentMenuList(this.productId)
this.type = 0
this.form.jumpMode = 1
},
// 编辑菜单
edit (record) {
this.type = 1
// 若有id为编辑
if (record.id) {
this.$nextTick(() => {
this.form = Object.assign({}, record)
this.getParentMenuList(this.productId)
})
}
},
// 选择上级菜单
handleChange (value) {
this.form.parentId = value
},
// 保存
submitForm (submitType) {
this.$refs.form.validate((valid) => {
if (valid) {
let method = ''
let url = ''
const formData = this.form
formData.productId = this.productId
if (!formData.id) {
method = 'post'
url = this.dataUrl
} else {
method = 'put'
url = `${this.dataUrl}/${formData.id}`
}
httpAction(url, formData, method)
.then((res) => {
if (res.status === 1) {
this.$message.success({
message: res.message,
showClose: true
})
this.close()
this.$emit('ok')
} else {
this.$message.error({ message: res.message, showClose: true })
}
})
.catch((err) => {
console.log(err)
})
}
})
},
// 重置
resetForm () {
this.$refs.form.resetFields()
this.form = {
icon: '',
code: ''
}
},
// 关闭
close () {
this.resetForm()
this.$emit('input', false)
}
}
}
</script>
<style scoped lang="scss">
</style>
import filter from '@/utils/filter.js'
class data extends filter {
constructor() {
super()
}
columns () {
return [
{
prop: "name",
label: "角色名称",
width: 130
},
{
prop: "description",
label: "备注"
}
]
}
}
export default new data()
<!-- 新增 & 修改角色 -->
<template>
<dialogBox
class="PersonnelDialog"
:title="title"
:width="'567px'"
:isMain="true"
@closeDialog="close"
@submitForm="submitForm"
v-model="myValue">
<div class="dialogCon">
<el-form ref="form" :model="dialogForm" :rules="rules" label-width="82px">
<el-row :gutter="24">
<el-col :span="23">
<el-form-item label="角色名称:" prop="roleName">
<el-input
v-model="dialogForm.roleName"
clearable
placeholder="角色名称" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="23">
<el-form-item label="备注:" class="form-item-mb0">
<el-input
v-model="dialogForm.roleTextArea"
clearable
:rows="10"
type="textarea"
maxlength="30"
placeholder="备注" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<!-- <template slot="footer">
<el-button
class="cancel-button"
@click="handleCloseDialog">取消</el-button>
<el-button
type="primary"
@click="handleSaveRole()">保存</el-button>
</template> -->
</dialogBox>
</template>
<script>
import Dialog from "@/components/Dialog/";
import { api, httpAction } from '@/api/manageApi'
export default {
components: {
Dialog
},
props: {
value: { type: Boolean, default: false },
},
data () {
return {
myValue: this.value,
title: '',
menuType: '',
roleId: '',
sort: 0,
dialogForm: {
roleName: '',
roleType: '',
roleTextArea: ''
},
rules: {
roleName: [
{ required: true, message: '请输入角色名称', trigger: 'blur' }
],
},
roleTypeOptions: [
{ name: '定制', value: '定制' },
{ name: '其他', value: '其他' }
]
}
},
watch: {
value (val) {
this.myValue = val
}
},
methods: {
// 保存新增或关闭事件
submitForm () {
this.$refs.form.validate((valid) => {
if (valid) {
try {
const params = {
category: 2,
description: this.dialogForm.roleTextArea,
name: this.dialogForm.roleName,
sort: this.sort,
type: this.dialogForm.roleType
}
if (this.roleId) {
params.id = this.roleId
httpAction(`${api.roles}/${params.id}`, params, 'post').then(
(res) => {
if (res.status === 1) {
this.$message.success({
message: '修改成功',
showClose: true
})
this.dialogForm = {
roleName: '',
}
this.$emit('ok')
} else {
this.$message.error({
message: res.message,
showClose: true
})
}
}
)
} else {
httpAction(api.roles, params, 'post').then((res) => {
if (res.status === 1) {
this.$message.success({
message: '新增成功',
showClose: true
})
this.close()
this.$emit('ok')
this.$emit('ok', this.menuType)
} else {
this.$message.error({
message: res.message,
showClose: true
})
}
})
}
} catch (e) {
console.error(e)
}
}
})
},
// 重置
resetForm () {
this.dialogForm = {
roleName: '',
}
this.$refs.form.resetFields()
},
// 关闭
close () {
this.resetForm()
this.$emit('input', false)
}
}
}
</script>
<style scoped lang="scss">
</style>
/*
* @Author: xiaomiao 1158771342@qq.com
* @Date: 2023-01-30 17:59:51
* @LastEditors: Please set LastEditors
* @LastEditTime: 2023-03-23 09:34:50
* @FilePath: \监管系统\js-web-jianguan\src\views\system\users\data\index.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import filter from '@/utils/filter.js'
class data extends filter {
constructor() {
super()
}
columns () {
return [
{
prop: "code",
label: "工号",
width: 130
},
{
prop: "name",
label: "姓名",
width: 100
},
{
prop: "loginName",
label: "用户名"
},
{
prop: "departmentName",
label: "组织机构",
minWidth: 130
},
{
prop: "telephone",
label: "电话"
},
{
prop: "jobLevel",
label: "职位"
},
]
}
}
export default new data()
<template>
<dialogBox :title="title" :width="'867px'" class="PersonnelDialog" @closeDialog="close" :isMain="true" @submitForm="submitForm"
v-model="myValue">
<div class="dialogCon">
<el-form ref="form" :model="form" :rules="rules">
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="姓名:" prop="name" label-width="100px">
<el-input v-model="form.name" placeholder="姓名" />
</el-form-item>
</el-col>
<el-col :span="23">
<el-col :span="18" class="col-pd0">
<el-form-item label="性别:" label-width="88px">
<el-radio v-for="(item, index) in sexList" :key="index" v-model="form.sex" :label="item.value">{{
item.name }}</el-radio>
</el-form-item>
</el-col>
<el-col :span="6">
<el-checkbox v-model="form.isDuty">负责人</el-checkbox>
</el-col>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="工号:" prop="code" label-width="100px">
<el-input v-model="form.code" placeholder="工号" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="用户名:" prop="loginName" label-width="72px">
<el-input v-model="form.loginName" :disabled="showLoginName" placeholder="用户名" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="身份证号码:" label-width="100px">
<el-input v-model="form.idCard" placeholder="身份证号码" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手机号码:" prop="mobilePhone" label-width="72px">
<el-input v-model="form.mobilePhone" placeholder="手机号码" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="最高职务级别:" label-width="100px">
<el-select v-model="form.jobLevel" placeholder="最高职务级别">
<el-option v-for="item in levelList" :key="item.value" :label="item.name" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="办公电话:" prop="telephone" label-width="72px">
<el-input v-model="form.telephone" placeholder="办公电话" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="24">
<el-form-item label="组织机构:" label-width="100px" prop="departmentId">
<el-select class="selbig" v-model="form.departmentId" placeholder="组织机构">
<el-option v-for="item in districtAreaList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="24">
<el-form-item label="办公地点:" label-width="100px" class="form-item-mb0">
<el-input v-model="form.address" placeholder="办公地点" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</dialogBox>
</template>
<script>
import { api, httpAction, getAction } from '@/api/manageApi'
export default {
name: "",
props: {
value: { type: Boolean, default: false },
},
data () {
return {
myValue: this.value,
districtAreaList: [],
form: {
sex: "0",
departmentId: '',
},
rules: {
name: [{ required: true, message: "请输入姓名", trigger: "blur" }],
code: [{ required: true, message: "请输入工号", trigger: "blur" }],
departmentId: [{ required: true, message: "请选择组织机构", trigger: 'change' }],
mobilePhone: [{ validator: "sddd", trigger: "blur" }],
loginName: [
{ required: true, message: "请输入用户名", trigger: "blur" },
],
},
title: "",
showLoginName: false,
sexList: [{ lable: "0", value: "0", name: "男" }, { lable: "1", value: "1", name: "女" }],
levelList: [{ lable: "0", value: "0", name: "干事" }, { lable: "1", value: "1", name: "经理" }],
dataUrl: api.users
};
},
watch: {
value (val) {
this.myValue = val
}
},
created () {
this.getdistricts()
},
methods: {
getdistricts () {
getAction(api.departments, {
queryOptions: { orderBys: [{ property: "sort", direction: "desc" }] },
}).then((res) => {
this.districtAreaList = res.content;
});
},
// 添加人员
adds () {
this.showLoginName = false
},
// 编辑
edit (record) {
this.showLoginName = true
// 若有id为编辑
if (record) {
this.$nextTick(() => {
this.form = Object.assign({}, record)
})
}
},
// 保存
submitForm () {
this.districtAreaList.forEach((item) => {
if (this.form.departmentId == item.id) {
this.form.organizationId = item.organizationId
}
})
this.$refs.form.validate((valid) => {
if (valid) {
let method = ''
let url = ''
const formData = this.form
if (!formData.id) {
method = 'post'
url = this.dataUrl
} else {
method = 'put'
url = `${this.dataUrl}/${formData.id}`
}
httpAction(url, formData, method).then((res) => {
if (res.status === 1) {
this.$message.success({ message: res.message, showClose: true })
this.close()
this.$emit('ok')
} else {
this.$message.error({ message: res.message, showClose: true })
}
})
} else {
return false
}
})
},
// 重置
resetForm () {
this.form = {
sex: '0'
}
this.$refs.form.resetFields()
},
// 关闭
close () {
this.resetForm()
this.$emit('input', false)
}
}
}
</script>
<style scoped lang="scss">
</style>
.btnColRight {
margin-top: 20px;
}