Initial commit
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
> 1%
|
||||||
|
last 2 versions
|
||||||
|
not dead
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
[*]
|
||||||
|
charset=utf-8
|
||||||
|
end_of_line=crlf
|
||||||
|
insert_final_newline=false
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[{*.ng,*.sht,*.html,*.shtm,*.shtml,*.htm}]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[{*.jhm,*.xslt,*.xul,*.rng,*.xsl,*.xsd,*.ant,*.tld,*.fxml,*.jrxml,*.xml,*.jnlp,*.wsdl}]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[*.svg]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[*.js.map]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[*.less]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[*.vue]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[{.analysis_options,*.yml,*.yaml}]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
|
||||||
|
[*.{js,jsx,ts,tsx,vue}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
NODE_ENV=production
|
||||||
|
VUE_APP_PLATFORM_NAME=JeroBoot 企业级快速开发平台
|
||||||
|
VUE_APP_SSO=false
|
||||||
|
VUE_TAG_FLAG=0
|
||||||
|
VUE_APP_LOGIN_PAGE='/user/login'
|
||||||
|
VUE_APP_CURRENT_SYSTEM='inner'
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
NODE_ENV=development
|
||||||
|
VUE_APP_TAG_FLAG=0
|
||||||
|
VUE_APP_LOGIN_PAGE='/user/login'
|
||||||
|
VUE_APP_CURRENT_SYSTEM='inner'
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
NODE_ENV=production
|
||||||
|
VUE_APP_TAG_FLAG=1
|
||||||
|
VUE_APP_LOGIN_PAGE='https://iam-uat.sinotruk.com:7011/idp/oauth2/authorize?redirect_uri=http://laws-test.sinotruk.com/dashboard/analysis&state=123&client_id=SRMS&response_type=code'
|
||||||
|
VUE_APP_CURRENT_SYSTEM='IAM'
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
NODE_ENV=production
|
||||||
|
VUE_APP_API_BASE_URL=http://boot.jero.com:8080/laws-sinotruk
|
||||||
|
VUE_APP_CAS_BASE_URL=http://cas.example.org:8443/cas
|
||||||
|
VUE_APP_ONLINE_BASE_URL=http://fileview.jero.com/onlinePreview
|
||||||
|
VUE_APP_TAG_FLAG=1
|
||||||
|
VUE_APP_LOGIN_PAGE='/user/login'
|
||||||
|
VUE_APP_CURRENT_SYSTEM='inner'
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
/dist
|
||||||
|
/public
|
||||||
|
/node_modules
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
node: true
|
||||||
|
},
|
||||||
|
'extends': [
|
||||||
|
'plugin:vue/essential',
|
||||||
|
'@vue/standard'
|
||||||
|
],
|
||||||
|
parserOptions: {
|
||||||
|
parser: 'babel-eslint'
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'quotes': [2, 'single', {
|
||||||
|
'avoidEscape': true,
|
||||||
|
'allowTemplateLiterals': true
|
||||||
|
}],
|
||||||
|
'semi': [2, 'never'],
|
||||||
|
'prefer-promise-reject-errors': 'warn'
|
||||||
|
}
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/dist
|
||||||
|
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# laws_sinotruk_mobile
|
||||||
|
|
||||||
|
## Project setup
|
||||||
|
```
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and hot-reloads for development
|
||||||
|
```
|
||||||
|
npm run serve
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and minifies for production
|
||||||
|
```
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lints and fixes files
|
||||||
|
```
|
||||||
|
npm run lint
|
||||||
|
```
|
||||||
|
|
||||||
|
### Customize configuration
|
||||||
|
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
presets: [
|
||||||
|
'@vue/cli-plugin-babel/preset'
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"module": "esnext",
|
||||||
|
"baseUrl": "./",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lib": [
|
||||||
|
"esnext",
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"scripthost"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+13598
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"name": "laws_sinotruk_mobile",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"serve": "vue-cli-service serve",
|
||||||
|
"build": "vue-cli-service build",
|
||||||
|
"lint": "vue-cli-service lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.21.1",
|
||||||
|
"core-js": "^3.8.3",
|
||||||
|
"jsencrypt": "^3.0.0-rc.1",
|
||||||
|
"md5": "^2.2.1",
|
||||||
|
"vant": "^2.13.2",
|
||||||
|
"vue": "^2.6.14",
|
||||||
|
"vue-i18n": "^8.7.0",
|
||||||
|
"vue-ls": "^3.2.0",
|
||||||
|
"vue-router": "^3.5.1",
|
||||||
|
"vuex": "^3.6.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.12.16",
|
||||||
|
"@babel/eslint-parser": "^7.12.16",
|
||||||
|
"@vue/cli-plugin-babel": "~5.0.0",
|
||||||
|
"@vue/cli-plugin-eslint": "~4.2.3",
|
||||||
|
"@vue/cli-plugin-router": "~5.0.0",
|
||||||
|
"@vue/cli-plugin-vuex": "~5.0.0",
|
||||||
|
"@vue/cli-service": "~5.0.0",
|
||||||
|
"@vue/eslint-config-standard": "^5.1.0",
|
||||||
|
"babel-eslint": "^7.2.3",
|
||||||
|
"compression-webpack-plugin": "^10.0.0",
|
||||||
|
"eslint": "^6.7.2",
|
||||||
|
"eslint-plugin-import": "^2.20.1",
|
||||||
|
"eslint-plugin-node": "^11.0.0",
|
||||||
|
"eslint-plugin-promise": "^4.2.1",
|
||||||
|
"eslint-plugin-standard": "^4.0.0",
|
||||||
|
"eslint-plugin-vue": "^6.1.2",
|
||||||
|
"less": "^3.9.0",
|
||||||
|
"less-loader": "^4.1.0",
|
||||||
|
"vue-template-compiler": "^2.6.14"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* 防止打包部署时路径被写死
|
||||||
|
*/
|
||||||
|
window._CONFIG = {}
|
||||||
|
window._CONFIG.domianURL = '/laws-sinotruk' // 路由转发 devServer
|
||||||
|
window._CONFIG.domianWebSocketURL = 'http://localhost:8184/laws-sinotruk'
|
||||||
|
// 单点登录地址
|
||||||
|
window._CONFIG.staticDomainURL = window._CONFIG.domianURL + '/sys/common/download'
|
||||||
|
window._CONFIG.pdfDomainURL = window._CONFIG.domianURL + '/sys/common/pdf/pdfPreviewIframe'
|
||||||
|
window._CONFIG.casPrefixUrl = 'http://cas.example.org:8443/cas'
|
||||||
|
// 预览文件地址
|
||||||
|
window._CONFIG.onlinePreviewDomainURL = 'http://127.0.0.1:8012/onlinePreview'
|
||||||
|
// onlyOffice前端服务地址
|
||||||
|
window._CONFIG.onlyOfficeUrl = 'http://127.0.0.1:8080'
|
||||||
|
// onlyOffice下载文件地址(暂时没用)
|
||||||
|
window._CONFIG.onlyOfficeDownloadFileUrl = 'http://localhost:8184/sys/common/download'
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0, maximum-scale=1, minimum-scale=1, user-scalable=no">
|
||||||
|
<!-- <link rel="icon" href="<%= BASE_URL %>favicon.ico">-->
|
||||||
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
font-size: calc(100vw / 10);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script src="<%= BASE_URL %>api_address_config.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||||
|
</noscript>
|
||||||
|
<div id="app"></div>
|
||||||
|
<!-- built files will be auto injected -->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
<template>
|
||||||
|
<div id="app">
|
||||||
|
<van-nav-bar
|
||||||
|
v-if="hasNavBar"
|
||||||
|
:title="pageTitle"
|
||||||
|
:left-text="hasBack ? $t('back') : ''"
|
||||||
|
:left-arrow="hasBack"
|
||||||
|
:right-text="isChinese ? $t('chinese') : $t('english')"
|
||||||
|
@click-left="handleBack"
|
||||||
|
@click-right="handleChangeLang"
|
||||||
|
/>
|
||||||
|
<router-view />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import Vue from 'vue'
|
||||||
|
import { Locale } from 'vant'
|
||||||
|
import zhCN from 'vant/es/locale/lang/zh-CN'
|
||||||
|
import enUS from 'vant/es/locale/lang/en-US'
|
||||||
|
|
||||||
|
const ZH = 'zh-CN'
|
||||||
|
const EN = 'en-US'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'App',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
currentLang: ZH
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
// 默认中文
|
||||||
|
Vue.ls.set('language', ZH, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
Locale.use('zh-CN', zhCN)
|
||||||
|
this.$i18n.locale = ZH
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 是否中文
|
||||||
|
isChinese () {
|
||||||
|
return this.currentLang === ZH
|
||||||
|
},
|
||||||
|
// 是否显示导航
|
||||||
|
hasNavBar () {
|
||||||
|
return this.$route.meta.hasNavBar
|
||||||
|
},
|
||||||
|
// 是否显示返回
|
||||||
|
hasBack () {
|
||||||
|
return this.$route.meta.hasBack
|
||||||
|
},
|
||||||
|
// 导航标题(国际化)
|
||||||
|
pageTitle () {
|
||||||
|
if (!this.$route.meta.pageTitle) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return this.$t('pageTitle.' + this.$route.meta.pageTitle)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 返回上一层
|
||||||
|
handleBack () {
|
||||||
|
this.$router.go(-1)
|
||||||
|
},
|
||||||
|
// 切换语言
|
||||||
|
handleChangeLang () {
|
||||||
|
// 如果是中文就切换英文,否则切换中文
|
||||||
|
const targetLang = this.isChinese ? EN : ZH
|
||||||
|
const vantLang = this.isChinese ? enUS : zhCN
|
||||||
|
// 更新响应式
|
||||||
|
this.currentLang = targetLang
|
||||||
|
// 更新本地存储
|
||||||
|
Vue.ls.set('language', targetLang, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
// 更新vant语言
|
||||||
|
Locale.use(targetLang, vantLang)
|
||||||
|
// 更新i18n语言
|
||||||
|
this.$i18n.locale = targetLang
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
</style>
|
||||||
+230
@@ -0,0 +1,230 @@
|
|||||||
|
import { getAction, httpAction, postAction, putAction } from '@/api/manage'
|
||||||
|
import Vue from 'vue'
|
||||||
|
import { UI_CACHE_DB_DICT_DATA } from '@/store/mutation-types'
|
||||||
|
|
||||||
|
// 角色管理
|
||||||
|
const addRole = (params) => postAction('/sys/role/add', params)
|
||||||
|
const editRole = (params) => postAction('/sys/role/edit', params)
|
||||||
|
const checkRoleCode = (params) => getAction('/sys/role/checkRoleCode', params)
|
||||||
|
const queryall = (params) => getAction('/sys/role/queryall', params)
|
||||||
|
|
||||||
|
// 用户管理
|
||||||
|
const addUser = (params) => postAction('/sys/user/add', params)
|
||||||
|
const editUser = (params) => postAction('/sys/user/edit', params)
|
||||||
|
const queryUserRole = (params) => getAction('/sys/user/queryUserRole', params)
|
||||||
|
const getUserList = (params) => getAction('/sys/user/page', params)
|
||||||
|
const frozenBatch = (params) => postAction('/sys/user/frozenBatch', params)
|
||||||
|
// 验证用户是否存在
|
||||||
|
const checkOnlyUser = (params) => getAction('/sys/user/checkOnlyUser', params)
|
||||||
|
// 改变密码
|
||||||
|
const changePassword = (params) => postAction('/sys/user/changePassword', params)
|
||||||
|
// 单点登录获取用户信息
|
||||||
|
const getSSOUserInfo = (params) => postAction('/iam/loginByOauth2', params)
|
||||||
|
|
||||||
|
// 权限管理
|
||||||
|
const addPermission = (params) => postAction('/sys/permission/add', params)
|
||||||
|
const editPermission = (params) => postAction('/sys/permission/edit', params)
|
||||||
|
const getPermissionList = (params) => getAction('/sys/permission/page', params)
|
||||||
|
const getSystemMenuList = (params) => getAction('/sys/permission/getSystemMenuList', params)
|
||||||
|
const getSystemSubmenu = (params) => getAction('/sys/permission/getSystemSubmenu', params)
|
||||||
|
const getSystemSubmenuBatch = (params) => getAction('/sys/permission/getSystemSubmenuBatch', params)
|
||||||
|
const queryTreeList = (params) => getAction('/sys/permission/queryTreeList', params)
|
||||||
|
const queryTreeListForRole = (params) => getAction('/sys/role/queryTreeList', params)
|
||||||
|
const queryListAsync = (params) => getAction('/sys/permission/queryListAsync', params)
|
||||||
|
const queryRolePermission = (params) => getAction('/sys/permission/queryRolePermission', params)
|
||||||
|
const saveRolePermission = (params) => postAction('/sys/permission/saveRolePermission', params)
|
||||||
|
const queryPermissionsByUser = () => getAction('/sys/permission/getUserPermissionByToken')
|
||||||
|
const loadAllRoleIds = (params) => getAction('/sys/permission/loadAllRoleIds', params)
|
||||||
|
const getPermissionRuleList = (params) => getAction('/sys/permission/getPermRuleListByPermId', params)
|
||||||
|
const queryPermissionRule = (params) => getAction('/sys/permission/queryPermissionRule', params)
|
||||||
|
|
||||||
|
// 部门管理
|
||||||
|
const queryDepartTreeList = (params) => getAction('/sys/sysDepart/queryTreeList', params)
|
||||||
|
const queryDepartTreeSync = (params) => getAction('/sys/sysDepart/queryDepartTreeSync', params)
|
||||||
|
const queryIdTree = (params) => getAction('/sys/sysDepart/queryIdTree', params)
|
||||||
|
const queryParentName = (params) => getAction('/sys/sysDepart/queryParentName', params)
|
||||||
|
const searchByKeywords = (params) => getAction('/sys/sysDepart/searchBy', params)
|
||||||
|
const deleteByDepartId = (params) => postAction('/sys/sysDepart/delete', params)
|
||||||
|
|
||||||
|
// 二级部门管理
|
||||||
|
const queryDepartPermission = (params) => getAction('/sys/permission/queryDepartPermission', params)
|
||||||
|
const saveDepartPermission = (params) => postAction('/sys/permission/saveDepartPermission', params)
|
||||||
|
const queryTreeListForDeptRole = (params) => getAction('/sys/sysDepartPermission/queryTreeListForDeptRole', params)
|
||||||
|
const queryDeptRolePermission = (params) => getAction('/sys/sysDepartPermission/queryDeptRolePermission', params)
|
||||||
|
const queryMyDepartTreeList = (params) => getAction('/sys/sysDepart/queryMyDeptTreeList', params)
|
||||||
|
|
||||||
|
// 日志管理
|
||||||
|
const deleteLog = (params) => postAction('/sys/log/delete', params)
|
||||||
|
const deleteLogList = (params) => postAction('/sys/log/deleteBatch', params)
|
||||||
|
|
||||||
|
// 数据字典
|
||||||
|
const addDict = (params) => postAction('/sys/dict/add', params)
|
||||||
|
const editDict = (params) => postAction('/sys/dict/edit', params)
|
||||||
|
const treeList = (params) => getAction('/sys/dict/treeList', params)
|
||||||
|
const queryDictName = (params) => getAction('/sys/dict/queryDictName', params)
|
||||||
|
const addDictItem = (params) => postAction('/sys/dictItem/add', params)
|
||||||
|
const editDictItem = (params) => postAction('/sys/dictItem/edit', params)
|
||||||
|
// 获得数据字典的树形格式数据
|
||||||
|
const getDictTreeList = (params) => getAction('/sys/dictItem/treeList', params)
|
||||||
|
// 获取能在form中使用的数据字典树形格式数据
|
||||||
|
const getFormDictTreeList = (params) => getAction('/sys/dictItem/treeListOption', params)
|
||||||
|
// 通过code值获取字典数据
|
||||||
|
const getDictByCode = (params) => getAction('/sys/dictItem/listByCodes', params)
|
||||||
|
|
||||||
|
// 字典标签专用(通过code获取字典数组)
|
||||||
|
export const ajaxGetDictItems = (code, params) => getAction(`/sys/dict/getDictItems/${code}`, params)
|
||||||
|
|
||||||
|
// 从缓存中获取字典配置
|
||||||
|
function getDictItemsFromCache (dictCode) {
|
||||||
|
if (Vue.ls.get(UI_CACHE_DB_DICT_DATA) && Vue.ls.get(UI_CACHE_DB_DICT_DATA)[dictCode] && Vue.ls.get(UI_CACHE_DB_DICT_DATA)[dictCode].length > 0) {
|
||||||
|
return Vue.ls.get(UI_CACHE_DB_DICT_DATA)[dictCode]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 系统通告
|
||||||
|
const doReleaseData = (params) => getAction('/sys/annountCement/doReleaseData', params)
|
||||||
|
const doReovkeData = (params) => getAction('/sys/annountCement/doReovkeData', params)
|
||||||
|
// 获取系统访问量
|
||||||
|
const getLoginfo = (params) => getAction('/sys/loginfo', params)
|
||||||
|
const getVisitInfo = (params) => getAction('/sys/visitInfo', params)
|
||||||
|
|
||||||
|
// 根据部门主键查询用户信息
|
||||||
|
const queryUserByDepId = (params) => getAction('/sys/user/queryUserByDepId', params)
|
||||||
|
|
||||||
|
// 重复校验
|
||||||
|
const duplicateCheck = (params) => getAction('/sys/duplicate/check', params)
|
||||||
|
// 加载分类字典
|
||||||
|
const loadCategoryData = (params) => getAction('/sys/category/loadAllData', params)
|
||||||
|
const checkRuleByCode = (params) => getAction('/sys/checkRule/checkByCode', params)
|
||||||
|
// 加载我的通告信息
|
||||||
|
const getUserNoticeInfo = (params) => getAction('/sys/sysAnnouncementSend/getMyAnnouncementSend', params)
|
||||||
|
const getTransitURL = url => `/sys/common/transitRESTful?url=${encodeURIComponent(url)}`
|
||||||
|
// 中转HTTP请求
|
||||||
|
export const transitRESTful = {
|
||||||
|
get: (url, parameter) => getAction(getTransitURL(url), parameter),
|
||||||
|
post: (url, parameter) => postAction(getTransitURL(url), parameter),
|
||||||
|
put: (url, parameter) => putAction(getTransitURL(url), parameter),
|
||||||
|
http: (url, parameter) => httpAction(getTransitURL(url), parameter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标签管理- 展示区域查询接口
|
||||||
|
const getShowAreaData = (params) => getAction('/tag/LawsArea/queryShowArea', params)
|
||||||
|
// 标签管理-展示区域管理-新增
|
||||||
|
const addAreaData = (params) => postAction('/tag/LawsArea/add', params)
|
||||||
|
// 标签管理-展示区域管理-编辑
|
||||||
|
const editAreaData = (params) => postAction('/tag/LawsArea/edit', params)
|
||||||
|
|
||||||
|
// 标签管理- 新增
|
||||||
|
const addTag = (params) => postAction('/tag/lawsTag/add', params)
|
||||||
|
// 标签管理- 编辑
|
||||||
|
const editTag = (params) => postAction('/tag/lawsTag/edit', params)
|
||||||
|
// 标签内容管理- 新增
|
||||||
|
const addCategoryItem = (params) => postAction('/sys/category/add', params)
|
||||||
|
const editCategoryItem = (params) => postAction('/sys/category/edit', params)
|
||||||
|
|
||||||
|
// 通过文件的id获取文件的相应信息
|
||||||
|
const getFileInfo = (params) => getAction('/sys/oss/file/queryById', params)
|
||||||
|
|
||||||
|
// 标准选择框,分页查询标准数据
|
||||||
|
const getStandardList = (params) => getAction('/laws/standard/common/getManyStandardSelectionBox', params)
|
||||||
|
|
||||||
|
// 内部工作组,左侧树查询
|
||||||
|
const getWorkGroupTreeList = (params) => getAction('/sys/lawsWorkingGroup/list', params)
|
||||||
|
|
||||||
|
// 企业级别映射管理,获取列表
|
||||||
|
const getEnterpriseLevelMapList = (params) => getAction('/sys/lawsGrade/list', params)
|
||||||
|
|
||||||
|
// ASMS接口管理-新增
|
||||||
|
const addAsmsInterface = (params) => postAction('/docking/asms/api/lawsAsmsOpenApi/add', params)
|
||||||
|
// ASMS接口管理-编辑
|
||||||
|
const editAsmsInterface = (params) => postAction('/docking/asms/api/lawsAsmsOpenApi/edit', params)
|
||||||
|
// ASMS接口管理-查看
|
||||||
|
const getAsmsInterfaceById = (params) => getAction('/docking/asms/api/lawsAsmsOpenApi/getInfoById', params)
|
||||||
|
// ASMS接口管理-同步
|
||||||
|
const syncAsmsInterface = (params) => getAction('/docking/asms/api/lawsAsmsOpenApi/syncBatch', params)
|
||||||
|
// ASMS接口管理-删除字典配置项
|
||||||
|
const batchDelDictItemAsmsInterface = (params) => getAction('/docking/asms/api/lawsAsmsOpenApi/removeDictItemBatch', params)
|
||||||
|
|
||||||
|
export {
|
||||||
|
addRole,
|
||||||
|
editRole,
|
||||||
|
checkRoleCode,
|
||||||
|
addUser,
|
||||||
|
editUser,
|
||||||
|
queryUserRole,
|
||||||
|
getUserList,
|
||||||
|
queryall,
|
||||||
|
frozenBatch,
|
||||||
|
checkOnlyUser,
|
||||||
|
changePassword,
|
||||||
|
getPermissionList,
|
||||||
|
addPermission,
|
||||||
|
editPermission,
|
||||||
|
queryTreeList,
|
||||||
|
queryListAsync,
|
||||||
|
queryRolePermission,
|
||||||
|
saveRolePermission,
|
||||||
|
queryPermissionsByUser,
|
||||||
|
loadAllRoleIds,
|
||||||
|
getPermissionRuleList,
|
||||||
|
queryPermissionRule,
|
||||||
|
queryDepartTreeList,
|
||||||
|
queryDepartTreeSync,
|
||||||
|
queryIdTree,
|
||||||
|
queryParentName,
|
||||||
|
searchByKeywords,
|
||||||
|
deleteByDepartId,
|
||||||
|
deleteLog,
|
||||||
|
deleteLogList,
|
||||||
|
addDict,
|
||||||
|
editDict,
|
||||||
|
treeList,
|
||||||
|
queryDictName,
|
||||||
|
addDictItem,
|
||||||
|
editDictItem,
|
||||||
|
getDictTreeList,
|
||||||
|
getFormDictTreeList,
|
||||||
|
getDictByCode,
|
||||||
|
doReleaseData,
|
||||||
|
doReovkeData,
|
||||||
|
getLoginfo,
|
||||||
|
getVisitInfo,
|
||||||
|
queryUserByDepId,
|
||||||
|
duplicateCheck,
|
||||||
|
queryTreeListForRole,
|
||||||
|
getSystemMenuList,
|
||||||
|
getSystemSubmenu,
|
||||||
|
getSystemSubmenuBatch,
|
||||||
|
loadCategoryData,
|
||||||
|
checkRuleByCode,
|
||||||
|
queryDepartPermission,
|
||||||
|
saveDepartPermission,
|
||||||
|
queryTreeListForDeptRole,
|
||||||
|
queryDeptRolePermission,
|
||||||
|
queryMyDepartTreeList,
|
||||||
|
getUserNoticeInfo,
|
||||||
|
getDictItemsFromCache,
|
||||||
|
|
||||||
|
getShowAreaData,
|
||||||
|
addAreaData,
|
||||||
|
editAreaData,
|
||||||
|
getFileInfo,
|
||||||
|
|
||||||
|
addTag,
|
||||||
|
editTag,
|
||||||
|
addCategoryItem,
|
||||||
|
editCategoryItem,
|
||||||
|
|
||||||
|
getStandardList,
|
||||||
|
|
||||||
|
getWorkGroupTreeList,
|
||||||
|
|
||||||
|
getEnterpriseLevelMapList,
|
||||||
|
getSSOUserInfo,
|
||||||
|
|
||||||
|
addAsmsInterface,
|
||||||
|
editAsmsInterface,
|
||||||
|
getAsmsInterfaceById,
|
||||||
|
syncAsmsInterface,
|
||||||
|
batchDelDictItemAsmsInterface
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
const api = {
|
||||||
|
Login: '/sys/login',
|
||||||
|
Logout: '/sys/logout',
|
||||||
|
ForgePassword: '/auth/forge-password',
|
||||||
|
Register: '/auth/register',
|
||||||
|
SendSms: '/account/sms',
|
||||||
|
// get my info
|
||||||
|
UserInfo: '/user/info'
|
||||||
|
}
|
||||||
|
export default api
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import api from './index'
|
||||||
|
import { axios } from '@/utils/request'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* login func
|
||||||
|
* parameter: {
|
||||||
|
* username: '',
|
||||||
|
* password: '',
|
||||||
|
* remember_me: true,
|
||||||
|
* captcha: '12345'
|
||||||
|
* }
|
||||||
|
* @param parameter
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function login (parameter) {
|
||||||
|
return axios({
|
||||||
|
url: '/sys/login',
|
||||||
|
method: 'post',
|
||||||
|
data: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function phoneLogin (parameter) {
|
||||||
|
return axios({
|
||||||
|
url: '/sys/phoneLogin',
|
||||||
|
method: 'post',
|
||||||
|
data: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSmsCaptcha (parameter) {
|
||||||
|
return axios({
|
||||||
|
url: api.SendSms,
|
||||||
|
method: 'post',
|
||||||
|
data: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// export function getInfo() {
|
||||||
|
// return axios({
|
||||||
|
// url: '/api/user/info',
|
||||||
|
// method: 'get',
|
||||||
|
// headers: {
|
||||||
|
// 'Content-Type': 'application/json;charset=UTF-8'
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
export function logout (logoutToken) {
|
||||||
|
return axios({
|
||||||
|
url: '/sys/logout',
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json;charset=UTF-8',
|
||||||
|
'X-Access-Token': logoutToken
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方登录
|
||||||
|
* @param token
|
||||||
|
* @param thirdType
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function thirdLogin (token, thirdType) {
|
||||||
|
return axios({
|
||||||
|
url: `/sys/thirdLogin/getLoginUser/${token}/${thirdType}`,
|
||||||
|
method: 'get',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json;charset=UTF-8'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强退其他账号
|
||||||
|
* @returns {*}
|
||||||
|
* @param parameter
|
||||||
|
*/
|
||||||
|
export function forceLogout (parameter) {
|
||||||
|
return axios({
|
||||||
|
url: '/sys/online/forceLogout',
|
||||||
|
method: 'post',
|
||||||
|
data: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import { axios } from '@/utils/request'
|
||||||
|
import { ACCESS_TOKEN } from '@/store/mutation-types'
|
||||||
|
import signMd5Utils from '@/utils/encryption/signMd5Utils'
|
||||||
|
|
||||||
|
const api = {
|
||||||
|
user: '/mock/api/user',
|
||||||
|
role: '/mock/api/role',
|
||||||
|
service: '/mock/api/service',
|
||||||
|
permission: '/mock/api/permission',
|
||||||
|
permissionNoPager: '/mock/api/permission/no-pager'
|
||||||
|
}
|
||||||
|
|
||||||
|
export default api
|
||||||
|
|
||||||
|
// post
|
||||||
|
export function postAction (url, parameter) {
|
||||||
|
const sign = signMd5Utils.getSign(url, parameter)
|
||||||
|
// 将签名和时间戳,添加在请求接口 Header
|
||||||
|
const signHeader = { 'X-Sign': sign, 'X-TIMESTAMP': signMd5Utils.getDateTimeToString() }
|
||||||
|
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
method: 'post',
|
||||||
|
data: parameter,
|
||||||
|
headers: signHeader
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// post method= {post | put}
|
||||||
|
export function httpAction (url, parameter, method) {
|
||||||
|
const sign = signMd5Utils.getSign(url, parameter)
|
||||||
|
// 将签名和时间戳,添加在请求接口 Header
|
||||||
|
const signHeader = { 'X-Sign': sign, 'X-TIMESTAMP': signMd5Utils.getDateTimeToString() }
|
||||||
|
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
method: method,
|
||||||
|
data: parameter,
|
||||||
|
headers: signHeader
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// put
|
||||||
|
export function putAction (url, parameter) {
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
method: 'put',
|
||||||
|
data: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// get
|
||||||
|
export function getAction (url, parameter) {
|
||||||
|
const sign = signMd5Utils.getSign(url, parameter)
|
||||||
|
// 将签名和时间戳,添加在请求接口 Header
|
||||||
|
const signHeader = { 'X-Sign': sign, 'X-TIMESTAMP': signMd5Utils.getDateTimeToString() }
|
||||||
|
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
method: 'get',
|
||||||
|
params: parameter,
|
||||||
|
headers: signHeader
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleteAction
|
||||||
|
export function deleteAction (url, parameter) {
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
method: 'delete',
|
||||||
|
params: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUserList (parameter) {
|
||||||
|
return axios({
|
||||||
|
url: api.user,
|
||||||
|
method: 'get',
|
||||||
|
params: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRoleList (parameter) {
|
||||||
|
return axios({
|
||||||
|
url: api.role,
|
||||||
|
method: 'get',
|
||||||
|
params: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getServiceList (parameter) {
|
||||||
|
return axios({
|
||||||
|
url: api.service,
|
||||||
|
method: 'get',
|
||||||
|
params: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPermissions (parameter) {
|
||||||
|
return axios({
|
||||||
|
url: api.permissionNoPager,
|
||||||
|
method: 'get',
|
||||||
|
params: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveService (parameter) {
|
||||||
|
return axios({
|
||||||
|
url: api.service,
|
||||||
|
method: 'post',
|
||||||
|
data: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载文件 用于excel导出
|
||||||
|
* @param url
|
||||||
|
* @param parameter
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function downFile (url, parameter) {
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
params: parameter,
|
||||||
|
method: 'get',
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载文件 用于excel导出
|
||||||
|
* @param url
|
||||||
|
* @param parameter
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function postDownFile (url, parameter) {
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
data: parameter,
|
||||||
|
method: 'post',
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载文件
|
||||||
|
* @param url 文件路径
|
||||||
|
* @param fileName 文件名
|
||||||
|
* @param parameter
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function downloadFile (url, fileName, parameter) {
|
||||||
|
return downFile(url, parameter).then((data) => {
|
||||||
|
if (!data || data.size === 0) {
|
||||||
|
Vue.prototype.$message.warning('文件下载失败')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (typeof window.navigator.msSaveBlob !== 'undefined') {
|
||||||
|
window.navigator.msSaveBlob(new Blob([data]), fileName)
|
||||||
|
} else {
|
||||||
|
const url = window.URL.createObjectURL(new Blob([data]))
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.style.display = 'none'
|
||||||
|
link.href = url
|
||||||
|
link.setAttribute('download', fileName)
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link) // 下载完成移除元素
|
||||||
|
window.URL.revokeObjectURL(url) // 释放掉blob对象
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传 用于富文本上传图片
|
||||||
|
* @param url
|
||||||
|
* @param parameter
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function uploadAction (url, parameter) {
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
data: parameter,
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data' // 文件上传
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件服务访问路径
|
||||||
|
* @param avatar
|
||||||
|
* @param subStr
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function getFileAccessHttpUrl (avatar, subStr) {
|
||||||
|
if (!subStr) subStr = 'http'
|
||||||
|
try {
|
||||||
|
if (avatar && avatar.startsWith(subStr)) {
|
||||||
|
return avatar
|
||||||
|
} else {
|
||||||
|
if (avatar && avatar.length > 0 && avatar.indexOf('[') === -1) {
|
||||||
|
const token = Vue.ls.get(ACCESS_TOKEN)
|
||||||
|
return window._CONFIG.staticDomainURL + '/' + avatar + '?token=' + token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* params传参的post
|
||||||
|
*/
|
||||||
|
export function postForParams (url, parameter) {
|
||||||
|
const sign = signMd5Utils.getSign(url, parameter)
|
||||||
|
// 将签名和时间戳,添加在请求接口 Header
|
||||||
|
const signHeader = { 'X-Sign': sign, 'X-TIMESTAMP': signMd5Utils.getDateTimeToString() }
|
||||||
|
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
method: 'post',
|
||||||
|
params: parameter,
|
||||||
|
headers: signHeader
|
||||||
|
})
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
@@ -0,0 +1 @@
|
|||||||
|
@primary-color: '#D52C26';
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
@@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
pageTitle: {
|
||||||
|
home: 'home'
|
||||||
|
},
|
||||||
|
back: 'back',
|
||||||
|
chinese: 'chinese',
|
||||||
|
english: 'english',
|
||||||
|
noMobile: '当前节点不支持手机端操作',
|
||||||
|
toPc: '请前往PC端进行操作'
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
pageTitle: {
|
||||||
|
home: '首页'
|
||||||
|
},
|
||||||
|
back: '返回',
|
||||||
|
chinese: '中',
|
||||||
|
english: '英',
|
||||||
|
noMobile: '当前节点不支持手机端操作',
|
||||||
|
toPc: '请前往PC端进行操作'
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import App from './App.vue'
|
||||||
|
import router from './router'
|
||||||
|
import store from './store'
|
||||||
|
import Storage from 'vue-ls'
|
||||||
|
|
||||||
|
import Vant from 'vant'
|
||||||
|
import 'vant/lib/index.css'
|
||||||
|
import 'vant/lib/index.less'
|
||||||
|
|
||||||
|
import VueI18n from 'vue-i18n'
|
||||||
|
import LangENUS from './common/lang/en-us'
|
||||||
|
import LangZHCN from './common/lang/zh-cn'
|
||||||
|
import { ACCESS_TOKEN, USER_INFO } from '@/store/mutation-types'
|
||||||
|
import './permission'
|
||||||
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
|
Vue.use(Vant)
|
||||||
|
Vue.use(VueI18n)
|
||||||
|
|
||||||
|
const i18n = new VueI18n({
|
||||||
|
locale: 'zh-CN',
|
||||||
|
messages: {
|
||||||
|
'en-US': LangENUS,
|
||||||
|
'zh-CN': LangZHCN
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Vue.use(Storage, {
|
||||||
|
namespace: 'pro__', // key prefix
|
||||||
|
name: 'ls', // name variable Vue.[ls] or this.[$ls],
|
||||||
|
storage: 'local' // storage name session, local, memory
|
||||||
|
})
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
router,
|
||||||
|
store,
|
||||||
|
i18n,
|
||||||
|
mounted () {
|
||||||
|
store.commit('SET_TOKEN', Vue.ls.get(ACCESS_TOKEN))
|
||||||
|
store.commit('SET_INFO', Vue.ls.get(USER_INFO))
|
||||||
|
},
|
||||||
|
render: h => h(App)
|
||||||
|
}).$mount('#app')
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import router from './router'
|
||||||
|
import store from './store'
|
||||||
|
import { ACCESS_TOKEN, UI_CACHE_DB_DICT_DATA, USER_INFO, USER_NAME } from '@/store/mutation-types'
|
||||||
|
import { welcome } from '@/utils/util'
|
||||||
|
import { getSSOUserInfo } from './api/api'
|
||||||
|
|
||||||
|
const whiteList = ['/user/login'] // no redirect whitelist
|
||||||
|
|
||||||
|
router.beforeEach(async (to, from, next) => {
|
||||||
|
// 单点登录
|
||||||
|
if (to.query.code) {
|
||||||
|
const { result } = await getSSOUserInfo({ code: to.query.code })
|
||||||
|
const userInfo = result.userInfo
|
||||||
|
Vue.ls.set(ACCESS_TOKEN, result.token, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
Vue.ls.set(USER_NAME, userInfo.username, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
Vue.ls.set(USER_INFO, userInfo, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
Vue.ls.set(UI_CACHE_DB_DICT_DATA, result.sysAllDictItems, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
store.commit('SET_TOKEN', result.token)
|
||||||
|
store.commit('SET_INFO', userInfo)
|
||||||
|
store.commit('SET_NAME', { username: userInfo.username, realname: userInfo.realname, welcome: welcome() })
|
||||||
|
store.commit('SET_AVATAR', userInfo.avatar)
|
||||||
|
}
|
||||||
|
if (Vue.ls.get(ACCESS_TOKEN)) {
|
||||||
|
/* has token */
|
||||||
|
if (to.path === '/user/login') {
|
||||||
|
next('/')
|
||||||
|
} else {
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (whiteList.indexOf(to.path) !== -1) {
|
||||||
|
// 在免登录白名单,直接进入
|
||||||
|
if (to.path === '/user/login' && to.path !== process.env.VUE_APP_LOGIN_PAGE) {
|
||||||
|
window.location.replace(process.env.VUE_APP_LOGIN_PAGE)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
next()
|
||||||
|
} else {
|
||||||
|
const path = '/user/login'
|
||||||
|
if (path === '/user/login' && path !== process.env.VUE_APP_LOGIN_PAGE) {
|
||||||
|
window.location.replace(process.env.VUE_APP_LOGIN_PAGE)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
next({ path: path, query: { redirect: to.fullPath } })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.afterEach(() => {
|
||||||
|
|
||||||
|
})
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import VueRouter from 'vue-router'
|
||||||
|
|
||||||
|
Vue.use(VueRouter)
|
||||||
|
|
||||||
|
const routes = [
|
||||||
|
{ // 登录页
|
||||||
|
path: '/user/login',
|
||||||
|
name: 'login',
|
||||||
|
component: () => import('@/views/user/Login'),
|
||||||
|
meta: {
|
||||||
|
// 是否显示头部导航
|
||||||
|
hasNavBar: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
name: 'home',
|
||||||
|
component: () => import('@/views/Home'),
|
||||||
|
meta: {
|
||||||
|
// 是否显示头部导航
|
||||||
|
hasNavBar: true,
|
||||||
|
// 当前页标题(国际化的标题,对应$t('pageTitle.home')中的home,如果为空则不显示
|
||||||
|
pageTitle: 'home',
|
||||||
|
// 是否显示返回
|
||||||
|
hasBack: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{ // 流程中节点不支持的页面
|
||||||
|
path: '/noMobile',
|
||||||
|
name: 'NoMobile',
|
||||||
|
meta: {
|
||||||
|
hasNavBar: true,
|
||||||
|
hasBack: true
|
||||||
|
},
|
||||||
|
component: () => import('@/views/exception/NoMobile')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '*',
|
||||||
|
redirect: '/'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const originalPush = VueRouter.prototype.push
|
||||||
|
VueRouter.prototype.push = function push (location, onResolve, onReject) {
|
||||||
|
if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
|
||||||
|
return originalPush.call(this, location).catch(err => err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const router = new VueRouter({
|
||||||
|
mode: 'history',
|
||||||
|
base: process.env.BASE_URL,
|
||||||
|
routes
|
||||||
|
})
|
||||||
|
|
||||||
|
export default router
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import { USER_INFO, ENHANCE_PRE } from '@/store/mutation-types'
|
||||||
|
|
||||||
|
const getters = {
|
||||||
|
device: state => state.app.device,
|
||||||
|
theme: state => state.app.theme,
|
||||||
|
color: state => state.app.color,
|
||||||
|
token: state => state.user.token,
|
||||||
|
avatar: state => {
|
||||||
|
state.user.avatar = Vue.ls.get(USER_INFO).avatar
|
||||||
|
return state.user.avatar
|
||||||
|
},
|
||||||
|
username: state => state.user.username,
|
||||||
|
nickname: state => {
|
||||||
|
state.user.realname = Vue.ls.get(USER_INFO).realname
|
||||||
|
return state.user.realname
|
||||||
|
},
|
||||||
|
welcome: state => state.user.welcome,
|
||||||
|
permissionList: state => state.user.permissionList,
|
||||||
|
userInfo: state => {
|
||||||
|
state.user.info = Vue.ls.get(USER_INFO)
|
||||||
|
return state.user.info
|
||||||
|
},
|
||||||
|
addRouters: state => state.permission.addRouters,
|
||||||
|
onlAuthFields: state => {
|
||||||
|
return state.online.authFields
|
||||||
|
},
|
||||||
|
enhanceJs: (state) => (code) => {
|
||||||
|
state.enhance.enhanceJs[code] = Vue.ls.get(ENHANCE_PRE + code)
|
||||||
|
return state.enhance.enhanceJs[code]
|
||||||
|
},
|
||||||
|
isEmbedded: state => state.app.isEmbedded,
|
||||||
|
defaultHeight: state => state.app.defaultHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getters
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import Vuex from 'vuex'
|
||||||
|
|
||||||
|
import app from './modules/app'
|
||||||
|
import user from './modules/user'
|
||||||
|
import getters from './getters'
|
||||||
|
|
||||||
|
Vue.use(Vuex)
|
||||||
|
|
||||||
|
export default new Vuex.Store({
|
||||||
|
modules: {
|
||||||
|
app,
|
||||||
|
user
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
|
||||||
|
},
|
||||||
|
getters
|
||||||
|
})
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import {
|
||||||
|
SIDEBAR_TYPE,
|
||||||
|
DEFAULT_THEME,
|
||||||
|
DEFAULT_LAYOUT_MODE,
|
||||||
|
DEFAULT_COLOR,
|
||||||
|
DEFAULT_COLOR_WEAK,
|
||||||
|
DEFAULT_FIXED_HEADER,
|
||||||
|
DEFAULT_FIXED_SIDEMENU,
|
||||||
|
DEFAULT_FIXED_HEADER_HIDDEN,
|
||||||
|
DEFAULT_CONTENT_WIDTH_TYPE,
|
||||||
|
DEFAULT_MULTI_PAGE
|
||||||
|
} from '@/store/mutation-types'
|
||||||
|
|
||||||
|
const app = {
|
||||||
|
state: {
|
||||||
|
sidebar: {
|
||||||
|
opened: true,
|
||||||
|
withoutAnimation: false
|
||||||
|
},
|
||||||
|
device: 'desktop',
|
||||||
|
theme: '',
|
||||||
|
layout: '',
|
||||||
|
contentWidth: '',
|
||||||
|
fixedHeader: false,
|
||||||
|
fixSiderbar: false,
|
||||||
|
autoHideHeader: false,
|
||||||
|
color: null,
|
||||||
|
weak: false,
|
||||||
|
multipage: true, // 默认多页签模式
|
||||||
|
isEmbedded: false, // 是否嵌入其他系统
|
||||||
|
defaultHeight: {} // 包含用户信息的高度、面包屑的高度、单行查询条件的高度、单行操作列的高度
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
SET_SIDEBAR_TYPE: (state, type) => {
|
||||||
|
state.sidebar.opened = type
|
||||||
|
Vue.ls.set(SIDEBAR_TYPE, type)
|
||||||
|
},
|
||||||
|
CLOSE_SIDEBAR: (state, withoutAnimation) => {
|
||||||
|
Vue.ls.set(SIDEBAR_TYPE, true)
|
||||||
|
state.sidebar.opened = false
|
||||||
|
state.sidebar.withoutAnimation = withoutAnimation
|
||||||
|
},
|
||||||
|
TOGGLE_DEVICE: (state, device) => {
|
||||||
|
state.device = device
|
||||||
|
},
|
||||||
|
TOGGLE_THEME: (state, theme) => {
|
||||||
|
// setStore('_DEFAULT_THEME', theme)
|
||||||
|
Vue.ls.set(DEFAULT_THEME, theme)
|
||||||
|
state.theme = theme
|
||||||
|
},
|
||||||
|
TOGGLE_LAYOUT_MODE: (state, layout) => {
|
||||||
|
Vue.ls.set(DEFAULT_LAYOUT_MODE, layout)
|
||||||
|
state.layout = layout
|
||||||
|
},
|
||||||
|
TOGGLE_FIXED_HEADER: (state, fixed) => {
|
||||||
|
Vue.ls.set(DEFAULT_FIXED_HEADER, fixed)
|
||||||
|
state.fixedHeader = fixed
|
||||||
|
},
|
||||||
|
TOGGLE_FIXED_SIDERBAR: (state, fixed) => {
|
||||||
|
Vue.ls.set(DEFAULT_FIXED_SIDEMENU, fixed)
|
||||||
|
state.fixSiderbar = fixed
|
||||||
|
},
|
||||||
|
TOGGLE_FIXED_HEADER_HIDDEN: (state, show) => {
|
||||||
|
Vue.ls.set(DEFAULT_FIXED_HEADER_HIDDEN, show)
|
||||||
|
state.autoHideHeader = show
|
||||||
|
},
|
||||||
|
TOGGLE_CONTENT_WIDTH: (state, type) => {
|
||||||
|
Vue.ls.set(DEFAULT_CONTENT_WIDTH_TYPE, type)
|
||||||
|
state.contentWidth = type
|
||||||
|
},
|
||||||
|
TOGGLE_COLOR: (state, color) => {
|
||||||
|
Vue.ls.set(DEFAULT_COLOR, color)
|
||||||
|
state.color = color
|
||||||
|
},
|
||||||
|
TOGGLE_WEAK: (state, flag) => {
|
||||||
|
Vue.ls.set(DEFAULT_COLOR_WEAK, flag)
|
||||||
|
state.weak = flag
|
||||||
|
},
|
||||||
|
SET_MULTI_PAGE (state, multipageFlag) {
|
||||||
|
Vue.ls.set(DEFAULT_MULTI_PAGE, multipageFlag)
|
||||||
|
state.multipage = multipageFlag
|
||||||
|
},
|
||||||
|
SET_IS_EMBEDDED (state, isEmbedded) {
|
||||||
|
state.isEmbedded = isEmbedded
|
||||||
|
},
|
||||||
|
SET_DEFAULT_HEIGHT (state, defaultHeight) {
|
||||||
|
state.defaultHeight = defaultHeight
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setSidebar: ({ commit }, type) => {
|
||||||
|
commit('SET_SIDEBAR_TYPE', type)
|
||||||
|
},
|
||||||
|
CloseSidebar ({ commit }, { withoutAnimation }) {
|
||||||
|
commit('CLOSE_SIDEBAR', withoutAnimation)
|
||||||
|
},
|
||||||
|
ToggleDevice ({ commit }, device) {
|
||||||
|
commit('TOGGLE_DEVICE', device)
|
||||||
|
},
|
||||||
|
ToggleTheme ({ commit }, theme) {
|
||||||
|
commit('TOGGLE_THEME', theme)
|
||||||
|
},
|
||||||
|
ToggleLayoutMode ({ commit }, mode) {
|
||||||
|
commit('TOGGLE_LAYOUT_MODE', mode)
|
||||||
|
},
|
||||||
|
ToggleFixedHeader ({ commit }, fixedHeader) {
|
||||||
|
if (!fixedHeader) {
|
||||||
|
commit('TOGGLE_FIXED_HEADER_HIDDEN', false)
|
||||||
|
}
|
||||||
|
commit('TOGGLE_FIXED_HEADER', fixedHeader)
|
||||||
|
},
|
||||||
|
ToggleFixSiderbar ({ commit }, fixSiderbar) {
|
||||||
|
commit('TOGGLE_FIXED_SIDERBAR', fixSiderbar)
|
||||||
|
},
|
||||||
|
ToggleFixedHeaderHidden ({ commit }, show) {
|
||||||
|
commit('TOGGLE_FIXED_HEADER_HIDDEN', show)
|
||||||
|
},
|
||||||
|
ToggleContentWidth ({ commit }, type) {
|
||||||
|
commit('TOGGLE_CONTENT_WIDTH', type)
|
||||||
|
},
|
||||||
|
ToggleColor ({ commit }, color) {
|
||||||
|
commit('TOGGLE_COLOR', color)
|
||||||
|
},
|
||||||
|
ToggleWeak ({ commit }, weakFlag) {
|
||||||
|
commit('TOGGLE_WEAK', weakFlag)
|
||||||
|
},
|
||||||
|
ToggleMultipage ({ commit }, multipageFlag) {
|
||||||
|
commit('SET_MULTI_PAGE', multipageFlag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default app
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import { login, logout, phoneLogin, thirdLogin } from '@/api/login'
|
||||||
|
import { ACCESS_TOKEN, USER_NAME, USER_INFO, USER_AUTH, SYS_BUTTON_AUTH, UI_CACHE_DB_DICT_DATA, TENANT_ID, CACHE_INCLUDED_ROUTES } from '@/store/mutation-types'
|
||||||
|
import store from '@/store'
|
||||||
|
import { welcome } from '@/utils/util'
|
||||||
|
import { queryPermissionsByUser } from '@/api/api'
|
||||||
|
import { getAction } from '@/api/manage'
|
||||||
|
|
||||||
|
const user = {
|
||||||
|
state: {
|
||||||
|
token: '',
|
||||||
|
username: '',
|
||||||
|
realname: '',
|
||||||
|
tenantid: '',
|
||||||
|
welcome: '',
|
||||||
|
avatar: '',
|
||||||
|
permissionList: [],
|
||||||
|
info: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
mutations: {
|
||||||
|
SET_TOKEN: (state, token) => {
|
||||||
|
state.token = token
|
||||||
|
},
|
||||||
|
SET_NAME: (state, { username, realname, welcome }) => {
|
||||||
|
state.username = username
|
||||||
|
state.realname = realname
|
||||||
|
state.welcome = welcome
|
||||||
|
},
|
||||||
|
SET_AVATAR: (state, avatar) => {
|
||||||
|
state.avatar = avatar
|
||||||
|
},
|
||||||
|
SET_PERMISSIONLIST: (state, permissionList) => {
|
||||||
|
state.permissionList = permissionList
|
||||||
|
},
|
||||||
|
SET_INFO: (state, info) => {
|
||||||
|
state.info = info
|
||||||
|
},
|
||||||
|
SET_TENANT: (state, id) => {
|
||||||
|
state.tenantid = id
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
// CAS验证登录
|
||||||
|
ValidateLogin ({ commit }, userInfo) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
getAction('/sys/cas/client/validateLogin', userInfo).then(response => {
|
||||||
|
console.log('----cas 登录--------', response)
|
||||||
|
if (response.success) {
|
||||||
|
const result = response.result
|
||||||
|
const userInfo = result.userInfo
|
||||||
|
Vue.ls.set(ACCESS_TOKEN, result.token, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
Vue.ls.set(USER_NAME, userInfo.username, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
Vue.ls.set(USER_INFO, userInfo, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
commit('SET_TOKEN', result.token)
|
||||||
|
commit('SET_INFO', userInfo)
|
||||||
|
commit('SET_NAME', { username: userInfo.username, realname: userInfo.realname, welcome: welcome() })
|
||||||
|
commit('SET_AVATAR', userInfo.avatar)
|
||||||
|
resolve(response)
|
||||||
|
} else {
|
||||||
|
resolve(response)
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 登录
|
||||||
|
Login ({ commit }, userInfo) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
login(userInfo).then(response => {
|
||||||
|
if (response.code + '' === '200') {
|
||||||
|
const result = response.result
|
||||||
|
const userInfo = result.userInfo
|
||||||
|
Vue.ls.set(ACCESS_TOKEN, result.token, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
Vue.ls.set(USER_NAME, userInfo.username, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
Vue.ls.set(USER_INFO, userInfo, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
Vue.ls.set(UI_CACHE_DB_DICT_DATA, result.sysAllDictItems, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
commit('SET_TOKEN', result.token)
|
||||||
|
commit('SET_INFO', userInfo)
|
||||||
|
commit('SET_NAME', { username: userInfo.username, realname: userInfo.realname, welcome: welcome() })
|
||||||
|
commit('SET_AVATAR', userInfo.avatar)
|
||||||
|
resolve(response)
|
||||||
|
} else {
|
||||||
|
reject(response)
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 手机号登录
|
||||||
|
PhoneLogin ({ commit }, userInfo) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
phoneLogin(userInfo).then(response => {
|
||||||
|
if (response.code + '' === '200') {
|
||||||
|
const result = response.result
|
||||||
|
const userInfo = result.userInfo
|
||||||
|
Vue.ls.set(ACCESS_TOKEN, result.token, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
Vue.ls.set(USER_NAME, userInfo.username, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
Vue.ls.set(USER_INFO, userInfo, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
Vue.ls.set(UI_CACHE_DB_DICT_DATA, result.sysAllDictItems, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
commit('SET_TOKEN', result.token)
|
||||||
|
commit('SET_INFO', userInfo)
|
||||||
|
commit('SET_NAME', { username: userInfo.username, realname: userInfo.realname, welcome: welcome() })
|
||||||
|
commit('SET_AVATAR', userInfo.avatar)
|
||||||
|
resolve(response)
|
||||||
|
} else {
|
||||||
|
reject(response)
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获取用户信息
|
||||||
|
GetPermissionList ({ commit }) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
queryPermissionsByUser().then(response => {
|
||||||
|
const menuData = response.result.menu
|
||||||
|
const authData = response.result.auth
|
||||||
|
const allAuthData = response.result.allAuth
|
||||||
|
// Vue.ls.set(USER_AUTH,authData);
|
||||||
|
sessionStorage.setItem(USER_AUTH, JSON.stringify(authData))
|
||||||
|
sessionStorage.setItem(SYS_BUTTON_AUTH, JSON.stringify(allAuthData))
|
||||||
|
if (menuData && menuData.length > 0) {
|
||||||
|
// update--begin--autor:qinfeng-----date:20200109------for: 一级菜单的子菜单全部是隐藏路由,则一级菜单不显示------
|
||||||
|
menuData.forEach((item) => {
|
||||||
|
if (item.children) {
|
||||||
|
const hasChildrenMenu = item.children.filter((i) => {
|
||||||
|
return !i.hidden || i.hidden === false
|
||||||
|
})
|
||||||
|
if (hasChildrenMenu == null || hasChildrenMenu.length === 0) {
|
||||||
|
item.hidden = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// console.log(" menu show json ", menuData)
|
||||||
|
// update--end--autor:qinfeng-----date:20200109------for: 一级菜单的子菜单全部是隐藏路由,则一级菜单不显示------
|
||||||
|
commit('SET_PERMISSIONLIST', menuData)
|
||||||
|
} else {
|
||||||
|
Vue.prototype.$Jmodal.error({
|
||||||
|
title: '无权限',
|
||||||
|
content: '该用户无权限,请联系管理员!',
|
||||||
|
okText: '确认',
|
||||||
|
mask: false,
|
||||||
|
onOk: () => {
|
||||||
|
store.dispatch('Logout')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
reject(new Error('getPermissionList: permissions must be a non-null array !'))
|
||||||
|
}
|
||||||
|
resolve(response)
|
||||||
|
}).catch(error => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 登出
|
||||||
|
Logout ({ commit, state }) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const logoutToken = state.token
|
||||||
|
commit('SET_TOKEN', '')
|
||||||
|
commit('SET_PERMISSIONLIST', [])
|
||||||
|
Vue.ls.remove(ACCESS_TOKEN)
|
||||||
|
Vue.ls.remove(USER_INFO)
|
||||||
|
Vue.ls.remove(USER_NAME)
|
||||||
|
Vue.ls.remove(UI_CACHE_DB_DICT_DATA)
|
||||||
|
Vue.ls.remove(CACHE_INCLUDED_ROUTES)
|
||||||
|
Vue.ls.remove(TENANT_ID)
|
||||||
|
// console.log('logoutToken: '+ logoutToken)
|
||||||
|
logout(logoutToken).then(() => {
|
||||||
|
if (process.env.VUE_APP_SSO + '' === 'true') {
|
||||||
|
const sevice = 'http://' + window.location.host + '/'
|
||||||
|
const serviceUrl = encodeURIComponent(sevice)
|
||||||
|
window.location.href = process.env.VUE_APP_CAS_BASE_URL + '/logout?service=' + serviceUrl
|
||||||
|
}
|
||||||
|
resolve()
|
||||||
|
window.location.replace(process.env.VUE_APP_LOGIN_PAGE)
|
||||||
|
}).catch(() => {
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 第三方登录
|
||||||
|
ThirdLogin ({ commit }, param) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
thirdLogin(param.token, param.thirdType).then(response => {
|
||||||
|
if (response.code + '' === '200') {
|
||||||
|
const result = response.result
|
||||||
|
const userInfo = result.userInfo
|
||||||
|
Vue.ls.set(ACCESS_TOKEN, result.token, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
Vue.ls.set(USER_NAME, userInfo.username, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
Vue.ls.set(USER_INFO, userInfo, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
commit('SET_TOKEN', result.token)
|
||||||
|
commit('SET_INFO', userInfo)
|
||||||
|
commit('SET_NAME', { username: userInfo.username, realname: userInfo.realname, welcome: welcome() })
|
||||||
|
commit('SET_AVATAR', userInfo.avatar)
|
||||||
|
resolve(response)
|
||||||
|
} else {
|
||||||
|
reject(response)
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
saveTenant ({ commit }, id) {
|
||||||
|
Vue.ls.set(TENANT_ID, id, 7 * 24 * 60 * 60 * 1000)
|
||||||
|
commit('SET_TENANT', id)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default user
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
export const ACCESS_TOKEN = 'Access-Token'
|
||||||
|
export const SIDEBAR_TYPE = 'SIDEBAR_TYPE'
|
||||||
|
export const DEFAULT_THEME = 'DEFAULT_THEME'
|
||||||
|
export const DEFAULT_LAYOUT_MODE = 'DEFAULT_LAYOUT_MODE'
|
||||||
|
export const DEFAULT_COLOR = 'DEFAULT_COLOR'
|
||||||
|
export const DEFAULT_COLOR_WEAK = 'DEFAULT_COLOR_WEAK'
|
||||||
|
export const DEFAULT_FIXED_HEADER = 'DEFAULT_FIXED_HEADER'
|
||||||
|
export const DEFAULT_FIXED_SIDEMENU = 'DEFAULT_FIXED_SIDEMENU'
|
||||||
|
export const DEFAULT_FIXED_HEADER_HIDDEN = 'DEFAULT_FIXED_HEADER_HIDDEN'
|
||||||
|
export const DEFAULT_CONTENT_WIDTH_TYPE = 'DEFAULT_CONTENT_WIDTH_TYPE'
|
||||||
|
export const DEFAULT_MULTI_PAGE = 'DEFAULT_MULTI_PAGE'
|
||||||
|
export const USER_NAME = 'Login_Username'
|
||||||
|
export const USER_INFO = 'Login_Userinfo'
|
||||||
|
export const USER_AUTH = 'LOGIN_USER_BUTTON_AUTH'
|
||||||
|
export const SYS_BUTTON_AUTH = 'SYS_BUTTON_AUTH'
|
||||||
|
export const ENCRYPTED_STRING = 'ENCRYPTED_STRING'
|
||||||
|
export const ENHANCE_PRE = 'enhance_'
|
||||||
|
export const UI_CACHE_DB_DICT_DATA = 'UI_CACHE_DB_DICT_DATA'
|
||||||
|
export const INDEX_MAIN_PAGE_PATH = '/dashboard/analysis'
|
||||||
|
export const OAUTH2_LOGIN_PAGE_PATH = '/oauth2-app/login'
|
||||||
|
export const TENANT_ID = 'TENANT_ID'
|
||||||
|
export const ONL_AUTH_FIELDS = 'ONL_AUTH_FIELDS'
|
||||||
|
// 路由缓存问题,关闭了tab页时再打开就不刷新 #842
|
||||||
|
export const CACHE_INCLUDED_ROUTES = 'CACHE_INCLUDED_ROUTES'
|
||||||
|
export const CONTENT_WIDTH_TYPE = {
|
||||||
|
Fluid: 'Fluid',
|
||||||
|
Fixed: 'Fixed'
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
const VueAxios = {
|
||||||
|
vm: {},
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
install (Vue, router = {}, instance) {
|
||||||
|
if (this.installed) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.installed = true
|
||||||
|
|
||||||
|
if (!instance) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error('You have to install axios')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Vue.axios = instance
|
||||||
|
|
||||||
|
Object.defineProperties(Vue.prototype, {
|
||||||
|
axios: {
|
||||||
|
get: function get () {
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
},
|
||||||
|
$http: {
|
||||||
|
get: function get () {
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
VueAxios
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
// instance as axios
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { axios } from '@/utils/request'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取RSA公钥
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function getRSAPublicKey () {
|
||||||
|
return axios({
|
||||||
|
url: `/sys/getRSAPublicKey`,
|
||||||
|
method: 'get',
|
||||||
|
timeout: 5000,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json;charset=UTF-8'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,128 @@
|
|||||||
|
import md5 from 'md5'
|
||||||
|
// 签名密钥串(前后端要一致,正式发布请自行修改)
|
||||||
|
const signatureSecret = 'dd05f1c54d63749eda95f9fa6d49v442a'
|
||||||
|
|
||||||
|
export default class signMd5Utils {
|
||||||
|
/**
|
||||||
|
* json参数升序
|
||||||
|
* @param jsonObj 发送参数
|
||||||
|
*/
|
||||||
|
|
||||||
|
static sortAsc (jsonObj) {
|
||||||
|
const arr = []
|
||||||
|
let num = 0
|
||||||
|
for (const i in jsonObj) {
|
||||||
|
arr[num] = i
|
||||||
|
num++
|
||||||
|
}
|
||||||
|
const sortArr = arr.sort()
|
||||||
|
const sortObj = {}
|
||||||
|
for (const i in sortArr) {
|
||||||
|
sortObj[sortArr[i]] = jsonObj[sortArr[i]]
|
||||||
|
}
|
||||||
|
return sortObj
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param url 请求的url,应该包含请求参数(url的?后面的参数)
|
||||||
|
* @param requestParams 请求参数(POST的JSON参数)
|
||||||
|
* @returns {string} 获取签名
|
||||||
|
*/
|
||||||
|
static getSign (url, requestParams) {
|
||||||
|
const urlParams = this.parseQueryString(url)
|
||||||
|
const jsonObj = this.mergeObject(urlParams, requestParams)
|
||||||
|
// console.log("sign jsonObj: ",jsonObj)
|
||||||
|
const requestBody = this.sortAsc(jsonObj)
|
||||||
|
console.log('sign requestBody: ', requestBody)
|
||||||
|
return md5(JSON.stringify(requestBody) + signatureSecret).toUpperCase()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param url 请求的url
|
||||||
|
* @returns {{}} 将url中请求参数组装成json对象(url的?后面的参数)
|
||||||
|
*/
|
||||||
|
static parseQueryString (url) {
|
||||||
|
const urlReg = /^[^?]+\?([\w\W]+)$/
|
||||||
|
const paramReg = /([^&=]+)=([\w\W]*?)(&|$|#)/g
|
||||||
|
const urlArray = urlReg.exec(url)
|
||||||
|
const result = {}
|
||||||
|
|
||||||
|
// 获取URL上最后带逗号的参数变量 sys/dict/getDictItems/sys_user,realname,username
|
||||||
|
// 【这边条件没有encode】带条件参数例子:/sys/dict/getDictItems/sys_user,realname,id,username!='admin'%20order%20by%20create_time
|
||||||
|
let lastpathVariable = url.substring(url.lastIndexOf('/') + 1)
|
||||||
|
if (lastpathVariable.includes(',')) {
|
||||||
|
if (lastpathVariable.includes('?')) {
|
||||||
|
lastpathVariable = lastpathVariable.substring(0, lastpathVariable.indexOf('?'))
|
||||||
|
}
|
||||||
|
// 解决Sign 签名校验失败 #2728
|
||||||
|
result['x-path-variable'] = decodeURIComponent(lastpathVariable)
|
||||||
|
}
|
||||||
|
if (urlArray && urlArray[1]) {
|
||||||
|
const paramString = urlArray[1]; let paramResult
|
||||||
|
while ((paramResult = paramReg.exec(paramString)) != null) {
|
||||||
|
// 数字值转为string类型,前后端加密规则保持一致
|
||||||
|
if (this.myIsNaN(paramResult[2])) {
|
||||||
|
paramResult[2] = paramResult[2].toString()
|
||||||
|
}
|
||||||
|
result[paramResult[1]] = paramResult[2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {*} 将两个对象合并成一个
|
||||||
|
*/
|
||||||
|
static mergeObject (objectOne, objectTwo) {
|
||||||
|
if (objectTwo && Object.keys(objectTwo).length > 0) {
|
||||||
|
for (const key in objectTwo) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(objectTwo, key) === true) {
|
||||||
|
// 数字值转为string类型,前后端加密规则保持一致
|
||||||
|
if (this.myIsNaN(objectTwo[key])) {
|
||||||
|
objectTwo[key] = objectTwo[key].toString()
|
||||||
|
}
|
||||||
|
objectOne[key] = objectTwo[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return objectOne
|
||||||
|
}
|
||||||
|
|
||||||
|
static urlEncode (param, key, encode) {
|
||||||
|
if (param == null) return ''
|
||||||
|
let paramStr = ''
|
||||||
|
const t = typeof (param)
|
||||||
|
if (t === 'string' || t === 'number' || t === 'boolean') {
|
||||||
|
paramStr += '&' + key + '=' + ((encode == null || encode) ? encodeURIComponent(param) : param)
|
||||||
|
} else {
|
||||||
|
for (const i in param) {
|
||||||
|
const k = key == null ? i : key + (param instanceof Array ? '[' + i + ']' : '.' + i)
|
||||||
|
paramStr += this.urlEncode(param[i], k, encode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paramStr
|
||||||
|
}
|
||||||
|
|
||||||
|
static getDateTimeToString () {
|
||||||
|
const date_ = new Date()
|
||||||
|
const year = date_.getFullYear()
|
||||||
|
let month = date_.getMonth() + 1
|
||||||
|
let day = date_.getDate()
|
||||||
|
if (month < 10) month = '0' + month
|
||||||
|
if (day < 10) day = '0' + day
|
||||||
|
let hours = date_.getHours()
|
||||||
|
let mins = date_.getMinutes()
|
||||||
|
let secs = date_.getSeconds()
|
||||||
|
const msecs = date_.getMilliseconds()
|
||||||
|
if (hours < 10) hours = '0' + hours
|
||||||
|
if (mins < 10) mins = '0' + mins
|
||||||
|
if (secs < 10) secs = '0' + secs
|
||||||
|
if (msecs < 10) secs = '0' + msecs
|
||||||
|
return year + '' + month + '' + day + '' + hours + '' + mins + '' + secs
|
||||||
|
}
|
||||||
|
|
||||||
|
// true:数值型的,false:非数值型
|
||||||
|
static myIsNaN (value) {
|
||||||
|
return typeof value === 'number' && !isNaN(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import axios from 'axios'
|
||||||
|
import store from '@/store'
|
||||||
|
import { VueAxios } from './axios'
|
||||||
|
import router from '@/router/index'
|
||||||
|
import { ACCESS_TOKEN, TENANT_ID } from '@/store/mutation-types'
|
||||||
|
import { Dialog, Toast } from 'vant'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【指定 axios的 baseURL】
|
||||||
|
* 如果手工指定 baseURL: '/laws-sinotruk'
|
||||||
|
* 则映射后端域名,通过 vue.config.js
|
||||||
|
* @type {*|string}
|
||||||
|
*/
|
||||||
|
const apiBaseUrl = window._CONFIG.domianURL || '/laws-sinotruk'
|
||||||
|
// console.log("apiBaseUrl= ",apiBaseUrl)
|
||||||
|
// 创建 axios 实例
|
||||||
|
const service = axios.create({
|
||||||
|
// baseURL: '/laws-sinotruk',
|
||||||
|
baseURL: apiBaseUrl, // api base_url
|
||||||
|
timeout: 30 * 60 * 1000 // 请求超时时间
|
||||||
|
})
|
||||||
|
|
||||||
|
const err = (error) => {
|
||||||
|
if (error.response) {
|
||||||
|
const data = error.response.data
|
||||||
|
const token = Vue.ls.get(ACCESS_TOKEN)
|
||||||
|
console.log('------异常响应------', token)
|
||||||
|
console.log('------异常响应------', error.response.status)
|
||||||
|
switch (error.response.status) {
|
||||||
|
case 403:
|
||||||
|
Toast('系统提示\n拒绝访问')
|
||||||
|
break
|
||||||
|
case 500:
|
||||||
|
console.log('------error.response------', error.response)
|
||||||
|
// update-begin- --- author:liusq ------ date:20200910 ---- for:处理Blob情况----
|
||||||
|
if (error.response.request.responseType === 'blob') {
|
||||||
|
blobToJson(data)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// update-end- --- author:liusq ------ date:20200910 ---- for:处理Blob情况----
|
||||||
|
if (data.includes('Token失效')) {
|
||||||
|
// update-begin- --- author:scott ------ date:20190225 ---- for:Token失效采用弹框模式,不直接跳转----
|
||||||
|
Dialog.alert({
|
||||||
|
title: '登录已过期',
|
||||||
|
message: '很抱歉,登录已过期,请重新登录',
|
||||||
|
confirmButtonText: '重新登录',
|
||||||
|
theme: 'round-button'
|
||||||
|
}).then(() => {
|
||||||
|
store.dispatch('Logout').then(() => {
|
||||||
|
Vue.ls.remove(ACCESS_TOKEN)
|
||||||
|
try {
|
||||||
|
const path = window.document.location.pathname
|
||||||
|
console.log('location pathname -> ' + path)
|
||||||
|
if (path !== '/' && path.indexOf('/user/login') === -1) {
|
||||||
|
window.location.reload()
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
window.location.reload()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// update-end- --- author:scott ------ date:20190225 ---- for:Token失效采用弹框模式,不直接跳转----
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 404:
|
||||||
|
Toast('系统提示\n很抱歉,资源未找到!')
|
||||||
|
break
|
||||||
|
case 504:
|
||||||
|
Toast('系统提示\n网络超时')
|
||||||
|
break
|
||||||
|
case 401:
|
||||||
|
Toast('系统提示\n未授权,请重新登录')
|
||||||
|
if (token) {
|
||||||
|
store.dispatch('Logout').then(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.reload()
|
||||||
|
}, 1500)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
Toast(data.message)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else if (error.message) {
|
||||||
|
if (error.message.includes('timeout')) {
|
||||||
|
Toast('网络超时')
|
||||||
|
} else {
|
||||||
|
Toast(error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// request interceptor
|
||||||
|
service.interceptors.request.use(config => {
|
||||||
|
const token = Vue.ls.get(ACCESS_TOKEN)
|
||||||
|
if (token) {
|
||||||
|
config.headers['X-Access-Token'] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
|
||||||
|
}
|
||||||
|
// update-begin--author:sunjianlei---date:20200723---for 如果当前在low-app环境,并且携带了appId,就向Header里传递appId
|
||||||
|
const $route = router.currentRoute
|
||||||
|
if ($route && $route.name && $route.name.startsWith('low-app') && $route.params.appId) {
|
||||||
|
config.headers['X-Low-App-ID'] = $route.params.appId
|
||||||
|
}
|
||||||
|
// update-end--author:sunjianlei---date:20200723---for 如果当前在low-app环境,并且携带了appId,就向Header里传递appId
|
||||||
|
|
||||||
|
// update-begin-author:taoyan date:2020707 for:多租户
|
||||||
|
let tenantid = Vue.ls.get(TENANT_ID)
|
||||||
|
if (!tenantid) {
|
||||||
|
tenantid = 0
|
||||||
|
}
|
||||||
|
config.headers['tenant-id'] = tenantid
|
||||||
|
|
||||||
|
let language = localStorage.getItem('language') || ''
|
||||||
|
if (!language) {
|
||||||
|
language = 'zh-cn'
|
||||||
|
}
|
||||||
|
const cut = language === 'zh-cn' ? 'zh' : 'en'
|
||||||
|
config.headers.Language = cut
|
||||||
|
// update-end-author:taoyan date:2020707 for:多租户
|
||||||
|
if (config.method === 'get') {
|
||||||
|
if (config.url.indexOf('sys/dict/getDictItems') < 0) {
|
||||||
|
config.params = {
|
||||||
|
_t: Date.parse(new Date()) / 1000,
|
||||||
|
...config.params
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}, (error) => {
|
||||||
|
return Promise.reject(error)
|
||||||
|
})
|
||||||
|
|
||||||
|
// response interceptor
|
||||||
|
service.interceptors.response.use((response) => {
|
||||||
|
return response.data
|
||||||
|
}, err)
|
||||||
|
|
||||||
|
const installer = {
|
||||||
|
vm: {},
|
||||||
|
install (Vue, router = {}) {
|
||||||
|
Vue.use(VueAxios, router, service)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Blob解析
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
function blobToJson (data) {
|
||||||
|
const fileReader = new FileReader()
|
||||||
|
const token = Vue.ls.get(ACCESS_TOKEN)
|
||||||
|
fileReader.onload = function () {
|
||||||
|
try {
|
||||||
|
const jsonData = JSON.parse(this.result) // 说明是普通对象数据,后台转换失败
|
||||||
|
console.log('jsonData', jsonData)
|
||||||
|
if (jsonData.status === 500) {
|
||||||
|
console.log('token----------》', token)
|
||||||
|
if (token && jsonData.message.includes('Token失效')) {
|
||||||
|
Dialog.alert({
|
||||||
|
title: '登录已过期',
|
||||||
|
message: '很抱歉,登录已过期,请重新登录',
|
||||||
|
confirmButtonText: '重新登录',
|
||||||
|
theme: 'round-button'
|
||||||
|
}).then(() => {
|
||||||
|
store.dispatch('Logout').then(() => {
|
||||||
|
Vue.ls.remove(ACCESS_TOKEN)
|
||||||
|
try {
|
||||||
|
const path = window.document.location.pathname
|
||||||
|
console.log('location pathname -> ' + path)
|
||||||
|
if (path !== '/' && path.indexOf('/user/login') === -1) {
|
||||||
|
window.location.reload()
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
window.location.reload()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// 解析成对象失败,说明是正常的文件流
|
||||||
|
console.log('blob解析fileReader返回err', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fileReader.readAsText(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
installer as VueAxios,
|
||||||
|
service as axios
|
||||||
|
}
|
||||||
@@ -0,0 +1,526 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import * as api from '@/api/api'
|
||||||
|
import { ACCESS_TOKEN } from '@/store/mutation-types'
|
||||||
|
//
|
||||||
|
export function timeFix () {
|
||||||
|
const time = new Date()
|
||||||
|
const hour = time.getHours()
|
||||||
|
return hour < 9 ? '早上好' : (hour <= 11 ? '上午好' : (hour <= 13 ? '中午好' : (hour < 20 ? '下午好' : '晚上好')))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function welcome () {
|
||||||
|
const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA', '我猜你可能累了']
|
||||||
|
const index = Math.floor((Math.random() * arr.length))
|
||||||
|
return arr[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发 window.resize
|
||||||
|
*/
|
||||||
|
export function triggerWindowResizeEvent () {
|
||||||
|
const event = document.createEvent('HTMLEvents')
|
||||||
|
event.initEvent('resize', true, true)
|
||||||
|
event.eventType = 'message'
|
||||||
|
window.dispatchEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤对象中为空的属性
|
||||||
|
* @param obj
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function filterObj (obj) {
|
||||||
|
if (!(typeof obj === 'object')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key in obj) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(obj, key) && (obj[key] == null || obj[key] === undefined || obj[key] === '')) {
|
||||||
|
delete obj[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间格式化
|
||||||
|
* @param value
|
||||||
|
* @param fmt
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function formatDate (value, fmt) {
|
||||||
|
const regPos = /^\d+(\.\d+)?$/
|
||||||
|
if (regPos.test(value)) {
|
||||||
|
// 如果是数字
|
||||||
|
const getDate = new Date(value)
|
||||||
|
const o = {
|
||||||
|
'M+': getDate.getMonth() + 1,
|
||||||
|
'd+': getDate.getDate(),
|
||||||
|
'h+': getDate.getHours(),
|
||||||
|
'm+': getDate.getMinutes(),
|
||||||
|
's+': getDate.getSeconds(),
|
||||||
|
'q+': Math.floor((getDate.getMonth() + 3) / 3),
|
||||||
|
S: getDate.getMilliseconds()
|
||||||
|
}
|
||||||
|
if (/(y+)/.test(fmt)) {
|
||||||
|
fmt = fmt.replace(RegExp.$1, (getDate.getFullYear() + '').substr(4 - RegExp.$1.length))
|
||||||
|
}
|
||||||
|
for (const k in o) {
|
||||||
|
if (new RegExp('(' + k + ')').test(fmt)) {
|
||||||
|
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
value = value.trim()
|
||||||
|
return value.substr(0, fmt.length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 深度克隆对象、数组
|
||||||
|
* @param obj 被克隆的对象
|
||||||
|
* @return 克隆后的对象
|
||||||
|
*/
|
||||||
|
export function cloneObject (obj) {
|
||||||
|
return JSON.parse(JSON.stringify(obj))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机生成数字
|
||||||
|
*
|
||||||
|
* 示例:生成长度为 12 的随机数:randomNumber(12)
|
||||||
|
* 示例:生成 3~23 之间的随机数:randomNumber(3, 23)
|
||||||
|
*
|
||||||
|
* @param1 最小值 | 长度
|
||||||
|
* @param2 最大值
|
||||||
|
* @return int 生成后的数字
|
||||||
|
*/
|
||||||
|
export function randomNumber () {
|
||||||
|
// 生成 最小值 到 最大值 区间的随机数
|
||||||
|
const random = (min, max) => {
|
||||||
|
return Math.floor(Math.random() * (max - min + 1) + min)
|
||||||
|
}
|
||||||
|
if (arguments.length === 1) {
|
||||||
|
const [length] = arguments
|
||||||
|
// 生成指定长度的随机数字,首位一定不是 0
|
||||||
|
const nums = [...Array(length).keys()].map((i) => (i > 0 ? random(0, 9) : random(1, 9)))
|
||||||
|
return parseInt(nums.join(''))
|
||||||
|
} else if (arguments.length >= 2) {
|
||||||
|
const [min, max] = arguments
|
||||||
|
return random(min, max)
|
||||||
|
} else {
|
||||||
|
return Number.NaN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机生成字符串
|
||||||
|
* @param length 字符串的长度
|
||||||
|
* @param chats 可选字符串区间(只会生成传入的字符串中的字符)
|
||||||
|
* @return string 生成的字符串
|
||||||
|
*/
|
||||||
|
export function randomString (length, chats) {
|
||||||
|
if (!length) length = 1
|
||||||
|
if (!chats) chats = '0123456789qwertyuioplkjhgfdsazxcvbnm'
|
||||||
|
let str = ''
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
const num = randomNumber(0, chats.length - 1)
|
||||||
|
str += chats[num]
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机生成uuid
|
||||||
|
* @return string 生成的uuid
|
||||||
|
*/
|
||||||
|
export function randomUUID () {
|
||||||
|
const chats = '0123456789abcdef'
|
||||||
|
return randomString(32, chats)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下划线转驼峰
|
||||||
|
* @param string
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function underLine2CamelCase (string) {
|
||||||
|
return string.replace(/_([a-z])/g, function (all, letter) {
|
||||||
|
return letter.toUpperCase()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否显示办理按钮
|
||||||
|
* @param bpmStatus
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function showDealBtn (bpmStatus) {
|
||||||
|
return bpmStatus + '' !== '1' && bpmStatus + '' !== '3' && bpmStatus + '' !== '4'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增强CSS,可以在页面上输出全局css
|
||||||
|
* @param css 要增强的css
|
||||||
|
* @param id style标签的id,可以用来清除旧样式
|
||||||
|
*/
|
||||||
|
export function cssExpand (css, id) {
|
||||||
|
const style = document.createElement('style')
|
||||||
|
style.type = 'text/css'
|
||||||
|
style.innerHTML = `@charset "UTF-8"; ${css}`
|
||||||
|
// 清除旧样式
|
||||||
|
if (id) {
|
||||||
|
const $style = document.getElementById(id)
|
||||||
|
if ($style != null) $style.outerHTML = ''
|
||||||
|
style.id = id
|
||||||
|
}
|
||||||
|
// 应用新样式
|
||||||
|
document.head.appendChild(style)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 用于js增强事件,运行JS代码,可以传参 */
|
||||||
|
// options 所需参数:
|
||||||
|
// 参数名 类型 说明
|
||||||
|
// vm VueComponent vue实例
|
||||||
|
// event Object event对象
|
||||||
|
// jsCode String 待执行的js代码
|
||||||
|
// errorMessage String 执行出错后的提示(控制台)
|
||||||
|
export function jsExpand (options = {}) {
|
||||||
|
// 绑定到window上的keyName
|
||||||
|
const windowKeyName = 'J_CLICK_EVENT_OPTIONS'
|
||||||
|
if (typeof window[windowKeyName] !== 'object') {
|
||||||
|
window[windowKeyName] = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 随机生成JS增强的执行id,防止冲突
|
||||||
|
const id = randomString(16, 'qwertyuioplkjhgfdsazxcvbnm'.toUpperCase())
|
||||||
|
// 封装按钮点击事件
|
||||||
|
const code = `
|
||||||
|
(function (o_${id}) {
|
||||||
|
try {
|
||||||
|
(function (globalEvent, vm) {
|
||||||
|
${options.jsCode}
|
||||||
|
})(o_${id}.event, o_${id}.vm)
|
||||||
|
} catch (e) {
|
||||||
|
o_${id}.error(e)
|
||||||
|
}
|
||||||
|
o_${id}.done()
|
||||||
|
})(window['${windowKeyName}']['EVENT_${id}'])
|
||||||
|
`
|
||||||
|
// 创建script标签
|
||||||
|
const script = document.createElement('script')
|
||||||
|
// 将需要传递的参数挂载到window对象上
|
||||||
|
window[windowKeyName]['EVENT_' + id] = {
|
||||||
|
vm: options.vm,
|
||||||
|
event: options.event,
|
||||||
|
// 当执行完成时,无论如何都会调用的回调事件
|
||||||
|
done () {
|
||||||
|
// 执行完后删除新增的 script 标签不会撤销执行结果(已产生的结果不会被撤销)
|
||||||
|
script.outerHTML = ''
|
||||||
|
delete window[windowKeyName]['EVENT_' + id]
|
||||||
|
},
|
||||||
|
// 当js运行出错的时候调用的事件
|
||||||
|
error (e) {
|
||||||
|
console.group(`${options.errorMessage || '用户自定义JS增强代码运行出错'}(${new Date()})`)
|
||||||
|
console.error(e)
|
||||||
|
console.groupEnd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 将事件挂载到document中
|
||||||
|
script.innerHTML = code
|
||||||
|
document.body.appendChild(script)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重复值验证工具方法
|
||||||
|
*
|
||||||
|
* 使用示例:
|
||||||
|
* { validator: (rule, value, callback) => validateDuplicateValue('sys_fill_rule', 'rule_code', value, this.model.id, callback) }
|
||||||
|
*
|
||||||
|
* @param tableName 被验证的表名
|
||||||
|
* @param fieldName 被验证的字段名
|
||||||
|
* @param fieldVal 被验证的值
|
||||||
|
* @param dataId 数据ID,可空
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
export function validateDuplicateValue (tableName, fieldName, fieldVal, dataId, callback) {
|
||||||
|
if (fieldVal) {
|
||||||
|
const params = { tableName, fieldName, fieldVal, dataId }
|
||||||
|
api.duplicateCheck(params).then(res => {
|
||||||
|
res.success ? callback() : callback(res.message)
|
||||||
|
}).catch(err => {
|
||||||
|
callback(err.message || err)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据编码校验规则code,校验传入的值是否合法
|
||||||
|
*
|
||||||
|
* 使用示例:
|
||||||
|
* { validator: (rule, value, callback) => validateCheckRule('common', value, callback) }
|
||||||
|
*
|
||||||
|
* @param ruleCode 编码校验规则 code
|
||||||
|
* @param value 被验证的值
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
export function validateCheckRule (ruleCode, value, callback) {
|
||||||
|
if (ruleCode && value) {
|
||||||
|
value = encodeURIComponent(value)
|
||||||
|
api.checkRuleByCode({ ruleCode, value }).then(res => {
|
||||||
|
res.success ? callback() : callback(res.message)
|
||||||
|
}).catch(err => {
|
||||||
|
callback(err.message || err)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果值不存在就 push 进数组,反之不处理
|
||||||
|
* @param array 要操作的数据
|
||||||
|
* @param value 要添加的值
|
||||||
|
* @param key 可空,如果比较的是对象,可能存在地址不一样但值实际上是一样的情况,可以传此字段判断对象中唯一的字段,例如 id。不传则直接比较实际值
|
||||||
|
* @returns {boolean} 成功 push 返回 true,不处理返回 false
|
||||||
|
*/
|
||||||
|
export function pushIfNotExist (array, value, key) {
|
||||||
|
for (const item of array) {
|
||||||
|
if (key && (item[key] === value[key])) {
|
||||||
|
return false
|
||||||
|
} else if (item === value) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
array.push(value)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可用于判断是否成功
|
||||||
|
* @type {symbol}
|
||||||
|
*/
|
||||||
|
export const succeedSymbol = Symbol('')
|
||||||
|
/**
|
||||||
|
* 可用于判断是否失败
|
||||||
|
* @type {symbol}
|
||||||
|
*/
|
||||||
|
export const failedSymbol = Symbol('')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使 promise 无论如何都会 resolve,除非传入的参数不是一个Promise对象或返回Promise对象的方法
|
||||||
|
* 一般用在 Promise.all 中
|
||||||
|
*
|
||||||
|
* @param promise 可传Promise对象或返回Promise对象的方法
|
||||||
|
* @returns {Promise<any>}
|
||||||
|
*/
|
||||||
|
export function alwaysResolve (promise) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let p = promise
|
||||||
|
if (typeof promise === 'function') {
|
||||||
|
p = promise()
|
||||||
|
}
|
||||||
|
if (p instanceof Promise) {
|
||||||
|
p.then(data => {
|
||||||
|
resolve({ type: succeedSymbol, data })
|
||||||
|
}).catch(error => {
|
||||||
|
resolve({ type: failedSymbol, error })
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
reject('alwaysResolve: 传入的参数不是一个Promise对象或返回Promise对象的方法')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简单实现防抖方法
|
||||||
|
*
|
||||||
|
* 防抖(debounce)函数在第一次触发给定的函数时,不立即执行函数,而是给出一个期限值(delay),比如100ms。
|
||||||
|
* 如果100ms内再次执行函数,就重新开始计时,直到计时结束后再真正执行函数。
|
||||||
|
* 这样做的好处是如果短时间内大量触发同一事件,只会执行一次函数。
|
||||||
|
*
|
||||||
|
* @param fn 要防抖的函数
|
||||||
|
* @param delay 防抖的毫秒数
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
export function simpleDebounce (fn, delay = 100) {
|
||||||
|
let timer = null
|
||||||
|
return function () {
|
||||||
|
const args = arguments
|
||||||
|
if (timer) {
|
||||||
|
clearTimeout(timer)
|
||||||
|
}
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
fn.apply(this, args)
|
||||||
|
}, delay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不用正则的方式替换所有值
|
||||||
|
* @param text 被替换的字符串
|
||||||
|
* @param checker 替换前的内容
|
||||||
|
* @param replacer 替换后的内容
|
||||||
|
* @returns {String} 替换后的字符串
|
||||||
|
*/
|
||||||
|
export function replaceAll (text, checker, replacer) {
|
||||||
|
const lastText = text
|
||||||
|
text = text.replace(checker, replacer)
|
||||||
|
if (lastText !== text) {
|
||||||
|
return replaceAll(text, checker, replacer)
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取事件冒泡路径,兼容 IE11,Edge,Chrome,Firefox,Safari
|
||||||
|
* 目前使用的地方:JEditableTable Span模式
|
||||||
|
*/
|
||||||
|
export function getEventPath (event) {
|
||||||
|
const target = event.target
|
||||||
|
const path = (event.composedPath && event.composedPath()) || event.path
|
||||||
|
|
||||||
|
if (path != null) {
|
||||||
|
return (path.indexOf(window) < 0) ? path.concat(window) : path
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target === window) {
|
||||||
|
return [window]
|
||||||
|
}
|
||||||
|
|
||||||
|
const getParents = (node, memo) => {
|
||||||
|
memo = memo || []
|
||||||
|
const parentNode = node.parentNode
|
||||||
|
|
||||||
|
if (!parentNode) {
|
||||||
|
return memo
|
||||||
|
} else {
|
||||||
|
return getParents(parentNode, memo.concat(parentNode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [target].concat(getParents(target), window)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据组件名获取父级
|
||||||
|
* @param vm
|
||||||
|
* @param name
|
||||||
|
* @returns {Vue | null|null|Vue}
|
||||||
|
*/
|
||||||
|
export function getVmParentByName (vm, name) {
|
||||||
|
const parent = vm.$parent
|
||||||
|
if (parent && parent.$options) {
|
||||||
|
if (parent.$options.name === name) {
|
||||||
|
return parent
|
||||||
|
} else {
|
||||||
|
const res = getVmParentByName(parent, name)
|
||||||
|
if (res) {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使一个值永远不会为(null | undefined)
|
||||||
|
*
|
||||||
|
* @param value 要处理的值
|
||||||
|
* @param def 默认值,如果value为(null | undefined)则返回的默认值,可不传,默认为''
|
||||||
|
*/
|
||||||
|
export function neverNull (value, def) {
|
||||||
|
return value == null ? (neverNull(def, '')) : value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据元素值移除数组中的一个元素
|
||||||
|
* @param array 数组
|
||||||
|
* @param prod 属性名
|
||||||
|
* @param value 属性值
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function removeArrayElement (array, prod, value) {
|
||||||
|
let index = -1
|
||||||
|
for (let i = 0; i < array.length; i++) {
|
||||||
|
if (array[i][prod] + '' === value + '') {
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index >= 0) {
|
||||||
|
array.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function findFirstRoute (data) {
|
||||||
|
if (data[0]) {
|
||||||
|
if (data[0] && data[0].children && data[0].children.length > 0) {
|
||||||
|
return findFirstRoute(data[0].children)
|
||||||
|
} else {
|
||||||
|
return data[0].path
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return '/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 判断是否是OAuth2APP环境 */
|
||||||
|
export function isOAuth2AppEnv () {
|
||||||
|
return /wxwork|dingtalk/i.test(navigator.userAgent)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取积木报表打印地址
|
||||||
|
* @param url
|
||||||
|
* @param id
|
||||||
|
* @param open 是否自动打开
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function getReportPrintUrl (url, id, open) {
|
||||||
|
// URL支持{{ window.xxx }}占位符变量
|
||||||
|
url = url.replace(/{{([^}]+)?}}/g, (s1, s2) => evil(s2))
|
||||||
|
if (url.includes('?')) {
|
||||||
|
url += '&'
|
||||||
|
} else {
|
||||||
|
url += '?'
|
||||||
|
}
|
||||||
|
url += `id=${id}`
|
||||||
|
url += `&token=${Vue.ls.get(ACCESS_TOKEN)}`
|
||||||
|
if (open) {
|
||||||
|
window.open(url)
|
||||||
|
}
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解决eval的eslint问题
|
||||||
|
* @param fn
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function evil (fn) {
|
||||||
|
const Fn = Function // 一个变量指向Function,防止有些前端编译工具报错
|
||||||
|
return new Fn('return ' + fn)()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将url的参数拆分成对象
|
||||||
|
* @param url
|
||||||
|
* @returns {{id: *, url}}
|
||||||
|
*/
|
||||||
|
export function urlToParams (url) {
|
||||||
|
const commonUrl = window._CONFIG.staticDomainURL
|
||||||
|
// url截取参数的部分
|
||||||
|
const paramsStr = url.slice(url.indexOf('?') + 1)
|
||||||
|
const paramsObj = {
|
||||||
|
url,
|
||||||
|
id: url.slice(url.indexOf(commonUrl) + commonUrl.length + 1, url.indexOf('?'))
|
||||||
|
}
|
||||||
|
paramsStr.split('&').forEach(item => {
|
||||||
|
const arr = item.split('=')
|
||||||
|
paramsObj[arr[0]] = arr[1]
|
||||||
|
})
|
||||||
|
return paramsObj
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* 邮箱
|
||||||
|
* @param {*} s
|
||||||
|
* 之前的正则 /^(([^<>()\[\]\\.,;:\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,}))$/
|
||||||
|
*/
|
||||||
|
export function isEmail (s) {
|
||||||
|
return /^\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/.test(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号码
|
||||||
|
* @param {*} s
|
||||||
|
*/
|
||||||
|
export function isMobile (s) {
|
||||||
|
return /^1[0-9]{10}$/.test(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电话号码
|
||||||
|
* @param {*} s
|
||||||
|
*/
|
||||||
|
export function isPhone (s) {
|
||||||
|
return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL地址
|
||||||
|
* @param {*} s
|
||||||
|
*/
|
||||||
|
export function isURL (s) {
|
||||||
|
return /^http[s]?:\/\/.*/.test(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号或座机号
|
||||||
|
*
|
||||||
|
* /^((13[0-9])|(14[579])|(15([0-3]|[5-9]))|(17[0135678])|(18[0-9])|(19[8|9])|(16[6]))\d{8}$/
|
||||||
|
* */
|
||||||
|
export function phoneReg (s) {
|
||||||
|
return /(^[1][3,456789][0-9]{9}$)|(^0\d{2,3}-?\d{7,8}$)/.test(s)
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
Vue.directive('watermark', {
|
||||||
|
bind: function (el, binding) {
|
||||||
|
// 水印文字,父元素,画布宽度,画布高度,字体,文字颜色,画布横坐标
|
||||||
|
function addWaterMarker (str, parentNode, width, height, font, textColor, fillTextX = '10') {
|
||||||
|
// 检查父元素是否包含子元素
|
||||||
|
const elementContains = (parent, child) => parent !== child && parent.contains(child)
|
||||||
|
const flag = elementContains(parentNode, document.querySelector('canvas'))
|
||||||
|
// 防止重复创建
|
||||||
|
if (!flag) {
|
||||||
|
const can = document.createElement('canvas')
|
||||||
|
parentNode.appendChild(can)
|
||||||
|
can.width = width || 300
|
||||||
|
can.height = height || 140
|
||||||
|
can.style.display = 'none'
|
||||||
|
const cans = can.getContext('2d')
|
||||||
|
cans.rotate(-20 * Math.PI / 180)
|
||||||
|
cans.font = font || '13px Microsoft Yahei'
|
||||||
|
cans.fillStyle = textColor || '#DDDDDD'
|
||||||
|
cans.textAlign = 'left'
|
||||||
|
cans.textBaseline = 'Middle'
|
||||||
|
cans.fillText(str, fillTextX, can.height)
|
||||||
|
// 设置背景图(整个项目中都添加水印建议使用此方法)
|
||||||
|
// parentNode.style.backgroundImage = "url(" + can.toDataURL("image/png") + ")";
|
||||||
|
|
||||||
|
// 创建div 定位覆盖(某个元素,如图片添加水印建议使用此方法)
|
||||||
|
const div = document.createElement('div')
|
||||||
|
div.id = str
|
||||||
|
div.style.pointerEvents = 'none'
|
||||||
|
div.style.top = '0'
|
||||||
|
div.style.left = '0'
|
||||||
|
div.style.position = 'absolute'
|
||||||
|
div.style.zIndex = '100000'
|
||||||
|
div.style.width = '100%'
|
||||||
|
div.style.height = '100%'
|
||||||
|
div.style.background = 'url(' + can.toDataURL('image/png') + ')'
|
||||||
|
parentNode.appendChild(div)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (binding.value.text) {
|
||||||
|
addWaterMarker(binding.value.text, el, binding.value.width, binding.value.height, binding.value.font, binding.value.textColor, binding.value.fillTextX)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<template>
|
||||||
|
<div class="home">
|
||||||
|
首页
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Home'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 移动端不支持时,显示的节点页面 -->
|
||||||
|
<div>
|
||||||
|
<div class="container">
|
||||||
|
<div class="error">
|
||||||
|
<img :src="require('@/assets/image/error.png')" alt="error">
|
||||||
|
</div>
|
||||||
|
<p>{{ $t('noMobile') }}</p>
|
||||||
|
<p>{{ $t('toPc') }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'NoMobile'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.container {
|
||||||
|
font-family: PingFang SC-Medium, PingFang SC, sans-serif;
|
||||||
|
margin: 20vh auto 0;
|
||||||
|
text-align: center;
|
||||||
|
.error {
|
||||||
|
font-size: 0;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 1.6rem;
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
font-size: 0.427rem;
|
||||||
|
line-height: 0.607rem;
|
||||||
|
font-weight: 500;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.error + p {
|
||||||
|
margin-top: 0.773rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
@font-color: #34383F;
|
||||||
|
#app > .van-nav-bar {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
|
||||||
|
.van-nav-bar__title {
|
||||||
|
color: @font-color;
|
||||||
|
}
|
||||||
|
.van-nav-bar__text {
|
||||||
|
color: @font-color;
|
||||||
|
}
|
||||||
|
.van-icon {
|
||||||
|
color: @font-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
<template>
|
||||||
|
<div class="login-box">
|
||||||
|
|
||||||
|
<van-field v-model="username" border center class="login-form-item" clearable placeholder="请输入账号"/>
|
||||||
|
<van-field v-model="password" :autocomplete="false" border center class="login-form-item" placeholder="请输入密码" :type="passwordFieldType"
|
||||||
|
@paste.native.capture.prevent="handleOperate">
|
||||||
|
<template #right-icon>
|
||||||
|
<div @click="switchPasswordType">
|
||||||
|
<van-icon name="eye" v-if="passwordFieldType!=='password'"/>
|
||||||
|
<van-icon name="closed-eye" v-else/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
<div class="random-image-box">
|
||||||
|
<van-field v-model="captcha" maxlength="4" :autocomplete="false" border center class="login-form-item" clearable placeholder="请输入验证码"/>
|
||||||
|
<template>
|
||||||
|
<img class="random-image" v-if="requestCodeSuccess" :src="randCodeImage" @click="handleChangeCheckCode" alt="code"/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<van-button class="login-btn" size="large" type="info" @click="handleSubmit">登录</van-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Toast } from 'vant'
|
||||||
|
import { getRSAPublicKey } from '@/utils/encryption'
|
||||||
|
import { JSEncrypt } from 'jsencrypt'
|
||||||
|
import { mapActions } from 'vuex'
|
||||||
|
import { getAction } from '@api/manage'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'LoginPage',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
captcha: '', // 验证码
|
||||||
|
rsaPublicKey: '', // 公钥
|
||||||
|
requestCodeSuccess: false, // 请求验证码图片是否成功
|
||||||
|
randCodeImage: '', // 验证码图片
|
||||||
|
passwordFieldType: 'password'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.getPublicKey()
|
||||||
|
this.handleChangeCheckCode()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['Login']),
|
||||||
|
// 获取RSA公钥
|
||||||
|
getPublicKey () {
|
||||||
|
// 获取公钥
|
||||||
|
getRSAPublicKey().then(res => {
|
||||||
|
this.rsaPublicKey = res.result
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleChangeCheckCode () {
|
||||||
|
this.currdatetime = new Date().getTime()
|
||||||
|
getAction(`/sys/randomImage/${this.currdatetime}`).then(res => {
|
||||||
|
if (res.success) {
|
||||||
|
this.randCodeImage = res.result
|
||||||
|
this.requestCodeSuccess = true
|
||||||
|
} else {
|
||||||
|
this.requestCodeSuccess = false
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.requestCodeSuccess = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleSubmit () {
|
||||||
|
if (!this.username) {
|
||||||
|
Toast('请输入账号')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.password) {
|
||||||
|
Toast('请输入密码')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.captcha) {
|
||||||
|
Toast('请输入验证码')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const loginParams = {
|
||||||
|
rsaPublicKey: this.rsaPublicKey
|
||||||
|
}
|
||||||
|
// 新建JSEncrypt对象
|
||||||
|
const encrypt = new JSEncrypt()
|
||||||
|
encrypt.setPublicKey(loginParams.rsaPublicKey)
|
||||||
|
// 公钥加密
|
||||||
|
loginParams.username = encrypt.encrypt(this.username)
|
||||||
|
loginParams.password = encrypt.encrypt(this.password)
|
||||||
|
loginParams.captcha = this.captcha
|
||||||
|
loginParams.checkKey = this.currdatetime
|
||||||
|
this.Login(loginParams).then(res => {
|
||||||
|
console.log(res, 'res')
|
||||||
|
this.loginSuccess()
|
||||||
|
}).catch((err) => {
|
||||||
|
if (err.code === 500) {
|
||||||
|
this.$toast(err.message)
|
||||||
|
// 刷新验证码
|
||||||
|
this.handleChangeCheckCode()
|
||||||
|
this.captcha = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
loginSuccess () {
|
||||||
|
Toast('登录成功')
|
||||||
|
this.$router.push({ path: '/' }).catch((res) => {
|
||||||
|
console.log(res)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 密码禁止粘贴
|
||||||
|
handleOperate () {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
switchPasswordType () {
|
||||||
|
this.passwordFieldType = this.passwordFieldType === 'password' ? 'text' : 'password'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.login-box {
|
||||||
|
height: 100vh;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #ccc;
|
||||||
|
.login-form-item {
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.login-btn {
|
||||||
|
background-color: #D52C26;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
const primaryColor = '#D52C26'
|
||||||
|
const white = '#FFFFFF'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// 定制主题:用于覆盖原组件的Less变量
|
||||||
|
// 注意:每次修改完之后要重启服务才能生效
|
||||||
|
theme: {
|
||||||
|
// 导航栏
|
||||||
|
'nav-bar-icon-color': white,
|
||||||
|
'nav-bar-text-color': white,
|
||||||
|
'nav-bar-title-text-color': white,
|
||||||
|
'nav-bar-background-color': primaryColor,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
const path = require('path')
|
||||||
|
const CompressionPlugin = require('compression-webpack-plugin')
|
||||||
|
const { theme } = require('./vant.config')
|
||||||
|
|
||||||
|
function resolve (dir) {
|
||||||
|
return path.join(__dirname, dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
// vue.config.js
|
||||||
|
module.exports = {
|
||||||
|
/*
|
||||||
|
Vue-cli3:
|
||||||
|
Crashed when using Webpack `import()` #2463
|
||||||
|
https://github.com/vuejs/vue-cli/issues/2463
|
||||||
|
*/
|
||||||
|
// 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
|
||||||
|
productionSourceMap: false,
|
||||||
|
// 打包app时放开该配置
|
||||||
|
// publicPath:'./',
|
||||||
|
configureWebpack: config => {
|
||||||
|
// 生产环境取消 console.log
|
||||||
|
if (process.env.NODE_ENV === 'production') {
|
||||||
|
config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
chainWebpack: (config) => {
|
||||||
|
config.resolve.alias
|
||||||
|
.set('@$', resolve('src'))
|
||||||
|
.set('@api', resolve('src/api'))
|
||||||
|
.set('@assets', resolve('src/assets'))
|
||||||
|
.set('@comp', resolve('src/components'))
|
||||||
|
.set('@views', resolve('src/views'))
|
||||||
|
|
||||||
|
// 生产环境,开启js\css压缩
|
||||||
|
if (process.env.NODE_ENV === 'production') {
|
||||||
|
config.plugin('compressionPlugin').use(new CompressionPlugin({
|
||||||
|
test: /\.(js|css|less)$/, // 匹配文件名
|
||||||
|
threshold: 10240, // 对超过10k的数据压缩
|
||||||
|
deleteOriginalAssets: false // 不删除源文件
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 配置 webpack 识别 markdown 为普通的文件
|
||||||
|
config.module
|
||||||
|
.rule('markdown')
|
||||||
|
.test(/\.md$/)
|
||||||
|
.use()
|
||||||
|
.loader('file-loader')
|
||||||
|
.end()
|
||||||
|
},
|
||||||
|
|
||||||
|
css: {
|
||||||
|
loaderOptions: {
|
||||||
|
less: {
|
||||||
|
modifyVars: {
|
||||||
|
/* less 变量覆盖,用于自定义 ant design 主题 */
|
||||||
|
'primary-color': '#D52C26',
|
||||||
|
'link-color': '#D52C26',
|
||||||
|
'border-radius-base': '4px',
|
||||||
|
/* vant组件变量覆盖 */
|
||||||
|
...theme
|
||||||
|
},
|
||||||
|
javascriptEnabled: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
devServer: {
|
||||||
|
port: 3335,
|
||||||
|
proxy: {
|
||||||
|
/* '/api': {
|
||||||
|
target: 'https://mock.ihx.me/mock/5baf3052f7da7e07e04a5116/antd-pro', //mock API接口系统
|
||||||
|
ws: false,
|
||||||
|
changeOrigin: true,
|
||||||
|
pathRewrite: {
|
||||||
|
'/laws-sinotruk': '' //默认所有请求都加了jero-boot前缀,需要去掉
|
||||||
|
}
|
||||||
|
}, */
|
||||||
|
'/laws-sinotruk': {
|
||||||
|
target: 'http://localhost:8184',
|
||||||
|
ws: false,
|
||||||
|
changeOrigin: true,
|
||||||
|
pathRewrite: {
|
||||||
|
// '/laws-sinotruk': '' // 默认所有请求都加了jero-boot前缀,需要去掉
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
lintOnSave: undefined
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user