panhui 5 lat temu
rodzic
commit
316778f8da

+ 2 - 2
App.js

@@ -53,8 +53,8 @@ export default function App() {
           routes: [
             {
               // name: initName,
-              // name: 'MerchantDetail',
-              name: 'Evaluate',
+              name: 'MerchantDetail',
+              // name: 'Collection',
             },
           ],
         })

+ 21 - 5
Utils/TotastUtils.js

@@ -1,3 +1,5 @@
+/* eslint-disable no-use-before-define */
+/* eslint-disable no-console */
 import React from 'react';
 import { Modal } from '@ant-design/react-native';
 import { Linking } from 'expo';
@@ -31,7 +33,7 @@ export function alert(title, content, submitEvent) {
     ]
   );
 }
-export function operation(list) {
+export function operation() {
   Modal.operation([
     { text: '标为未读', onPress: () => console.log('标为未读被点击了') },
     { text: '置顶聊天', onPress: () => console.log('置顶聊天被点击了') },
@@ -39,7 +41,6 @@ export function operation(list) {
 }
 
 export function connectKefu(orderId) {
-  console.log(orderId);
   Modal.alert(
     '',
     <Text style={{ marginHorizontal: 15 }} more>
@@ -49,9 +50,7 @@ export function connectKefu(orderId) {
     [
       {
         text: '客服电话',
-        onPress: () => {
-          Linking.openURL('tel:+123456789');
-        },
+        onPress: connectKefuOn,
         style: { color: '#000', fontSize: 12, lineHeight: 30 },
       },
       {
@@ -64,3 +63,20 @@ export function connectKefu(orderId) {
     ]
   );
 }
+
+export function connectKefuOn() {
+  Linking.openURL('tel:+123456789');
+}
+
+export function prompt(title, plac, defaultValue, callBack) {
+  Modal.prompt(
+    title || '',
+    '',
+    (val) => {
+      if (callBack) callBack(val);
+    },
+    'default',
+    defaultValue || '',
+    [plac || '']
+  );
+}

BIN
assets/images/icon.png


+ 10 - 6
components/Header.js

@@ -1,22 +1,26 @@
+/* eslint-disable react/style-prop-object */
 import * as React from 'react';
-import { Platform } from 'react-native';
+import { View } from 'react-native';
 import { StatusBar } from 'expo-status-bar';
-import Constants from 'expo-constants';
 import { Appbar } from 'react-native-paper';
 import { goBack } from '../navigation/RootNavigation';
 
-export default function Header() {
+export default function Header({ title, noBack }) {
   return (
     <>
       <StatusBar backgroundColor="#FFC21C" style="light" translucent />
 
       <Appbar.Header dark>
-        <Appbar.BackAction onPress={goBack} />
+        {!noBack && <Appbar.BackAction onPress={goBack} />}
         <Appbar.Content
-          title="忘记密码"
+          title={title}
           titleStyle={{ textAlign: 'center', fontSize: 16 }}
         />
-        <Appbar.Action icon="dots-vertical" />
+        {!noBack && (
+          <Appbar.Action
+            icon={() => <View style={{ width: 24, height: 24 }} />}
+          />
+        )}
       </Appbar.Header>
     </>
   );

+ 3 - 3
components/ImagePicker.js

@@ -43,15 +43,15 @@ const _pickImage = (aspect, loading) => {
 };
 
 export default function ImagePickerCom(props) {
-  const { aspect, img, setImg, cancelEvent } = props;
+  const { aspect, img, setImg, cancelEvent, h, w } = props;
   const { loading, clearLoading } = useModel(Toast, []);
 
   return (
     <Div mr="sm" mb="sm">
       <Button
         bg="brand200"
-        h={67}
-        w={67}
+        h={h || 67}
+        w={w || 67}
         rounded="xs"
         onPress={() => {
           _pickImage(aspect || [1, 1], loading)

+ 22 - 0
flooks/User.js

@@ -60,6 +60,28 @@ const app = (now) => ({
       success('退出成功');
     });
   },
+  uploadInfo({ ...info }) {
+    const { id, getUser } = now();
+    const { loading, warnning, success } = now(Toast);
+    loading();
+    return request
+      .post('/user/save', {
+        data: {
+          ...info,
+          id,
+        },
+      })
+      .then(() => {
+        return getUser();
+      })
+      .then(() => {
+        success('更新成功');
+        return Promise.resolve();
+      })
+      .catch((e) => {
+        warnning(e.error);
+      });
+  },
 });
 
 export default app;

+ 16 - 3
navigation/BaseNavigator.jsx

@@ -3,25 +3,31 @@ import Login from '../screens/Login';
 import MerchantDetailScreen from '../screens/Detail/MerchantDetailScreen';
 import InitAppScreen from '../screens/InitAppScreen';
 
+// 订单
 import OrderDetail from '../screens/Order/OrderDetailScreen';
 import Complaint from '../screens/Order/ComplaintScreen';
 import ComplaintNext from '../screens/Order/ComplaintNextScreen';
 import EvaluateScreen from '../screens/Order/EvaluateScreen';
 
+// 用户
+import Setting from '../screens/User/SettingScreen';
+import Coupon from '../screens/userCoupon/CouponScreen';
+import Collection from '../screens/User/CollectionScreen';
+
 export default function BasicScreens(Screen) {
   return (
     <>
       <Screen name="InitApp" component={InitAppScreen} />
       {/* 登录路由 */}
       {Login(Screen)}
-
       {/* 详情页 */}
       <Screen
         name="MerchantDetail"
         component={MerchantDetailScreen}
         initialParams={{ merchantId: 189 }}
       />
-
+      {/* ****************************订单******************************** */}
+      {/* 订单详情 */}
       <Screen
         name="OrderDetail"
         initialParams={{ orderId: 386 }}
@@ -43,7 +49,7 @@ export default function BasicScreens(Screen) {
         }}
         component={ComplaintNext}
       />
-      {/* 投诉 2 */}
+      {/* 评论 */}
       <Screen
         name="Evaluate"
         initialParams={{
@@ -51,6 +57,13 @@ export default function BasicScreens(Screen) {
         }}
         component={EvaluateScreen}
       />
+      {/* *************************用户*********************************** */}
+      {/* 设置 */}
+      <Screen name="Setting" component={Setting} />
+      {/* 优惠券 */}
+      <Screen name="Coupon" component={Coupon} />
+      {/* 我的收藏 */}
+      <Screen name="Collection" component={Collection} />
     </>
   );
 }

+ 1 - 1
navigation/BottomTabNavigator.jsx

@@ -10,7 +10,7 @@ const BottomTab = createBottomTabNavigator();
 
 export default function BottomTabNavigator() {
   return (
-    <BottomTab.Navigator initialRouteName="Order">
+    <BottomTab.Navigator initialRouteName="User">
       <BottomTab.Screen
         name="Home"
         component={HomeScreen}

+ 1 - 1
screens/Detail/Cart.jsx

@@ -162,7 +162,7 @@ export default function Cart() {
               onPress={() => {}}
               loading={cartRequest.loading}
             >
-              {!canSubmit ? `¥${startingAmount}起送` : '去结算'}
+              {!canSubmit ? `¥${startingAmount || 0}起送` : '去结算'}
             </Button>
           </Flex>
         </View>

+ 49 - 6
screens/Detail/Center.jsx

@@ -3,14 +3,18 @@ import * as React from 'react';
 import { StyleSheet, View, Image } from 'react-native';
 import { Flex } from '@ant-design/react-native';
 import { TouchableRipple } from 'react-native-paper';
+import { useRequest } from '@umijs/hooks';
 import useModel from 'flooks';
 import Detail from './model';
+import User from '../../flooks/User';
 import Text from '../../components/Text';
 import Chip from '../../components/Chip';
-import Icon from '../../components/SvgIcon';
+import SvgIcon from '../../components/SvgIcon';
+import Icon from 'react-native-vector-icons/FontAwesome';
 
 export default function Center() {
-  const { merchantInfo } = useModel(Detail);
+  const { merchantInfo, like, delLike } = useModel(Detail, ['merchantInfo']);
+  const { id } = useModel(User, ['id']);
   const {
     logo,
     showName,
@@ -19,7 +23,36 @@ export default function Center() {
     badNum,
     fullReductions,
     proclamation,
+    mid,
   } = merchantInfo;
+
+  const [Collection, setCollection] = React.useState({});
+
+  const collectRequest = useRequest(
+    () => {
+      const params = {
+        query: {
+          merchantId: mid,
+          userId: id,
+        },
+      };
+      const urls = Object.keys(params).map((item) => {
+        return `${item}=${encodeURI(JSON.stringify(params[item]))}`;
+      });
+      return `/myCollection/all?${urls.join('&')}`;
+    },
+    {
+      refreshDeps: [mid],
+      onSuccess: (result) => {
+        if (!result.empty) {
+          setCollection(result.content[0]);
+        } else {
+          setCollection({});
+        }
+      },
+    }
+  );
+
   return (
     <View style={styles.main}>
       <Flex>
@@ -30,13 +63,13 @@ export default function Center() {
           </Text>
           <Flex justify="space-around" style={styles.lab}>
             <Flex>
-              <Icon name="zan" type="primary" width={18} height={18} />
+              <SvgIcon name="zan" type="primary" width={18} height={18} />
               <Text size="c1" type="primary">
                 {goodNum || 0}
               </Text>
             </Flex>
             <Flex style={styles.text}>
-              <Icon name="zan" Flip color="#000" width={18} height={18} />
+              <SvgIcon name="zan" Flip color="#000" width={18} height={18} />
               <Text size="c1" type="info">
                 {badNum || 0}
               </Text>
@@ -51,11 +84,21 @@ export default function Center() {
         </Flex.Item>
         <TouchableRipple
           onPress={() => {
-            console.log('like');
+            Collection.id
+              ? delLike(Collection.id).then(() => {
+                  collectRequest.run();
+                })
+              : like().then(() => {
+                  collectRequest.run();
+                });
           }}
           style={styles.like}
         >
-          <Icon name="like" width={15} height={15} color="#FF0000" />
+          <Icon
+            name={Collection.id ? 'heart' : 'heart-o'}
+            size={16}
+            color="#FF0000"
+          />
         </TouchableRipple>
       </Flex>
 

+ 28 - 12
screens/Detail/Classification.jsx

@@ -1,29 +1,32 @@
 import * as WebBrowser from 'expo-web-browser';
 import * as React from 'react';
-import { StyleSheet, View, FlatList } from 'react-native';
+import { StyleSheet, FlatList } from 'react-native';
+import { Div, Text } from 'react-native-magnus';
+import { TouchableRipple } from 'react-native-paper';
 
 import { useRequest } from '@umijs/hooks';
 
 import useModel from 'flooks';
 import Detail from './model';
 
-import Text from '../../components/Text';
-
-function Item({ name }) {
+function Item({ name, isChoose, select }) {
   return (
-    <View style={styles.item}>
-      <Text center size="c1">
-        {name}
-      </Text>
-    </View>
+    <TouchableRipple onPress={select}>
+      <Div py={10} px={20} bg={isChoose ? 'white' : ''}>
+        <Text color={isChoose ? 'brand500' : ''}>{name}</Text>
+      </Div>
+    </TouchableRipple>
   );
 }
 export default function Classification() {
-  const { id } = useModel(Detail, ['id']);
+  const { id, selectClass, changeSelectClass } = useModel(Detail, [
+    'id',
+    'selectClass',
+  ]);
 
   const [classifications, setclassifications] = React.useState([]);
 
-  const recommendRequest = useRequest(
+  useRequest(
     () => {
       const params = {
         query: {
@@ -41,6 +44,9 @@ export default function Classification() {
       refreshDeps: [id],
       onSuccess: (result) => {
         setclassifications(result.content);
+        if (!result.empty) {
+          changeSelectClass(result.content[0].id);
+        }
       },
     }
   );
@@ -49,8 +55,17 @@ export default function Classification() {
     <FlatList
       style={styles.left}
       data={classifications}
-      renderItem={({ item }) => <Item name={item.name} />}
+      renderItem={({ item }) => (
+        <Item
+          name={item.name}
+          isChoose={selectClass === item.id}
+          select={() => {
+            changeSelectClass(item.id);
+          }}
+        />
+      )}
       keyExtractor={(item) => item.id}
+      extraData={selectClass}
     />
   );
 }
@@ -59,6 +74,7 @@ const styles = StyleSheet.create({
   left: {
     width: 95,
     maxWidth: 95,
+    paddingBottom: 100,
   },
   item: {
     paddingHorizontal: 15,

+ 91 - 0
screens/Detail/ClassificationList.jsx

@@ -0,0 +1,91 @@
+import * as WebBrowser from 'expo-web-browser';
+import * as React from 'react';
+import { StyleSheet, FlatList } from 'react-native';
+import { Div, Image, Text } from 'react-native-magnus';
+
+import { useRequest } from '@umijs/hooks';
+
+import useModel from 'flooks';
+import Detail from './model';
+
+function Item({ info }) {
+  return (
+    <Div py={5} px={10} row bg="white">
+      <Image
+        w={70}
+        h={70}
+        bg="gray200"
+        rounded="sm"
+        source={{ uri: info.img }}
+      />
+      <Div flex={1} ml={5}>
+        <Text>{info.name}</Text>
+        <Text color="gray300" fontSize="xs">
+          {info.introduction}
+        </Text>
+        <Text color="gray300" fontSize="xs">
+          月售{info.inventory || 0}
+        </Text>
+        <Div flex={1} />
+        <Div row alignItems="center">
+          <Text color="red500">¥{info.discountAmount || info.amount}</Text>
+          {!!info.discountAmount && (
+            <Text
+              color="gray300"
+              ml={5}
+              fontSize="xs"
+              textDecorLine="line-through"
+              textDecorColor="gray300"
+            >
+              ¥{info.amount}
+            </Text>
+          )}
+        </Div>
+      </Div>
+    </Div>
+  );
+}
+export default function ClassificationList() {
+  const { selectClass } = useModel(Detail, ['selectClass']);
+
+  const [goodsList, setgoodsList] = React.useState([]);
+  const [scroll, setScroll] = React.useState('');
+
+  useRequest(`/classification/allGoods?classificationId=${selectClass}`, {
+    refreshDeps: [selectClass],
+    onSuccess: (result) => {
+      scroll.scrollToOffset(0);
+      setgoodsList(
+        result.filter((item) => {
+          return item;
+        }) || []
+      );
+    },
+  });
+  // classification;
+  return (
+    <Div bg="white" flex={1}>
+      <FlatList
+        ref={(ref) => setScroll(ref)}
+        style={styles.right}
+        data={goodsList}
+        renderItem={({ item }) => <Item info={item} />}
+        keyExtractor={(item) => item.id}
+        ListEmptyComponent={() => (
+          <Div px={10} py={20}>
+            <Text color="gray300" textAlign="center">
+              暂无数据
+            </Text>
+          </Div>
+        )}
+      />
+    </Div>
+  );
+}
+
+const styles = StyleSheet.create({
+  right: {
+    flexGrow: 1,
+    paddingBottom: 100,
+  },
+});

+ 2 - 5
screens/Detail/Order.jsx

@@ -10,6 +10,7 @@ import Detail from './model';
 
 import Recommend from './Recommend';
 import Classification from './Classification';
+import ClassificationList from './ClassificationList';
 
 const { height, width } = Dimensions.get('window');
 
@@ -24,11 +25,7 @@ export default function Order() {
       >
         <Classification />
 
-        <Flex.Item style={styles.right}>
-          <ScrollView>
-            <Text>2222</Text>
-          </ScrollView>
-        </Flex.Item>
+        <ClassificationList />
       </Flex>
     </>
   );

+ 19 - 0
screens/Detail/model.js

@@ -1,5 +1,6 @@
 import request from '../../Utils/RequestUtils';
 import Toast from '../../flooks/Toast';
+import User from '../../flooks/User';
 
 const DetailModel = (now) => ({
   id: 0,
@@ -9,6 +10,7 @@ const DetailModel = (now) => ({
   selectInfo: null,
   cartRequest: null,
   heardColor: '',
+  selectClass: '',
   init(id) {
     now({ id: 0, merchantInfo: {} });
     return request.get(`/merchant/getDTO/${id}`).then((res) => {
@@ -114,6 +116,23 @@ const DetailModel = (now) => ({
         warnning(e.error);
       });
   },
+  delLike(id) {
+    return request.post(`/myCollection/del/${id}`);
+  },
+  // 收藏
+  like() {
+    const { merchantInfo } = now();
+    const { id } = now(User);
+    return request.post('/myCollection/save', {
+      data: {
+        userId: id,
+        merchantId: merchantInfo.mid,
+      },
+    });
+  },
+  changeSelectClass(id) {
+    now({ selectClass: id });
+  },
 });
 
 export default DetailModel;

+ 94 - 76
screens/Main/Home/MerchantCom.jsx

@@ -1,19 +1,19 @@
 import * as WebBrowser from 'expo-web-browser';
 import * as React from 'react';
-import { StyleSheet, View, Image } from 'react-native';
+import { StyleSheet, View } from 'react-native';
+import { Div, Text, Image } from 'react-native-magnus';
 import { Flex } from '@ant-design/react-native';
 import { TouchableRipple } from 'react-native-paper';
 import { useCreation } from '@umijs/hooks';
 import { useNavigation } from '@react-navigation/native';
-import Text from '../../../components/Text';
 import Chip from '../../../components/Chip';
 import Icon from '../../../components/SvgIcon';
 
 // 首页商家组件
 
 export default function MerchantCom(props) {
-  const { info } = props;
-
+  const { info, isCollection, id } = props;
+  console.log(isCollection);
   const navigation = useNavigation();
 
   const {
@@ -29,7 +29,7 @@ export default function MerchantCom(props) {
     badNum,
     preparationTime,
     mid,
-  } = info;
+  } = info || { showName: '' };
 
   const tags = useCreation(() => {
     let list = [];
@@ -51,89 +51,107 @@ export default function MerchantCom(props) {
   const long = useCreation(() => {
     if (distance < 1000) {
       return `${distance}米`;
-    } else {
+    } else if (distance) {
       return `${(distance / 1000).toFixed(1)}km`;
+    } else {
+      return false;
     }
   }, [distance]);
 
   return (
-    <TouchableRipple
-      onPress={() => {
-        navigation.navigate('MerchantDetail', {
-          merchantId: mid,
-        });
-      }}
-    >
-      <Flex align="start" style={styles.merchant}>
-        <Image style={styles.image} resizeMode="cover" source={{ uri: logo }} />
-        <Flex.Item style={styles.main}>
-          <Text size="s1" bold>
-            {showName}
-          </Text>
-          {tags.length > 0 && (
+    <Div my={isCollection ? 5 : 0}>
+      <TouchableRipple
+        onPress={() => {
+          navigation.navigate('MerchantDetail', {
+            merchantId: isCollection ? info.id : mid,
+          });
+        }}
+      >
+        <Div row px={10} pt={10} bg="white">
+          <Image
+            w={67}
+            h={67}
+            bg="gray200"
+            rounded="sm"
+            source={{ uri: logo }}
+          />
+          <Div
+            flex={1}
+            ml={10}
+            pb={4}
+            borderColor="gray300"
+            borderBottomWidth={1}
+          >
+            <Text size="xl" bold>
+              {showName}
+            </Text>
+            {tags.length > 0 && (
+              <Flex>
+                {tags.map((item, index) => {
+                  return <Chip key={index}>{item.name}</Chip>;
+                })}
+              </Flex>
+            )}
+
             <Flex>
-              {tags.map((item, index) => {
-                return <Chip key={index}>{item.name}</Chip>;
-              })}
+              <Flex>
+                <Icon name="zan" type="primary" width={18} height={18} />
+                <Text fontSize="sm" color="brand500">
+                  {goodNum || 0}
+                </Text>
+              </Flex>
+              <Flex style={styles.text}>
+                <Icon name="zan" Flip color="#000" width={18} height={18} />
+                <Text fontSize="sm" color="gray300">
+                  {badNum || 0}
+                </Text>
+              </Flex>
+              <Flex style={styles.text}>
+                <Text size="c1" color="gray300">
+                  月售
+                  {monthSales}
+                </Text>
+              </Flex>
             </Flex>
-          )}
-
-          <Flex>
             <Flex>
-              <Icon name="zan" type="primary" width={18} height={18} />
-              <Text size="c1" type="primary">
-                {goodNum || 0}
+              <Text fontSize="sm" color="gray300">
+                起送$
+                {startingAmount || 0}
               </Text>
-            </Flex>
-            <Flex style={styles.text}>
-              <Icon name="zan" Flip color="#000" width={18} height={18} />
-              <Text size="c1" type="info">
-                {badNum || 0}
+              <Flex.Item style={styles.text}>
+                <Text fontSize="sm" color="gray300">
+                  配送$ 10
+                </Text>
+              </Flex.Item>
+              <Text fontSize="sm" color="gray300">
+                {preparationTime || 60}
+                分钟
               </Text>
+              {!!long && (
+                <View style={styles.text}>
+                  <Text fontSize="sm" color="gray300">
+                    {long}
+                  </Text>
+                </View>
+              )}
             </Flex>
-            <Flex style={styles.text}>
-              <Text size="c1" type="info">
-                月售
-                {monthSales}
-              </Text>
+            <Flex style={styles.label2}>
+              <Chip size="mini" color="#FFE3B9" fontColor="#FF0000">
+                “喜欢您来金拱门喜欢您来金拱门”
+              </Chip>
+              <Chip size="mini" color="#FFE3B9" fontColor="#FF0000">
+                “喜欢您来金拱门喜欢您来金拱门”
+              </Chip>
             </Flex>
-          </Flex>
-          <Flex>
-            <Text size="c1" type="info">
-              起送$
-              {startingAmount || 0}
-            </Text>
-            <Flex.Item style={styles.text}>
-              <Text size="c1" type="info">
-                配送$ 10
-              </Text>
-            </Flex.Item>
-            <Text size="c1" type="info">
-              {preparationTime || 60}
-              分钟
-            </Text>
-            <View style={styles.text}>
-              <Text size="c1" type="info">
-                {long}
-              </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>
-    </TouchableRipple>
+            <Flex style={styles.label2} wrap="wrap">
+              <Chip size="mini" outline color="#FF0000">
+                12减5
+              </Chip>
+            </Flex>
+          </Div>
+        </Div>
+      </TouchableRipple>
+    </Div>
   );
 }
 

+ 2 - 3
screens/Order/ComplaintNextScreen.jsx

@@ -1,11 +1,9 @@
 import * as WebBrowser from 'expo-web-browser';
 import * as React from 'react';
 import { StyleSheet, View } from 'react-native';
-import { Flex, List, TextareaItem } from '@ant-design/react-native';
-import { TouchableRipple, Divider } from 'react-native-paper';
+import { Flex, TextareaItem } from '@ant-design/react-native';
 import { Div, Button } from 'react-native-magnus';
 import { ScrollView } from 'react-native-gesture-handler';
-import Icon from 'react-native-vector-icons/FontAwesome';
 
 import { useRoute } from '@react-navigation/native';
 import { useCreation } from '@umijs/hooks';
@@ -17,6 +15,7 @@ import Header from './Header'; // 头部
 
 import Text from '../../components/Text';
 import ImagePicker from '../../components/ImagePicker';
+
 const Name = new Map([
   ['MERCHANT', '商家'],
   ['RIDER', '骑手'],

+ 1 - 1
screens/Order/EvaluateScreen.jsx

@@ -99,7 +99,7 @@ export default function EvaluateScreen({ navigation }) {
       chooseMer === 'good',
       content2,
       riderScore,
-      content
+      content + [...Array.from(tags)].join(',')
     ).then(() => {
       navigation.goBack();
     });

+ 3 - 3
screens/Order/model.js

@@ -29,7 +29,7 @@ const OrderModel = (now) => ({
   userAppraisal(
     orderId,
     merchantId,
-    jobNumber,
+    riderId,
     img,
     goodsLike,
     goodsAppraise,
@@ -42,8 +42,8 @@ const OrderModel = (now) => ({
       .post(`/appraisal/userAppraisal`, {
         data: {
           orderId,
-          merchantId,
-          jobNumber,
+          // merchantId,
+          // jobNumber,
           img,
           goodsLike,
           goodsAppraise,

+ 65 - 0
screens/User/CollectionScreen.jsx

@@ -0,0 +1,65 @@
+import * as WebBrowser from 'expo-web-browser';
+import * as React from 'react';
+import { Div, Button, Image, Text, Avatar } from 'react-native-magnus';
+import { ScrollView } from 'react-native-gesture-handler';
+
+import { useRequest } from '@umijs/hooks';
+import useModel from 'flooks';
+import User from '../../flooks/User'; // detail模块通用方法
+
+import Header from '../../components/Header';
+import MerchantCom from '../Main/Home/MerchantCom';
+
+export default function CollectionScreen() {
+  const { id } = useModel(User, ['id']);
+  const [Collection, setCollection] = React.useState([]);
+  const CollectionRequest = useRequest(
+    () => {
+      const params = {
+        query: {
+          userId: id,
+          page: 0,
+          size: 100,
+        },
+      };
+      const urls = Object.keys(params).map((item) => {
+        return `${item}=${encodeURI(JSON.stringify(params[item]))}`;
+      });
+      return `/myCollection/all?${urls.join('&')}`;
+    },
+    {
+      refreshDeps: [id],
+      onSuccess: (result) => {
+        setCollection(result.content || []);
+      },
+    }
+  );
+
+  return (
+    <>
+      <Header title="我的收藏" />
+      <ScrollView
+        contentContainerStyle={{ backgroundColor: '#fff', flexGrow: 1 }}
+      >
+        {Collection.length === 0 && (
+          <Div p={10}>
+            <Text color="gray300" textAlign="center">
+              暂无数据
+            </Text>
+          </Div>
+        )}
+
+        {Collection.map((item) => {
+          return (
+            <MerchantCom
+              key={item.id}
+              id={item.id}
+              isCollection
+              info={item.merchant}
+            />
+          );
+        })}
+      </ScrollView>
+    </>
+  );
+}

+ 65 - 0
screens/User/SettingScreen.jsx

@@ -0,0 +1,65 @@
+import * as WebBrowser from 'expo-web-browser';
+import * as React from 'react';
+import { Div, Button, Text } from 'react-native-magnus';
+import { TouchableRipple } from 'react-native-paper';
+import { ScrollView } from 'react-native-gesture-handler';
+import Icon from 'react-native-vector-icons/FontAwesome';
+
+import useModel from 'flooks';
+import User from '../../flooks/User'; // detail模块通用方法
+
+import Header from '../../components/Header';
+import ImagePicker from '../../components/ImagePicker';
+
+import { prompt } from '../../Utils/TotastUtils';
+
+export default function LinksScreen() {
+  const { userInfo, uploadInfo, logout } = useModel(User, ['userInfo']);
+  const { avatar, nickname } = userInfo || {
+    nickname: '未登录',
+    avatar: '',
+  };
+
+  return (
+    <>
+      <Header title="个人资料" />
+      <ScrollView>
+        <Div row bg="white" rounded="none" p={9} alignItems="center" my={5}>
+          <Text flex={1}>头像:</Text>
+          <ImagePicker
+            img={avatar}
+            h={33}
+            w={33}
+            setImg={(img) => uploadInfo({ avatar: img })}
+          />
+          <Icon name="angle-right" color="#000" />
+        </Div>
+        <TouchableRipple
+          onPress={() => {
+            prompt('昵称', '请输入昵称', nickname, (val) =>
+              uploadInfo({ nickname: val })
+            );
+          }}
+        >
+          <Div
+            row
+            bg="white"
+            rounded="none"
+            p={9}
+            alignItems="center"
+            my={5}
+            minH={51}
+          >
+            <Text flex={1}>昵称:</Text>
+            <Text mr={5}>{nickname}</Text>
+            <Icon name="angle-right" color="#000" />
+          </Div>
+        </TouchableRipple>
+
+        <Button block bg="brand500" m={10} onPress={logout}>
+          退出登录
+        </Button>
+      </ScrollView>
+    </>
+  );
+}

+ 122 - 5
screens/User/UserScreen.jsx

@@ -1,9 +1,126 @@
+/* eslint-disable react/style-prop-object */
 import * as WebBrowser from 'expo-web-browser';
 import * as React from 'react';
-import { StyleSheet, View } from 'react-native';
+import { Div, Button, Image, Text, Avatar } from 'react-native-magnus';
+import { List } from 'react-native-paper';
+import { ScrollView } from 'react-native-gesture-handler';
+import { StatusBar } from 'expo-status-bar';
+import Constants from 'expo-constants';
 
-export default function UserScreen() {
-  return <View />;
-}
+import useModel from 'flooks';
+import User from '../../flooks/User'; // detail模块通用方法
+
+import UserCoupon from '../userCoupon/SettingCom';
+
+import { connectKefuOn } from '../../Utils/TotastUtils';
 
-const styles = StyleSheet.create({});
+export default function UserScreen({ navigation }) {
+  const { userInfo } = useModel(User, ['id']);
+  const { avatar, nickname, username } = userInfo || {
+    nickname: '未登录',
+  };
+  return (
+    <>
+      <StatusBar backgroundColor="transparent" style="light" translucent />
+
+      <ScrollView>
+        <Div row bg="white" pt={Constants.statusBarHeight + 20} px={20} pb={20}>
+          <Button
+            bg="white"
+            p={0}
+            onPress={() => {
+              navigation.navigate('Setting');
+            }}
+          >
+            {avatar ? (
+              <Image
+                h={53}
+                w={53}
+                rounded="circle"
+                source={{
+                  uri: avatar,
+                }}
+              />
+            ) : (
+              <Avatar bg="red300" color="white" h={53} w={53}>
+                {nickname ? nickname.substr(0, 1) : ''}
+              </Avatar>
+            )}
+          </Button>
+          <Div justifyContent="space-between" ml={10}>
+            <Text fontSize="xl" fontWeight="bold">
+              {nickname}
+            </Text>
+            <Text fontSize="sm">叮咚外卖{username}</Text>
+          </Div>
+        </Div>
+        <UserCoupon />
+        <Div bg="white" mb={5}>
+          <List.Item
+            title="我的收藏"
+            left={(props) => (
+              <List.Icon {...props} icon="heart-outline" color="#FFB11E" />
+            )}
+            right={(props) => <List.Icon {...props} icon="chevron-right" />}
+            onPress={() => navigation.navigate('Collection')}
+          />
+        </Div>
+        <Div bg="white" mb={5}>
+          <List.Item
+            title="联系客服"
+            left={(props) => (
+              <List.Icon {...props} icon="headset" color="#FFB11E" />
+            )}
+            right={(props) => <List.Icon {...props} icon="chevron-right" />}
+            onPress={connectKefuOn}
+          />
+        </Div>
+        <Div bg="white" mb={5}>
+          <List.Item
+            title="我的地址"
+            left={(props) => (
+              <List.Icon {...props} icon="map-marker-radius" color="#FFB11E" />
+            )}
+            right={(props) => <List.Icon {...props} icon="chevron-right" />}
+          />
+        </Div>
+        <Div bg="white" mb={5}>
+          <List.Item
+            title="合作申请"
+            left={(props) => (
+              <List.Icon {...props} icon="briefcase" color="#FFB11E" />
+            )}
+            right={(props) => <List.Icon {...props} icon="chevron-right" />}
+          />
+        </Div>
+        <Div bg="white" mb={5}>
+          <List.Item
+            title="设置"
+            left={(props) => (
+              <List.Icon {...props} icon="cog-outline" color="#FFB11E" />
+            )}
+            right={(props) => <List.Icon {...props} icon="chevron-right" />}
+          />
+        </Div>
+        <Div bg="white" mb={5}>
+          <List.Item
+            title="隐私条款"
+            left={(props) => (
+              <List.Icon {...props} icon="text-box" color="#FFB11E" />
+            )}
+            right={(props) => <List.Icon {...props} icon="chevron-right" />}
+          />
+        </Div>
+        <Div bg="white" mb={5}>
+          <List.Item
+            title="意见反馈"
+            left={(props) => (
+              <List.Icon {...props} icon="tooltip-plus" color="#FFB11E" />
+            )}
+            right={(props) => <List.Icon {...props} icon="chevron-right" />}
+          />
+        </Div>
+      </ScrollView>
+    </>
+  );
+}

+ 107 - 0
screens/userCoupon/CouponScreen.jsx

@@ -0,0 +1,107 @@
+import * as WebBrowser from 'expo-web-browser';
+import * as React from 'react';
+import { Div, Button, Image, Text, Avatar } from 'react-native-magnus';
+import { TouchableRipple } from 'react-native-paper';
+import { ScrollView } from 'react-native-gesture-handler';
+
+import { useNavigation } from '@react-navigation/native';
+import { useRequest } from '@umijs/hooks';
+import useModel from 'flooks';
+import userCoupon from './model'; // 优惠券模块
+
+import Header from '../../components/Header';
+
+const counpon = {
+  amount: 18,
+  enabled: true,
+  endDate: '2022-12-11',
+  fullAmount: 50,
+  id: 744,
+  merchantId: 189,
+  name: '六一优惠',
+  startDate: '2022-12-08',
+};
+
+const CounponItem = ({ info, isEnd }) => {
+  const navigation = useNavigation();
+  return (
+    <Div mt={10} mx={5}>
+      <TouchableRipple
+        disabled={isEnd}
+        onPress={() => navigation.navigate('Home', { screen: 'Home' })}
+      >
+        <Div row bg="white" alignItems="center" py={15} pr={15}>
+          <Div minW={80} alignItems="center">
+            <Text color={isEnd ? 'gray400' : 'red500'} fontSize="xl">
+              ¥{counpon.amount}
+            </Text>
+            {counpon.fullAmount > 0 && (
+              <Text fontSize="xs" color="gray300">
+                满{counpon.fullAmount}元可用
+              </Text>
+            )}
+            {counpon.fullAmount === 0 && (
+              <Text fontSize="xs" color="gray300">
+                无金额门槛
+              </Text>
+            )}
+          </Div>
+          <Div flex={1}>
+            <Text
+              color={isEnd ? 'gray400' : 'black'}
+              fontSize="xl"
+              fontWeight="bold"
+            >
+              {counpon.name}
+            </Text>
+            <Text fontSize="xs" color="gray300">
+              限{counpon.startDate}至{counpon.endDate}使用
+            </Text>
+          </Div>
+          {isEnd ? (
+            <Text color="gray500" fontSize="sm">
+              已过期
+            </Text>
+          ) : (
+            <Text color="gray500" fontSize="sm">
+              去使用
+            </Text>
+          )}
+        </Div>
+      </TouchableRipple>
+    </Div>
+  );
+};
+
+export default function LinksScreen() {
+  const {
+    userCouponList,
+    userCouponListHis,
+    init,
+    getBadList,
+  } = useModel(userCoupon, ['userCouponList', 'userCouponListHis']);
+
+  useRequest(init, {});
+  useRequest(getBadList, {});
+
+  return (
+    <>
+      <Header title="红包卡券" />
+      <ScrollView>
+        {userCouponList.map((item) => {
+          return <CounponItem key={item.id} info={item} />;
+        })}
+
+        {userCouponList.length === 0 && userCouponListHis.length === 0 && (
+          <Div p={10} alignItems="center">
+            <Text>暂无数据</Text>
+          </Div>
+        )}
+
+        {userCouponListHis.map((item) => {
+          return <CounponItem key={item.id} info={item} isEnd />;
+        })}
+      </ScrollView>
+    </>
+  );
+}

+ 37 - 0
screens/userCoupon/SettingCom.jsx

@@ -0,0 +1,37 @@
+import * as WebBrowser from 'expo-web-browser';
+import * as React from 'react';
+import { Div, Button, Text } from 'react-native-magnus';
+
+import { useNavigation } from '@react-navigation/native';
+import { useRequest } from '@umijs/hooks';
+import useModel from 'flooks';
+import userCoupon from './model'; // 优惠券模块
+
+export default function SettingCom() {
+  const { userCouponList, init } = useModel(userCoupon, ['userCouponList']);
+  useRequest(init, {});
+
+  const navigation = useNavigation();
+
+  return (
+    <Button
+      block
+      m={5}
+      bg="white"
+      rounded="none"
+      onPress={() => navigation.navigate('Coupon')}
+    >
+      <Div alignItems="center">
+        <Text fontSize="xl" fontWeight="bold">
+          红包卡券
+        </Text>
+        <Div row mt={2}>
+          <Text fontSize="sm" color="red500">
+            {userCouponList.length}
+          </Text>
+          <Text fontSize="sm">个未使用红包</Text>
+        </Div>
+      </Div>
+    </Button>
+  );
+}

+ 31 - 0
screens/userCoupon/model.js

@@ -0,0 +1,31 @@
+import request from '../../Utils/RequestUtils';
+import Toast from '../../flooks/Toast';
+
+const userCoupon = (now) => ({
+  userCouponList: [],
+  userCouponListHis: [],
+  // 获取未过期的优惠券
+  init() {
+    return request
+      .get(`/userCoupon/my`)
+      .then((res) => {
+        now({ userCouponList: res });
+      })
+      .catch(() => {
+        now({ userCouponList: [] });
+      });
+  },
+  // 获取过期的优惠券
+  getBadList() {
+    return request
+      .get(`/userCoupon/myHis`)
+      .then((res) => {
+        now({ userCouponListHis: res });
+      })
+      .catch(() => {
+        now({ userCouponListHis: [] });
+      });
+  },
+});
+
+export default userCoupon;