Commit 5dec9443 by 杨周龙

优化代码

1 parent 71e5cdaf
......@@ -3,3 +3,5 @@ lib/
babel.config.js
metro.config.js
prod.js
__test*
mock/
{
"env": {
"browser": true,
"es2021": true,
"es6": true,
"node": true,
"mocha": true,
"jest": true,
......@@ -19,7 +19,7 @@
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"ecmaVersion": 8,
"sourceType": "module"
},
"plugins": [
......
......@@ -18,19 +18,21 @@ import { APP } from './src/config'
import SplashScreen from 'react-native-splash-screen'
import store from './src/store'
// 阻止系统缩放
TextInput['defaultProps'] = Object.assign({}, TextInput['defaultProps'], { allowFontScaling: false })
Text['defaultProps'] = Object.assign({}, Text['defaultProps'], { allowFontScaling: false })
//阻止系统缩放
TextInput.defaultProps = Object.assign({}, TextInput.defaultProps, { allowFontScaling: false })
Text.defaultProps = Object.assign({}, Text.defaultProps, { allowFontScaling: false })
const Page = () => {
const Page: React.FC = () => {
useLayoutEffect(() => {
SplashScreen.hide()
}, [])
useEffect(() => {
(async () => Update(`${APP.appAdminUrl}/api/app/version/${APP.APP_CODE}`, await getVersionCode()))()
const get = async (): Promise<void> => {
Update(`${APP.appAdminUrl}/api/app/version/${APP.APP_CODE}`, await getVersionCode())
return
}
get()
}, [])
return (
......
import { FETCH } from '../libs/fetch'
import { APP } from '../config/app'
import { CancelTokenSource } from 'axios'
export const getTopVersion = (successCall, errorCall): CancelTokenSource => {
return FETCH.sourceRequest({
url: `${APP.appAdminUrl}/api/app/version/${APP.APP_CODE}`
}, successCall, errorCall)
}
/** 获取版本更新列表 */
export const getVersionList = (successCall, errorCall): CancelTokenSource => {
return FETCH.sourceRequest({
url: `${APP.appAdminUrl}/api/app_version/${APP.APP_CODE}`
}, successCall, errorCall)
}
import { StyleSheet } from 'react-native'
import { setUnit } from '../../libs/utils'
import { Alert } from '../../theme/colors'
const styles = StyleSheet.create({
content: {
color: '#333',
color: Alert.content,
fontSize: setUnit(30)
},
privacy: {
color: '#1892FF',
color: Alert.privacy,
fontSize: setUnit(30)
}
})
......
......@@ -7,29 +7,28 @@ import React, { useCallback, useEffect, useState } from 'react'
import { Text, Linking } from 'react-native'
import { Modal, Storage } from 'react-native-mb-ui'
import { APP } from '../../config'
import { setUnit } from '../../libs/utils'
import { styles } from './style'
const PrivacyAlert = () => {
const PrivacyAlert: React.FC = () => {
const [visible, setVisible] = useState(false)
useEffect(() => {
showPrivacy()
}, [])
const goPrivacy = useCallback(() => Linking.openURL(APP.privacyLink), [])
const showPrivacy = async () => {
const showPrivacy = async (): Promise<void> => {
const notFirst = await Storage.getItem(APP.notFirstInstall)
if (notFirst === null)
setVisible(true)
}
showPrivacy()
}, [])
const goPrivacy = useCallback(() => Linking.openURL(APP.privacyLink), [])
const onOk = useCallback(() => {
setVisible(false)
Storage.setItem(APP.notFirstInstall, true)
})
}, [])
return (
<Modal
......@@ -37,7 +36,6 @@ const PrivacyAlert = () => {
title='温馨提示'
onClose={onOk}
button={[{ text: '我知道了' }]}
style={{ width: setUnit(560) }}
content={
<Text style={styles.content}>{`欢迎来到信巴迪商品交易所, 感谢您对信巴迪的信任和支持!\n`}
为了提供给您更加优质和个性化的服务, 我们会收集或使用您的搜索、浏览与购买等信息。具体内容请您详阅
......
const isBuildDebug = process.env.NODE_ENV === 'development' || false
const APP = {
appName: '',
/** @description token存储的名称 */
tokenName: 'jwt',
/** @description token在存储的时长,单位 天 */
tokenExpires: 7,
/**@description 初始的HTTP请求的全局header头*/
/** @description 初始的HTTP请求的全局header头*/
header: {},
/**@description API基础请求地址*/
baseUrl: isBuildDebug ? `https://gateway-dev.b2bwings.com/` : 'https://gateway.b2bwings.com' ,
/** @description API基础请求地址*/
baseUrl: isBuildDebug ? `https://gateway-dev.b2bwings.com/` : 'https://gateway.b2bwings.com',
/**@description 应用的登陆API的PATH*/
/** @description 应用的登陆API的PATH*/
loginPath: '/user/sysLogin/login',
/**@description 401页面地址,用于提醒用户登陆状态失效*/
/** @description 401页面地址,用于提醒用户登陆状态失效*/
error404: '/404',
/**@description 静态资源目录,必须。用于菜单图标显示*/
/** @description 静态资源目录,必须。用于菜单图标显示*/
STATIS_URL: 'https://b2bwings-system-image.oss-cn-shenzhen.aliyuncs.com/',
/**@description 静态资源目录,必须。图片地址*/
/** @description 静态资源目录,必须。图片地址*/
IMG_URL: 'https://images.b2bwings.com/',
/**@description tab按钮颜色配置*/
/** @description tab按钮颜色配置*/
tabConfig: {
activeTintColor: '#F77116',
inactiveTintColor: '#434343'
......@@ -53,22 +54,22 @@ const APP = {
/** @description 配置发送邮件接口中的跳转链接(link参数),重置邮箱用 */
emailLinkSetEmail: isBuildDebug ? 'https://xbd-dev.b2bwings.com/setMail' : 'https://xbd.b2bwings.com/setMail',
/**@description 用户信息本地存储名称 */
/** @description 用户信息本地存储名称 */
authCacheName: '_auth',
/**@description 查询版本更新的API地址 */
/** @description 查询版本更新的API地址 */
updateApi: isBuildDebug ? 'http://app-admin-dev.b2bwings.com/api/app/version/' : 'http://app-admin.b2bwings.com/api/app/version/',
/**@description app版本管理url */
/** @description app版本管理url */
appAdminUrl: isBuildDebug ? 'http://app-admin-dev.b2bwings.com' : 'http://app-admin.b2bwings.com',
/**@public APP编码 */
/** @public APP编码 */
APP_CODE: isBuildDebug ? '' : '',
/**@description 隐私政策链接 */
/** @description 隐私政策链接 */
privacyLink: 'https://app-static.b2bwings.com/static/page/privacy-policy/PrivacyPolicy.html',
/**@description 是否首次安装进入app */
/** @description 是否首次安装进入app */
notFirstInstall: '_not_first_install'
}
......
......@@ -5,21 +5,21 @@
*/
class CheckUtil {
/**校验邮箱格式 */
static isEmail(str) {
let reg = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
/** 校验邮箱格式 */
static isEmail(str): boolean {
const reg = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
return reg.test(str)
}
/**校验手机号 */
static isMobile(str) {
let reg = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/
/** 校验手机号 */
static isMobile(str): boolean {
const reg = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/
return reg.test(str)
}
/**校验用户账号 */
static checkAccount(str) {
let reg = /^\d{9}$/
/** 校验用户账号 */
static checkAccount(str): boolean {
const reg = /^\d{9}$/
return reg.test(str)
}
}
......
import http from './http-request'
import Http from './http-request'
import { APP } from '../config'
const FETCH = new http(APP.baseUrl)
const FETCH = new Http(APP.baseUrl)
export { FETCH }
......@@ -4,7 +4,7 @@
* @param {String|Number} num
* @returns {String}
*/
export function formatPhoneNo(num) {
export function formatPhoneNo(num): string {
return num.toString().replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}
......@@ -12,16 +12,16 @@ export function formatPhoneNo(num) {
* 格式化Email为 h****@b2bwings.com 的格式
* @param {*} str
*/
export function formatEmail(str) {
if (!str) {
export function formatEmail(str): string {
if (!str)
return ''
}
let i = str.indexOf('@')
if (i <= 0) {
const i = str.indexOf('@')
if (i <= 0)
return ''
}
let start = str.substring(0, 1)
let end = str.substring(i)
const start = str.substring(0, 1)
const end = str.substring(i)
return `${start}****${end}`
}
......@@ -31,13 +31,10 @@ export function formatEmail(str) {
* @author sheng
* @date 2020/04/26
*/
export function thousandBitSeparator(num) {
return num && (num.toString().indexOf('.') != -1
? num.toString().replace(/(\d)(?=(\d{3})+\.)/g, function ($0, $1) {
return $1 + ","
}) : num.toString().replace(/(\d)(?=(\d{3})+$)/g, function ($0, $1) {
return $1 + ","
}))
export function thousandBitSeparator(num): string {
return num && (num.toString().indexOf('.') !== -1
? num.toString().replace(/(\d)(?=(\d{3})+\.)/g, function ($0, $1) { return $1 + ","}) :
num.toString().replace(/(\d)(?=(\d{3})+$)/g, function ($0, $1) { return $1 + "," }))
}
/**
......@@ -45,7 +42,7 @@ export function thousandBitSeparator(num) {
* @param {number} stmp 毫秒时间戳
* @returns {number} 毫秒时间戳
*/
export function getDateStartTime(stmp) {
export function getDateStartTime(stmp): number {
return new Date(new Date(Number(stmp)).toLocaleDateString()).getTime()
}
......@@ -54,7 +51,7 @@ export function getDateStartTime(stmp) {
* @param {date} date 毫秒时间戳
* @returns {number} 毫秒时间戳
*/
export function getDateEndTime(stmp) {
export function getDateEndTime(stmp): Date {
return new Date(
new Date(new Date(Number(stmp)).toLocaleDateString()).getTime() +
24 * 60 * 60 * 1000 -
......@@ -67,9 +64,9 @@ export function getDateEndTime(stmp) {
* @param {*} fmt
* @param {*} time 毫秒时间戳
*/
export function dateFormat(fmt, time) {
export function dateFormat(fmt, time): string {
let ret
let newDate = new Date() //实例化一个Date对象
const newDate = new Date() // 实例化一个Date对象
newDate.setTime(time)
const opt = {
"Y+": newDate.getFullYear().toString(), // 年
......@@ -79,11 +76,12 @@ export function dateFormat(fmt, time) {
"m+": newDate.getMinutes().toString(), // 分
"s+": newDate.getSeconds().toString() // 秒
}
for (let k in opt) {
for (const k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt)
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1) ?
(opt[k]) : (opt[k].padStart(ret[1].length, "0")))
fmt = fmt.replace(ret[1], (ret[1].length === 1) ?
(opt[k]) :
(opt[k].padStart(ret[1].length, "0")))
}
}
return fmt
......@@ -95,27 +93,25 @@ export function dateFormat(fmt, time) {
* @author sheng
* @date 2020/06/23
*/
export function formatQuery(query) {
if (typeof query !== 'object') {
return ''
}
let params = []
export function formatQuery(query): string {
if (typeof query !== 'object') return ''
const params = []
if (query) {
for (let item in query) {
let vals = query[item]
if (vals !== undefined) {
params.push(item + '=' + query[item])
}
for (const item in query) {
const vals = query[item]
if (vals !== undefined) params.push(item + '=' + query[item])
}
}
return params.length ? '?' + params.join('&') : ''
}
/**minutes */
export function getRemainTime(minutes) {
/**剩余小时 */
let hour = Math.floor(minutes / 60)
/**剩余分钟 */
let min = Math.round(minutes % 60)
/** minutes */
export function getRemainTime(minutes): string {
/** 剩余小时 */
const hour = Math.floor(minutes / 60)
/** 剩余分钟 */
const min = Math.round(minutes % 60)
return hour <= 0 ? `${min}分钟` : `${hour}小时${min}分钟`
}
import axios from 'axios'
import axios, { AxiosInstance, AxiosResponse, CancelTokenSource } from 'axios'
import { APP } from '../config'
import { getStore } from '../store/context'
import { navigate } from '../router/ref'
import { ModalManager } from 'react-native-mb-ui'
class HttpRequest {
public instance = null
public instance: AxiosInstance = null
public header = null
constructor(private baseUrl) {
this.header = { ...APP.header }
this.init()
}
/**初始化 */
init() {
let instance = axios.create({ baseURL: this.baseUrl, headers: this.header })
/** 初始化 */
init(): void {
const instance = axios.create({ baseURL: this.baseUrl, headers: this.header })
this.interceptors(instance)
this.instance = instance
}
/**绑定请求拦截器 */
interceptors(instance) {
/** 绑定请求拦截器 */
interceptors(instance): void {
// 请求
instance.interceptors.request.use(config => {
return config
......@@ -34,14 +34,16 @@ class HttpRequest {
return this.handleRespone(res)
}, error => {
/* eslint-disable no-console */
if (process.env.NODE_ENV === 'development') console.warn(error)
return Promise.reject(error.response ? `发生错误,错误代码:${error.response.status};详情:${error.response.message || ''}` : error.message + "")
})
}
/**请求 */
async request(options) {
/** 请求 */
async request(options): Promise<AxiosResponse<unknown>> {
return this.instance(options)
}
......@@ -51,8 +53,8 @@ class HttpRequest {
* @param {function} successCallback
* @param {function} errorCallback
*/
sourceRequest(options, successCallback, errorCallback) {
const source = axios.CancelToken.source()
sourceRequest(options, successCallback, errorCallback): CancelTokenSource {
const source: CancelTokenSource = axios.CancelToken.source()
options = Object.assign(options, { cancelToken: source.token })
this.instance(options)
.then(successCallback)
......@@ -66,7 +68,7 @@ class HttpRequest {
* @param {string} key
* @param {any} value
*/
setHeader(key, value) {
setHeader(key, value): void {
this.instance.defaults.headers.common[key] = value
}
......@@ -74,7 +76,7 @@ class HttpRequest {
* 设置URL
* @param {string} url
*/
setBaseUrl(url) {
setBaseUrl(url): void {
this.instance.defaults.baseURL = url
}
......@@ -82,10 +84,10 @@ class HttpRequest {
* 处理响用体
* @param {response} res
*/
handleRespone(res) {
handleRespone(res): Promise<string| unknown> {
const { code, message, data } = res.data
switch (code) {
case 200: 1590
case 200:
return data
case 401:
ModalManager.alert({ title: '提示', content: '登陆状态失效,请重新登陆' })
......@@ -99,7 +101,7 @@ class HttpRequest {
}
}
resetState() {
resetState(): void {
getStore().dispatch.user.reset()
getStore().dispatch.me.reset()
navigate('Login')
......
......@@ -16,18 +16,18 @@ const UI_SACEL = WINDOWS.width / UI_WIDTH
* 设置px单位
* @param {*} num
*/
export const setUnit = num => {
export const setUnit = (num): number => {
return num * UI_SACEL
}
/** 获取版本号 */
export const getVersionCode = async () => await DeviceInfo.getBuildNumber()
export const getVersionCode = async (): Promise<number> => Number(await DeviceInfo.getBuildNumber())
/** 获取版本名称 */
export const getVersion = async () => await DeviceInfo.getVersion()
export const getVersion = async (): Promise<string> => DeviceInfo.getVersion()
/** 获取屏幕高度 */
export const getHeight = () => WINDOWS.height
export const getHeight = (): number => WINDOWS.height
/**
......@@ -35,16 +35,16 @@ export const getHeight = () => WINDOWS.height
* @param {string} phone
* @returns {Object}
*/
export const checkPhoneAndCode = (phone, code) => {
if (!phone.trim().length) {
export const checkPhoneAndCode = (phone, code): { status: number; msg: string } => {
if (!phone.trim().length)
return { status: 0, msg: '手机号不能为空' }
}
if (!CheckUtil.isMobile(phone)) {
if (!CheckUtil.isMobile(phone))
return { status: 0, msg: '手机号格式不正确' }
}
if (!code.trim().length) {
if (!code.trim().length)
return { status: 0, msg: '验证码不能为空' }
}
return { status: 1, msg: '' }
}
......@@ -54,16 +54,16 @@ export const checkPhoneAndCode = (phone, code) => {
* @param {*} confirmEmail
* @returns {Object}
*/
export const checkEmails = (email, confirmEmail) => {
if (!email.trim().length) {
export const checkEmails = (email, confirmEmail): { status: number; msg: string } => {
if (!email.trim().length)
return { status: 0, msg: '邮箱不能为空' }
}
if (!CheckUtil.isEmail(email)) {
if (!CheckUtil.isEmail(email))
return { status: 0, msg: '邮箱格式不正确' }
}
if (email !== confirmEmail) {
if (email !== confirmEmail)
return { status: 0, msg: '两次输入邮箱不一致' }
}
return { status: 1, msg: '' }
}
......@@ -71,8 +71,8 @@ export const checkEmails = (email, confirmEmail) => {
* 判断token是否过期
* @param {*} saveTime token存储时间
*/
export const isTokenExpired = (saveTime) => {
let now = new Date().getTime()
export const isTokenExpired = (saveTime): boolean => {
const now = new Date().getTime()
return now - saveTime > APP.tokenExpires * 24 * 60 * 60 * 1000
}
......@@ -81,7 +81,7 @@ export const isTokenExpired = (saveTime) => {
* @param {*} jwt
* @param {*} sessionId
*/
export const setHeader = (jwt, sessionId) => {
export const setHeader = (jwt, sessionId): void => {
FETCH.setHeader('Authorization', jwt)
FETCH.setHeader('Sessionid', sessionId)
}
......@@ -91,14 +91,42 @@ export const setHeader = (jwt, sessionId) => {
* 重置路由栈
* @param {*} navigation
*/
export const resetRoutes = navigation => {
export const resetRoutes = (navigation): void => {
navigation.dispatch(
CommonActions.reset({
index: 1,
routes: [
{ name: 'Index' },
{ name: 'Login' }
],
]
})
)
}
/**
* 日期格式化
* @param {*} fmt
* @param {*} time 毫秒时间戳
*/
export function dateFormat(fmt, time): string {
let ret
const newDate: Date = new Date() // 实例化一个Date对象
newDate.setTime(time)
const opt = {
"Y+": newDate.getFullYear().toString(), // 年
"M+": (newDate.getMonth() + 1).toString(), // 月
"D+": newDate.getDate().toString(), // 日
"h+": newDate.getHours().toString(), // 时
"m+": newDate.getMinutes().toString(), // 分
"s+": newDate.getSeconds().toString() // 秒
}
for (const k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt)
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length === 1) ?
(opt[k]) :
(opt[k].padStart(ret[1].length, "0")))
}
}
return fmt
}
......@@ -5,7 +5,6 @@ import { CardStyleInterpolators } from '@react-navigation/stack'
import { setUnit } from '../libs/utils'
import { Icons } from '../assets/icons'
const headerStyle = {
headerTitleAlign: 'center', // 文字居中
headerStyle: {
......@@ -19,21 +18,13 @@ const headerStyle = {
fontSize: setUnit(38)
},
headerShown: false,
headerBackImage: Platform.OS === 'ios' ? undefined : () => <Icons name="fanhui" size={setUnit(33)} color="#262626" />, // 标题栏返回图标
headerBackImage: Platform.OS === 'ios' ? undefined : (): React.ReactNode => <Icons name="fanhui" size={setUnit(33)} color="#262626" />, // 标题栏返回图标
headerBackTitleVisible: false,
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, // 设置左右滑动
gestureDirection: 'horizontal', // 初始化右滑手势配置
gestureEnabled: true, // 启用右滑返回
gestureResponseDistance: { horizontal: 20 }
gestureResponseDistance: { horizontal: 20 },
headerTitleAllowFontScaling: false
}
const headerRightButton = StyleSheet.create({
text: {
fontWeight: '400',
fontSize: setUnit(29),
color: '#6c6c6c',
paddingRight: setUnit(25)
}
})
export { headerStyle, headerRightButton }
export { headerStyle }
......@@ -5,7 +5,7 @@ import { Route } from './route'
import { navigateRef } from './ref'
/** 路由视图 */
const RouterView = () => {
const RouterView: React.FC = () => {
return (
<NavigationContainer ref={navigateRef}>
<Route />
......
......@@ -8,6 +8,6 @@ export const navigateRef: React.RefObject<NavigationContainerRef> = React.create
* @param {*} name
* @param {*} params
*/
export const navigate = (name: string, params: Record<string, unknown> | undefined): void => {
export const navigate = (name: string, params?: Record<string, unknown> | undefined): void => {
if (navigateRef.current) navigateRef.current.navigate(name, params)
}
// 路由配置
import React from 'react'
import { createStackNavigator } from '@react-navigation/stack'
import { createStackNavigator, StackNavigationOptions } from '@react-navigation/stack'
import { headerStyle } from '../config'
import TabRouter from '../tab'
......@@ -9,20 +9,54 @@ import Privacy from '../../views/about/privacy'
import Features from '../../views/about/features'
import FeatureDetail from '../../views/about/feature-detail'
interface Route {
name: string;
options?: StackNavigationOptions;
component: React.FC;
}
const Routes: Route[] = [
{
name: 'Index',
options: { title: '首页' },
component: TabRouter
},
{
name: 'About',
options: { title: '', headerShown: true, headerStyle: { elevation: 0, backgroundColor: '#fff' }},
component: About
},
{
name: 'Privacy',
component: Privacy,
options: { title: '隐私协议', headerShown: true }
},
{
name: 'Features',
component: Features,
options: { headerShown: true, title: '功能介绍' }
},
{
name: 'FeatureDetail',
component: FeatureDetail,
options: { headerShown: true, title: '', headerStyle: { elevation: 0, backgroundColor: '#fff' } }
}
]
export type RouteList = {
Index: undefined;
About: undefined;
Privacy: undefined;
Features: undefined;
FeatureDetail: { content?: string };
}
const Stack = createStackNavigator()
const Route = () => {
const Route: React.FC = () => {
return (
<Stack.Navigator initialRouteName="Index" screenOptions={{ ...headerStyle }} mode={'card'} >
<Stack.Screen name="Index" options={{ title: '首页' }} component={TabRouter} />
{/* 关于 */}
<Stack.Screen name='About' options={{ title: '', headerShown: true, headerStyle: { elevation: 0, backgroundColor: '#fff' } }} component={About} />
{/* 隐私协议与政策 */}
<Stack.Screen name='Privacy' options={{ title: '隐私协议', headerShown: true }} component={Privacy} />
{/* 功能介绍 */}
<Stack.Screen name='Features' options={{ headerShown: true, title: '功能介绍' }} component={Features} />
{/* 功能介绍 */}
<Stack.Screen name='FeatureDetail' options={{ headerShown: true, title: '', headerStyle: { elevation: 0, backgroundColor: '#fff' } }} component={FeatureDetail} />
<Stack.Navigator initialRouteName="Index" screenOptions={{ ...headerStyle as StackNavigationOptions }} mode={'card'} >
{Routes.map(item => <Stack.Screen {...item} key={item.name} />)}
</Stack.Navigator>
)
}
......
// 底部tab路由配置
import React from 'react'
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import { BottomTabNavigationOptions, createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import { APP } from '../../config'
import Home from '../../views/home'
const Tab = createBottomTabNavigator() // 创建tab栈堆
/** 选项配置函数 */
const tabScreen = ({ route }) => ({
tabBarIcon: ({ focused, size }) => {
const tabScreen = ({ route }): BottomTabNavigationOptions => ({
tabBarIcon: (): React.ReactNode | null => {
switch (route.name) {
case 'home':
return null
default:
return null
}
}
})
const TabRoute = () => {
const TabRoute: React.FC = () => {
return (
<Tab.Navigator backBehavior={'none'} screenOptions={tabScreen} tabBarOptions={APP.tabConfig}>
<Tab.Screen options={{ title: '首页' }} name="home" component={Home} />
......
var STORE_CONTEXT = null
/* eslint-disable @typescript-eslint/explicit-function-return-type */
export const createConetxt = store => STORE_CONTEXT = store
let STORE_CONTEXT = null
export const createConetxt = (store) => STORE_CONTEXT = store
export const getStore = () => STORE_CONTEXT
export const Alert = {
content: '#333',
privacy: '#1892FF'
}
export const View = {
background: '#fff'
}
export const desc = '#434343'
export const subTitle = '#8c8c8c'
export const title = '#262626'
export const tips = '#6292D0'
import { StyleSheet } from 'react-native'
import { setUnit } from '../../../libs/utils'
import { View, desc } from '../../../theme/colors'
const styles = StyleSheet.create({
container: {
backgroundColor: View.background,
flex: 1,
padding: setUnit(32),
backgroundColor: '#fff'
padding: setUnit(32)
},
desc: {
color: '#434343',
color: desc,
fontSize: setUnit(24)
}
})
......
......@@ -8,18 +8,23 @@ import { View, Text } from 'react-native'
import { styles } from './style'
import { Icons } from '../../../assets/icons'
import { setUnit } from '../../../libs/utils'
import { NavigationProp, RouteProp } from '@react-navigation/native'
import { RouteList } from '../../../router/route'
const Page = ({ route, navigation }) => {
const Page: React.FC<{
route: RouteProp<RouteList, 'FeatureDetail'>;
navigation: NavigationProp<RouteList>;
}> = ({ route, navigation }) => {
useLayoutEffect(() => {
navigation.setOptions({
headerLeft: () => (
headerLeft: (): React.ReactNode => (
<Icons
name='guanbi'
color='#555'
size={setUnit(32)}
style={{ paddingHorizontal: setUnit(24) }}
onPress={() => navigation.goBack()}
onPress={(): void => navigation.goBack()}
/>
)
})
......
import { StyleSheet } from 'react-native'
import { setUnit } from '../../../libs/utils'
import { View, desc, subTitle } from '../../../theme/colors'
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff'
backgroundColor: View.background,
flex: 1
},
item: {
paddingHorizontal: setUnit(25),
paddingVertical: setUnit(16),
containerStyle: {
alignItems: 'center',
flexDirection: 'row'
flex: 1,
justifyContent: 'center'
},
content: {
flex: 1
},
title: {
fontSize: setUnit(28),
color: '#434343'
emptyText: {
color: desc,
fontSize: setUnit(33)
},
item: {
alignItems: 'center',
flexDirection: 'row',
paddingHorizontal: setUnit(25),
paddingVertical: setUnit(16)
},
subtitle: {
color: '#8c8c8c',
color: subTitle,
fontSize: setUnit(24)
},
emptyText: {
fontSize: setUnit(33),
color: '#434343'
},
containerStyle: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
title: {
color: desc,
fontSize: setUnit(28)
}
})
......
/* eslint-disable @typescript-eslint/camelcase */
/**
* @author sheng
* @description 功能介绍列表页
* @date 2020/09/03
*/
import React, { memo, useState, useLayoutEffect, useCallback, useEffect } from 'react'
import React, { memo, useState, useLayoutEffect, useEffect } from 'react'
import { Text, View, FlatList, Pressable, InteractionManager } from 'react-native'
import { Icons } from '../../../assets/icons'
import { styles } from './style'
import { dateFormat, setUnit } from '../../../libs/utils'
import { Toast, Divider, Empty } from 'react-native-mb-ui'
import { Toast, Divider, Empty, ModalManager } from 'react-native-mb-ui'
import { getVersionList } from '../../../api/version'
import { NavigationProp } from '@react-navigation/native'
import { RouteList } from '../../../router/route'
const Item = memo(({ navigation, item }) => {
const { version, create_time, remark } = item
interface Items {
version: string;
create_time: number;
remark: string;
id: number;
}
interface ItemProp {
onClick: () => void;
item: Items;
}
const Item = memo(({ onClick, item }: ItemProp) => {
const { version, create_time } = item
return (
<>
<Pressable
style={styles.item}
android_ripple={{ color: '#eee' }}
onPress={() => { navigation.navigate('FeatureDetail', { content: remark || '' }) }}
onPress={onClick}
>
<View style={styles.content}>
<Text style={styles.title}>商品交易所{version}主要更新</Text>
......@@ -32,7 +47,7 @@ const Item = memo(({ navigation, item }) => {
})
let http
const Page = ({ navigation }) => {
const Page: React.FC<{ navigation: NavigationProp<RouteList> }> = ({ navigation }) => {
const [records, setRecords] = useState([])
useLayoutEffect(() => {
......@@ -43,20 +58,14 @@ const Page = ({ navigation }) => {
color='#555'
size={setUnit(32)}
style={{ paddingHorizontal: setUnit(24) }}
onPress={() => navigation.goBack()}
onPress={(): void => navigation.goBack()}
/>
)
})
}, [navigation])
useEffect(() => {
fetchData()
return () => {
http && http.cancel()
}
}, [])
const fetchData = useCallback(() => {
const fetchData = (): void => {
InteractionManager.runAfterInteractions(() => {
Toast.loading()
http = getVersionList(res => {
......@@ -64,19 +73,34 @@ const Page = ({ navigation }) => {
Toast.hideLoading()
}, err => {
Toast.hideLoading()
alert(err)
ModalManager.alert({
title: '错误',
content: err
})
})
})
}
fetchData()
return (): void => {
if (http) http.cancel()
}
}, [])
return (
<View style={styles.container}>
<FlatList
data={records}
contentContainerStyle={!records.length ? styles.containerStyle : {}}
keyExtractor={(item, index) => item.id?.toString()}
renderItem={({ item }) => <Item navigation={navigation} item={item} />}
ListEmptyComponent={() => <Empty style={{ paddingTop: 100 }} />}
keyExtractor={(item: Items): string => item.id?.toString()}
renderItem={({ item }: { item: Items }): React.ReactElement => (
<Item
onClick={(): void => navigation.navigate('FeatureDetail', { content: item.remark || '' })}
item={item}
/>
)}
ListEmptyComponent={(): React.ReactElement => <Empty style={{ paddingTop: 100 }} />}
/>
</View>
)
......
......@@ -2,13 +2,13 @@ import { StyleSheet } from 'react-native'
const styles = StyleSheet.create({
wrapper: {
position: 'absolute',
left: 0,
alignItems: 'center',
bottom: 0,
right: 0,
top: 0,
justifyContent: 'center',
alignItems: 'center'
left: 0,
position: 'absolute',
right: 0,
top: 0
}
})
......
......@@ -3,19 +3,20 @@
* @description 隐私政策
* @date 2020/09/03
*/
import { NavigationProp } from '@react-navigation/native'
import React, { useEffect, useState } from 'react'
import { View, ActivityIndicator } from 'react-native'
import WebView from 'react-native-webview'
import { Colors } from '../../../commo/theme'
import { APP } from '../../../config'
import { RouteList } from '../../../router/route'
import { styles } from './style'
const Page = ({ navigation }) => {
const Page: React.FC<{ navigation: NavigationProp<RouteList> }> = ({ navigation }) => {
const [show, setShow] = useState(false)
const indicator = () => {
const indicator = (): React.ReactNode => {
return (
<View style={styles.wrapper}>
<ActivityIndicator size={'large'} color={Colors.primary} />
<ActivityIndicator size={'large'} />
</View>
)
}
......@@ -29,7 +30,7 @@ const Page = ({ navigation }) => {
navigation.goBack()
})
return () => remove && remove()
return (): void => remove && remove()
}, [])
return (
......
import { StyleSheet } from 'react-native'
import { setUnit } from '../../libs/utils'
import { subTitle, View, title, tips } from '../../theme/colors'
const styles = StyleSheet.create({
center: {
marginTop: setUnit(56)
},
container: {
flex: 1,
backgroundColor: '#fff'
backgroundColor: View.background,
flex: 1
},
copyright: {
color: subTitle,
marginTop: setUnit(24),
textAlign: 'center'
},
footer: {
alignItems: 'center',
paddingBottom: setUnit(48)
},
header: {
marginTop: setUnit(112),
alignItems: 'center'
alignItems: 'center',
marginTop: setUnit(112)
},
logo: {
width: setUnit(160),
height: setUnit(160)
height: setUnit(160),
width: setUnit(160)
},
name: {
marginTop: setUnit(32),
color: '#262626',
color: title,
fontSize: setUnit(40),
fontWeight: '500',
fontSize: setUnit(40)
},
version: {
marginTop: setUnit(12),
color: '#262626',
fontSize: setUnit(32)
},
center: {
marginTop: setUnit(56)
},
footer: {
alignItems: 'center',
paddingBottom: setUnit(48)
marginTop: setUnit(32)
},
private: {
fontSize: setUnit(26),
color: '#6292D0'
color: tips,
fontSize: setUnit(26)
},
copyright: {
marginTop: setUnit(24),
textAlign: 'center',
color: '#8c8c8c',
version: {
color: title,
fontSize: setUnit(32),
marginTop: setUnit(12)
}
})
......
/* eslint-disable @typescript-eslint/camelcase */
/**
* @author sheng
* @description 关于信巴迪
......@@ -11,30 +12,38 @@ import { styles } from './style'
import { getVersion, getVersionCode, setUnit } from '../../libs/utils'
import { getTopVersion } from '../../api/version'
import { APP } from '../../config'
import { RouteList } from '../../router/route'
import { NavigationProp } from '@react-navigation/native'
let http
const Page = ({ navigation }) => {
const Page: React.FC<{ navigation: NavigationProp<RouteList, 'About'> }> = ({ navigation }) => {
const [version, setVersion] = useState('')
const downUrl = useRef('')
useEffect(() => {
getCurVersion()
return () => http && http.cancel()
(async (): Promise<void> => {
const version = await getVersion()
setVersion(version)
})()
return (): void => http && http.cancel()
}, [])
/** 打开下载链接 */
const openDown = () => {
const openDown = (): void => {
Linking.openURL(downUrl.current)
.then(() => { })
.catch(err => Toast.info('打开下载地址失败,请重试'))
.catch(() => Toast.info('打开下载地址失败,请重试'))
}
const getUpdate = async () => {
const getUpdate = async (): Promise<void> => {
const versionCode = await getVersionCode()
http = getTopVersion(res => {
if (res === null) return Toast.info('已是最新版本')
if (res === null) {
Toast.info('已是最新版本')
return
}
const { version_code, down, version } = res
downUrl.current = down
......@@ -47,19 +56,13 @@ const Page = ({ navigation }) => {
{ text: '立即更新', onPress: openDown }
]
})
} else {
} else
Toast.info('已是最新版本')
}
}, err => Toast.info(err))
}
/**获取当前版本号 */
const getCurVersion = useCallback(async () => {
const version = await getVersion()
setVersion(version)
}, [])
const goPage = useCallback(() => {
navigation.navigate('Privacy')
}, [navigation])
......@@ -77,7 +80,7 @@ const Page = ({ navigation }) => {
</View>
<View style={styles.center}>
<Divider style={{ marginHorizontal: setUnit(25) }} />
<Cell label={'功能介绍'} onClick={() => navigation.navigate('Features')} />
<Cell label={'功能介绍'} onClick={(): void => navigation.navigate('Features')} />
<Cell label={'版本更新'} onClick={getUpdate} />
</View>
</View>
......
import React from 'react'
import { View, Text } from 'react-native'
import { styles } from './styles'
import { name as appName } from '../../../app.json';
import { name as appName } from '../../../app.json'
import { NavigationProp } from '@react-navigation/native'
import { RouteList } from '../../router/route'
const Page = ({ navigation }) => {
const Page: React.FC<{ navigation: NavigationProp<RouteList> }> = ({ navigation }) => {
return (
<View >
<Text style={styles.title} >{appName}</Text>
<Text style={styles.title} onPress={() => navigation.navigate('About')} >查看APP详细信息</Text>
<Text style={styles.title} onPress={(): void => navigation.navigate('About')} >查看APP详细信息</Text>
</View>
)
}
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!