diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..5266a0221 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,78 @@ +module.exports = { + root: true, // 将eslint配置限制在当前配置文件所在目录下 + // 继承其他规则 + 'extends': ['eslint:recommended', 'plugin:vue/recommended'], + // 解析选项 + 'parserOptions': { + parser: "babel-eslint", // 解析器 + 'ecmaVersion': 6, // ES 语法版本 + 'sourceType': 'module', // ES 模块化 + 'ecmaFeatures': { // ES 其他特性 + 'jsx': true // 如果是 React 项目,就需要开启 jsx 语法 + } + }, + plugins: [ + // '@stylistic/js' + ], + // 具体检查规则 + 'rules': { + 'no-var': 'error', // 不能使用 var 定义变量 + 'eqeqeq': [ + 'warn', // 建议使用 === 和 !==,否则警告 + 'smart' // https://eslint.bootcss.com/docs/rules/eqeqeq#smart 除了少数情况下不会有警告 + ], + 'prefer-arrow-callback': 'warn', // 建议使用箭头函数 + 'prefer-const': 'error', // 强制使用 const 定义常量 + 'indent': ['error', 2], // 缩进 2 个空格 + // '@stylistic/js/indent': ['error', 2], // 缩进 2 个空格 + 'no-mixed-spaces-and-tabs': 'error', // 禁止混用空格和 tab缩进 + 'quotes': ['error', 'single'], // 强制使用单引号 + "spaced-comment": ["error", "always"], // 注释后面需要有空格 + "prefer-template": "error", // 字符串拼接使用模版字符串 'hello' + world => `hello${world}` + "template-curly-spacing": ["error", "always"], // 模版字符串中{}前后内有一个或多个空格 `hello${ world }` => `hello${ world }` + "key-spacing": ["error", { mode: "strict" }], // 对象字面量中冒号的前后空格 { "foo" : 42 } => { "foo": 42 } + "comma-spacing": ["error", { "before": false, "after": true }], // 逗号前面不能有空格,后面需要有空格 [1, 2 , 3 ,4] => [1, 2, 4, 4] + "array-bracket-spacing": ["error","always"], // 数组前后需要有空格 [ 1,2 ] => [ 1,2 ] + "object-curly-spacing": ["error","always"], // 对象前后需要有空格 { a:b } => { a:b } + "no-whitespace-before-property": "error", // 禁止属性前有空格 obj . foo => obj.foo + "func-call-spacing": ["error", "never"], // 函数调用时,函数名与()之间不能有空格 fn () => fn() + 'space-before-function-paren': ['error', 'always'], // 函数左括号空格 function name(){} => function name (){} + // "rest-spread-spacing": "error", // 展开运算符前后需要有空格 ...arr => ... arr + 'space-before-blocks': 'error', // 代码块前面(if function等的大括号之前)需要有空格 function name(){} => function name() {} + "space-infix-ops": 'error', // 操作符前后需要有空格 a=0 => a = 0 + 'arrow-spacing': ['error', { before: true, after: true }], // 箭头函数前后需要有空格 + "brace-style": ["error", "1tbs", { "allowSingleLine": true }], // if else 等的大括号风格 + "no-irregular-whitespace": 'error', // 不能有不规则的空格 https://eslint.nodejs.cn/docs/latest/rules/no-irregular-whitespace + "no-trailing-spaces": 'error', // 一行结束后面不要有空格 + "padded-blocks": ["error", "never"], // 代码块内部前后不要有空行 + "semi-spacing": ["error", { "before": false, "after": true }], // 分号前面不能有空格,后面需要有空格 var foo ; var bar; => var foo; var bar; + 'no-multiple-empty-lines': [ 'error', { max: 1 }], // 最多只能有一行空行 + 'no-return-assign': ['error', 'except-parens'], // 禁止在 return 语句中使用赋值语句 + 'no-self-assign': 'error', // 禁止自我赋值 + 'no-self-compare': 'error', // 禁止自身比较 + // "newline-per-chained-call": ["error", { "ignoreChainWithDepth": 1 }], // 链式调用时,每个调用都需要换行 + "no-duplicate-imports": "error", // 禁止重复 import + // 以下规则都是基于plugin:vue/recommended的默认值 + 'vue/max-attributes-per-line': [ + 'error', + { + singleline: 4, // 单行最多 4 个属性 + multiline: { + max: 1, // 多行最多 1 个属性 + allowFirstLine: false, // 不允许属性与组件名称在同一行 + }, + }, + ], + 'vue/singleline-html-element-content-newline': 'off', // 单行元素内容之前和之后不需要换行 + 'vue/multiline-html-element-content-newline': 'error', // 多行元素内容之前和之后需要换行 + 'vue/html-indent': ['error', 2], // 缩进 2 个空格 + 'vue/html-closing-bracket-newline': ['error', { // 强制或禁止在自闭合标签之前换行 + 'singleline': 'never', + 'multiline': 'always', + }], + }, + env: { + browser: true, + node: true + } +} diff --git a/package.json b/package.json index 775b992bf..40e694060 100644 --- a/package.json +++ b/package.json @@ -43,11 +43,15 @@ "vuex": "^3.4.0" }, "devDependencies": { + "@stylistic/eslint-plugin-js": "^1.5.1", "@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-router": "~4.5.0", "@vue/cli-plugin-vuex": "~4.5.0", "@vue/cli-service": "~4.5.0", + "babel-eslint": "^10.1.0", "babel-plugin-import": "^1.13.3", + "eslint": "6.7.2", + "eslint-plugin-vue": "6.2.2", "less": "^3.13.1", "less-loader": "^5.0.0", "popper.js": "^1.16.1", diff --git a/src/App.vue b/src/App.vue index 6894e69cf..75d3b7ce4 100644 --- a/src/App.vue +++ b/src/App.vue @@ -34,7 +34,7 @@
- {{ $store.getters.userInfo.uName }} + {{ uName }}
@@ -70,7 +70,7 @@
- {{ $store.getters.userInfo.uName }} + {{ uName }}
@@ -97,9 +97,9 @@ diff --git a/src/router/index.js b/src/router/index.js index aaf88fedc..435eb1610 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -68,10 +68,12 @@ const routes = [ title: '手机提示页面', } }, + /* { path: '*', redirect: '/loginVerify' }, + */ // 单点登录跳转页面 { path: '/checkPage', @@ -5000,8 +5002,11 @@ const routes = [ { path: '/standardSearch/:selectKey?/:searchValue?', name: 'StandardSearch', + /* component: () => import('@/pages/searchCenter/pages/standardSearch'), + */ + component: () => import('@/pages/searchCenter/pages/standardSearch/index'), meta: { requireAuth: true, title: '标准检索', diff --git a/src/sysConfig/index-20231213.js b/src/sysConfig/index-20231213.js new file mode 100644 index 000000000..ee2edb8aa --- /dev/null +++ b/src/sysConfig/index-20231213.js @@ -0,0 +1,72 @@ +const devIp = 'localhost' +// const devIp = '10.0.10.115' +const devInterfacePORT = '10086' +// const devInterfacePORT = '4202' +// 配置 idm 认证 +const ssoLogin = 'http://sso.foton.com.cn/oauth2.0/authorize?client_id=app_slrs&response_type=code&redirect_uri=' +// 配置 前端服务 +// const devWebUrl = 'http://62.234.136.153:8038/#/' +const devWebUrl = 'http://localhost:9090/#/' +// webLoginType : idm (线上统一登录) 、 webLoginType: dev (测试环境登录) +const webLoginType = 'dev' + +// const kkFileViewUrl = 'https://srms.foton.com.cn/preview' +const kkFileViewUrl = 'http://127.0.0.1:8012' +// 配置onlyOffice 前端服务 +const onlyOfficeUrl = 'http://127.0.0.1:8080' +// const onlyOfficeUrl = 'http://10.10.10.46:8889' + +// 云端端口号 +const DEV_CLOUD_RES_INTERFACE_PORT = '7777' +const simpleFilePath = 'att/attFile/upload' +const multipleFilePath = 'att/attFile/uploadFiles' +const staticFilePath = '192.168.10.140:10010' +// const staticFilePath = '106.2.13.189:8888' +const staticPDFPath = '192.168.7.140' +const webSocket = '192.168.7.178' +// const enterprise = '' +const enterprise = 'SJZX' +const theme = 'theme-one' // 主题(theme-one浅蓝色,theme-two深蓝色) +const processPort = '17210' +/***************************************************************** + + <<<<<<<<< 主题修改 >>>>>>>>> + + 1. 主题分为theme-one,theme-two两种 + 2. 修改assets/styles/style.less文件,注释theme-one/theme-two + 3. 将上方theme改为theme-one/theme-two + + *****************************************************************/ + // 生产环境配置 + // const prodIp = '39.98.140.126' + // const prodInterfacePORT = '4201' +const prodIp = '10.10.10.46' +const prodInterfacePORT = '4202' +// const prodIp = 'slrs.foton.com.cn' +// const prodInterfacePORT = '' + +// 判断环境 +const serverIP = process.env.NODE_ENV === 'production' ? prodIp : devIp +const interfacePORT = process.env.NODE_ENV === 'production' ? prodInterfacePORT : devInterfacePORT +const CLOUD_RES_INTERFACE_PORT = process.env.NODE_ENV === 'production' ? DEV_CLOUD_RES_INTERFACE_PORT : DEV_CLOUD_RES_INTERFACE_PORT + +module.exports = { + baseUrl: 'http://' + serverIP + ':' + interfacePORT, + webLoginType: webLoginType, + ssoLoginUrlDev: ssoLogin + devWebUrl, + ssoLoginUrl: ssoLogin, + kkFileViewUrl, + onlyOfficeUrl: onlyOfficeUrl, + devWebUrl: devWebUrl, + serverUrl: 'http://' + serverIP, // 服务器IP地址 + interfaceUrl: 'http://' + serverIP + ':' + interfacePORT + '/api/', // 服务器端接口访问地址, + cloudResInterFaceUrl: 'http://' + serverIP + ':' + interfacePORT + '/busApi/', // 云端资源库服务器端接口访问地址, + simpleUploadPath: 'api/' + simpleFilePath, // 单文件上传地址 + multipleUploadPath: 'api/' + multipleFilePath, // 多文件上传地址 + staticFilePath: 'http://' + staticFilePath, + staticPDFPath: 'http://' + staticPDFPath, + webSocket: webSocket + ':' + devInterfacePORT + '/websocket/socketServer', // webSocket连接 + enterprise: enterprise, // GQ广汽 SJZX数据中心 + theme: theme, // 主题 + processInterfaceURL: `http://${serverIP}:${processPort}/bat-wkflow` +} diff --git a/src/sysConfig/index.js b/src/sysConfig/index.js index 523461111..63d01aa6c 100644 --- a/src/sysConfig/index.js +++ b/src/sysConfig/index.js @@ -1,81 +1,76 @@ -/*** 前端本地配置文件: - @description: 通用配置 - * @author: chenxiaoxi - * @date: 2018-09-04 17:47:46 - */ -// 服务器地址 -// const devIp = '39.98.140.126' -// const devInterfacePORT = '4202' -// const devIp = '192.168.1.42' -// const devInterfacePORT = '9999' -// const devIp = '10.10.10.46' -// const devInterfacePORT = '4202' -// // const devIp = '10.0.3.10' -const devIp = '10.0.3.11' -const devInterfacePORT = '10086' -// const devIp = '62.234.136.153' -// const devInterfacePORT = '8033' -// 配置 idm 认证 -const ssoLogin = 'http://localhost:9090/#/' -// 配置 前端服务 -const devWebUrl = 'http://localhost:9090/#/' -// webLoginType : idm (线上统一登录) 、 webLoginType: dev (测试环境登录) -const webLoginType = 'dev' - -// 配置onlyOffice 前端服务 -const onlyOfficeUrl = 'http://127.0.0.1:8080' -// const onlyOfficeUrl = 'http://10.10.10.46:8889' - -// 云端端口号 -const DEV_CLOUD_RES_INTERFACE_PORT = '7777' -const simpleFilePath = 'att/attFile/upload' -const multipleFilePath = 'att/attFile/uploadFiles' -const staticFilePath = '192.168.10.140:10010' -// const staticFilePath = '106.2.13.189:8888' -const staticPDFPath = '192.168.7.140' -const webSocket = '192.168.7.178' -// const enterprise = '' -const enterprise = 'SJZX' const theme = 'theme-one' // 主题(theme-one浅蓝色,theme-two深蓝色) -const processPort = '17210' /***************************************************************** - <<<<<<<<< 主题修改 >>>>>>>>> - 1. 主题分为theme-one,theme-two两种 2. 修改assets/styles/style.less文件,注释theme-one/theme-two 3. 将上方theme改为theme-one/theme-two - *****************************************************************/ -// 生产环境配置 + +const simpleUploadPath = 'api/att/attFile/upload' +const multipleUploadPath = 'api/att/attFile/uploadFiles' + +const ssoLoginProd = 'http://sso.foton.com.cn/oauth2.0/authorize?client_id=app_slrs&response_type=code&redirect_uri=' +const ssoLoginDev = 'http://testsso1.foton.com.cn/oauth2.0/authorize?client_id=app_slrs&response_type=code&redirect_uri=' + +const ssoLogoutProd = 'http://sso.foton.com.cn/logout?service=' +const ssoLogoutDev = 'http://testsso1.foton.com.cn/logout?service=' + +// webLoginType : idm (线上统一登录) 、 webLoginType: dev (测试环境登录、本地环境登录) +// const webLoginType = 'idm' // (线上统一登录) +const webLoginType = 'dev' // (后门登录、测试环境登录、本地环境登录) + +// 配置kkFileView +const kkFileViewUrlDev = 'http://127.0.0.1:8012' +const kkFileViewUrlProd = 'https://srms.foton.com.cn/preview' + +// 配置onlyOffice +const onlyOfficeUrlDev = 'http://127.0.0.1:8080' +const onlyOfficeUrlProd = 'http://10.100.5.116:8088' + +// 本地环境 +const devIp = 'localhost' +const devPORT = '10086' + +// 测试环境 // const prodIp = '39.98.140.126' -// const prodInterfacePORT = '4201' -const prodIp = '10.10.10.46' -const prodInterfacePORT = '4202' -// const prodIp = 'slrs.foton.com.cn' -// const prodInterfacePORT = '' +// const prodPORT = '4201' +// const prodPORT = '4202' + +// 后门 +// const prodIp = '172.24.7.197' +// const prodPORT = '4202' +// const prodIp = '10.19.11.243' +// const prodPORT = '4204' + +// 生产环境配置 +const prodIp = 'srms.foton.com.cn' +const prodPORT = '' // 判断环境 -const serverIP = process.env.NODE_ENV === 'production' ? prodIp : devIp -const interfacePORT = process.env.NODE_ENV === 'production' ? prodInterfacePORT : devInterfacePORT -const CLOUD_RES_INTERFACE_PORT = process.env.NODE_ENV === 'production' ? DEV_CLOUD_RES_INTERFACE_PORT : DEV_CLOUD_RES_INTERFACE_PORT +const IP = process.env.NODE_ENV === 'production' ? prodIp : devIp +const PORT = process.env.NODE_ENV === 'production' ? prodPORT : devPORT +const kkFileViewUrl = process.env.NODE_ENV === 'production' ? kkFileViewUrlProd : kkFileViewUrlDev +const onlyOfficeUrl = process.env.NODE_ENV === 'production' ? onlyOfficeUrlProd : onlyOfficeUrlDev +const protocol = process.env.NODE_ENV === 'production' ? 'https://' : 'http://' + +// 配置 idm 认证 +const ssoLogin = process.env.NODE_ENV === 'production' ? ssoLoginProd : ssoLoginDev +const ssoLogout = process.env.NODE_ENV === 'production' ? ssoLogoutProd : ssoLogoutDev + +const baseUrl = protocol + IP + ':' + PORT +const interfaceUrl = protocol + IP + ':' + PORT + '/api/' // 服务器端接口访问地址, module.exports = { - baseUrl: 'http://' + serverIP + ':' + interfacePORT, - webLoginType: webLoginType, - ssoLoginUrlDev: ssoLogin + devWebUrl, - ssoLoginUrl: ssoLogin, - onlyOfficeUrl: onlyOfficeUrl, - devWebUrl: devWebUrl, - serverUrl: 'http://' + serverIP, // 服务器IP地址 - interfaceUrl: 'http://' + serverIP + ':' + interfacePORT + '/api/', // 服务器端接口访问地址, - cloudResInterFaceUrl: 'http://' + serverIP + ':' + interfacePORT + '/busApi/', // 云端资源库服务器端接口访问地址, - simpleUploadPath: 'api/' + simpleFilePath, // 单文件上传地址 - multipleUploadPath: 'api/' + multipleFilePath, // 多文件上传地址 - staticFilePath: 'http://' + staticFilePath, - staticPDFPath: 'http://' + staticPDFPath, - webSocket: webSocket + ':' + devInterfacePORT + '/websocket/socketServer', // webSocket连接 - enterprise: enterprise, // GQ广汽 SJZX数据中心 - theme: theme, // 主题 - processInterfaceURL: `http://${serverIP}:${processPort}/bat-wkflow` + baseUrl, + interfaceUrl, // 服务器端接口访问地址, + simpleUploadPath, // 单文件上传地址 + multipleUploadPath, // 多文件上传地址 + + webLoginType, + ssoLogin, + ssoLogout, + + kkFileViewUrl, + onlyOfficeUrl, + theme, // 主题 } diff --git a/src/utils/login.js b/src/utils/login.js new file mode 100644 index 000000000..0286df90d --- /dev/null +++ b/src/utils/login.js @@ -0,0 +1,200 @@ +import { webLoginType, ssoLogin, ssoLogout } from '@/sysConfig' +import { getMenu, loginIdm } from '@/api/process' +import { getTokenToWeLink } from '@/api/phoneWeLink' +import isMobile from '@/store/isMobile' +import store from '@/store' +import router from '@/router' +import hwh5 from '@/api/hwh5-cloudonline.js' +import { Message, MessageBox, Loading } from 'element-ui' +import { Dialog } from 'vant' + +function getCode () { + const url = window.location.href + if (url && url !== '') { + if (url.split('code=').length > 1) { + return url.split('code=')[1] + } + } +} + +function toIdmLoginPage (url) { + if (webLoginType === 'idm') { + let href = url + if (href.indexOf('localhost:9090' > -1)) { + href = href.replace('localhost:9090', '39.98.140.126:9090') // 开发环境 + } + console.log(ssoLogin + encodeURIComponent(href)) + window.location.href = ssoLogin + encodeURIComponent(href) + } +} + +// 重新登录 +function loginAgain () { + store.dispatch('logout').then(() => { + if (webLoginType === 'idm') { + if (isMobile()) { + loginInPhone().then(() => { + router.go(0) + }) + } else { + window.location.href = ssoLogout + encodeURIComponent(window.location.href) + } + } + if (webLoginType === 'dev') { + router.push('/login') + } + }) +} + +// 退出登录 +function loginOut () { + store.dispatch('logout').then(() => { + if (webLoginType === 'idm') { + window.location.href = ssoLogout + encodeURIComponent(window.location.origin) + } + if (webLoginType === 'dev') { + router.push('/login') + } + }) +} + +// idm登录 +function loginInIdm (code) { + return new Promise((resolve, reject) => { + const loading = Loading.service({ + lock: true, + text: '登录中...', + spinner: 'el-icon-loading' + }) + const _formData = new FormData() + _formData.append('code', code) + // 获取用户信息 + loginIdm(_formData).then(res => { + if (res.ok) { + loginNew(res) + .then(() => { + resolve() + }) + .finally(() => { + loading.close() + }) + } else { + if (res.respCode && res.respCode === 'r0011') { + quit() + loading.close() + } + } + }) + }) +} + +// welink登录 +function loginInPhone () { + return new Promise( (resolve, reject) => { + const loading = Loading.service({ + lock: true, + text: '登录中...', + spinner: 'el-icon-loading' + }) + hwh5.getAuthCode().then(data => { + console.log('获取到了welinkCode', data) + if (data) { + const code = data.code + getTokenToWeLink({ + code: code, + name: encodeURIComponent('standards' + '-' + 'regulations'), + type: '', + corpCode: '' + }).then(res => { + if (res.ok) { + loginNew(res) + .then(() => { + resolve() + }) + .finally(() => { + loading.close() + }) + } else { + if (res.respCode && res.respCode === 'r0011') { + quit() + loading.close() + } + } + }) + } + }) + }).catch(e => { + Message.warning(e) + }) +} + +function loginNew (res) { + return new Promise((resolve, reject) => { + if (res.data.orgId === null || res.data.orgId === '') { + Message.warning('未分配组织机构,请联系管理员分配后重新登录') + return + } + const Base64 = require('js-base64').Base64 + // 解析用户信息 + const userInfoStr = Base64.decode(res.data) + const userInfoJSON = decodeURIComponent(userInfoStr) + const userInfo = JSON.parse(userInfoJSON) + userInfo.userId = userInfo.usid + store.commit('setToken', userInfo.token) + store.commit('setUserInfo', JSON.stringify(userInfo)) + getMenu({ userId: store.getters.userInfo.userId }) + .then(menuRes => { + if (menuRes.ok) { + let hasHomeMenu = false + const menuList = menuRes.data + menuList.forEach(menu => { + if (menu.id === 'asdfadf') { + hasHomeMenu = true + } + }) + if (hasHomeMenu) { + store.dispatch('setMenu', JSON.stringify(menuList)).then(() => { + resolve() + }) + } + } else { + reject(menuRes) + } + }) + .catch(e => { + reject(e) + }) + }) +} + +function quit () { + Message.warning('系统无权限访问') + if (isMobile()) { + Dialog.confirm({ + message: '您没有系统访问权限,请联系管理员进行授权' + }).then(() => { + store.dispatch('logout').then(() => { + close() + }) + }) + } else { + MessageBox.confirm('您没有系统访问权限,请联系管理员进行授权', '提示', { + confirmButtonText: '确定', + type: 'warning', + showClose: false, + showCancelButton: false + }).then(() => { + store.dispatch('logout').then(() => { + window.location.href = ssoLogout + encodeURIComponent(window.location.origin) + }) + }) + } +} + +function close () { + if (isMobile()) { + hwh5.close() + } +} + +export { toIdmLoginPage, getCode, loginInIdm, loginInPhone, loginAgain, loginOut, close }