feat(登录登出): 已完成用户使用账号密码登录登出

This commit is contained in:
xuan 2022-09-13 14:17:04 +08:00
parent a07ca24140
commit 5bc498ad31
14 changed files with 297 additions and 242 deletions

View File

@ -1,43 +1,39 @@
import Taro from "@tarojs/taro"
import Taro from '@tarojs/taro'
import Qs from 'qs'
/**
*
* @param path
* @param params
* @param path
* @param params
* @param type false true tabbar页面
*/
type ParamLink = 'navigateTo'|'switchTab'|'reLaunch'|'redirectTo'
type ParamLink = 'navigateTo' | 'switchTab' | 'reLaunch' | 'redirectTo'
export const goLink = (path = '', params = {}, way: ParamLink = 'navigateTo') => {
if(path) {
let params_str = Qs.stringify(params)
console.log('params_str::',params_str)
path = params_str?path+'?'+params_str:path
console.log('path::', way)
Taro[way]({url: path})
}
if (path) {
let params_str = Qs.stringify(params)
path = params_str ? path + '?' + params_str : path
Taro[way]({ url: path })
}
}
/**
*
* @param object
* @returns
* @param object
* @returns
*/
export const isEmptyObject = (object: any)=>{
if(object==undefined||object==null||Number.isNaN(object)){
return true;
}else{
if(object.constructor==Object){
return Reflect.ownKeys(object).length==0;
}else if(object.constructor==Array){
return object.length==0;
}else if(object.constructor==String){
return object=="";
}
export const isEmptyObject = (object: any) => {
if (object == undefined || object == null || Number.isNaN(object)) {
return true
} else {
if (object.constructor == Object) {
return Reflect.ownKeys(object).length == 0
} else if (object.constructor == Array) {
return object.length == 0
} else if (object.constructor == String) {
return object == ''
}
return false;
}
return false
}
/**
*
@ -58,86 +54,90 @@ export const isEmptyObject = (object: any)=>{
* @param message
* @returns
*/
export const retrieval = (data: any, rules?: Object, message: string="请填写完信息")=>{
return new Promise((resolve, reject)=>{
if(rules){
const keys = Reflect.ownKeys(rules);
const result = keys.some((key:any)=>{
for(let item of (rules as any)[key]){
let _res = false;
if(item.validator){
if(item.validator(data[key],item)){
_res=true;
}
}else if(item.regex){
if(!item.regex.test(data[key])){
_res=true;
}
}else{
if(isEmptyObject(data[key])){
_res=true;
}
export const retrieval = (data: any, rules?: Object, message: string = '请填写完信息') => {
return new Promise((resolve, reject) => {
if (rules) {
const keys = Reflect.ownKeys(rules)
const result = keys.some((key: any) => {
for (let item of (rules as any)[key]) {
let _res = false
if (item.validator) {
if (item.validator(data[key], item)) {
_res = true
}
} else if (item.regex) {
if (!item.regex.test(data[key])) {
_res = true
}
} else {
if (isEmptyObject(data[key])) {
_res = true
}
message = item.message;
return _res;
}
});
if(result){
reject(message);
}
}else{
const keys = Reflect.ownKeys(data);
if(keys.some((key:any)=>isEmptyObject(data[key]))){
reject(message);
message = item.message
return _res
}
})
if (result) {
reject(message)
}
} else {
const keys = Reflect.ownKeys(data)
if (keys.some((key: any) => isEmptyObject(data[key]))) {
reject(message)
}
resolve(null);
})
}
/**
* toast提示
*/
export const alert = {
success(title: string){
Taro.showToast({
title,icon: "success"
})
},
error(title: string){
Taro.showToast({
title,icon: "error"
})
},
loading(title: string, mask: true|false = false){
Taro.showToast({
title,icon: "loading",
mask
})
},
none(title: string){
Taro.showToast({
title,icon: "none"
})
},
showLoading(title: string, mask: true|false = true) {
Taro.showLoading({title, mask})
},
hideLoading() {
Taro.hideLoading()
}
}
resolve(null)
})
}
/**
* toast提示
*/
export const alert = {
success(title: string) {
Taro.showToast({
title,
icon: 'success',
})
},
error(title: string) {
Taro.showToast({
title,
icon: 'error',
})
},
loading(title: string, mask: true | false = false) {
Taro.showToast({
title,
icon: 'loading',
mask,
})
},
none(title: string) {
Taro.showToast({
title,
icon: 'none',
})
},
showLoading(title: string, mask: boolean = true) {
Taro.showLoading({ title, mask })
},
hideLoading() {
Taro.hideLoading()
},
}
// 金额千位分割符
export const formatKbPrice = (number: string) => {
const ret = Array.from(number).reverse().reduce((result: string[],next,i,arr) => {
if((i+1)%3 === 0 && (i+1) !== arr.length) {
result.push(next,',')
return result;
}
result.push(next);
return result;
},[])
return ret.reverse().join('');
const ret = Array.from(number)
.reverse()
.reduce((result: string[], next, i, arr) => {
if ((i + 1) % 3 === 0 && i + 1 !== arr.length) {
result.push(next, ',')
return result
}
result.push(next)
return result
}, [])
return ret.reverse().join('')
}

View File

@ -1,3 +1,10 @@
.checkbox {
display: flex;
align-items: center;
&--text {
margin-left: 10px;
}
}
.checkbox_main {
display: flex;
justify-content: center;

View File

@ -14,9 +14,10 @@ type params = {
circle?: boolean
round?: boolean
size?: CheckboxSize
children?: React.ReactNode
}
export default forwardRef((props: params, ref) => {
const { onSelect, onClose, status = false, disabled = false, circle = false, round = true, size = 'normal' } = props
const { onSelect, onClose, status = false, disabled = false, circle = false, round = true, size = 'normal', children } = props
const [selected, SetSelected] = useState(false)
const onSelectEven = () => {
if (disabled) return false
@ -54,12 +55,13 @@ export default forwardRef((props: params, ref) => {
SetSelected(status)
}, [status])
return (
<>
<View className={classnames(styles.checkbox_main, getMainClassName())} onClick={() => onSelectEven()}>
<View className={styles.checkbox} onClick={() => onSelectEven()}>
<View className={classnames(styles.checkbox_main, getMainClassName())}>
<View className={classnames(styles.checkbox_item, getClassName())}>
{selected && <IconFont name='icon-a-jizhumima' size={22} color='#fff'></IconFont>}
</View>
</View>
</>
{children && <View className={styles['checkbox--text']}>{children}</View>}
</View>
)
})

View File

@ -41,7 +41,6 @@ const NormalButton: FC<PropsType> = (props) => {
[styles['button--plain']]: plain,
[styles['button--circle']]: circle,
}
console.log('classObj==>button', classObject)
return classObject
}

View File

@ -1,11 +1,25 @@
export const SET_USERINFO = 'setUserInfo'
export const SET_ADMINUSERINFO = 'setAdminUserInfo'
export const SET_TOKEN = 'setToken'
export const SET_SESSIONKEY = 'setSessionkey'
export const SET_SORTCODE = 'setSortCode'
export const CLEAR_TOKEN = 'clearToken'
export const CLEAR_SESSIONKEY = 'clearSessionkey'
export const CLEAR_USERINFO = 'clearUserInfo'
export const CLEAR_ADMINUSERINFO = 'clearAdminUserInfo'
export const CLEAR_SORTCODE = 'clearSortCode'
export const LOGIN_STATUS = 'loginStatus'
// export const SET_USERINFO = 'setUserInfo'
// export const SET_ADMINUSERINFO = 'setAdminUserInfo'
// export const SET_TOKEN = 'setToken'
// export const SET_SESSIONKEY = 'setSessionkey'
// export const SET_SORTCODE = 'setSortCode'
// export const CLEAR_TOKEN = 'clearToken'
// export const CLEAR_SESSIONKEY = 'clearSessionkey'
// export const CLEAR_USERINFO = 'clearUserInfo'
// export const CLEAR_ADMINUSERINFO = 'clearAdminUserInfo'
// export const CLEAR_SORTCODE = 'clearSortCode'
// export const LOGIN_STATUS = 'loginStatus'
export const enum UserInfoActionType {
SET_USERINFO = 'setUserInfo',
SET_ADMINUSERINFO = 'setAdminUserInfo',
SET_TOKEN = 'setToken',
SET_SESSIONKEY = 'setSessionkey',
SET_SORTCODE = 'setSortCode',
CLEAR_TOKEN = 'clearToken',
CLEAR_SESSIONKEY = 'clearSessionkey',
CLEAR_USERINFO = 'clearUserInfo',
CLEAR_ADMINUSERINFO = 'clearAdminUserInfo',
CLEAR_SORTCODE = 'clearSortCode',
LOGIN_STATUS = 'loginStatus',
}

View File

@ -25,8 +25,6 @@ type TabBarIndexMap = {
const CustomTabBar: FC = () => {
console.log('重新渲染')
const { selectedId, tabItem } = useSelector((state) => {
console.log('sdfasdfa', state)
return state.tabBarData

View File

@ -1,6 +1,6 @@
import Divider from '@/components/divider'
import IconFont from '@/components/iconfont'
import { View, Image, Text, Input, CommonEventFunction } from '@tarojs/components'
import { View, Image, Text, Input } from '@tarojs/components'
import { FC, useState } from 'react'
import styles from './index.module.scss'
import MCheckbox from '@/components/checkbox'
@ -8,11 +8,14 @@ import NormalButton from '@/components/normalButton'
import IconCard from '@/components/iconCard'
import {memo} from 'react'
import { LoginApi } from '@/api'
import Taro from '@tarojs/taro'
import { alert } from '@/common/common'
import useUserInfo from '@/use/useUserInfo'
const Login: FC = () => {
const [isRemember, setRemember] = useState(false)
const [eyesStatus, setEyesStatus] = useState(false)
const [eyesStatus, setEyesStatus] = useState(true)
const handlePwdVisible = () => {
setEyesStatus((value) => !value)
@ -30,19 +33,47 @@ const Login: FC = () => {
const [account, setAccount] = useState('')
const [password, setPassword] = useState('')
const formatInput = (value:string) => {
return value.trim()
}
const handleInputAccount = (event: any) => {
const formated = formatInput(event.detail.value)
setAccount(formated)
}
const handleInputPassword = () => {
const handleInputPassword = (event: any) => {
const formated = formatInput(event.detail.value)
setPassword(formated)
}
const { fetchData , state} = LoginApi()
const { setToken, setUserInfo } = useUserInfo()
const { fetchData } = LoginApi()
const handleLogin = async () => {
await fetchData({
if (account === '' || password === '') return alert.error('账号密码不能为空!')
console.log('账户密码:', account, password)
const res = await fetchData({
account,
password,
})
console.log('state===>', res)
if (res.success) {
alert.success('登陆成功')
setToken(res.data.token)
setUserInfo({ ...res.data })
Taro.redirectTo({
url: '/pages/index/index',
})
} else {
alert.error('登陆失败')
}
}
return (
@ -61,9 +92,14 @@ const Login: FC = () => {
<View className={styles['input-bar']}>
<IconFont name='icon-mima' size={48} color='#999999'></IconFont>
<Divider direction='vertical'></Divider>
<Input onInput={handleInputPassword} className={styles['input-bar--password']} type='safe-password' placeholder='请输入密码'></Input>
<Input
onInput={handleInputPassword}
password={eyesStatus}
className={styles['input-bar--password']}
type='safe-password'
placeholder='请输入密码'></Input>
<View onClick={handlePwdVisible}>
{eyesStatus ? (
{!eyesStatus ? (
<IconFont name='icon-yanjing' size={48} color='#999999'></IconFont>
) : (
<IconFont name='icon-biyan' size={48} color='#999999'></IconFont>
@ -72,8 +108,9 @@ const Login: FC = () => {
</View>
<View className={styles['login-options']}>
<View className={styles['login-option']}>
<MCheckbox status={isRemember} size='small' circle onSelect={selectCallBack} onClose={closeCallBack}></MCheckbox>
<Text className={styles.isRememberPwd}></Text>
<MCheckbox status={isRemember} size='small' circle onSelect={selectCallBack} onClose={closeCallBack}>
</MCheckbox>
</View>
<View className={styles['login-option']}>
<Text className={styles.isForgetPwd}></Text>

View File

@ -1,6 +1,5 @@
import { isEmptyObject } from '@/common/common'
import { Button, View, Image, Text } from '@tarojs/components'
import { FC, memo, useMemo, useState } from 'react'
import { View, Image, Text } from '@tarojs/components'
import { FC, useState } from 'react'
import styles from './index.module.scss'
import defaultAvatar from '../../styles/image/defaultAvatar.png'
import NormalButton from '@/components/normalButton'
@ -9,6 +8,8 @@ import Divider from '@/components/Divider'
import LayoutBlock from '@/components/layoutBlock'
import IconCard from '@/components/iconCard'
import IconFont from '@/components/iconfont'
import useUserInfo from '@/use/useUserInfo'
import { goLink } from '@/common/common'
type IconfontName = Parameters<typeof IconFont>['0']['name']
type IconCardType = {
@ -19,11 +20,13 @@ type IconCardType = {
// 用户信息
const UserInfo: FC = () => {
const [userInfo, setUserInfo] = useState({
avatarUrl: '',
username: '',
userno: '',
})
const { removeToken, removeUserInfo, userInfo } = useUserInfo()
console.log('userInfo==>', userInfo)
// const [userInfo, setUserInfo] = useState({
// avatarUrl: '',
// username: '',
// userno: '',
// })
const feature: IconCardType[] = [
@ -110,18 +113,24 @@ const UserInfo: FC = () => {
},
]
const handleLogout = () => {}
// 退出登录
const handleLogout = () => {
removeToken()
removeUserInfo()
goLink('/pages/login/index', {}, 'reLaunch')
}
return (
<>
<LayoutBlock circle>
<View className={styles.topBar}>
<View className={styles.left}>
<UserAvatar src={userInfo.avatarUrl} />
<UserAvatar src={userInfo.userInfo.avatar_url} />
</View>
<View className={styles.middle}>
<Text className={styles.username}></Text>
<Text className={styles.userno}>064</Text>
<Text className={styles.username}>{userInfo.userInfo.user_name}</Text>
<Text className={styles.userno}>{userInfo.userInfo.user_code}</Text>
</View>
<View className={styles.right}>
<NormalButton type='primary' round size='normal' onClick={handleLogout}>
@ -161,13 +170,6 @@ const UserInfo: FC = () => {
})}
</View>
</LayoutBlock>
{/* <LayoutBlock circle>
<View className={styles.layoutTabBar}>
<View className={styles.layoutTitle}></View>
<View className={styles.layoutDescription}> </View>
</View>
asdfasdfasdfas
</LayoutBlock> */}
</>
)
}

View File

@ -19,7 +19,7 @@ const INIT = {
shopCount: Taro.getStorageSync(STORAGE_SHOPCOUNT)?JSON.parse(Taro.getStorageSync(STORAGE_SHOPCOUNT)).shopCount:0,
}
export default function counter (state = INIT, action: Action) {
export default (state = INIT, action: Action) => {
const {type, data} = action
switch (type) {
case SET_SHOPCOUNT:
@ -31,4 +31,4 @@ export default function counter (state = INIT, action: Action) {
default:
return state
}
}
}

View File

@ -5,7 +5,7 @@ import { DataParam as userInfoParam } from './userInfo';
import { DataParam as commonDataParam } from './commonData';
import { TabBarData as tabbarDataParam } from './tabBar';
type Params = {
userInfo: userInfoParam
userInfoData: userInfoParam
commonData: commonDataParam
tabBarData: tabbarDataParam
}

View File

@ -1,10 +1,10 @@
import { combineReducers } from 'redux'
import userInfo from './userInfo'
import userInfoData from './userInfo'
import commonData from './commonData'
import tabBarReducer from './tabBar'
export type Reducers = {
userInfo: typeof userInfo
userInfoData: typeof userInfoData
commonData: typeof commonData
tabBarData: typeof tabBarReducer
}
@ -12,7 +12,7 @@ export type Reducers = {
export type ReducersKey = keyof Reducers
export default combineReducers<Reducers>({
userInfo,
userInfoData,
commonData,
tabBarData: tabBarReducer,
})

View File

@ -1,31 +1,18 @@
import Taro from '@tarojs/taro'
import {
SET_USERINFO,
SET_ADMINUSERINFO,
SET_TOKEN,
SET_SESSIONKEY,
SET_SORTCODE,
CLEAR_TOKEN,
CLEAR_USERINFO,
CLEAR_SESSIONKEY,
CLEAR_ADMINUSERINFO,
CLEAR_SORTCODE,
LOGIN_STATUS
} from '../constants/userInfo'
import { UserInfoActionType } from '../constants/userInfo'
export type UserParam = {
nickName?:string,
phone?:string,
avatarUrl?:string,
city?: string,
country?: string,
province?: string,
gender?: number,
language?: string,
timestamp?: number,
physical_warehouse?: number,
physical_warehouse_name?: string,
department_code?: string
department_id?: string
department_name?: string
physical_warehouse?: number
physical_warehouse_name?: string
token?: string
user_code?: number
user_id?: string
user_name?: number
avatar_url?: string
}
export type UserAdminParam = {
@ -38,8 +25,8 @@ export type UserAdminParam = {
user_id?: number,
user_name?: string,
wechat_user_open_id?: number
is_authorize_name?: false|true,
is_authorize_phone?: false|true,
is_authorize_name?: boolean,
is_authorize_phone?: boolean,
phone?:string,
authentication_status?:number,
authentication_status_name: string,
@ -64,11 +51,11 @@ export type DataParam = {
userInfo: UserParam,
adminUserInfo: UserAdminParam,
sort_code: SortCodeParam
logingStatus?: false //登录状态 true 正在登录
logingStatus?: boolean //登录状态 true 正在登录
}
type Action = {
type?: string,
export type UserInfoAction = {
type: UserInfoActionType
data?: DataParam
}
@ -82,42 +69,42 @@ const INIT_USER = {
logingStatus: false
}
export default function counter (state = INIT_USER, action: Action) {
const {type, data} = action
switch (type) {
case SET_USERINFO:
Taro.setStorageSync('userInfo',JSON.stringify(data?.userInfo))
return {...state,...data}
case SET_ADMINUSERINFO:
Taro.setStorageSync('adminUserInfo',JSON.stringify(data?.adminUserInfo))
return {...state,...data}
case SET_TOKEN:
Taro.setStorageSync('token',data?.token)
return {...state,...data}
case SET_SESSIONKEY:
Taro.setStorageSync('session_key',data?.session_key)
return {...state,...data}
case SET_SORTCODE:
Taro.setStorageSync('sort_code',JSON.stringify(data?.sort_code))
return {...state,...data}
case CLEAR_TOKEN:
Taro.removeStorageSync('token')
return {...state, token:''}
case CLEAR_SESSIONKEY:
Taro.removeStorageSync('session_key')
return {...state, session_key:''}
case CLEAR_USERINFO:
Taro.removeStorageSync('userInfo')
return {...state, userInfo: null}
case CLEAR_ADMINUSERINFO:
Taro.removeStorageSync('adminUserInfo')
return {...state, adminUserInfo: null}
case CLEAR_SORTCODE:
Taro.removeStorageSync('sort_code')
return {...state, sortCode: null}
case LOGIN_STATUS:
return {...state, ...data}
default:
return state
}
}
export default (state = INIT_USER, action: UserInfoAction) => {
const { type, data } = action
switch (type) {
case UserInfoActionType.SET_USERINFO:
Taro.setStorageSync('userInfo', JSON.stringify(data?.userInfo))
return { ...state, ...data }
case UserInfoActionType.SET_ADMINUSERINFO:
Taro.setStorageSync('adminUserInfo', JSON.stringify(data?.adminUserInfo))
return { ...state, ...data }
case UserInfoActionType.SET_TOKEN:
Taro.setStorageSync('token', data?.token)
return { ...state, ...data }
case UserInfoActionType.SET_SESSIONKEY:
Taro.setStorageSync('session_key', data?.session_key)
return { ...state, ...data }
case UserInfoActionType.SET_SORTCODE:
Taro.setStorageSync('sort_code', JSON.stringify(data?.sort_code))
return { ...state, ...data }
case UserInfoActionType.CLEAR_TOKEN:
Taro.removeStorageSync('token')
return { ...state, token: '' }
case UserInfoActionType.CLEAR_SESSIONKEY:
Taro.removeStorageSync('session_key')
return { ...state, session_key: '' }
case UserInfoActionType.CLEAR_USERINFO:
Taro.removeStorageSync('userInfo')
return { ...state, userInfo: null }
case UserInfoActionType.CLEAR_ADMINUSERINFO:
Taro.removeStorageSync('adminUserInfo')
return { ...state, adminUserInfo: null }
case UserInfoActionType.CLEAR_SORTCODE:
Taro.removeStorageSync('sort_code')
return { ...state, sortCode: null }
case UserInfoActionType.LOGIN_STATUS:
return { ...state, ...data }
default:
return state
}
}

View File

@ -122,6 +122,7 @@ export const useRequest = (
}
const stateRef = useRef({ ...params })
console.log('stateRef==>', stateRef)
const [state, setState] = useState({ ...stateRef.current })
const { removeToken, removeSessionKey, removeUserInfo } = useUserInfo()
const { login } = useLoginRequest()
@ -152,11 +153,11 @@ export const useRequest = (
},
...(options.method?.toUpperCase() == 'GET'
? {
data: stateRef.current.query,
}
data: stateRef.current.query,
}
: {
data: options.type?.toUpperCase() == 'FORMDATA' ? qs.stringify(stateRef.current.query) : stateRef.current.query,
}),
data: options.type?.toUpperCase() == 'FORMDATA' ? qs.stringify(stateRef.current.query) : stateRef.current.query,
}),
}
const result = await Taro.request(q as any)
const { statusCode } = result
@ -196,10 +197,11 @@ export const useRequest = (
}
stateRef.current.error = false
stateRef.current.loading = false
setState(() => ({ ...stateRef.current }))
setState(() => ({...stateRef.current}))
console.log('request result stateRef', stateRef.current)
console.log('request result state', state)
return stateRef.current
}
return {
fetchData,
state,

View File

@ -1,40 +1,47 @@
import { useDispatch, useSelector } from 'react-redux'
import { CLEAR_SESSIONKEY, SET_USERINFO, SET_TOKEN, SET_SESSIONKEY, CLEAR_USERINFO, CLEAR_TOKEN, SET_ADMINUSERINFO, SET_SORTCODE } from '@/constants/userInfo'
import { DataParam, UserParam, UserAdminParam, SortCodeParam } from '@/reducers/userInfo'
import { useDispatch } from 'react-redux'
import { UserInfoActionType } from '@/constants/userInfo'
import { DataParam, UserParam, UserAdminParam, SortCodeParam, UserInfoAction } from '@/reducers/userInfo'
import { Dispatch } from 'redux'
import { useSelector } from '@/reducers/hooks'
export default () => {
const userInfo = useSelector((state: DataParam) => state.userInfo) as DataParam
const dispatch = useDispatch()
const userInfo = useSelector((state) => state.userInfoData)
const dispatch = useDispatch<Dispatch<UserInfoAction>>()
const setToken = (token: string) => {
dispatch({ type: SET_TOKEN, data: { token } })
// @ts-ignore
dispatch({ type: UserInfoActionType.SET_TOKEN, data: { token } })
}
const setSessionKey = (sessionkey: string) => {
dispatch({ type: SET_SESSIONKEY, data: { session_key: sessionkey } })
// @ts-ignore
dispatch({ type: UserInfoActionType.SET_SESSIONKEY, data: { session_key: sessionkey } })
}
const setUserInfo = (userInfo: UserParam) => {
dispatch({ type: SET_USERINFO, data: { userInfo } })
// @ts-ignore
dispatch({ type: UserInfoActionType.SET_USERINFO, data: { userInfo } })
}
const setAdminUserInfo = (adminUserInfo: UserAdminParam) => {
dispatch({ type: SET_ADMINUSERINFO, data: { adminUserInfo } })
// @ts-ignore
dispatch({ type: UserInfoActionType.SET_ADMINUSERINFO, data: { adminUserInfo } })
}
const setSortCode = (sortCode: SortCodeParam) => {
dispatch({ type: SET_SORTCODE, data: { sort_code: sortCode } })
// @ts-ignore
dispatch({ type: UserInfoActionType.SET_SORTCODE, data: { sort_code: sortCode } })
}
const removeUserInfo = () => {
dispatch({ type: CLEAR_USERINFO })
dispatch({ type: UserInfoActionType.CLEAR_USERINFO })
}
const removeToken = () => {
dispatch({ type: CLEAR_TOKEN })
dispatch({ type: UserInfoActionType.CLEAR_TOKEN })
}
const removeSessionKey = () => {
dispatch({ type: CLEAR_SESSIONKEY })
dispatch({ type: UserInfoActionType.CLEAR_SESSIONKEY })
}
return {