panhui 5 жил өмнө
parent
commit
f6281d3d3c

+ 3 - 0
App.js

@@ -17,6 +17,7 @@ import useCachedResources from './hooks/useCachedResources';
 import BottomTabNavigator from './navigation/BottomTabNavigator';
 import BasicScreens from './navigation/BaseNavigator';
 import words from './flooks/Words';
+import Toast from './flooks/Toast';
 import user from './flooks/User';
 import request from './Utils/RequestUtils';
 import theme from './constants/Theme';
@@ -25,6 +26,8 @@ const Stack = createStackNavigator();
 
 export default function App() {
   const isLoadingComplete = useCachedResources();
+  // 初始化 Toast
+  useModel(Toast, []);
   const { wordsInit, local } = useModel(words, ['local']);
   // Load words  local语言转变,切换语言
   React.useEffect(() => {

+ 16 - 0
Utils/ColorUtils.js

@@ -0,0 +1,16 @@
+const mainColors = [
+  '#22AC38',
+  '#A84200',
+  '#FF5A5A',
+  '#F384EA',
+  '#EC6941',
+  '#00A0E9',
+];
+
+function getRndInteger(min, max) {
+  return Math.floor(Math.random() * (max - min)) + min;
+}
+const getColor = () => {
+  return mainColors[getRndInteger(0, 6)];
+};
+export { getColor, mainColors };

+ 9 - 0
Utils/SvgUtilsNew.js

@@ -178,4 +178,13 @@ export default new Map([
       ],
     },
   ],
+  [
+    'zan',
+    {
+      viewBox: '0 0 160 160',
+      d:
+        'M131.138,100.938 C117.569,134.150 116.462,135.530 108.242,135.530 L60.089,135.530 C58.786,135.530 57.729,134.439 57.729,133.094 L57.729,73.549 C57.955,72.912 58.469,71.851 59.549,70.595 C59.572,70.528 59.585,70.459 59.614,70.393 C59.614,70.393 59.732,70.316 59.910,70.197 C60.960,69.065 62.465,67.811 64.611,66.587 C67.584,64.041 71.242,60.378 73.710,56.056 C79.885,45.248 82.674,31.399 83.029,29.545 C83.534,29.212 89.998,20.201 101.850,25.672 C115.212,31.840 106.765,52.705 105.260,56.087 C104.474,57.854 103.967,59.051 103.626,59.895 C122.396,59.434 146.434,63.503 131.138,100.938 ZM57.662,73.752 C57.587,74.353 57.502,74.277 57.662,73.752 ZM57.729,72.436 L57.729,73.549 C57.702,73.624 57.681,73.689 57.662,73.752 C57.697,73.468 57.729,73.045 57.729,72.436 ZM83.069,29.331 C83.069,29.331 83.055,29.408 83.029,29.545 C82.975,29.581 82.987,29.520 83.069,29.331 ZM55.132,136.017 L34.360,131.388 C33.057,131.388 32.000,130.451 32.000,129.295 L32.000,76.965 C32.000,75.808 33.057,74.871 34.360,74.871 L55.132,70.243 C56.436,70.243 57.493,71.334 57.493,72.679 L57.493,133.581 C57.493,134.926 56.436,136.017 55.132,136.017 Z',
+      defaultWidth: 160,
+    },
+  ],
 ]);

+ 15 - 0
app.json

@@ -27,6 +27,21 @@
     "ios": {
       "supportsTablet": true
     },
+    "android": {
+      "package": "com.izouma.dingdongClient",
+      "versionCode": 1,
+      "permissions": [
+        "CAMERA",
+        "READ_INTERNAL_STORAGE",
+        "WRITE_INTERNAL_STORAGE",
+        "READ_EXTERNAL_STORAGE",
+        "WRITE_EXTERNAL_STORAGE"
+      ]
+    },
+    "androidStatusBar": {
+      "backgroundColor": "#FFC21C",
+      "translucent": false
+    },
     "web": {
       "favicon": "./assets/images/favicon.png"
     },

+ 3 - 3
babel.config.js

@@ -1,5 +1,5 @@
 module.exports = (api) => {
-  api.cache(true)
+  api.cache(true);
   return {
     presets: ['babel-preset-expo'],
     plugins: [
@@ -11,5 +11,5 @@ module.exports = (api) => {
       ],
       'react-native-paper/babel',
     ],
-  }
-}
+  };
+};

+ 28 - 3
components/Button.js

@@ -6,6 +6,7 @@ import {
   Caption,
   withTheme,
   Text,
+  Subheading,
 } from 'react-native-paper';
 
 function MyButton(props) {
@@ -19,6 +20,7 @@ function MyButton(props) {
     theme,
     block,
     style,
+    left,
   } = props;
   let { fontColor } = props;
   const { colors } = theme;
@@ -44,7 +46,7 @@ function MyButton(props) {
       color = colors.error;
       break;
     default:
-      color = colors.primary;
+      color = colors.font;
       break;
   }
 
@@ -63,7 +65,7 @@ function MyButton(props) {
       childNode = () => (
         <Text
           style={[
-            { fontSize: 10 },
+            { fontSize: 10, lineHeight: 10 },
             fontColor ? { color: fontColor } : { color: dark ? '#fff' : color },
           ]}
         >
@@ -74,8 +76,10 @@ function MyButton(props) {
     case 'small':
       contentStyle = { height: 30 };
       childNode = () => (
+        // 14
         <Caption
           style={[
+            { lineHeight: 14 },
             fontColor ? { color: fontColor } : { color: dark ? '#fff' : color },
           ]}
         >
@@ -88,6 +92,7 @@ function MyButton(props) {
       childNode = () => (
         <Paragraph
           style={[
+            { lineHeight: 16 },
             fontColor ? { color: fontColor } : { color: dark ? '#fff' : color },
           ]}
         >
@@ -95,11 +100,29 @@ function MyButton(props) {
         </Paragraph>
       );
       break;
+    case 'large':
+      // 16
+      contentStyle = { width: 120, height: 44 };
+      if (left) {
+        contentStyle = { height: 44, paddingRight: 30 };
+      }
+      childNode = () => (
+        <Subheading
+          style={[
+            { lineHeight: 18 },
+            fontColor ? { color: fontColor } : { color: dark ? '#fff' : color },
+          ]}
+        >
+          {children}
+        </Subheading>
+      );
+      break;
     default:
       contentStyle = { width: 120, height: 30 };
       childNode = () => (
         <Paragraph
           style={[
+            { lineHeight: 16 },
             fontColor ? { color: fontColor } : { color: dark ? '#fff' : color },
           ]}
         >
@@ -124,6 +147,7 @@ function MyButton(props) {
             height: 0,
           },
           shadowOpacity: 0,
+          paddingVertical: 0,
         }}
       >
         {childNode()}
@@ -136,7 +160,6 @@ function MyButton(props) {
           mode={mode}
           color={color}
           contentStyle={contentStyle}
-          onPress={onPressa}
           style={{
             elevation: 0,
             shadowOffset: {
@@ -145,6 +168,8 @@ function MyButton(props) {
             },
             shadowOpacity: 0,
           }}
+          onPress={onPress}
+          compact={left}
         >
           {childNode()}
         </Button>

+ 65 - 0
components/Chip.js

@@ -0,0 +1,65 @@
+import * as React from 'react';
+import { Chip, withTheme } from 'react-native-paper';
+import { getColor } from '../Utils/ColorUtils';
+
+function MyChip(props) {
+  const { children, size, last, onPress, outline } = props;
+  let { color, fontColor } = props;
+  if (!color) {
+    color = getColor();
+  }
+  if (!fontColor) {
+    fontColor = '#fff';
+  }
+  let chipHeight = 20;
+  let fontSize = 12;
+  let fontLine = 12;
+  if (size === 'mini') {
+    fontSize = 10;
+    fontLine = 10;
+    chipHeight = 16;
+  }
+
+  let right = 6;
+  if (last) {
+    right = 0;
+  }
+
+  let mode = 'flat';
+  if (outline) {
+    mode = 'outlined';
+  }
+
+  return (
+    <Chip
+      theme={{ colors: { text: outline ? color : fontColor } }}
+      color={color}
+      mode={mode}
+      style={[
+        {
+          padding: 0,
+          margin: 0,
+          height: chipHeight,
+          marginRight: right,
+          marginBottom: 6,
+        },
+        !outline && { backgroundColor: color },
+        outline && { borderColor: color },
+      ]}
+      textStyle={[
+        {
+          fontSize,
+          margin: 0,
+          padding: 0,
+          lineHeight: fontLine,
+          minHeight: fontLine,
+        },
+      ]}
+      onPress={onPress}
+    >
+      {children}
+    </Chip>
+  );
+}
+
+export default withTheme(MyChip);

+ 1 - 3
components/StyledText.js

@@ -2,7 +2,5 @@ import * as React from 'react';
 import { Text } from 'react-native';
 
 export function MonoText(props) {
-  return (
-    <Text {...props} style={[props.style, { fontFamily: 'space-mono' }]} />
-  );
+  return <Text {...props} style={[props.style]} />;
 }

+ 21 - 8
components/SvgIcon.js

@@ -1,15 +1,22 @@
+/* eslint-disable no-underscore-dangle */
 import * as React from 'react';
-import { svg, path } from 'react-native-svg';
+import Svg, { Path } from 'react-native-svg';
 import { withTheme } from 'react-native-paper';
 import svgMap from '../Utils/SvgUtilsNew';
 
 function Icon(props) {
-  const { name, width, height, type, theme, fillAll } = props;
-  let { color } = props;
+  const { name, type, theme, fillAll, Flip } = props;
+  let { color, width, height } = props;
   const { colors } = theme;
   if (type) {
     color = colors[type];
   }
+  if (!width) {
+    width = 32;
+  }
+  if (!height) {
+    height = 32;
+  }
   const svgInfo = svgMap.get(name);
   const viewBox = svgInfo
     ? svgInfo.viewBox || '0 0 1024 1024'
@@ -21,7 +28,12 @@ function Icon(props) {
         },
       ]
     : [];
-  console.log(color);
+  let transform = '';
+  if (Flip) {
+    transform = `rotate(180 ${svgInfo.defaultWidth / 2} ${
+      svgInfo.defaultWidth / 2
+    })`;
+  }
   const pathComList = () => {
     return pathList.map((item, index) => {
       const pathProps = { ...item };
@@ -33,14 +45,15 @@ function Icon(props) {
         pathProps.stroke = color;
       }
       delete pathProps.viewBox;
-      console.log(pathProps);
-      return <path {...pathProps} key={index} />;
+      delete pathProps.defaultWidth;
+      return <Path {...pathProps} key={index} transform={transform} />;
     });
   };
+
   return (
-    <svg width={width} height={height} viewBox={viewBox}>
+    <Svg width={width} height={height} viewBox={viewBox}>
       {pathComList()}
-    </svg>
+    </Svg>
   );
 }
 

+ 42 - 6
components/Text.js

@@ -10,7 +10,7 @@ import {
 
 function MyText(props) {
   const { type, size, children, bold } = props;
-  let { color, theme, style } = props;
+  let { color, theme, style, center } = props;
   const { colors } = theme;
   if (type) {
     color = colors[type];
@@ -31,39 +31,75 @@ function MyText(props) {
       fontWeight: 'bold',
     };
   }
+  if (center) {
+    style = {
+      ...style,
+      textAlign: 'center',
+    };
+  }
 
   switch (size) {
     case 'h1':
       // 24
       return (
-        <Headline theme={theme} style={{ ...style }}>
+        <Headline
+          theme={theme}
+          style={{ ...style }}
+          numberOfLines={1}
+          ellipsizeMode="tail"
+          align="center"
+        >
           {children}
         </Headline>
       );
     case 's1':
       // 16
       return (
-        <Subheading theme={theme} style={{ ...style }}>
+        <Subheading
+          theme={theme}
+          style={{ ...style }}
+          numberOfLines={1}
+          ellipsizeMode="tail"
+        >
           {children}
         </Subheading>
       );
     case 'c1':
       // 12
       return (
-        <Caption theme={theme} style={{ ...style }}>
+        <Caption
+          theme={theme}
+          style={{ ...style }}
+          numberOfLines={1}
+          ellipsizeMode="tail"
+        >
           {children}
         </Caption>
       );
     case 'c2':
       // 10
       return (
-        <Text theme={theme} style={[{ fontSize: 10 }, { ...style }]}>
+        <Text
+          theme={theme}
+          style={[{ fontSize: 10 }, { ...style }]}
+          numberOfLines={1}
+          ellipsizeMode="tail"
+        >
           {children}
         </Text>
       );
     default:
       // 14
-      return <Paragraph theme={theme}>{children}</Paragraph>;
+      return (
+        <Paragraph
+          theme={theme}
+          numberOfLines={1}
+          ellipsizeMode="tail"
+          style={{ ...style }}
+        >
+          {children}
+        </Paragraph>
+      );
   }
 }
 

+ 3 - 3
constants/Theme.js

@@ -1,4 +1,4 @@
-import { DefaultTheme } from 'react-native-paper'
+import { DefaultTheme } from 'react-native-paper';
 
 const theme = {
   ...DefaultTheme,
@@ -11,6 +11,6 @@ const theme = {
     info: '#B4B4B4',
     lightInfo: '#F0F0F0',
   },
-}
+};
 
-export default theme
+export default theme;

+ 0 - 5
flooks/Banner.js

@@ -1,5 +0,0 @@
-const banner = (now) => ({
-  bannerList: [],
-});
-
-export default banner;

+ 2 - 15
hooks/useCachedResources.js

@@ -1,10 +1,8 @@
 /* eslint-disable global-require */
 import { Ionicons } from '@expo/vector-icons';
-import useModel from 'flooks';
 import * as Font from 'expo-font';
 import * as SplashScreen from 'expo-splash-screen';
 import * as React from 'react';
-import Toast from '../flooks/Toast';
 
 export default function useCachedResources() {
   const [isLoadingComplete, setLoadingComplete] = React.useState(false);
@@ -14,24 +12,13 @@ export default function useCachedResources() {
     async function loadResourcesAndDataAsync() {
       try {
         SplashScreen.preventAutoHideAsync();
-        // 初始化 Toast
-        useModel(Toast, []);
         // Load fonts
 
-        await Font.loadAsync(
-          'antoutline',
-          // eslint-disable-next-line
-          require('@ant-design/icons-react-native/fonts/antoutline.ttf')
-        );
-
-        await Font.loadAsync(
-          'antfill',
-          // eslint-disable-next-line
-          require('@ant-design/icons-react-native/fonts/antfill.ttf')
-        );
         await Font.loadAsync({
           ...Ionicons.font,
           'space-mono': require('../assets/fonts/SpaceMono-Regular.ttf'),
+          antoutline: require('@ant-design/icons-react-native/fonts/antoutline.ttf'),
+          antfill: require('@ant-design/icons-react-native/fonts/antfill.ttf'),
         });
       } catch (e) {
         // We might want to provide this error information to an error reporting service

+ 4 - 4
navigation/BottomTabNavigator.jsx

@@ -1,7 +1,7 @@
 import * as React from 'react';
 import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
-import HomeScreen from '../screens/Home/HomeScreen';
-import LinksScreen from '../screens/Home/LinksScreen';
+import HomeScreen from '../screens/Main/HomeScreen';
+import LinksScreen from '../screens/Main/LinksScreen';
 import Icon from '../components/SvgIcon';
 import Text from '../components/Text';
 
@@ -43,7 +43,7 @@ export default function BottomTabNavigator() {
           ),
         }}
       />
-      <BottomTab.Screen
+      {/* <BottomTab.Screen
         name="User"
         component={LinksScreen}
         options={{
@@ -60,7 +60,7 @@ export default function BottomTabNavigator() {
             />
           ),
         }}
-      />
+      /> */}
     </BottomTab.Navigator>
   );
 }

+ 3 - 2
package.json

@@ -12,6 +12,7 @@
     "preset": "jest-expo"
   },
   "dependencies": {
+    "@ant-design/icons-react-native": "^2.2.1",
     "@ant-design/react-native": "^3.3.0",
     "@babel/polyfill": "^7.10.1",
     "@expo/vector-icons": "^10.0.0",
@@ -49,11 +50,11 @@
     "react-native-reanimated": "^1.7.1",
     "react-native-safe-area-context": "0.7.3",
     "react-native-screens": "~2.2.0",
+    "react-native-svg": "11.0.1",
     "react-native-tab-view": "^2.14.2",
     "react-native-ui-lib": "^5.8.1",
     "react-native-web": "^0.11.7",
-    "umi-request": "^1.3.3",
-    "react-native-svg": "11.0.1"
+    "umi-request": "^1.3.3"
   },
   "devDependencies": {
     "@babel/cli": "^7.10.1",

+ 0 - 92
screens/Home/HomeScreen.jsx

@@ -1,92 +0,0 @@
-import * as WebBrowser from 'expo-web-browser';
-import * as React from 'react';
-import { Platform, StyleSheet, View } from 'react-native';
-import { ScrollView } from 'react-native-gesture-handler';
-import {
-  WhiteSpace,
-  WingBlank,
-  Carousel,
-  Grid,
-} from '@ant-design/react-native';
-import {
-  Paragraph,
-  Menu,
-  Divider,
-  Provider,
-  Text,
-  Card,
-} from 'react-native-paper';
-import Button from '../../components/Button';
-import Header from '../../components/HomeHeader';
-import Icon from '../../components/SvgIcon';
-
-const data = [];
-
-export default function HomeScreen() {
-  return (
-    <ScrollView style={styles.container}>
-      <Header />
-      <WingBlank>
-        <Button block size="small" type="info" onPress={() => {}}>
-          搜索
-        </Button>
-      </WingBlank>
-
-      <View style={styles.main}>
-        <Carousel style={styles.wrapper} selectedIndex={2} autoplay infinite>
-          <Card>
-            <Card.Cover
-              source={{ uri: 'https://picsum.photos/700' }}
-              resizeMode="center"
-              borderRadius={0}
-            />
-          </Card>
-          <Card>
-            <Card.Cover
-              source={{ uri: 'https://picsum.photos/700' }}
-              resizeMode="center"
-              borderRadius={0}
-            />
-          </Card>
-          <Card>
-            <Card.Cover
-              source={{ uri: 'https://picsum.photos/700' }}
-              resizeMode="center"
-              borderRadius={0}
-            />
-          </Card>
-        </Carousel>
-
-        <Grid
-          data={data}
-          columnNum={3}
-          itemStyle={{ height: 150, backgroundColor: '#ffff00' }}
-        />
-      </View>
-    </ScrollView>
-  );
-}
-HomeScreen.navigationOptions = {
-  header: null,
-};
-
-const styles = StyleSheet.create({
-  container: {
-    flex: 1,
-    backgroundColor: '#fff',
-  },
-  contentStyle: {
-    height: 20,
-  },
-  text: {
-    fontSize: 10,
-    color: '#AAAAAA',
-  },
-  main: {
-    flex: 1,
-    paddingTop: 10,
-  },
-  wrapper: {
-    height: 80,
-  },
-});

+ 7 - 1
screens/InitAppScreen.jsx

@@ -15,7 +15,13 @@ export default function LinksScreen() {
     getUser();
   });
   return (
-    <Flex justify="center" style={{ flex: 1, backgroundColor: '#FFC21C' }}>
+    <Flex
+      justify="center"
+      style={{
+        flex: 1,
+        backgroundColor: '#FFC21C',
+      }}
+    >
       <Avatar.Image size={80} source={splash} />
     </Flex>
   );

+ 42 - 0
screens/Main/Home/Banner.jsx

@@ -0,0 +1,42 @@
+import * as WebBrowser from 'expo-web-browser';
+import * as React from 'react';
+import { StyleSheet } from 'react-native';
+import { Carousel } from '@ant-design/react-native';
+import { Card } from 'react-native-paper';
+import useModel from 'flooks';
+import HomeModel from './model';
+
+export default function Banner() {
+  const { bannerList } = useModel(HomeModel);
+  const [index, setIndex] = React.useState(0);
+  if (bannerList.length > 0) {
+    return (
+      <Carousel
+        style={styles.wrapper}
+        selectedIndex={index}
+        autoplay
+        infinite
+        afterChange={setIndex}
+      >
+        {bannerList.map((item) => (
+          <Card key={item.id}>
+            <Card.Cover
+              source={{ uri: item.pic }}
+              resizeMode="cover"
+              style={{ height: 80 }}
+              borderRadius={0}
+            />
+          </Card>
+        ))}
+      </Carousel>
+    );
+  } else {
+    return null;
+  }
+}
+
+const styles = StyleSheet.create({
+  wrapper: {
+    height: 80,
+  },
+});

+ 114 - 0
screens/Main/Home/List.jsx

@@ -0,0 +1,114 @@
+import * as WebBrowser from 'expo-web-browser';
+import * as React from 'react';
+import { StyleSheet, View } from 'react-native';
+import { WingBlank, Flex } from '@ant-design/react-native';
+import { Menu } from 'react-native-paper';
+import { useBoolean } from '@umijs/hooks';
+import Button from '../../../components/Button';
+import MerchantCom from './MerchantCom';
+
+const firstMenus = new Map([
+  ['综合排序', { id: 1 }],
+  ['好评优先', { id: 2 }],
+  ['起送价最低', { id: 3 }],
+  ['配送最快', { id: 4 }],
+  ['配送费最低', { id: 5 }],
+  ['人均从低到高', { id: 6 }],
+  ['人均从高到低', { id: 7 }],
+  ['通用排序', { id: 8 }],
+]);
+export default function List() {
+  const firstSortMenu = useBoolean(false);
+
+  const menuMap = (_map) => {
+    return _map.forEach((value, key) => {
+      return (
+        <Menu.Item
+          key={value.id}
+          onPress={() => {
+            console.log(value.id);
+          }}
+          title={key}
+        />
+      );
+    });
+  };
+
+  return (
+    <WingBlank>
+      <Flex>
+        <Button text size="large" left onPress={() => {}}>
+          推荐商家
+        </Button>
+        {/* <View style={{ width: 33 }} /> */}
+        <Button text size="large" fontColor="#000" left onPress={() => {}}>
+          发现美食
+        </Button>
+      </Flex>
+
+      <Flex>
+        <Menu
+          visible={firstSortMenu.state}
+          onDismiss={firstSortMenu.setFalse}
+          anchor={
+            <Button
+              text
+              size="small"
+              fontColor="#000"
+              left
+              onPress={firstSortMenu.setTrue}
+            >
+              综合排序
+            </Button>
+          }
+        >
+          <Menu.Item
+            onPress={() => {
+              console.log('综合排序');
+            }}
+            title="综合排序"
+          />
+          <Menu.Item
+            onPress={() => {
+              console.log('好评优先');
+            }}
+            title="好评优先"
+          />
+        </Menu>
+        <Button
+          text
+          size="small"
+          fontColor="#000"
+          left
+          onPress={firstSortMenu.setTrue}
+        >
+          距离
+        </Button>
+        <Button
+          text
+          size="small"
+          fontColor="#000"
+          left
+          onPress={firstSortMenu.setTrue}
+        >
+          销量
+        </Button>
+        <Button
+          text
+          size="small"
+          fontColor="#000"
+          left
+          onPress={firstSortMenu.setTrue}
+        >
+          筛选
+        </Button>
+      </Flex>
+
+      <View>
+        <MerchantCom />
+      </View>
+    </WingBlank>
+  );
+}
+
+const styles = StyleSheet.create({});

+ 117 - 0
screens/Main/Home/Menu.jsx

@@ -0,0 +1,117 @@
+import * as WebBrowser from 'expo-web-browser';
+import * as React from 'react';
+import { StyleSheet, View } from 'react-native';
+import { Flex, WingBlank } from '@ant-design/react-native';
+import { Card } from 'react-native-paper';
+import Text from '../../../components/Text';
+
+export default function RecommendStore() {
+  return (
+    <WingBlank style={{ marginTop: 15, marginBottom: 5 }}>
+      <Flex style={styles.content} justify="between">
+        <Text size="s1" bold>
+          新店推荐
+        </Text>
+        <Text size="c2">更多新店 〉</Text>
+      </Flex>
+
+      <Flex style={styles.content2}>
+        <Flex.Item style={{ paddingHorizontal: 5 }}>
+          <Card elevation={0} style={styles.card}>
+            <Card.Cover
+              style={styles.image2}
+              resizeMode="cover"
+              source={{ uri: 'https://picsum.photos/700' }}
+            />
+            <Card.Content style={styles.main2}>
+              <Text size="c2" type="info" center>
+                按摩
+              </Text>
+            </Card.Content>
+          </Card>
+        </Flex.Item>
+        <Flex.Item style={{ paddingHorizontal: 5 }}>
+          <Card elevation={0} style={styles.card}>
+            <Card.Cover
+              style={styles.image2}
+              resizeMode="cover"
+              source={{ uri: 'https://picsum.photos/700' }}
+            />
+            <Card.Content style={styles.main2}>
+              <Text size="c2" type="info" center>
+                按摩
+              </Text>
+            </Card.Content>
+          </Card>
+        </Flex.Item>
+        <Flex.Item style={{ paddingHorizontal: 5 }}>
+          <Card elevation={0} style={styles.card}>
+            <Card.Cover
+              style={styles.image2}
+              resizeMode="cover"
+              source={{ uri: 'https://picsum.photos/700' }}
+            />
+            <Card.Content style={styles.main2}>
+              <Text size="c2" type="info" center>
+                按摩
+              </Text>
+            </Card.Content>
+          </Card>
+        </Flex.Item>
+        <Flex.Item style={{ paddingHorizontal: 5 }}>
+          <Card elevation={0} style={styles.card}>
+            <Card.Cover
+              style={styles.image2}
+              resizeMode="cover"
+              source={{ uri: 'https://picsum.photos/700' }}
+            />
+            <Card.Content style={styles.main2}>
+              <Text size="c2" type="info" center>
+                按摩
+              </Text>
+            </Card.Content>
+          </Card>
+        </Flex.Item>
+        <Flex.Item style={{ paddingHorizontal: 5 }}>
+          <Card elevation={0} style={styles.card}>
+            <Card.Cover
+              style={styles.image2}
+              resizeMode="cover"
+              source={{ uri: 'https://picsum.photos/700' }}
+            />
+            <Card.Content style={styles.main2}>
+              <Text size="c2" type="info" center>
+                按摩
+              </Text>
+            </Card.Content>
+          </Card>
+        </Flex.Item>
+      </Flex>
+    </WingBlank>
+  );
+}
+
+const styles = StyleSheet.create({
+  image2: {
+    width: 47,
+    height: 47,
+    alignSelf: 'center',
+    marginHorizontal: 10,
+    borderRadius: 3,
+  },
+  main2: {
+    marginTop: 7,
+    paddingHorizontal: 0,
+  },
+  card: {
+    marginVertical: 5,
+    borderWidth: 0,
+    elevation: 0,
+    shadowOffset: {
+      width: 0,
+      height: 0,
+    },
+    shadowOpacity: 0,
+    shadowRadius: 0,
+  },
+});

+ 104 - 0
screens/Main/Home/MerchantCom.jsx

@@ -0,0 +1,104 @@
+import * as WebBrowser from 'expo-web-browser';
+import * as React from 'react';
+import { StyleSheet, View, Image } from 'react-native';
+import { Flex, WhiteSpace, WingBlank, Badge } from '@ant-design/react-native';
+import Text from '../../../components/Text';
+import Chip from '../../../components/Chip';
+import Icon from '../../../components/SvgIcon';
+
+// 首页商家组件
+
+export default function MerchantCom() {
+  return (
+    <Flex align="start" style={styles.merchant}>
+      <Image
+        style={styles.image}
+        resizeMode="cover"
+        source={{ uri: 'https://picsum.photos/700' }}
+      />
+      <Flex.Item style={styles.main}>
+        <Text size="s1" bold>
+          111
+        </Text>
+        <Flex>
+          <Chip>连锁品牌</Chip>
+          <Chip>百年老店</Chip>
+        </Flex>
+        <Flex>
+          <Flex>
+            <Icon name="zan" type="primary" width={18} height={18} />
+            <Text size="c1" type="primary">
+              9999+
+            </Text>
+          </Flex>
+          <Flex style={styles.text}>
+            <Icon name="zan" Flip color="#000" width={18} height={18} />
+            <Text size="c1" type="info">
+              9999+
+            </Text>
+          </Flex>
+          <Flex style={styles.text}>
+            <Text size="c1" type="info">
+              月售9999+
+            </Text>
+          </Flex>
+        </Flex>
+        <Flex>
+          <Text size="c1" type="info">
+            起送$ 10
+          </Text>
+          <Flex.Item style={styles.text}>
+            <Text size="c1" type="info">
+              配送$ 10
+            </Text>
+          </Flex.Item>
+          <Text size="c1" type="info">
+            20分钟
+          </Text>
+          <View style={styles.text}>
+            <Text size="c1" type="info">
+              4.2km
+            </Text>
+          </View>
+        </Flex>
+        <Flex style={styles.label2}>
+          <Chip size="mini" color="#FFE3B9" fontColor="#FF0000">
+            “喜欢您来金拱门喜欢您来金拱门”
+          </Chip>
+          <Chip size="mini" color="#FFE3B9" fontColor="#FF0000">
+            “喜欢您来金拱门喜欢您来金拱门”
+          </Chip>
+        </Flex>
+        <Flex style={styles.label2} wrap="wrap">
+          <Chip size="mini" outline color="#FF0000">
+            12减5
+          </Chip>
+        </Flex>
+      </Flex.Item>
+    </Flex>
+  );
+}
+
+const styles = StyleSheet.create({
+  image: {
+    width: 67,
+    height: 67,
+    borderRadius: 3,
+  },
+  text: {
+    marginLeft: 6,
+  },
+  label2: {
+    marginTop: 4,
+    overflow: 'hidden',
+  },
+  main: {
+    marginLeft: 10,
+    borderBottomWidth: 1,
+    borderBottomColor: '#C9C9C9',
+    paddingBottom: 4,
+  },
+  merchant: {
+    paddingTop: 10,
+  },
+});

+ 115 - 0
screens/Main/Home/RecommendStore.jsx

@@ -0,0 +1,115 @@
+import * as WebBrowser from 'expo-web-browser';
+import * as React from 'react';
+import { StyleSheet, View } from 'react-native';
+import { Flex, WingBlank } from '@ant-design/react-native';
+import { Card } from 'react-native-paper';
+import Text from '../../../components/Text';
+
+export default function RecommendStore() {
+  return (
+    <WingBlank style={{ marginTop: 15, marginBottom: 5 }}>
+      <Flex style={styles.content} justify="between">
+        <Text size="s1" bold>
+          新店推荐
+        </Text>
+        <Text size="c2">更多新店 〉</Text>
+      </Flex>
+
+      <Flex style={styles.content2}>
+        <Flex.Item style={{ paddingHorizontal: 5 }}>
+          <Card elevation={0} style={styles.card}>
+            <Card.Cover
+              style={styles.image2}
+              resizeMode="cover"
+              source={{ uri: 'https://picsum.photos/700' }}
+            />
+            <Card.Content style={styles.main2}>
+              <Text size="c2" type="info" center>
+                麦当劳(奥体大街)
+              </Text>
+              <Text size="c2" color="#FF6C00" center>
+                1.1km
+              </Text>
+            </Card.Content>
+          </Card>
+        </Flex.Item>
+        <Flex.Item style={{ paddingHorizontal: 5 }}>
+          <Card elevation={0} style={styles.card}>
+            <Card.Cover
+              style={styles.image2}
+              resizeMode="cover"
+              source={{ uri: 'https://picsum.photos/700' }}
+            />
+            <Card.Content style={styles.main2}>
+              <Text size="c2" type="info" center>
+                麦当劳(奥体大街)
+              </Text>
+              <Text size="c2" color="#FF6C00" center>
+                1.1km
+              </Text>
+            </Card.Content>
+          </Card>
+        </Flex.Item>
+        <Flex.Item style={{ paddingHorizontal: 5 }}>
+          <Card elevation={0} style={styles.card}>
+            <Card.Cover
+              style={styles.image2}
+              resizeMode="cover"
+              source={{ uri: 'https://picsum.photos/700' }}
+            />
+            <Card.Content style={styles.main2}>
+              <Text size="c2" type="info" center>
+                麦当劳(奥体大街)
+              </Text>
+              <Text size="c2" color="#FF6C00" center>
+                1.1km
+              </Text>
+            </Card.Content>
+          </Card>
+        </Flex.Item>
+        <Flex.Item style={{ paddingHorizontal: 5 }}>
+          <Card elevation={0} style={styles.card}>
+            <Card.Cover
+              style={styles.image2}
+              resizeMode="cover"
+              source={{ uri: 'https://picsum.photos/700' }}
+            />
+            <Card.Content style={styles.main2}>
+              <Text size="c2" type="info" center>
+                麦当劳(奥体大街)
+              </Text>
+              <Text size="c2" color="#FF6C00" center>
+                1.1km
+              </Text>
+            </Card.Content>
+          </Card>
+        </Flex.Item>
+      </Flex>
+    </WingBlank>
+  );
+}
+
+const styles = StyleSheet.create({
+  image2: {
+    width: 47,
+    height: 47,
+    alignSelf: 'center',
+    marginHorizontal: 10,
+    borderRadius: 3,
+  },
+  main2: {
+    marginTop: 7,
+    paddingHorizontal: 0,
+  },
+  card: {
+    marginVertical: 5,
+    borderWidth: 0,
+    elevation: 0,
+    shadowOffset: {
+      width: 0,
+      height: 0,
+    },
+    shadowOpacity: 0,
+    shadowRadius: 0,
+  },
+});

+ 145 - 0
screens/Main/Home/SpecialArea.jsx

@@ -0,0 +1,145 @@
+import * as WebBrowser from 'expo-web-browser';
+import * as React from 'react';
+import { StyleSheet } from 'react-native';
+import { Flex, WingBlank } from '@ant-design/react-native';
+import { Card } from 'react-native-paper';
+import Text from '../../../components/Text';
+
+// 优惠专区
+export default function SpecialArea() {
+  return (
+    <>
+      <WingBlank style={{ marginTop: 10, marginBottom: 5 }}>
+        <Text size="s1" bold>
+          优惠专区
+        </Text>
+        <Flex style={styles.content}>
+          <Flex.Item style={{ paddingHorizontal: 1.5 }}>
+            <Card>
+              <Card.Cover
+                style={styles.image}
+                resizeMode="cover"
+                source={{ uri: 'https://picsum.photos/700' }}
+              />
+              <Card.Content>
+                <Text size="s1">麦当劳(奥体大街)</Text>
+                <Text size="c2">
+                  倒计时
+                  <Text size="c2" type="error">
+                    {' '}
+                    15小时20分43秒
+                  </Text>
+                </Text>
+              </Card.Content>
+            </Card>
+          </Flex.Item>
+          <Flex.Item style={{ paddingHorizontal: 1.5 }}>
+            <Card>
+              <Card.Cover
+                style={styles.image}
+                resizeMode="cover"
+                source={{ uri: 'https://picsum.photos/700' }}
+              />
+              <Card.Content>
+                <Text size="s1">麦当劳(奥体大街)</Text>
+                <Text size="c2">
+                  倒计时
+                  <Text size="c2" type="error">
+                    {' '}
+                    15小时20分43秒
+                  </Text>
+                </Text>
+              </Card.Content>
+            </Card>
+          </Flex.Item>
+        </Flex>
+        <Flex style={styles.content2}>
+          <Flex.Item style={{ paddingHorizontal: 1.5 }}>
+            <Card>
+              <Card.Cover
+                style={styles.image2}
+                resizeMode="cover"
+                source={{ uri: 'https://picsum.photos/700' }}
+              />
+              <Card.Content style={styles.main2}>
+                <Text size="c2">麦当劳(奥体大街)</Text>
+              </Card.Content>
+            </Card>
+          </Flex.Item>
+          <Flex.Item style={{ paddingHorizontal: 1.5 }}>
+            <Card>
+              <Card.Cover
+                style={styles.image2}
+                resizeMode="cover"
+                source={{ uri: 'https://picsum.photos/700' }}
+              />
+              <Card.Content style={styles.main2}>
+                <Text size="c2">麦当劳(奥体大街)</Text>
+              </Card.Content>
+            </Card>
+          </Flex.Item>
+          <Flex.Item style={{ paddingHorizontal: 1.5 }}>
+            <Card>
+              <Card.Cover
+                style={styles.image2}
+                resizeMode="cover"
+                source={{ uri: 'https://picsum.photos/700' }}
+              />
+              <Card.Content style={styles.main2}>
+                <Text size="c2">麦当劳(奥体大街)</Text>
+              </Card.Content>
+            </Card>
+          </Flex.Item>
+          <Flex.Item style={{ paddingHorizontal: 1.5 }}>
+            <Card>
+              <Card.Cover
+                style={styles.image2}
+                resizeMode="cover"
+                source={{ uri: 'https://picsum.photos/700' }}
+              />
+              <Card.Content style={styles.main2}>
+                <Text size="c2">麦当劳(奥体大街)</Text>
+              </Card.Content>
+            </Card>
+          </Flex.Item>
+        </Flex>
+      </WingBlank>
+      <WingBlank style={{ marginTop: 15, marginBottom: 5 }}>
+        <Text size="s1" bold>
+          优惠专区2
+        </Text>
+
+        <Card.Cover
+          style={styles.imageMain}
+          resizeMode="cover"
+          source={{ uri: 'https://picsum.photos/700' }}
+        />
+      </WingBlank>
+    </>
+  );
+}
+
+const styles = StyleSheet.create({
+  image: {
+    height: 77,
+  },
+  image2: {
+    height: 80,
+  },
+  main2: {
+    paddingBottom: 6,
+    paddingVertical: 6,
+    paddingHorizontal: 10,
+  },
+  content: {
+    marginTop: 5,
+  },
+  content2: {
+    marginTop: 3,
+  },
+  imageMain: {
+    height: 74,
+    borderRadius: 3,
+    marginTop: 5,
+  },
+});

+ 23 - 0
screens/Main/Home/model.js

@@ -0,0 +1,23 @@
+import request from '../../../Utils/RequestUtils';
+
+const HomeModel = (now) => ({
+  bannerList: [],
+  initBanner() {
+    now({
+      bannerList: [],
+    });
+    return request
+      .get('/banner/all', {
+        sort: {
+          type: 'TOP',
+        },
+      })
+      .then((res) => {
+        now({
+          bannerList: res.content,
+        });
+      });
+  },
+});
+
+export default HomeModel;

+ 72 - 0
screens/Main/HomeScreen.jsx

@@ -0,0 +1,72 @@
+import * as WebBrowser from 'expo-web-browser';
+import * as React from 'react';
+import { StyleSheet, View } from 'react-native';
+import { ScrollView } from 'react-native-gesture-handler';
+import { WingBlank, Flex } from '@ant-design/react-native';
+import { Menu } from 'react-native-paper';
+import useModel from 'flooks';
+import { useMount, useToggle } from '@umijs/hooks';
+import Button from '../../components/Button';
+import Header from '../../components/HomeHeader';
+import Text from '../../components/Text';
+import Banner from './Home/Banner';
+import MenuCom from './Home/Menu';
+import List from './Home/List';
+import RecommendStore from './Home/RecommendStore';
+import SpecialArea from './Home/SpecialArea';
+import HomeModel from './Home/model';
+
+const tabs = [
+  { title: 'First Tab' },
+  { title: 'Second Tab' },
+  { title: 'Third Tab' },
+];
+
+export default function HomeScreen() {
+  const { initBanner } = useModel(HomeModel, []);
+
+  useMount(() => {
+    initBanner();
+  });
+
+  return (
+    <ScrollView style={styles.container}>
+      <Header />
+      <WingBlank>
+        <Button block size="small" type="info" onPress={() => {}}>
+          搜索
+        </Button>
+      </WingBlank>
+
+      <View style={styles.main}>
+        <Banner />
+        <MenuCom />
+        <SpecialArea />
+        <RecommendStore />
+      </View>
+      <List />
+    </ScrollView>
+  );
+}
+HomeScreen.navigationOptions = {
+  header: null,
+};
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    backgroundColor: '#fff',
+  },
+  contentStyle: {
+    height: 20,
+  },
+  text: {
+    fontSize: 10,
+    color: '#AAAAAA',
+  },
+  main: {
+    flex: 1,
+    paddingTop: 10,
+    width: '100%',
+  },
+});

+ 0 - 0
screens/Home/LinksScreen.jsx → screens/Main/LinksScreen.jsx