diff --git a/config/config.ts b/config/config.ts index fe69449135a90af52e61a8f5c4599acb43ea27d7..bfa47453ecab32f248f509255f6cd9230b4292a2 100644 --- a/config/config.ts +++ b/config/config.ts @@ -1,13 +1,11 @@ import { IConfig, IPlugin } from 'umi-types'; - -import defaultSettings from './defaultSettings'; -// https://umijs.org/config/ +import defaultSettings from './defaultSettings'; // https://umijs.org/config/ import slash from 'slash2'; import webpackPlugin from './plugin.config'; +import theme from './theme.config'; +const path = require('path'); -const { pwa, primaryColor } = defaultSettings; - -// preview.pro.ant.design only do not use in your production ; +const { pwa } = defaultSettings; // preview.pro.ant.design only do not use in your production ; // preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。 const { ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION } = process.env; @@ -91,15 +89,232 @@ export default { routes: [ { path: '/', - component: '../layouts/BasicLayout', - Routes: ['src/pages/Authorized'], - authority: ['admin', 'user'], + component: '../layouts/BlankLayout', routes: [ + { + path: '/404', + component: './404', + }, + { + path: '/user', + component: '../layouts/UserLayout', + routes: [ + { + path: '/user', + redirect: '/user/login', + }, + { + name: 'login', + path: '/user/login', + component: './user/login', + }, + ], + }, { path: '/', - name: 'welcome', - icon: 'smile', - component: './Welcome', + component: '../layouts/BasicLayout', + Routes: ['src/pages/Authorized'], + authority: ['user'], + routes: [ + { + path: '/', + redirect: '/dashboard/analysis', + }, + { + path: '/dashboard', + name: 'dashboard', + icon: 'dashboard', + routes: [ + { + name: 'analysis', + path: '/dashboard/analysis', + component: './dashboard/analysis', + }, + { + name: 'monitor', + path: '/dashboard/monitor', + component: './dashboard/monitor', + }, + { + name: 'workplace', + path: '/dashboard/workplace', + component: './dashboard/workplace', + }, + ], + }, + { + path: '/form', + icon: 'form', + name: 'form', + routes: [ + { + name: 'basic-form', + path: '/form/basic-form', + component: './form/basic-form', + }, + { + name: 'step-form', + path: '/form/step-form', + component: './form/step-form', + }, + { + name: 'advanced-form', + path: '/form/advanced-form', + component: './form/advanced-form', + }, + ], + }, + { + path: '/list', + icon: 'table', + name: 'list', + routes: [ + { + path: '/list/search', + name: 'search-list', + component: './list/search', + routes: [ + { + path: '/list/search', + redirect: '/list/search/articles', + }, + { + name: 'articles', + path: '/list/search/articles', + component: './list/search/articles', + }, + { + name: 'projects', + path: '/list/search/projects', + component: './list/search/projects', + }, + { + name: 'applications', + path: '/list/search/applications', + component: './list/search/applications', + }, + ], + }, + { + name: 'table-list', + path: '/list/table-list', + component: './list/table-list', + }, + { + name: 'basic-list', + path: '/list/basic-list', + component: './list/basic-list', + }, + { + name: 'card-list', + path: '/list/card-list', + component: './list/card-list', + }, + ], + }, + { + path: '/profile', + name: 'profile', + icon: 'profile', + routes: [ + { + name: 'basic', + path: '/profile/basic', + component: './profile/basic', + }, + { + name: 'advanced', + path: '/profile/advanced', + component: './profile/advanced', + }, + ], + }, + { + name: 'result', + icon: 'check-circle-o', + path: '/result', + routes: [ + { + name: 'success', + path: '/result/success', + component: './result/success', + }, + { + name: 'fail', + path: '/result/fail', + component: './result/fail', + }, + ], + }, + { + name: 'exception', + icon: 'warning', + path: '/exception', + routes: [ + { + name: '403', + path: '/exception/403', + component: './exception/403', + }, + { + name: '404', + path: '/exception/404', + component: './exception/404', + }, + { + name: '500', + path: '/exception/500', + component: './exception/500', + }, + ], + }, + { + name: 'account', + icon: 'user', + path: '/account', + routes: [ + { + name: 'center', + path: '/account/center', + component: './account/center', + }, + { + name: 'settings', + path: '/account/settings', + component: './account/settings', + }, + ], + }, + { + name: 'editor', + icon: 'highlight', + path: '/editor', + routes: [ + { + name: 'flow', + path: '/editor/flow', + component: './editor/flow', + }, + { + name: 'mind', + path: '/editor/mind', + component: './editor/mind', + }, + { + name: 'koni', + path: '/editor/koni', + component: './editor/koni', + }, + ], + }, + { + name: 'parameter', + icon: 'highlight', + path: '/parameter', + component: './system/parameter', + authority: ['user'], + }, + ], }, { component: './404', @@ -110,10 +325,9 @@ export default { component: './404', }, ], - // Theme for antd: https://ant.design/docs/react/customize-theme-cn - theme: { - 'primary-color': primaryColor, - }, + // Theme for antd + // https://ant.design/docs/react/customize-theme-cn + theme, define: { ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION || '', // preview.pro.ant.design only do not use in your production ; preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。 @@ -158,6 +372,16 @@ export default { basePath: '/', }, chainWebpack: webpackPlugin, + // 配置 webpack 的 resolve.alias 属性 默认src=>@ + alias: { + src: path.join(__dirname, '../src'), + components: path.join(__dirname, '../src', 'components'), + utils: path.join(__dirname, '../src', 'utils'), + assets: path.join(__dirname, '../src', 'assets'), + themes: path.join(__dirname, '../src', 'themes'), + config: path.join(__dirname, '../src', '../config'), + public: path.join(__dirname, '../public'), + }, /* proxy: { '/server/api/': { diff --git a/config/defaultSettings.ts b/config/defaultSettings.ts index 0f6d6fcb5b7e4d32e8a7dc876c0752f01e1062a7..1add9e2290488bd94ba42c3022309e51592543f5 100644 --- a/config/defaultSettings.ts +++ b/config/defaultSettings.ts @@ -57,9 +57,9 @@ export default { primaryColor: '#43cec4', layout: 'sidemenu', contentWidth: 'Fluid', - fixedHeader: false, + fixedHeader: true, autoHideHeader: false, - fixSiderbar: false, + fixSiderbar: true, colorWeak: false, menu: { locale: true, diff --git a/public/images/default-avatar.png b/public/images/default-avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..ff1cd0e12a41e82509f86eae05b854f54194bc0b Binary files /dev/null and b/public/images/default-avatar.png differ diff --git a/src/app.js b/src/app.js index ff52b98efd73c52e0845960b081e8b52932ced06..903106bc88ab508b633db50388b73e7a3b8a2916 100644 --- a/src/app.js +++ b/src/app.js @@ -1,6 +1,7 @@ export const dva = { config: { onError(e) { + console.error(e); e.preventDefault(); }, }, diff --git a/src/components/Authorized/Authorized.tsx b/src/components/Authorized/Authorized.tsx index 6f8702c1805d872254bdb49bd3d4078ac4971cb7..b5eff807d971975d5352ae39ee0477fb61b2ac24 100644 --- a/src/components/Authorized/Authorized.tsx +++ b/src/components/Authorized/Authorized.tsx @@ -20,7 +20,6 @@ const Authorized: React.FunctionComponent = ({ authority, noMatch = null, }) => { - console.log('noMatch1', noMatch); const childrenRender: React.ReactNode = typeof children === 'undefined' ? null : children; const dom = check(authority, childrenRender, noMatch); return <>{dom}; diff --git a/src/components/Authorized/CheckPermissions.tsx b/src/components/Authorized/CheckPermissions.tsx index e8795791eaa9858092cc85486aa73e964c41b07b..4afe7ad020958b959c36d7d2d553651c8b5ad441 100644 --- a/src/components/Authorized/CheckPermissions.tsx +++ b/src/components/Authorized/CheckPermissions.tsx @@ -24,10 +24,6 @@ const checkPermissions = ( target: T, Exception: K, ): T | K | React.ReactNode => { - console.log('authority:', authority); - console.log('currentAuthority:', currentAuthority); - console.log('target:', target); - console.log('noMatch2', Exception); // 没有判定权限.默认查看所有 // Retirement authority, return target; if (!authority) { diff --git a/src/components/Authorized/renderAuthorize.ts b/src/components/Authorized/renderAuthorize.ts index f12b443ae5d476e54a733b95a3118f859a978836..df008750168e2473f16c1cae5bc518b628186fc7 100644 --- a/src/components/Authorized/renderAuthorize.ts +++ b/src/components/Authorized/renderAuthorize.ts @@ -10,8 +10,6 @@ type CurrentAuthorityType = string | string[] | (() => typeof CURRENT); const renderAuthorize = (Authorized: T): ((currentAuthority: CurrentAuthorityType) => T) => ( currentAuthority: CurrentAuthorityType, ): T => { - console.log('currentAuthoritycurrentAuthority', currentAuthority); - if (currentAuthority) { if (typeof currentAuthority === 'function') { CURRENT = currentAuthority(); @@ -25,7 +23,6 @@ const renderAuthorize = (Authorized: T): ((currentAuthority: CurrentAuthority } else { CURRENT = 'NULL'; } - console.log('CURRENT', CURRENT); return Authorized; }; diff --git a/src/components/GlobalHeader/AvatarDropdown.tsx b/src/components/GlobalHeader/AvatarDropdown.tsx index ccdb7494f4497fe5020a2c0eb7fb34aec76ddc9a..865f4bff9b313c2c268b0a9c5fe96e0a0ccf1530 100644 --- a/src/components/GlobalHeader/AvatarDropdown.tsx +++ b/src/components/GlobalHeader/AvatarDropdown.tsx @@ -32,13 +32,17 @@ class AvatarDropdown extends React.Component { router.push(`/account/${key}`); }; + getUserName = (userName: string) => { + return userName.length > 10 ? `${userName.substr(0, 10)}...` : userName; + }; + render(): React.ReactNode { const { currentUser = {}, menu } = this.props; if (!menu) { return ( - {currentUser.name} + {this.getUserName(currentUser.userName || '')} ); } @@ -60,11 +64,14 @@ class AvatarDropdown extends React.Component { ); - return currentUser && currentUser.name ? ( + console.log(currentUser.avatar); + return currentUser && currentUser.userName ? ( - {currentUser.name} + + {this.getUserName(currentUser.userName || '')} + ) : ( diff --git a/src/components/GlobalHeader/RightContent.tsx b/src/components/GlobalHeader/RightContent.tsx index 9b0d933940b87ce3e4fde9f16544d2eae0883b8c..08402c32d7f86fc8b2fbdf61b79bfae2882c08e6 100644 --- a/src/components/GlobalHeader/RightContent.tsx +++ b/src/components/GlobalHeader/RightContent.tsx @@ -1,5 +1,5 @@ import { ConnectProps, ConnectState } from '@/models/connect'; -import { Icon, Tooltip } from 'antd'; +import { Icon, Tooltip, message } from 'antd'; import Avatar from './AvatarDropdown'; import HeaderSearch from '../HeaderSearch'; import React from 'react'; @@ -16,6 +16,11 @@ export interface GlobalHeaderRightProps extends ConnectProps { layout: 'sidemenu' | 'topmenu'; } +const goHelpPage = (e: React.MouseEvent) => { + e.preventDefault(); + message.info('go go go! help page.'); +}; + const GlobalHeaderRight: React.SFC = props => { const { theme, layout } = props; let className = styles.right; @@ -26,40 +31,12 @@ const GlobalHeaderRight: React.SFC = props => { return (
- { - console.log('input', value); - }} - onPressEnter={value => { - console.log('enter', value); - }} - /> - + diff --git a/src/config.js b/src/config.js index ea626cb3cc6c59b7e95bd6eeaeec8fc6cf8d914d..147283e8a8aa67701af39318d7ab0ef8ceee9e4d 100644 --- a/src/config.js +++ b/src/config.js @@ -1,16 +1,15 @@ -// import store from './utils/store'; - export default { - baseUrl: 'http://platform.kuopu.net:9080', storeNameSpace: 'kim', - headers: () => ({ - Authorization: - 'eyJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjMzLCJ1c24iOiLmrKfpmLPljZrlrofmrKfpmLPljZrlrofmrKfpmLPljZrlrofmrKfpmLPljZrlrofmrKfpmLPljZrlrofmrKfpmLPljZrlrofmrKfpmLPljZrlrociLCJzdGEiOjE1NjE2MDE3ODA3NDksImxpZCI6Im91eWFuZ2JveXUifQ.PY2oCcc9ESRVw2UmAnvZddgrl6Ycn2462L7xvI4FCLY', - }), - resCodeKey: 'code', // 后台正常返回错误编码 - resMessageKey: 'message', // 后台正常返回错误编码 - successCode: 'sys.success', // 后台正常返回错误编码 - isThrowError: true, // 默认为true + request: { + apiPrefix: '', + baseUrl: 'http://platform.kuopu.net:9080', + resCodeKey: 'code', // 后台正常返回错误编码 + resMessageKey: 'message', // 后台正常返回错误编码 + successCode: 'sys.success', // 后台正常返回错误编码 + isThrowError: true, // 默认为true + }, copyright: `${new Date().getFullYear()} KIM3.0技术中台部出品`, homePage: '/dashboard/analysis', + fileServerUrl: 'http://platform.kuopu.net:9008', + defaultAvatar: '/images/default-avatar.png', }; diff --git a/src/global.less b/src/global.less index ad04cbd76ec42d019939049c4b7fdf07579cff19..4def5d37373670199baba52c5b7e44d018131664 100644 --- a/src/global.less +++ b/src/global.less @@ -1,4 +1,4 @@ -@import '~antd/es/style/themes/default.less'; +@import '~@/themes/vars.less'; html, body, @@ -49,6 +49,40 @@ ol { // 覆盖antd design pro样式 :global { + ::-webkit-scrollbar { + width: 6px; + height: 6px; + margin-right: 10px; + /*background-color: #ddd;*/ + } + + /*滑块*/ + ::-webkit-scrollbar-thumb { + //background-color: #43cec4; + width: 6px; + height: 6px; + border-radius: 10px; + cursor: default; + margin-left: -10px; + background-color: rgba(170, 170, 170, 0.8); + transition: background-color 0.2s linear, width 0.2s ease-in-out; + -webkit-transition: background-color 0.2s linear, width 0.2s ease-in-out; + } + + ::-webkit-scrollbar-thumb:hover { + //background-color: #aaa; + background-color: #aaa; + } + + /*滑道*/ + ::-webkit-scrollbar-track { + margin-right: 20px; + // box-shadow: inset 0 0 6px #333; + background-color: rgba(201, 201, 201, 0.8); + border-radius: 10px; + width: 6px; + } + .kim-layout { .ant-pro-sider-menu-logo { padding-left: 8px; @@ -60,5 +94,8 @@ ol { .ant-pro-global-header { // background: #43cec4; } + .ant-pro-basicLayout-content { + margin: @space-sm; + } } } diff --git a/src/layouts/BasicLayout.tsx b/src/layouts/BasicLayout.tsx index a146e297716aec188b38a64062c6374b9aeffa35..ac74446bd752dc60162eca2fa9d0ea6f02440acb 100644 --- a/src/layouts/BasicLayout.tsx +++ b/src/layouts/BasicLayout.tsx @@ -10,7 +10,7 @@ import ProLayout, { Settings, SettingDrawer, } from '@ant-design/pro-layout'; -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import Authorized from '@/utils/Authorized'; import Link from 'umi/link'; import router from 'umi/router'; @@ -21,7 +21,7 @@ import { formatMessage } from 'umi-plugin-react/locale'; import { isAntDesignPro } from '@/utils/utils'; import { message } from 'antd'; import store from '@/utils/store'; -import user from 'mock/user'; +import { async } from 'q'; export interface BasicLayoutProps extends ProLayoutProps, Omit { breadcrumbNameMap: { [path: string]: MenuDataItem; @@ -73,7 +73,10 @@ const footerRender: BasicLayoutProps['footerRender'] = (_, defaultDom) => { }; const loadInitData = (dispatch: Dispatch) => { - Promise.all([dispatch({ type: 'public/getUserInfo' }), dispatch({ type: 'public/getUserInfo' })]); + return Promise.all([ + dispatch({ type: 'user/getCurrent' }), + dispatch({ type: 'settings/getSettings' }), + ]); }; const BasicLayout: React.FC = props => { @@ -81,19 +84,19 @@ const BasicLayout: React.FC = props => { /** * constructor */ - const [loaded, setLoaded] = useState(false); - useState(() => { + + useEffect(() => { if (dispatch) { // 查看当前用户是否在登录状态 dispatch({ - type: 'user/checkUserLoginStatus', - }).then(({ code, data = false }: { code: string; data: boolean }) => { - setLoaded(true); + type: 'user/checkLoginStatus', + }).then(async ({ code, data = false }: { code: string; data: boolean }) => { if (code === 'sys.success') { // 登录成功 if (data) { - loadInitData(dispatch); + await loadInitData(dispatch); + setLoaded(true); } else if (store.get('userId')) { store.set('token', ''); store.set('userId', ''); @@ -106,12 +109,8 @@ const BasicLayout: React.FC = props => { } } }); - - // dispatch({ - // type: 'settings/getSetting', - // }); } - }); + }, []); /** * init variables */ diff --git a/src/models/global.ts b/src/models/global.ts index eec3a8045f58d59d2842bcb2bc527e78bdc50169..77d9c6740f24a3784a97342e5b511709ba7a7860 100644 --- a/src/models/global.ts +++ b/src/models/global.ts @@ -1,9 +1,14 @@ import { Reducer } from 'redux'; -import { Subscription } from 'dva'; - import { Effect } from './connect.d'; +import { Subscription } from 'dva'; +import { routerRedux } from 'dva/router'; +import store from '@/utils/store'; +import { getPageQuery } from '@/utils'; +import { setAuthority } from '@/utils/authority'; +import { reloadAuthorized } from '@/utils/Authorized'; import { NoticeIconData } from '@/components/NoticeIcon'; import { queryNotices } from '@/services/user'; +import { login, logout } from '@/services/global'; export interface NoticeItem extends NoticeIconData { id: string; @@ -23,12 +28,13 @@ export interface GlobalModelType { fetchNotices: Effect; clearNotices: Effect; changeNoticeReadState: Effect; - checkUserLoginStatus: Effect; + login: Effect; }; reducers: { changeLayoutCollapsed: Reducer; saveNotices: Reducer; saveClearedNotices: Reducer; + changeLoginStatus: Reducer; }; subscriptions: { setup: Subscription }; } @@ -42,6 +48,41 @@ const GlobalModel: GlobalModelType = { }, effects: { + *login({ payload }, { call, put }) { + const { code, data } = yield call(login, payload); + if (code === 'sys.success') { + yield put({ + type: 'changeLoginStatus', + payload: {}, + }); + reloadAuthorized(); + const { token, userId } = data; + store.set('token', token); + store.set('userId', userId); + + const urlParams = new URL(window.location.href); + const params = getPageQuery(); + // 是否需要重定向 + let { redirect } = params; + if (redirect) { + const redirectUrlParams = new URL(redirect); + // origin相同 + if (redirectUrlParams.origin === urlParams.origin) { + redirect = redirect.substr(urlParams.origin.length); + if (redirect.match(/^\/.*#/)) { + redirect = redirect.substr(redirect.indexOf('#') + 1); + } + } else { + window.location.href = redirect; + return; + } + } + // else { + // redirect = config.homePage; + // } + yield put(routerRedux.replace(redirect || '/')); + } + }, *fetchNotices(_, { call, put, select }) { const data = yield call(queryNotices); yield put({ @@ -103,6 +144,12 @@ const GlobalModel: GlobalModelType = { }, reducers: { + changeLoginStatus(state, { payload }) { + setAuthority('user'); + return { + ...state, + }; + }, changeLayoutCollapsed(state = { notices: [], collapsed: true }, { payload }): GlobalModelState { return { ...state, diff --git a/src/models/setting.ts b/src/models/setting.ts index 860b9dd625d162953e508870c6affe2771a2e789..c71ad394f01af2fbde44e7027714518ac5e55283 100644 --- a/src/models/setting.ts +++ b/src/models/setting.ts @@ -2,11 +2,17 @@ import { Reducer } from 'redux'; import { message } from 'antd'; import defaultSettings, { DefaultSettings } from '../../config/defaultSettings'; import themeColorClient from '../components/SettingDrawer/themeColorClient'; +import { getCurrentUserSetting } from '@/services/user'; +import { Effect } from 'dva'; export interface SettingModelType { namespace: 'settings'; state: DefaultSettings; + effects: { + getSettings: Effect; + }; reducers: { + saveSettings: Reducer; getSetting: Reducer; changeSetting: Reducer; }; @@ -95,7 +101,44 @@ const updateColorWeak: (colorWeak: boolean) => void = colorWeak => { const SettingModel: SettingModelType = { namespace: 'settings', state: defaultSettings, + effects: { + *getSettings({ payload }, { call, put }) { + const { data, code } = yield call(getCurrentUserSetting, payload); + let settings = defaultSettings; + if (code === 'sys.success' && data) { + const { + appStyle, + appTheme, + navigatorStyle, + contentWidth, + fixedHead, + fixedSide, + hideHead, + } = data; + settings = { + ...settings, + navTheme: appStyle === 0 ? 'light' : 'dark', + primaryColor: appTheme, + layout: navigatorStyle === 0 ? 'sidemenu' : 'topmenu', + contentWidth: contentWidth === 0 ? 'Fluid' : 'Fixed', + fixedHeader: fixedHead, + autoHideHeader: hideHead, + fixSiderbar: fixedSide, + }; + } + yield put({ + type: 'saveSettings', + payload: settings, + }); + }, + }, reducers: { + saveSettings(state, { payload }) { + return { + ...state, + ...payload, + }; + }, getSetting(state = defaultSettings) { const setting: Partial = {}; const urlParams = new URL(window.location.href); diff --git a/src/models/user.ts b/src/models/user.ts index f337663390edfe1ac775c2738202de4f1ae386b6..f528b98da8f0a67dcb33ba3bf2038e9f92417788 100644 --- a/src/models/user.ts +++ b/src/models/user.ts @@ -1,21 +1,78 @@ -import { queryCurrent, query as queryUsers, checkUserLoginStatus } from '@/services/user'; +import { checkUserLoginStatus, getCurrentUserInfo } from '@/services/user'; import { Effect } from 'dva'; import { Reducer } from 'redux'; +import config from '@/config'; -export interface CurrentUser { +const { fileServerUrl, defaultAvatar } = config; + +export interface Role extends BaseModel { + roleId?: number; + roleName?: string; + roleCode?: string; + remark?: string; + roleState?: number; +} + +export interface Menu extends BaseModel { + menuId?: number; + pMenuId?: number; + menuName?: string; + menuType?: number; + menuUrl?: string; + menuIcon?: string; + viewIndex?: number; + menuState?: number; +} + +export interface Component extends BaseModel { + componentId?: number; + componentName?: string; + componentCode?: string; + menuId?: number; + componentType?: number; + componentState?: number; +} + +export interface CurrentUser extends BaseModel { + userId?: string; + loginId?: string; + userPassword?: string; + userName?: string; + effDate?: string; + expDate?: string; + userTitle?: string; + mobilePhone?: string; + fixedPhone?: string; + userEmail?: string; + userState?: string; + lockState?: string; + userPortrait?: string; avatar?: string; - name?: string; - title?: string; - group?: string; - signature?: string; - tags?: { - key: string; - label: string; - }[]; + enabled?: string; + accountNonExpired?: string; + credentialsNonExpired?: string; + accountNonLocked?: string; + roleList?: Role[]; + menuList?: Menu[]; + componentList?: Component[]; + allCount?: number; unreadCount?: number; } +export interface UserSetting { + enabled?: number; + appTheme?: string; + contentWidth?: number; + fixedHead?: number; + fixedSide?: number; + hideHead?: number; + navigatorStyle?: number; + settingId?: number; + userId?: number; + userSetting?: UserSetting; +} + export interface UserModelState { currentUser?: CurrentUser; } @@ -24,9 +81,8 @@ export interface UserModelType { namespace: 'user'; state: UserModelState; effects: { - fetch: Effect; - fetchCurrent: Effect; - checkUserLoginStatus: Effect; + getCurrent: Effect; + checkLoginStatus: Effect; }; reducers: { saveCurrentUser: Reducer; @@ -42,31 +98,29 @@ const UserModel: UserModelType = { }, effects: { - *fetch(_, { call, put }) { - const response = yield call(queryUsers); - yield put({ - type: 'save', - payload: response, - }); + *checkLoginStatus({ payload }, { call }) { + return yield call(checkUserLoginStatus, payload); }, - *fetchCurrent(_, { call, put }) { - const response = yield call(queryCurrent); + *getCurrent({ payload }, { call, put }) { + const { data, code } = yield call(getCurrentUserInfo, payload); yield put({ type: 'saveCurrentUser', - payload: response, + payload: { ...data }, }); - }, - *checkUserLoginStatus({ payload }, { call }) { - const res = yield call(checkUserLoginStatus, payload); - return res; + const result = code === 'sys.success'; + return result; }, }, reducers: { - saveCurrentUser(state, action) { + saveCurrentUser(state, { payload }) { + const { userPortrait } = payload; return { ...state, - currentUser: action.payload || {}, + currentUser: { + avatar: userPortrait ? `${fileServerUrl}/${userPortrait}` : defaultAvatar, + ...(payload || {}), + }, }; }, changeNotifyCount( @@ -79,7 +133,7 @@ const UserModel: UserModelType = { ...state, currentUser: { ...state.currentUser, - notifyCount: action.payload.totalCount, + allCount: action.payload.totalCount, unreadCount: action.payload.unreadCount, }, }; diff --git a/src/pages/Authorized.tsx b/src/pages/Authorized.tsx index 2ed9838078e1363385e7c02ce9cb7c8d216149e1..23ef95f1c51d9dee36d0ceac3c3324865d8fce08 100644 --- a/src/pages/Authorized.tsx +++ b/src/pages/Authorized.tsx @@ -14,11 +14,6 @@ const getRouteAuthority = (path: string, routeData: Route[]) => { routeData.forEach(route => { // match prefix if (pathToRegexp(`${route.path}(.*)`).test(path)) { - console.log('----------------------'); - console.log('route.path:', route.path); - console.log('path:', path); - console.log('route.authority:', route.authority); - authorities = route.authority || authorities; // 官方代码好像有问题https://github.com/ant-design/ant-design-pro/commit/4a10734dcf858c6363af719a5886a24ec1115b33#diff-2041540b332693486a24a543b6ba0cc8 // // exact match diff --git a/src/pages/user/login/index.js b/src/pages/user/login/index.js index 24e5d3477aa8c88503ae155eecd44f154a74a7f0..e5e45b774494c77880b734fd94800f69a101a20d 100644 --- a/src/pages/user/login/index.js +++ b/src/pages/user/login/index.js @@ -27,7 +27,7 @@ class Login extends React.Component { const { username, password } = this.state; const { dispatch } = this.props; dispatch({ - type: 'userLogin/login', + type: 'global/login', payload: { userName: username, password }, }); }; diff --git a/src/pages/user/login/models/index.js b/src/pages/user/login/models/index.js deleted file mode 100644 index 37dd0df48a9c259e04f8d3d1af5c35ec93902e1e..0000000000000000000000000000000000000000 --- a/src/pages/user/login/models/index.js +++ /dev/null @@ -1,61 +0,0 @@ -import { routerRedux } from 'dva/router'; -import { login } from '../services'; -import store from '@/utils/store'; -import { getPageQuery } from '@/utils'; -import config from '@/config'; -import { setAuthority } from '@/utils/authority'; -import { reloadAuthorized } from '@/utils/Authorized'; - -const initData = {}; -export default { - namespace: 'userLogin', - state: { - ...initData, - }, - effects: { - *login({ payload }, { call, put }) { - const { code, data } = yield call(login, payload); - if (code === 'sys.success') { - yield put({ - type: 'changeLoginStatus', - payload: {}, - }); - reloadAuthorized(); - const { token, userId } = data; - store.set('token', token); - store.set('userId', userId); - - const urlParams = new URL(window.location.href); - const params = getPageQuery(); - // 是否需要重定向 - let { redirect } = params; - if (redirect) { - const redirectUrlParams = new URL(redirect); - // origin相同 - if (redirectUrlParams.origin === urlParams.origin) { - redirect = redirect.substr(urlParams.origin.length); - if (redirect.match(/^\/.*#/)) { - redirect = redirect.substr(redirect.indexOf('#') + 1); - } - } else { - window.location.href = redirect; - return; - } - } - // else { - // redirect = config.homePage; - // } - yield put(routerRedux.replace(redirect || '/')); - } - }, - }, - reducers: { - clearData: () => ({ ...initData }), - changeLoginStatus(state, { payload }) { - setAuthority('user'); - return { - ...state, - }; - }, - }, -}; diff --git a/src/pages/user/login/services/index.js b/src/pages/user/login/services/index.js deleted file mode 100644 index 16a6c6c4aee557bebde86ffd66d5649324398077..0000000000000000000000000000000000000000 --- a/src/pages/user/login/services/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import { post } from '@/utils/request'; - -export const login = data => post('/api/v1/login', data); diff --git a/src/services/global.ts b/src/services/global.ts new file mode 100644 index 0000000000000000000000000000000000000000..f414a6db83cdc2b662b0704282a2875e8c9d0f9e --- /dev/null +++ b/src/services/global.ts @@ -0,0 +1,16 @@ +import { get, post, put } from '@/utils/request'; +/** + * 登录 + * @param data + */ +export const login = data => post('/api/v1/login', data); +/** + * 登出 + */ +export const logout = () => put('/api/v1/logout'); +/** + * 获取静态数据数据 + * @param data + */ +export const getStaticData = data => + get('/api/v1/params/businesses/paramList', { ...data, paramLocale: 'zh_CN' }); diff --git a/src/services/user.ts b/src/services/user.ts index f9661f12ea0efe2c5928190709f28e07168df624..03243f5266e0845d231b81d016d5ff6b63afdef4 100644 --- a/src/services/user.ts +++ b/src/services/user.ts @@ -15,4 +15,12 @@ export async function queryNotices(): Promise { /** * 查看是否已经登录 */ -export const checkUserLoginStatus = () => get(`/api/v1/login/status`); +export const checkUserLoginStatus = async () => get(`/api/v1/login/status`); +/** + * 查看当前用户信息 + */ +export const getCurrentUserInfo = async () => get(`/api/v1/detail`); +/** + * 获取用户配置信息 + */ +export const getCurrentUserSetting = async () => get(`/api/v1/profile/settings`); diff --git a/src/typings.d.ts b/src/typings.d.ts index 379c06998b470be521f38eb6acc4598a0134f43c..bd7bf72f847815e371b881bd754cde80bb802545 100644 --- a/src/typings.d.ts +++ b/src/typings.d.ts @@ -32,3 +32,10 @@ declare let ga: Function; // preview.pro.ant.design only do not use in your production ; // preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。 declare let ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: 'site' | undefined; + +declare interface BaseModel { + creatorId?: number; + createdDate?: string; + editorId?: string; + editDate?: number; +} diff --git a/src/utils/authority.ts b/src/utils/authority.ts index 30931bc042f03bc9e762291bf9989e40361ee21a..35c1f38643726afed327bb44f0f94a1c36255cc4 100644 --- a/src/utils/authority.ts +++ b/src/utils/authority.ts @@ -15,10 +15,6 @@ export function getAuthority(str?: string): string | string[] { if (typeof authority === 'string') { return [authority]; } - console.log( - 'ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION', - ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION, - ); // preview.pro.ant.design only do not use in your production. // preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。 if (!authority && ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site') { diff --git a/src/utils/kim-request.js b/src/utils/kim-request.js index 5f24d89880c8b084df6af96b42b37dc94b9c1cf8..63f00fe125a8117f0334f3518e793f9099758570 100644 --- a/src/utils/kim-request.js +++ b/src/utils/kim-request.js @@ -1,4 +1,5 @@ import axios from 'axios'; +import { string } from 'prop-types'; class HttpRequest { constructor(options) { @@ -7,6 +8,12 @@ class HttpRequest { } getInsideConfig() { + let headers = {}; + if (this.options.headers instanceof Function) { + headers = this.options.headers(); + } else { + headers = { ...this.options.headers }; + } const config = { baseURL: this.options.baseUrl, // baseURL timeout: 10000, @@ -17,7 +24,7 @@ class HttpRequest { 'Content-Type': 'application/json', Accept: 'application/json', 'X-Requested-With': 'XMLHttpRequest', - ...this.options.headers, + ...headers, }, }; return config; diff --git a/src/utils/request.js b/src/utils/request.js index 779275c01b1030b9310368cdabb72c43d8baa76e..2fce439caf0b370f49b4a33bf7bb7f21ee17b48a 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -1,6 +1,7 @@ import { notification } from 'antd'; import HttpRequest from './kim-request'; import config from '@/config'; +import store from '@/utils/store'; /** * todo 还需处理国际化 @@ -24,13 +25,15 @@ const codeMessage = { 504: '网关超时。', }; const { - baseUrl, - apiPrefix, - headers, - resCodeKey, - resMessageKey, - successCode, - isThrowError = true, + request: { + baseUrl, + apiPrefix, + resCodeKey, + resMessageKey, + successCode, + isThrowError = true, + redirectFunc, + }, } = config; /** @@ -48,9 +51,13 @@ const mergeApi = (url, more) => { return url; }; +const headers = () => ({ + Authorization: store.get('token'), +}); + const axios = new HttpRequest({ baseUrl, - headers: headers() || {}, + headers: headers || {}, }); /**