fix: 修复登陆的 bug

test
chibing.fy 6 years ago
commit af7a9c2d8c

@ -22,6 +22,8 @@ export function showMessage(message: string, type?: MSG_TYPE): ShowMessageAction
return result
}
export { MSG_TYPE } from 'components/common/Message'
export interface ShowMessageAction {
type: SHOW_MESSAGE
payload: {

@ -1,5 +1,5 @@
import React, { useState } from 'react'
import { useDispatch } from 'react-redux'
import { useDispatch, useSelector } from 'react-redux'
import config from '../../config'
import { Button, createStyles, makeStyles, List, ListItem, InputLabel, Input, FormControl, InputAdornment, IconButton, Paper } from '@material-ui/core'
import Logo from 'components/layout/Logo'
@ -11,9 +11,10 @@ import Visibility from '@material-ui/icons/Visibility'
import VisibilityOff from '@material-ui/icons/VisibilityOff'
import Refresh from '@material-ui/icons/Refresh'
import { login } from 'actions/account'
import { showMessage } from 'actions/common'
import { MSG_TYPE } from '../common/Message'
import URI from 'urijs'
import { showMessage, MSG_TYPE } from 'actions/common'
import { push } from 'connected-react-router'
import { getRouter } from 'selectors/router'
const { serve } = config
@ -35,6 +36,9 @@ const useStyles = makeStyles(() => createStyles({
display: 'flex',
justifyContent: 'space-between',
},
captchaWrapper: {
cursor: 'pointer',
},
captcha: {
width: 108,
height: 36,
@ -56,20 +60,29 @@ export default function LoginForm() {
const [bg] = useState(getBGImageUrl())
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [captchaId, setCaptchaId] = useState(0)
const [captchaId, setCaptchaId] = useState(Date.now())
const [captcha, setCaptcha] = useState('')
const [showPassword, setShowPassword] = useState(false)
const classes = useStyles()
const dispatch = useDispatch()
const router = useSelector(getRouter)
const { pathname, hash, search } = router.location
const handleSubmit = (e?: any) => {
e && e.preventDefault()
if (!email || !password || !captcha) {
dispatch(showMessage(`请输入账号、密码、验证码`, MSG_TYPE.WARNING))
} else {
dispatch(login({ email, password, captcha }, () => {
window.location.href = '/'
}))
dispatch(
login({ email, password, captcha }, () => {
const uri = URI(pathname + hash + search)
const original = uri.search(true).original
if (original) {
dispatch(push(decodeURIComponent(original)))
} else {
dispatch(push('/'))
}
})
)
}
}
@ -128,7 +141,7 @@ export default function LoginForm() {
tabIndex={2}
name="captcha"
value={captcha}
autoComplete="new-password"
autoComplete="off"
onKeyDown={e => e.keyCode === 13 && handleSubmit()}
onChange={e => setCaptcha(e.target.value)}
endAdornment={
@ -141,9 +154,9 @@ export default function LoginForm() {
/>
</FormControl>
</ListItem>
<ListItem className={classes.ctl} onClick={() => setCaptchaId(Date.now())}>
<div>
<img src={`${serve}/captcha?t=${captchaId || ''}`} className={classes.captcha} alt="captcha" />
<ListItem className={classes.ctl}>
<div className={classes.captchaWrapper} onClick={() => setCaptchaId(Date.now())}>
<img src={`${serve}/captcha?t=${captchaId}`} className={classes.captcha} alt="captcha" />
<Refresh />
</div>
<div className={classes.buttonWrapper}>

@ -41,7 +41,7 @@ type InterfaceSummaryState = {
}
class InterfaceSummary extends Component<InterfaceSummaryProps, InterfaceSummaryState> {
static contextTypes = {
onAddForeignRoomCase: PropTypes.func.isRequired,
// onAddForeignRoomCase: PropTypes.func.isRequired,
onDeleteInterface: PropTypes.func.isRequired,
}
constructor(props: any) {
@ -197,17 +197,17 @@ class InterfaceSummary extends Component<InterfaceSummaryProps, InterfaceSummary
}
}
handleUpdate = () => { /** empty */ }
createCase = (e: any, repositoryId: any, interfaceId: any, name: any) => {
e.preventDefault()
this.setState({ name })
const { onAddForeignRoomCase } = this.context
onAddForeignRoomCase({
id: repositoryId,
itf: interfaceId,
name,
})
// itf.repositoryId
}
// createCase = (e: any, repositoryId: any, interfaceId: any, name: any) => {
// e.preventDefault()
// this.setState({ name })
// const { onAddForeignRoomCase } = this.context
// onAddForeignRoomCase({
// id: repositoryId,
// itf: interfaceId,
// name,
// })
// // itf.repositoryId
// }
}
const mapStateToProps = (state: RootState) => ({
room: state.foreign,

@ -1,17 +1,36 @@
import { takeLatest } from 'redux-saga/effects'
import start from './start'
import handleLocation from './handleLocation'
import { createBrowserHistory as createHistory, History } from 'history'
import {
createStore,
applyMiddleware,
combineReducers,
compose,
Store
} from 'redux'
import {
routerMiddleware as createRouterMiddleware,
connectRouter
} from 'connected-react-router'
import loggerMiddleware from './loggerMiddleware'
import createSagaMiddleware from 'redux-saga'
import URI from 'urijs'
const _relatives: any = []
const _reducers: any = {} // { id/key: reducer }
const _prefilters: any[] = []
const _sagas: any = {} // { pattern: [sagas] }
const _listeners: any = {} // { pathname: [listeners] }
let _routes: any
// let _routes: any
const Family = {
store: null,
history: null,
const Family: {
store?: Store;
history?: History;
[k: string]: any;
} = {
store: undefined,
history: undefined,
addRelative(relative: any) {
_relatives.push(relative)
return this
@ -25,9 +44,13 @@ const Family = {
return this
},
addReducers(map: any) {
if (!map) { return this }
if (!map) {
return this
}
// tslint:disable-next-line: forin
for (const id in map) { _reducers[id] = map[id] }
for (const id in map) {
_reducers[id] = map[id]
}
return this
},
addPrefilter(prefilter: any) {
@ -43,7 +66,9 @@ const Family = {
return this
},
addSagas(sagas: any) {
if (!sagas) { return this }
if (!sagas) {
return this
}
// tslint:disable-next-line: forin
for (const pattern in sagas) {
if (Array.isArray(sagas[pattern])) {
@ -59,16 +84,22 @@ const Family = {
return this
},
addListeners(map: any) {
if (!map) { return this }
if (!map) {
return this
}
// tslint:disable-next-line: forin
for (const pathname in map) { this.addListener(pathname, map[pathname]) }
return this
},
setRoutes(routes: any) {
if (!routes) { return this }
_routes = routes
for (const pathname in map) {
this.addListener(pathname, map[pathname])
}
return this
},
// setRoutes(routes: any) {
// if (!routes) {
// return this
// }
// _routes = routes
// return this
// },
start(container: any) {
_relatives.forEach(({ reducers = {}, sagas = {}, listeners = {} }: any) => {
this.addReducers(reducers)
@ -76,34 +107,72 @@ const Family = {
this.addSagas(sagas)
})
const props = { reducers: _reducers, listeners: _listeners, Routes: _routes }
start(container, props, (err: any, { store, history, sagaMiddleware, renderRoot }: any) => {
if (err) {
console.log(err)
return
}
/** init store begin */
const logger = false
const history = createHistory()
const routerMiddleware = createRouterMiddleware(history)
const sagaMiddleware = createSagaMiddleware({})
const composeEnhancers =
// @ts-ignore
(window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ &&
// @ts-ignore
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
trace: true,
traceLimit: 100,
})) ||
compose
const middlewares = logger
? [loggerMiddleware, routerMiddleware, sagaMiddleware]
: [routerMiddleware, sagaMiddleware]
const store = createStore<any, any, any, any>(
combineReducers({ ..._reducers, router: connectRouter(history) }),
composeEnhancers(applyMiddleware(...middlewares))
)
// 初始化当前页所需的数据
// @ts-ignore
history.location.params = URI(history.location.search || '').search(true)
history.listen((location, action: any) =>
handleLocation({ store, listeners: _listeners, location, action })
)
Family.store = store
Family.history = history
handleLocation({
store,
listeners: _listeners,
location: { pathname: '*' },
})
handleLocation({
store,
listeners: _listeners,
location: store.getState().router.location,
})
/** init store end */
Family.store = store
Family.history = history
function* rootSaga() {
function* rootSaga() {
try {
for (const prefilter of _prefilters) {
yield* prefilter({ store, renderRoot })
}
// tslint:disable-next-line: forin
for (const pattern in _sagas) {
for (const saga of _sagas[pattern]) {
yield takeLatest(pattern, saga)
}
yield* prefilter({ store })
}
} catch (error) {
return
}
renderRoot(() => {
handleLocation({ store, listeners: _listeners, location: { pathname: '*' } })
handleLocation({ store, listeners: _listeners, location: store.getState().router.location })
})
// 在执行 prefilter 之后再开始渲染主UI
start(container, { store, history })
// tslint:disable-next-line: forin
for (const pattern in _sagas) {
for (const saga of _sagas[pattern]) {
yield takeLatest(pattern, saga)
}
}
sagaMiddleware.run(rootSaga)
})
}
sagaMiddleware.run(rootSaga)
},
}

@ -5,6 +5,8 @@ import lodash from 'lodash'
import _URI from 'urijs'
import _moment from 'moment'
import { RouterState } from 'connected-react-router'
import { Store } from 'redux'
import { History } from 'history'
export default Family
export { Bundle }
@ -18,6 +20,8 @@ export { call, put, take, takeLatest } from 'redux-saga/effects'
export { delay } from 'redux-saga/effects'
export const _ = lodash
export const URI = _URI
export const store = Family.store as Store
export const history = Family.history as History
export const StoreStateRouterLocationURI = (router: RouterState) => {
const { pathname, search, hash } = router.location
return URI(pathname + search + hash)

@ -1,14 +1,10 @@
import React, { Component } from 'react'
import { render } from 'react-dom'
import { createStore, applyMiddleware, combineReducers, compose } from 'redux'
import { Store } from 'redux'
import { Provider } from 'react-redux'
import { createBrowserHistory as createHistory } from 'history'
import { routerMiddleware as createRouterMiddleware, connectRouter, ConnectedRouter } from 'connected-react-router'
import { History } from 'history'
import { ConnectedRouter } from 'connected-react-router'
import MuiThemeProvider from '@material-ui/core/styles/MuiThemeProvider'
import createSagaMiddleware from 'redux-saga'
import URI from 'urijs'
import loggerMiddleware from './loggerMiddleware'
import handleLocation from './handleLocation'
import { withStyles } from '@material-ui/core'
import GlobalStyles from '../components/common/GlobalStyles'
import ThemeProvider from '@material-ui/core/styles/MuiThemeProvider'
@ -16,24 +12,10 @@ import MuiTheme from '../components/common/MuiTheme'
import Routes from 'routes'
import { PropTypes } from 'family'
const logger = false
const start = (container: any, { reducers, listeners }: any, callback: any) => {
const history = createHistory()
const routerMiddleware = createRouterMiddleware(history)
const sagaMiddleware = createSagaMiddleware({})
// @ts-ignore
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
const middlewares = logger ? [loggerMiddleware, routerMiddleware, sagaMiddleware] : [routerMiddleware, sagaMiddleware]
const store = createStore(
combineReducers({ ...reducers, router: connectRouter(history) }),
composeEnhancers(applyMiddleware(...middlewares))
)
// 初始化当前页所需的数据
// @ts-ignore
history.location.params = URI(history.location.search || '').search(true)
history.listen((location, action: any) => handleLocation({ store, listeners, location, action }))
const start = (
container: any,
{ store, history }: { store: Store; history: History }
) => {
class RootBase extends Component<any> {
static childContextTypes = {
store: PropTypes.object,
@ -48,7 +30,7 @@ const start = (container: any, { reducers, listeners }: any, callback: any) =>
<MuiThemeProvider theme={MuiTheme}>
<Provider store={store}>
<ConnectedRouter history={history}>
<Routes store={store} />
<Routes/>
</ConnectedRouter>
</Provider>
</MuiThemeProvider>
@ -58,14 +40,7 @@ const start = (container: any, { reducers, listeners }: any, callback: any) =>
}
const Root = withStyles(GlobalStyles)(RootBase)
const renderRoot = (callback: any) => {
render(<Root />, container, callback) // 开始渲染
}
if (callback) { callback(null, { store, history, sagaMiddleware, renderRoot }) }
return { store, sagaMiddleware, renderRoot }
render(<Root />, container)
}
export default start

@ -4,9 +4,8 @@ import './assets/index.css'
import 'animate.css'
import React from 'react'
import Family, { render, push } from './family'
import Family, { render } from './family'
import { call, put } from 'redux-saga/effects'
import Routes from './routes'
import AccountRelative from './relatives/AccountRelative'
import HomeRelative from './relatives/HomeRelative'
import StatusRelative from './relatives/StatusRelative'
@ -41,13 +40,20 @@ function* authenticate() {
if (auth) {
yield put(AccountAction.fetchLoginInfoSucceeded(auth))
} else {
yield put(push(`/account/login`))
const { pathname, search, hash } = window.location
// const uri = URI(pathname + search + hash)
if (pathname.indexOf('/account/login') > -1) {
yield Promise.resolve()
return
}
const hasOriginal = pathname !== '/'
window.location.href = `/account/login${hasOriginal ? `?original=${encodeURIComponent(pathname + search + hash)}` : ''}`
yield Promise.reject()
}
}
document.addEventListener('DOMContentLoaded', () => {
Family
.setRoutes(Routes)
.addRelative(AccountRelative)
.addRelative(HomeRelative)
.addRelative(StatusRelative)

@ -4,6 +4,7 @@ import * as CommonAction from '../actions/common'
import AccountService from './services/Account'
import { StoreStateRouterLocationURI, replace, push } from '../family'
import { RootState } from '../actions/types'
import { showMessage, MSG_TYPE } from 'actions/common'
const relatives = {
reducers: {
@ -54,14 +55,26 @@ const relatives = {
return state
}
},
users(state: any = { data: [], pagination: { total: 0, limit: 100, cursor: 1 } }, action: any) {
users(
state: any = {
data: [],
pagination: { total: 0, limit: 100, cursor: 1 },
},
action: any
) {
switch (action.type) {
case '...':
return state
case AccountAction.addUserSucceeded({}).type:
return { data: [...state.data, action.user], pagination: state.pagination }
return {
data: [...state.data, action.user],
pagination: state.pagination,
}
case AccountAction.fetchUserCountSucceeded(0).type:
return { data: [...state.data], pagination: { ...state.pagination, total: action.count } }
return {
data: [...state.data],
pagination: { ...state.pagination, total: action.count },
}
case AccountAction.fetchUserListSucceeded([]).type:
return action.users
default:
@ -78,7 +91,9 @@ const relatives = {
*[AccountAction.fetchLoginInfo().type]() {
try {
const user = yield call(AccountService.fetchLoginInfo)
if (user.id) { yield put(AccountAction.fetchLoginInfoSucceeded(user)) }
if (user.id) {
yield put(AccountAction.fetchLoginInfoSucceeded(user))
}
} catch (e) {
yield put(AccountAction.fetchLoginInfoFailed(e.message))
}
@ -90,7 +105,9 @@ const relatives = {
yield put(AccountAction.addUserSucceeded(user))
try {
const user = yield call(AccountService.fetchLoginInfo)
if (user.id) { yield put(AccountAction.fetchLoginInfoSucceeded(user)) }
if (user.id) {
yield put(AccountAction.fetchLoginInfoSucceeded(user))
}
} catch (e) {
yield put(AccountAction.fetchLoginInfoFailed(e.message))
}
@ -98,22 +115,32 @@ const relatives = {
} else {
yield put(AccountAction.addUserFailed('注册失败'))
}
if (action.onResolved) { action.onResolved() }
if (action.onResolved) {
action.onResolved()
}
} catch (e) {
yield put(AccountAction.addUserFailed(e.message))
}
},
*[AccountAction.login({}, () => { /** empty */ }).type](action: any) {
*[AccountAction.login({}, () => {
/** empty */
}).type](action: any) {
try {
const user = yield call(AccountService.login, action.user)
if (user.errMsg) {
throw new Error(user.errMsg)
}
if (user) {
yield put(AccountAction.loginSucceeded(user))
// yield put(AccountAction.fetchLoginInfo()) // 注意:更好的方式是在 rootSaga 中控制跳转,而不是在这里重再次请求。
if (action.onResolved) { action.onResolved() }
if (action.onResolved) {
action.onResolved()
}
} else {
yield put(AccountAction.loginFailed(undefined))
}
} catch (e) {
yield put(showMessage(e.message, MSG_TYPE.WARNING))
yield put(AccountAction.loginFailed(e.message))
}
},

@ -7,7 +7,7 @@ import Home from './components/home/Home'
import LoginForm from './components/account/LoginForm'
import RegisterForm from './components/account/RegisterForm'
import Message from 'components/common/Message'
import { connect } from 'react-redux'
import { useSelector } from 'react-redux'
import { RootState } from 'actions/types'
const UserList = (props: any) => (
@ -82,8 +82,9 @@ const Utils = (props: any) => (
</Bundle>
)
const Routes = ({ store, message }: any) => {
const auth = store.getState().auth
const Routes = () => {
const auth = useSelector((state: RootState) => state.auth)
const message = useSelector((state: RootState) => state.message)
if (!auth) { return <Spin /> } // 渲染整站开屏动画,已经在 src/index 中实现。这里的代码用于支持没有接入 SSO 的情况。
if (!auth.id) { // 引导用户登陆,已经在 src/index 中实现。这里的代码用于支持没有接入 SSO 的情况。
return (
@ -179,6 +180,4 @@ const Routes = ({ store, message }: any) => {
)
}
export default connect((state: RootState) => ({
message: state.message,
}), null)(Routes)
export default Routes

Loading…
Cancel
Save