Commit 56b75cb2 authored by 赵振东's avatar 赵振东

feat: 完善登录功能,对接登录接口,增加需求单页面

parent 1c5b8893
......@@ -28,6 +28,5 @@ package.json
**/__snapshots__/**
**/.node/**
**/esm/**
src/services
android
ios
import * as React from 'react';
import {
NavigationContainerRef,
StackActions,
CommonActions,
NavigationState,
} from '@react-navigation/native';
import { RootStackParamList } from './types';
import { ROUTERS } from './routers';
let lastRoute: NavigationState['routes'][0] | null = null;
const limits = ['CustomerQuery', 'CustomerNewDrawer', 'OrderIndex'];
export const navigationRef =
React.createRef<NavigationContainerRef<RootStackParamList>>();
export function navigate(name: string, params: Object) {
navigationRef.current?.navigate(name as any, params);
}
export function replace(name: string, params?: Object) {
const BottomTabsRouteNames = ROUTERS.map(item => item.name);
const limitList = [...BottomTabsRouteNames, ...limits];
// 如果传入name存在Stack中,则直接替换当前页面
// 否则全部跳转到首页
if (!limitList.includes(name)) {
navigationRef.current?.dispatch(() => {
return StackActions.replace(name, params);
});
} else {
navigationRef.current?.dispatch(() => {
return StackActions.replace('BottomTabs');
});
}
}
export function replaceLogin(loginName: string, params?: Object) {
navigationRef.current?.dispatch(state => {
const loginInStack = state.routes.find(item => item.name === loginName);
// 如果登录页不在在路由栈,则直接替换到路由页面,否则直接跳转(待验证)
if (!loginInStack) {
lastRoute = state.routes.slice(-1)[0];
return StackActions.replace(loginName, params);
}
// return CommonActions.navigate(loginName, params);
return CommonActions.reset(state);
});
}
export function getLastRoute() {
return lastRoute;
}
export function resetLastRoute() {
lastRoute = null;
}
......@@ -5,7 +5,7 @@ import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { RootStackParamList } from './types';
import { ROUTERS as SCREEN } from './routers';
import Theme from '../constants/theme';
import { navigationRef } from './RootNavigation';
const RootStack = createNativeStackNavigator<RootStackParamList>();
const SCREEN_NAMES = Object.keys(SCREEN) as (keyof typeof SCREEN)[];
......@@ -27,12 +27,12 @@ const RootNavigationContainer: React.FC<Iprops> = props => {
};
return (
<NavigationContainer theme={CurrentTheme()}>
<NavigationContainer theme={CurrentTheme()} ref={navigationRef}>
<RootStack.Navigator
screenOptions={{
headerTitleAlign: 'center',
}}
initialRouteName="OrderList"
initialRouteName="Home"
>
{SCREEN_NAMES.map(name => (
<RootStack.Screen
......
......@@ -10,6 +10,7 @@ import OrderList from '../views/Order/OrderList';
import OrderDetail from '../views/Order/MycommodityDetails';
import InputCaptureCode from '../views/InputCaptureCode';
import EditPassword from '../views/EditPasasord';
import RequireOrder from '../views/RequireOrder';
export const ROUTERS = {
Login: {
title: '登入',
......@@ -71,4 +72,9 @@ export const ROUTERS = {
component: EditPassword,
headerShown: false,
},
RequireOrder: {
title: '求购需求单',
component: RequireOrder,
headerShown: false,
},
};
......@@ -6,16 +6,15 @@
* @Description: In User Settings Edit
* @FilePath: \lingxi-mobile-app\src\services\basic\requestService.ts
*/
import { requestFetch, RequestFetchOptions } from './requestFetch'
import { RequestFactoryModel, IRequestSuccess, requestHeaders } from './types'
import { GlobalConfig } from '../../constants/global'
import { mergeConfig } from './utils'
import { getAsyncStorage } from '../../utils/storage'
import { TOKEN } from '../../constants/index'
// import * as navigation from '../../routers/navigationRef'
import Store from '../../store'
const env = require('../../../.projectEnv/env')
import { requestFetch, RequestFetchOptions } from './requestFetch';
import { RequestFactoryModel, IRequestSuccess, requestHeaders } from './types';
import { GlobalConfig } from '../../constants/global';
import { mergeConfig } from './utils';
import { getAsyncStorage } from '../../utils/storage';
import { TOKEN, USER_INFO } from '../../constants/index';
import * as RootNavigation from '../../routers/RootNavigation';
import { Store } from '../../store';
const env = require('../../../.projectEnv/env');
/**
* 使用dotenv动态引入
......@@ -39,16 +38,18 @@ class RequestFactory implements RequestFactoryModel {
paramsConfig: RequestFetchOptions,
): Promise<IRequestSuccess<T>> {
const headers = { ...defaultHeaders };
// const Token = await getAsyncStorage(TOKEN);
// console.log('TokenTokenToken', Token)
// if (Token) {
// headers.token = Token;
// }
let Token = null;
try {
Token = await getAsyncStorage(TOKEN);
} catch {}
if (Token) {
headers.token = Token;
}
const config: RequestFetchOptions = paramsConfig;
config.headers = config.headers ? mergeConfig(headers, config.headers) : headers;
config.headers = config.headers
? mergeConfig(headers, config.headers)
: headers;
console.log('请求地址:', `${requestBaseUrl + url}`, config);
console.log('请求参数:', config);
......@@ -60,17 +61,19 @@ class RequestFactory implements RequestFactoryModel {
requestFetch<IRequestSuccess<T>>(requestBaseUrl + url, config)
.then((res: IRequestSuccess<T>) => {
// 未登录
console.log('请求结果:', res);
if (res.code === 1101) {
// Store.userStore.removeUserInfo();
// navigation.dispatch("Login");
new Store().userStore.removeUserInfo();
// 自动跳转登录页面
RootNavigation.replaceLogin('Login');
reject(res);
return;
}
// 错误提示,忽略掉 post 请求,因为很多页面都处理了
if (
(config.method as unknown) !== 'POST'
&& res.code !== 1000
&& res.message
(config.method as unknown) !== 'POST' &&
res.code !== 1000 &&
res.message
) {
if (config.showError !== false) {
// Toast.show(res.message);
......@@ -79,7 +82,7 @@ class RequestFactory implements RequestFactoryModel {
}
resolve(res);
})
.catch((err) => {
.catch(err => {
if (config.showError !== false) {
// Toast.show(err.code);
}
......@@ -87,7 +90,7 @@ class RequestFactory implements RequestFactoryModel {
// navigate("Network", {});
// }
reject(err);
})
});
});
}
}
......
......@@ -38,16 +38,19 @@ export class UserStore {
}
}
// 用户登录时,或者修改用户信息的时候更新UserInfo
// async setUserInfo(data: userInfoType) {
// const result = {
// ...data,
// memberRoleName: getMemberRoleName(data),
// };
// await setAsyncStorage(USER_INFO, result);
// runInAction(() => {
// this.userInfo = result;
// });
// 不清除userInfo
// *removeUserInfo() {
// try {
// yield removeAsyncStorage(TOKEN);
// yield removeAsyncStorage(USER_INFO);
// // 商品分享口令生成数字
// yield removeAsyncStorage('SHARE_CODE_NUM');
// // console.log('store移除用户信息-----Success');
// this.userInfo = null;
// } catch (error) {
// console.log('store移除用户信息-----Error', error);
// }
// }
*removeUserInfo() {
......@@ -57,7 +60,6 @@ export class UserStore {
// 商品分享口令生成数字
yield removeAsyncStorage('SHARE_CODE_NUM');
// console.log('store移除用户信息-----Success');
this.userInfo = null;
} catch (error) {
console.log('store移除用户信息-----Error', error);
......
......@@ -64,6 +64,7 @@ interface NavBarProps {
* 返回icon,默认 #252D37
*/
backIconColor?: string;
data: any;
}
const Header: React.FC<NavBarProps> = (props: NavBarProps) => {
......@@ -72,13 +73,11 @@ const Header: React.FC<NavBarProps> = (props: NavBarProps) => {
customStyle,
titleColor = '#303133',
backIconColor = '#252D37',
data,
} = props;
const [languageTitle, setLanguageTitle] = useState<string>('简体中文');
const {
userStore: { userInfo },
} = useStores();
const myStyle = useAppStyle(styles);
const navigation = useNavigation();
......@@ -101,7 +100,7 @@ const Header: React.FC<NavBarProps> = (props: NavBarProps) => {
navigation.navigate('SelectLanguage');
};
const jumpToMember = () => {
navigation.navigate('SelectMembers', userInfo);
navigation.navigate('SelectMembers', data);
};
return (
......
......@@ -18,27 +18,35 @@ import ghxlogo from '../../../assets/images/home_image/gaohuaxue_logo.png';
import Icons from 'react-native-vector-icons/AntDesign';
import useLocale from '../../hooks/useLocale';
import { roleType } from '../../store/userStore/types';
import { getMemberMobileLoginReget } from '../../services/MemberV2Api';
type HomeNavigationProp = CompositeScreenProps<
RootTabScreenProps<'Home'>,
StackScreenProps<RootStackParamList>
>;
const column = [
{ label: '查看订单', icon: order, route: 'Order' },
{ label: '查看订单', icon: order, route: 'OrderList' },
{ label: '订单审核', icon: verify, route: 'Verify' },
{ label: '查看询价单', icon: enquiry, route: 'Enquiry' },
{ label: '确认询价报价', icon: check, route: 'Check' },
{ label: '求购需求单', icon: Purchase, route: 'Purchase' },
{ label: '求购需求单', icon: Purchase, route: 'requireOrder' },
{ label: '消息中心', icon: news, route: 'News' },
];
const Home: React.FC<HomeNavigationProp> = ({ navigation, route }) => {
const {
userStore: { userInfo },
} = useStores();
const { userStore } = useStores();
const [userInfo, setUerInfo] = useState({});
useEffect(() => {
const getInfo = async () => {
const { data } = await getMemberMobileLoginReget({ shopType: '1' });
setUerInfo(data);
userStore.setUserInfo(data);
};
getInfo();
}, []);
const getCurrentRole = () => {
const currentRole = userInfo?.roles.find(el => {
const currentRole = userInfo?.roles?.find(el => {
return el.roleId === userInfo.memberRoleId;
});
return currentRole;
......@@ -47,7 +55,7 @@ const Home: React.FC<HomeNavigationProp> = ({ navigation, route }) => {
const [initColumn, setInitColumn] = useState([]);
useEffect(() => {
const _roleType = getCurrentRole().roleType;
const _roleType = getCurrentRole()?.roleType;
// 会员角色类型,1-服务提供者,2-服务消费者
if (_roleType === roleType.provider) {
const _column = [...column];
......@@ -69,7 +77,6 @@ const Home: React.FC<HomeNavigationProp> = ({ navigation, route }) => {
const jumpSetting = () => {
navigation.navigate('AccountInfo');
};
console.log('2222222222222222');
return (
<View
style={{
......@@ -77,7 +84,7 @@ const Home: React.FC<HomeNavigationProp> = ({ navigation, route }) => {
backgroundColor: '#F4F5F7',
}}
>
<Header title={getCurrentRole()?.roleName} noLeft />
<Header title={getCurrentRole()?.roleName} noLeft data={userInfo} />
{/* 图标页 */}
<View style={styles.Lcontainer}>
<Image source={ghxlogo} style={styles.logo} />
......
......@@ -53,15 +53,14 @@ const Login: React.FC<LoginScreenNavigationProp> = ({ navigation }) => {
obj.shopType = value.shopType;
break;
}
try {
const { code, data, message } = await service?.(
current === 1 ? value : obj,
);
if (code === 1000) {
userStore.setUserInfo(data);
setAsyncStorage(USER_INFO, data);
setAsyncStorage(TOKEN, data.token);
// navigation.replace('SelectMembers', data);
if (data.roles.length > 1) {
navigation.replace('SelectMembers', data);
}
......
/*
* @Author: XieZhiXiong
* @Date: 2021-10-09 09:59:00
* @LastEditors: XieZhiXiong
* @LastEditTime: 2021-11-19 11:49:51
* @Description: 导航栏
*/
import React from 'react';
import {
View,
ViewStyle,
TouchableOpacity,
Text,
StatusBar,
} from 'react-native';
import Icons from 'react-native-vector-icons/AntDesign';
import { useNavigation } from '@react-navigation/native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import useAppStyle from '../../hooks/useAppStyle';
import styles from './styles';
interface NavBarProps {
/**
* 自定义渲染左侧内容
*/
customRenderLeft?: React.ReactNode;
/**
* 没有左侧内容
*/
noLeft?: Boolean;
/**
* 标题
*/
title?: React.ReactNode;
/**
* 右侧拓展内容
*/
extra?: React.ReactNode;
/**
* 自定义外部容器 style
*/
customStyle?: ViewStyle;
/**
* 默认中间内容部分是平分的,如果想中间内容部分的大小能够占满剩下(不包括右侧胶囊的空间)空间,可开启该属性
*/
greedy?: boolean;
/**
* 返回事件
*/
back?: Function;
/**
* 标题颜色
*/
titleColor?: string;
/**
* 返回icon,默认 ChevronLeft
*/
backIconName?: string;
/**
* 返回icon,默认 #252D37
*/
backIconColor?: string;
}
const Header: React.FC<NavBarProps> = (props: NavBarProps) => {
const {
customRenderLeft,
title,
extra,
customStyle,
greedy = false,
back,
titleColor = '#303133',
backIconName = 'left',
backIconColor = '#252D37',
noLeft,
} = props;
const myStyle = useAppStyle(styles);
const navigation = useNavigation();
const safeInset = useSafeAreaInsets();
const handleBack = () => {
back ? back() : navigation.goBack();
};
return (
<View
style={[
myStyle['nav-bar'],
customStyle,
{
paddingTop: safeInset.top,
height: safeInset.top + 44,
},
]}
>
<StatusBar
translucent
backgroundColor="transparent"
barStyle="dark-content"
/>
<View style={myStyle['nav-bar-left-view']}>
{customRenderLeft === undefined ? (
<TouchableOpacity
style={[
myStyle['nav-bar-left-arrow'],
greedy && myStyle['nav-bar-left-arrow__greedy'],
]}
onPress={handleBack}
activeOpacity={0.8}
>
{noLeft ? null : (
<Icons name={backIconName} size={24} color={backIconColor} />
)}
{/* <Icons name={backIconName} size={24} color={backIconColor} /> */}
</TouchableOpacity>
) : (
<View style={myStyle['nav-bar-left-arrow']}>{customRenderLeft}</View>
)}
<Text
style={[
myStyle['nav-bar-title'],
{ color: titleColor },
greedy && myStyle['nav-bar-title__greedy'],
]}
numberOfLines={1}
>
{title}
</Text>
</View>
<View
style={[
myStyle['nav-bar-right-view'],
greedy && myStyle['nav-bar-right-view__greedy'],
]}
>
{extra}
</View>
</View>
);
};
export default Header;
import { Platform, StyleSheet } from 'react-native';
import { ThemeStyle } from '../../constants/theme';
import themeLayout from '../../constants/theme/layout';
export default (theme: ThemeStyle) =>
StyleSheet.create({
'nav-bar': {
flexDirection: 'row',
alignCtems: 'center',
paddingHorizontal: themeLayout['padding-s'],
backgroundColor: '#FFFFFF',
height: 44,
// backgroundColor: 'red',
},
'nav-bar-left-view': {
flexDirection: 'row',
alignItems: 'center',
flex: 7,
},
'nav-bar-right-view': {
flex: 2,
alignItems: 'flex-end',
justifyContent: 'center',
marginLeft: themeLayout['margin-xs'],
},
'nav-bar-right-view__greedy': {
flex: 0,
},
'nav-bar-left-arrow': {
flex: 2,
},
'nav-bar-left-arrow__greedy': {
flex: 0,
},
'nav-bar-title': {
flex: 5,
paddingHorizontal: themeLayout['padding-s'],
textAlign: 'center',
color: theme.fonts.black1,
fontSize: 18,
fontWeight: Platform.OS === 'ios' ? '500' : '600',
},
'nav-bar-title__greedy': {
flex: 1,
textAlign: 'left',
},
});
import React from 'react';
import {
View,
Text,
TextInput,
Image,
StatusBar,
TouchableOpacity,
ScrollView,
FlatList,
} from 'react-native';
import i18n from '../../../src/locales';
import useAppStyle from '../../hooks/useAppStyle';
import styles from './styles';
import searchImg from '../../../assets/images/search.png';
import useLocale from '../../hooks/useLocale';
import Icons from 'react-native-vector-icons/AntDesign';
const RequireOrder = () => {
const myStyle = useAppStyle(styles);
const { t } = useLocale('order');
const renderItem = () => {
return (
<View
style={{
// backgroundColor: '#fff',
backgroundColor: 'red',
width: '100%',
borderRadius: 8,
paddingVertical: 10,
paddingHorizontal: 12,
flexDirection: 'column',
marginBottom: 10,
}}
>
<Text>88888</Text>
</View>
);
};
return (
<View style={myStyle.container}>
{/* <StatusBar
translucent
backgroundColor="transparent"
barStyle="dark-content"
/> */}
{/* 头部区域 */}
<View
style={{
width: '100%',
flexDirection: 'row',
backgroundColor: '#fff',
alignItems: 'center',
position: 'relative',
}}
>
<Image source={searchImg} style={myStyle.searchImg} />
<View style={[myStyle.searchBox, { width: '65%' }]}>
<TextInput
placeholder={'HAHAHAHAH'}
style={{
fontSize: 14,
width: '90%',
backgroundColor: '#F6F8FA',
borderRadius: 4,
paddingLeft: 25,
}}
/>
</View>
<TouchableOpacity
style={{ backgroundColor: 'transparent' }}
// onPress={() => setVisible(!visible)}
>
<Icons name="filter" size={30} style={{ backgroundColor: '#fff' }} />
</TouchableOpacity>
</View>
{/* tab栏区域 */}
<View style={myStyle.categoryContainer}>
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
style={myStyle.categoryWrap}
>
<Text>6666</Text>
<Text>6666</Text>
<Text>6666</Text>
</ScrollView>
</View>
{/* 内容区域 */}
<View style={myStyle.commodityList}>
<FlatList
data={[22, 33]}
renderItem={renderItem}
scrollEventThrottle={16}
horizontal={false}
// onEndReached={() => handleLoadMore()}
showsVerticalScrollIndicator={false}
// ListFooterComponent={<Loading loading={loading} noMore={!hasMore} />}
// onEndReachedThreshold={0.05}
style={{
flex: 1,
}}
/>
</View>
</View>
);
};
export default RequireOrder;
import { StyleSheet } from 'react-native';
import { ThemeStyle } from '../../constants/theme';
import themeLayout from '../../constants/theme/layout';
export default (theme: ThemeStyle) =>
StyleSheet.create({
container: {
flex: 1,
// backgroundColor: '#F4F5F7',
backgroundColor: 'green',
flexDirection: 'column',
},
nav: {},
search: {
display: 'flex',
width: '60%',
// flexDirection:'row'
},
categoryContainer: {
paddingHorizontal: themeLayout['padding-l'],
alignItems: 'center',
flexDirection: 'row',
backgroundColor: '#FFF',
},
categoryWrap: {
flex: 1,
overflow: 'hidden',
},
categoryItem: {
// width: '25%',
paddingHorizontal: 25,
marginRight: 5,
},
categoryText: {
fontSize: 14,
textAlign: 'center',
paddingVertical: 13,
color: theme.fonts.black2,
fontWeight: '500',
},
categoryTextActive: {
color: '#000',
fontSize: 14,
fontWeight: '500',
paddingVertical: 13,
// paddingBottom: 5,
textAlign: 'center',
borderBottomWidth: 2,
borderBottomColor: theme.colors.primary,
},
commodityList: {
paddingHorizontal: 12,
paddingVertical: 20,
flex: 1,
},
backBtn: {
marginTop: 10,
width: '100%',
// display: 'flex',
justifyContent: 'flex-end',
// backgroundColor: 'red',
},
searchImg: {
width: 18,
height: 18,
backgroundColor: '#F6F8FA',
position: 'absolute',
left: 25,
top: 12,
zIndex: 10,
},
backFlex: {},
backBtnTxet: {
fontSize: 12,
borderRadius: 4,
backgroundColor: '#F5F6F7',
paddingHorizontal: themeLayout['padding-m'],
paddingVertical: themeLayout['padding-xxs'],
},
primaryBtnTxet: {
fontSize: 12,
borderRadius: 4,
color: theme.colors.primary,
backgroundColor: '#F5FBFE',
paddingHorizontal: themeLayout['padding-m'],
paddingVertical: themeLayout['padding-xxs'],
},
searchBox: {
// flex: 0.9,
width: '90%',
height: 40,
borderRadius: 18,
alignItems: 'center',
backgroundColor: '#F7F8FA',
paddingLeft: themeLayout['padding-xs'],
overflow: 'hidden',
},
searchInputStyle: {
flex: 1,
height: 32,
paddingVertical: 0,
marginVertical: 0,
borderBottomWidth: 0,
},
OrderItem: {
backgroundColor: '#fff',
width: '100%',
borderRadius: 8,
paddingVertical: 10,
paddingHorizontal: 12,
flexDirection: 'column',
marginBottom: 10,
},
OrderFlex: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
width: '100%',
},
logo: {
flex: 1,
},
label: {
fontSize: 12,
color: '#252D37',
},
stauts: {
fontSize: 12,
color: '#91959B',
},
OrderMian: {
marginTop: 10,
},
Card: {
flex: 1,
overflow: 'hidden',
flexDirection: 'column',
justifyContent: 'space-between',
},
CardText: {
fontSize: 12,
},
tag: {
fontSize: 12,
color: '#91959B',
},
Sku: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
},
SkuText: {
display: 'flex',
alignItems: 'flex-end',
},
num: {
fontSize: 12,
},
Totalprice: {
marginTop: 10,
display: 'flex',
justifyContent: 'flex-end',
alignItems: 'flex-end',
},
List: {
marginTop: 10,
flex: 1,
overflow: 'hidden',
},
countDown: {
display: 'flex',
flexDirection: 'column',
// alignItems: 'center',
},
countDownTitle: {
fontSize: 12,
fontWeight: '600',
textAlign: 'left',
},
time: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
},
timeUnit: {
backgroundColor: '#fff',
color: '#5C626A',
padding: 2,
borderRadius: 2,
fontSize: 12,
},
splitCode: {
fontSize: 12,
color: '#5C626A',
marginHorizontal: 1,
fontWeight: '600',
},
});
......@@ -29,6 +29,7 @@ const SelectMembers = (props: { route: any; navigation: any }) => {
const check = (index: number, id: any) => {
setIndex(index);
};
return (
<View style={styles.container}>
<NavBar title="选择角色" noLeft={!isCanGoBack} />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment