Commit fdf67e83 authored by 水落(YangLei)'s avatar 水落(YangLei)

feat: 项目结构调整,api请求处理

parent b6e6a7c4
VUE_APP_API_BASE_URL=http://dev.iczer.com
VUE_APP_API_BASE_URL=http://platform.kuopu.net:9300
......@@ -5,30 +5,29 @@ import Viser from 'viser-vue';
import Router from 'vue-router';
import { initRouter } from './router';
import VueI18n from 'vue-i18n';
import {accountModule, settingModule} from './pages/frame/store';
import { accountModule, settingModule } from './pages/frame/store';
import App from './App.vue';
import "tailwindcss/tailwind.css"
import 'tailwindcss/tailwind.css';
import 'animate.css/source/animate.css';
import './theme/index.less';
import Plugins from './plugins';
import { loadRoutes, loadGuards, setAppOptions } from './utils/routerUtil';
import { loadInterceptors } from './utils/requestUtil';
import guards from './router/guards';
import interceptors from './router/interceptors';
import { loadResponseInterceptor } from './utils/requestUtil';
import '@/mock';
// import '@/mock';
import 'moment/locale/zh-cn';
//设置为非生产提示
//设置为非生产提示
Vue.config.productionTip = false;
//装载Vuex控件
Vue.use(Vuex)
//加载 框架的module包括 命名空间accountModule,settingModule
Vue.use(Vuex);
//加载 框架的module包括 命名空间accountModule,settingModule
const store = new Vuex.Store({
modules: {accountModule, settingModule}
modules: { accountModule, settingModule },
});
//装载vue-router控件 如果开发时 不用动态可直接修改这里 isAsynRount=false
......@@ -44,11 +43,12 @@ const localeLang = store.state.settingModule.lang;
//default'EN'
const fallbackLang = store.state.settingModule.fallbackLang;
const i18n = new VueI18n({
locale: localeLang,
fallbackLocale: fallbackLang,
silentFallbackWarn: true,
locale: localeLang,
fallbackLocale: fallbackLang,
silentFallbackWarn: true,
});
//装载antd控件
Vue.use(Antd);
......@@ -60,17 +60,26 @@ Vue.use(Plugins);
//启动引导方法应用启动时需要执行的操作放在这里
//设置应用配置
setAppOptions({ router, store, i18n });
// 加载 axios 拦截器
loadInterceptors(interceptors, { router, store, i18n, message: Vue.prototype.$message });
// 加载路由
loadRoutes();
// 加载路由守卫
loadGuards(guards, { router, store, i18n, message: Vue.prototype.$message });
// this.$notification.open({
// message: 'Notification Title',
// description:
// 'This is the content of the notification. This is the content of the notification. This is the content of the notification.',
// onClick: () => {
// console.log('Notification Clicked!');
// },
// });
loadResponseInterceptor();
new Vue({
router,
store,
i18n,
render: h => h(App),
router,
store,
i18n,
render: h => h(App),
}).$mount('#app');
<template>
<a-dropdown class="lang header-item">
<div>
<a-icon type="global" /> {{langAlias}}
</div>
<div><a-icon type="global" /> {{ langAlias }}</div>
<a-menu @click="val => setLang(val.key)" :selected-keys="[lang]" slot="overlay">
<a-menu-item v-for=" lang in langList" :key="lang.key">{{lang.key.toLowerCase() + ' ' + lang.name}}</a-menu-item>
<a-menu-item v-for="lang in langList" :key="lang.key">
{{ lang.key.toLowerCase() + ' ' + lang.name }}
</a-menu-item>
</a-menu>
</a-dropdown>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import {globalConfig} from '@/config';
import { globalConfig } from '@/config';
export default {
name: "LayoutTopHeaderLang",
name: 'LayoutTopHeaderLang',
data() {
return {
langList: globalConfig.langs,
};
},
computed: {
...mapState("settingModule", ["lang"]),
...mapState('settingModule', ['lang']),
langAlias() {
let lang = this.langList.find((item) => item.key == this.lang);
let lang = this.langList.find(item => item.key == this.lang);
return lang.alias;
},
},
methods: {
...mapMutations("settingModule", ["setLang"]),
...mapMutations('settingModule', ['setLang']),
},
};
</script>
<style lang="less">
</style>
import { request, METHOD, removeAuthorization } from '@/utils/requestUtil';
import BASE_URL from '@/utils/baseUrlUtil';
import { request, METHOD } from '@/utils/requestUtil';
import md5 from 'crypto-js/md5';
/**
* 登录服务,登录成功后 根据用户ID 获取用户 角色 + 菜单 + 功能权限 + 用户基本信息
......@@ -7,27 +7,25 @@ import BASE_URL from '@/utils/baseUrlUtil';
* @param password 账户密码
* @returns {Promise<AxiosResponse<T>>}
*/
export async function login(name, password) {
let loginApi = `${BASE_URL}/login`;
return request(loginApi, METHOD.POST, {
name: name,
password: password
});
export async function login(userName, password) {
return request('/api/v1/login', METHOD.POST, {
userName,
password: md5(password).toString(),
});
}
/**
* 退出登录
*/
export function logout() {
//清除所有保存的信息
localStorage.removeItem(process.env.VUE_APP_ROUTES_KEY);
localStorage.removeItem(process.env.VUE_APP_PERMISSIONS_KEY);
localStorage.removeItem(process.env.VUE_APP_ROLES_KEY);
localStorage.removeItem(process.env.VUE_APP_USER_KEY);
removeAuthorization();
//清除所有保存的信息
localStorage.removeItem(process.env.VUE_APP_ROUTES_KEY);
localStorage.removeItem(process.env.VUE_APP_PERMISSIONS_KEY);
localStorage.removeItem(process.env.VUE_APP_ROLES_KEY);
localStorage.removeItem(process.env.VUE_APP_USER_KEY);
}
export default {
login,
logout,
}
login,
logout,
};
import { globalConfig, settingConfig } from "@/config";
import { formatFullPath } from "@/utils/i18nUtil";
import { filterMenu } from "@/utils/authorityUtil";
import { getLocalSetting } from "@/utils/themeUtil";
import deepClone from "lodash.clonedeep";
import { globalConfig, settingConfig } from '@/config';
import { formatFullPath } from '@/utils/i18nUtil';
import { filterMenu } from '@/utils/authorityUtil';
import { getLocalSetting } from '@/utils/themeUtil';
import { langUtil } from '@/utils';
import deepClone from 'lodash.clonedeep';
const localSetting = getLocalSetting(true);
const customTitlesStr = sessionStorage.getItem(process.env.VUE_APP_TBAS_TITLES_KEY);
......@@ -17,6 +18,7 @@ export default {
pageMinHeight: 0,
menuData: [],
activatedFirst: undefined,
lang: '',
customTitles,
...settingConfig,
...localSetting,
......@@ -34,7 +36,7 @@ export default {
if (menuData.length > 0 && !menuData[0].fullPath) {
formatFullPath(menuData);
}
return menuData.map((item) => {
return menuData.map(item => {
const menuItem = { ...item };
delete menuItem.children;
return menuItem;
......@@ -45,7 +47,7 @@ export default {
if (menuData.length > 0 && !menuData[0].fullPath) {
formatFullPath(menuData);
}
const current = menuData.find((menu) => menu.fullPath === activatedFirst);
const current = menuData.find(menu => menu.fullPath === activatedFirst);
return (current && current.children) || [];
},
},
......@@ -73,6 +75,7 @@ export default {
},
setLang(state, lang) {
state.lang = lang;
langUtil.set(lang);
},
setHideSetting(state, hideSetting) {
state.hideSetting = hideSetting;
......@@ -97,13 +100,16 @@ export default {
},
setCustomTitle(state, { path, title }) {
if (title) {
const obj = state.customTitles.find((item) => item.path === path);
const obj = state.customTitles.find(item => item.path === path);
if (obj) {
obj.title = title;
} else {
state.customTitles.push({ path, title });
}
sessionStorage.setItem(process.env.VUE_APP_TBAS_TITLES_KEY, JSON.stringify(state.customTitles));
sessionStorage.setItem(
process.env.VUE_APP_TBAS_TITLES_KEY,
JSON.stringify(state.customTitles),
);
}
},
},
......
......@@ -12,8 +12,12 @@
<a-tabs size="large" :tabBarStyle="{ textAlign: 'center' }">
<a-tab-pane :tab="$t('tabTitle')" key="1">
<a-form-item>
<a-input autocomplete="autocomplete" size="large" :placeholder="$t('idPlaceHolder')" v-decorator="[
'name',
<a-input
autocomplete="autocomplete"
size="large"
:placeholder="$t('idPlaceHolder')"
v-decorator="[
'userName',
{
rules: [
{
......@@ -23,12 +27,18 @@
},
],
},
]">
]"
>
<a-icon slot="prefix" type="user" />
</a-input>
</a-form-item>
<a-form-item>
<a-input size="large" :placeholder="$t('pwdPlaceHolder')" autocomplete="autocomplete" type="password" v-decorator="[
<a-input
size="large"
:placeholder="$t('pwdPlaceHolder')"
autocomplete="autocomplete"
type="password"
v-decorator="[
'password',
{
rules: [
......@@ -39,7 +49,8 @@
},
],
},
]">
]"
>
<a-icon slot="prefix" type="lock" />
</a-input>
</a-form-item>
......@@ -50,7 +61,14 @@
<a style="float: right">{{ $t('forgetPwdLink') }}</a>
</div>
<a-form-item>
<a-button :loading="logging" class="logging-button" size="large" htmlType="submit" type="primary">{{ $t('loginButton') }}</a-button>
<a-button
:loading="logging"
class="logging-button"
size="large"
htmlType="submit"
type="primary"
>{{ $t('loginButton') }}</a-button
>
</a-form-item>
</a-form>
</div>
......@@ -60,13 +78,12 @@
<script>
import CommonLayout from '@/pages/frame/layouts/CommonLayout';
import { login } from '@/pages/frame/services/accountService';
import { setAuthorization } from '@/utils/requestUtil';
import { setToken } from '@/utils/requestUtil';
import { loadRoutes } from '@/utils/routerUtil';
import { mapMutations } from 'vuex';
import loginI18n from './i18n';
export default {
name: 'yarn',
components: { CommonLayout },
i18n: loginI18n,
data() {
......@@ -85,13 +102,12 @@ export default {
...mapMutations('accountModule', ['setUser', 'setPermissions', 'setRoles']),
onSubmit(e) {
e.preventDefault();
this.form.validateFields((err) => {
this.form.validateFields(err => {
if (!err) {
this.logging = true;
const name = this.form.getFieldValue('name');
const userName = this.form.getFieldValue('userName');
const password = this.form.getFieldValue('password');
login(name, password).then(this.afterLogin);
login(userName, password).then(this.afterLogin);
}
});
},
......@@ -100,24 +116,19 @@ export default {
},
afterLogin(result) {
this.logging = false;
const loginResult = result.data;
const { token, userId } = result;
setToken(token);
this.$router.replace('/dashboard/workbench');
if (loginResult.code >= 0) {
const { user, permissions, roles, routers } = loginResult.data;
this.setUser(user);
this.setPermissions(permissions);
this.setRoles(roles);
setAuthorization({
token: loginResult.data.token,
expireAt: new Date(loginResult.data.expireAt),
});
// 获取路由配置
loadRoutes(routers);
this.$router.push('/dashboard/workbench');
this.$message.success(loginResult.message, 2);
} else {
this.$message.error(loginResult.message, 2);
}
// this.setUser(user);
// this.setPermissions(permissions);
// this.setRoles(roles);
// setAuthorization({
// token: loginResult.data.token,
// expireAt: new Date(loginResult.data.expireAt),
// });
// // 获取路由配置
// loadRoutes(routers);
},
},
};
......
export default {
messages: {
zh_CN: {
appName: '基于Antd Vue v1.73 的前端小框架',
tabTitle: '账号密码登录',
idPlaceHolder: '请输入登录账号',
pwdPlaceHolder: '请输入登录密码',
autoLoginLink: '自动登录',
forgetPwdLink: '忘记密码',
loginButton: '登录',
idNotBlankValider: '登录Id不能为空',
pwdNotBlankValider: '登录密码不能为空',
messages: {
zh_CN: {
appName: '基于Antd Vue v1.73 的前端小框架',
tabTitle: '账号密码登录',
idPlaceHolder: '请输入登录账号',
pwdPlaceHolder: '请输入登录密码',
autoLoginLink: '自动登录',
forgetPwdLink: '忘记密码',
loginButton: '登录',
idNotBlankValider: '登录Id不能为空',
pwdNotBlankValider: '登录密码不能为空',
},
en_US: {
appName: 'Akina Antd Vue Pro',
tabTitle: 'Login Account',
idPlaceHolder: 'Please input login Id',
pwdPlaceHolder: 'Please input password',
autoLoginLink: 'Auto Login',
forgetPwdLink: 'Forget Password',
loginButton: 'Login',
idNotBlankValider: 'Login Id is required',
pwdNotBlankValider: 'Login password is required',
},
},
en_US: {
appName: 'Akina Antd Vue Pro',
tabTitle: 'Login Account',
idPlaceHolder: 'Please input login Id',
pwdPlaceHolder: 'Please input password',
autoLoginLink: 'Auto Login',
forgetPwdLink: 'Forget Password',
loginButton: 'Login',
idNotBlankValider: 'Login Id is required',
pwdNotBlankValider: 'Login password is required',
},
}
}
};
import {hasAuthority} from '@/utils/authorityUtil'
import {loginIgnore} from '@/router/index'
import {checkAuthorization} from '@/utils/requestUtil'
import NProgress from 'nprogress'
import { hasAuthority } from '@/utils/authorityUtil';
import { loginIgnore } from '@/router/index';
import { checkAuthorization } from '@/utils/requestUtil';
import NProgress from 'nprogress';
NProgress.configure({ showSpinner: false })
NProgress.configure({ showSpinner: false });
/**
* 进度条开始
......@@ -12,12 +12,12 @@ NProgress.configure({ showSpinner: false })
* @param next
*/
const progressStart = (to, from, next) => {
// start progress bar
if (!NProgress.isStarted()) {
NProgress.start()
}
next()
}
// start progress bar
if (!NProgress.isStarted()) {
NProgress.start();
}
next();
};
/**
* 登录守卫
......@@ -27,14 +27,14 @@ const progressStart = (to, from, next) => {
* @param options
*/
const loginGuard = (to, from, next, options) => {
const {message} = options
if (!loginIgnore.includes(to) && !checkAuthorization()) {
message.warning('登录已失效,请重新登录')
next({path: '/login'})
} else {
next()
}
}
const { message } = options;
if (!loginIgnore.includes(to) && !checkAuthorization()) {
message.warning('登录已失效,请重新登录');
next({ path: '/login' });
} else {
next();
}
};
/**
* 权限守卫
......@@ -44,17 +44,17 @@ const loginGuard = (to, from, next, options) => {
* @param options
*/
const authorityGuard = (to, from, next, options) => {
const {store, message} = options
const permissions = store.getters['accountModule/permissions']
const roles = store.getters['accountModule/roles']
if (!hasAuthority(to, permissions, roles)) {
message.warning(`对不起,您无权访问页面: ${to.fullPath},请联系管理员`)
next({path: '/403'})
// NProgress.done()
} else {
next()
}
}
const { store, message } = options;
const permissions = store.getters['accountModule/permissions'];
const roles = store.getters['accountModule/roles'];
if (!hasAuthority(to, permissions, roles)) {
message.warning(`对不起,您无权访问页面: ${to.fullPath},请联系管理员`);
next({ path: '/403' });
// NProgress.done()
} else {
next();
}
};
/**
* 混合导航模式下一级菜单跳转重定向
......@@ -65,27 +65,27 @@ const authorityGuard = (to, from, next, options) => {
* @returns {*}
*/
const redirectGuard = (to, from, next, options) => {
const {store} = options
const getFirstChild = (routes) => {
const route = routes[0]
if (!route.children || route.children.length === 0) {
return route
}
return getFirstChild(route.children)
}
if (store.state.settingModule.layout === 'mix') {
const firstMenu = store.getters['settingModule/firstMenu']
if (firstMenu.find(item => item.fullPath === to.fullPath)) {
store.commit('settingModule/setActivatedFirst', to.fullPath)
const subMenu = store.getters['settingModule/subMenu']
if (subMenu.length > 0) {
const redirect = getFirstChild(subMenu)
return next({path: redirect.fullPath})
}
const { store } = options;
const getFirstChild = routes => {
const route = routes[0];
if (!route.children || route.children.length === 0) {
return route;
}
return getFirstChild(route.children);
};
if (store.state.settingModule.layout === 'mix') {
const firstMenu = store.getters['settingModule/firstMenu'];
if (firstMenu.find(item => item.fullPath === to.fullPath)) {
store.commit('settingModule/setActivatedFirst', to.fullPath);
const subMenu = store.getters['settingModule/subMenu'];
if (subMenu.length > 0) {
const redirect = getFirstChild(subMenu);
return next({ path: redirect.fullPath });
}
}
}
}
next()
}
next();
};
/**
* 进度条结束
......@@ -94,11 +94,11 @@ const redirectGuard = (to, from, next, options) => {
* @param options
*/
const progressDone = () => {
// finish progress bar
NProgress.done()
}
// finish progress bar
NProgress.done();
};
export default {
beforeEach: [progressStart, loginGuard, authorityGuard, redirectGuard],
afterEach: [progressDone]
}
beforeEach: [progressStart, loginGuard, authorityGuard, redirectGuard],
afterEach: [progressDone],
};
import { notification } from 'antd';
import { getLocale, history } from 'umi';
import config from '@/config';
import { clearLoginStatus, getLocaleText } from '@/utils';
import HttpRequest from './kim-request';
import store from 'store';
// const codeMessage = {
// 200: getLocaleText('kim.system.request.200'),
// 201: getLocaleText('kim.system.request.201'),
// 202: getLocaleText('kim.system.request.202'),
// 204: getLocaleText('kim.system.request.204'),
// 400: getLocaleText('kim.system.request.400'),
// 401: getLocaleText('kim.system.request.401'),
// 403: getLocaleText('kim.system.request.403'),
// 404: getLocaleText('kim.system.request.404'),
// 406: getLocaleText('kim.system.request.406'),
// 410: getLocaleText('kim.system.request.410'),
// 422: getLocaleText('kim.system.request.422'),
// 500: getLocaleText('kim.system.request.500'),
// 502: getLocaleText('kim.system.request.502'),
// 503: getLocaleText('kim.system.request.503'),
// 504: getLocaleText('kim.system.request.504'),
// };
const {
request: {
baseUrl,
apiPrefix,
resCodeKey,
resMessageKey,
successCode,
isThrowError = true,
authCodes = ['error.system.authc'],
},
} = config;
/**
* 组装url
* @param {url} url
* @param {{}} more
*/
const merge = (url: string, more: any) => {
if (more && more.apiPrefix && typeof more.apiPrefix === 'string') {
return `${config.apiPrefix}${url}`;
}
if (apiPrefix && typeof apiPrefix === 'string') {
return `${config.apiPrefix}${url}`;
}
return url;
};
const headers = () => ({
Authorization: store.get('token'),
'X-Access-Lang': getLocale().replace(/-/, '_'),
});
const axios = new HttpRequest({
baseUrl,
headers: headers || {},
});
/**
* 正常返回结果处理
* @param {返回请求数据} response
* @param {配置项} more
*/
const handleResponse = (response) => {
const { data } = response;
console.log('response', response);
//
if (`${data[resCodeKey]}` !== `${successCode}`) {
if (isThrowError) {
const errorMessage =
data[resMessageKey] || getLocaleText('kim.system.request.default.message');
let error = new Error();
error = { ...error, ...data };
error.code = data[resCodeKey];
error.message = errorMessage;
return Promise.reject(error);
}
}
// success
return data;
};
const handleError = (error, more) => {
const codeMessage = {
200: getLocaleText('kim.system.request.200'),
201: getLocaleText('kim.system.request.201'),
202: getLocaleText('kim.system.request.202'),
204: getLocaleText('kim.system.request.204'),
400: getLocaleText('kim.system.request.400'),
401: getLocaleText('kim.system.request.401'),
403: getLocaleText('kim.system.request.403'),
404: getLocaleText('kim.system.request.404'),
406: getLocaleText('kim.system.request.406'),
410: getLocaleText('kim.system.request.410'),
422: getLocaleText('kim.system.request.422'),
500: getLocaleText('kim.system.request.500'),
502: getLocaleText('kim.system.request.502'),
503: getLocaleText('kim.system.request.503'),
504: getLocaleText('kim.system.request.504'),
};
const { response } = error;
const options = { isThrowError, ...more };
// status
if (response && response.status) {
const errorText = codeMessage[response.status] || response.statusText;
const {
status,
config: { url },
} = response;
notification.error({
message: `${getLocaleText('kim.system.request.dialog.title')} ${status}`,
description: `${url}${errorText}`,
});
// 跳转到404页面
if (status >= 404 && status < 422) {
history.push('/exception/404');
}
if (status <= 504 && status >= 500) {
history.push('/exception/500');
}
// 跳转到登录页面 可能原因:token 失效
if (status === 403 && status === 401) {
clearLoginStatus();
history.push('/user/login');
}
} else {
// code
const { code, message } = error;
notification.error({
key: `notification_${code ? message : code}`,
message: getLocaleText('kim.system.request.dialog.title'),
description: message,
});
// 跳转到登录页面 可能原因:token 失效
if (authCodes && authCodes.includes(code)) {
// 清空相关信息
clearLoginStatus();
history.push('/user/login');
}
}
if (options.isThrowError) {
throw error;
} else {
return error;
}
};
export default function request(url, options = {}, more = {}, handle = false) {
let newOptions = options;
newOptions.url = url;
if (more.headers) {
newOptions = { ...options, headers: more.headers };
}
if (handle) {
return axios.request(newOptions);
}
return axios
.request(newOptions)
.then((response) => handleResponse(response, more))
.catch((error) => handleError(error, more));
}
/**
* get请求
* @param url
* @param data
* @param more
* @returns {AxiosPromise<any>|Promise<Promise<never> | 返回请求数据.data | *>}
*/
const get = (url, data, more = {}) => {
if (data?.current && !data?.pageNum) {
// eslint-disable-next-line no-param-reassign
data.pageNum = data.current;
}
return request(
`${merge(url, more)}`,
{
method: 'get', // default
params: data,
},
more,
);
};
/**
* post请求
* @param url
* @param data
* @param more
* @returns {AxiosPromise<any>|Promise<Promise<never> | 返回请求数据.data | *>}
*/
const post = (url, data, more = {}) =>
request(
`${merge(url, more)}`,
{
method: 'post', // default
data,
},
more,
);
/**
* put请求
* @param url
* @param data
* @param more
* @returns {AxiosPromise<any>|Promise<Promise<never> | 返回请求数据.data | *>}
*/
const put = (url, data, more = {}) =>
request(
`${merge(url, more)}`,
{
method: 'put', // default
data,
},
more,
);
/**
* delete请求
* @param url
* @param data
* @param more
* @returns {AxiosPromise<any>|Promise<Promise<never> | 返回请求数据.data | *>}
*/
const del = (url, data, more = {}) =>
request(
`${merge(url, more)}`,
{
method: 'delete', // default
data,
},
more,
);
/**
* patch请求
* @param url
* @param data
* @param more
* @returns {AxiosPromise<any>|Promise<Promise<never> | 返回请求数据.data | *>}
*/
const patch = (url, data, more = {}) =>
request(
`${merge(url, more)}`,
{
method: 'patch', // default
data,
...more,
},
more,
);
const downloadFile = (url, data, more = {}) => {
console.log('xiazai');
return request(
`${merge(url, more)}`,
{
method: 'get', // default
params: data,
responseType: 'blob',
},
more,
true,
).then((response) => {
return new Blob([response.data]);
});
};
const formDataUpload = (url, options, more = {}) => {
const formData = new FormData();
if (options) {
Object.keys(options).forEach((key) => {
formData.append(key, options[key]);
});
}
return post(`${merge(url, more)}`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
Authorization: store.get('token'),
},
...more,
}).then((res) => {
const { code } = res;
if (code === 'sys.success' && typeof options.onSuccess) {
return options.onSuccess(res);
}
return res;
});
};
/**
* 上传文件
* @param {url} url
* @param {data} data
* @param {type} type
* @param {more} more
*/
const uploadFile = (url, data, type = 'formData', more = {}) => {
if (type === 'formData') {
return formDataUpload(url, data, more);
}
return null;
};
export { request, get, post, put, del, patch, uploadFile, downloadFile };
export { default as langUtil } from './langUtils';
const LANG_KEY = 'LANG_KEY';
function setLang(val) {
window.sessionStorage.setItem(LANG_KEY, val);
}
function getLang() {
return window.sessionStorage.getItem(LANG_KEY);
}
export default {
get: getLang,
set: setLang,
};
import axios from 'axios'
import Cookie from 'js-cookie'
import axios from 'axios';
import { notification } from 'ant-design-vue';
import md5 from 'crypto-js/md5';
import { langUtil } from '.';
// 跨域认证信息 header 名
const xsrfHeaderName = 'Authorization'
const xsrfHeaderName = 'Authorization';
axios.defaults.timeout = 5000
axios.defaults.withCredentials= true
axios.defaults.xsrfHeaderName= xsrfHeaderName
axios.defaults.xsrfCookieName= xsrfHeaderName
axios.defaults.timeout = 5000;
axios.defaults.withCredentials = true;
axios.defaults.xsrfHeaderName = xsrfHeaderName;
axios.defaults.xsrfCookieName = xsrfHeaderName;
/**
* @param {*} info 提示函数
*/
function loadResponseInterceptor() {
axios.interceptors.request.use(
function(config) {
// 在发送请求之前做些什么
config.headers = {
...config.headers,
Authorization: getToken(),
'X-Access-Lang': langUtil.get() || 'zh_CN',
};
return config;
},
function(error) {
// 对请求错误做些什么
return Promise.reject(error);
},
);
// 添加响应拦截器
axios.interceptors.response.use(
function(response) {
const { data } = response;
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
if (data.code === 'sys.success') {
return data.data;
}
notification.error({
message: data.code,
description: h => h('pre', data.message),
});
return Promise.reject(data.message);
},
function(error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
notification.error({
message: `${error.response.status} ${error.response.statusText}`,
description: h => h('pre', error.message),
});
return Promise.reject(error);
},
);
}
// 认证类型
const AUTH_TYPE = {
BEARER: 'Bearer',
BASIC: 'basic',
AUTH1: 'auth1',
AUTH2: 'auth2',
}
BEARER: 'Bearer',
BASIC: 'basic',
AUTH1: 'auth1',
AUTH2: 'auth2',
};
// http method
const METHOD = {
GET: 'get',
POST: 'post',
PUT: 'put',
DELETE: 'delete',
}
GET: 'get',
POST: 'post',
PUT: 'put',
DELETE: 'delete',
};
/**
* axios请求
......@@ -34,142 +83,66 @@ const METHOD = {
* @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)
case METHOD.PUT:
return axios.put(url, params, config)
case METHOD.DELETE:
return axios.delete(url, {params, ...config})
default:
return axios.get(url, {params, ...config})
}
switch (method) {
case METHOD.GET:
return axios.get(url, { params, ...config });
case METHOD.POST:
return axios.post(url, params, config);
case METHOD.PUT:
return axios.put(url, params, config);
case METHOD.DELETE:
return axios.delete(url, { params, ...config });
default:
return axios.get(url, { params, ...config });
}
}
/**
* 设置认证信息
* @param auth {Object}
* @param authType {AUTH_TYPE} 认证类型,默认:{AUTH_TYPE.BEARER}
* 解析 url 中的参数
* @param url
* @returns {Object}
*/
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
}
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 params;
}
/**
* 移出认证信息
* @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 TOKEN_KEY = md5('TOKEN').toString();
function getToken() {
return window.sessionStorage.getItem(TOKEN_KEY) ?? '';
}
/**
* 检查认证信息
* @param authType
* @returns {boolean}
*/
function checkAuthorization(authType = AUTH_TYPE.BEARER) {
switch (authType) {
case AUTH_TYPE.BEARER:
if (Cookie.get(xsrfHeaderName)) {
return true
}
break
case AUTH_TYPE.BASIC:
case AUTH_TYPE.AUTH1:
case AUTH_TYPE.AUTH2:
default:
break
}
return false
function setToken(val) {
window.sessionStorage.setItem(TOKEN_KEY, val);
}
/**
* 加载 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
}
if (!onRejected || typeof onRejected !== 'function') {
onRejected = error => Promise.reject(error)
}
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
}
if (!onRejected || typeof onRejected !== 'function') {
onRejected = error => Promise.reject(error)
}
axios.interceptors.response.use(
response => onFulfilled(response, options),
error => onRejected(error, options)
)
})
function clearToken() {
window.sessionStorage.removeItem(TOKEN_KEY);
}
/**
* 解析 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 params
function checkAuthorization() {
return !!getToken();
}
export {
METHOD,
AUTH_TYPE,
request,
setAuthorization,
removeAuthorization,
checkAuthorization,
loadInterceptors,
parseUrlParams
}
METHOD,
AUTH_TYPE,
request,
parseUrlParams,
loadResponseInterceptor,
setToken,
checkAuthorization,
clearToken,
};
......@@ -5,74 +5,74 @@ import { globalConfig, settingConfig } from '../config';
const theme = settingConfig.theme;
function getThemeColors(color, $theme) {
const _color = color || theme.color
const mode = $theme || theme.mode
const replaceColors = getThemeToggleColors(_color, mode)
const themeColors = [
...replaceColors.mainColors,
...replaceColors.subColors,
...replaceColors.menuColors,
...replaceColors.contentColors,
...replaceColors.rgbColors,
...replaceColors.functionalColors.success,
...replaceColors.functionalColors.warning,
...replaceColors.functionalColors.error,
]
return themeColors
const _color = color || theme.color;
const mode = $theme || theme.mode;
const replaceColors = getThemeToggleColors(_color, mode);
const themeColors = [
...replaceColors.mainColors,
...replaceColors.subColors,
...replaceColors.menuColors,
...replaceColors.contentColors,
...replaceColors.rgbColors,
...replaceColors.functionalColors.success,
...replaceColors.functionalColors.warning,
...replaceColors.functionalColors.error,
];
return themeColors;
}
function changeThemeColor(newColor, $theme) {
let promise = client.changer.changeColor({newColors: getThemeColors(newColor, $theme)})
return promise
let promise = client.changer.changeColor({ newColors: getThemeColors(newColor, $theme) });
return promise;
}
function modifyVars(color) {
let _color = color || theme.color
const palettes = getAntdColors(_color, theme.mode)
const menuColors = getMenuColors(_color, theme.mode)
const {success, warning, error} = getFunctionalColors(theme.mode)
const primary = palettes[5]
return {
'primary-color': primary,
'primary-1': palettes[0],
'primary-2': palettes[1],
'primary-3': palettes[2],
'primary-4': palettes[3],
'primary-5': palettes[4],
'primary-6': palettes[5],
'primary-7': palettes[6],
'primary-8': palettes[7],
'primary-9': palettes[8],
'primary-10': palettes[9],
'info-color': primary,
'success-color': success[5],
'warning-color': warning[5],
'error-color': error[5],
'alert-info-bg-color': palettes[0],
'alert-info-border-color': palettes[2],
'alert-success-bg-color': success[0],
'alert-success-border-color': success[2],
'alert-warning-bg-color': warning[0],
'alert-warning-border-color': warning[2],
'alert-error-bg-color': error[0],
'alert-error-border-color': error[2],
'processing-color': primary,
'menu-dark-submenu-bg': menuColors[0],
'layout-header-background': menuColors[1],
'layout-trigger-background': menuColors[2],
'btn-danger-bg': error[4],
'btn-danger-border': error[4],
...globalConfig.theme[theme.mode]
}
let _color = color || theme.color;
const palettes = getAntdColors(_color, theme.mode);
const menuColors = getMenuColors(_color, theme.mode);
const { success, warning, error } = getFunctionalColors(theme.mode);
const primary = palettes[5];
return {
'primary-color': primary,
'primary-1': palettes[0],
'primary-2': palettes[1],
'primary-3': palettes[2],
'primary-4': palettes[3],
'primary-5': palettes[4],
'primary-6': palettes[5],
'primary-7': palettes[6],
'primary-8': palettes[7],
'primary-9': palettes[8],
'primary-10': palettes[9],
'info-color': primary,
'success-color': success[5],
'warning-color': warning[5],
'error-color': error[5],
'alert-info-bg-color': palettes[0],
'alert-info-border-color': palettes[2],
'alert-success-bg-color': success[0],
'alert-success-border-color': success[2],
'alert-warning-bg-color': warning[0],
'alert-warning-border-color': warning[2],
'alert-error-bg-color': error[0],
'alert-error-border-color': error[2],
'processing-color': primary,
'menu-dark-submenu-bg': menuColors[0],
'layout-header-background': menuColors[1],
'layout-trigger-background': menuColors[2],
'btn-danger-bg': error[4],
'btn-danger-border': error[4],
...globalConfig.theme[theme.mode],
};
}
function loadLocalTheme(localSetting) {
if (localSetting && localSetting.theme) {
let {color, mode} = localSetting.theme
color = color || theme.color
mode = mode || theme.mode
changeThemeColor(color, mode)
}
if (localSetting && localSetting.theme) {
let { color, mode } = localSetting.theme;
color = color || theme.color;
mode = mode || theme.mode;
changeThemeColor(color, mode);
}
}
/**
......@@ -81,23 +81,17 @@ function loadLocalTheme(localSetting) {
* @returns {Object}
*/
function getLocalSetting(loadTheme) {
let localSetting = {}
try {
const localSettingStr = localStorage.getItem(process.env.VUE_APP_SETTING_KEY)
localSetting = JSON.parse(localSettingStr)
} catch (e) {
console.error(e)
}
if (loadTheme) {
loadLocalTheme(localSetting)
}
return localSetting
let localSetting = {};
try {
const localSettingStr = localStorage.getItem(process.env.VUE_APP_SETTING_KEY) || '{}';
localSetting = JSON.parse(localSettingStr);
} catch (e) {
console.error(e);
}
if (loadTheme) {
loadLocalTheme(localSetting);
}
return localSetting;
}
export {
getThemeColors,
changeThemeColor,
modifyVars,
loadLocalTheme,
getLocalSetting
}
export { getThemeColors, changeThemeColor, modifyVars, loadLocalTheme, getLocalSetting };
......@@ -194,15 +194,17 @@ const assetsCDN = {
module.exports = {
devServer: {
// proxy: {
// '/api': { //此处要与 /services/api.js 中的 API_PROXY_PREFIX 值保持一致
// target: process.env.VUE_APP_API_BASE_URL,
// changeOrigin: true,
// pathRewrite: {
// '^/api': ''
// }
// }
// }
proxy: {
'/api': {
//此处要与 /services/api.js 中的 API_PROXY_PREFIX 值保持一致
// target: process.env.VUE_APP_API_BASE_URL,
target: 'http://platform.kuopu.net:9300',
changeOrigin: true,
// pathRewrite: {
// '^/api': ''
// }
},
},
},
pluginOptions: {
/**
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment