parent
56635a948b
commit
a31960fc1a
45 changed files with 10449 additions and 10308 deletions
@ -1 +1,20 @@ |
||||
VUE_APP_API_BASE_URL=http://dev.iczer.com |
||||
ENV = 'development' |
||||
|
||||
# base api |
||||
# PRIVATE -加密 PUBLIC-不加密 |
||||
VUE_APP_ENCRYPT = 'PUBLIC' |
||||
|
||||
VUE_APP_BASE_API = '/api' |
||||
VUE_APP_BASE_LSM_API = '/lsm'cls |
||||
# 文件上传 |
||||
VUE_APP_UPLOAD_URL = '/api/oil-oss/obejct/uploadFile' |
||||
VUE_APP_UPLOAD_PRIVATE_URL = '/api/oil-dict/imageHandler/uploadProtectedImg' |
||||
VUE_APP_DOMAIN = '127.0.0.1:38080' |
||||
|
||||
# 开发环境,不会进行加密,会打印出数据1 |
||||
VUE_APP_ENV = 'production' |
||||
#production |
||||
|
||||
|
||||
VUE_CLI_BABEL_TRANSPILE_MODULES = true |
||||
|
||||
@ -0,0 +1,14 @@ |
||||
ENV = 'production' |
||||
|
||||
# base api |
||||
VUE_APP_ENCRYPT = 'PRIVATE' |
||||
|
||||
VUE_APP_BASE_API = '/adminapi' |
||||
VUE_APP_BASE_LSM_API = '/lsm' |
||||
# 文件上传 |
||||
VUE_APP_UPLOAD_URL = '/adminapi/oil-oss/obejct/uploadFile' |
||||
VUE_APP_UPLOAD_PRIVATE_URL = '/adminapi/oil-dict/imageHandler/uploadProtectedImg' |
||||
# 生产环境,进行加密 |
||||
VUE_APP_ENV = 'production' |
||||
|
||||
VUE_APP_DOMAIN ='www.xingoil.com/ws' |
||||
@ -1,38 +0,0 @@ |
||||
--- |
||||
name: Bug report |
||||
about: Create a report to help us improve |
||||
title: '' |
||||
labels: '' |
||||
assignees: '' |
||||
|
||||
--- |
||||
|
||||
**Describe the bug** |
||||
A clear and concise description of what the bug is. |
||||
|
||||
**To Reproduce** |
||||
Steps to reproduce the behavior: |
||||
1. Go to '...' |
||||
2. Click on '....' |
||||
3. Scroll down to '....' |
||||
4. See error |
||||
|
||||
**Expected behavior** |
||||
A clear and concise description of what you expected to happen. |
||||
|
||||
**Screenshots** |
||||
If applicable, add screenshots to help explain your problem. |
||||
|
||||
**Desktop (please complete the following information):** |
||||
- OS: [e.g. iOS] |
||||
- Browser [e.g. chrome, safari] |
||||
- Version [e.g. 22] |
||||
|
||||
**Smartphone (please complete the following information):** |
||||
- Device: [e.g. iPhone6] |
||||
- OS: [e.g. iOS8.1] |
||||
- Browser [e.g. stock browser, safari] |
||||
- Version [e.g. 22] |
||||
|
||||
**Additional context** |
||||
Add any other context about the problem here. |
||||
@ -1,20 +0,0 @@ |
||||
--- |
||||
name: Feature request |
||||
about: Suggest an idea for this project |
||||
title: '' |
||||
labels: '' |
||||
assignees: '' |
||||
|
||||
--- |
||||
|
||||
**Is your feature request related to a problem? Please describe.** |
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] |
||||
|
||||
**Describe the solution you'd like** |
||||
A clear and concise description of what you want to happen. |
||||
|
||||
**Describe alternatives you've considered** |
||||
A clear and concise description of any alternative solutions or features you've considered. |
||||
|
||||
**Additional context** |
||||
Add any other context or screenshots about the feature request here. |
||||
@ -1,17 +0,0 @@ |
||||
--- |
||||
title: 首页 |
||||
home: true |
||||
heroImage: /logo.png |
||||
heroText: Vue Antd Admin |
||||
tagline: 开箱即用的中台前端/设计解决方案 |
||||
actionText: 快速上手 → |
||||
actionLink: /start/use |
||||
features: |
||||
- title: 简洁 |
||||
details: 以 Markdown 为中心的项目结构,以最少的配置帮助你专注于写作。 |
||||
- title: 优雅 |
||||
details: 享受 Vue + webpack 的开发体验,在 Markdown 中使用 Vue 组件,同时可以使用 Vue 来开发自定义主题。 |
||||
- title: 自然 |
||||
details: VuePress 为每个页面预渲染生成静态的 HTML,同时在页面被加载的时候,将作为 SPA 运行。 |
||||
footer: MIT Licensed | Copyright © 2018-present iczer |
||||
--- |
||||
@ -1,10 +0,0 @@ |
||||
--- |
||||
title: 108个小技巧 |
||||
lang: zn-CN |
||||
--- |
||||
# 108个小技巧 |
||||
|
||||
## 自定义菜单icon |
||||
## 隐藏页面标题 |
||||
## 关闭页签API |
||||
## 权限校验PI |
||||
@ -1,5 +0,0 @@ |
||||
--- |
||||
title: 开发 |
||||
lang: zh-CN |
||||
--- |
||||
# 开发 |
||||
@ -1,161 +0,0 @@ |
||||
--- |
||||
title: 服务端交互 |
||||
lang: zh-CN |
||||
--- |
||||
# 服务端交互 |
||||
数据服务是一个应用的灵魂,它驱动着应用的各个功能模块的正常运转。Vue Antd Admin 在 service 模块封装了服务端交互,通过 API 的形式可以和任何技术栈的服务端应用一起工作。 |
||||
## 服务交互流程 |
||||
在 Vue Antd Admin 中,服务端交互流程如下: |
||||
* 组件内调用 service 服务 API |
||||
* service 服务 API 封装请求数据,通过 request.js 发送请求 |
||||
* 组件获取 service 返回的数据,更新视图数据或触发其它行为 |
||||
|
||||
我们以登录为例,Login.vue 组件内,用户输入账号密码,点击登录,调用 services/user/login api |
||||
```vue {5,17} |
||||
<template> |
||||
... |
||||
</template> |
||||
<script> |
||||
import {login} from '@/services/user' |
||||
... |
||||
export default { |
||||
name: 'Login', |
||||
methods: { |
||||
onSubmit (e) { |
||||
e.preventDefault() |
||||
this.form.validateFields((err) => { |
||||
if (!err) { |
||||
this.logging = true |
||||
const name = this.form.getFieldValue('name') |
||||
const password = this.form.getFieldValue('password') |
||||
login(name, password).then(res => this.afterLogin(res)) |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
``` |
||||
`services/user/login` 封装账户密码数据,通过 `request.js` 发送登录服务请求 |
||||
```js |
||||
import {request, METHOD} from '@/utils/request' |
||||
/** |
||||
* 登录服务 |
||||
* @param name 账户名 |
||||
* @param password 账户密码 |
||||
* @returns {Promise<AxiosResponse<T>>} |
||||
*/ |
||||
async function login(name, password) { |
||||
return request(LOGIN, METHOD.POST, { |
||||
name: name, |
||||
password: password |
||||
}) |
||||
} |
||||
``` |
||||
Login.vue 获取登录服务返回的数据,进行后续操作 |
||||
```vue {14,18-23} |
||||
<template> |
||||
... |
||||
</template> |
||||
<script> |
||||
import {login} from '@/services/user' |
||||
... |
||||
export default { |
||||
name: 'Login', |
||||
methods: { |
||||
onSubmit (e) { |
||||
this.form.validateFields((err) => { |
||||
if (!err) { |
||||
... |
||||
login(name, password).then(res => this.afterLogin(res)) |
||||
} |
||||
}) |
||||
}, |
||||
afterLogin(res) { |
||||
if (res.data.code >= 0) { //登录成功 |
||||
... |
||||
} else { //登录失败 |
||||
this.error = loginRes.message |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
``` |
||||
## 服务模块结构 |
||||
服务模块结构如下: |
||||
```bash |
||||
... |
||||
├── src |
||||
│ └── services # 数据服务模块 |
||||
│ ├── user.js # 用户数据服务 |
||||
│ ├── product.js # 产品服务 |
||||
│ ... |
||||
│ ├── api.js # api 地址管理 |
||||
│ └── index.js # 服务模块导出 |
||||
... |
||||
│ └── utils # 数据服务模块 |
||||
│ ├── request.js # 基于 axios 的 http 请求工具 |
||||
... |
||||
``` |
||||
services 文件夹下, api.js 用于服务请求地址的统一管理,index.js 用于模块化导出服务,其它 *.js 文件对应各个服务模块。 |
||||
## request.js |
||||
request.js 基于 axios 封装了一些常用的函数,如下: |
||||
```js |
||||
export { |
||||
METHOD, //http method 常量 |
||||
AUTH_TYPE, //凭证认证类型 常量 |
||||
request, //http请求函数 |
||||
setAuthorization, //设置身份凭证函数 |
||||
removeAuthorization, //移除身份凭证函数 |
||||
checkAuthorization //检查身份凭证是否过期函数 |
||||
} |
||||
``` |
||||
:::tip |
||||
凭证认证类型默认为 [Bearer](https://www.jianshu.com/p/8f7009456abc),你可以根据自己的需要实现其它类型的认证 |
||||
::: |
||||
## Base url 配置 |
||||
你可以在项目根目录下的环境变量文件(.env 和 .env.development)中配置你的 API 服务 base url 地址。 |
||||
|
||||
生产环境,.env 文件 |
||||
```properties |
||||
VUE_APP_API_BASE_URL=https://www.server.com |
||||
``` |
||||
开发环境,.env.development 文件: |
||||
```properties |
||||
VUE_APP_API_BASE_URL=https://localhost:8000 |
||||
``` |
||||
## 跨域设置 |
||||
在开发环境中,通常我们的Vue应用和服务应用运行在不同的地址或端口上。我们可以通过简单的设置,代理前端请求,来避免跨域问题。如下: |
||||
|
||||
首先,在 services/api.js 文件中设置 API_PROXY_PREFIX 常量,BASE_URL 像下面这样设置: |
||||
```js {2,4} |
||||
//跨域代理前缀 |
||||
const API_PROXY_PREFIX='/api' |
||||
//base url |
||||
const BASE_URL = process.env.NODE_ENV === 'production' ? process.env.VUE_APP_API_BASE_URL : API_PROXY_PREFIX |
||||
//导出api服务地址 |
||||
module.exports = { |
||||
LOGIN: `${BASE_URL}/login`, |
||||
ROUTES: `${BASE_URL}/routes` |
||||
} |
||||
``` |
||||
然后,在 vue.config.js 文件中配置代理: |
||||
```js |
||||
model.exports = { |
||||
devServer: { |
||||
proxy: { |
||||
'/api': { //此处要与 /services/api.js 中的 API_PROXY_PREFIX 值保持一致 |
||||
target: process.env.VUE_APP_API_BASE_URL, |
||||
changeOrigin: true, |
||||
pathRewrite: { |
||||
'^/api': '' |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
``` |
||||
:::tip |
||||
此代理配置仅适用于开发环境,生产环境的跨域代理请在自己的web服务器配置。 |
||||
::: |
||||
@ -1,5 +0,0 @@ |
||||
--- |
||||
title: 其它 |
||||
lang: zh-CN |
||||
--- |
||||
# 其它 |
||||
@ -1,8 +0,0 @@ |
||||
--- |
||||
title: 社区 |
||||
lang: zh-CN |
||||
--- |
||||
# 社区 |
||||
|
||||
## 交流学习 |
||||
### QQ群:812277510、610090280(已满) |
||||
@ -1,5 +0,0 @@ |
||||
--- |
||||
title: 更新日志 |
||||
lang: zh-CN |
||||
--- |
||||
# 更新日志 |
||||
@ -1,5 +0,0 @@ |
||||
--- |
||||
title: 开始 |
||||
lang: zh-CN |
||||
--- |
||||
## 开始 |
||||
@ -1,22 +0,0 @@ |
||||
--- |
||||
title: 常见问题 |
||||
lang: zh-CN |
||||
--- |
||||
# 常见问题 |
||||
### 为什么不是 Ant Design Pro Vue ? |
||||
[Ant Design Pro Vue](https://github.com/vueComponent/ant-design-vue-pro) 是 [Ant Design Pro](https://github.com/ant-design/ant-design-pro) 的 Vue 版本,其中项目结构、组件、 |
||||
布局和使用方法等基本与 Ant Design Pro 的 react 版本保持一致。如果你比较熟悉 react 版,或者你已经在使用它,这确实是一个不错的选择。 |
||||
|
||||
[Vue Antd Admin](https://github.com/iczer/vue-antd-admin) 同样实现了 Ant Design Pro 的所有功能。与此同时,我们还根据 Vue 的特性,对 Ant Design Pro 的一些组件和布局作出了相应的修改及优化,同时不影响保持与 Ant Design Pro 的一致。 |
||||
|
||||
另外,我们还在添加一些 Ant Design Pro 没有的功能,比如全局动画、多页签模式等。 |
||||
|
||||
如果你想使用 Ant Design Pro,但又觉得它缺乏一些你想要的功能,不妨看看 [Vue Antd Admin](https://github.com/iczer/vue-antd-admin),我们会认真考虑每个用户的需求。 |
||||
|
||||
因此,如果你有一些不错的想法和建议,欢迎随时和我们交流,很可能你的想法就在我们下一个版本中实现。 |
||||
|
||||
### 如何使用 Vue Antd Admin ? |
||||
请阅读文档 [开始使用](./use.md)。有任何疑问,欢迎在 github 上给我们提交 [issue](https://github.com/iczer/vue-antd-admin/issues/new)。 |
||||
|
||||
### 是否支持国际化 ? |
||||
Vue Antd Admin 引入了 vue-i18n 支持。因此你可以使用 vue-i18n 的特性对项目做国际化修改,详细请查看 [国际化](../advance/i18n.md) |
||||
@ -0,0 +1,52 @@ |
||||
import request from '@/utils/request' |
||||
var service_name = 'oil-identity' |
||||
var group_name = 'customerLoginSystem' |
||||
export default { |
||||
getByPage(page) { // 分页查询
|
||||
return request({ |
||||
url: `/${service_name}/${group_name}/getByPage`, |
||||
method: 'post', |
||||
data: page |
||||
}) |
||||
}, |
||||
save(oilDicMark) { // 保存
|
||||
return request({ |
||||
url: `/${service_name}/${group_name}/save`, |
||||
method: 'post', |
||||
data: oilDicMark |
||||
}) |
||||
}, |
||||
get(id) { // 根据id查询
|
||||
return request({ |
||||
url: `/${service_name}/${group_name}/get/${id}`, |
||||
method: 'get' |
||||
}) |
||||
}, |
||||
getUserLoginSystem(customerId) { // 所有系统以及用户登录权限
|
||||
return request({ |
||||
url: `/${service_name}/${group_name}/getUserLoginSystem/${customerId}`, |
||||
method: 'get' |
||||
}) |
||||
}, |
||||
toggleAuth(oilDicMark) { // 修改登录授权状态
|
||||
return request({ |
||||
url: `/${service_name}/${group_name}/toggleAuth`, |
||||
method: 'put', |
||||
data: oilDicMark |
||||
}) |
||||
}, |
||||
update(oilDicMark) { // 更新
|
||||
return request({ |
||||
url: `/${service_name}/${group_name}/update`, |
||||
method: 'put', |
||||
data: oilDicMark |
||||
}) |
||||
}, |
||||
deleteById(id) { // 根据id删除
|
||||
return request({ |
||||
url: `/${service_name}/${group_name}/delete`, |
||||
method: 'put', |
||||
data: { id: id } |
||||
}) |
||||
} |
||||
} |
||||
@ -0,0 +1,41 @@ |
||||
import request from '@/utils/request' |
||||
|
||||
export function login(data) { |
||||
return request({ |
||||
url: '/oil-identity/operationUser/loginPwd', |
||||
method: 'post', |
||||
data |
||||
}) |
||||
} |
||||
|
||||
export function sendManagerLoginSms(phone) { |
||||
return request({ |
||||
url: '/oil-identity/operationUser/sendManagerLoginSms', |
||||
method: 'post', |
||||
data: { |
||||
phone |
||||
} |
||||
}) |
||||
} |
||||
|
||||
export function loginSms(data) { |
||||
return request({ |
||||
url: '/oil-identity/operationUser/loginSms', |
||||
method: 'post', |
||||
data |
||||
}) |
||||
} |
||||
|
||||
export function getInfo() { |
||||
return request({ |
||||
url: '/oil-identity/unionAuth/info', |
||||
method: 'get' |
||||
}) |
||||
} |
||||
|
||||
export function logout() { |
||||
return request({ |
||||
url: '/oil-identity/authorization/logout', |
||||
method: 'get' |
||||
}) |
||||
} |
||||
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 5.2 KiB |
@ -1,12 +1,16 @@ |
||||
// 自定义配置,参考 ./default/setting.config.js,需要自定义的属性在这里配置即可
|
||||
module.exports = { |
||||
theme: { |
||||
color: '#13c2c2', |
||||
color: '#1890ff', |
||||
mode: 'dark', |
||||
success: '#52c41a', |
||||
warning: '#faad14', |
||||
error: '#f5222f' |
||||
}, |
||||
multiPage: true, |
||||
animate: { |
||||
name: 'lightSpeed', |
||||
name: 'fade', |
||||
direction: 'left' |
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,56 @@ |
||||
import Cookies from 'js-cookie' |
||||
const getters = { |
||||
sidebar: state => state.app.sidebar, |
||||
size: state => state.app.size, |
||||
markData: state => state.global.markData, |
||||
device: state => state.app.device, |
||||
visitedViews: state => state.tagsView.visitedViews, |
||||
cachedViews: state => state.tagsView.cachedViews, |
||||
token: state => state.user.token, |
||||
avatar: state => state.user.avatar, |
||||
name: state => state.user.name, |
||||
introduction: state => state.user.introduction, |
||||
role: state => state.user.role, |
||||
auths: state => state.user.auths, |
||||
permission_routes: state => state.permission.routes, |
||||
sysUserList: state => state.user.sysUserList, |
||||
user: state => state.user.user, |
||||
areaTree: state => state.global.areaTree, |
||||
networkList: state => state.global.networkList, |
||||
departmentList: state => state.global.departmentList, |
||||
fleetList: state => state.global.fleetList, |
||||
waybillId: state => state.global.waybillId, |
||||
plateNumber: state => state.global.plateNumber, |
||||
bannerInfoList: state => state.global.bannerInfoList, |
||||
|
||||
trackCss: state => state.global.trackCss, |
||||
|
||||
Link: state => state.global.Link, |
||||
|
||||
helpInfo: state => state.global.helpInfo, |
||||
drawerFixed: state => state.global.drawerFixed, |
||||
vehicleTypeList: state => state.global.vehicleTypeList, |
||||
largeAreaList: state => state.global.largeAreaList, |
||||
incomeBankList: state => state.global.incomeBankList, |
||||
currentIncomeBank: state => { |
||||
let incomeBank = state.global.currentIncomeBank |
||||
if (!incomeBank.incomeBankId) { |
||||
incomeBank = Cookies.get('currentIncome') |
||||
if (incomeBank) { |
||||
incomeBank = JSON.parse(incomeBank) |
||||
} |
||||
} |
||||
return incomeBank |
||||
}, |
||||
autoCheckDocument: state => state.status.autoCheckDocument, |
||||
|
||||
uploadToken: state => { |
||||
const token = state.global.uploadToken.pop() |
||||
return token |
||||
}, |
||||
tokenEncrypt: state => { |
||||
const token = state.global.tokenEncrypt.pop() |
||||
return token |
||||
} |
||||
} |
||||
export default getters |
||||
@ -1,8 +1,10 @@ |
||||
import Vue from 'vue' |
||||
import Vuex from 'vuex' |
||||
import modules from './modules' |
||||
import getters from './getters' |
||||
|
||||
Vue.use(Vuex) |
||||
const store = new Vuex.Store({modules}) |
||||
|
||||
console.log(modules,'11') |
||||
const store = new Vuex.Store({modules,getters}) |
||||
console.log(store,'store') |
||||
export default store |
||||
|
||||
@ -1,4 +1,5 @@ |
||||
import account from './account' |
||||
import setting from './setting' |
||||
import user from './user' |
||||
|
||||
export default {account, setting} |
||||
export default {account, setting,user} |
||||
@ -0,0 +1,114 @@ |
||||
import { login, loginSms, logout, getInfo } from '@/api/identity/user' |
||||
import { getToken, setToken, removeToken, setUsername, setPassword, setChecked, removeChecked, removeUsername, removePassword } from '@/utils/auth' |
||||
import md5 from 'js-md5' |
||||
import store from "@/store"; |
||||
const state = { |
||||
token: getToken(), |
||||
role: null, // 角色
|
||||
auths: [], // 权限
|
||||
user: {}// 存储用户信息
|
||||
} |
||||
|
||||
const mutations = { |
||||
SET_TOKEN: (state, token) => { |
||||
state.token = token |
||||
}, |
||||
SET_ROLE: (state, role) => { |
||||
state.role = role |
||||
}, |
||||
SET_AUTHS: (state, auths) => { |
||||
state.auths = auths |
||||
}, |
||||
SET_USER: (state, user) => { |
||||
state.user = user |
||||
} |
||||
} |
||||
|
||||
const actions = { |
||||
login({ commit }, userInfo) { |
||||
const { username, password, checked, verifyCode } = userInfo |
||||
return new Promise((resolve, reject) => { |
||||
login({ username: username.trim(), password: md5(password), verifyCode }).then(res => { |
||||
// 存到vuex
|
||||
commit('SET_TOKEN', res.data.accessToken) |
||||
// 存到cookie
|
||||
setToken(res.data.accessToken) |
||||
// 将账号密码和公司存入cookie中
|
||||
if (checked) { |
||||
setChecked(checked) |
||||
setUsername(username.trim()) |
||||
setPassword(md5(password)) |
||||
} |
||||
resolve(res) |
||||
}).catch(error => { |
||||
reject(error) |
||||
}) |
||||
}) |
||||
}, |
||||
loginSms({ commit }, userInfo) { |
||||
console.log('666666') |
||||
return new Promise((resolve, reject) => { |
||||
loginSms(userInfo).then(res => { |
||||
// 存到vuex
|
||||
commit('SET_TOKEN', res.data.accessToken) |
||||
// 存到cookie
|
||||
setToken(res.data.accessToken)
|
||||
resolve() |
||||
}).catch(error => { |
||||
reject(error) |
||||
}) |
||||
}) |
||||
}, |
||||
|
||||
getInfo({ commit }) { |
||||
return new Promise((resolve, reject) => { |
||||
getInfo().then( response => { |
||||
const data = response.data |
||||
store.dispatch('user/createWebsocket',data.id) |
||||
commit('SET_ROLE', data.role) |
||||
commit('SET_AUTHS', data.authList) |
||||
commit('SET_USER', data) |
||||
resolve(data) |
||||
}).catch(error => { |
||||
reject(error) |
||||
}) |
||||
}) |
||||
}, |
||||
|
||||
// user logout
|
||||
logout({ commit }) { |
||||
return new Promise((resolve, reject) => { |
||||
logout().then(() => { |
||||
commit('SET_TOKEN', '') |
||||
commit('SET_ROLE', null) |
||||
commit('SET_AUTHS', []) |
||||
removeToken() |
||||
removeChecked() |
||||
removeUsername() |
||||
removePassword() |
||||
// websocket.closeWebSocket()
|
||||
resolve() |
||||
}).catch(error => { |
||||
reject(error) |
||||
}) |
||||
}) |
||||
}, |
||||
|
||||
resetToken({ commit }) { |
||||
return new Promise(resolve => { |
||||
commit('SET_TOKEN', '') |
||||
commit('SET_ROLE', null) |
||||
commit('SET_AUTHS', []) |
||||
commit('SET_USER', {}) |
||||
removeToken() |
||||
resolve() |
||||
}) |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
namespaced: true, |
||||
state, |
||||
mutations, |
||||
actions |
||||
} |
||||
@ -0,0 +1,64 @@ |
||||
import Cookies from 'js-cookie' |
||||
|
||||
const TokenKey = 'Authorization' |
||||
const NetWorkId = 'networkId' |
||||
const UserName = 'username' |
||||
const PassWord = 'password' |
||||
const Checked = 'checked' |
||||
|
||||
export function getToken() { |
||||
return Cookies.get(TokenKey) |
||||
} |
||||
|
||||
export function setToken(token) { |
||||
return Cookies.set(TokenKey, token, { expires: 1 }) |
||||
} |
||||
|
||||
export function removeToken() { |
||||
return Cookies.remove(TokenKey) |
||||
} |
||||
|
||||
export function setNet(networkId) { |
||||
return Cookies.set(NetWorkId, networkId, { expires: 7 }) |
||||
} |
||||
|
||||
export function setUsername(username) { |
||||
return Cookies.set(UserName, username, { expires: 7 }) |
||||
} |
||||
|
||||
export function setPassword(password) { |
||||
return Cookies.set(PassWord, password, { expires: 7 }) |
||||
} |
||||
|
||||
export function getNet() { |
||||
return Cookies.get(NetWorkId) |
||||
} |
||||
|
||||
export function getUsername() { |
||||
return Cookies.get(UserName) |
||||
} |
||||
|
||||
export function getPassword() { |
||||
return Cookies.get(PassWord) |
||||
} |
||||
|
||||
export function setChecked(checked) { |
||||
return Cookies.set(Checked, checked, { expires: 7 }) |
||||
} |
||||
|
||||
export function getChecked() { |
||||
return Cookies.get(Checked) |
||||
} |
||||
|
||||
export function removeNet() { |
||||
return Cookies.remove(NetWorkId) |
||||
} |
||||
export function removeChecked() { |
||||
return Cookies.remove(Checked) |
||||
} |
||||
export function removeUsername() { |
||||
return Cookies.remove(UserName) |
||||
} |
||||
export function removePassword() { |
||||
return Cookies.remove(PassWord) |
||||
} |
||||
@ -0,0 +1,47 @@ |
||||
import CryptoJS from 'crypto-js' |
||||
import bcrypt from 'bcryptjs' |
||||
import md5 from 'js-md5' |
||||
var keyStr = 'qDfajQ*v@W1mCruZ' |
||||
|
||||
export default { |
||||
|
||||
/** |
||||
* @param {*需要加密的字符串 注:对象转化为json字符串再加密} word |
||||
* @param {*aes加密需要的key值,这个key值后端同学会告诉你} keyStr |
||||
*/ |
||||
encrypt(word) { // 加密
|
||||
var key = CryptoJS.enc.Utf8.parse(keyStr) |
||||
var srcs = CryptoJS.enc.Utf8.parse(word) |
||||
var encrypted = CryptoJS.AES.encrypt(srcs, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }) // 加密模式为ECB,补码方式为PKCS5Padding(也就是PKCS7)
|
||||
return encrypted.toString() |
||||
}, |
||||
decrypt(word) { // 解密
|
||||
var key = CryptoJS.enc.Utf8.parse(keyStr) |
||||
var decrypt = CryptoJS.AES.decrypt(word, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }) |
||||
return CryptoJS.enc.Utf8.stringify(decrypt).toString() |
||||
}, |
||||
md5Salt(str) { // md5盐加密
|
||||
return md5(str + 'kdq*&qflbn1gga?aDq') |
||||
}, |
||||
md5NoSalt(str) { |
||||
return md5(str) |
||||
}, |
||||
uuid() { // 获取uuid
|
||||
var s = [] |
||||
var hexDigits = '0123456789abcdef' |
||||
for (var i = 0; i < 36; i++) { |
||||
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1) |
||||
} |
||||
s[14] = '4' |
||||
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1) |
||||
s[8] = s[13] = s[18] = s[23] = '-' |
||||
|
||||
var uuid = s.join('') |
||||
return uuid |
||||
}, |
||||
bcrypt(str) { |
||||
var salt = bcrypt.genSaltSync(10) // 定义密码加密的计算强度,默认10
|
||||
var hash = bcrypt.hashSync(this.md5Salt(str), salt) // 把要加密的内容带进去,变量hash就是加密后的密码
|
||||
return hash |
||||
} |
||||
} |
||||
@ -1,168 +1,167 @@ |
||||
import axios from 'axios' |
||||
import Cookie from 'js-cookie' |
||||
import utils from '@/utils/encode' |
||||
import store from '@/store' |
||||
import { getToken } from '@/utils/auth' |
||||
import { message } from 'ant-design-vue'; |
||||
const CancelToken = axios.CancelToken; |
||||
|
||||
// 跨域认证信息 header 名
|
||||
const xsrfHeaderName = 'Authorization' |
||||
const timeout = 20000 |
||||
const WhiteApiErr = ['userSavePermissionByPhone','batchEnableDisable','batchPriceEnableDisable','getPushOrderInfo'] |
||||
const service = axios.create({ |
||||
baseURL: process.env.VUE_APP_BASE_API, |
||||
timeout: timeout // 默认请求超时时间
|
||||
}) |
||||
const timeoutWhite = ['/oil-finance/oilOrderInfo/importExcelOrder'] |
||||
|
||||
axios.defaults.timeout = 5000 |
||||
axios.defaults.withCredentials= true |
||||
axios.defaults.xsrfHeaderName= xsrfHeaderName |
||||
axios.defaults.xsrfCookieName= xsrfHeaderName |
||||
|
||||
// 认证类型
|
||||
const AUTH_TYPE = { |
||||
BEARER: 'Bearer', |
||||
BASIC: 'basic', |
||||
AUTH1: 'auth1', |
||||
AUTH2: 'auth2', |
||||
} |
||||
|
||||
// http method
|
||||
const METHOD = { |
||||
GET: 'get', |
||||
POST: 'post' |
||||
} |
||||
|
||||
/** |
||||
* axios请求 |
||||
* @param url 请求地址 |
||||
* @param method {METHOD} http method |
||||
* @param params 请求参数 |
||||
* @returns {Promise<AxiosResponse<T>>} |
||||
*/ |
||||
async function request(url, method, params, config) { |
||||
switch (method) { |
||||
case METHOD.GET: |
||||
return axios.get(url, {params, ...config}) |
||||
case METHOD.POST: |
||||
return axios.post(url, params, config) |
||||
default: |
||||
return axios.get(url, {params, ...config}) |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 设置认证信息 |
||||
* @param auth {Object} |
||||
* @param authType {AUTH_TYPE} 认证类型,默认:{AUTH_TYPE.BEARER} |
||||
*/ |
||||
function setAuthorization(auth, authType = AUTH_TYPE.BEARER) { |
||||
switch (authType) { |
||||
case AUTH_TYPE.BEARER: |
||||
Cookie.set(xsrfHeaderName, 'Bearer ' + auth.token, {expires: auth.expireAt}) |
||||
break |
||||
case AUTH_TYPE.BASIC: |
||||
case AUTH_TYPE.AUTH1: |
||||
case AUTH_TYPE.AUTH2: |
||||
default: |
||||
break |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 移出认证信息 |
||||
* @param authType {AUTH_TYPE} 认证类型 |
||||
*/ |
||||
function removeAuthorization(authType = AUTH_TYPE.BEARER) { |
||||
switch (authType) { |
||||
case AUTH_TYPE.BEARER: |
||||
Cookie.remove(xsrfHeaderName) |
||||
break |
||||
case AUTH_TYPE.BASIC: |
||||
case AUTH_TYPE.AUTH1: |
||||
case AUTH_TYPE.AUTH2: |
||||
default: |
||||
break |
||||
} |
||||
} |
||||
// 加密白名单
|
||||
const encryptWhite = ['/oil-finance/oilOrderInfo/importExcelOrder'] |
||||
let a = [] |
||||
// request 拦截器
|
||||
service.interceptors.request.use( |
||||
config => { |
||||
let source = CancelToken.source(); |
||||
config.cancelToken = source.token; |
||||
if(a.includes(config.url)){ |
||||
source.cancel(`tooRapid`); |
||||
return config |
||||
} |
||||
a.push(config.url) |
||||
if ( timeoutWhite.includes(config.url)) { |
||||
config.timeout = 0 |
||||
} else { |
||||
config.timeout = timeout |
||||
} |
||||
const notEncrypt = config.notEncrypt |
||||
config.headers['dataSources'] = 'WEB' |
||||
if (store.getters.token) { |
||||
config.headers['Authorization'] = getToken() |
||||
} |
||||
const JSESSIONID = utils.uuid() |
||||
config.headers['JSESSIONID'] = JSESSIONID |
||||
config.headers['token'] = utils.bcrypt(JSESSIONID) |
||||
const env = process.env.VUE_APP_ENV |
||||
if (env === 'test') { |
||||
console.log('这里是测试') |
||||
// 测试环境,加密,打印参数
|
||||
// 设置jsessionid和token
|
||||
if (!notEncrypt && encryptWhite.indexOf(config.url) < 0) { |
||||
const data = { // 用于存储加密
|
||||
params: '' // 加密后的密文
|
||||
} |
||||
// 要加密
|
||||
console.log('请求路径', config.url, '参数加密前', config.data) |
||||
data.params = utils.encrypt(JSON.stringify(config.data)) |
||||
config.data = data |
||||
} |
||||
} |
||||
if (env === 'development') { |
||||
console.log('这里是测试') |
||||
// 测试环境,不加密,打印参数
|
||||
console.log('请求路径', config.url, '参数加密前', config.data) |
||||
} |
||||
|
||||
/** |
||||
* 检查认证信息 |
||||
* @param authType |
||||
* @returns {boolean} |
||||
*/ |
||||
function checkAuthorization(authType = AUTH_TYPE.BEARER) { |
||||
switch (authType) { |
||||
case AUTH_TYPE.BEARER: |
||||
if (Cookie.get(xsrfHeaderName)) { |
||||
return true |
||||
if (env === 'production') { |
||||
console.log('这里是生产') |
||||
// 生产环境,加密,不输出任何东西
|
||||
// 设置jsessionid和token
|
||||
const JSESSIONID = utils.uuid() |
||||
config.headers['JSESSIONID'] = JSESSIONID |
||||
config.headers['token'] = utils.bcrypt(JSESSIONID) |
||||
if (!notEncrypt && encryptWhite.indexOf(config.url) < 0) { |
||||
const data = { // 用于存储加密
|
||||
params: '' // 加密后的密文
|
||||
} |
||||
// 要加密
|
||||
data.params = utils.encrypt(JSON.stringify(config.data)) |
||||
config.data = data |
||||
} |
||||
break |
||||
case AUTH_TYPE.BASIC: |
||||
case AUTH_TYPE.AUTH1: |
||||
case AUTH_TYPE.AUTH2: |
||||
default: |
||||
break |
||||
} |
||||
return config |
||||
}, |
||||
error => { |
||||
console.log(error.message,'req') |
||||
return Promise.reject(error) |
||||
} |
||||
return false |
||||
} |
||||
) |
||||
|
||||
/** |
||||
* 加载 axios 拦截器 |
||||
* @param interceptors |
||||
* @param options |
||||
*/ |
||||
function loadInterceptors(interceptors, options) { |
||||
const {request, response} = interceptors |
||||
// 加载请求拦截器
|
||||
request.forEach(item => { |
||||
let {onFulfilled, onRejected} = item |
||||
if (!onFulfilled || typeof onFulfilled !== 'function') { |
||||
onFulfilled = config => config |
||||
// response 拦截器
|
||||
service.interceptors.response.use( |
||||
response => { |
||||
let urlIndex = a.indexOf(response.config.url) |
||||
if(urlIndex!==-1){ |
||||
a.splice(urlIndex,1); |
||||
console.log(a,'防抖移除') |
||||
} |
||||
if (!onRejected || typeof onRejected !== 'function') { |
||||
onRejected = error => Promise.reject(error) |
||||
console.log(a,response.config.url,'闭包') |
||||
// 这里设置loading
|
||||
const res = response.data |
||||
const env = process.env.VUE_APP_ENV |
||||
if (response.headers['content-type'].indexOf('application/json') !== -1) { |
||||
if (env === 'test') { |
||||
// 测试环境,进行加密解密,打印路径和数据
|
||||
if (res.encrypt === 1) { |
||||
// 加密的数据,需要解密
|
||||
console.log('请求路径', response.config.url, '返回结果解密前', res) |
||||
const dataParam = JSON.parse(utils.decrypt(res.data)) |
||||
res.data = JSON.stringify(dataParam) === '{}' ? null : dataParam |
||||
console.log('请求路径', response.config.url, '返回结果解密后', res) |
||||
console.log('-------------------------------------------') |
||||
} else { |
||||
console.log('请求路径', response.config.url, '返回结果未加密', res) |
||||
console.log('-------------------------------------------') |
||||
} |
||||
} |
||||
if (env === 'production') { |
||||
// 生产环境,进行加密解密,不输出日志
|
||||
if (res.encrypt === 1) { |
||||
// 加密的数据,需要解密
|
||||
const dataParam = JSON.parse(utils.decrypt(res.data)) |
||||
res.data = JSON.stringify(dataParam) === '{}' ? null : dataParam |
||||
} |
||||
} |
||||
} else { |
||||
return res |
||||
} |
||||
axios.interceptors.request.use( |
||||
config => onFulfilled(config, options), |
||||
error => onRejected(error, options) |
||||
) |
||||
}) |
||||
// 加载响应拦截器
|
||||
response.forEach(item => { |
||||
let {onFulfilled, onRejected} = item |
||||
if (!onFulfilled || typeof onFulfilled !== 'function') { |
||||
onFulfilled = response => response |
||||
|
||||
// 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
|
||||
if (res && res.code) { |
||||
if (res.code === 42011) { |
||||
message.error(res.msg||'您的登录已失效,请重新登录') |
||||
// to re-login
|
||||
// Message({
|
||||
// message: res.msg || '您的登录已失效,请重新登录',
|
||||
// type: 'error',
|
||||
// duration: 5 * 1000
|
||||
// })
|
||||
store.dispatch('user/resetToken').then(() => { |
||||
location.reload() |
||||
}) |
||||
// 排除自定义的车队返回结果状态码
|
||||
} else if (res.code !== 20000 && res.code !== 30001 && res.code !== 30002 && res.code !== 20001) { |
||||
if(WhiteApiErr.includes(response.config.url.split('/')[3])){ |
||||
return res |
||||
}else{ |
||||
message.error(res.msg||'操作失败') |
||||
return Promise.reject(new Error(res.message || '操作失败')) |
||||
} |
||||
} else { |
||||
return res |
||||
} |
||||
} |
||||
if (!onRejected || typeof onRejected !== 'function') { |
||||
onRejected = error => Promise.reject(error) |
||||
}, |
||||
(error) => { |
||||
if(error.message=='tooRapid'){ |
||||
console.log(error,'res防抖拦截') |
||||
message.warning ('请求过于频繁!') |
||||
}else{ |
||||
let urlIndex = a.indexOf(error.config.url) |
||||
if(urlIndex!==-1){ |
||||
a.splice(urlIndex,1); |
||||
} |
||||
message.error ('操作失败!') |
||||
} |
||||
axios.interceptors.response.use( |
||||
response => onFulfilled(response, options), |
||||
error => onRejected(error, options) |
||||
) |
||||
}) |
||||
} |
||||
|
||||
/** |
||||
* 解析 url 中的参数 |
||||
* @param url |
||||
* @returns {Object} |
||||
*/ |
||||
function parseUrlParams(url) { |
||||
const params = {} |
||||
if (!url || url === '' || typeof url !== 'string') { |
||||
return params |
||||
} |
||||
const paramsStr = url.split('?')[1] |
||||
if (!paramsStr) { |
||||
return params |
||||
} |
||||
const paramsArr = paramsStr.replace(/&|=/g, ' ').split(' ') |
||||
for (let i = 0; i < paramsArr.length / 2; i++) { |
||||
const value = paramsArr[i * 2 + 1] |
||||
params[paramsArr[i * 2]] = value === 'true' ? true : (value === 'false' ? false : value) |
||||
return Promise.reject(error) |
||||
} |
||||
return params |
||||
} |
||||
) |
||||
|
||||
export { |
||||
METHOD, |
||||
AUTH_TYPE, |
||||
request, |
||||
setAuthorization, |
||||
removeAuthorization, |
||||
checkAuthorization, |
||||
loadInterceptors, |
||||
parseUrlParams |
||||
} |
||||
export default service |
||||
|
||||
Loading…
Reference in new issue