diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/package.json b/package.json index e687665..c966921 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "vue-template-compiler": "2.5.17", "webpack": "4.16.5", "webpack-bundle-analyzer": "^3.4.1", - "webpack-cli": "3.1.0", + "webpack-cli": "^3.1.0", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/package.json b/package.json index e687665..c966921 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "vue-template-compiler": "2.5.17", "webpack": "4.16.5", "webpack-bundle-analyzer": "^3.4.1", - "webpack-cli": "3.1.0", + "webpack-cli": "^3.1.0", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, diff --git a/src/api/system/user.js b/src/api/system/user.js index 91e7aa7..f470dbd 100644 --- a/src/api/system/user.js +++ b/src/api/system/user.js @@ -113,3 +113,20 @@ } }) } + +// 单点登录获取token +export function fetchToken(params) { + return request({ + url: 'platform/checkZFToken', + method: 'get', + params + }) +} +// 同步用户 +export function syncUser(data) { + return request({ + url: 'ssoUser/syncUser', + method: 'post', + data + }) +} diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/package.json b/package.json index e687665..c966921 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "vue-template-compiler": "2.5.17", "webpack": "4.16.5", "webpack-bundle-analyzer": "^3.4.1", - "webpack-cli": "3.1.0", + "webpack-cli": "^3.1.0", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, diff --git a/src/api/system/user.js b/src/api/system/user.js index 91e7aa7..f470dbd 100644 --- a/src/api/system/user.js +++ b/src/api/system/user.js @@ -113,3 +113,20 @@ } }) } + +// 单点登录获取token +export function fetchToken(params) { + return request({ + url: 'platform/checkZFToken', + method: 'get', + params + }) +} +// 同步用户 +export function syncUser(data) { + return request({ + url: 'ssoUser/syncUser', + method: 'post', + data + }) +} diff --git a/src/components/Map/MarsMap.vue b/src/components/Map/MarsMap.vue index c400842..893e665 100644 --- a/src/components/Map/MarsMap.vue +++ b/src/components/Map/MarsMap.vue @@ -9,7 +9,7 @@ diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/package.json b/package.json index e687665..c966921 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "vue-template-compiler": "2.5.17", "webpack": "4.16.5", "webpack-bundle-analyzer": "^3.4.1", - "webpack-cli": "3.1.0", + "webpack-cli": "^3.1.0", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, diff --git a/src/api/system/user.js b/src/api/system/user.js index 91e7aa7..f470dbd 100644 --- a/src/api/system/user.js +++ b/src/api/system/user.js @@ -113,3 +113,20 @@ } }) } + +// 单点登录获取token +export function fetchToken(params) { + return request({ + url: 'platform/checkZFToken', + method: 'get', + params + }) +} +// 同步用户 +export function syncUser(data) { + return request({ + url: 'ssoUser/syncUser', + method: 'post', + data + }) +} diff --git a/src/components/Map/MarsMap.vue b/src/components/Map/MarsMap.vue index c400842..893e665 100644 --- a/src/components/Map/MarsMap.vue +++ b/src/components/Map/MarsMap.vue @@ -9,7 +9,7 @@ diff --git a/src/layout/LayoutApp.vue b/src/layout/LayoutApp.vue index 81db434..ae5731a 100644 --- a/src/layout/LayoutApp.vue +++ b/src/layout/LayoutApp.vue @@ -30,7 +30,7 @@ this.title = this.$route.query.name this.url = this.$route.query.url } - if(this.baseConfig.toDashboard===false){ + if (this.baseConfig.toDashboard===false){ this.showBack = false } }, diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/package.json b/package.json index e687665..c966921 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "vue-template-compiler": "2.5.17", "webpack": "4.16.5", "webpack-bundle-analyzer": "^3.4.1", - "webpack-cli": "3.1.0", + "webpack-cli": "^3.1.0", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, diff --git a/src/api/system/user.js b/src/api/system/user.js index 91e7aa7..f470dbd 100644 --- a/src/api/system/user.js +++ b/src/api/system/user.js @@ -113,3 +113,20 @@ } }) } + +// 单点登录获取token +export function fetchToken(params) { + return request({ + url: 'platform/checkZFToken', + method: 'get', + params + }) +} +// 同步用户 +export function syncUser(data) { + return request({ + url: 'ssoUser/syncUser', + method: 'post', + data + }) +} diff --git a/src/components/Map/MarsMap.vue b/src/components/Map/MarsMap.vue index c400842..893e665 100644 --- a/src/components/Map/MarsMap.vue +++ b/src/components/Map/MarsMap.vue @@ -9,7 +9,7 @@ diff --git a/src/layout/LayoutApp.vue b/src/layout/LayoutApp.vue index 81db434..ae5731a 100644 --- a/src/layout/LayoutApp.vue +++ b/src/layout/LayoutApp.vue @@ -30,7 +30,7 @@ this.title = this.$route.query.name this.url = this.$route.query.url } - if(this.baseConfig.toDashboard===false){ + if (this.baseConfig.toDashboard===false){ this.showBack = false } }, diff --git a/src/main.js b/src/main.js index fd1d17e..7568b6e 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,9 @@ +console.log('==============main.js===============') import Vue from 'vue' import 'normalize.css/normalize.css' // A modern alternative to CSS resets import '../theme/index.css' // 引入自定义主题 import ElementUI from 'element-ui' -// import 'element-ui/lib/theme-chalk/index.css' +import 'element-ui/lib/theme-chalk/index.css' import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n import '@/styles/index.scss' // global css diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/package.json b/package.json index e687665..c966921 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "vue-template-compiler": "2.5.17", "webpack": "4.16.5", "webpack-bundle-analyzer": "^3.4.1", - "webpack-cli": "3.1.0", + "webpack-cli": "^3.1.0", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, diff --git a/src/api/system/user.js b/src/api/system/user.js index 91e7aa7..f470dbd 100644 --- a/src/api/system/user.js +++ b/src/api/system/user.js @@ -113,3 +113,20 @@ } }) } + +// 单点登录获取token +export function fetchToken(params) { + return request({ + url: 'platform/checkZFToken', + method: 'get', + params + }) +} +// 同步用户 +export function syncUser(data) { + return request({ + url: 'ssoUser/syncUser', + method: 'post', + data + }) +} diff --git a/src/components/Map/MarsMap.vue b/src/components/Map/MarsMap.vue index c400842..893e665 100644 --- a/src/components/Map/MarsMap.vue +++ b/src/components/Map/MarsMap.vue @@ -9,7 +9,7 @@ diff --git a/src/layout/LayoutApp.vue b/src/layout/LayoutApp.vue index 81db434..ae5731a 100644 --- a/src/layout/LayoutApp.vue +++ b/src/layout/LayoutApp.vue @@ -30,7 +30,7 @@ this.title = this.$route.query.name this.url = this.$route.query.url } - if(this.baseConfig.toDashboard===false){ + if (this.baseConfig.toDashboard===false){ this.showBack = false } }, diff --git a/src/main.js b/src/main.js index fd1d17e..7568b6e 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,9 @@ +console.log('==============main.js===============') import Vue from 'vue' import 'normalize.css/normalize.css' // A modern alternative to CSS resets import '../theme/index.css' // 引入自定义主题 import ElementUI from 'element-ui' -// import 'element-ui/lib/theme-chalk/index.css' +import 'element-ui/lib/theme-chalk/index.css' import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n import '@/styles/index.scss' // global css diff --git a/src/permission.js b/src/permission.js index c4f95f2..55bd751 100644 --- a/src/permission.js +++ b/src/permission.js @@ -4,8 +4,11 @@ import 'nprogress/nprogress.css' // progress bar style 进度条样式 import { Message } from 'element-ui' import { getToken } from '@/utils/auth' // getToken from cookie +import axios from 'axios' import { getCurrentSys } from './utils/auth' import Vue from 'vue' +import { extractURLParameters } from '@/utils/validate' +import { fetchToken } from '@/api/system/user' NProgress.configure({ showSpinner: false })// NProgress configuration @@ -83,23 +86,65 @@ console.log('is In WhiteList') next() } else { + debugger // 获取链接里的token const token = to.query.token - console.log('token' + to.query.token) - if (token) { - // 调用自动登录接口,否则跳转到登录页 - store.dispatch('AppLogin', token).then(() => { - console.log('自动登录成功') - console.log(to.path) - next({ ...to, replace: true }) // 登录成功继续 - }).catch(() => { - next('/401') // 否则全部重定向到401没有权限页面 + console.log('token' + token) + // // 携带token 需要去掉 + // const zfToken = to.query['ZF-TOKEN'] + let zfToken = '' + // 携带token 需要去掉 + const hrefIdx = window.location.href.indexOf('ZF-TOKEN') // url中是否携带token + if (hrefIdx > -1) { + // const params = queryString(window.location.href) + // zfToken = stripscript(params.token) + console.log('hrefIdx', extractURLParameters(window.location.href)) + const params = extractURLParameters(window.location.href) + zfToken = params['ZF-TOKEN'] + } + console.log('zfToken' + zfToken) + if (zfToken) { + const sendParams = { + zf_token: zfToken + } + // eslint-disable-next-line no-unused-vars + debugger + // window.location.href = 'https://www.baidu.com/?tn=25017023_17_dg' + fetchToken(sendParams).then((resToken) => { + if (resToken.code === 200) { + axios.get('./static/project.config.json').then((result) => { + const params = '?token=' + resToken.data.token + '&url=' + result.data.singleSignLastUrl + const loginUrl = result.data.singleSignFirstUrl + '/sso/integrationConfig/login' + // next({ + // path: '/appSubject', + // query: { name: resToken.data.title, url: loginUrl + params } + // }) + // window.open(loginUrl + params, '_blank') + window.location.href = loginUrl + params + }) + } else { + console.log('用户验证失败') + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } }) } else { - if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { - next(`/applogin`) // 否则全部重定向到登录页 + debugger + if (token) { + // 调用自动登录接口,否则跳转到登录页 + const params = token + store.dispatch('AppLogin', params).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) } else { - next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } } } NProgress.done() diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/package.json b/package.json index e687665..c966921 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "vue-template-compiler": "2.5.17", "webpack": "4.16.5", "webpack-bundle-analyzer": "^3.4.1", - "webpack-cli": "3.1.0", + "webpack-cli": "^3.1.0", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, diff --git a/src/api/system/user.js b/src/api/system/user.js index 91e7aa7..f470dbd 100644 --- a/src/api/system/user.js +++ b/src/api/system/user.js @@ -113,3 +113,20 @@ } }) } + +// 单点登录获取token +export function fetchToken(params) { + return request({ + url: 'platform/checkZFToken', + method: 'get', + params + }) +} +// 同步用户 +export function syncUser(data) { + return request({ + url: 'ssoUser/syncUser', + method: 'post', + data + }) +} diff --git a/src/components/Map/MarsMap.vue b/src/components/Map/MarsMap.vue index c400842..893e665 100644 --- a/src/components/Map/MarsMap.vue +++ b/src/components/Map/MarsMap.vue @@ -9,7 +9,7 @@ diff --git a/src/layout/LayoutApp.vue b/src/layout/LayoutApp.vue index 81db434..ae5731a 100644 --- a/src/layout/LayoutApp.vue +++ b/src/layout/LayoutApp.vue @@ -30,7 +30,7 @@ this.title = this.$route.query.name this.url = this.$route.query.url } - if(this.baseConfig.toDashboard===false){ + if (this.baseConfig.toDashboard===false){ this.showBack = false } }, diff --git a/src/main.js b/src/main.js index fd1d17e..7568b6e 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,9 @@ +console.log('==============main.js===============') import Vue from 'vue' import 'normalize.css/normalize.css' // A modern alternative to CSS resets import '../theme/index.css' // 引入自定义主题 import ElementUI from 'element-ui' -// import 'element-ui/lib/theme-chalk/index.css' +import 'element-ui/lib/theme-chalk/index.css' import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n import '@/styles/index.scss' // global css diff --git a/src/permission.js b/src/permission.js index c4f95f2..55bd751 100644 --- a/src/permission.js +++ b/src/permission.js @@ -4,8 +4,11 @@ import 'nprogress/nprogress.css' // progress bar style 进度条样式 import { Message } from 'element-ui' import { getToken } from '@/utils/auth' // getToken from cookie +import axios from 'axios' import { getCurrentSys } from './utils/auth' import Vue from 'vue' +import { extractURLParameters } from '@/utils/validate' +import { fetchToken } from '@/api/system/user' NProgress.configure({ showSpinner: false })// NProgress configuration @@ -83,23 +86,65 @@ console.log('is In WhiteList') next() } else { + debugger // 获取链接里的token const token = to.query.token - console.log('token' + to.query.token) - if (token) { - // 调用自动登录接口,否则跳转到登录页 - store.dispatch('AppLogin', token).then(() => { - console.log('自动登录成功') - console.log(to.path) - next({ ...to, replace: true }) // 登录成功继续 - }).catch(() => { - next('/401') // 否则全部重定向到401没有权限页面 + console.log('token' + token) + // // 携带token 需要去掉 + // const zfToken = to.query['ZF-TOKEN'] + let zfToken = '' + // 携带token 需要去掉 + const hrefIdx = window.location.href.indexOf('ZF-TOKEN') // url中是否携带token + if (hrefIdx > -1) { + // const params = queryString(window.location.href) + // zfToken = stripscript(params.token) + console.log('hrefIdx', extractURLParameters(window.location.href)) + const params = extractURLParameters(window.location.href) + zfToken = params['ZF-TOKEN'] + } + console.log('zfToken' + zfToken) + if (zfToken) { + const sendParams = { + zf_token: zfToken + } + // eslint-disable-next-line no-unused-vars + debugger + // window.location.href = 'https://www.baidu.com/?tn=25017023_17_dg' + fetchToken(sendParams).then((resToken) => { + if (resToken.code === 200) { + axios.get('./static/project.config.json').then((result) => { + const params = '?token=' + resToken.data.token + '&url=' + result.data.singleSignLastUrl + const loginUrl = result.data.singleSignFirstUrl + '/sso/integrationConfig/login' + // next({ + // path: '/appSubject', + // query: { name: resToken.data.title, url: loginUrl + params } + // }) + // window.open(loginUrl + params, '_blank') + window.location.href = loginUrl + params + }) + } else { + console.log('用户验证失败') + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } }) } else { - if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { - next(`/applogin`) // 否则全部重定向到登录页 + debugger + if (token) { + // 调用自动登录接口,否则跳转到登录页 + const params = token + store.dispatch('AppLogin', params).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) } else { - next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } } } NProgress.done() diff --git a/src/permissionBak.js b/src/permissionBak.js new file mode 100644 index 0000000..ba87122 --- /dev/null +++ b/src/permissionBak.js @@ -0,0 +1,103 @@ +import router from './router' +import store from './store' +import NProgress from 'nprogress' // progress bar 进度条 +import 'nprogress/nprogress.css' // progress bar style 进度条样式 +import { Message } from 'element-ui' +import { getToken } from '@/utils/auth' // getToken from cookie +import { getCurrentSys } from './utils/auth' + +NProgress.configure({ showSpinner: false })// NProgress configuration + +const whiteList = ['/login', '/applogin', '/appFaceLogin', '/404', 'config/baseconfig', '/full/storageTopic', '/full/waterThreat', '/full/highConsequence', '/full/constructionThreat', '/full/routeTopic', '/full/waterThreat', '/full/sinkThreat', '/full/vip', '/full/weather', '/full/needTopic', '/full/supplyTopic', '/full/pipeOverview', '/full/overview'] // 不重定向白名单 +// 全局钩子 +router.beforeEach((to, from, next) => { + NProgress.start() // 加载进度条 + console.log('to Path:' + to.path) + // 如果有token + if (getToken()) { + console.log('hasToken') + // 登录后进入登录页 + if (to.path === '/login') { + next({ path: '/login' }) + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else if (to.path === '/dashboard') { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next('/appIndex') // 否则全部重定向到登录页 + } else { + next() + } + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else { + // 当进入非登陆页或非主页时 + if (store.getters.roleList.length === 0) { // 判断当前用户是否已拉取完user_info信息 + store.dispatch('GetInfo').then(res => { // 拉取用户信息 + let currentSys = getCurrentSys() + // 根据路由去找当前子系统 + if (to.query.sys) { + currentSys = { + code: to.query.code, + name: to.query.sys, + url: to.query.url + } + // 将当前系统信息保存在localStorage中 + store.commit('SET_SYSTEM', currentSys) + } + // 如果已有当前可进入的子系统,刷新子系统菜单 + if (currentSys) { + console.log('hasCurrentSystem') + // 远程访问获取权限列表(菜单&按钮) + store.dispatch('GetMenus', currentSys).then(() => { + store.commit('SET_CHANGEFLAG', '0') + // 获取所有地址列表 + router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表 + // 判断路由是否被允许,不允许则重定向 + next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record + }) + } else { // 没有当前子系统信息,跳转到选择子系统页面 + console.log('dontHasCurrentSystem') + next({ path: '/dashboard' }) + } + }).catch((err) => { + console.log('toFedLogOut') + store.dispatch('FedLogOut').then(() => { + Message.error(err || '权限验证失败,请重新登录系统') + next({ path: '/' }) + }) + }) + } else { + // TODO: 判断路由是否被允许,不允许则重定向 + next() + } + } + } else { + if (whiteList.indexOf(to.path) !== -1) { // 免登录白名单,直接进入 + console.log('is In WhiteList') + next() + } else { + // 获取链接里的token + const token = to.query.token + console.log('token' + to.query.token) + if (token) { + // 调用自动登录接口,否则跳转到登录页 + store.dispatch('AppLogin', token).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) + } else { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } + } + NProgress.done() + } + } +}) + +router.afterEach(() => { + NProgress.done() // 结束Progress +}) diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/package.json b/package.json index e687665..c966921 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "vue-template-compiler": "2.5.17", "webpack": "4.16.5", "webpack-bundle-analyzer": "^3.4.1", - "webpack-cli": "3.1.0", + "webpack-cli": "^3.1.0", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, diff --git a/src/api/system/user.js b/src/api/system/user.js index 91e7aa7..f470dbd 100644 --- a/src/api/system/user.js +++ b/src/api/system/user.js @@ -113,3 +113,20 @@ } }) } + +// 单点登录获取token +export function fetchToken(params) { + return request({ + url: 'platform/checkZFToken', + method: 'get', + params + }) +} +// 同步用户 +export function syncUser(data) { + return request({ + url: 'ssoUser/syncUser', + method: 'post', + data + }) +} diff --git a/src/components/Map/MarsMap.vue b/src/components/Map/MarsMap.vue index c400842..893e665 100644 --- a/src/components/Map/MarsMap.vue +++ b/src/components/Map/MarsMap.vue @@ -9,7 +9,7 @@ diff --git a/src/layout/LayoutApp.vue b/src/layout/LayoutApp.vue index 81db434..ae5731a 100644 --- a/src/layout/LayoutApp.vue +++ b/src/layout/LayoutApp.vue @@ -30,7 +30,7 @@ this.title = this.$route.query.name this.url = this.$route.query.url } - if(this.baseConfig.toDashboard===false){ + if (this.baseConfig.toDashboard===false){ this.showBack = false } }, diff --git a/src/main.js b/src/main.js index fd1d17e..7568b6e 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,9 @@ +console.log('==============main.js===============') import Vue from 'vue' import 'normalize.css/normalize.css' // A modern alternative to CSS resets import '../theme/index.css' // 引入自定义主题 import ElementUI from 'element-ui' -// import 'element-ui/lib/theme-chalk/index.css' +import 'element-ui/lib/theme-chalk/index.css' import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n import '@/styles/index.scss' // global css diff --git a/src/permission.js b/src/permission.js index c4f95f2..55bd751 100644 --- a/src/permission.js +++ b/src/permission.js @@ -4,8 +4,11 @@ import 'nprogress/nprogress.css' // progress bar style 进度条样式 import { Message } from 'element-ui' import { getToken } from '@/utils/auth' // getToken from cookie +import axios from 'axios' import { getCurrentSys } from './utils/auth' import Vue from 'vue' +import { extractURLParameters } from '@/utils/validate' +import { fetchToken } from '@/api/system/user' NProgress.configure({ showSpinner: false })// NProgress configuration @@ -83,23 +86,65 @@ console.log('is In WhiteList') next() } else { + debugger // 获取链接里的token const token = to.query.token - console.log('token' + to.query.token) - if (token) { - // 调用自动登录接口,否则跳转到登录页 - store.dispatch('AppLogin', token).then(() => { - console.log('自动登录成功') - console.log(to.path) - next({ ...to, replace: true }) // 登录成功继续 - }).catch(() => { - next('/401') // 否则全部重定向到401没有权限页面 + console.log('token' + token) + // // 携带token 需要去掉 + // const zfToken = to.query['ZF-TOKEN'] + let zfToken = '' + // 携带token 需要去掉 + const hrefIdx = window.location.href.indexOf('ZF-TOKEN') // url中是否携带token + if (hrefIdx > -1) { + // const params = queryString(window.location.href) + // zfToken = stripscript(params.token) + console.log('hrefIdx', extractURLParameters(window.location.href)) + const params = extractURLParameters(window.location.href) + zfToken = params['ZF-TOKEN'] + } + console.log('zfToken' + zfToken) + if (zfToken) { + const sendParams = { + zf_token: zfToken + } + // eslint-disable-next-line no-unused-vars + debugger + // window.location.href = 'https://www.baidu.com/?tn=25017023_17_dg' + fetchToken(sendParams).then((resToken) => { + if (resToken.code === 200) { + axios.get('./static/project.config.json').then((result) => { + const params = '?token=' + resToken.data.token + '&url=' + result.data.singleSignLastUrl + const loginUrl = result.data.singleSignFirstUrl + '/sso/integrationConfig/login' + // next({ + // path: '/appSubject', + // query: { name: resToken.data.title, url: loginUrl + params } + // }) + // window.open(loginUrl + params, '_blank') + window.location.href = loginUrl + params + }) + } else { + console.log('用户验证失败') + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } }) } else { - if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { - next(`/applogin`) // 否则全部重定向到登录页 + debugger + if (token) { + // 调用自动登录接口,否则跳转到登录页 + const params = token + store.dispatch('AppLogin', params).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) } else { - next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } } } NProgress.done() diff --git a/src/permissionBak.js b/src/permissionBak.js new file mode 100644 index 0000000..ba87122 --- /dev/null +++ b/src/permissionBak.js @@ -0,0 +1,103 @@ +import router from './router' +import store from './store' +import NProgress from 'nprogress' // progress bar 进度条 +import 'nprogress/nprogress.css' // progress bar style 进度条样式 +import { Message } from 'element-ui' +import { getToken } from '@/utils/auth' // getToken from cookie +import { getCurrentSys } from './utils/auth' + +NProgress.configure({ showSpinner: false })// NProgress configuration + +const whiteList = ['/login', '/applogin', '/appFaceLogin', '/404', 'config/baseconfig', '/full/storageTopic', '/full/waterThreat', '/full/highConsequence', '/full/constructionThreat', '/full/routeTopic', '/full/waterThreat', '/full/sinkThreat', '/full/vip', '/full/weather', '/full/needTopic', '/full/supplyTopic', '/full/pipeOverview', '/full/overview'] // 不重定向白名单 +// 全局钩子 +router.beforeEach((to, from, next) => { + NProgress.start() // 加载进度条 + console.log('to Path:' + to.path) + // 如果有token + if (getToken()) { + console.log('hasToken') + // 登录后进入登录页 + if (to.path === '/login') { + next({ path: '/login' }) + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else if (to.path === '/dashboard') { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next('/appIndex') // 否则全部重定向到登录页 + } else { + next() + } + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else { + // 当进入非登陆页或非主页时 + if (store.getters.roleList.length === 0) { // 判断当前用户是否已拉取完user_info信息 + store.dispatch('GetInfo').then(res => { // 拉取用户信息 + let currentSys = getCurrentSys() + // 根据路由去找当前子系统 + if (to.query.sys) { + currentSys = { + code: to.query.code, + name: to.query.sys, + url: to.query.url + } + // 将当前系统信息保存在localStorage中 + store.commit('SET_SYSTEM', currentSys) + } + // 如果已有当前可进入的子系统,刷新子系统菜单 + if (currentSys) { + console.log('hasCurrentSystem') + // 远程访问获取权限列表(菜单&按钮) + store.dispatch('GetMenus', currentSys).then(() => { + store.commit('SET_CHANGEFLAG', '0') + // 获取所有地址列表 + router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表 + // 判断路由是否被允许,不允许则重定向 + next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record + }) + } else { // 没有当前子系统信息,跳转到选择子系统页面 + console.log('dontHasCurrentSystem') + next({ path: '/dashboard' }) + } + }).catch((err) => { + console.log('toFedLogOut') + store.dispatch('FedLogOut').then(() => { + Message.error(err || '权限验证失败,请重新登录系统') + next({ path: '/' }) + }) + }) + } else { + // TODO: 判断路由是否被允许,不允许则重定向 + next() + } + } + } else { + if (whiteList.indexOf(to.path) !== -1) { // 免登录白名单,直接进入 + console.log('is In WhiteList') + next() + } else { + // 获取链接里的token + const token = to.query.token + console.log('token' + to.query.token) + if (token) { + // 调用自动登录接口,否则跳转到登录页 + store.dispatch('AppLogin', token).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) + } else { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } + } + NProgress.done() + } + } +}) + +router.afterEach(() => { + NProgress.done() // 结束Progress +}) diff --git a/src/utils/validate.js b/src/utils/validate.js index d7e84e4..52736af 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -7,35 +7,35 @@ * 未知用途 */ export function isExternal(path) { - return /^(https?:|mailto:|tel:)/.test(path) + return /^(https?:|mailto:|tel:)/.test(path); } /* 合法uri*/ export function validateURL(textval) { - const urlregex = /^(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 urlregex.test(textval) + const urlregex = /^(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 urlregex.test(textval); } /* 合法uri*/ export function validateNull(textval) { - return !!textval + return !!textval; } /* 验证小写字母*/ export function validateLowerCase(str) { - const reg = /^[a-z]+$/ - return reg.test(str) + const reg = /^[a-z]+$/; + return reg.test(str); } /* 验证大写字母*/ export function validateUpperCase(str) { - const reg = /^[A-Z]+$/ - return reg.test(str) + const reg = /^[A-Z]+$/; + return reg.test(str); } /* 验证大小写字母*/ export function validateAlphabets(str) { - const reg = /^[A-Za-z]+$/ - return reg.test(str) + const reg = /^[A-Za-z]+$/; + return reg.test(str); } /** @@ -44,8 +44,8 @@ * @returns {boolean} */ export function validateEmail(email) { - const re = /^(([^<>()\[\]\\.,;:\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 re.test(email) + const re = /^(([^<>()\[\]\\.,;:\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 re.test(email); } /** @@ -54,38 +54,70 @@ * @returns {boolean} */ export function validatePhone(phone) { - const re = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/ - return re.test(phone) + const re = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/; + return re.test(phone); } /** * 验证一定范围内的非负整数 */ export function validateIntPlus(value, min, max) { - const re = /^\d+$/ + const re = /^\d+$/; if (re.test(value)) { - const data = parseInt(value) + const data = parseInt(value); if (data > max || data < min) { - return false + return false; } - return true + return true; } else { - return false + return false; } } /** * 验证一定范围内的非负小数 */ export function validateFloatPlus(value, min, max) { - const re = /^\d+(\.\d+)?$/ + const re = /^\d+(\.\d+)?$/; if (re.test(value)) { - const data = parseFloat(value) + const data = parseFloat(value); if (data > max || data < min) { - return false + return false; } else { - return true + return true; } } else { - return false + return false; } } + +// 提取url params参数 +export function queryString(str) { + const params = str.split('?')[1] // 截取?号后的字符串即name=itclanCoder&study=css + const param = params.split('&') // 通过&符号进行分割即["name=itclanCoder", "study=css"] + const obj = {} // 用一个对象存储目标值 + for (let i = 0; i < param.length; i++) { + // 循环遍历截取出来的param数组 + const paramsA = param[i].split('=') // 通过split,=继续对数组params每一项进行分割,生成数组["name", "itclanCoder"] + const key = paramsA[0] // 取数组项["name", "itclanCoder"]中第0位,即name + const value = paramsA[1] // 取数组项["name", "itclanCoder"]中第1位,即itclanCoder + obj[key] = value + } + return obj +} +// 去除字符串中的特殊符号 +export function stripscript(s) { + var pattern = /[[\]\/:*?"<>|#]/ + var rs = '' + for (var i = 0; i < s.length; i++) { + rs = rs + s.substr(i, 1).replace(pattern, '') + } + return rs +} + +export function extractURLParameters(url) { + const params = new URLSearchParams(url.split('?')[1]); + return Array.from(params.entries()).reduce((acc, [key, value]) => { + acc[key] = value; + return acc; + }, {}); +} diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/package.json b/package.json index e687665..c966921 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "vue-template-compiler": "2.5.17", "webpack": "4.16.5", "webpack-bundle-analyzer": "^3.4.1", - "webpack-cli": "3.1.0", + "webpack-cli": "^3.1.0", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, diff --git a/src/api/system/user.js b/src/api/system/user.js index 91e7aa7..f470dbd 100644 --- a/src/api/system/user.js +++ b/src/api/system/user.js @@ -113,3 +113,20 @@ } }) } + +// 单点登录获取token +export function fetchToken(params) { + return request({ + url: 'platform/checkZFToken', + method: 'get', + params + }) +} +// 同步用户 +export function syncUser(data) { + return request({ + url: 'ssoUser/syncUser', + method: 'post', + data + }) +} diff --git a/src/components/Map/MarsMap.vue b/src/components/Map/MarsMap.vue index c400842..893e665 100644 --- a/src/components/Map/MarsMap.vue +++ b/src/components/Map/MarsMap.vue @@ -9,7 +9,7 @@ diff --git a/src/layout/LayoutApp.vue b/src/layout/LayoutApp.vue index 81db434..ae5731a 100644 --- a/src/layout/LayoutApp.vue +++ b/src/layout/LayoutApp.vue @@ -30,7 +30,7 @@ this.title = this.$route.query.name this.url = this.$route.query.url } - if(this.baseConfig.toDashboard===false){ + if (this.baseConfig.toDashboard===false){ this.showBack = false } }, diff --git a/src/main.js b/src/main.js index fd1d17e..7568b6e 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,9 @@ +console.log('==============main.js===============') import Vue from 'vue' import 'normalize.css/normalize.css' // A modern alternative to CSS resets import '../theme/index.css' // 引入自定义主题 import ElementUI from 'element-ui' -// import 'element-ui/lib/theme-chalk/index.css' +import 'element-ui/lib/theme-chalk/index.css' import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n import '@/styles/index.scss' // global css diff --git a/src/permission.js b/src/permission.js index c4f95f2..55bd751 100644 --- a/src/permission.js +++ b/src/permission.js @@ -4,8 +4,11 @@ import 'nprogress/nprogress.css' // progress bar style 进度条样式 import { Message } from 'element-ui' import { getToken } from '@/utils/auth' // getToken from cookie +import axios from 'axios' import { getCurrentSys } from './utils/auth' import Vue from 'vue' +import { extractURLParameters } from '@/utils/validate' +import { fetchToken } from '@/api/system/user' NProgress.configure({ showSpinner: false })// NProgress configuration @@ -83,23 +86,65 @@ console.log('is In WhiteList') next() } else { + debugger // 获取链接里的token const token = to.query.token - console.log('token' + to.query.token) - if (token) { - // 调用自动登录接口,否则跳转到登录页 - store.dispatch('AppLogin', token).then(() => { - console.log('自动登录成功') - console.log(to.path) - next({ ...to, replace: true }) // 登录成功继续 - }).catch(() => { - next('/401') // 否则全部重定向到401没有权限页面 + console.log('token' + token) + // // 携带token 需要去掉 + // const zfToken = to.query['ZF-TOKEN'] + let zfToken = '' + // 携带token 需要去掉 + const hrefIdx = window.location.href.indexOf('ZF-TOKEN') // url中是否携带token + if (hrefIdx > -1) { + // const params = queryString(window.location.href) + // zfToken = stripscript(params.token) + console.log('hrefIdx', extractURLParameters(window.location.href)) + const params = extractURLParameters(window.location.href) + zfToken = params['ZF-TOKEN'] + } + console.log('zfToken' + zfToken) + if (zfToken) { + const sendParams = { + zf_token: zfToken + } + // eslint-disable-next-line no-unused-vars + debugger + // window.location.href = 'https://www.baidu.com/?tn=25017023_17_dg' + fetchToken(sendParams).then((resToken) => { + if (resToken.code === 200) { + axios.get('./static/project.config.json').then((result) => { + const params = '?token=' + resToken.data.token + '&url=' + result.data.singleSignLastUrl + const loginUrl = result.data.singleSignFirstUrl + '/sso/integrationConfig/login' + // next({ + // path: '/appSubject', + // query: { name: resToken.data.title, url: loginUrl + params } + // }) + // window.open(loginUrl + params, '_blank') + window.location.href = loginUrl + params + }) + } else { + console.log('用户验证失败') + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } }) } else { - if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { - next(`/applogin`) // 否则全部重定向到登录页 + debugger + if (token) { + // 调用自动登录接口,否则跳转到登录页 + const params = token + store.dispatch('AppLogin', params).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) } else { - next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } } } NProgress.done() diff --git a/src/permissionBak.js b/src/permissionBak.js new file mode 100644 index 0000000..ba87122 --- /dev/null +++ b/src/permissionBak.js @@ -0,0 +1,103 @@ +import router from './router' +import store from './store' +import NProgress from 'nprogress' // progress bar 进度条 +import 'nprogress/nprogress.css' // progress bar style 进度条样式 +import { Message } from 'element-ui' +import { getToken } from '@/utils/auth' // getToken from cookie +import { getCurrentSys } from './utils/auth' + +NProgress.configure({ showSpinner: false })// NProgress configuration + +const whiteList = ['/login', '/applogin', '/appFaceLogin', '/404', 'config/baseconfig', '/full/storageTopic', '/full/waterThreat', '/full/highConsequence', '/full/constructionThreat', '/full/routeTopic', '/full/waterThreat', '/full/sinkThreat', '/full/vip', '/full/weather', '/full/needTopic', '/full/supplyTopic', '/full/pipeOverview', '/full/overview'] // 不重定向白名单 +// 全局钩子 +router.beforeEach((to, from, next) => { + NProgress.start() // 加载进度条 + console.log('to Path:' + to.path) + // 如果有token + if (getToken()) { + console.log('hasToken') + // 登录后进入登录页 + if (to.path === '/login') { + next({ path: '/login' }) + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else if (to.path === '/dashboard') { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next('/appIndex') // 否则全部重定向到登录页 + } else { + next() + } + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else { + // 当进入非登陆页或非主页时 + if (store.getters.roleList.length === 0) { // 判断当前用户是否已拉取完user_info信息 + store.dispatch('GetInfo').then(res => { // 拉取用户信息 + let currentSys = getCurrentSys() + // 根据路由去找当前子系统 + if (to.query.sys) { + currentSys = { + code: to.query.code, + name: to.query.sys, + url: to.query.url + } + // 将当前系统信息保存在localStorage中 + store.commit('SET_SYSTEM', currentSys) + } + // 如果已有当前可进入的子系统,刷新子系统菜单 + if (currentSys) { + console.log('hasCurrentSystem') + // 远程访问获取权限列表(菜单&按钮) + store.dispatch('GetMenus', currentSys).then(() => { + store.commit('SET_CHANGEFLAG', '0') + // 获取所有地址列表 + router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表 + // 判断路由是否被允许,不允许则重定向 + next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record + }) + } else { // 没有当前子系统信息,跳转到选择子系统页面 + console.log('dontHasCurrentSystem') + next({ path: '/dashboard' }) + } + }).catch((err) => { + console.log('toFedLogOut') + store.dispatch('FedLogOut').then(() => { + Message.error(err || '权限验证失败,请重新登录系统') + next({ path: '/' }) + }) + }) + } else { + // TODO: 判断路由是否被允许,不允许则重定向 + next() + } + } + } else { + if (whiteList.indexOf(to.path) !== -1) { // 免登录白名单,直接进入 + console.log('is In WhiteList') + next() + } else { + // 获取链接里的token + const token = to.query.token + console.log('token' + to.query.token) + if (token) { + // 调用自动登录接口,否则跳转到登录页 + store.dispatch('AppLogin', token).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) + } else { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } + } + NProgress.done() + } + } +}) + +router.afterEach(() => { + NProgress.done() // 结束Progress +}) diff --git a/src/utils/validate.js b/src/utils/validate.js index d7e84e4..52736af 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -7,35 +7,35 @@ * 未知用途 */ export function isExternal(path) { - return /^(https?:|mailto:|tel:)/.test(path) + return /^(https?:|mailto:|tel:)/.test(path); } /* 合法uri*/ export function validateURL(textval) { - const urlregex = /^(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 urlregex.test(textval) + const urlregex = /^(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 urlregex.test(textval); } /* 合法uri*/ export function validateNull(textval) { - return !!textval + return !!textval; } /* 验证小写字母*/ export function validateLowerCase(str) { - const reg = /^[a-z]+$/ - return reg.test(str) + const reg = /^[a-z]+$/; + return reg.test(str); } /* 验证大写字母*/ export function validateUpperCase(str) { - const reg = /^[A-Z]+$/ - return reg.test(str) + const reg = /^[A-Z]+$/; + return reg.test(str); } /* 验证大小写字母*/ export function validateAlphabets(str) { - const reg = /^[A-Za-z]+$/ - return reg.test(str) + const reg = /^[A-Za-z]+$/; + return reg.test(str); } /** @@ -44,8 +44,8 @@ * @returns {boolean} */ export function validateEmail(email) { - const re = /^(([^<>()\[\]\\.,;:\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 re.test(email) + const re = /^(([^<>()\[\]\\.,;:\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 re.test(email); } /** @@ -54,38 +54,70 @@ * @returns {boolean} */ export function validatePhone(phone) { - const re = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/ - return re.test(phone) + const re = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/; + return re.test(phone); } /** * 验证一定范围内的非负整数 */ export function validateIntPlus(value, min, max) { - const re = /^\d+$/ + const re = /^\d+$/; if (re.test(value)) { - const data = parseInt(value) + const data = parseInt(value); if (data > max || data < min) { - return false + return false; } - return true + return true; } else { - return false + return false; } } /** * 验证一定范围内的非负小数 */ export function validateFloatPlus(value, min, max) { - const re = /^\d+(\.\d+)?$/ + const re = /^\d+(\.\d+)?$/; if (re.test(value)) { - const data = parseFloat(value) + const data = parseFloat(value); if (data > max || data < min) { - return false + return false; } else { - return true + return true; } } else { - return false + return false; } } + +// 提取url params参数 +export function queryString(str) { + const params = str.split('?')[1] // 截取?号后的字符串即name=itclanCoder&study=css + const param = params.split('&') // 通过&符号进行分割即["name=itclanCoder", "study=css"] + const obj = {} // 用一个对象存储目标值 + for (let i = 0; i < param.length; i++) { + // 循环遍历截取出来的param数组 + const paramsA = param[i].split('=') // 通过split,=继续对数组params每一项进行分割,生成数组["name", "itclanCoder"] + const key = paramsA[0] // 取数组项["name", "itclanCoder"]中第0位,即name + const value = paramsA[1] // 取数组项["name", "itclanCoder"]中第1位,即itclanCoder + obj[key] = value + } + return obj +} +// 去除字符串中的特殊符号 +export function stripscript(s) { + var pattern = /[[\]\/:*?"<>|#]/ + var rs = '' + for (var i = 0; i < s.length; i++) { + rs = rs + s.substr(i, 1).replace(pattern, '') + } + return rs +} + +export function extractURLParameters(url) { + const params = new URLSearchParams(url.split('?')[1]); + return Array.from(params.entries()).reduce((acc, [key, value]) => { + acc[key] = value; + return acc; + }, {}); +} diff --git a/src/views/system/resource/editResource.vue b/src/views/system/resource/editResource.vue index 2a22a73..acfc6b5 100644 --- a/src/views/system/resource/editResource.vue +++ b/src/views/system/resource/editResource.vue @@ -152,7 +152,7 @@ resourceType: row.resourceType, num: row.num, icon: row.icon, - tips:row.tips + tips: row.tips } } }, @@ -187,7 +187,7 @@ resourceType: '', num: '', icon: '', - tips:'' + tips: '' } }, // 保存数据 diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/package.json b/package.json index e687665..c966921 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "vue-template-compiler": "2.5.17", "webpack": "4.16.5", "webpack-bundle-analyzer": "^3.4.1", - "webpack-cli": "3.1.0", + "webpack-cli": "^3.1.0", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, diff --git a/src/api/system/user.js b/src/api/system/user.js index 91e7aa7..f470dbd 100644 --- a/src/api/system/user.js +++ b/src/api/system/user.js @@ -113,3 +113,20 @@ } }) } + +// 单点登录获取token +export function fetchToken(params) { + return request({ + url: 'platform/checkZFToken', + method: 'get', + params + }) +} +// 同步用户 +export function syncUser(data) { + return request({ + url: 'ssoUser/syncUser', + method: 'post', + data + }) +} diff --git a/src/components/Map/MarsMap.vue b/src/components/Map/MarsMap.vue index c400842..893e665 100644 --- a/src/components/Map/MarsMap.vue +++ b/src/components/Map/MarsMap.vue @@ -9,7 +9,7 @@ diff --git a/src/layout/LayoutApp.vue b/src/layout/LayoutApp.vue index 81db434..ae5731a 100644 --- a/src/layout/LayoutApp.vue +++ b/src/layout/LayoutApp.vue @@ -30,7 +30,7 @@ this.title = this.$route.query.name this.url = this.$route.query.url } - if(this.baseConfig.toDashboard===false){ + if (this.baseConfig.toDashboard===false){ this.showBack = false } }, diff --git a/src/main.js b/src/main.js index fd1d17e..7568b6e 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,9 @@ +console.log('==============main.js===============') import Vue from 'vue' import 'normalize.css/normalize.css' // A modern alternative to CSS resets import '../theme/index.css' // 引入自定义主题 import ElementUI from 'element-ui' -// import 'element-ui/lib/theme-chalk/index.css' +import 'element-ui/lib/theme-chalk/index.css' import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n import '@/styles/index.scss' // global css diff --git a/src/permission.js b/src/permission.js index c4f95f2..55bd751 100644 --- a/src/permission.js +++ b/src/permission.js @@ -4,8 +4,11 @@ import 'nprogress/nprogress.css' // progress bar style 进度条样式 import { Message } from 'element-ui' import { getToken } from '@/utils/auth' // getToken from cookie +import axios from 'axios' import { getCurrentSys } from './utils/auth' import Vue from 'vue' +import { extractURLParameters } from '@/utils/validate' +import { fetchToken } from '@/api/system/user' NProgress.configure({ showSpinner: false })// NProgress configuration @@ -83,23 +86,65 @@ console.log('is In WhiteList') next() } else { + debugger // 获取链接里的token const token = to.query.token - console.log('token' + to.query.token) - if (token) { - // 调用自动登录接口,否则跳转到登录页 - store.dispatch('AppLogin', token).then(() => { - console.log('自动登录成功') - console.log(to.path) - next({ ...to, replace: true }) // 登录成功继续 - }).catch(() => { - next('/401') // 否则全部重定向到401没有权限页面 + console.log('token' + token) + // // 携带token 需要去掉 + // const zfToken = to.query['ZF-TOKEN'] + let zfToken = '' + // 携带token 需要去掉 + const hrefIdx = window.location.href.indexOf('ZF-TOKEN') // url中是否携带token + if (hrefIdx > -1) { + // const params = queryString(window.location.href) + // zfToken = stripscript(params.token) + console.log('hrefIdx', extractURLParameters(window.location.href)) + const params = extractURLParameters(window.location.href) + zfToken = params['ZF-TOKEN'] + } + console.log('zfToken' + zfToken) + if (zfToken) { + const sendParams = { + zf_token: zfToken + } + // eslint-disable-next-line no-unused-vars + debugger + // window.location.href = 'https://www.baidu.com/?tn=25017023_17_dg' + fetchToken(sendParams).then((resToken) => { + if (resToken.code === 200) { + axios.get('./static/project.config.json').then((result) => { + const params = '?token=' + resToken.data.token + '&url=' + result.data.singleSignLastUrl + const loginUrl = result.data.singleSignFirstUrl + '/sso/integrationConfig/login' + // next({ + // path: '/appSubject', + // query: { name: resToken.data.title, url: loginUrl + params } + // }) + // window.open(loginUrl + params, '_blank') + window.location.href = loginUrl + params + }) + } else { + console.log('用户验证失败') + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } }) } else { - if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { - next(`/applogin`) // 否则全部重定向到登录页 + debugger + if (token) { + // 调用自动登录接口,否则跳转到登录页 + const params = token + store.dispatch('AppLogin', params).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) } else { - next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } } } NProgress.done() diff --git a/src/permissionBak.js b/src/permissionBak.js new file mode 100644 index 0000000..ba87122 --- /dev/null +++ b/src/permissionBak.js @@ -0,0 +1,103 @@ +import router from './router' +import store from './store' +import NProgress from 'nprogress' // progress bar 进度条 +import 'nprogress/nprogress.css' // progress bar style 进度条样式 +import { Message } from 'element-ui' +import { getToken } from '@/utils/auth' // getToken from cookie +import { getCurrentSys } from './utils/auth' + +NProgress.configure({ showSpinner: false })// NProgress configuration + +const whiteList = ['/login', '/applogin', '/appFaceLogin', '/404', 'config/baseconfig', '/full/storageTopic', '/full/waterThreat', '/full/highConsequence', '/full/constructionThreat', '/full/routeTopic', '/full/waterThreat', '/full/sinkThreat', '/full/vip', '/full/weather', '/full/needTopic', '/full/supplyTopic', '/full/pipeOverview', '/full/overview'] // 不重定向白名单 +// 全局钩子 +router.beforeEach((to, from, next) => { + NProgress.start() // 加载进度条 + console.log('to Path:' + to.path) + // 如果有token + if (getToken()) { + console.log('hasToken') + // 登录后进入登录页 + if (to.path === '/login') { + next({ path: '/login' }) + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else if (to.path === '/dashboard') { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next('/appIndex') // 否则全部重定向到登录页 + } else { + next() + } + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else { + // 当进入非登陆页或非主页时 + if (store.getters.roleList.length === 0) { // 判断当前用户是否已拉取完user_info信息 + store.dispatch('GetInfo').then(res => { // 拉取用户信息 + let currentSys = getCurrentSys() + // 根据路由去找当前子系统 + if (to.query.sys) { + currentSys = { + code: to.query.code, + name: to.query.sys, + url: to.query.url + } + // 将当前系统信息保存在localStorage中 + store.commit('SET_SYSTEM', currentSys) + } + // 如果已有当前可进入的子系统,刷新子系统菜单 + if (currentSys) { + console.log('hasCurrentSystem') + // 远程访问获取权限列表(菜单&按钮) + store.dispatch('GetMenus', currentSys).then(() => { + store.commit('SET_CHANGEFLAG', '0') + // 获取所有地址列表 + router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表 + // 判断路由是否被允许,不允许则重定向 + next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record + }) + } else { // 没有当前子系统信息,跳转到选择子系统页面 + console.log('dontHasCurrentSystem') + next({ path: '/dashboard' }) + } + }).catch((err) => { + console.log('toFedLogOut') + store.dispatch('FedLogOut').then(() => { + Message.error(err || '权限验证失败,请重新登录系统') + next({ path: '/' }) + }) + }) + } else { + // TODO: 判断路由是否被允许,不允许则重定向 + next() + } + } + } else { + if (whiteList.indexOf(to.path) !== -1) { // 免登录白名单,直接进入 + console.log('is In WhiteList') + next() + } else { + // 获取链接里的token + const token = to.query.token + console.log('token' + to.query.token) + if (token) { + // 调用自动登录接口,否则跳转到登录页 + store.dispatch('AppLogin', token).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) + } else { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } + } + NProgress.done() + } + } +}) + +router.afterEach(() => { + NProgress.done() // 结束Progress +}) diff --git a/src/utils/validate.js b/src/utils/validate.js index d7e84e4..52736af 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -7,35 +7,35 @@ * 未知用途 */ export function isExternal(path) { - return /^(https?:|mailto:|tel:)/.test(path) + return /^(https?:|mailto:|tel:)/.test(path); } /* 合法uri*/ export function validateURL(textval) { - const urlregex = /^(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 urlregex.test(textval) + const urlregex = /^(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 urlregex.test(textval); } /* 合法uri*/ export function validateNull(textval) { - return !!textval + return !!textval; } /* 验证小写字母*/ export function validateLowerCase(str) { - const reg = /^[a-z]+$/ - return reg.test(str) + const reg = /^[a-z]+$/; + return reg.test(str); } /* 验证大写字母*/ export function validateUpperCase(str) { - const reg = /^[A-Z]+$/ - return reg.test(str) + const reg = /^[A-Z]+$/; + return reg.test(str); } /* 验证大小写字母*/ export function validateAlphabets(str) { - const reg = /^[A-Za-z]+$/ - return reg.test(str) + const reg = /^[A-Za-z]+$/; + return reg.test(str); } /** @@ -44,8 +44,8 @@ * @returns {boolean} */ export function validateEmail(email) { - const re = /^(([^<>()\[\]\\.,;:\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 re.test(email) + const re = /^(([^<>()\[\]\\.,;:\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 re.test(email); } /** @@ -54,38 +54,70 @@ * @returns {boolean} */ export function validatePhone(phone) { - const re = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/ - return re.test(phone) + const re = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/; + return re.test(phone); } /** * 验证一定范围内的非负整数 */ export function validateIntPlus(value, min, max) { - const re = /^\d+$/ + const re = /^\d+$/; if (re.test(value)) { - const data = parseInt(value) + const data = parseInt(value); if (data > max || data < min) { - return false + return false; } - return true + return true; } else { - return false + return false; } } /** * 验证一定范围内的非负小数 */ export function validateFloatPlus(value, min, max) { - const re = /^\d+(\.\d+)?$/ + const re = /^\d+(\.\d+)?$/; if (re.test(value)) { - const data = parseFloat(value) + const data = parseFloat(value); if (data > max || data < min) { - return false + return false; } else { - return true + return true; } } else { - return false + return false; } } + +// 提取url params参数 +export function queryString(str) { + const params = str.split('?')[1] // 截取?号后的字符串即name=itclanCoder&study=css + const param = params.split('&') // 通过&符号进行分割即["name=itclanCoder", "study=css"] + const obj = {} // 用一个对象存储目标值 + for (let i = 0; i < param.length; i++) { + // 循环遍历截取出来的param数组 + const paramsA = param[i].split('=') // 通过split,=继续对数组params每一项进行分割,生成数组["name", "itclanCoder"] + const key = paramsA[0] // 取数组项["name", "itclanCoder"]中第0位,即name + const value = paramsA[1] // 取数组项["name", "itclanCoder"]中第1位,即itclanCoder + obj[key] = value + } + return obj +} +// 去除字符串中的特殊符号 +export function stripscript(s) { + var pattern = /[[\]\/:*?"<>|#]/ + var rs = '' + for (var i = 0; i < s.length; i++) { + rs = rs + s.substr(i, 1).replace(pattern, '') + } + return rs +} + +export function extractURLParameters(url) { + const params = new URLSearchParams(url.split('?')[1]); + return Array.from(params.entries()).reduce((acc, [key, value]) => { + acc[key] = value; + return acc; + }, {}); +} diff --git a/src/views/system/resource/editResource.vue b/src/views/system/resource/editResource.vue index 2a22a73..acfc6b5 100644 --- a/src/views/system/resource/editResource.vue +++ b/src/views/system/resource/editResource.vue @@ -152,7 +152,7 @@ resourceType: row.resourceType, num: row.num, icon: row.icon, - tips:row.tips + tips: row.tips } } }, @@ -187,7 +187,7 @@ resourceType: '', num: '', icon: '', - tips:'' + tips: '' } }, // 保存数据 diff --git a/src/views/system/role/editRole.vue b/src/views/system/role/editRole.vue index 0c2a54b..cc48cf3 100644 --- a/src/views/system/role/editRole.vue +++ b/src/views/system/role/editRole.vue @@ -170,7 +170,7 @@ pids: '', num: 99, tips: '', - dataScopeType:'', + dataScopeType: '', version: '' } }, diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/package.json b/package.json index e687665..c966921 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "vue-template-compiler": "2.5.17", "webpack": "4.16.5", "webpack-bundle-analyzer": "^3.4.1", - "webpack-cli": "3.1.0", + "webpack-cli": "^3.1.0", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, diff --git a/src/api/system/user.js b/src/api/system/user.js index 91e7aa7..f470dbd 100644 --- a/src/api/system/user.js +++ b/src/api/system/user.js @@ -113,3 +113,20 @@ } }) } + +// 单点登录获取token +export function fetchToken(params) { + return request({ + url: 'platform/checkZFToken', + method: 'get', + params + }) +} +// 同步用户 +export function syncUser(data) { + return request({ + url: 'ssoUser/syncUser', + method: 'post', + data + }) +} diff --git a/src/components/Map/MarsMap.vue b/src/components/Map/MarsMap.vue index c400842..893e665 100644 --- a/src/components/Map/MarsMap.vue +++ b/src/components/Map/MarsMap.vue @@ -9,7 +9,7 @@ diff --git a/src/layout/LayoutApp.vue b/src/layout/LayoutApp.vue index 81db434..ae5731a 100644 --- a/src/layout/LayoutApp.vue +++ b/src/layout/LayoutApp.vue @@ -30,7 +30,7 @@ this.title = this.$route.query.name this.url = this.$route.query.url } - if(this.baseConfig.toDashboard===false){ + if (this.baseConfig.toDashboard===false){ this.showBack = false } }, diff --git a/src/main.js b/src/main.js index fd1d17e..7568b6e 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,9 @@ +console.log('==============main.js===============') import Vue from 'vue' import 'normalize.css/normalize.css' // A modern alternative to CSS resets import '../theme/index.css' // 引入自定义主题 import ElementUI from 'element-ui' -// import 'element-ui/lib/theme-chalk/index.css' +import 'element-ui/lib/theme-chalk/index.css' import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n import '@/styles/index.scss' // global css diff --git a/src/permission.js b/src/permission.js index c4f95f2..55bd751 100644 --- a/src/permission.js +++ b/src/permission.js @@ -4,8 +4,11 @@ import 'nprogress/nprogress.css' // progress bar style 进度条样式 import { Message } from 'element-ui' import { getToken } from '@/utils/auth' // getToken from cookie +import axios from 'axios' import { getCurrentSys } from './utils/auth' import Vue from 'vue' +import { extractURLParameters } from '@/utils/validate' +import { fetchToken } from '@/api/system/user' NProgress.configure({ showSpinner: false })// NProgress configuration @@ -83,23 +86,65 @@ console.log('is In WhiteList') next() } else { + debugger // 获取链接里的token const token = to.query.token - console.log('token' + to.query.token) - if (token) { - // 调用自动登录接口,否则跳转到登录页 - store.dispatch('AppLogin', token).then(() => { - console.log('自动登录成功') - console.log(to.path) - next({ ...to, replace: true }) // 登录成功继续 - }).catch(() => { - next('/401') // 否则全部重定向到401没有权限页面 + console.log('token' + token) + // // 携带token 需要去掉 + // const zfToken = to.query['ZF-TOKEN'] + let zfToken = '' + // 携带token 需要去掉 + const hrefIdx = window.location.href.indexOf('ZF-TOKEN') // url中是否携带token + if (hrefIdx > -1) { + // const params = queryString(window.location.href) + // zfToken = stripscript(params.token) + console.log('hrefIdx', extractURLParameters(window.location.href)) + const params = extractURLParameters(window.location.href) + zfToken = params['ZF-TOKEN'] + } + console.log('zfToken' + zfToken) + if (zfToken) { + const sendParams = { + zf_token: zfToken + } + // eslint-disable-next-line no-unused-vars + debugger + // window.location.href = 'https://www.baidu.com/?tn=25017023_17_dg' + fetchToken(sendParams).then((resToken) => { + if (resToken.code === 200) { + axios.get('./static/project.config.json').then((result) => { + const params = '?token=' + resToken.data.token + '&url=' + result.data.singleSignLastUrl + const loginUrl = result.data.singleSignFirstUrl + '/sso/integrationConfig/login' + // next({ + // path: '/appSubject', + // query: { name: resToken.data.title, url: loginUrl + params } + // }) + // window.open(loginUrl + params, '_blank') + window.location.href = loginUrl + params + }) + } else { + console.log('用户验证失败') + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } }) } else { - if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { - next(`/applogin`) // 否则全部重定向到登录页 + debugger + if (token) { + // 调用自动登录接口,否则跳转到登录页 + const params = token + store.dispatch('AppLogin', params).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) } else { - next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } } } NProgress.done() diff --git a/src/permissionBak.js b/src/permissionBak.js new file mode 100644 index 0000000..ba87122 --- /dev/null +++ b/src/permissionBak.js @@ -0,0 +1,103 @@ +import router from './router' +import store from './store' +import NProgress from 'nprogress' // progress bar 进度条 +import 'nprogress/nprogress.css' // progress bar style 进度条样式 +import { Message } from 'element-ui' +import { getToken } from '@/utils/auth' // getToken from cookie +import { getCurrentSys } from './utils/auth' + +NProgress.configure({ showSpinner: false })// NProgress configuration + +const whiteList = ['/login', '/applogin', '/appFaceLogin', '/404', 'config/baseconfig', '/full/storageTopic', '/full/waterThreat', '/full/highConsequence', '/full/constructionThreat', '/full/routeTopic', '/full/waterThreat', '/full/sinkThreat', '/full/vip', '/full/weather', '/full/needTopic', '/full/supplyTopic', '/full/pipeOverview', '/full/overview'] // 不重定向白名单 +// 全局钩子 +router.beforeEach((to, from, next) => { + NProgress.start() // 加载进度条 + console.log('to Path:' + to.path) + // 如果有token + if (getToken()) { + console.log('hasToken') + // 登录后进入登录页 + if (to.path === '/login') { + next({ path: '/login' }) + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else if (to.path === '/dashboard') { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next('/appIndex') // 否则全部重定向到登录页 + } else { + next() + } + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else { + // 当进入非登陆页或非主页时 + if (store.getters.roleList.length === 0) { // 判断当前用户是否已拉取完user_info信息 + store.dispatch('GetInfo').then(res => { // 拉取用户信息 + let currentSys = getCurrentSys() + // 根据路由去找当前子系统 + if (to.query.sys) { + currentSys = { + code: to.query.code, + name: to.query.sys, + url: to.query.url + } + // 将当前系统信息保存在localStorage中 + store.commit('SET_SYSTEM', currentSys) + } + // 如果已有当前可进入的子系统,刷新子系统菜单 + if (currentSys) { + console.log('hasCurrentSystem') + // 远程访问获取权限列表(菜单&按钮) + store.dispatch('GetMenus', currentSys).then(() => { + store.commit('SET_CHANGEFLAG', '0') + // 获取所有地址列表 + router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表 + // 判断路由是否被允许,不允许则重定向 + next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record + }) + } else { // 没有当前子系统信息,跳转到选择子系统页面 + console.log('dontHasCurrentSystem') + next({ path: '/dashboard' }) + } + }).catch((err) => { + console.log('toFedLogOut') + store.dispatch('FedLogOut').then(() => { + Message.error(err || '权限验证失败,请重新登录系统') + next({ path: '/' }) + }) + }) + } else { + // TODO: 判断路由是否被允许,不允许则重定向 + next() + } + } + } else { + if (whiteList.indexOf(to.path) !== -1) { // 免登录白名单,直接进入 + console.log('is In WhiteList') + next() + } else { + // 获取链接里的token + const token = to.query.token + console.log('token' + to.query.token) + if (token) { + // 调用自动登录接口,否则跳转到登录页 + store.dispatch('AppLogin', token).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) + } else { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } + } + NProgress.done() + } + } +}) + +router.afterEach(() => { + NProgress.done() // 结束Progress +}) diff --git a/src/utils/validate.js b/src/utils/validate.js index d7e84e4..52736af 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -7,35 +7,35 @@ * 未知用途 */ export function isExternal(path) { - return /^(https?:|mailto:|tel:)/.test(path) + return /^(https?:|mailto:|tel:)/.test(path); } /* 合法uri*/ export function validateURL(textval) { - const urlregex = /^(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 urlregex.test(textval) + const urlregex = /^(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 urlregex.test(textval); } /* 合法uri*/ export function validateNull(textval) { - return !!textval + return !!textval; } /* 验证小写字母*/ export function validateLowerCase(str) { - const reg = /^[a-z]+$/ - return reg.test(str) + const reg = /^[a-z]+$/; + return reg.test(str); } /* 验证大写字母*/ export function validateUpperCase(str) { - const reg = /^[A-Z]+$/ - return reg.test(str) + const reg = /^[A-Z]+$/; + return reg.test(str); } /* 验证大小写字母*/ export function validateAlphabets(str) { - const reg = /^[A-Za-z]+$/ - return reg.test(str) + const reg = /^[A-Za-z]+$/; + return reg.test(str); } /** @@ -44,8 +44,8 @@ * @returns {boolean} */ export function validateEmail(email) { - const re = /^(([^<>()\[\]\\.,;:\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 re.test(email) + const re = /^(([^<>()\[\]\\.,;:\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 re.test(email); } /** @@ -54,38 +54,70 @@ * @returns {boolean} */ export function validatePhone(phone) { - const re = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/ - return re.test(phone) + const re = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/; + return re.test(phone); } /** * 验证一定范围内的非负整数 */ export function validateIntPlus(value, min, max) { - const re = /^\d+$/ + const re = /^\d+$/; if (re.test(value)) { - const data = parseInt(value) + const data = parseInt(value); if (data > max || data < min) { - return false + return false; } - return true + return true; } else { - return false + return false; } } /** * 验证一定范围内的非负小数 */ export function validateFloatPlus(value, min, max) { - const re = /^\d+(\.\d+)?$/ + const re = /^\d+(\.\d+)?$/; if (re.test(value)) { - const data = parseFloat(value) + const data = parseFloat(value); if (data > max || data < min) { - return false + return false; } else { - return true + return true; } } else { - return false + return false; } } + +// 提取url params参数 +export function queryString(str) { + const params = str.split('?')[1] // 截取?号后的字符串即name=itclanCoder&study=css + const param = params.split('&') // 通过&符号进行分割即["name=itclanCoder", "study=css"] + const obj = {} // 用一个对象存储目标值 + for (let i = 0; i < param.length; i++) { + // 循环遍历截取出来的param数组 + const paramsA = param[i].split('=') // 通过split,=继续对数组params每一项进行分割,生成数组["name", "itclanCoder"] + const key = paramsA[0] // 取数组项["name", "itclanCoder"]中第0位,即name + const value = paramsA[1] // 取数组项["name", "itclanCoder"]中第1位,即itclanCoder + obj[key] = value + } + return obj +} +// 去除字符串中的特殊符号 +export function stripscript(s) { + var pattern = /[[\]\/:*?"<>|#]/ + var rs = '' + for (var i = 0; i < s.length; i++) { + rs = rs + s.substr(i, 1).replace(pattern, '') + } + return rs +} + +export function extractURLParameters(url) { + const params = new URLSearchParams(url.split('?')[1]); + return Array.from(params.entries()).reduce((acc, [key, value]) => { + acc[key] = value; + return acc; + }, {}); +} diff --git a/src/views/system/resource/editResource.vue b/src/views/system/resource/editResource.vue index 2a22a73..acfc6b5 100644 --- a/src/views/system/resource/editResource.vue +++ b/src/views/system/resource/editResource.vue @@ -152,7 +152,7 @@ resourceType: row.resourceType, num: row.num, icon: row.icon, - tips:row.tips + tips: row.tips } } }, @@ -187,7 +187,7 @@ resourceType: '', num: '', icon: '', - tips:'' + tips: '' } }, // 保存数据 diff --git a/src/views/system/role/editRole.vue b/src/views/system/role/editRole.vue index 0c2a54b..cc48cf3 100644 --- a/src/views/system/role/editRole.vue +++ b/src/views/system/role/editRole.vue @@ -170,7 +170,7 @@ pids: '', num: 99, tips: '', - dataScopeType:'', + dataScopeType: '', version: '' } }, diff --git a/src/views/system/user/editUser.vue b/src/views/system/user/editUser.vue index 9b1ee73..77af02e 100644 --- a/src/views/system/user/editUser.vue +++ b/src/views/system/user/editUser.vue @@ -180,8 +180,8 @@ message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }], phone: [{ - required: false, - pattern: /^1[34578]\d{9}$/, // 可以写正则表达式呦呦呦 + required: true, + pattern: /^1[3456789]\d{9}$/, // 可以写正则表达式呦呦呦 message: '请输入正确的手机号', trigger: ['blur', 'change'] }] }, // 前端校验规则 diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/package.json b/package.json index e687665..c966921 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "vue-template-compiler": "2.5.17", "webpack": "4.16.5", "webpack-bundle-analyzer": "^3.4.1", - "webpack-cli": "3.1.0", + "webpack-cli": "^3.1.0", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, diff --git a/src/api/system/user.js b/src/api/system/user.js index 91e7aa7..f470dbd 100644 --- a/src/api/system/user.js +++ b/src/api/system/user.js @@ -113,3 +113,20 @@ } }) } + +// 单点登录获取token +export function fetchToken(params) { + return request({ + url: 'platform/checkZFToken', + method: 'get', + params + }) +} +// 同步用户 +export function syncUser(data) { + return request({ + url: 'ssoUser/syncUser', + method: 'post', + data + }) +} diff --git a/src/components/Map/MarsMap.vue b/src/components/Map/MarsMap.vue index c400842..893e665 100644 --- a/src/components/Map/MarsMap.vue +++ b/src/components/Map/MarsMap.vue @@ -9,7 +9,7 @@ diff --git a/src/layout/LayoutApp.vue b/src/layout/LayoutApp.vue index 81db434..ae5731a 100644 --- a/src/layout/LayoutApp.vue +++ b/src/layout/LayoutApp.vue @@ -30,7 +30,7 @@ this.title = this.$route.query.name this.url = this.$route.query.url } - if(this.baseConfig.toDashboard===false){ + if (this.baseConfig.toDashboard===false){ this.showBack = false } }, diff --git a/src/main.js b/src/main.js index fd1d17e..7568b6e 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,9 @@ +console.log('==============main.js===============') import Vue from 'vue' import 'normalize.css/normalize.css' // A modern alternative to CSS resets import '../theme/index.css' // 引入自定义主题 import ElementUI from 'element-ui' -// import 'element-ui/lib/theme-chalk/index.css' +import 'element-ui/lib/theme-chalk/index.css' import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n import '@/styles/index.scss' // global css diff --git a/src/permission.js b/src/permission.js index c4f95f2..55bd751 100644 --- a/src/permission.js +++ b/src/permission.js @@ -4,8 +4,11 @@ import 'nprogress/nprogress.css' // progress bar style 进度条样式 import { Message } from 'element-ui' import { getToken } from '@/utils/auth' // getToken from cookie +import axios from 'axios' import { getCurrentSys } from './utils/auth' import Vue from 'vue' +import { extractURLParameters } from '@/utils/validate' +import { fetchToken } from '@/api/system/user' NProgress.configure({ showSpinner: false })// NProgress configuration @@ -83,23 +86,65 @@ console.log('is In WhiteList') next() } else { + debugger // 获取链接里的token const token = to.query.token - console.log('token' + to.query.token) - if (token) { - // 调用自动登录接口,否则跳转到登录页 - store.dispatch('AppLogin', token).then(() => { - console.log('自动登录成功') - console.log(to.path) - next({ ...to, replace: true }) // 登录成功继续 - }).catch(() => { - next('/401') // 否则全部重定向到401没有权限页面 + console.log('token' + token) + // // 携带token 需要去掉 + // const zfToken = to.query['ZF-TOKEN'] + let zfToken = '' + // 携带token 需要去掉 + const hrefIdx = window.location.href.indexOf('ZF-TOKEN') // url中是否携带token + if (hrefIdx > -1) { + // const params = queryString(window.location.href) + // zfToken = stripscript(params.token) + console.log('hrefIdx', extractURLParameters(window.location.href)) + const params = extractURLParameters(window.location.href) + zfToken = params['ZF-TOKEN'] + } + console.log('zfToken' + zfToken) + if (zfToken) { + const sendParams = { + zf_token: zfToken + } + // eslint-disable-next-line no-unused-vars + debugger + // window.location.href = 'https://www.baidu.com/?tn=25017023_17_dg' + fetchToken(sendParams).then((resToken) => { + if (resToken.code === 200) { + axios.get('./static/project.config.json').then((result) => { + const params = '?token=' + resToken.data.token + '&url=' + result.data.singleSignLastUrl + const loginUrl = result.data.singleSignFirstUrl + '/sso/integrationConfig/login' + // next({ + // path: '/appSubject', + // query: { name: resToken.data.title, url: loginUrl + params } + // }) + // window.open(loginUrl + params, '_blank') + window.location.href = loginUrl + params + }) + } else { + console.log('用户验证失败') + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } }) } else { - if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { - next(`/applogin`) // 否则全部重定向到登录页 + debugger + if (token) { + // 调用自动登录接口,否则跳转到登录页 + const params = token + store.dispatch('AppLogin', params).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) } else { - next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } } } NProgress.done() diff --git a/src/permissionBak.js b/src/permissionBak.js new file mode 100644 index 0000000..ba87122 --- /dev/null +++ b/src/permissionBak.js @@ -0,0 +1,103 @@ +import router from './router' +import store from './store' +import NProgress from 'nprogress' // progress bar 进度条 +import 'nprogress/nprogress.css' // progress bar style 进度条样式 +import { Message } from 'element-ui' +import { getToken } from '@/utils/auth' // getToken from cookie +import { getCurrentSys } from './utils/auth' + +NProgress.configure({ showSpinner: false })// NProgress configuration + +const whiteList = ['/login', '/applogin', '/appFaceLogin', '/404', 'config/baseconfig', '/full/storageTopic', '/full/waterThreat', '/full/highConsequence', '/full/constructionThreat', '/full/routeTopic', '/full/waterThreat', '/full/sinkThreat', '/full/vip', '/full/weather', '/full/needTopic', '/full/supplyTopic', '/full/pipeOverview', '/full/overview'] // 不重定向白名单 +// 全局钩子 +router.beforeEach((to, from, next) => { + NProgress.start() // 加载进度条 + console.log('to Path:' + to.path) + // 如果有token + if (getToken()) { + console.log('hasToken') + // 登录后进入登录页 + if (to.path === '/login') { + next({ path: '/login' }) + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else if (to.path === '/dashboard') { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next('/appIndex') // 否则全部重定向到登录页 + } else { + next() + } + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else { + // 当进入非登陆页或非主页时 + if (store.getters.roleList.length === 0) { // 判断当前用户是否已拉取完user_info信息 + store.dispatch('GetInfo').then(res => { // 拉取用户信息 + let currentSys = getCurrentSys() + // 根据路由去找当前子系统 + if (to.query.sys) { + currentSys = { + code: to.query.code, + name: to.query.sys, + url: to.query.url + } + // 将当前系统信息保存在localStorage中 + store.commit('SET_SYSTEM', currentSys) + } + // 如果已有当前可进入的子系统,刷新子系统菜单 + if (currentSys) { + console.log('hasCurrentSystem') + // 远程访问获取权限列表(菜单&按钮) + store.dispatch('GetMenus', currentSys).then(() => { + store.commit('SET_CHANGEFLAG', '0') + // 获取所有地址列表 + router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表 + // 判断路由是否被允许,不允许则重定向 + next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record + }) + } else { // 没有当前子系统信息,跳转到选择子系统页面 + console.log('dontHasCurrentSystem') + next({ path: '/dashboard' }) + } + }).catch((err) => { + console.log('toFedLogOut') + store.dispatch('FedLogOut').then(() => { + Message.error(err || '权限验证失败,请重新登录系统') + next({ path: '/' }) + }) + }) + } else { + // TODO: 判断路由是否被允许,不允许则重定向 + next() + } + } + } else { + if (whiteList.indexOf(to.path) !== -1) { // 免登录白名单,直接进入 + console.log('is In WhiteList') + next() + } else { + // 获取链接里的token + const token = to.query.token + console.log('token' + to.query.token) + if (token) { + // 调用自动登录接口,否则跳转到登录页 + store.dispatch('AppLogin', token).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) + } else { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } + } + NProgress.done() + } + } +}) + +router.afterEach(() => { + NProgress.done() // 结束Progress +}) diff --git a/src/utils/validate.js b/src/utils/validate.js index d7e84e4..52736af 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -7,35 +7,35 @@ * 未知用途 */ export function isExternal(path) { - return /^(https?:|mailto:|tel:)/.test(path) + return /^(https?:|mailto:|tel:)/.test(path); } /* 合法uri*/ export function validateURL(textval) { - const urlregex = /^(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 urlregex.test(textval) + const urlregex = /^(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 urlregex.test(textval); } /* 合法uri*/ export function validateNull(textval) { - return !!textval + return !!textval; } /* 验证小写字母*/ export function validateLowerCase(str) { - const reg = /^[a-z]+$/ - return reg.test(str) + const reg = /^[a-z]+$/; + return reg.test(str); } /* 验证大写字母*/ export function validateUpperCase(str) { - const reg = /^[A-Z]+$/ - return reg.test(str) + const reg = /^[A-Z]+$/; + return reg.test(str); } /* 验证大小写字母*/ export function validateAlphabets(str) { - const reg = /^[A-Za-z]+$/ - return reg.test(str) + const reg = /^[A-Za-z]+$/; + return reg.test(str); } /** @@ -44,8 +44,8 @@ * @returns {boolean} */ export function validateEmail(email) { - const re = /^(([^<>()\[\]\\.,;:\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 re.test(email) + const re = /^(([^<>()\[\]\\.,;:\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 re.test(email); } /** @@ -54,38 +54,70 @@ * @returns {boolean} */ export function validatePhone(phone) { - const re = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/ - return re.test(phone) + const re = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/; + return re.test(phone); } /** * 验证一定范围内的非负整数 */ export function validateIntPlus(value, min, max) { - const re = /^\d+$/ + const re = /^\d+$/; if (re.test(value)) { - const data = parseInt(value) + const data = parseInt(value); if (data > max || data < min) { - return false + return false; } - return true + return true; } else { - return false + return false; } } /** * 验证一定范围内的非负小数 */ export function validateFloatPlus(value, min, max) { - const re = /^\d+(\.\d+)?$/ + const re = /^\d+(\.\d+)?$/; if (re.test(value)) { - const data = parseFloat(value) + const data = parseFloat(value); if (data > max || data < min) { - return false + return false; } else { - return true + return true; } } else { - return false + return false; } } + +// 提取url params参数 +export function queryString(str) { + const params = str.split('?')[1] // 截取?号后的字符串即name=itclanCoder&study=css + const param = params.split('&') // 通过&符号进行分割即["name=itclanCoder", "study=css"] + const obj = {} // 用一个对象存储目标值 + for (let i = 0; i < param.length; i++) { + // 循环遍历截取出来的param数组 + const paramsA = param[i].split('=') // 通过split,=继续对数组params每一项进行分割,生成数组["name", "itclanCoder"] + const key = paramsA[0] // 取数组项["name", "itclanCoder"]中第0位,即name + const value = paramsA[1] // 取数组项["name", "itclanCoder"]中第1位,即itclanCoder + obj[key] = value + } + return obj +} +// 去除字符串中的特殊符号 +export function stripscript(s) { + var pattern = /[[\]\/:*?"<>|#]/ + var rs = '' + for (var i = 0; i < s.length; i++) { + rs = rs + s.substr(i, 1).replace(pattern, '') + } + return rs +} + +export function extractURLParameters(url) { + const params = new URLSearchParams(url.split('?')[1]); + return Array.from(params.entries()).reduce((acc, [key, value]) => { + acc[key] = value; + return acc; + }, {}); +} diff --git a/src/views/system/resource/editResource.vue b/src/views/system/resource/editResource.vue index 2a22a73..acfc6b5 100644 --- a/src/views/system/resource/editResource.vue +++ b/src/views/system/resource/editResource.vue @@ -152,7 +152,7 @@ resourceType: row.resourceType, num: row.num, icon: row.icon, - tips:row.tips + tips: row.tips } } }, @@ -187,7 +187,7 @@ resourceType: '', num: '', icon: '', - tips:'' + tips: '' } }, // 保存数据 diff --git a/src/views/system/role/editRole.vue b/src/views/system/role/editRole.vue index 0c2a54b..cc48cf3 100644 --- a/src/views/system/role/editRole.vue +++ b/src/views/system/role/editRole.vue @@ -170,7 +170,7 @@ pids: '', num: 99, tips: '', - dataScopeType:'', + dataScopeType: '', version: '' } }, diff --git a/src/views/system/user/editUser.vue b/src/views/system/user/editUser.vue index 9b1ee73..77af02e 100644 --- a/src/views/system/user/editUser.vue +++ b/src/views/system/user/editUser.vue @@ -180,8 +180,8 @@ message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }], phone: [{ - required: false, - pattern: /^1[34578]\d{9}$/, // 可以写正则表达式呦呦呦 + required: true, + pattern: /^1[3456789]\d{9}$/, // 可以写正则表达式呦呦呦 message: '请输入正确的手机号', trigger: ['blur', 'change'] }] }, // 前端校验规则 diff --git a/src/views/system/user/listUser.vue b/src/views/system/user/listUser.vue index 8cfb01c..dcecf1e 100644 --- a/src/views/system/user/listUser.vue +++ b/src/views/system/user/listUser.vue @@ -9,16 +9,9 @@ 组织机构 - + @@ -28,33 +21,38 @@ - + - + - 新增 - 修改 - 删除 - 重置密码 - 角色分配 - 注册人脸 + 新增 + 修改 + 删除 + 重置密码 + 角色分配 + 注册人脸 + 用户同步 - + + + @@ -62,19 +60,21 @@ - + {{ scope.row.statusName }} - {{ btnNames[scope.row.statusName] }} + {{ btnNames[scope.row.statusName] }} - {{ faceReged[scope.row.attr1] }} + {{ faceReged[scope.row.attr1] }} @@ -82,8 +82,8 @@ - - + + @@ -93,7 +93,7 @@ import editUser from '@/views/system/user/editUser' import roleAssign from '@/views/system/user/roleAssign' import RegFace from '@/views/system/user/regFace' -import { getUserList, delUser, freezeUser, unfreezeUser, resetPwd, delFace } from '@/api/system/user' +import { getUserList, delUser, freezeUser, unfreezeUser, resetPwd, delFace, syncUser } from '@/api/system/user' import { getDeptTreeList } from '@/api/system/dept' import { toTreeList } from '@/utils/structure' @@ -177,7 +177,8 @@ roleAssignShow: false, // 角色分配组件是否显示 expandAllNode: true, expandNodeClick: false, - regFaceShow: false + regFaceShow: false, + multipleSelection: [], } }, watch: { @@ -196,6 +197,44 @@ this.fetchData() }, methods: { + // 多选触发方法 + handleSelectionChange(val) { + console.log('selectionChange') + this.multipleSelection = val + }, + // 同步用户 + sync() { + if (!this.multipleSelection.length) { + this.$message({ + message: '请选择要同步的用户', + type: 'warning' + }) + return + } + // 检查用户是否全面(都含有手机号) + if (this.multipleSelection.some(item => !item.phone)) { + const userList = this.multipleSelection.map(item => !item.phone).map(item => item.name) + this.$message({ + message: `用户:${userList.join('、')},缺少手机号,请补充手机号后再进行同步`, + type: 'warning' + }) + return + } + syncUser(this.multipleSelection.map((item) => ({ + userName: item.name, + phone: item.phone + }))).then(res => { + if (response.code === 200) { + this.$message.success('同步成功') + this.multipleSelection = [] + // 清空多选 + this.$refs.normalTable.clearSelection() + } + else { + this.$message.error('同步失败') + } + }) + }, // 打开新增对话框 add() { this.dialogStatus = 'create' @@ -416,35 +455,41 @@ diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/package.json b/package.json index e687665..c966921 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "vue-template-compiler": "2.5.17", "webpack": "4.16.5", "webpack-bundle-analyzer": "^3.4.1", - "webpack-cli": "3.1.0", + "webpack-cli": "^3.1.0", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, diff --git a/src/api/system/user.js b/src/api/system/user.js index 91e7aa7..f470dbd 100644 --- a/src/api/system/user.js +++ b/src/api/system/user.js @@ -113,3 +113,20 @@ } }) } + +// 单点登录获取token +export function fetchToken(params) { + return request({ + url: 'platform/checkZFToken', + method: 'get', + params + }) +} +// 同步用户 +export function syncUser(data) { + return request({ + url: 'ssoUser/syncUser', + method: 'post', + data + }) +} diff --git a/src/components/Map/MarsMap.vue b/src/components/Map/MarsMap.vue index c400842..893e665 100644 --- a/src/components/Map/MarsMap.vue +++ b/src/components/Map/MarsMap.vue @@ -9,7 +9,7 @@ diff --git a/src/layout/LayoutApp.vue b/src/layout/LayoutApp.vue index 81db434..ae5731a 100644 --- a/src/layout/LayoutApp.vue +++ b/src/layout/LayoutApp.vue @@ -30,7 +30,7 @@ this.title = this.$route.query.name this.url = this.$route.query.url } - if(this.baseConfig.toDashboard===false){ + if (this.baseConfig.toDashboard===false){ this.showBack = false } }, diff --git a/src/main.js b/src/main.js index fd1d17e..7568b6e 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,9 @@ +console.log('==============main.js===============') import Vue from 'vue' import 'normalize.css/normalize.css' // A modern alternative to CSS resets import '../theme/index.css' // 引入自定义主题 import ElementUI from 'element-ui' -// import 'element-ui/lib/theme-chalk/index.css' +import 'element-ui/lib/theme-chalk/index.css' import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n import '@/styles/index.scss' // global css diff --git a/src/permission.js b/src/permission.js index c4f95f2..55bd751 100644 --- a/src/permission.js +++ b/src/permission.js @@ -4,8 +4,11 @@ import 'nprogress/nprogress.css' // progress bar style 进度条样式 import { Message } from 'element-ui' import { getToken } from '@/utils/auth' // getToken from cookie +import axios from 'axios' import { getCurrentSys } from './utils/auth' import Vue from 'vue' +import { extractURLParameters } from '@/utils/validate' +import { fetchToken } from '@/api/system/user' NProgress.configure({ showSpinner: false })// NProgress configuration @@ -83,23 +86,65 @@ console.log('is In WhiteList') next() } else { + debugger // 获取链接里的token const token = to.query.token - console.log('token' + to.query.token) - if (token) { - // 调用自动登录接口,否则跳转到登录页 - store.dispatch('AppLogin', token).then(() => { - console.log('自动登录成功') - console.log(to.path) - next({ ...to, replace: true }) // 登录成功继续 - }).catch(() => { - next('/401') // 否则全部重定向到401没有权限页面 + console.log('token' + token) + // // 携带token 需要去掉 + // const zfToken = to.query['ZF-TOKEN'] + let zfToken = '' + // 携带token 需要去掉 + const hrefIdx = window.location.href.indexOf('ZF-TOKEN') // url中是否携带token + if (hrefIdx > -1) { + // const params = queryString(window.location.href) + // zfToken = stripscript(params.token) + console.log('hrefIdx', extractURLParameters(window.location.href)) + const params = extractURLParameters(window.location.href) + zfToken = params['ZF-TOKEN'] + } + console.log('zfToken' + zfToken) + if (zfToken) { + const sendParams = { + zf_token: zfToken + } + // eslint-disable-next-line no-unused-vars + debugger + // window.location.href = 'https://www.baidu.com/?tn=25017023_17_dg' + fetchToken(sendParams).then((resToken) => { + if (resToken.code === 200) { + axios.get('./static/project.config.json').then((result) => { + const params = '?token=' + resToken.data.token + '&url=' + result.data.singleSignLastUrl + const loginUrl = result.data.singleSignFirstUrl + '/sso/integrationConfig/login' + // next({ + // path: '/appSubject', + // query: { name: resToken.data.title, url: loginUrl + params } + // }) + // window.open(loginUrl + params, '_blank') + window.location.href = loginUrl + params + }) + } else { + console.log('用户验证失败') + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } }) } else { - if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { - next(`/applogin`) // 否则全部重定向到登录页 + debugger + if (token) { + // 调用自动登录接口,否则跳转到登录页 + const params = token + store.dispatch('AppLogin', params).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) } else { - next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } } } NProgress.done() diff --git a/src/permissionBak.js b/src/permissionBak.js new file mode 100644 index 0000000..ba87122 --- /dev/null +++ b/src/permissionBak.js @@ -0,0 +1,103 @@ +import router from './router' +import store from './store' +import NProgress from 'nprogress' // progress bar 进度条 +import 'nprogress/nprogress.css' // progress bar style 进度条样式 +import { Message } from 'element-ui' +import { getToken } from '@/utils/auth' // getToken from cookie +import { getCurrentSys } from './utils/auth' + +NProgress.configure({ showSpinner: false })// NProgress configuration + +const whiteList = ['/login', '/applogin', '/appFaceLogin', '/404', 'config/baseconfig', '/full/storageTopic', '/full/waterThreat', '/full/highConsequence', '/full/constructionThreat', '/full/routeTopic', '/full/waterThreat', '/full/sinkThreat', '/full/vip', '/full/weather', '/full/needTopic', '/full/supplyTopic', '/full/pipeOverview', '/full/overview'] // 不重定向白名单 +// 全局钩子 +router.beforeEach((to, from, next) => { + NProgress.start() // 加载进度条 + console.log('to Path:' + to.path) + // 如果有token + if (getToken()) { + console.log('hasToken') + // 登录后进入登录页 + if (to.path === '/login') { + next({ path: '/login' }) + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else if (to.path === '/dashboard') { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next('/appIndex') // 否则全部重定向到登录页 + } else { + next() + } + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else { + // 当进入非登陆页或非主页时 + if (store.getters.roleList.length === 0) { // 判断当前用户是否已拉取完user_info信息 + store.dispatch('GetInfo').then(res => { // 拉取用户信息 + let currentSys = getCurrentSys() + // 根据路由去找当前子系统 + if (to.query.sys) { + currentSys = { + code: to.query.code, + name: to.query.sys, + url: to.query.url + } + // 将当前系统信息保存在localStorage中 + store.commit('SET_SYSTEM', currentSys) + } + // 如果已有当前可进入的子系统,刷新子系统菜单 + if (currentSys) { + console.log('hasCurrentSystem') + // 远程访问获取权限列表(菜单&按钮) + store.dispatch('GetMenus', currentSys).then(() => { + store.commit('SET_CHANGEFLAG', '0') + // 获取所有地址列表 + router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表 + // 判断路由是否被允许,不允许则重定向 + next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record + }) + } else { // 没有当前子系统信息,跳转到选择子系统页面 + console.log('dontHasCurrentSystem') + next({ path: '/dashboard' }) + } + }).catch((err) => { + console.log('toFedLogOut') + store.dispatch('FedLogOut').then(() => { + Message.error(err || '权限验证失败,请重新登录系统') + next({ path: '/' }) + }) + }) + } else { + // TODO: 判断路由是否被允许,不允许则重定向 + next() + } + } + } else { + if (whiteList.indexOf(to.path) !== -1) { // 免登录白名单,直接进入 + console.log('is In WhiteList') + next() + } else { + // 获取链接里的token + const token = to.query.token + console.log('token' + to.query.token) + if (token) { + // 调用自动登录接口,否则跳转到登录页 + store.dispatch('AppLogin', token).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) + } else { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } + } + NProgress.done() + } + } +}) + +router.afterEach(() => { + NProgress.done() // 结束Progress +}) diff --git a/src/utils/validate.js b/src/utils/validate.js index d7e84e4..52736af 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -7,35 +7,35 @@ * 未知用途 */ export function isExternal(path) { - return /^(https?:|mailto:|tel:)/.test(path) + return /^(https?:|mailto:|tel:)/.test(path); } /* 合法uri*/ export function validateURL(textval) { - const urlregex = /^(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 urlregex.test(textval) + const urlregex = /^(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 urlregex.test(textval); } /* 合法uri*/ export function validateNull(textval) { - return !!textval + return !!textval; } /* 验证小写字母*/ export function validateLowerCase(str) { - const reg = /^[a-z]+$/ - return reg.test(str) + const reg = /^[a-z]+$/; + return reg.test(str); } /* 验证大写字母*/ export function validateUpperCase(str) { - const reg = /^[A-Z]+$/ - return reg.test(str) + const reg = /^[A-Z]+$/; + return reg.test(str); } /* 验证大小写字母*/ export function validateAlphabets(str) { - const reg = /^[A-Za-z]+$/ - return reg.test(str) + const reg = /^[A-Za-z]+$/; + return reg.test(str); } /** @@ -44,8 +44,8 @@ * @returns {boolean} */ export function validateEmail(email) { - const re = /^(([^<>()\[\]\\.,;:\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 re.test(email) + const re = /^(([^<>()\[\]\\.,;:\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 re.test(email); } /** @@ -54,38 +54,70 @@ * @returns {boolean} */ export function validatePhone(phone) { - const re = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/ - return re.test(phone) + const re = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/; + return re.test(phone); } /** * 验证一定范围内的非负整数 */ export function validateIntPlus(value, min, max) { - const re = /^\d+$/ + const re = /^\d+$/; if (re.test(value)) { - const data = parseInt(value) + const data = parseInt(value); if (data > max || data < min) { - return false + return false; } - return true + return true; } else { - return false + return false; } } /** * 验证一定范围内的非负小数 */ export function validateFloatPlus(value, min, max) { - const re = /^\d+(\.\d+)?$/ + const re = /^\d+(\.\d+)?$/; if (re.test(value)) { - const data = parseFloat(value) + const data = parseFloat(value); if (data > max || data < min) { - return false + return false; } else { - return true + return true; } } else { - return false + return false; } } + +// 提取url params参数 +export function queryString(str) { + const params = str.split('?')[1] // 截取?号后的字符串即name=itclanCoder&study=css + const param = params.split('&') // 通过&符号进行分割即["name=itclanCoder", "study=css"] + const obj = {} // 用一个对象存储目标值 + for (let i = 0; i < param.length; i++) { + // 循环遍历截取出来的param数组 + const paramsA = param[i].split('=') // 通过split,=继续对数组params每一项进行分割,生成数组["name", "itclanCoder"] + const key = paramsA[0] // 取数组项["name", "itclanCoder"]中第0位,即name + const value = paramsA[1] // 取数组项["name", "itclanCoder"]中第1位,即itclanCoder + obj[key] = value + } + return obj +} +// 去除字符串中的特殊符号 +export function stripscript(s) { + var pattern = /[[\]\/:*?"<>|#]/ + var rs = '' + for (var i = 0; i < s.length; i++) { + rs = rs + s.substr(i, 1).replace(pattern, '') + } + return rs +} + +export function extractURLParameters(url) { + const params = new URLSearchParams(url.split('?')[1]); + return Array.from(params.entries()).reduce((acc, [key, value]) => { + acc[key] = value; + return acc; + }, {}); +} diff --git a/src/views/system/resource/editResource.vue b/src/views/system/resource/editResource.vue index 2a22a73..acfc6b5 100644 --- a/src/views/system/resource/editResource.vue +++ b/src/views/system/resource/editResource.vue @@ -152,7 +152,7 @@ resourceType: row.resourceType, num: row.num, icon: row.icon, - tips:row.tips + tips: row.tips } } }, @@ -187,7 +187,7 @@ resourceType: '', num: '', icon: '', - tips:'' + tips: '' } }, // 保存数据 diff --git a/src/views/system/role/editRole.vue b/src/views/system/role/editRole.vue index 0c2a54b..cc48cf3 100644 --- a/src/views/system/role/editRole.vue +++ b/src/views/system/role/editRole.vue @@ -170,7 +170,7 @@ pids: '', num: 99, tips: '', - dataScopeType:'', + dataScopeType: '', version: '' } }, diff --git a/src/views/system/user/editUser.vue b/src/views/system/user/editUser.vue index 9b1ee73..77af02e 100644 --- a/src/views/system/user/editUser.vue +++ b/src/views/system/user/editUser.vue @@ -180,8 +180,8 @@ message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }], phone: [{ - required: false, - pattern: /^1[34578]\d{9}$/, // 可以写正则表达式呦呦呦 + required: true, + pattern: /^1[3456789]\d{9}$/, // 可以写正则表达式呦呦呦 message: '请输入正确的手机号', trigger: ['blur', 'change'] }] }, // 前端校验规则 diff --git a/src/views/system/user/listUser.vue b/src/views/system/user/listUser.vue index 8cfb01c..dcecf1e 100644 --- a/src/views/system/user/listUser.vue +++ b/src/views/system/user/listUser.vue @@ -9,16 +9,9 @@ 组织机构 - + @@ -28,33 +21,38 @@ - + - + - 新增 - 修改 - 删除 - 重置密码 - 角色分配 - 注册人脸 + 新增 + 修改 + 删除 + 重置密码 + 角色分配 + 注册人脸 + 用户同步 - + + + @@ -62,19 +60,21 @@ - + {{ scope.row.statusName }} - {{ btnNames[scope.row.statusName] }} + {{ btnNames[scope.row.statusName] }} - {{ faceReged[scope.row.attr1] }} + {{ faceReged[scope.row.attr1] }} @@ -82,8 +82,8 @@ - - + + @@ -93,7 +93,7 @@ import editUser from '@/views/system/user/editUser' import roleAssign from '@/views/system/user/roleAssign' import RegFace from '@/views/system/user/regFace' -import { getUserList, delUser, freezeUser, unfreezeUser, resetPwd, delFace } from '@/api/system/user' +import { getUserList, delUser, freezeUser, unfreezeUser, resetPwd, delFace, syncUser } from '@/api/system/user' import { getDeptTreeList } from '@/api/system/dept' import { toTreeList } from '@/utils/structure' @@ -177,7 +177,8 @@ roleAssignShow: false, // 角色分配组件是否显示 expandAllNode: true, expandNodeClick: false, - regFaceShow: false + regFaceShow: false, + multipleSelection: [], } }, watch: { @@ -196,6 +197,44 @@ this.fetchData() }, methods: { + // 多选触发方法 + handleSelectionChange(val) { + console.log('selectionChange') + this.multipleSelection = val + }, + // 同步用户 + sync() { + if (!this.multipleSelection.length) { + this.$message({ + message: '请选择要同步的用户', + type: 'warning' + }) + return + } + // 检查用户是否全面(都含有手机号) + if (this.multipleSelection.some(item => !item.phone)) { + const userList = this.multipleSelection.map(item => !item.phone).map(item => item.name) + this.$message({ + message: `用户:${userList.join('、')},缺少手机号,请补充手机号后再进行同步`, + type: 'warning' + }) + return + } + syncUser(this.multipleSelection.map((item) => ({ + userName: item.name, + phone: item.phone + }))).then(res => { + if (response.code === 200) { + this.$message.success('同步成功') + this.multipleSelection = [] + // 清空多选 + this.$refs.normalTable.clearSelection() + } + else { + this.$message.error('同步失败') + } + }) + }, // 打开新增对话框 add() { this.dialogStatus = 'create' @@ -416,35 +455,41 @@ diff --git a/src/views/system/user/resetPwd.vue b/src/views/system/user/resetPwd.vue index 5afa427..4605025 100644 --- a/src/views/system/user/resetPwd.vue +++ b/src/views/system/user/resetPwd.vue @@ -39,7 +39,7 @@ if (value === '') { callback(new Error('密码不能为空')) } else { - var reg = /^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&*]+$)[a-zA-Z\d!@#$%^&*]+$/ + var reg = /^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&*_]+$)[a-zA-Z\d!@#$%^&*_]+$/ if (value.match(reg)) { // 样式匹配 if (value.length < 8 || value.length > 16) { callback(new Error('密码长度必须在8到16位之间')) diff --git a/README-zh.md b/README-zh.md index eecdd8d..de54718 100644 --- a/README-zh.md +++ b/README-zh.md @@ -83,3 +83,6 @@ ## License Copyright (c) 2019-present WangXiaoying + + +###注意: mars3d-cesium@1.94 diff --git a/config/index.js b/config/index.js index ab8f4e5..5e9542d 100644 --- a/config/index.js +++ b/config/index.js @@ -65,6 +65,7 @@ */ //定义静态资源的公开路径,也就是真正的引用路径 assetsPublicPath: '/hxrq/', + // assetsPublicPath: './', //定义是否生成生产环境的SourceMap, sourcemap是用来debug编译后文件的,通过映射到编译前文件来实现 productionSourceMap: false, diff --git a/devDependenciesVersion.md b/devDependenciesVersion.md new file mode 100644 index 0000000..d7fdb1e --- /dev/null +++ b/devDependenciesVersion.md @@ -0,0 +1,24 @@ +# 项目依赖版本统计 + +# "axios": "^0.19.0", +# "babel-polyfill": "^6.26.0", +# "echarts": "^4.2.1", +# "element-ui": "2.12.0", +# "event-source-polyfill": "^1.0.5", +# "js-cookie": "2.2.0", +# "js-md5": "^0.7.3", +# "jsencrypt": "^3.0.0-rc.1", +# "lodash": "^4.17.15", +# "mars3d": "3.0.25", +# "mars3d-echarts": "3.0.3", +# "mars3d-heatmap": "3.0.6", +# "mars3d-mapv": "3.0.3", +# "mockjs": "1.0.1-beta3", +# "moment": "2.24.0", +# "normalize.css": "7.0.0", +# "nprogress": "0.2.0", +# "v-charts": "1.19.0", +# "vue": "2.5.17", +# "vue-router": "3.0.1", +# "vuex": "3.0.1" +# "mars3d-cesium" 1.80.1 \ No newline at end of file diff --git a/package.json b/package.json index e687665..c966921 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "vue-template-compiler": "2.5.17", "webpack": "4.16.5", "webpack-bundle-analyzer": "^3.4.1", - "webpack-cli": "3.1.0", + "webpack-cli": "^3.1.0", "webpack-dev-server": "3.1.14", "webpack-merge": "4.1.4" }, diff --git a/src/api/system/user.js b/src/api/system/user.js index 91e7aa7..f470dbd 100644 --- a/src/api/system/user.js +++ b/src/api/system/user.js @@ -113,3 +113,20 @@ } }) } + +// 单点登录获取token +export function fetchToken(params) { + return request({ + url: 'platform/checkZFToken', + method: 'get', + params + }) +} +// 同步用户 +export function syncUser(data) { + return request({ + url: 'ssoUser/syncUser', + method: 'post', + data + }) +} diff --git a/src/components/Map/MarsMap.vue b/src/components/Map/MarsMap.vue index c400842..893e665 100644 --- a/src/components/Map/MarsMap.vue +++ b/src/components/Map/MarsMap.vue @@ -9,7 +9,7 @@ diff --git a/src/layout/LayoutApp.vue b/src/layout/LayoutApp.vue index 81db434..ae5731a 100644 --- a/src/layout/LayoutApp.vue +++ b/src/layout/LayoutApp.vue @@ -30,7 +30,7 @@ this.title = this.$route.query.name this.url = this.$route.query.url } - if(this.baseConfig.toDashboard===false){ + if (this.baseConfig.toDashboard===false){ this.showBack = false } }, diff --git a/src/main.js b/src/main.js index fd1d17e..7568b6e 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,9 @@ +console.log('==============main.js===============') import Vue from 'vue' import 'normalize.css/normalize.css' // A modern alternative to CSS resets import '../theme/index.css' // 引入自定义主题 import ElementUI from 'element-ui' -// import 'element-ui/lib/theme-chalk/index.css' +import 'element-ui/lib/theme-chalk/index.css' import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n import '@/styles/index.scss' // global css diff --git a/src/permission.js b/src/permission.js index c4f95f2..55bd751 100644 --- a/src/permission.js +++ b/src/permission.js @@ -4,8 +4,11 @@ import 'nprogress/nprogress.css' // progress bar style 进度条样式 import { Message } from 'element-ui' import { getToken } from '@/utils/auth' // getToken from cookie +import axios from 'axios' import { getCurrentSys } from './utils/auth' import Vue from 'vue' +import { extractURLParameters } from '@/utils/validate' +import { fetchToken } from '@/api/system/user' NProgress.configure({ showSpinner: false })// NProgress configuration @@ -83,23 +86,65 @@ console.log('is In WhiteList') next() } else { + debugger // 获取链接里的token const token = to.query.token - console.log('token' + to.query.token) - if (token) { - // 调用自动登录接口,否则跳转到登录页 - store.dispatch('AppLogin', token).then(() => { - console.log('自动登录成功') - console.log(to.path) - next({ ...to, replace: true }) // 登录成功继续 - }).catch(() => { - next('/401') // 否则全部重定向到401没有权限页面 + console.log('token' + token) + // // 携带token 需要去掉 + // const zfToken = to.query['ZF-TOKEN'] + let zfToken = '' + // 携带token 需要去掉 + const hrefIdx = window.location.href.indexOf('ZF-TOKEN') // url中是否携带token + if (hrefIdx > -1) { + // const params = queryString(window.location.href) + // zfToken = stripscript(params.token) + console.log('hrefIdx', extractURLParameters(window.location.href)) + const params = extractURLParameters(window.location.href) + zfToken = params['ZF-TOKEN'] + } + console.log('zfToken' + zfToken) + if (zfToken) { + const sendParams = { + zf_token: zfToken + } + // eslint-disable-next-line no-unused-vars + debugger + // window.location.href = 'https://www.baidu.com/?tn=25017023_17_dg' + fetchToken(sendParams).then((resToken) => { + if (resToken.code === 200) { + axios.get('./static/project.config.json').then((result) => { + const params = '?token=' + resToken.data.token + '&url=' + result.data.singleSignLastUrl + const loginUrl = result.data.singleSignFirstUrl + '/sso/integrationConfig/login' + // next({ + // path: '/appSubject', + // query: { name: resToken.data.title, url: loginUrl + params } + // }) + // window.open(loginUrl + params, '_blank') + window.location.href = loginUrl + params + }) + } else { + console.log('用户验证失败') + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } }) } else { - if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { - next(`/applogin`) // 否则全部重定向到登录页 + debugger + if (token) { + // 调用自动登录接口,否则跳转到登录页 + const params = token + store.dispatch('AppLogin', params).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) } else { - next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } } } NProgress.done() diff --git a/src/permissionBak.js b/src/permissionBak.js new file mode 100644 index 0000000..ba87122 --- /dev/null +++ b/src/permissionBak.js @@ -0,0 +1,103 @@ +import router from './router' +import store from './store' +import NProgress from 'nprogress' // progress bar 进度条 +import 'nprogress/nprogress.css' // progress bar style 进度条样式 +import { Message } from 'element-ui' +import { getToken } from '@/utils/auth' // getToken from cookie +import { getCurrentSys } from './utils/auth' + +NProgress.configure({ showSpinner: false })// NProgress configuration + +const whiteList = ['/login', '/applogin', '/appFaceLogin', '/404', 'config/baseconfig', '/full/storageTopic', '/full/waterThreat', '/full/highConsequence', '/full/constructionThreat', '/full/routeTopic', '/full/waterThreat', '/full/sinkThreat', '/full/vip', '/full/weather', '/full/needTopic', '/full/supplyTopic', '/full/pipeOverview', '/full/overview'] // 不重定向白名单 +// 全局钩子 +router.beforeEach((to, from, next) => { + NProgress.start() // 加载进度条 + console.log('to Path:' + to.path) + // 如果有token + if (getToken()) { + console.log('hasToken') + // 登录后进入登录页 + if (to.path === '/login') { + next({ path: '/login' }) + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else if (to.path === '/dashboard') { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next('/appIndex') // 否则全部重定向到登录页 + } else { + next() + } + NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it + } else { + // 当进入非登陆页或非主页时 + if (store.getters.roleList.length === 0) { // 判断当前用户是否已拉取完user_info信息 + store.dispatch('GetInfo').then(res => { // 拉取用户信息 + let currentSys = getCurrentSys() + // 根据路由去找当前子系统 + if (to.query.sys) { + currentSys = { + code: to.query.code, + name: to.query.sys, + url: to.query.url + } + // 将当前系统信息保存在localStorage中 + store.commit('SET_SYSTEM', currentSys) + } + // 如果已有当前可进入的子系统,刷新子系统菜单 + if (currentSys) { + console.log('hasCurrentSystem') + // 远程访问获取权限列表(菜单&按钮) + store.dispatch('GetMenus', currentSys).then(() => { + store.commit('SET_CHANGEFLAG', '0') + // 获取所有地址列表 + router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表 + // 判断路由是否被允许,不允许则重定向 + next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record + }) + } else { // 没有当前子系统信息,跳转到选择子系统页面 + console.log('dontHasCurrentSystem') + next({ path: '/dashboard' }) + } + }).catch((err) => { + console.log('toFedLogOut') + store.dispatch('FedLogOut').then(() => { + Message.error(err || '权限验证失败,请重新登录系统') + next({ path: '/' }) + }) + }) + } else { + // TODO: 判断路由是否被允许,不允许则重定向 + next() + } + } + } else { + if (whiteList.indexOf(to.path) !== -1) { // 免登录白名单,直接进入 + console.log('is In WhiteList') + next() + } else { + // 获取链接里的token + const token = to.query.token + console.log('token' + to.query.token) + if (token) { + // 调用自动登录接口,否则跳转到登录页 + store.dispatch('AppLogin', token).then(() => { + console.log('自动登录成功') + console.log(to.path) + next({ ...to, replace: true }) // 登录成功继续 + }).catch(() => { + next('/401') // 否则全部重定向到401没有权限页面 + }) + } else { + if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { + next(`/applogin`) // 否则全部重定向到登录页 + } else { + next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页 + } + } + NProgress.done() + } + } +}) + +router.afterEach(() => { + NProgress.done() // 结束Progress +}) diff --git a/src/utils/validate.js b/src/utils/validate.js index d7e84e4..52736af 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -7,35 +7,35 @@ * 未知用途 */ export function isExternal(path) { - return /^(https?:|mailto:|tel:)/.test(path) + return /^(https?:|mailto:|tel:)/.test(path); } /* 合法uri*/ export function validateURL(textval) { - const urlregex = /^(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 urlregex.test(textval) + const urlregex = /^(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 urlregex.test(textval); } /* 合法uri*/ export function validateNull(textval) { - return !!textval + return !!textval; } /* 验证小写字母*/ export function validateLowerCase(str) { - const reg = /^[a-z]+$/ - return reg.test(str) + const reg = /^[a-z]+$/; + return reg.test(str); } /* 验证大写字母*/ export function validateUpperCase(str) { - const reg = /^[A-Z]+$/ - return reg.test(str) + const reg = /^[A-Z]+$/; + return reg.test(str); } /* 验证大小写字母*/ export function validateAlphabets(str) { - const reg = /^[A-Za-z]+$/ - return reg.test(str) + const reg = /^[A-Za-z]+$/; + return reg.test(str); } /** @@ -44,8 +44,8 @@ * @returns {boolean} */ export function validateEmail(email) { - const re = /^(([^<>()\[\]\\.,;:\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 re.test(email) + const re = /^(([^<>()\[\]\\.,;:\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 re.test(email); } /** @@ -54,38 +54,70 @@ * @returns {boolean} */ export function validatePhone(phone) { - const re = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/ - return re.test(phone) + const re = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/; + return re.test(phone); } /** * 验证一定范围内的非负整数 */ export function validateIntPlus(value, min, max) { - const re = /^\d+$/ + const re = /^\d+$/; if (re.test(value)) { - const data = parseInt(value) + const data = parseInt(value); if (data > max || data < min) { - return false + return false; } - return true + return true; } else { - return false + return false; } } /** * 验证一定范围内的非负小数 */ export function validateFloatPlus(value, min, max) { - const re = /^\d+(\.\d+)?$/ + const re = /^\d+(\.\d+)?$/; if (re.test(value)) { - const data = parseFloat(value) + const data = parseFloat(value); if (data > max || data < min) { - return false + return false; } else { - return true + return true; } } else { - return false + return false; } } + +// 提取url params参数 +export function queryString(str) { + const params = str.split('?')[1] // 截取?号后的字符串即name=itclanCoder&study=css + const param = params.split('&') // 通过&符号进行分割即["name=itclanCoder", "study=css"] + const obj = {} // 用一个对象存储目标值 + for (let i = 0; i < param.length; i++) { + // 循环遍历截取出来的param数组 + const paramsA = param[i].split('=') // 通过split,=继续对数组params每一项进行分割,生成数组["name", "itclanCoder"] + const key = paramsA[0] // 取数组项["name", "itclanCoder"]中第0位,即name + const value = paramsA[1] // 取数组项["name", "itclanCoder"]中第1位,即itclanCoder + obj[key] = value + } + return obj +} +// 去除字符串中的特殊符号 +export function stripscript(s) { + var pattern = /[[\]\/:*?"<>|#]/ + var rs = '' + for (var i = 0; i < s.length; i++) { + rs = rs + s.substr(i, 1).replace(pattern, '') + } + return rs +} + +export function extractURLParameters(url) { + const params = new URLSearchParams(url.split('?')[1]); + return Array.from(params.entries()).reduce((acc, [key, value]) => { + acc[key] = value; + return acc; + }, {}); +} diff --git a/src/views/system/resource/editResource.vue b/src/views/system/resource/editResource.vue index 2a22a73..acfc6b5 100644 --- a/src/views/system/resource/editResource.vue +++ b/src/views/system/resource/editResource.vue @@ -152,7 +152,7 @@ resourceType: row.resourceType, num: row.num, icon: row.icon, - tips:row.tips + tips: row.tips } } }, @@ -187,7 +187,7 @@ resourceType: '', num: '', icon: '', - tips:'' + tips: '' } }, // 保存数据 diff --git a/src/views/system/role/editRole.vue b/src/views/system/role/editRole.vue index 0c2a54b..cc48cf3 100644 --- a/src/views/system/role/editRole.vue +++ b/src/views/system/role/editRole.vue @@ -170,7 +170,7 @@ pids: '', num: 99, tips: '', - dataScopeType:'', + dataScopeType: '', version: '' } }, diff --git a/src/views/system/user/editUser.vue b/src/views/system/user/editUser.vue index 9b1ee73..77af02e 100644 --- a/src/views/system/user/editUser.vue +++ b/src/views/system/user/editUser.vue @@ -180,8 +180,8 @@ message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }], phone: [{ - required: false, - pattern: /^1[34578]\d{9}$/, // 可以写正则表达式呦呦呦 + required: true, + pattern: /^1[3456789]\d{9}$/, // 可以写正则表达式呦呦呦 message: '请输入正确的手机号', trigger: ['blur', 'change'] }] }, // 前端校验规则 diff --git a/src/views/system/user/listUser.vue b/src/views/system/user/listUser.vue index 8cfb01c..dcecf1e 100644 --- a/src/views/system/user/listUser.vue +++ b/src/views/system/user/listUser.vue @@ -9,16 +9,9 @@ 组织机构 - + @@ -28,33 +21,38 @@ - + - + - 新增 - 修改 - 删除 - 重置密码 - 角色分配 - 注册人脸 + 新增 + 修改 + 删除 + 重置密码 + 角色分配 + 注册人脸 + 用户同步 - + + + @@ -62,19 +60,21 @@ - + {{ scope.row.statusName }} - {{ btnNames[scope.row.statusName] }} + {{ btnNames[scope.row.statusName] }} - {{ faceReged[scope.row.attr1] }} + {{ faceReged[scope.row.attr1] }} @@ -82,8 +82,8 @@ - - + + @@ -93,7 +93,7 @@ import editUser from '@/views/system/user/editUser' import roleAssign from '@/views/system/user/roleAssign' import RegFace from '@/views/system/user/regFace' -import { getUserList, delUser, freezeUser, unfreezeUser, resetPwd, delFace } from '@/api/system/user' +import { getUserList, delUser, freezeUser, unfreezeUser, resetPwd, delFace, syncUser } from '@/api/system/user' import { getDeptTreeList } from '@/api/system/dept' import { toTreeList } from '@/utils/structure' @@ -177,7 +177,8 @@ roleAssignShow: false, // 角色分配组件是否显示 expandAllNode: true, expandNodeClick: false, - regFaceShow: false + regFaceShow: false, + multipleSelection: [], } }, watch: { @@ -196,6 +197,44 @@ this.fetchData() }, methods: { + // 多选触发方法 + handleSelectionChange(val) { + console.log('selectionChange') + this.multipleSelection = val + }, + // 同步用户 + sync() { + if (!this.multipleSelection.length) { + this.$message({ + message: '请选择要同步的用户', + type: 'warning' + }) + return + } + // 检查用户是否全面(都含有手机号) + if (this.multipleSelection.some(item => !item.phone)) { + const userList = this.multipleSelection.map(item => !item.phone).map(item => item.name) + this.$message({ + message: `用户:${userList.join('、')},缺少手机号,请补充手机号后再进行同步`, + type: 'warning' + }) + return + } + syncUser(this.multipleSelection.map((item) => ({ + userName: item.name, + phone: item.phone + }))).then(res => { + if (response.code === 200) { + this.$message.success('同步成功') + this.multipleSelection = [] + // 清空多选 + this.$refs.normalTable.clearSelection() + } + else { + this.$message.error('同步失败') + } + }) + }, // 打开新增对话框 add() { this.dialogStatus = 'create' @@ -416,35 +455,41 @@ diff --git a/src/views/system/user/resetPwd.vue b/src/views/system/user/resetPwd.vue index 5afa427..4605025 100644 --- a/src/views/system/user/resetPwd.vue +++ b/src/views/system/user/resetPwd.vue @@ -39,7 +39,7 @@ if (value === '') { callback(new Error('密码不能为空')) } else { - var reg = /^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&*]+$)[a-zA-Z\d!@#$%^&*]+$/ + var reg = /^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&*_]+$)[a-zA-Z\d!@#$%^&*_]+$/ if (value.match(reg)) { // 样式匹配 if (value.length < 8 || value.length > 16) { callback(new Error('密码长度必须在8到16位之间')) diff --git a/static/project.config.json b/static/project.config.json index f75c6e3..20d345b 100644 --- a/static/project.config.json +++ b/static/project.config.json @@ -1,7 +1,9 @@ { "title": "管理者驾驶舱", - "baseUrl": "http://59.49.106.24:8080/cockpit/", + "baseUrl": "http://192.168.204.127:8080/cockpit/", "biUrl": "http://59.49.106.24:9001", + "singleSignFirstUrl": "http://59.49.106.24:9001", + "singleSignLastUrl": "http://10.100.252.13:9001/browse/2/BD1629B6396A40748E6E04D28B5B5EC1", "sameWindow": false, "toDashboard": false, "biLogin": "http://59.49.106.24:9001/sso/integrationConfig/login",