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'; ...@@ -5,30 +5,29 @@ import Viser from 'viser-vue';
import Router from 'vue-router'; import Router from 'vue-router';
import { initRouter } from './router'; import { initRouter } from './router';
import VueI18n from 'vue-i18n'; 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 App from './App.vue';
import "tailwindcss/tailwind.css" import 'tailwindcss/tailwind.css';
import 'animate.css/source/animate.css'; import 'animate.css/source/animate.css';
import './theme/index.less'; import './theme/index.less';
import Plugins from './plugins'; import Plugins from './plugins';
import { loadRoutes, loadGuards, setAppOptions } from './utils/routerUtil'; import { loadRoutes, loadGuards, setAppOptions } from './utils/routerUtil';
import { loadInterceptors } from './utils/requestUtil';
import guards from './router/guards'; import guards from './router/guards';
import interceptors from './router/interceptors'; import { loadResponseInterceptor } from './utils/requestUtil';
import '@/mock'; // import '@/mock';
import 'moment/locale/zh-cn'; import 'moment/locale/zh-cn';
//设置为非生产提示 //设置为非生产提示
Vue.config.productionTip = false; Vue.config.productionTip = false;
//装载Vuex控件 //装载Vuex控件
Vue.use(Vuex) Vue.use(Vuex);
//加载 框架的module包括 命名空间accountModule,settingModule //加载 框架的module包括 命名空间accountModule,settingModule
const store = new Vuex.Store({ const store = new Vuex.Store({
modules: {accountModule, settingModule} modules: { accountModule, settingModule },
}); });
//装载vue-router控件 如果开发时 不用动态可直接修改这里 isAsynRount=false //装载vue-router控件 如果开发时 不用动态可直接修改这里 isAsynRount=false
...@@ -44,11 +43,12 @@ const localeLang = store.state.settingModule.lang; ...@@ -44,11 +43,12 @@ const localeLang = store.state.settingModule.lang;
//default'EN' //default'EN'
const fallbackLang = store.state.settingModule.fallbackLang; const fallbackLang = store.state.settingModule.fallbackLang;
const i18n = new VueI18n({ const i18n = new VueI18n({
locale: localeLang, locale: localeLang,
fallbackLocale: fallbackLang, fallbackLocale: fallbackLang,
silentFallbackWarn: true, silentFallbackWarn: true,
}); });
//装载antd控件 //装载antd控件
Vue.use(Antd); Vue.use(Antd);
...@@ -60,17 +60,26 @@ Vue.use(Plugins); ...@@ -60,17 +60,26 @@ Vue.use(Plugins);
//启动引导方法应用启动时需要执行的操作放在这里 //启动引导方法应用启动时需要执行的操作放在这里
//设置应用配置 //设置应用配置
setAppOptions({ router, store, i18n }); setAppOptions({ router, store, i18n });
// 加载 axios 拦截器
loadInterceptors(interceptors, { router, store, i18n, message: Vue.prototype.$message });
// 加载路由 // 加载路由
loadRoutes(); loadRoutes();
// 加载路由守卫 // 加载路由守卫
loadGuards(guards, { router, store, i18n, message: Vue.prototype.$message }); 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({ new Vue({
router, router,
store, store,
i18n, i18n,
render: h => h(App), render: h => h(App),
}).$mount('#app'); }).$mount('#app');
<template> <template>
<a-dropdown class="lang header-item"> <a-dropdown class="lang header-item">
<div> <div><a-icon type="global" /> {{ langAlias }}</div>
<a-icon type="global" /> {{langAlias}}
</div>
<a-menu @click="val => setLang(val.key)" :selected-keys="[lang]" slot="overlay"> <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-menu>
</a-dropdown> </a-dropdown>
</template> </template>
<script> <script>
import { mapState, mapMutations } from 'vuex'; import { mapState, mapMutations } from 'vuex';
import {globalConfig} from '@/config'; import { globalConfig } from '@/config';
export default { export default {
name: "LayoutTopHeaderLang", name: 'LayoutTopHeaderLang',
data() { data() {
return { return {
langList: globalConfig.langs, langList: globalConfig.langs,
}; };
}, },
computed: { computed: {
...mapState("settingModule", ["lang"]), ...mapState('settingModule', ['lang']),
langAlias() { langAlias() {
let lang = this.langList.find((item) => item.key == this.lang); let lang = this.langList.find(item => item.key == this.lang);
return lang.alias; return lang.alias;
}, },
}, },
methods: { methods: {
...mapMutations("settingModule", ["setLang"]), ...mapMutations('settingModule', ['setLang']),
}, },
}; };
</script> </script>
<style lang="less">
</style>
import { request, METHOD, removeAuthorization } from '@/utils/requestUtil'; import { request, METHOD } from '@/utils/requestUtil';
import BASE_URL from '@/utils/baseUrlUtil'; import md5 from 'crypto-js/md5';
/** /**
* 登录服务,登录成功后 根据用户ID 获取用户 角色 + 菜单 + 功能权限 + 用户基本信息 * 登录服务,登录成功后 根据用户ID 获取用户 角色 + 菜单 + 功能权限 + 用户基本信息
...@@ -7,27 +7,25 @@ import BASE_URL from '@/utils/baseUrlUtil'; ...@@ -7,27 +7,25 @@ import BASE_URL from '@/utils/baseUrlUtil';
* @param password 账户密码 * @param password 账户密码
* @returns {Promise<AxiosResponse<T>>} * @returns {Promise<AxiosResponse<T>>}
*/ */
export async function login(name, password) { export async function login(userName, password) {
let loginApi = `${BASE_URL}/login`; return request('/api/v1/login', METHOD.POST, {
return request(loginApi, METHOD.POST, { userName,
name: name, password: md5(password).toString(),
password: password });
});
} }
/** /**
* 退出登录 * 退出登录
*/ */
export function logout() { export function logout() {
//清除所有保存的信息 //清除所有保存的信息
localStorage.removeItem(process.env.VUE_APP_ROUTES_KEY); localStorage.removeItem(process.env.VUE_APP_ROUTES_KEY);
localStorage.removeItem(process.env.VUE_APP_PERMISSIONS_KEY); localStorage.removeItem(process.env.VUE_APP_PERMISSIONS_KEY);
localStorage.removeItem(process.env.VUE_APP_ROLES_KEY); localStorage.removeItem(process.env.VUE_APP_ROLES_KEY);
localStorage.removeItem(process.env.VUE_APP_USER_KEY); localStorage.removeItem(process.env.VUE_APP_USER_KEY);
removeAuthorization();
} }
export default { export default {
login, login,
logout, logout,
} };
import { globalConfig, settingConfig } from "@/config"; import { globalConfig, settingConfig } from '@/config';
import { formatFullPath } from "@/utils/i18nUtil"; import { formatFullPath } from '@/utils/i18nUtil';
import { filterMenu } from "@/utils/authorityUtil"; import { filterMenu } from '@/utils/authorityUtil';
import { getLocalSetting } from "@/utils/themeUtil"; import { getLocalSetting } from '@/utils/themeUtil';
import deepClone from "lodash.clonedeep"; import { langUtil } from '@/utils';
import deepClone from 'lodash.clonedeep';
const localSetting = getLocalSetting(true); const localSetting = getLocalSetting(true);
const customTitlesStr = sessionStorage.getItem(process.env.VUE_APP_TBAS_TITLES_KEY); const customTitlesStr = sessionStorage.getItem(process.env.VUE_APP_TBAS_TITLES_KEY);
...@@ -17,6 +18,7 @@ export default { ...@@ -17,6 +18,7 @@ export default {
pageMinHeight: 0, pageMinHeight: 0,
menuData: [], menuData: [],
activatedFirst: undefined, activatedFirst: undefined,
lang: '',
customTitles, customTitles,
...settingConfig, ...settingConfig,
...localSetting, ...localSetting,
...@@ -34,7 +36,7 @@ export default { ...@@ -34,7 +36,7 @@ export default {
if (menuData.length > 0 && !menuData[0].fullPath) { if (menuData.length > 0 && !menuData[0].fullPath) {
formatFullPath(menuData); formatFullPath(menuData);
} }
return menuData.map((item) => { return menuData.map(item => {
const menuItem = { ...item }; const menuItem = { ...item };
delete menuItem.children; delete menuItem.children;
return menuItem; return menuItem;
...@@ -45,7 +47,7 @@ export default { ...@@ -45,7 +47,7 @@ export default {
if (menuData.length > 0 && !menuData[0].fullPath) { if (menuData.length > 0 && !menuData[0].fullPath) {
formatFullPath(menuData); formatFullPath(menuData);
} }
const current = menuData.find((menu) => menu.fullPath === activatedFirst); const current = menuData.find(menu => menu.fullPath === activatedFirst);
return (current && current.children) || []; return (current && current.children) || [];
}, },
}, },
...@@ -73,6 +75,7 @@ export default { ...@@ -73,6 +75,7 @@ export default {
}, },
setLang(state, lang) { setLang(state, lang) {
state.lang = lang; state.lang = lang;
langUtil.set(lang);
}, },
setHideSetting(state, hideSetting) { setHideSetting(state, hideSetting) {
state.hideSetting = hideSetting; state.hideSetting = hideSetting;
...@@ -97,13 +100,16 @@ export default { ...@@ -97,13 +100,16 @@ export default {
}, },
setCustomTitle(state, { path, title }) { setCustomTitle(state, { path, title }) {
if (title) { if (title) {
const obj = state.customTitles.find((item) => item.path === path); const obj = state.customTitles.find(item => item.path === path);
if (obj) { if (obj) {
obj.title = title; obj.title = title;
} else { } else {
state.customTitles.push({ path, title }); 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 @@ ...@@ -12,8 +12,12 @@
<a-tabs size="large" :tabBarStyle="{ textAlign: 'center' }"> <a-tabs size="large" :tabBarStyle="{ textAlign: 'center' }">
<a-tab-pane :tab="$t('tabTitle')" key="1"> <a-tab-pane :tab="$t('tabTitle')" key="1">
<a-form-item> <a-form-item>
<a-input autocomplete="autocomplete" size="large" :placeholder="$t('idPlaceHolder')" v-decorator="[ <a-input
'name', autocomplete="autocomplete"
size="large"
:placeholder="$t('idPlaceHolder')"
v-decorator="[
'userName',
{ {
rules: [ rules: [
{ {
...@@ -23,12 +27,18 @@ ...@@ -23,12 +27,18 @@
}, },
], ],
}, },
]"> ]"
>
<a-icon slot="prefix" type="user" /> <a-icon slot="prefix" type="user" />
</a-input> </a-input>
</a-form-item> </a-form-item>
<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', 'password',
{ {
rules: [ rules: [
...@@ -39,7 +49,8 @@ ...@@ -39,7 +49,8 @@
}, },
], ],
}, },
]"> ]"
>
<a-icon slot="prefix" type="lock" /> <a-icon slot="prefix" type="lock" />
</a-input> </a-input>
</a-form-item> </a-form-item>
...@@ -50,7 +61,14 @@ ...@@ -50,7 +61,14 @@
<a style="float: right">{{ $t('forgetPwdLink') }}</a> <a style="float: right">{{ $t('forgetPwdLink') }}</a>
</div> </div>
<a-form-item> <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-item>
</a-form> </a-form>
</div> </div>
...@@ -60,13 +78,12 @@ ...@@ -60,13 +78,12 @@
<script> <script>
import CommonLayout from '@/pages/frame/layouts/CommonLayout'; import CommonLayout from '@/pages/frame/layouts/CommonLayout';
import { login } from '@/pages/frame/services/accountService'; import { login } from '@/pages/frame/services/accountService';
import { setAuthorization } from '@/utils/requestUtil'; import { setToken } from '@/utils/requestUtil';
import { loadRoutes } from '@/utils/routerUtil'; import { loadRoutes } from '@/utils/routerUtil';
import { mapMutations } from 'vuex'; import { mapMutations } from 'vuex';
import loginI18n from './i18n'; import loginI18n from './i18n';
export default { export default {
name: 'yarn',
components: { CommonLayout }, components: { CommonLayout },
i18n: loginI18n, i18n: loginI18n,
data() { data() {
...@@ -85,13 +102,12 @@ export default { ...@@ -85,13 +102,12 @@ export default {
...mapMutations('accountModule', ['setUser', 'setPermissions', 'setRoles']), ...mapMutations('accountModule', ['setUser', 'setPermissions', 'setRoles']),
onSubmit(e) { onSubmit(e) {
e.preventDefault(); e.preventDefault();
this.form.validateFields((err) => { this.form.validateFields(err => {
if (!err) { if (!err) {
this.logging = true; this.logging = true;
const name = this.form.getFieldValue('name'); const userName = this.form.getFieldValue('userName');
const password = this.form.getFieldValue('password'); const password = this.form.getFieldValue('password');
login(userName, password).then(this.afterLogin);
login(name, password).then(this.afterLogin);
} }
}); });
}, },
...@@ -100,24 +116,19 @@ export default { ...@@ -100,24 +116,19 @@ export default {
}, },
afterLogin(result) { afterLogin(result) {
this.logging = false; this.logging = false;
const loginResult = result.data; const { token, userId } = result;
setToken(token);
this.$router.replace('/dashboard/workbench');
if (loginResult.code >= 0) { // this.setUser(user);
const { user, permissions, roles, routers } = loginResult.data; // this.setPermissions(permissions);
this.setUser(user); // this.setRoles(roles);
this.setPermissions(permissions); // setAuthorization({
this.setRoles(roles); // token: loginResult.data.token,
setAuthorization({ // expireAt: new Date(loginResult.data.expireAt),
token: loginResult.data.token, // });
expireAt: new Date(loginResult.data.expireAt), // // 获取路由配置
}); // loadRoutes(routers);
// 获取路由配置
loadRoutes(routers);
this.$router.push('/dashboard/workbench');
this.$message.success(loginResult.message, 2);
} else {
this.$message.error(loginResult.message, 2);
}
}, },
}, },
}; };
......
export default { export default {
messages: { messages: {
zh_CN: { zh_CN: {
appName: '基于Antd Vue v1.73 的前端小框架', appName: '基于Antd Vue v1.73 的前端小框架',
tabTitle: '账号密码登录', tabTitle: '账号密码登录',
idPlaceHolder: '请输入登录账号', idPlaceHolder: '请输入登录账号',
pwdPlaceHolder: '请输入登录密码', pwdPlaceHolder: '请输入登录密码',
autoLoginLink: '自动登录', autoLoginLink: '自动登录',
forgetPwdLink: '忘记密码', forgetPwdLink: '忘记密码',
loginButton: '登录', loginButton: '登录',
idNotBlankValider: '登录Id不能为空', idNotBlankValider: '登录Id不能为空',
pwdNotBlankValider: '登录密码不能为空', 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 { hasAuthority } from '@/utils/authorityUtil';
import {loginIgnore} from '@/router/index' import { loginIgnore } from '@/router/index';
import {checkAuthorization} from '@/utils/requestUtil' import { checkAuthorization } from '@/utils/requestUtil';
import NProgress from 'nprogress' import NProgress from 'nprogress';
NProgress.configure({ showSpinner: false }) NProgress.configure({ showSpinner: false });
/** /**
* 进度条开始 * 进度条开始
...@@ -12,12 +12,12 @@ NProgress.configure({ showSpinner: false }) ...@@ -12,12 +12,12 @@ NProgress.configure({ showSpinner: false })
* @param next * @param next
*/ */
const progressStart = (to, from, next) => { const progressStart = (to, from, next) => {
// start progress bar // start progress bar
if (!NProgress.isStarted()) { if (!NProgress.isStarted()) {
NProgress.start() NProgress.start();
} }
next() next();
} };
/** /**
* 登录守卫 * 登录守卫
...@@ -27,14 +27,14 @@ const progressStart = (to, from, next) => { ...@@ -27,14 +27,14 @@ const progressStart = (to, from, next) => {
* @param options * @param options
*/ */
const loginGuard = (to, from, next, options) => { const loginGuard = (to, from, next, options) => {
const {message} = options const { message } = options;
if (!loginIgnore.includes(to) && !checkAuthorization()) { if (!loginIgnore.includes(to) && !checkAuthorization()) {
message.warning('登录已失效,请重新登录') message.warning('登录已失效,请重新登录');
next({path: '/login'}) next({ path: '/login' });
} else { } else {
next() next();
} }
} };
/** /**
* 权限守卫 * 权限守卫
...@@ -44,17 +44,17 @@ const loginGuard = (to, from, next, options) => { ...@@ -44,17 +44,17 @@ const loginGuard = (to, from, next, options) => {
* @param options * @param options
*/ */
const authorityGuard = (to, from, next, options) => { const authorityGuard = (to, from, next, options) => {
const {store, message} = options const { store, message } = options;
const permissions = store.getters['accountModule/permissions'] const permissions = store.getters['accountModule/permissions'];
const roles = store.getters['accountModule/roles'] const roles = store.getters['accountModule/roles'];
if (!hasAuthority(to, permissions, roles)) { if (!hasAuthority(to, permissions, roles)) {
message.warning(`对不起,您无权访问页面: ${to.fullPath},请联系管理员`) message.warning(`对不起,您无权访问页面: ${to.fullPath},请联系管理员`);
next({path: '/403'}) next({ path: '/403' });
// NProgress.done() // NProgress.done()
} else { } else {
next() next();
} }
} };
/** /**
* 混合导航模式下一级菜单跳转重定向 * 混合导航模式下一级菜单跳转重定向
...@@ -65,27 +65,27 @@ const authorityGuard = (to, from, next, options) => { ...@@ -65,27 +65,27 @@ const authorityGuard = (to, from, next, options) => {
* @returns {*} * @returns {*}
*/ */
const redirectGuard = (to, from, next, options) => { const redirectGuard = (to, from, next, options) => {
const {store} = options const { store } = options;
const getFirstChild = (routes) => { const getFirstChild = routes => {
const route = routes[0] const route = routes[0];
if (!route.children || route.children.length === 0) { if (!route.children || route.children.length === 0) {
return route return route;
} }
return getFirstChild(route.children) return getFirstChild(route.children);
} };
if (store.state.settingModule.layout === 'mix') { if (store.state.settingModule.layout === 'mix') {
const firstMenu = store.getters['settingModule/firstMenu'] const firstMenu = store.getters['settingModule/firstMenu'];
if (firstMenu.find(item => item.fullPath === to.fullPath)) { if (firstMenu.find(item => item.fullPath === to.fullPath)) {
store.commit('settingModule/setActivatedFirst', to.fullPath) store.commit('settingModule/setActivatedFirst', to.fullPath);
const subMenu = store.getters['settingModule/subMenu'] const subMenu = store.getters['settingModule/subMenu'];
if (subMenu.length > 0) { if (subMenu.length > 0) {
const redirect = getFirstChild(subMenu) const redirect = getFirstChild(subMenu);
return next({path: redirect.fullPath}) return next({ path: redirect.fullPath });
} }
}
} }
} next();
next() };
}
/** /**
* 进度条结束 * 进度条结束
...@@ -94,11 +94,11 @@ const redirectGuard = (to, from, next, options) => { ...@@ -94,11 +94,11 @@ const redirectGuard = (to, from, next, options) => {
* @param options * @param options
*/ */
const progressDone = () => { const progressDone = () => {
// finish progress bar // finish progress bar
NProgress.done() NProgress.done();
} };
export default { export default {
beforeEach: [progressStart, loginGuard, authorityGuard, redirectGuard], beforeEach: [progressStart, loginGuard, authorityGuard, redirectGuard],
afterEach: [progressDone] 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 axios from 'axios';
import Cookie from 'js-cookie' import { notification } from 'ant-design-vue';
import md5 from 'crypto-js/md5';
import { langUtil } from '.';
// 跨域认证信息 header 名 // 跨域认证信息 header 名
const xsrfHeaderName = 'Authorization' const xsrfHeaderName = 'Authorization';
axios.defaults.timeout = 5000 axios.defaults.timeout = 5000;
axios.defaults.withCredentials= true axios.defaults.withCredentials = true;
axios.defaults.xsrfHeaderName= xsrfHeaderName axios.defaults.xsrfHeaderName = xsrfHeaderName;
axios.defaults.xsrfCookieName= 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 = { const AUTH_TYPE = {
BEARER: 'Bearer', BEARER: 'Bearer',
BASIC: 'basic', BASIC: 'basic',
AUTH1: 'auth1', AUTH1: 'auth1',
AUTH2: 'auth2', AUTH2: 'auth2',
} };
// http method // http method
const METHOD = { const METHOD = {
GET: 'get', GET: 'get',
POST: 'post', POST: 'post',
PUT: 'put', PUT: 'put',
DELETE: 'delete', DELETE: 'delete',
} };
/** /**
* axios请求 * axios请求
...@@ -34,142 +83,66 @@ const METHOD = { ...@@ -34,142 +83,66 @@ const METHOD = {
* @returns {Promise<AxiosResponse<T>>} * @returns {Promise<AxiosResponse<T>>}
*/ */
async function request(url, method, params, config) { async function request(url, method, params, config) {
switch (method) { switch (method) {
case METHOD.GET: case METHOD.GET:
return axios.get(url, {params, ...config}) return axios.get(url, { params, ...config });
case METHOD.POST: case METHOD.POST:
return axios.post(url, params, config) return axios.post(url, params, config);
case METHOD.PUT: case METHOD.PUT:
return axios.put(url, params, config) return axios.put(url, params, config);
case METHOD.DELETE: case METHOD.DELETE:
return axios.delete(url, {params, ...config}) return axios.delete(url, { params, ...config });
default: default:
return axios.get(url, {params, ...config}) return axios.get(url, { params, ...config });
} }
} }
/** /**
* 设置认证信息 * 解析 url 中的参数
* @param auth {Object} * @param url
* @param authType {AUTH_TYPE} 认证类型,默认:{AUTH_TYPE.BEARER} * @returns {Object}
*/ */
function setAuthorization(auth, authType = AUTH_TYPE.BEARER) { function parseUrlParams(url) {
switch (authType) { const params = {};
case AUTH_TYPE.BEARER: if (!url || url === '' || typeof url !== 'string') {
Cookie.set(xsrfHeaderName, 'Bearer ' + auth.token, {expires: auth.expireAt}) return params;
break }
case AUTH_TYPE.BASIC: const paramsStr = url.split('?')[1];
case AUTH_TYPE.AUTH1: if (!paramsStr) {
case AUTH_TYPE.AUTH2: return params;
default: }
break 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;
} }
/** const TOKEN_KEY = md5('TOKEN').toString();
* 移出认证信息 function getToken() {
* @param authType {AUTH_TYPE} 认证类型 return window.sessionStorage.getItem(TOKEN_KEY) ?? '';
*/
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
}
} }
/** function setToken(val) {
* 检查认证信息 window.sessionStorage.setItem(TOKEN_KEY, val);
* @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 clearToken() {
* 加载 axios 拦截器 window.sessionStorage.removeItem(TOKEN_KEY);
* @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 checkAuthorization() {
* 解析 url 中的参数 return !!getToken();
* @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
} }
export { export {
METHOD, METHOD,
AUTH_TYPE, AUTH_TYPE,
request, request,
setAuthorization, parseUrlParams,
removeAuthorization, loadResponseInterceptor,
checkAuthorization, setToken,
loadInterceptors, checkAuthorization,
parseUrlParams clearToken,
} };
...@@ -5,74 +5,74 @@ import { globalConfig, settingConfig } from '../config'; ...@@ -5,74 +5,74 @@ import { globalConfig, settingConfig } from '../config';
const theme = settingConfig.theme; const theme = settingConfig.theme;
function getThemeColors(color, $theme) { function getThemeColors(color, $theme) {
const _color = color || theme.color const _color = color || theme.color;
const mode = $theme || theme.mode const mode = $theme || theme.mode;
const replaceColors = getThemeToggleColors(_color, mode) const replaceColors = getThemeToggleColors(_color, mode);
const themeColors = [ const themeColors = [
...replaceColors.mainColors, ...replaceColors.mainColors,
...replaceColors.subColors, ...replaceColors.subColors,
...replaceColors.menuColors, ...replaceColors.menuColors,
...replaceColors.contentColors, ...replaceColors.contentColors,
...replaceColors.rgbColors, ...replaceColors.rgbColors,
...replaceColors.functionalColors.success, ...replaceColors.functionalColors.success,
...replaceColors.functionalColors.warning, ...replaceColors.functionalColors.warning,
...replaceColors.functionalColors.error, ...replaceColors.functionalColors.error,
] ];
return themeColors return themeColors;
} }
function changeThemeColor(newColor, $theme) { function changeThemeColor(newColor, $theme) {
let promise = client.changer.changeColor({newColors: getThemeColors(newColor, $theme)}) let promise = client.changer.changeColor({ newColors: getThemeColors(newColor, $theme) });
return promise return promise;
} }
function modifyVars(color) { function modifyVars(color) {
let _color = color || theme.color let _color = color || theme.color;
const palettes = getAntdColors(_color, theme.mode) const palettes = getAntdColors(_color, theme.mode);
const menuColors = getMenuColors(_color, theme.mode) const menuColors = getMenuColors(_color, theme.mode);
const {success, warning, error} = getFunctionalColors(theme.mode) const { success, warning, error } = getFunctionalColors(theme.mode);
const primary = palettes[5] const primary = palettes[5];
return { return {
'primary-color': primary, 'primary-color': primary,
'primary-1': palettes[0], 'primary-1': palettes[0],
'primary-2': palettes[1], 'primary-2': palettes[1],
'primary-3': palettes[2], 'primary-3': palettes[2],
'primary-4': palettes[3], 'primary-4': palettes[3],
'primary-5': palettes[4], 'primary-5': palettes[4],
'primary-6': palettes[5], 'primary-6': palettes[5],
'primary-7': palettes[6], 'primary-7': palettes[6],
'primary-8': palettes[7], 'primary-8': palettes[7],
'primary-9': palettes[8], 'primary-9': palettes[8],
'primary-10': palettes[9], 'primary-10': palettes[9],
'info-color': primary, 'info-color': primary,
'success-color': success[5], 'success-color': success[5],
'warning-color': warning[5], 'warning-color': warning[5],
'error-color': error[5], 'error-color': error[5],
'alert-info-bg-color': palettes[0], 'alert-info-bg-color': palettes[0],
'alert-info-border-color': palettes[2], 'alert-info-border-color': palettes[2],
'alert-success-bg-color': success[0], 'alert-success-bg-color': success[0],
'alert-success-border-color': success[2], 'alert-success-border-color': success[2],
'alert-warning-bg-color': warning[0], 'alert-warning-bg-color': warning[0],
'alert-warning-border-color': warning[2], 'alert-warning-border-color': warning[2],
'alert-error-bg-color': error[0], 'alert-error-bg-color': error[0],
'alert-error-border-color': error[2], 'alert-error-border-color': error[2],
'processing-color': primary, 'processing-color': primary,
'menu-dark-submenu-bg': menuColors[0], 'menu-dark-submenu-bg': menuColors[0],
'layout-header-background': menuColors[1], 'layout-header-background': menuColors[1],
'layout-trigger-background': menuColors[2], 'layout-trigger-background': menuColors[2],
'btn-danger-bg': error[4], 'btn-danger-bg': error[4],
'btn-danger-border': error[4], 'btn-danger-border': error[4],
...globalConfig.theme[theme.mode] ...globalConfig.theme[theme.mode],
} };
} }
function loadLocalTheme(localSetting) { function loadLocalTheme(localSetting) {
if (localSetting && localSetting.theme) { if (localSetting && localSetting.theme) {
let {color, mode} = localSetting.theme let { color, mode } = localSetting.theme;
color = color || theme.color color = color || theme.color;
mode = mode || theme.mode mode = mode || theme.mode;
changeThemeColor(color, mode) changeThemeColor(color, mode);
} }
} }
/** /**
...@@ -81,23 +81,17 @@ function loadLocalTheme(localSetting) { ...@@ -81,23 +81,17 @@ function loadLocalTheme(localSetting) {
* @returns {Object} * @returns {Object}
*/ */
function getLocalSetting(loadTheme) { function getLocalSetting(loadTheme) {
let localSetting = {} let localSetting = {};
try { try {
const localSettingStr = localStorage.getItem(process.env.VUE_APP_SETTING_KEY) const localSettingStr = localStorage.getItem(process.env.VUE_APP_SETTING_KEY) || '{}';
localSetting = JSON.parse(localSettingStr) localSetting = JSON.parse(localSettingStr);
} catch (e) { } catch (e) {
console.error(e) console.error(e);
} }
if (loadTheme) { if (loadTheme) {
loadLocalTheme(localSetting) loadLocalTheme(localSetting);
} }
return localSetting return localSetting;
} }
export { export { getThemeColors, changeThemeColor, modifyVars, loadLocalTheme, getLocalSetting };
getThemeColors,
changeThemeColor,
modifyVars,
loadLocalTheme,
getLocalSetting
}
...@@ -194,15 +194,17 @@ const assetsCDN = { ...@@ -194,15 +194,17 @@ const assetsCDN = {
module.exports = { module.exports = {
devServer: { devServer: {
// proxy: { proxy: {
// '/api': { //此处要与 /services/api.js 中的 API_PROXY_PREFIX 值保持一致 '/api': {
// target: process.env.VUE_APP_API_BASE_URL, //此处要与 /services/api.js 中的 API_PROXY_PREFIX 值保持一致
// changeOrigin: true, // target: process.env.VUE_APP_API_BASE_URL,
// pathRewrite: { target: 'http://platform.kuopu.net:9300',
// '^/api': '' changeOrigin: true,
// } // pathRewrite: {
// } // '^/api': ''
// } // }
},
},
}, },
pluginOptions: { 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