From 02708f8a29b5e5fd43c0a516e2019362062969cb Mon Sep 17 00:00:00 2001 From: duanledexianxianxian Date: Mon, 1 Jul 2019 01:44:27 +0800 Subject: [PATCH] sync code --- config/config.ts | 256 ++++++++++++++++-- config/defaultSettings.ts | 4 +- public/images/default-avatar.png | Bin 0 -> 29718 bytes src/app.js | 1 + src/components/Authorized/Authorized.tsx | 1 - .../Authorized/CheckPermissions.tsx | 4 - src/components/Authorized/renderAuthorize.ts | 3 - .../GlobalHeader/AvatarDropdown.tsx | 13 +- src/components/GlobalHeader/RightContent.tsx | 37 +-- src/config.js | 21 +- src/global.less | 39 ++- src/layouts/BasicLayout.tsx | 27 +- src/models/global.ts | 53 +++- src/models/setting.ts | 43 +++ src/models/user.ts | 112 ++++++-- src/pages/Authorized.tsx | 5 - src/pages/user/login/index.js | 2 +- src/pages/user/login/models/index.js | 61 ----- src/pages/user/login/services/index.js | 3 - src/services/global.ts | 16 ++ src/services/user.ts | 10 +- src/typings.d.ts | 7 + src/utils/authority.ts | 4 - src/utils/kim-request.js | 9 +- src/utils/request.js | 23 +- 25 files changed, 553 insertions(+), 201 deletions(-) create mode 100644 public/images/default-avatar.png delete mode 100644 src/pages/user/login/models/index.js delete mode 100644 src/pages/user/login/services/index.js create mode 100644 src/services/global.ts diff --git a/config/config.ts b/config/config.ts index fe694491..bfa47453 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 0f6d6fcb..1add9e22 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 GIT binary patch literal 29718 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

!cHx>5>c1(!}(b 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 literal 0 HcmV?d00001 diff --git a/src/app.js b/src/app.js index ff52b98e..903106bc 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 6f8702c1..b5eff807 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 e8795791..4afe7ad0 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 f12b443a..df008750 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 ccdb7494..865f4bff 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 9b0d9339..08402c32 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 ea626cb3..147283e8 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 ad04cbd7..4def5d37 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 a146e297..ac74446b 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 eec3a804..77d9c674 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 860b9dd6..c71ad394 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 f3376633..f528b98d 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 2ed98380..23ef95f1 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 24e5d347..e5e45b77 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 37dd0df4..00000000 --- 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 16a6c6c4..00000000 --- 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 00000000..f414a6db --- /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 f9661f12..03243f52 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 379c0699..bd7bf72f 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 30931bc0..35c1f386 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 5f24d898..63f00fe1 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 779275c0..2fce439c 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 || {}, }); /** -- GitLab