Browse Source

钱包模块

panhui 5 years ago
parent
commit
f6b8e38e03

+ 13 - 8
components/ImagePicker.tsx

@@ -42,15 +42,20 @@ const _pickImage = (aspect) => {
     });
 };
 
-export default function ImagePickerCom(props) {
-  const { aspect, img, setImg, cancelEvent, h, w } = props;
-
+export default function ImagePickerCom({
+  aspect = [1, 1],
+  img,
+  setImg,
+  cancelEvent,
+  h = 67,
+  w = 67,
+}) {
   return (
     <Div mr="sm" mb="sm">
       <Button
         bg="yellow200"
-        h={h || 67}
-        w={w || 67}
+        h={h}
+        w={w}
         rounded="xs"
         onPress={() => {
           _pickImage(aspect || [1, 1])
@@ -70,8 +75,8 @@ export default function ImagePickerCom(props) {
         {!img && <Icon name="plus" color="white" fontSize="4xl" />}
         {!!img && (
           <Image
-            h={67}
-            w={67}
+            h={h}
+            w={w}
             rounded="xs"
             source={{
               uri: img,
@@ -79,7 +84,7 @@ export default function ImagePickerCom(props) {
           />
         )}
       </Button>
-      {cancelEvent && (
+      {!!cancelEvent && (
         <Button
           bg="red500"
           h={16}

+ 29 - 1
locales/en.json

@@ -61,5 +61,33 @@
   "you-wu-jia-shi-zheng": "Driver's license",
   "zai-ci-shu-ru-que-ren-mi-ma": "Enter the confirm password again",
   "zhen-shi-xing-ming": "actual name",
-  "zhong-xin-shen-qing": "Re-apply"
+  "zhong-xin-shen-qing": "Re-apply",
+  "bang-ding-yin-hang-ka": "Bind bank card",
+  "bao-cun": "save",
+  "ding-dan": "Orders",
+  "geng-gai-mi-ma": "change the password",
+  "geng-xin-cheng-gong": "update completed",
+  "gong-xi-nin-de-shen-qing-yi-tong-guo": "Congratulations!!! Your application has been passed",
+  "ji-ben-xin-xi": "Basic Information",
+  "jin-ri-huan-mei-you-zhang-dan-xin-xio": "There is no bill information today~",
+  "jin-ri-shou-ru": "Today's income",
+  "jin-ri-zhang-dan": "Today's bill",
+  "jin-ri-zhi-chu": "Spend today",
+  "nin-de-gong-hao-wei": "Your job number is",
+  "qing-shu-ru-xin-mi-ma": "Please enter a new password",
+  "qing-shu-ru-yuan-mi-ma": "Please enter the original password",
+  "qing-zhong-fu-shu-ru-xin-mi-ma": "Please repeat the new password",
+  "shou-ru": "income",
+  "ti-xian": "withdraw",
+  "tou-xiang": "Avatar",
+  "tui-chu-cheng-gong": "exit successfully",
+  "wo-de": "mine",
+  "wo-de-ding-dong-bi": "My dingdong coin",
+  "wo-de-dui-zhang-dan": "My statement",
+  "xiao-xi": "news",
+  "xin-mi-ma": "new password",
+  "xuan-ze-yin-hang-ka": "Choose bank card",
+  "yu-e": "Balance",
+  "yuan-mi-ma": "old password",
+  "zhi-chu": "expenditure"
 }

+ 29 - 1
locales/th.json

@@ -61,5 +61,33 @@
   "you-wu-jia-shi-zheng": "ใบขับขี่",
   "zai-ci-shu-ru-que-ren-mi-ma": "ป้อนรหัสผ่านยืนยันอีกครั้ง",
   "zhen-shi-xing-ming": "ชื่อจริง",
-  "zhong-xin-shen-qing": "ทาซ้ำ"
+  "zhong-xin-shen-qing": "ทาซ้ำ",
+  "bang-ding-yin-hang-ka": "ผูกบัตรธนาคาร",
+  "bao-cun": "บันทึก",
+  "ding-dan": "ใบสั่ง",
+  "geng-gai-mi-ma": "เปลี่ยนรหัสผ่าน",
+  "geng-xin-cheng-gong": "การอัปเดตเสร็จสมบูรณ์",
+  "gong-xi-nin-de-shen-qing-yi-tong-guo": "ขอแสดงความยินดี !!! ใบสมัครของคุณผ่านไปแล้ว",
+  "ji-ben-xin-xi": "ข้อมูลพื้นฐาน",
+  "jin-ri-huan-mei-you-zhang-dan-xin-xio": "ไม่มีข้อมูลการเรียกเก็บเงินในวันนี้ ~",
+  "jin-ri-shou-ru": "รายได้ของวันนี้",
+  "jin-ri-zhang-dan": "ค่าของวันนี้",
+  "jin-ri-zhi-chu": "ใช้จ่ายวันนี้",
+  "nin-de-gong-hao-wei": "หมายเลขงานของคุณคือ",
+  "qing-shu-ru-xin-mi-ma": "กรุณาใส่รหัสผ่านใหม่",
+  "qing-shu-ru-yuan-mi-ma": "กรุณาใส่รหัสผ่านเดิม",
+  "qing-zhong-fu-shu-ru-xin-mi-ma": "กรุณาทำซ้ำรหัสผ่านใหม่",
+  "shou-ru": "เงินได้",
+  "ti-xian": "ถอน",
+  "tou-xiang": "สัญลักษณ์",
+  "tui-chu-cheng-gong": "ออกเรียบร้อยแล้ว",
+  "wo-de": "เหมือง",
+  "wo-de-ding-dong-bi": "เหรียญ dingdong ของฉัน",
+  "wo-de-dui-zhang-dan": "คำสั่งของฉัน",
+  "xiao-xi": "ข่าว",
+  "xin-mi-ma": "รหัสผ่านใหม่",
+  "xuan-ze-yin-hang-ka": "เลือกบัตรธนาคาร",
+  "yu-e": "สมดุล",
+  "yuan-mi-ma": "รหัสผ่านเก่า",
+  "zhi-chu": "รายจ่าย"
 }

+ 27 - 1
locales/zh-CN.json

@@ -63,5 +63,31 @@
   "song-can-jiao-tong-gong-ju-xin-xi": "送餐交通工具信息",
   "shen-fen-ren-zheng-xin-xi": "身份认证信息",
   "gong-xi-nin-de-shen-qing-yi-tong-guo": "恭喜!!!您的申请已通过",
-  "nin-de-gong-hao-wei": "您的工号为"
+  "nin-de-gong-hao-wei": "您的工号为",
+  "tui-chu-cheng-gong": "退出成功",
+  "geng-xin-cheng-gong": "更新成功",
+  "tou-xiang": "头像",
+  "yuan-mi-ma": "原密码",
+  "qing-shu-ru-yuan-mi-ma": "请输入原密码",
+  "xin-mi-ma": "新密码",
+  "qing-shu-ru-xin-mi-ma": "请输入新密码",
+  "qing-zhong-fu-shu-ru-xin-mi-ma": "请重复输入新密码",
+  "bao-cun": "保存",
+  "ji-ben-xin-xi": "基本信息",
+  "geng-gai-mi-ma": "更改密码",
+  "ding-dan": "订单",
+  "xiao-xi": "消息",
+  "wo-de": "我的",
+  "wo-de-ding-dong-bi": "我的叮咚币",
+  "shou-ru": "收入",
+  "zhi-chu": "支出",
+  "jin-ri-huan-mei-you-zhang-dan-xin-xio": "今日还没有账单信息哦~",
+  "ti-xian": "提现",
+  "yu-e": "余额",
+  "jin-ri-zhang-dan": "今日账单",
+  "jin-ri-shou-ru": "今日收入",
+  "jin-ri-zhi-chu": "今日支出",
+  "wo-de-dui-zhang-dan": "我的对账单",
+  "xuan-ze-yin-hang-ka": "选择银行卡",
+  "bang-ding-yin-hang-ka": "绑定银行卡"
 }

+ 136 - 0
mine/ChangePasswordScreen.tsx

@@ -0,0 +1,136 @@
+import { StackScreenProps } from '@react-navigation/stack';
+import * as React from 'react';
+import { Div, Button, Image, Text, Avatar, Input } from 'react-native-magnus';
+import { ScrollView } from 'react-native-gesture-handler';
+import { useTranslation } from 'react-i18next';
+import { useCreation } from 'ahooks';
+
+export default function ChangePasswordScreen({ navigation }: StackScreenProps) {
+  const { t } = useTranslation();
+
+  const [password, setPassword] = React.useState<string>('');
+  const [passwordNew1, setPasswordNew1] = React.useState<string>('');
+  const [passwordNew2, setPasswordNew2] = React.useState<string>('');
+  const canNext = useCreation(() => {
+    if (password && passwordNew1 && passwordNew1 === passwordNew2) {
+      return true;
+    } else {
+      return false;
+    }
+  }, [password, passwordNew1, passwordNew2]);
+
+  return (
+    <Div bg="gray100" flex={1}>
+      <ScrollView
+        contentContainerStyle={{
+          flexGrow: 1,
+          backgroundColor: '#f2f2f2',
+        }}
+      >
+        <Div bg="white" px={15}>
+          <Div
+            row
+            alignItems="center"
+            py={10}
+            borderColor="gray100"
+            borderBottomWidth={1}
+          >
+            <Text w={75} textAlign="left">
+              {t('yuan-mi-ma')}:
+            </Text>
+            <Input
+              flex={1}
+              rounded="sm"
+              loaderColor="gray400"
+              px={12}
+              ml={5}
+              h={30}
+              type={'custom'}
+              value={password}
+              borderWidth={0}
+              fontSize="md"
+              secureTextEntry
+              color="gray700"
+              onChangeText={(text) => {
+                setPassword(text);
+              }}
+              style={{ flex: 1 }}
+              placeholder={t('qing-shu-ru-yuan-mi-ma')}
+            />
+          </Div>
+          <Div
+            row
+            alignItems="center"
+            py={10}
+            borderColor="gray100"
+            borderBottomWidth={1}
+          >
+            <Text w={75} textAlign="left">
+              {t('xin-mi-ma')}:
+            </Text>
+            <Input
+              flex={1}
+              rounded="sm"
+              loaderColor="gray400"
+              px={12}
+              ml={5}
+              h={30}
+              type={'custom'}
+              value={passwordNew1}
+              borderWidth={0}
+              fontSize="md"
+              secureTextEntry
+              color="gray700"
+              onChangeText={(text) => {
+                setPasswordNew1(text);
+              }}
+              style={{ flex: 1 }}
+              placeholder={t('qing-shu-ru-xin-mi-ma')}
+            />
+          </Div>
+          <Div
+            row
+            alignItems="center"
+            py={10}
+            borderColor="gray100"
+            borderBottomWidth={1}
+          >
+            <Text w={75} textAlign="left">
+              {t('que-ren-mi-ma')}:
+            </Text>
+            <Input
+              flex={1}
+              rounded="sm"
+              loaderColor="gray400"
+              px={12}
+              ml={5}
+              h={30}
+              type={'custom'}
+              value={passwordNew2}
+              borderWidth={0}
+              fontSize="md"
+              secureTextEntry
+              color="gray700"
+              onChangeText={(text) => {
+                setPasswordNew2(text);
+              }}
+              style={{ flex: 1 }}
+              placeholder={t('qing-zhong-fu-shu-ru-xin-mi-ma')}
+            />
+          </Div>
+        </Div>
+
+        <Button
+          disabled={!canNext}
+          block
+          my={50}
+          mx={15}
+          bg="yellow500"
+          fontSize="sm"
+        >
+          {t('bao-cun')}
+        </Button>
+      </ScrollView>
+    </Div>
+  );
+}

+ 135 - 0
mine/MineInfoScreen.tsx

@@ -0,0 +1,135 @@
+import { StackScreenProps } from '@react-navigation/stack';
+import * as React from 'react';
+import { Div, Button, Image, Text, Avatar, Icon } from 'react-native-magnus';
+import { ScrollView } from 'react-native-gesture-handler';
+import useModel from 'flooks';
+import { useTranslation } from 'react-i18next';
+import User from '../stores/User';
+
+import ImagePicker from '../components/ImagePicker';
+
+import { promot } from '../utils/SystemUtils';
+
+export default function MineInfoScreen({ navigation }: StackScreenProps) {
+  const { t } = useTranslation();
+  const { userInfo, updateUser, riderInfo } = useModel(User, ['userInfo']);
+  const { avatar, nickname, phone } = userInfo;
+  const { jobNumber, area } = riderInfo;
+  function updateInfo(key, val) {
+    updateUser({
+      [key]: val,
+    });
+  }
+
+  return (
+    <Div bg="gray100">
+      <ScrollView
+        contentContainerStyle={{
+          flexGrow: 1,
+          backgroundColor: '#f2f2f2',
+        }}
+      >
+        <Div mb={10} row bg="white" row h={55} alignItems="center" px={15}>
+          <Text flex={1} fontSize="sm">
+            {t('tou-xiang')}:
+          </Text>
+
+          <ImagePicker
+            img={avatar}
+            setImg={(img) => updateInfo('avatar', img)}
+            w={33}
+            h={33}
+          />
+          <Icon ml={5} name="right" fontSize="sm" />
+        </Div>
+        <Button
+          mb={10}
+          bg="transparent"
+          p={0}
+          block
+          onPress={() => {
+            promot(navigation, {
+              title: '昵称',
+              defaultVal: nickname,
+              hasCancel: true,
+              submitEvent: (val) => {
+                updateInfo('nickname', val);
+              },
+            });
+          }}
+        >
+          <Div flex={1} row bg="white" row h={55} alignItems="center" px={15}>
+            <Text flex={1} fontSize="sm">
+              昵称:
+            </Text>
+
+            <Text color="gray500" fontSize="sm">
+              {nickname}
+            </Text>
+            <Icon ml={5} name="right" fontSize="sm" />
+          </Div>
+        </Button>
+        <Div mb={10} row bg="white" row h={55} alignItems="center" px={15}>
+          <Text flex={1} fontSize="sm">
+            更改密码:
+          </Text>
+
+          <Icon ml={5} name="right" fontSize="sm" />
+        </Div>
+        <Div bg="white" px={15}>
+          <Div
+            row
+            py={12}
+            alignItems="center"
+            borderBottomWidth={1}
+            borderColor="gray100"
+          >
+            <Text flex={1} fontSize="sm">
+              工号:
+            </Text>
+            <Text fontSize="sm" color="gray500">
+              {jobNumber}
+            </Text>
+          </Div>
+          <Div
+            row
+            py={12}
+            alignItems="center"
+            borderBottomWidth={1}
+            borderColor="gray100"
+          >
+            <Text fontSize="sm" minW={75}>
+              地 址:
+            </Text>
+            <Text fontSize="sm" color="gray500">
+              {area}
+            </Text>
+          </Div>
+          <Div
+            row
+            py={12}
+            alignItems="center"
+            borderBottomWidth={1}
+            borderColor="gray100"
+          >
+            <Text flex={1} fontSize="sm">
+              电 话:
+            </Text>
+            <Text fontSize="sm" color="gray500">
+              {phone}
+            </Text>
+          </Div>
+
+          <Div row py={12} alignItems="center">
+            <Text fontSize="sm" minW={75}>
+              工作范围:
+            </Text>
+            <Text fontSize="sm" color="gray500">
+              {area}
+            </Text>
+          </Div>
+        </Div>
+      </ScrollView>
+    </Div>
+  );
+}

+ 110 - 7
mine/MineScreen.tsx

@@ -1,21 +1,124 @@
 import { StackScreenProps } from '@react-navigation/stack';
 import * as React from 'react';
-import { Div, Button, Image, Text, Avatar } from 'react-native-magnus';
+import { Div, Button, Image, Text, Avatar, Icon } from 'react-native-magnus';
 import { ScrollView } from 'react-native-gesture-handler';
 
 import { RootStackParamList } from '../types';
 
-export default function RegisterScreen({
-  navigation,
-}: StackScreenProps<RootStackParamList, 'Login'>) {
+import useModel from 'flooks';
+
+import User from '../stores/User';
+
+import { connect } from '../utils/SystemUtils';
+
+const logo = require('../assets/images/logo.png');
+
+export default function RegisterScreen({ navigation }: StackScreenProps) {
+  const { userInfo, riderInfo } = useModel(User, ['userInfo']);
+  const { avatar, nickname, money } = userInfo;
+  const { jobNumber } = riderInfo;
+
   return (
-    <Div bg="gray100">
+    <Div bg="yellow500" flex={1}>
       <ScrollView
         contentContainerStyle={{ flexGrow: 1, backgroundColor: '#f2f2f2' }}
       >
-        <Div>
-          <Text></Text>
+        <Div h={112} bg="yellow500" justifyContent="flex-end" p={20}>
+          <Button
+            p={0}
+            bg="transparent"
+            onPress={() =>
+              navigation.navigate('MineStack', {
+                screen: 'MineInfo',
+              })
+            }
+          >
+            <Div flex={1} row alignItems="center">
+              <Image w={53} h={53} source={avatar || logo} />
+              <Div flex={1} ml={14}>
+                <Div row alignItems="center">
+                  <Text fontSize="xl" fontWeight="bold" flex={1}>
+                    {nickname}
+                  </Text>
+
+                  <Icon color="black" name="right" ml={10} fontSize="xl" />
+                </Div>
+                <Text fontSize="sm" mt={5}>
+                  工号:{jobNumber}
+                </Text>
+              </Div>
+            </Div>
+          </Button>
+        </Div>
+        <Div bg="gray100" p={10}>
+          <Button block bg="white" p={10} rounded="sm">
+            <Div flex={1} row>
+              <Div flex={1}>
+                <Text>我的叮咚币</Text>
+                <Div row alignItems="center" mt={5}>
+                  <Text fontSize="xl" color="yellow400">
+                    578.63
+                  </Text>
+                  <Text fontSize="sm" color="gray700" ml={6}>
+                    今日收入
+                  </Text>
+                  <Text fontSize="xl" color="yellow400" ml={35}>
+                    578.63
+                  </Text>
+                  <Text fontSize="sm" color="gray700" ml={6}>
+                    今日收入
+                  </Text>
+                </Div>
+              </Div>
+              <Icon name="right" />
+            </Div>
+          </Button>
         </Div>
+        <Button block bg="white" p={20} rounded="sm" mb={10}>
+          <Div flex={1} row>
+            <Text flex={1}>单量热力图</Text>
+            <Icon name="right" />
+          </Div>
+        </Button>
+        <Button block bg="white" p={20} rounded="sm" mb={10}>
+          <Div flex={1} row>
+            <Text flex={1}>我的评价</Text>
+            <Icon name="right" />
+          </Div>
+        </Button>
+        <Button block bg="white" p={20} rounded="sm" mb={10}>
+          <Div flex={1} row>
+            <Text flex={1}>我的投诉</Text>
+            <Icon name="right" />
+          </Div>
+        </Button>
+        <Button block bg="white" p={20} rounded="sm" mb={10}>
+          <Div flex={1} row>
+            <Text flex={1}>培训中心</Text>
+            <Icon name="right" />
+          </Div>
+        </Button>
+        <Button
+          block
+          bg="white"
+          p={20}
+          rounded="sm"
+          mb={10}
+          onPress={() => {
+            connect(navigation);
+          }}
+        >
+          <Div flex={1} row>
+            <Text flex={1}>联系客服</Text>
+            <Icon name="right" />
+          </Div>
+        </Button>
+        <Button block bg="white" p={20} rounded="sm" mb={10}>
+          <Div flex={1} row>
+            <Text flex={1}>设置</Text>
+            <Icon name="right" />
+          </Div>
+        </Button>
       </ScrollView>
     </Div>
   );

+ 70 - 0
modals/InputModalScreen.tsx

@@ -0,0 +1,70 @@
+import { StackScreenProps } from '@react-navigation/stack';
+import * as React from 'react';
+import * as Animatable from 'react-native-animatable';
+import { Div, Button, Image, Text, Avatar, Input } from 'react-native-magnus';
+import { ScrollView } from 'react-native-gesture-handler';
+import { useTranslation } from 'react-i18next';
+
+export default function InputModalScreen({
+  navigation,
+  route,
+}: StackScreenProps) {
+  const { params } = route;
+  const { title, defaultVal, hasCancel, submitText, submitEvent } =
+    params || {};
+  const { t } = useTranslation();
+
+  const [val, setVal] = React.useState<string>('');
+
+  const inRef = React.useRef();
+
+  return (
+    <Div flex={1} bg="black600" alignItems="center" justifyContent="center">
+      <Animatable.View animation="slideInUp" duration={300}>
+        <Div bg="white" p={10} rounded="sm" minW={287}>
+          <Text fontSize="lg" textAlign="center">
+            {title || t('ti-shi')}
+          </Text>
+
+          <Input
+            autoFocus={true}
+            defaultValue={defaultVal}
+            mt={10}
+            onChangeText={(text) => setVal(text)}
+          />
+
+          <Div row py={10} mt={10}>
+            <Button
+              flex={1}
+              mx={3}
+              rounded="xs"
+              bg="white"
+              color="black"
+              borderWidth={1}
+              borderColor="yellow500"
+              fontSize="sm"
+              onPress={() => navigation.goBack()}
+            >
+              {hasCancel ? t('qu-xiao') : submitText || t('que-ren')}
+            </Button>
+            <Button
+              flex={1}
+              mx={3}
+              rounded="xs"
+              bg="yellow500"
+              fontSize="sm"
+              onPress={() => {
+                if (submitEvent) {
+                  submitEvent(val);
+                }
+                navigation.goBack();
+              }}
+            >
+              {submitText || t('que-ren')}
+            </Button>
+          </Div>
+        </Div>
+      </Animatable.View>
+    </Div>
+  );
+}

+ 15 - 9
navigation/MianTabNavigator.tsx

@@ -5,9 +5,13 @@ import * as React from 'react';
 import { Icon, Text } from 'react-native-magnus';
 import Colors from '../constants/Colors';
 import useColorScheme from '../hooks/useColorScheme';
-import OrderStackNavigator from './OrderStackNavigator';
-import NoticeStackNavigator from './NoticeStackNavigator';
-import MineStackNavigator from './MineStackNavigator';
+
+import MineScreen from '../mine/MineScreen';
+import NoticeScreen from '../notice/NoticeScreen';
+import OrderScreen from '../order/OrderScreen';
+
+import { useTranslation } from 'react-i18next';
+
 import { MainTabParamList } from '../types';
 
 const MainTab = createBottomTabNavigator<MainTabParamList>();
@@ -15,6 +19,8 @@ const MainTab = createBottomTabNavigator<MainTabParamList>();
 export default function MainTabNavigator() {
   const colorScheme = useColorScheme();
 
+  const { t } = useTranslation();
+
   return (
     <MainTab.Navigator
       initialRouteName="Mine"
@@ -22,7 +28,7 @@ export default function MainTabNavigator() {
     >
       <MainTab.Screen
         name="Order"
-        component={OrderStackNavigator}
+        component={OrderScreen}
         options={{
           tabBarIcon: ({ color }) => (
             <Icon
@@ -34,14 +40,14 @@ export default function MainTabNavigator() {
           ),
           tabBarLabel: ({ focused }) => (
             <Text fontSize="xs" color={focused ? 'yellow500' : 'black'}>
-              订单
+              {t('ding-dan')}
             </Text>
           ),
         }}
       />
       <MainTab.Screen
         name="Notice"
-        component={NoticeStackNavigator}
+        component={NoticeScreen}
         options={{
           tabBarIcon: ({ color }) => (
             <Icon
@@ -53,14 +59,14 @@ export default function MainTabNavigator() {
           ),
           tabBarLabel: ({ focused }) => (
             <Text fontSize="xs" color={focused ? 'yellow500' : 'black'}>
-              消息
+              {t('xiao-xi')}
             </Text>
           ),
         }}
       />
       <MainTab.Screen
         name="Mine"
-        component={MineStackNavigator}
+        component={MineScreen}
         options={{
           tabBarIcon: ({ color }) => (
             <Icon
@@ -72,7 +78,7 @@ export default function MainTabNavigator() {
           ),
           tabBarLabel: ({ focused }) => (
             <Text fontSize="xs" color={focused ? 'yellow500' : 'black'}>
-              我的
+              {t('wo-de')}
             </Text>
           ),
         }}

+ 39 - 5
navigation/MineStackNavigator.tsx

@@ -14,7 +14,14 @@ import { useTranslation } from 'react-i18next';
 
 import { MineStackParamList } from '../types';
 
-import MineScreen from '../mine/MineScreen';
+import MineInfoScreen from '../mine/MineInfoScreen';
+import ChangePasswordScreen from '../mine/ChangePasswordScreen';
+
+//叮咚币
+import MineWalletScreen from '../wallet/MineWalletScreen';
+import WithdrawApplyScreen from '../wallet/WithdrawApplyScreen';
+import BankCardScreen from '../wallet/BankCardScreen';
+import AddBankCardScreen from '../wallet/AddBankCardScreen';
 
 const MineStack = createStackNavigator<MineStackParamList>();
 export default function Navigation({
@@ -25,7 +32,7 @@ export default function Navigation({
   const { t } = useTranslation();
   return (
     <MineStack.Navigator
-      initialRouteName="Mine"
+      initialRouteName="AddBankCard"
       screenOptions={{
         cardOverlayEnabled: true,
         cardStyle: { backgroundColor: '#f2f2f2', flex: 1 },
@@ -45,9 +52,36 @@ export default function Navigation({
       }}
     >
       <MineStack.Screen
-        name="Mine"
-        component={MineScreen}
-        options={{ headerShown: false }}
+        name="MineInfo"
+        component={MineInfoScreen}
+        options={{ title: t('ji-ben-xin-xi') }}
+      />
+      <MineStack.Screen
+        name="ChangePassword"
+        component={ChangePasswordScreen}
+        options={{ title: t('geng-gai-mi-ma') }}
+      />
+      <MineStack.Screen
+        name="Wallet"
+        component={MineWalletScreen}
+        options={{ title: t('wo-de-ding-dong-bi') }}
+      />
+      <MineStack.Screen
+        name="WithdrawApply"
+        component={WithdrawApplyScreen}
+        options={{ title: t('ti-xian') }}
+      />
+
+      <MineStack.Screen
+        name="BankCard"
+        component={BankCardScreen}
+        options={{ title: t('xuan-ze-yin-hang-ka') }}
+      />
+
+      <MineStack.Screen
+        name="AddBankCard"
+        component={AddBankCardScreen}
+        options={{ title: t('bang-ding-yin-hang-ka') }}
       />
     </MineStack.Navigator>
   );

+ 40 - 0
navigation/ModalStackNavigator.tsx

@@ -0,0 +1,40 @@
+import {
+  NavigationContainer,
+  DefaultTheme,
+  DarkTheme,
+} from '@react-navigation/native';
+import {
+  createStackNavigator,
+  CardStyleInterpolators,
+} from '@react-navigation/stack';
+import * as React from 'react';
+import { ColorSchemeName } from 'react-native';
+import useModel from 'flooks';
+import { useTranslation } from 'react-i18next';
+
+import { MineStackParamList } from '../types';
+
+import AlertModalScreen from '../modals/AlertModalScreen';
+import InputModalScreen from '../modals/InputModalScreen';
+
+const ModalStack = createStackNavigator<MineStackParamList>();
+export default function Navigation({
+  colorScheme,
+}: {
+  colorScheme: ColorSchemeName;
+}) {
+  const { t } = useTranslation();
+  return (
+    <ModalStack.Navigator
+      mode="modals"
+      screenOptions={{
+        cardStyle: { backgroundColor: 'transparent' },
+        animationEnabled: false,
+        headerShown: false,
+      }}
+    >
+      <ModalStack.Screen name="Alert" component={AlertModalScreen} />
+      <ModalStack.Screen name="Promot" component={InputModalScreen} />
+    </ModalStack.Navigator>
+  );
+}

+ 37 - 9
navigation/index.tsx

@@ -12,6 +12,7 @@ import useModel from 'flooks';
 
 //弹窗模块
 import AlertModalScreen from '../modals/AlertModalScreen';
+import ModalStackNavigator from './ModalStackNavigator';
 
 //登录模块堆栈
 import LoginStackNavigator from './LoginStackNavigator';
@@ -19,6 +20,11 @@ import LoginStackNavigator from './LoginStackNavigator';
 //首页堆栈
 import MainTabNavigator from './MianTabNavigator';
 
+//我的模块堆栈
+import MineStackNavigator from './MineStackNavigator';
+
+import { useCreation } from 'ahooks';
+
 import { RootStackParamList } from '../types';
 import LinkingConfiguration from './LinkingConfiguration';
 
@@ -31,6 +37,21 @@ export default function Navigation({
 }) {
   const { initialRouteName } = useModel(User, ['initialRouteName']);
   const navRef = React.useRef();
+
+  const initRoute = useCreation(() => {
+    if (__DEV__) {
+      return {
+        name: 'MineStack',
+        screen: 'ChangePassword',
+      };
+    } else {
+      return {
+        name: initialRouteName !== 'Main' ? 'Login' : initialRouteName,
+        screen: initialRouteName !== 'Main' ? initialRouteName : 'Order',
+      };
+    }
+  }, [__DEV__, initialRouteName]);
+
   React.useEffect(() => {
     if (navRef.current) {
       navRef.current.dispatch(
@@ -38,12 +59,8 @@ export default function Navigation({
           index: 0,
           routes: [
             {
-              name: initialRouteName !== 'Main' ? 'Login' : initialRouteName,
-              screen: __DEV__
-                ? 'Certification'
-                : initialRouteName !== 'Main'
-                ? initialRouteName
-                : 'TabOne',
+              name: initRoute.name,
+              screen: initRoute.screen,
             },
           ],
         })
@@ -57,18 +74,18 @@ export default function Navigation({
       linking={LinkingConfiguration}
       theme={colorScheme === 'dark' ? DarkTheme : DefaultTheme}
     >
-      <RootNavigator />
+      <RootNavigator initRoute={initRoute} />
     </NavigationContainer>
   );
 }
 
 const Stack = createStackNavigator<RootStackParamList>();
 
-function RootNavigator() {
+function RootNavigator({ initRoute }) {
   const { t } = useTranslation();
   return (
     <Stack.Navigator
-      initialRouteName="Main"
+      initialRouteName={initRoute.name}
       screenOptions={{
         stackPresentation: 'push',
         headerShown: false,
@@ -78,6 +95,17 @@ function RootNavigator() {
 
       <Stack.Screen name="Main" component={MainTabNavigator} />
 
+      <Stack.Screen name="MineStack" component={MineStackNavigator} />
+      <Stack.Screen
+        name="Modal"
+        mode="modals"
+        component={ModalStackNavigator}
+        options={{
+          cardStyle: { backgroundColor: 'transparent' },
+          animationEnabled: false,
+        }}
+      />
+
       <Stack.Screen
         name="AlertModal"
         mode="modals"

+ 5 - 2
notice/NoticeScreen.tsx

@@ -6,13 +6,16 @@ import { ScrollView } from 'react-native-gesture-handler';
 import { RootStackParamList } from '../types';
 import IM from './model';
 
-export default function RegisterScreen({
+export default function NoticeScreen({
   navigation,
 }: StackScreenProps<RootStackParamList, 'Login'>) {
   return (
     <Div bg="gray100">
       <ScrollView
-        contentContainerStyle={{ flexGrow: 1, backgroundColor: '#f2f2f2' }}
+        contentContainerStyle={{
+          flexGrow: 1,
+          backgroundColor: '#f2f2f2',
+        }}
       >
         <Div>
           <Text></Text>

+ 5 - 0
package-lock.json

@@ -11637,6 +11637,11 @@
         "minimist": "^1.2.5"
       }
     },
+    "moment": {
+      "version": "2.27.0",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz",
+      "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ=="
+    },
     "ms": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",

+ 1 - 0
package.json

@@ -40,6 +40,7 @@
     "flooks": "^3.0.0",
     "i18n-js": "^3.7.1",
     "i18next": "^19.6.2",
+    "moment": "^2.27.0",
     "qs": "^6.9.4",
     "react": "~16.11.0",
     "react-dom": "~16.11.0",

+ 0 - 43
screens/NotFoundScreen.tsx

@@ -1,43 +0,0 @@
-import { StackScreenProps } from '@react-navigation/stack';
-import * as React from 'react';
-import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
-
-import { RootStackParamList } from '../types';
-
-export default function NotFoundScreen({
-  navigation,
-}: StackScreenProps<RootStackParamList, 'NotFound'>) {
-  return (
-    <View style={styles.container}>
-      <Text style={styles.title}>This screen doesn't exist.</Text>
-      <TouchableOpacity
-        onPress={() => navigation.replace('Root')}
-        style={styles.link}
-      >
-        <Text style={styles.linkText}>Go to home screen!</Text>
-      </TouchableOpacity>
-    </View>
-  );
-}
-
-const styles = StyleSheet.create({
-  container: {
-    flex: 1,
-    backgroundColor: '#fff',
-    alignItems: 'center',
-    justifyContent: 'center',
-    padding: 20,
-  },
-  title: {
-    fontSize: 20,
-    fontWeight: 'bold',
-  },
-  link: {
-    marginTop: 15,
-    paddingVertical: 15,
-  },
-  linkText: {
-    fontSize: 14,
-    color: '#2e78b7',
-  },
-});

+ 0 - 36
screens/TabOneScreen.tsx

@@ -1,36 +0,0 @@
-import * as React from 'react';
-import { StyleSheet } from 'react-native';
-
-import EditScreenInfo from '../components/EditScreenInfo';
-import { Text, View } from '../components/Themed';
-
-export default function TabOneScreen() {
-  return (
-    <View style={styles.container}>
-      <Text style={styles.title}>Tab One</Text>
-      <View
-        style={styles.separator}
-        lightColor="#f2f2f2"
-        darkColor="rgba(255,255,255,0.1)"
-      />
-      <EditScreenInfo path="/screens/TabOneScreen.tsx" />
-    </View>
-  );
-}
-
-const styles = StyleSheet.create({
-  container: {
-    flex: 1,
-    alignItems: 'center',
-    justifyContent: 'center',
-  },
-  title: {
-    fontSize: 20,
-    fontWeight: 'bold',
-  },
-  separator: {
-    marginVertical: 30,
-    height: 1,
-    width: '80%',
-  },
-});

+ 0 - 32
screens/TabTwoScreen.tsx

@@ -1,32 +0,0 @@
-import * as React from 'react';
-import { StyleSheet } from 'react-native';
-
-import EditScreenInfo from '../components/EditScreenInfo';
-import { Text, View } from '../components/Themed';
-
-export default function TabTwoScreen() {
-  return (
-    <View style={styles.container}>
-      <Text style={styles.title}>Tab Two</Text>
-      <View style={styles.separator} lightColor="#f2f2f2" darkColor="rgba(255,255,255,0.1)" />
-      <EditScreenInfo path="/screens/TabTwoScreen.tsx" />
-    </View>
-  );
-}
-
-const styles = StyleSheet.create({
-  container: {
-    flex: 1,
-    alignItems: 'center',
-    justifyContent: 'center',
-  },
-  title: {
-    fontSize: 20,
-    fontWeight: 'bold',
-  },
-  separator: {
-    marginVertical: 30,
-    height: 1,
-    width: '80%',
-  },
-});

+ 9 - 6
stores/User.ts

@@ -12,6 +12,8 @@ import {
 } from '../utils/SystemUtils';
 import IM from '../im/model';
 
+import i18n from '../i18n';
+
 const user = (now) => ({
   id: null,
   userInfo: {},
@@ -67,13 +69,12 @@ const user = (now) => ({
     removeAsyncStorage('token').then(() => {
       // 清除用户信息
       now({ id: 0, userInfo: {} });
-      success('退出成功');
+      toastSuccess(i18n.t('tui-chu-cheng-gong'));
     });
   },
-  uploadInfo({ ...info }) {
+  updateUser({ ...info }) {
     const { id, getUser } = now();
-    const { loading, warnning, success } = now(Toast);
-    loading();
+    toastShow();
     return request
       .post('/user/save', {
         data: {
@@ -85,11 +86,13 @@ const user = (now) => ({
         return getUser();
       })
       .then(() => {
-        success('更新成功');
+        toastHide();
+        toastSuccess(i18n.t('geng-xin-cheng-gong'));
         return Promise.resolve();
       })
       .catch((e) => {
-        warnning(e.error);
+        toastHide();
+        toastInfo(e.error);
       });
   },
   getInit() {

+ 18 - 0
utils/MoneyUtils.ts

@@ -0,0 +1,18 @@
+const FinancialType = new Map([
+  [
+    'INCOME',
+    {
+      name: 'shou-ru',
+      backMoney: (money = 0) => '+' + money.toFixed(2),
+    },
+  ],
+  [
+    'EXPENDITURE',
+    {
+      name: 'zhi-chu',
+      backMoney: (money = 0) => '-' + money.toFixed(2),
+    },
+  ],
+]);
+
+export { FinancialType };

+ 36 - 7
utils/SystemUtils.ts

@@ -5,16 +5,33 @@ import * as Linking from 'expo-linking';
 import { Platform } from 'react-native';
 
 function connect(navigation) {
-  navigation.navigate('AlertModal', {
-    msg: `${i18n.t('tips1')}:0512-109291882?`,
-    hasCancel: true,
-    submitText: i18n.t('li-ji-bo-da'),
-    submitEvent: () => {
-      Linking.openURL('tel:+123456789');
+  navigation.navigate('Modal', {
+    screen: 'Alert',
+    params: {
+      msg: `${i18n.t('tips1')}:0512-109291882?`,
+      hasCancel: true,
+      submitText: i18n.t('li-ji-bo-da'),
+      submitEvent: () => {
+        Linking.openURL('tel:+123456789');
+      },
     },
   });
 }
 
+function promot(
+  navigation,
+  params = {
+    title: '',
+    submitEvent: (val) => {},
+    hasCancel: true,
+  }
+) {
+  navigation.navigate('Modal', {
+    screen: 'Promot',
+    params,
+  });
+}
+
 function toastShow() {
   if (Platform.OS === 'web') return;
   ModalIndicator.show(i18n.t('jia-zai-zhong'));
@@ -33,4 +50,16 @@ function toastInfo(title) {
   Toast.message(title);
 }
 
-export { connect, toastShow, toastHide, toastInfo, toastSuccess };
+function getMoney(money = 0) {
+  return money.toFixed(2);
+}
+
+export {
+  connect,
+  promot,
+  toastShow,
+  toastHide,
+  toastInfo,
+  toastSuccess,
+  getMoney,
+};

+ 12 - 0
utils/TimeUtils.ts

@@ -0,0 +1,12 @@
+import moment from 'moment';
+
+function today() {
+  return __DEV__
+    ? '2020-06-17 00:00:00,2020-06-17 23:59:59'
+    : moment().format('YYYY-MM-DD') +
+        ' 00:00:00,' +
+        moment().add(1, 'days').format('YYYY-MM-DD') +
+        ' 00:00:00';
+}
+
+export { today };

+ 21 - 0
wallet/AddBankCardScreen.tsx

@@ -0,0 +1,21 @@
+import { StackScreenProps } from '@react-navigation/stack';
+import * as React from 'react';
+import { Div, Button, Image, Text, Avatar } from 'react-native-magnus';
+import { ScrollView } from 'react-native-gesture-handler';
+
+export default function AddBankCardScreen({ navigation }: StackScreenProps) {
+  return (
+    <Div bg="gray100">
+      <ScrollView
+        contentContainerStyle={{
+          flexGrow: 1,
+          backgroundColor: '#f2f2f2',
+        }}
+      >
+        <Div>
+          <Text></Text>
+        </Div>
+      </ScrollView>
+    </Div>
+  );
+}

+ 60 - 0
wallet/BankCardScreen.tsx

@@ -0,0 +1,60 @@
+import { StackScreenProps } from '@react-navigation/stack';
+import * as React from 'react';
+import { Div, Button, Image, Text, Avatar, Icon } from 'react-native-magnus';
+import { ScrollView } from 'react-native-gesture-handler';
+import { useRequest } from 'ahooks';
+
+export default function BankCardScreen({ navigation }: StackScreenProps) {
+  const { data, loading } = useRequest('/bankCard/my', {
+    formatResult: (response) => response.content,
+    initialData: [],
+    defaultLoading: true,
+  });
+
+  navigation.setOptions({
+    headerRight: () => (
+      <Button
+        bg="transparent"
+        mx={10}
+        onPress={() => navigation.navigate('AddBankCard')}
+      >
+        <Icon name="plus" color="white" />
+      </Button>
+    ),
+  });
+
+  return (
+    <Div bg="gray100">
+      <ScrollView
+        contentContainerStyle={{
+          flexGrow: 1,
+          backgroundColor: '#f2f2f2',
+        }}
+      >
+        {data.map((item) => {
+          return <bankCom key={item.id} info={item} />;
+        })}
+
+        {data.length === 0 && !loading && (
+          <Div>
+            <Text py={30} textAlign="center">
+              当前还没有银行信息
+            </Text>
+
+            <Button
+              alignSelf="center"
+              bg="yellow500"
+              onPress={() => navigation.navigate('AddBankCard')}
+            >
+              去添加
+            </Button>
+          </Div>
+        )}
+      </ScrollView>
+    </Div>
+  );
+}
+
+function bankCom(params: type) {
+  return <Div p={15} bg="white" />;
+}

+ 128 - 0
wallet/MineWalletScreen.tsx

@@ -0,0 +1,128 @@
+import { StackScreenProps } from '@react-navigation/stack';
+import * as React from 'react';
+import { Div, Button, Image, Text, Avatar, Icon } from 'react-native-magnus';
+import { ScrollView } from 'react-native-gesture-handler';
+
+import { RootStackParamList } from '../types';
+import { useRequest } from 'ahooks';
+import useModel from 'flooks';
+
+import User from '../stores/User';
+
+import { getMoney } from '../utils/SystemUtils';
+import request from '../utils/RequestUtils';
+import { today } from '../utils/TimeUtils';
+import { useTranslation } from 'react-i18next';
+
+import ReacordCom from './ReacordCom';
+
+export default function MineWalletScreen({
+  navigation,
+}: StackScreenProps<RootStackParamList, 'Login'>) {
+  const { t } = useTranslation();
+  const { userInfo } = useModel(User, ['userInfo']);
+
+  const { data, loading } = useRequest(
+    () => {
+      return request.get(__DEV__ ? '/moneyRecord/all' : '/moneyRecord/my', {
+        params: {
+          query: {
+            time: today(),
+          },
+        },
+      });
+    },
+    {
+      formatResult: (response) => response.content,
+      initialData: [],
+      defaultLoading: true,
+    }
+  );
+
+  const { money } = userInfo;
+
+  return (
+    <Div bg="gray100" flex={1}>
+      <Div bg="yellow500" row>
+        <Text color="red700" fontSize="sm" flex={1} pl={20} pt={30}>
+          {t('yu-e')}
+        </Text>
+        <Text
+          flex={1}
+          textAlign="center"
+          fontSize="6xl"
+          color="white"
+          fontWeight="bold"
+          py={20}
+        >
+          {getMoney(money)}
+        </Text>
+        <Button
+          onPress={() => navigation.navigate('WithdrawApply')}
+          flex={1}
+          bg="transparent"
+          alignSelf="flex-end"
+          py={30}
+        >
+          <Text
+            textDecorLine="underline"
+            textDecorColor="white"
+            color="white"
+            fontSize="xl"
+          >
+            {t('ti-xian')}
+          </Text>
+        </Button>
+      </Div>
+      <ScrollView
+        contentContainerStyle={{
+          flexGrow: 1,
+          backgroundColor: '#f2f2f2',
+        }}
+        stickyHeaderIndices={[0, 2]}
+      >
+        <Div row h={40} alignItems="center" bg="gray100" px={20}>
+          <Text flex={1} fontSize="sm">
+            {t('jin-ri-zhang-dan')}
+          </Text>
+          <Text fontSize="sm" color="gray500">
+            {t('jin-ri-shou-ru')}¥ 16,752.95
+          </Text>
+          <Text fontSize="sm" color="gray500" ml={10}>
+            {t('jin-ri-zhi-chu')} ¥ 6,752.95
+          </Text>
+        </Div>
+
+        <Div bg="white" px={15}>
+          {data.map((item) => {
+            return <ReacordCom key={item.id} info={item} />;
+          })}
+
+          {data.length == 0 && !loading && (
+            <Text p={15} textAlign="center">
+              {t('jin-ri-huan-mei-you-zhang-dan-xin-xio')}
+            </Text>
+          )}
+        </Div>
+
+        <Div
+          mb={10}
+          row
+          bg="white"
+          row
+          h={52}
+          mt={10}
+          alignItems="center"
+          px={15}
+          mb={50}
+        >
+          <Text flex={1} fontSize="sm">
+            {t('wo-de-dui-zhang-dan')}
+          </Text>
+
+          <Icon ml={5} name="right" fontSize="sm" />
+        </Div>
+      </ScrollView>
+    </Div>
+  );
+}

+ 45 - 0
wallet/ReacordCom.tsx

@@ -0,0 +1,45 @@
+import * as React from 'react';
+import { Div, Button, Image, Text, Avatar, Icon } from 'react-native-magnus';
+import { useTranslation } from 'react-i18next';
+
+import { FinancialType } from '../utils/MoneyUtils';
+
+export default function ReacordCom({ info }) {
+  const { t } = useTranslation();
+  const { name, amount, avatar, num, type, time } = info;
+
+  const typeInfo = FinancialType.get(type);
+
+  return (
+    <Div
+      bg="white"
+      row
+      alignItems="center"
+      py={10}
+      borderColor="gray100"
+      borderBottomWidth={1}
+    >
+      {avatar ? (
+        <Image w={33} h={33} rounded="circle" source={{ uri: avatar }} />
+      ) : (
+        <Icon
+          w={33}
+          h={33}
+          name="creditcard"
+          bg="yellow500"
+          color="white"
+          rounded="circle"
+        />
+      )}
+
+      <Div flex={1} ml={5}>
+        <Div row>
+          <Text flex={1}>{name}</Text>
+          <Text>{typeInfo.backMoney(amount)}</Text>
+        </Div>
+        <Text>{time}</Text>
+        <Text>{t(typeInfo.name)}</Text>
+      </Div>
+    </Div>
+  );
+}

+ 23 - 0
wallet/WithdrawApplyScreen.tsx

@@ -0,0 +1,23 @@
+import { StackScreenProps } from '@react-navigation/stack';
+import * as React from 'react';
+import { Div, Button, Image, Text, Avatar } from 'react-native-magnus';
+import { ScrollView } from 'react-native-gesture-handler';
+
+import { RootStackParamList } from '../types';
+
+export default function WithdrawApplyScreen({ navigation }: StackScreenProps) {
+  return (
+    <Div bg="gray100">
+      <ScrollView
+        contentContainerStyle={{
+          flexGrow: 1,
+          backgroundColor: '#f2f2f2',
+        }}
+      >
+        <Div>
+          <Text></Text>
+        </Div>
+      </ScrollView>
+    </Div>
+  );
+}