panhui 5 lat temu
rodzic
commit
2b78ec684a

+ 87 - 105
App.js

@@ -19,6 +19,7 @@ import {
   CardStyleInterpolators,
 } from "@react-navigation/stack";
 import { useModel } from "flooks";
+import { useUpdateEffect, useMount } from "@umijs/hooks";
 import { enableScreens } from "react-native-screens";
 // eslint-disable-next-line no-unused-vars
 import * as model from "./models";
@@ -40,128 +41,109 @@ const fontFile = require("./assets/fonts/SpaceMono-Regular.ttf");
 
 export default function App(props) {
   const [isLoadingComplete, setLoadingComplete] = React.useState(false);
-  const { getWords } = useModel("wordsModel", true);
-  const { loading, clearLoading } = useModel("loadingModel", true);
+  const { getWords, local } = useModel("wordsModel");
+  const { clearLoading } = useModel("loadingModel", true);
+  const {
+    mid,
+    guideStep,
+    getUserInfo,
+    checkNowGuideStep,
+    setinitRoute,
+  } = useModel("userModel");
 
-  // Load any resources or data that we need prior to rendering the app
-  React.useEffect(() => {
-    async function loadResourcesAndDataAsync() {
-      try {
-        SplashScreen.preventAutoHide();
-        // Load fonts
-        await Font.loadAsync({
-          ...Ionicons.font,
-          "space-mono": fontFile,
-        });
-
-        await Font.loadAsync(
+  useMount(() => {
+    SplashScreen.preventAutoHide();
+    Font.loadAsync({
+      ...Ionicons.font,
+      "space-mono": fontFile,
+    })
+      .then(() => {
+        return Font.loadAsync(
           "antoutline",
           // eslint-disable-next-line
           require("@ant-design/icons-react-native/fonts/antoutline.ttf")
         );
-
-        await Font.loadAsync(
+      })
+      .then(() => {
+        return Font.loadAsync(
           "antfill",
           // eslint-disable-next-line
           require("@ant-design/icons-react-native/fonts/antfill.ttf")
         );
-
-        getWords();
-      } catch (e) {
-        // We might want to provide this error information to an error reporting service
-        // eslint-disable-next-line no-console
+      })
+      .then(() => {
+        return getUserInfo();
+      })
+      .catch(e => {
         console.log(e);
-      } finally {
-        setLoadingComplete(true);
-        SplashScreen.hide();
-      }
-    }
+      });
+    //   .finally(() => {
+    //     setLoadingComplete(true);
+    //     SplashScreen.hide();
+    //   });
+  });
 
-    loadResourcesAndDataAsync();
-  }, []);
+  React.useEffect(() => {
+    getWords();
+  }, [local]);
 
   const [initRouteName, setInit] = React.useState("");
-  const {
-    getUserInfo,
-    getGuideStep,
-    initApp,
-    refreashReason,
-    changeInIt,
-    setinitRoute,
-  } = useModel("userModel");
 
-  React.useEffect(() => {
-    function getLogin() {
-      if (refreashReason !== "guideStep") {
-        return getUserInfo();
-      }
-      return Promise.resolve();
+  useUpdateEffect(() => {
+    if (mid === 0) {
+      // 未登录
+      setinitRoute("Login");
+      setInit("Login");
+    } else if (mid !== 0) {
+      checkNowGuideStep();
     }
-
-    if (initApp && initRouteName) {
-      loading();
+  }, [mid]);
+
+  useUpdateEffect(() => {
+    switch (guideStep) {
+      case "finish":
+        setInit("Root");
+        break;
+      case "ComeBack":
+        setinitRoute("RegisterSe");
+        setInit("Login");
+        break;
+      case "1":
+        setInit("Guide1");
+        break;
+      case "2":
+        setInit("Guide2");
+        break;
+      case "3":
+        setInit("Guide3");
+        break;
+      case "4":
+        setInit("Guide4");
+        break;
+      case "5":
+        setInit("StoreAudit");
+        break;
+      default:
+        setInit("Login");
+        break;
     }
-
-    if (initApp) {
-      getLogin()
-        .then(() => {
-          return getGuideStep();
+  }, [guideStep]);
+
+  useUpdateEffect(() => {
+    if (!isLoadingComplete) {
+      setLoadingComplete(true);
+      SplashScreen.hide();
+    } else {
+      navigationRef.current.dispatch(
+        CommonActions.reset({
+          index: 0,
+          routes: [
+            {
+              name: initRouteName,
+            },
+          ],
         })
-        .then(res => {
-          switch (res) {
-            case "finish":
-              setInit("Root");
-              break;
-            case "ComeBack":
-              setinitRoute("RegisterSe");
-              setInit("Login");
-              break;
-            case "1":
-              setInit("Guide1");
-              break;
-            case "2":
-              setInit("Guide2");
-              break;
-            case "3":
-              setInit("Guide3");
-              break;
-            case "4":
-              setInit("Guide4");
-              break;
-            case "5":
-              setInit("StoreAudit");
-              break;
-            default:
-              setInit("");
-              break;
-          }
-        })
-        .catch(() => {
-          //  未登录
-          setinitRoute("Login");
-          setInit("Login");
-        })
-        .finally(() => {
-          changeInIt();
-        });
-    }
-  }, [initApp]);
-
-  React.useEffect(() => {
-    if (navigationRef.current) {
-      const { name } = navigationRef.current.getCurrentRoute();
-      if (name !== initRouteName && initRouteName) {
-        navigationRef.current.dispatch(
-          CommonActions.reset({
-            index: 0,
-            routes: [
-              {
-                name: initRouteName,
-              },
-            ],
-          })
-        );
-      }
+      );
       clearLoading();
     }
   }, [initRouteName]);

+ 4 - 3
Redux/DataListRedux.js

@@ -47,19 +47,20 @@ export function DataListReducer(state, action) {
         loading: false,
       };
     case "setInfo":
+      console.log(action.payload.list);
       return {
         ...state,
         dataList:
           state.page === 0
-            ? action.payload.list
-            : state.dataList.concat(action.payload.list),
+            ? [...action.payload.list]
+            : state.dataList.concat([...action.payload.list]),
         finish: action.payload.finish,
         page: action.payload.finish ? state.page : state.page + 1,
       };
     case "remove": {
       const list = [...state.dataList];
       list.splice(action.payload.index, 1);
-    //   console.log(list);
+      //   console.log(list);
       return {
         ...state,
         dataList: list,

+ 135 - 92
components/FormInput.js

@@ -14,6 +14,7 @@ import {
   SelectItem,
 } from "@ui-kitten/components";
 import { Cascader, BottomModal } from "beeshell";
+import { useCreation } from "@umijs/hooks";
 import { useModel } from "flooks";
 import moment from "moment";
 import OpenTime from "./OpenTime";
@@ -83,94 +84,125 @@ function* flattenSelect(array, key) {
   }
 }
 
+function getInputProps(
+  type,
+  value,
+  placeholder,
+  onChange,
+  secureTextEntry,
+  renderIcon
+) {
+  let _props = {
+    defaultValue: value || "",
+    placeholder,
+  };
+  if (type === "phone") {
+    _props = {
+      ..._props,
+      dataDetectorTypes: "phoneNumber",
+      maxLength: 11,
+      keyboardType: "phone-pad",
+    };
+  } else if (type === "password") {
+    _props = {
+      ..._props,
+      accessoryRight: ImageProps => renderIcon(ImageProps),
+      secureTextEntry,
+    };
+  } else if (type === "code") {
+    _props = {
+      ..._props,
+      maxLength: 6,
+      keyboardType: "numeric",
+    };
+  } else if (type === "amount" || type === "money") {
+    _props = {
+      ..._props,
+      keyboardType: "numeric",
+    };
+  }
+  if (onChange) {
+    _props = {
+      ..._props,
+      onChangeText: nextValue => onChange(nextValue),
+    };
+  }
+
+  return _props;
+}
+
+const ForwardIcon = props => <Icon {...props} name="arrow-ios-forward" />;
+
+const Label = ({ type, labelStyle, label, appearance }) => {
+  return (
+    <View
+      style={[
+        appearance === "inner" ? styles.labelleft : styles.label,
+        type === "img" ? { alignSelf: "flex-start" } : {},
+        labelStyle || {},
+      ]}
+    >
+      <Text
+        category="c1"
+        style={{
+          textAlign: appearance !== "inner" ? "right" : "left",
+        }}
+      >
+        {label}
+      </Text>
+    </View>
+  );
+};
+
+const Btn = ({ btnText }) => (
+  <Button
+    appearance="ghost"
+    size="tiny"
+    style={{ paddingVertical: 8, marginLeft: 5 }}
+  >
+    {btnText}
+  </Button>
+);
 const FormInput = React.memo(props => {
-  const { appearance, type, selectList } = props;
+  const {
+    placeholder,
+    appearance,
+    type,
+    selectList,
+    value,
+    style,
+    sub,
+    onChange,
+    labelStyle,
+    label,
+  } = props;
+
   const [secureTextEntry, setSecureTextEntry] = React.useState(true);
   const { cancel, confirm } = useModel("wordsModel");
   const toggleSecureEntry = () => {
     setSecureTextEntry(!secureTextEntry);
   };
-
   // eslint-disable-next-line no-shadow
   const renderIcon = props => (
     <TouchableWithoutFeedback onPress={toggleSecureEntry}>
       <Icon {...props} name={secureTextEntry ? "eye-off" : "eye"} />
     </TouchableWithoutFeedback>
   );
-  function getInputProps(props) {
-    let _props = {
-      value: props.value || "",
-      placeholder: props.placeholder,
-    };
-    if (type === "phone") {
-      _props = {
-        ..._props,
-        dataDetectorTypes: "phoneNumber",
-        maxLength: 11,
-        keyboardType: "phone-pad",
-      };
-    } else if (type === "password") {
-      _props = {
-        ..._props,
-        accessoryRight: ImageProps => renderIcon(ImageProps),
-        secureTextEntry,
-      };
-    } else if (type === "code") {
-      _props = {
-        ..._props,
-        maxLength: 6,
-        keyboardType: "numeric",
-      };
-    } else if (type === "amount" || props.type === "money") {
-      _props = {
-        ..._props,
-        keyboardType: "numeric",
-      };
-    }
-    if (props.onChange) {
-      _props = {
-        ..._props,
-        onChangeText: nextValue => props.onChange(nextValue),
-      };
-    }
-
-    return _props;
-  }
-
-  const inputProps = getInputProps(props);
-
-  // const myInput = () => {
-  //     if (inputProps != null) {
-  //         return;
-  //     }
-  // };
-
-  const Label = ({ type, labelStyle, label }) => {
-    return (
-      <View
-        style={[
-          appearance === "inner" ? styles.labelleft : styles.label,
-          type === "img" ? { alignSelf: "flex-start" } : {},
-          labelStyle || {},
-        ]}
-      >
-        <Text
-          category="c1"
-          style={{
-            textAlign: appearance !== "inner" ? "right" : "left",
-          }}
-        >
-          {label}
-        </Text>
-      </View>
+  const inputProps = useCreation(() => {
+    return getInputProps(
+      type,
+      value,
+      placeholder,
+      onChange,
+      secureTextEntry,
+      renderIcon
     );
-  };
-  const ForwardIcon = props => <Icon {...props} name="arrow-ios-forward" />;
+  }, [type, value, placeholder, onChange, secureTextEntry, renderIcon]);
 
   const [bottomModalX, changeBottomModalx] = React.useState("");
   const [selectVal, setSelectVal] = React.useState("");
 
-  const selectInfo = React.useMemo(() => {
+  const selectInfo = useCreation(() => {
     if (type === "select" && props.value && selectList) {
       const childrens = [...flattenSelect(selectList, "children")];
       return (
@@ -180,21 +212,11 @@ const FormInput = React.memo(props => {
       );
     }
     return { name: " " };
-  }, [props.value, type, selectList]);
+  }, [value, type, selectList]);
 
   const [open, ChangeOpen] = React.useState(false);
 
-  const Btn = ({ btnText }) => (
-    <Button
-      appearance="ghost"
-      size="tiny"
-      style={{ paddingVertical: 8, marginLeft: 5 }}
-    >
-      {btnText}
-    </Button>
-  );
-
-  function getMain(type, props) {
+  function getMain(type, props, inputProps) {
     if (type === "select") {
       return (
         <>
@@ -305,7 +327,14 @@ const FormInput = React.memo(props => {
       return (
         <Input
           {...inputProps}
-          accessoryLeft={leftprops => <Label {...props} {...leftprops} />}
+          accessoryLeft={() => (
+            <Label
+              type={type}
+              labelStyle={labelStyle}
+              label={label}
+              appearance={appearance}
+            />
+          )}
           accessoryRight={() => <Btn btnText={props.btnText} />}
           size="small"
           style={styles.input}
@@ -317,7 +346,14 @@ const FormInput = React.memo(props => {
       return (
         <Input
           {...inputProps}
-          accessoryLeft={leftprops => <Label {...props} {...leftprops} />}
+          accessoryLeft={() => (
+            <Label
+              type={type}
+              labelStyle={labelStyle}
+              label={label}
+              appearance={appearance}
+            />
+          )}
           size="small"
           style={styles.input}
           appearance="inner"
@@ -335,22 +371,29 @@ const FormInput = React.memo(props => {
       level="1"
       style={[
         styles.inputContainer,
-        { ...props.style },
-        props.type === "img" ? { flexDirection: "column" } : {},
+        { ...style },
+        type === "img" ? { flexDirection: "column" } : {},
         { paddingVertical: appearance === "inner" ? 0 : 10 },
       ]}
     >
-      {appearance !== "inner" && <Label {...props} />}
+      {appearance !== "inner" && (
+        <Label
+          type={type}
+          labelStyle={labelStyle}
+          label={label}
+          appearance={appearance}
+        />
+      )}
 
-      {(!props.value || props.value === " ") && (
+      {(!value || value === " ") && (
         <Text category="c1" style={styles.sub}>
-          {props.sub}
+          {sub}
         </Text>
       )}
 
-      {getMain(props.type, props)}
+      {getMain(type, props, inputProps)}
 
-      {appearance !== "inner" && props.type === "code" && Btn(props)}
+      {appearance !== "inner" && type === "code" && Btn(props)}
     </Layout>
   );
 });

+ 17 - 0
components/ListComponent.js

@@ -27,8 +27,25 @@ export default function ListComponent(props) {
     startState, // 父级调刷新
     initialNumToRender,
     saveList, // 保持状态
+    list$,
   } = props;
 
+  function setList(newList) {
+    dispatch({
+      type: "setInfo",
+      payload: { list: newList, finish: true },
+    });
+  }
+
+  if (list$) {
+    list$.useSubscription(info => {
+      const list = [...dataList];
+      let newList = [];
+      newList = info.changeEvent(list, info.list, info.type, info.extra);
+      setList(newList);
+    });
+  }
+
   function getList() {
     if (getInfo != null) {
       return getInfo(page, size).then(res => {

+ 62 - 76
components/MoneyRecord.js

@@ -1,87 +1,73 @@
 import React from "react";
 import { StyleSheet } from "react-native";
-import {
-    Card,
-    Text,
-    Layout,
-    Avatar,
-    Icon,
-} from "@ui-kitten/components";
+import { Card, Text, Layout, Avatar, Icon } from "@ui-kitten/components";
 import { useModel } from "flooks";
 
-
 const styles = StyleSheet.create({
-    main: {
-        flexDirection: "row",
-        alignItems: "center",
-        backgroundColor: 'transparent',
-    },
-    avatar: {
-        width: 33,
-        height: 33,
-        backgroundColor: "#eee",
-    },
-    center: {
-        flex: 1,
-        marginLeft: 14,
-        backgroundColor: 'transparent',
-    },
-    text2: {
-        paddingTop: 5,
-        paddingBottom: 3,
-    },
-    code: {
-        alignSelf: "flex-start",
-    },
-    icon: {
-        width: 20,
-        position: "absolute",
-        right: 0,
-        top: "50%",
-        marginTop: -10,
-    },
+  main: {
+    flexDirection: "row",
+    alignItems: "center",
+    backgroundColor: "transparent",
+  },
+  avatar: {
+    width: 33,
+    height: 33,
+    backgroundColor: "#eee",
+  },
+  center: {
+    flex: 1,
+    marginLeft: 14,
+    backgroundColor: "transparent",
+  },
+  text2: {
+    paddingTop: 5,
+    paddingBottom: 3,
+  },
+  code: {
+    alignSelf: "flex-start",
+  },
+  icon: {
+    width: 20,
+    position: "absolute",
+    right: 0,
+    top: "50%",
+    marginTop: -10,
+  },
 });
 
-
 export default function MoneyRecord(props) {
-    const { getWordsStr } = useModel("wordsModel");
-    const { info } = props;
-    const {  avatar, name, time, type, amount } = info || {};
-    const code = React.useMemo(() => {
-        if (amount) {
-            return (amount > 0 ? "+ " : "- ") + amount.toFixed(2);
-        } 
-            return "+ 0.00";
-        
-    }, [amount]);
-    return (
-      <Card appearance='walletCard'>
-        <Layout style={styles.main}>
-          <Avatar
-            style={styles.avatar}
-            source={{
-                        uri: avatar,
-                    }}
-          />
-          <Layout style={styles.center}>
-            <Text category='s1'>{name}</Text>
-            <Text category='h1' status='info' style={styles.text2}>
-              {time}
-            </Text>
-            <Text category='h1' status='info'>
-              {getWordsStr(type)}
-            </Text>
-          </Layout>
-          <Text category='s1' style={styles.code}>
-            {code}
+  const { getWordsStr } = useModel("wordsModel");
+  const { info } = props;
+  const { avatar, name, time, type, amount } = info || {};
+  const code = React.useMemo(() => {
+    if (amount) {
+      return (type === "WITHDRAW" ? "-" : "+") + amount.toFixed(2);
+    }
+    return `${type === "WITHDRAW" ? "-" : "+"  } 0.00`;
+  }, [amount, type]);
+  return (
+    <Card appearance="walletCard">
+      <Layout style={styles.main}>
+        <Avatar
+          style={styles.avatar}
+          source={{
+            uri: avatar,
+          }}
+        />
+        <Layout style={styles.center}>
+          <Text category="s1">{name}</Text>
+          <Text category="h1" status="info" style={styles.text2}>
+            {time}
+          </Text>
+          <Text category="h1" status="info">
+            {getWordsStr(type)}
           </Text>
-          <Icon
-            name='arrow-ios-forward'
-            fill='#C9C9C9'
-            style={styles.icon}
-          />
         </Layout>
-      </Card>
-    );
+        <Text category="s1" style={styles.code}>
+          {code}
+        </Text>
+        <Icon name="arrow-ios-forward" fill="#C9C9C9" style={styles.icon} />
+      </Layout>
+    </Card>
+  );
 }
-

+ 21 - 19
components/UpLoadImage.js

@@ -1,3 +1,5 @@
+/* eslint-disable consistent-return */
+/* eslint-disable no-else-return */
 /* eslint-disable react/destructuring-assignment */
 /* eslint-disable no-async-promise-executor */
 /* eslint-disable prefer-promise-reject-errors */
@@ -8,37 +10,37 @@ import { useModel } from "flooks";
 import * as ImagePicker from "expo-image-picker";
 import { Image, Platform } from "react-native";
 
-const _pickImage = () => {
-  return new Promise(async (resolve, reject) => {
-    try {
-      const permissionResult = await ImagePicker.requestCameraRollPermissionsAsync();
-
-      if (permissionResult.granted === false) {
-        reject("notAllod");
+const _pickImage = loading => {
+  return ImagePicker.requestCameraRollPermissionsAsync()
+    .then(res => {
+      if (!res.granted) {
+        return Promise.reject("notAllod");
       } else {
-        const result = await ImagePicker.launchImageLibraryAsync({
+        return ImagePicker.launchImageLibraryAsync({
           mediaTypes: ImagePicker.MediaTypeOptions.Images,
           allowsEditing: true,
           aspect: [1, 1],
           quality: 1,
           base64: true,
         });
-        if (!result.cancelled) {
-          if (Platform.OS === "web") {
-            resolve(result.uri);
-          } else {
-            resolve(result.base64);
-          }
+      }
+    })
+    .then(res => {
+      if (!res.cancelled) {
+        loading();
+        if (Platform.OS === "web") {
+          return Promise.resolve(res.uri);
         }
+        return Promise.resolve(res.base64);
+      } else {
+        return Promise.reject("cancel");
       }
-    } catch (e) {
-      reject(e);
-    }
-  });
+    });
 };
 
 export default function UpLoadImage(props) {
   const { httpPost } = useModel("httpModel", true);
+  const { loading } = useModel("loadingModel", true);
   // eslint-disable-next-line no-shadow
   const renderPulseIcon = props => <Icon {...props} name="plus-outline" />;
 
@@ -51,7 +53,7 @@ export default function UpLoadImage(props) {
         ]}
         appearance="imageButton"
         onPress={() => {
-          _pickImage().then(img => {
+          _pickImage(loading).then(img => {
             httpPost("/upload/base64", {
               base64: img,
             }).then(res => {

+ 0 - 2
language/index.js

@@ -1,5 +1,4 @@
 // I18n.js
-import * as Localization from "expo-localization";
 import i18n from "i18n-js";
 import th from "./th";
 import zh from "./zh";
@@ -9,7 +8,6 @@ i18n.translations = {
     th,
     zh,
 };
-i18n.locale = Localization.locale;
 i18n.fallbacks = true;
 
 const keys = Object.keys(zh);

+ 10 - 5
models/goodsModel.js

@@ -63,7 +63,8 @@ export default {
     saveInfo(info, noTip) {
       const { saveSuccess, editSuccess } = model("wordsModel");
       const { httpPost } = model("httpModel");
-      const { success } = model("loadingModel");
+      const { success, loading } = model("loadingModel");
+      loading();
       return httpPost(
         "/classification/save",
         info,
@@ -81,7 +82,8 @@ export default {
       const { showDialog } = model("dialogModel");
       const { removeTips, editSuccess } = model("wordsModel");
       const { httpGet } = model("httpModel");
-      const { success } = model("loadingModel");
+      const { success, loading } = model("loadingModel");
+      loading();
       showDialog({
         bodyText: removeTips,
         status: "danger",
@@ -104,8 +106,9 @@ export default {
     // 添加分类商品
     addClassGoods(info) {
       const { successText } = model("wordsModel");
-      const { success } = model("loadingModel");
-      const { httpPost } = model("httpModel");
+      const { success, loading } = model("loadingModel");
+      const { httpPost} = model("httpModel");
+      loading();
       return httpPost(
         "/goodsSpecification/save",
         info,
@@ -123,7 +126,9 @@ export default {
       const { showDialog } = model("dialogModel");
       const { removeTips, editSuccess } = model("wordsModel");
       const { httpPost } = model("httpModel");
-      const { success } = model("loadingModel");
+      const { success, loading } = model("loadingModel");
+
+      loading();
       showDialog({
         bodyText: removeTips,
         status: "danger",

+ 9 - 29
models/httpModel.js

@@ -59,7 +59,7 @@ export default {
       const { getAxiosInstance } = model();
       const { loading, warnning, clearLoading } = model("loadingModel");
       params = params || {};
-      loading();
+      //   loading();
       return new Promise((resolve, reject) => {
         getAxiosInstance()
           .get(url, {
@@ -82,7 +82,7 @@ export default {
     httpPost(url, body, options, needWarning) {
       const { getAxiosInstance } = model();
       const { loading, warnning, clearLoading } = model("loadingModel");
-      loading();
+      //   loading();
       options = options || {};
       body = body || {};
       if (!(body instanceof FormData)) {
@@ -107,35 +107,15 @@ export default {
           });
       });
     },
-    addAsyncStorage(key, value) {
-      return new Promise(async (resolve, reject) => {
-        try {
-          await AsyncStorage.setItem(key, value);
-          resolve();
-        } catch (e) {
-          reject(e);
-        }
-      });
+    async addAsyncStorage(key, value) {
+      await AsyncStorage.setItem(key, value);
     },
-    removeAsyncStorage(key) {
-      return new Promise(async (resolve, reject) => {
-        try {
-          await AsyncStorage.removeItem(key);
-          resolve();
-        } catch (e) {
-          reject(e);
-        }
-      });
+    async removeAsyncStorage(key) {
+      await AsyncStorage.removeItem(key);
     },
-    getAsyncStorage(key) {
-      return new Promise(async (resolve, reject) => {
-        try {
-          const val = await AsyncStorage.getItem(key);
-          resolve(val);
-        } catch (e) {
-          reject(e);
-        }
-      });
+    async getAsyncStorage(key) {
+      const val = await AsyncStorage.getItem(key);
+      return Promise.resolve(val);
     },
   }),
 };

+ 35 - 15
models/userModel.js

@@ -5,7 +5,7 @@ import * as RootNavigation from "../navigation/RootNavigation";
 
 export default {
   state: {
-    mid: 0,
+    mid: null,
     name: "未登录",
     showName: "未登录",
     phone: "",
@@ -27,13 +27,17 @@ export default {
       const { updateUser } = model();
       const { httpGet } = model("httpModel");
       const { changeVerfied } = model("verifiedModel");
-      return httpGet("/merchant/my").then(res => {
-        const _res = { ...res };
-        if (_res) {
-          updateUser(_res);
-          changeVerfied(_res.userId);
-        }
-      });
+      return httpGet("/merchant/my")
+        .then(res => {
+          const _res = { ...res };
+          if (_res) {
+            updateUser(_res);
+            changeVerfied(_res.userId);
+          }
+        })
+        .catch(() => {
+          setState({ mid: 0 });
+        });
     },
     changeInIt() {
       setState({ initApp: false });
@@ -147,13 +151,8 @@ export default {
     },
     changeGuideStep(step) {
       const { addAsyncStorage } = model("httpModel");
-      addAsyncStorage("guideStep", step.toString()).then(() => {
-        setState({ initApp: true, refreashReason: "guideStep" });
-
-        setTimeout(() => {
-          setState({ initApp: false });
-        }, 500);
-      });
+      setState({ guideStep: step });
+      return addAsyncStorage("guideStep", step.toString());
     },
     saveMerchant({ ...data }) {
       const { mid, changeGuideStep } = model();
@@ -260,6 +259,25 @@ export default {
         }
       });
     },
+    checkNowGuideStep() {
+      const { status } = model();
+      const { getAsyncStorage } = model("httpModel");
+
+      return getAsyncStorage("guideStep").then(res => {
+        console.log(res);
+        let guideStep = res;
+        if (status === "PASS" && !guideStep) {
+          guideStep = "5";
+        } else if (
+          status === "DENY" &&
+          (!guideStep || guideStep === "finish")
+        ) {
+          guideStep = "5";
+        }
+        setState({ guideStep: guideStep || "1" });
+        return Promise.resolve(guideStep || "1");
+      });
+    },
     closeMer() {
       const { isOpening, getUserInfo } = model();
       const { httpGet } = model("httpModel");
@@ -312,7 +330,9 @@ export default {
       };
     },
     checkAgain({ ...info }) {
+      const { loading } = model("loadingModel");
       const { updateMerchant, changeGuideStep } = model();
+      loading();
       updateMerchant({
         ...info,
         status: "PENDING",

+ 53 - 37
models/wordsModel.js

@@ -1,43 +1,59 @@
+import * as Localization from "expo-localization";
 import { i18n, keys } from "../language";
 
 export default {
-    state: {},
-    actions: ({ model, setState }) => ({
-        getWords() {
-			
-            const words = {};
-            keys.forEach(item => {
-                words[item] = i18n.t(item);
-            });
-            setState({ ...words });
-        },
-        getWordsStr(key) {
-            const allWords = model();
-            return allWords[key];
-        },
-        weekWords() {
-            const {
-                MONDAY,
-                TUESDAY,
-                WEDNESDAY,
-                THURSDAY,
-                FRIDAY,
-                SATURDAY,
-                SUNDAY,
-                every,
-            } = model();
+  state: {
+    local: "",
+  },
+  actions: ({ model, setState }) => ({
+    getWords() {
+      const { local } = model();
+      if (local) {
+        i18n.locale = local;
+      } else {
+        i18n.locale = Localization.locale;
+      }
+      const words = {};
+      keys.forEach(item => {
+        words[item] = i18n.t(item);
+      });
+      setState({ ...words });
+    },
+    getWordsStr(key) {
+      const allWords = model();
+      return allWords[key];
+    },
+    weekWords() {
+      const {
+        MONDAY,
+        TUESDAY,
+        WEDNESDAY,
+        THURSDAY,
+        FRIDAY,
+        SATURDAY,
+        SUNDAY,
+        every,
+      } = model();
 
-            return {
-                MONDAY,
-                TUESDAY,
-                WEDNESDAY,
-                THURSDAY,
-                FRIDAY,
-                SATURDAY,
-                SUNDAY,
-                all: every,
-            };
-        },
-    }),
+      return {
+        MONDAY,
+        TUESDAY,
+        WEDNESDAY,
+        THURSDAY,
+        FRIDAY,
+        SATURDAY,
+        SUNDAY,
+        all: every,
+      };
+    },
+    changeLocal() {
+      const { local } = model();
+      if (local) {
+        setState({ local: "" });
+      } else {
+        setState({ local: "th" });
+      }
+    },
+  }),
 };
 // 国际化

+ 51 - 0
package-lock.json

@@ -3415,6 +3415,28 @@
         "react-native-eva-icons": "^1.3.1"
       }
     },
+    "@umijs/hooks": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/@umijs/hooks/-/hooks-1.9.3.tgz",
+      "integrity": "sha512-h83Zk0x2oO8HeTZlSLsT4KVh+Me1VoXu+DHmT+cpqR7caBhii0T5c8Weko/pFBkEiB4QKzvWi7Zj+78VSKkI5w==",
+      "requires": {
+        "@umijs/use-request": "^1.4.3",
+        "intersection-observer": "^0.7.0",
+        "lodash.isequal": "^4.5.0",
+        "resize-observer-polyfill": "^1.5.1",
+        "screenfull": "^5.0.0"
+      }
+    },
+    "@umijs/use-request": {
+      "version": "1.4.3",
+      "resolved": "https://registry.npmjs.org/@umijs/use-request/-/use-request-1.4.3.tgz",
+      "integrity": "sha512-aH4GCdRnMCaaciygdN0KtCDQdBBh1KyiNUAgYDPX8Y4brmbymEpJViX1FU4isOTbV34WlbkWTiBpR9HIi2ciNQ==",
+      "requires": {
+        "lodash.debounce": "^4.0.8",
+        "lodash.throttle": "^4.1.1",
+        "umi-request": "^1.2.17"
+      }
+    },
     "@unimodules/core": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/@unimodules/core/-/core-5.1.2.tgz",
@@ -8810,6 +8832,11 @@
         "side-channel": "^1.0.2"
       }
     },
+    "intersection-observer": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.7.0.tgz",
+      "integrity": "sha512-Id0Fij0HsB/vKWGeBe9PxeY45ttRiBmhFyyt/geBdDHBYNctMRTE3dC1U3ujzz3lap+hVXlEcVaB56kZP/eEUg=="
+    },
     "invariant": {
       "version": "2.2.4",
       "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
@@ -10879,6 +10906,11 @@
       "resolved": "https://registry.npmjs.org/lodash.findindex/-/lodash.findindex-4.6.0.tgz",
       "integrity": "sha1-oyRd7mH7m24GJLU1ElYku2nBEQY="
     },
+    "lodash.isequal": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+      "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
+    },
     "lodash.memoize": {
       "version": "4.1.2",
       "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -15178,6 +15210,11 @@
       "resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz",
       "integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc="
     },
+    "resize-observer-polyfill": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+    },
     "resolve": {
       "version": "1.17.0",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
@@ -15376,6 +15413,11 @@
         "ajv-keywords": "^3.4.1"
       }
     },
+    "screenfull": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.0.2.tgz",
+      "integrity": "sha512-cCF2b+L/mnEiORLN5xSAz6H3t18i2oHh9BA8+CQlAh5DRw2+NFAGQJOSYbcGw8B2k04g/lVvFcfZ83b3ysH5UQ=="
+    },
     "semver": {
       "version": "5.7.1",
       "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
@@ -16839,6 +16881,15 @@
       "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz",
       "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po="
     },
+    "umi-request": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/umi-request/-/umi-request-1.3.3.tgz",
+      "integrity": "sha512-TRf5x11OJ/9VBi2ZzCJGg/ZFs6KXxpZg1hV0/9oYa9d4YZtQ62Gk6djbonYoMFkyw7fMcxRh8ayPe4YG/gCNeg==",
+      "requires": {
+        "isomorphic-fetch": "^2.2.1",
+        "qs": "^6.9.1"
+      }
+    },
     "unicode-canonical-property-names-ecmascript": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",

+ 1 - 0
package.json

@@ -26,6 +26,7 @@
     "@react-navigation/web": "~1.0.0-alpha.9",
     "@ui-kitten/components": "^5.0.0",
     "@ui-kitten/eva-icons": "^5.0.0",
+    "@umijs/hooks": "^1.9.3",
     "axios": "^0.19.2",
     "beeshell": "^2.0.11",
     "chokidar": "^3.4.0",

+ 1 - 1
screens/Attestation/LegalPersonScreen.js

@@ -121,7 +121,7 @@ export default function LegalPersonScreen({ navigation }) {
             labelStyle={{ width: 100 }}
           />
           <FormInput
-            key="idNoImg"
+            key="before"
             label="证件原件照片:"
             type="label"
             textAlign="right"

+ 3 - 2
screens/Attestation/StoreScreen.js

@@ -61,7 +61,7 @@ export default function StoreScreen({ navigation }) {
     updateMerchant,
     changeRegisterInfo,
   } = useModel("userModel");
-  const { success } = useModel("loadingModel", true);
+  const { success, loading } = useModel("loadingModel", true);
 
   const [doorHeadImg, setDoorHeadImg] = React.useState("");
   const [img1, setImg1] = React.useState("");
@@ -95,6 +95,7 @@ export default function StoreScreen({ navigation }) {
     const imgList = new ListUtil([img1, img2, img3, img4, img5]);
 
     if (mid) {
+      loading();
       updateMerchant({
         doorHeadImg,
         img: imgList.getListValue(),
@@ -114,7 +115,7 @@ export default function StoreScreen({ navigation }) {
 
   return (
     <>
-      <NavHeaderBar title="编辑法人信息" />
+      <NavHeaderBar title="编辑门店信息" />
       <ScrollPage>
         <Layout style={styles.container}>
           <FormInput

+ 121 - 9
screens/Goods/GoodsSpecificationScreen.js

@@ -16,6 +16,7 @@ import {
   Toggle,
 } from "@ui-kitten/components";
 import { useFocusEffect, useRoute } from "@react-navigation/native";
+import { useEventEmitter } from "@umijs/hooks";
 import ActionButton from "react-native-action-button";
 import ListComponent from "../../components/ListComponent";
 import NavHeaderBar from "../../components/NavHeaderBar";
@@ -64,6 +65,9 @@ const styles = StyleSheet.create({
     width: 80,
     alignSelf: "center",
   },
+  separatorStyle: {
+    height: 0,
+  },
 });
 
 export default function GoodsSpecificationScreen() {
@@ -78,6 +82,7 @@ export default function GoodsSpecificationScreen() {
   const [startState, changeState] = React.useState(true);
   const [editList, setEditList] = React.useState([]);
   const [addNew, changeNew] = React.useState([]);
+  const list$ = useEventEmitter();
 
   const {
     delText,
@@ -151,7 +156,7 @@ export default function GoodsSpecificationScreen() {
       content = content.map(item => {
         const _info = {
           ...item,
-          amount: item.amount ? item.amount.toString() : "",
+          amount: item.amount != null ? item.amount.toString() : "",
         };
         if (!_info.id || editList.indexOf(_info.id) !== -1) {
           _info.edit = true;
@@ -169,11 +174,73 @@ export default function GoodsSpecificationScreen() {
     });
   }
 
+  const listByOrder = (list1, list2, type, extra) => {
+    let list = [...list1];
+    if (type === "add") {
+      list2.forEach((item, index) => {
+        if (item.addType === "1") {
+          list.push({ name: "", multiple: false, addIndex: index });
+        } else {
+          let _index = list.findIndex(_i => {
+            return _i.id === item.parent;
+          });
+          list.splice(_index + 1, 0, {
+            name: "",
+            amount: "",
+            parent: item.parent,
+            addIndex: index,
+          });
+        }
+      });
+    } else if (type === "save") {
+      list = list.map(item => {
+        if (
+          (item.addIndex === extra && extra != null) ||
+          item.id === list2[0].id
+        ) {
+          item = { ...list2[0] };
+        }
+        return item;
+      });
+    } else if (type === "edit") {
+      list = list.map(item => {
+        if (item.id === extra) {
+          item = {
+            ...item,
+            edit: true,
+          };
+        }
+        return item;
+      });
+    } else if (type === "cancel" && extra.id) {
+      list = list.map(item => {
+        if (item.id === extra.id) {
+          item.edit = false;
+        }
+        return item;
+      });
+    } else if (type === "del" || (!extra.id && type === "cancel")) {
+      list = list.filter(item => {
+        return (
+          (extra.id && item.id !== extra.id) ||
+          (!extra.id && item.addIndex !== extra.addIndex)
+        );
+      });
+    }
+    setEdit(list);
+    return list;
+  };
+
   const editInfo = id => {
     const _editList = [...editList];
     _editList.push(id);
     setEditList(_editList);
-    changeState(true);
+    list$.emit({
+      type: "edit",
+      list: [],
+      changeEvent: listByOrder,
+      extra: id,
+    });
   };
   const delInfo = info => {
     showDialog({
@@ -197,7 +264,13 @@ export default function GoodsSpecificationScreen() {
         httpPost(`/goodsSpecification/del/${info.id}`)
           .then(() => {
             success(successText);
-            changeState(true);
+            // changeState(true);
+            list$.emit({
+              type: "del",
+              list: [],
+              changeEvent: listByOrder,
+              extra: info,
+            });
           })
           .catch(e => {
             warnning(e.error);
@@ -213,12 +286,25 @@ export default function GoodsSpecificationScreen() {
         return item !== info.id;
       });
       setEditList(_editList);
+      list$.emit({
+        type: "cancel",
+        list: [],
+        changeEvent: listByOrder,
+        extra: info,
+      });
     } else {
       let _addNew = [...addNew];
       _addNew.splice(info.addIndex, 1);
       changeNew(_addNew);
+
+      list$.emit({
+        type: "cancel",
+        list: [],
+        changeEvent: listByOrder,
+        extra: info,
+      });
     }
-    changeState(true);
+    // changeState(true);
   };
 
   // 保存
@@ -235,19 +321,29 @@ export default function GoodsSpecificationScreen() {
       goodsId,
     };
     delete data.addIndex;
-    addClassGoods(data).then(() => {
+    addClassGoods(data).then(res => {
       if (info.id) {
         let _editList = [...editList];
         _editList = _editList.filter(item => {
           return item !== info.id;
         });
         setEditList(_editList);
+        list$.emit({
+          type: "save",
+          list: [res],
+          changeEvent: listByOrder,
+        });
       } else {
         let _addNew = [...addNew];
         _addNew.splice(info.addIndex, 1);
         changeNew(_addNew);
+        list$.emit({
+          type: "save",
+          list: [res],
+          extra: info.addIndex,
+          changeEvent: listByOrder,
+        });
       }
-      changeState(true);
     });
   };
 
@@ -265,15 +361,30 @@ export default function GoodsSpecificationScreen() {
       if (!hasParent) {
         list.push(info);
         changeNew(list);
-        changeState(true);
+        list$.emit({
+          type: "add",
+          list: [
+            {
+              ...info,
+            },
+          ],
+          changeEvent: listByOrder,
+        });
       }
     } else if (!info && !hasType1) {
       list.push({
         addType: "1",
       });
-      console.log(list);
       changeNew(list);
-      changeState(true);
+      list$.emit({
+        type: "add",
+        list: [
+          {
+            addType: "1",
+          },
+        ],
+        changeEvent: listByOrder,
+      });
     }
   };
 
@@ -418,6 +529,7 @@ export default function GoodsSpecificationScreen() {
           showEmpty
           extraData={{ allEditInfo }}
           startState={startState}
+          list$={list$}
         />
         <ActionButton
           buttonColor={theme["color-primary-500"]}

+ 2 - 1
screens/Guide1Screen.js

@@ -75,7 +75,7 @@ export default function Guide1Screen({ navigation }) {
   const theme = useTheme();
   const { changeBackground } = useModel("barModel");
   const { httpGet, httpPost } = useModel("httpModel", true);
-  const { success } = useModel("loadingModel", true);
+  const { success, loading } = useModel("loadingModel", true);
   const { mid, changeGuideStep } = useModel("userModel", true);
   const { addClassification, sortClassification } = useModel(
     "goodsModel",
@@ -157,6 +157,7 @@ export default function Guide1Screen({ navigation }) {
       if (params) {
         if (params.id) {
           changeId(params.id);
+          loading();
           httpGet(`/goods/get/${params.id}`).then(res => {
             getInfo(res);
           });

+ 13 - 20
screens/RegisterSeScreen.js

@@ -7,6 +7,7 @@ import { StyleSheet } from "react-native";
 import { Layout, Text, useTheme, Button, Card } from "@ui-kitten/components";
 
 import { useFocusEffect } from "@react-navigation/native";
+import { useToggle, useMount } from "@umijs/hooks";
 
 import ScrollPage from "../components/ScrollPage";
 import FormInput from "../components/FormInput";
@@ -72,18 +73,16 @@ export default function RegisterScreen() {
   const [categoryList, changeCategoryList] = React.useState([]);
   const [merchantNatureList, changeMerchantNatureList] = React.useState([]);
   const [qualification, changeQualification] = React.useState("");
-  useFocusEffect(
-    React.useCallback(() => {
-      changeBackground(theme["color-primary-500"]);
-      httpGet("/category/tree", { id: 1 }).then(res => {
-        changeCategoryList(res);
-      });
+  useMount(() => {
+    changeBackground(theme["color-primary-500"]);
+    httpGet("/category/tree", { id: 1 }).then(res => {
+      changeCategoryList(res);
+    });
 
-      httpGet("/merchantNature/all").then(res => {
-        changeMerchantNatureList(res.content);
-      });
-    }, [])
-  );
+    httpGet("/merchantNature/all").then(res => {
+      changeMerchantNatureList(res.content);
+    });
+  });
 
   const [category, changeCategory] = React.useState("");
   const [address, changeAddress] = React.useState("");
@@ -95,7 +94,6 @@ export default function RegisterScreen() {
   const [doorHeadImg, changeDoorHeadeImg] = React.useState("");
   const [img, changeImg] = React.useState("");
 
-
   // 法人信息
   const [realName, setRealName] = React.useState("");
   const [idNo, setIdNo] = React.useState("");
@@ -115,9 +113,6 @@ export default function RegisterScreen() {
     if (registerVerifiedInfo && registerVerifiedInfo.handheldIdNo) {
       setHandheldIdNo(registerVerifiedInfo.handheldIdNo);
     }
-  }, [registerVerifiedInfo]);
-
-  React.useEffect(() => {
     if (verifiedInfo && verifiedInfo.realName) {
       setRealName(verifiedInfo.realName);
     }
@@ -130,7 +125,7 @@ export default function RegisterScreen() {
     if (verifiedInfo && verifiedInfo.handheldIdNo) {
       setHandheldIdNo(verifiedInfo.handheldIdNo);
     }
-  }, [verifiedInfo]);
+  }, [registerVerifiedInfo, verifiedInfo]);
 
   React.useEffect(() => {
     if (registerInfo && registerInfo.qualification) {
@@ -143,6 +138,7 @@ export default function RegisterScreen() {
       changeImg(registerInfo.img);
     }
   }, [registerInfo]);
+  
   React.useEffect(() => {
     if (mid) {
       if (userInfo.category.length > 0) {
@@ -157,11 +153,8 @@ export default function RegisterScreen() {
       changeQualification(userInfo.qualification);
       changeDoorHeadeImg(userInfo.doorHeadImg);
       changeImg(userInfo.img);
-      console.log(userInfo);
-
-      
     }
-  }, [mid]);
+  }, [userInfo]);
 
   const timeValue = React.useMemo(() => {
     if (week && startTime && endTime) {