panhui 5 лет назад
Родитель
Сommit
24d6603051

+ 1 - 1
App.js

@@ -135,7 +135,7 @@ export default function App(props) {
                                         cardStyleInterpolator:
                                             CardStyleInterpolators.forHorizontalIOS,
                                     }}
-                                    // initialRouteName="Automatic"
+                                    initialRouteName='CouponAdd'
                                 >
                                     {/* <Stack.Screen
                                     name='LoadingModel'

+ 13 - 1
Redux/DataListRedux.js

@@ -49,10 +49,22 @@ export function DataListReducer(state, action) {
         case "setInfo":
             return {
                 ...state,
-                dataList: action.payload.list,
+                dataList:
+                    state.page == 0
+                        ? action.payload.list
+                        : state.dataList.concat(action.payload.list),
                 finish: action.payload.finish,
                 page: action.payload.finish ? state.page : state.page + 1,
             };
+        case "remove": {
+            let list = [...state.dataList];
+            list.splice(action.payload.index, 1);
+            console.log(list);
+            return {
+                ...state,
+                dataList: list,
+            };
+        }
         default:
             return state;
     }

+ 10 - 3
Utils/ListUtil.js

@@ -1,11 +1,18 @@
 export default class ListUtil {
     constructor(list) {
-        console.log(list);
-        this.list = list || [];
+        if (list && list.constructor === String) {
+            this.list = list.split(",");
+        } else {
+            this.list = list || [];
+        }
+    }
+
+    getLength() {
+        return this.list.length;
     }
 
     getKey(key) {
-        let _list=[...this.list]
+        let _list = [...this.list];
         if (_list.length > 0) {
             return _list.pop()[key];
         } else {

+ 28 - 0
Utils/SystemRuleUtil.js

@@ -0,0 +1,28 @@
+//系统检查方法
+
+//商品分类
+
+const systemMenus = ["好评热销", "点单必读", "折扣"];
+const menuTips = {
+    好评热销: ["systemClassification1", "systemClassification2"],
+    点单必读: ["systemClassification3", "systemClassification4"],
+    折扣: ["systemClassification5", "systemClassification6"],
+};
+export class ClassificationUtil {
+    constructor(classification) {
+        let { name, id, goodsIds, isOpen } = classification || {};
+        this.name = name || "";
+        this.id = id || "";
+        this.goodsIds = goodsIds || "";
+        this.isOpen = isOpen || false;
+        this.allInfo = classification || {};
+    }
+
+    checkSystem() {
+        return systemMenus.indexOf(this.name) != -1;
+    }
+
+    getMenuTipsList() {
+        return menuTips[this.name] || [];
+    }
+}

+ 19 - 0
Utils/TimeUtil.js

@@ -0,0 +1,19 @@
+import moment from "moment";
+
+export function getNowYear() {
+    return new Date().getFullYear();
+}
+
+export function getNowDate() {
+    return new Date().getDate();
+}
+
+export function getDateStr() {
+    return moment().format("YYYY-MM-DD");
+}
+
+export function getAddDateStr(num) {
+    return moment()
+        .add(num || 2, "days")
+        .format("YYYY-MM-DD");
+}

+ 88 - 0
components/Coupon.js

@@ -0,0 +1,88 @@
+import React from "react";
+import { StyleSheet } from "react-native";
+import {
+    Modal,
+    Card,
+    Text,
+    Button,
+    Layout,
+    Avatar,
+    Icon,
+} from "@ui-kitten/components";
+import { useModel } from "flooks";
+
+export default function Coupon(props) {
+    const { getWordsStr } = useModel("wordsModel");
+    const { info } = props;
+    const { id, amount, fullAmount, name, endDate, startDate } = info || {};
+    const code = React.useMemo(() => {
+        if (amount) {
+            return (amount > 0 ? "+ " : "- ") + amount.toFixed(2);
+        } else {
+            return "+ 0.00";
+        }
+    }, [amount]);
+    return (
+        <Card appearance='walletCard'>
+            <Layout style={styles.main}>
+                <Layout style={styles.left}>
+                    <Text category='h6' status='danger'>
+                        <Text category='h1' status='danger'>¥</Text>
+                        {amount}
+                    </Text>
+                    <Text category='h1' status='info'>
+                        {fullAmount
+                            ? "满" + fullAmount + "元可用"
+                            : "无金额门槛"}
+                    </Text>
+                </Layout>
+                <Layout style={styles.center}>
+                    <Text category='h6'>{name}</Text>
+                    <Text category='h1' status='info' style={styles.text2}>
+                        {startDate}
+                        {endDate}
+                    </Text>
+                </Layout>
+            </Layout>
+        </Card>
+    );
+}
+
+const ForwardIcon = props => (
+    <Icon
+        {...props}
+        name='arrow-ios-forward'
+        fill='#B4B4B4'
+        style={{ width: 15, height: 15, fontWeight: 500 }}
+    />
+);
+const styles = StyleSheet.create({
+    main: {
+        flexDirection: "row",
+        alignItems: "center",
+        backgroundColor: "transparent",
+    },
+    left: {
+        width: 80,
+        flexShrink: 0,
+        alignItems: "center",
+    },
+    center: {
+        flex: 1,
+        marginLeft: 14,
+        backgroundColor: "transparent",
+    },
+    text2: {
+        paddingTop: 6,
+    },
+    code: {
+        alignSelf: "flex-start",
+    },
+    icon: {
+        width: 20,
+        position: "absolute",
+        right: 0,
+        top: "50%",
+        marginTop: -10,
+    },
+});

+ 66 - 0
components/Datepicker.js

@@ -0,0 +1,66 @@
+import React from "react";
+import PropTypes from "prop-types";
+import {
+    StyleSheet,
+    TouchableOpacity,
+    LayoutAnimation,
+    Platform,
+    UIManager,
+} from "react-native";
+import {
+    CheckBox,
+    Layout,
+    Modal,
+    Button,
+    Card,
+    Text,
+    MenuItem,
+    Icon,
+    SelectItem,
+} from "@ui-kitten/components";
+import { Datepicker, BottomModal } from "beeshell";
+import moment from "moment";
+import * as TimeUtil from "../Utils/TimeUtil";
+
+const ForwardIcon = props => <Icon {...props} name='arrow-ios-forward' />;
+
+export default function MyDatepicker(props) {
+    const { value, chooseDate } = props || {};
+
+    const [dateValue, chooseValue] = React.useState();
+
+    const [bottomModal, setBottomModal] = React.useState();
+
+    return (
+        <>
+            <SelectItem
+                appearance='form'
+                style={{ flex: 1, height: 32 }}
+                accessoryRight={ForwardIcon}
+                title={value || " "}
+                onPress={() => {
+                    bottomModal.open();
+                }}
+            />
+            <BottomModal
+                title=''
+                cancelable={true}
+                ref={c => setBottomModal(c)}
+                rightCallback={() => {
+                    chooseDate(dateValue);
+                }}
+            >
+                <Datepicker
+                    style={{ minHeight: 200, width: "100%", flexShrink: 0 }}
+                    proportion={[1, 1, 1]}
+                    startYear={TimeUtil.getNowYear()}
+                    numberOfYears={10}
+                    date={TimeUtil.getDateStr()}
+                    onChange={date => {
+                        chooseValue(date);
+                    }}
+                />
+            </BottomModal>
+        </>
+    );
+}

+ 5 - 1
components/EmptyComponent.js

@@ -8,7 +8,11 @@ export default function EmptyComponent(props) {
         <Text
             category='h1'
             status='info'
-            style={{ textAlign: "center", backgroundColor: "transparent" }}
+            style={{
+                textAlign: "center",
+                backgroundColor: "transparent",
+                paddingVertical: 20,
+            }}
         >
             {nothingTips}
         </Text>

+ 6 - 3
components/FormInput.js

@@ -14,6 +14,7 @@ import { Cascader, BottomModal } from "beeshell";
 import variables from "../constants/customTheme";
 import { useModel } from "flooks";
 import OpenTime from "./OpenTime";
+import Datepicker from "./Datepicker";
 import UpLoadImage from "./UpLoadImage";
 import moment from "moment";
 import Actionsheet from "./Actionsheet";
@@ -219,6 +220,10 @@ const FormInput = React.memo(props => {
                     defaultValue={props.defaultValue}
                 />
             );
+        } else if (type == "date") {
+            return (
+                <Datepicker chooseDate={props.onChange} value={props.value} />
+            );
         } else if (type == "url") {
             return (
                 <SelectItem
@@ -254,9 +259,7 @@ const FormInput = React.memo(props => {
                     accessoryLeft={leftprops => (
                         <Label {...props} {...leftprops} />
                     )}
-                    accessoryRight={() => (
-                        <Btn btnText={props.btnText} />
-                    )}
+                    accessoryRight={() => <Btn btnText={props.btnText} />}
                     size='small'
                     style={styles.input}
                     appearance='innerCode'

+ 44 - 8
components/GoodsCard.js

@@ -11,10 +11,20 @@ import {
 } from "@ui-kitten/components";
 import { useModel } from "flooks";
 export default function GoodsCard(props) {
-    const { add, remove } = useModel("wordsModel");
-    const { info } = props;
-    const { id, img, name, introduction, totalSales, discountAmount, amount } =
-        info || {};
+    const { add, remove, getWordsStr } = useModel("wordsModel");
+    const { info, changeInfo } = props;
+    const {
+        id,
+        img,
+        name,
+        introduction,
+        totalSales,
+        discountAmount,
+        amount,
+        takeOff,
+    } = info || {};
+
+    const { takeOffInfo, ChangeTakeOff } = useModel("goodsModel", true);
 
     return (
         <Card
@@ -65,6 +75,31 @@ export default function GoodsCard(props) {
                         </Text>
                     </Layout>
 
+                    {!props.appearance && props.isAdd && (
+                        <Layout style={styles.butContent}>
+                            <Button
+                                status='primary'
+                                size='small'
+                                appearance='outline'
+                                onPress={() => {
+                                    if (!takeOff) {
+                                        takeOffInfo(() => {
+                                            ChangeTakeOff(info).then(res => {
+                                                changeInfo(res);
+                                            });
+                                        });
+                                    } else {
+                                        ChangeTakeOff(info).then(res => {
+                                            changeInfo(res);
+                                        });
+                                    }
+                                }}
+                            >
+                                {getWordsStr(takeOff ? "takeUp" : "takeOff")}
+                            </Button>
+                        </Layout>
+                    )}
+
                     {!props.appearance && !props.isAdd && (
                         <Layout style={styles.butContent}>
                             <Button
@@ -77,7 +112,7 @@ export default function GoodsCard(props) {
                         </Layout>
                     )}
 
-                    {!props.appearance && props.isAdd && (
+                    {props.appearance && props.isAdd && (
                         <Layout style={styles.butContent}>
                             <Button
                                 status='danger'
@@ -88,15 +123,16 @@ export default function GoodsCard(props) {
                             </Button>
                         </Layout>
                     )}
-                    {/* 
+
                     {props.appearance == "classification" &&
                         props.type != "goodsList" && (
                             <Button
                                 style={styles.miniButton}
                                 status='danger'
+                                onPress={props.removeEvent}
                                 accessoryLeft={StarIcon}
                             />
-                        )} */}
+                        )}
                 </Layout>
             ) : (
                 <Layout style={styles.layout} />
@@ -104,7 +140,7 @@ export default function GoodsCard(props) {
         </Card>
     );
 }
-const StarIcon = props => <Icon {...props} name='minus-outline' />;
+const StarIcon = props => <Icon {...props} name='minus' />;
 
 const styles = StyleSheet.create({
     card: { marginTop: 10 },

+ 25 - 8
components/ListComponent.js

@@ -21,6 +21,7 @@ export default function ListComponent(props) {
         emptyEvent,
         showList,
         extraData,
+        delId,
     } = props;
 
     useFocusEffect(
@@ -28,15 +29,17 @@ export default function ListComponent(props) {
             onRefresh();
         }, [])
     );
-
     function getList() {
         if (getInfo != null) {
             return getInfo(page, size).then(res => {
-                if (res.numberOfElements === 0) {
-                    emptyEvent(true);
-                } else {
-                    emptyEvent(false);
+                if (emptyEvent) {
+                    if (res.numberOfElements === 0) {
+                        emptyEvent(true);
+                    } else {
+                        emptyEvent(false);
+                    }
                 }
+
                 dispatch({
                     type: "setInfo",
                     payload: { list: res.content, finish: res.last },
@@ -47,6 +50,21 @@ export default function ListComponent(props) {
         }
     }
 
+    React.useEffect(() => {
+        if (delId) {
+            let list = [...dataList];
+            let Index = list.findIndex(item => {
+                return item.id === delId;
+            });
+            if (Index != -1) {
+                dispatch({
+                    type: "remove",
+                    payload: { index: Index },
+                });
+            }
+        }
+    }, [delId]);
+
     // 刷新接口
     function onRefresh() {
         dispatch({ type: "startPageMore" });
@@ -80,14 +98,13 @@ export default function ListComponent(props) {
     const changePorps = React.useMemo(() => {
         let _props = { renderItem: () => <Layout /> };
         if (showList != false) {
-            _props = { renderItem };
+            _props = { renderItem: renderItem };
             if (showEmpty) {
                 _props = {
                     ..._props,
-                    EmptyComponent,
+                    ListEmptyComponent: EmptyComponent,
                 };
             }
-
             if (extraData) {
                 _props = {
                     ..._props,

+ 35 - 15
components/ScrollPage.js

@@ -2,16 +2,31 @@ import React from "react";
 import { ScrollView, RefreshControl } from "react-native";
 import { initState, refreashReducer } from "../Redux/RefreashRedux";
 import { useFocusEffect } from "@react-navigation/native";
+import NavHeaderBar from "./NavHeaderBar";
+import { useTheme } from "@ui-kitten/components";
+import { useModel } from "flooks";
 export default function scrollPage(props) {
-    const { style, enabledFresh, refreshEvent } = props;
+    const {
+        style,
+        enabledFresh,
+        refreshEvent,
+        statusType,
+        navHeaderBarTitle,
+    } = props;
     const [state, dispatch] = React.useReducer(refreashReducer, initState);
     const { refreshing, error } = state;
-    
+    const theme = useTheme();
+    const { changeBackground } = useModel("barModel");
+
     useFocusEffect(
         React.useCallback(() => {
             if (enabledFresh && refreshEvent) {
                 onRefresh();
             }
+
+            if (statusType === "primary") {
+                changeBackground(theme["color-primary-500"]);
+            }
         }, [])
     );
 
@@ -41,18 +56,23 @@ export default function scrollPage(props) {
     }
 
     return (
-        <ScrollView
-            refreshControl={
-                <RefreshControl
-                    refreshing={refreshing}
-                    onRefresh={onRefresh}
-                    enabled={enabledFresh || false}
-                />
-            }
-            style={style}
-            contentContainerStyle={{ flexGrow: 1 }}
-        >
-            {props.children}
-        </ScrollView>
+        <>
+            {navHeaderBarTitle != null && (
+                <NavHeaderBar title={navHeaderBarTitle} />
+            )}
+            <ScrollView
+                refreshControl={
+                    <RefreshControl
+                        refreshing={refreshing}
+                        onRefresh={onRefresh}
+                        enabled={enabledFresh || false}
+                    />
+                }
+                style={style}
+                contentContainerStyle={{ flexGrow: 1 }}
+            >
+                {props.children}
+            </ScrollView>
+        </>
     );
 }

+ 34 - 0
components/TipNavHeader.js

@@ -0,0 +1,34 @@
+import * as React from "react";
+import NavHeaderBar from "./NavHeaderBar";
+import { Layout } from "@ui-kitten/components";
+import { StyleSheet } from "react-native";
+
+//导航条+头部提示模块
+export default function TipNavHeader({ title, children }) {
+    return (
+        <>
+            <NavHeaderBar title={title} />
+            <Layout style={styles.top}>
+                {children.map(item => {
+                    if (item.type.styledComponentName === "Text") {
+                        return {
+                            ...item,
+                            props: {
+                                category: "c1",
+                                ...item.props,
+                            },
+                        };
+                    } else {
+                        return item;
+                    }
+                })}
+            </Layout>
+        </>
+    );
+}
+const styles = StyleSheet.create({
+    top: {
+        marginTop: 7,
+        padding: 15,
+    },
+});

+ 42 - 8
language/zh.js

@@ -68,6 +68,17 @@ export default {
     goodsClassificationTitle1: "分类下的商品",
     goodsClassificationTitle2: "已选择的商品",
     goodsClassificationTitle3: "未选择的商品",
+    systemClassification1:
+        "该分类为系统预制分类,主要用于提醒用户相关的信息,您可以放餐具以及点单必读等信息。",
+    systemClassification2:
+        "如果您没有放置点单必读商品,系统将不显示该分类。所以,如果暂时没有符合标准的产品,也建议您打开。",
+    systemClassification3:
+        "该分类为系统预制分类,自动罗列了商户中的畅销产品和好评度高的产品,系统会根据销售和评价动态更新。",
+    systemClassification4: "所以,如果暂时没有符合标准的产品,也建议您打开。",
+    systemClassification5:
+        "该分类为系统预制分类,自动罗列了已设置的折扣商品,如果没有折扣商品,系统将不显示该分类。",
+    systemClassification6: "您可以在“我的”->“我的优惠活动”中配置折扣商品。",
+    systemClassTips1: "确定要关闭该系统分类吗?",
 
     storeAudio: "审核店铺",
     storeAudioText1: "您的店铺正在审核中",
@@ -76,6 +87,8 @@ export default {
     storeAudioText4: "您的店铺审核成功!",
     addGoods: "编辑(新增)商品",
     addGoods2: "新增商品",
+    takeOff: "下架",
+    takeUp: "上架",
 
     homeBar: "我的店面",
     homeTip1: "添加banner",
@@ -141,17 +154,36 @@ export default {
     bankTitle5: "同意《叮咚外卖快捷支付服务协议》",
     rechargeBtnText: "预计两小时内到账,确认提现",
 
-
     //设置
-    
-    automaticText1:'自动评价回复',
-    automaticText2:'好评自动评价回复',
-    automaticText3:'差评自动评价回复',
-    automaticText4:'添加回复(不超过100字)',
 
+    automaticText1: "自动评价回复",
+    automaticText2: "好评自动评价回复",
+    automaticText3: "差评自动评价回复",
+    automaticText4: "添加回复(不超过100字)",
+
+    distributionTitle: "配送设置",
+    distributionText1: "起送金额",
+    distributionText2: "每餐平均准备时间",
+    distributionText3: "输入金额",
+    distributionText4: "输入时间",
+    distributionText5: "温馨提示",
+    distributionText6:
+        "起送金额为店铺外送起送金额,每餐平均准备时间用于计算商品配送时间,请根据店铺实际餐品准备情况设置。",
 
+    // 我的分类
+    ClassificationManage: "我的分类",
+    ClassificationManageText1: "合理的设置分类具有如下好处",
+    ClassificationManageText2: "(1)可以让用户快速找到适合的商品",
+    ClassificationManageText3:
+        "(2)可以让用户知道商家对于某一样商品的看法和态度",
+    ClassificationManageText4: "同一种商品可以置于不同的分类下。",
+    ClassificationManageText5: "当前有的分类",
+    ClassificationManageText6:'该分类包含了以下商品',
     //公共的文字
 
+    saveSuccess: "保存成功",
+    editSuccess: "修改成功",
+    yuan: "元",
     changeToEnglish: "切换到泰文",
     changeToChinese: "切换到中文",
     appName: "叮咚外卖",
@@ -173,6 +205,7 @@ export default {
     end: "结束时间",
     hour: "时",
     min: "分",
+    minutes: "分钟",
     weekName: "周期",
     tip: "提示",
     passTips: "确认要跳过吗?",
@@ -186,8 +219,9 @@ export default {
     uplaodText: "上传",
     uplaodImg: "上传图片",
     removeTips: "确定要移除吗?移除后不可恢复",
+    takeOffTips: "确定要下架该商品吗?",
     autoBackText: "自动回复",
-    editAutoBack:"编辑自动回复",
+    editAutoBack: "编辑自动回复",
     storeBackInfo: "商家回复",
     delText: "删除",
     successText: "成功",
@@ -200,7 +234,7 @@ export default {
     applySuccess: "申请成功",
     rechargeTime: "预计到账时间",
     rechargeTitle2: "银行卡",
-    rechargeTitle3:'提现金额',
+    rechargeTitle3: "提现金额",
 
     //订单状态
     NOT_RECEIVED: "未接单",

+ 54 - 0
models/couponModel.js

@@ -0,0 +1,54 @@
+//优惠券操作
+
+import * as TimeUtil from "../Utils/TimeUtil";
+export default {
+    state: {
+        defaultStartTime: TimeUtil.getDateStr(),
+        defaultEndTime: TimeUtil.getAddDateStr(),
+    },
+    actions: ({ model, setState }) => ({
+        //获取商家优惠券
+        getMyList(page, size) {
+            const { mid } = model("userModel");
+            const { httpGet } = model("httpModel");
+            return httpGet(
+                "/coupon/all",
+                {
+                    page,
+                    size,
+                    query: {
+                        merchantId: mid,
+                    },
+                },
+                true
+            );
+        },
+        saveInfo(info) {
+            let { httpPost } = model("httpModel");
+            let { mid } = model("userModel");
+            let { success } = model("loadingModel");
+            return httpPost(
+                "/coupon/save",
+                {
+                    ...info,
+                    merchantId: mid,
+                },
+                { body: "json" },
+                true
+            ).then(res => {
+                success("保存成功");
+                return Promise.resolve(res);
+            });
+        },
+        removeInfo(id) {
+            let { removeEvent } = model("dialogModel");
+            let { success } = model("loadingModel");
+            removeEvent(() => {
+                httpPost("/coupon/del/" + id, {}, true).then(res => {
+                    success("删除成功");
+                    return Promise.resolve(res);
+                });
+            });
+        },
+    }),
+};

+ 122 - 0
models/goodsModel.js

@@ -1,3 +1,4 @@
+import ListUtil from "../Utils/ListUtil";
 export default {
     state: {
         selectInfos: [],
@@ -9,5 +10,126 @@ export default {
                 selectInfos: list,
             });
         },
+        //下架提示
+        takeOffInfo(callBack) {
+            let { showDialog } = model("dialogModel");
+            let { takeOffTips } = model("wordsModel");
+            showDialog({
+                bodyText: takeOffTips,
+                status: "danger",
+                cancelable: true,
+                confirmCallback: () => callBack(),
+            });
+        },
+        //商品上下架
+        ChangeTakeOff(info) {
+            let { id, takeOff } = info;
+            let { getWordsStr, successText } = model("wordsModel");
+            let { httpGet } = model("httpModel");
+            let { success } = model("loadingModel");
+
+            return httpGet(
+                "/goods/take",
+                {
+                    id,
+                },
+                true
+            )
+                .then(() => {
+                    return httpGet("/goods/get/" + id, {}, true);
+                })
+                .then(res => {
+                    success(
+                        getWordsStr(res.takeOff ? "takeOff" : "takeUp") +
+                            successText
+                    );
+                    return Promise.resolve(res);
+                });
+        },
+        //关闭分类提示
+        clossClassTip(callBack) {
+            let { showDialog } = model("dialogModel");
+            let { systemClassTips1 } = model("wordsModel");
+            showDialog({
+                bodyText: systemClassTips1,
+                status: "danger",
+                cancelable: true,
+                confirmCallback: () => callBack(),
+            });
+        },
+        saveInfo(info, noTip) {
+            let { saveSuccess, editSuccess } = model("wordsModel");
+            let { httpPost } = model("httpModel");
+            let { success } = model("loadingModel");
+            return httpPost(
+                "/classification/save",
+                info,
+                { body: "json" },
+                true
+            ).then(res => {
+                if (!noTip) {
+                    success(info.id ? editSuccess : saveSuccess);
+                }
+                return Promise.resolve(res);
+            });
+        },
+        //移除分类商品
+        removeClassGoods(classificationId, goodId, callBack) {
+            let { showDialog } = model("dialogModel");
+            let { removeTips, editSuccess } = model("wordsModel");
+            let { httpGet } = model("httpModel");
+            let { success } = model("loadingModel");
+            showDialog({
+                bodyText: removeTips,
+                status: "danger",
+                cancelable: true,
+                confirmCallback: () => {
+                    httpGet(
+                        "/classification/delGoods",
+                        {
+                            classificationId: classificationId,
+                            goodId: goodId,
+                        },
+                        true
+                    ).then(res => {
+                        success(editSuccess);
+                        callBack(res);
+                    });
+                },
+            });
+        },
+        // 添加分类商品
+        addClassGoods(info) {},
+        //移除商品分类
+        removeCLass(info,callBack) {
+            let { showDialog } = model("dialogModel");
+            let { removeTips, editSuccess } = model("wordsModel");
+            let { httpPost } = model("httpModel");
+            let { success } = model("loadingModel");
+            showDialog({
+                bodyText: removeTips,
+                status: "danger",
+                cancelable: true,
+                confirmCallback: () => {
+                    let goods = new ListUtil(info.goodsIds);
+                    if (goods.length > 0) {
+                        showDialog({
+                            bodyText: "该分类下有商品,暂不可删除该商品分类",
+                            status: "danger",
+                        });
+                    } else {
+                        httpPost(
+                            "/classification/del/" + info.id,
+                            {},
+                            {},
+                            true
+                        ).then(res => {
+                            success(editSuccess);
+                            callBack(res);
+                        });
+                    }
+                },
+            });
+        },
     }),
 };

+ 2 - 0
models/index.js

@@ -6,9 +6,11 @@ import barModel from "./barModel";
 import goodsModel from "./goodsModel";
 import orderInfoModel from "./orderInfoModel";
 import appUserModel from "./appUserModel";
+import couponModel from "./couponModel";
 
 
 setModel("goodsModel", goodsModel);
+setModel("couponModel", couponModel);
 setModel("barModel", barModel);
 setModel("userModel", userModel);
 setModel("wordsModel", wordsModel);

+ 3 - 0
navigation/BasicNavigator.js

@@ -10,6 +10,7 @@ import Guide2Screen from "../screens/Guide2Screen";
 import MoneyListScreen from "../screens/MoneyListScreen";
 import Bank from "../screens/Bank";
 import SetEvent from "../screens/Set";
+import Coupon from "../screens/Coupon";
 
 export default function BasicScreens(Screen) {
     return (
@@ -29,6 +30,8 @@ export default function BasicScreens(Screen) {
             {Bank(Screen)}
 
             {SetEvent(Screen)}
+
+            {Coupon(Screen)}
         </>
     );
 }

+ 194 - 0
screens/Coupon/AddScreen.js

@@ -0,0 +1,194 @@
+import * as WebBrowser from "expo-web-browser";
+import * as React from "react";
+import { StyleSheet } from "react-native";
+import { useModel } from "flooks";
+import NavHeaderBar from "../../components/NavHeaderBar";
+import { useFocusEffect } from "@react-navigation/native";
+import {
+    Layout,
+    Button,
+    useTheme,
+    TopNavigationAction,
+    Icon,
+    Input,
+    Radio,
+    Divider,
+} from "@ui-kitten/components";
+import FormInput from "../../components/FormInput";
+
+const PlusIcon = props => <Icon {...props} fill='#fff' name='plus' />;
+
+export default function CouponAddScreen({ navigation, route }) {
+    const theme = useTheme();
+    const { changeBackground } = useModel("barModel");
+
+    const { httpPost, httpGet } = useModel("httpModel", true);
+    const { userId } = useModel("userModel");
+    const { success } = useModel("loadingModel", true);
+    const { removeEvent } = useModel("dialogModel", true);
+    const [id, setId] = React.useState();
+    const [prePage, setPrePage] = React.useState();
+    const { defaultStartTime, defaultEndTime, saveInfo, removeInfo } = useModel(
+        "couponModel"
+    );
+    const [name, changeName] = React.useState("");
+    const [amount, changeAmount] = React.useState("");
+    const [fullAmount, changeFullAmount] = React.useState("");
+    const [startDate, changeStartDate] = React.useState("");
+    const [endDate, changeEndDate] = React.useState("");
+
+    useFocusEffect(
+        React.useCallback(() => {
+            changeBackground(theme["color-primary-500"]);
+            let { params } = route;
+            let { id, pageName } = params || {};
+            if (id) {
+                setId(id);
+            } else {
+                changeEndDate(defaultEndTime);
+                changeStartDate(defaultStartTime);
+            }
+        }, [])
+    );
+
+    React.useEffect(() => {
+        if (id) {
+            // httpGet("/bankCard/get/" + id, {}, true).then(res => {
+            //     function getVal(value) {
+            //         return value || "";
+            //     }
+            //     changeName(getVal(res.name));
+            //     changeAmount(getVal(res.amount));
+            //     changeFullAmount(getVal(res.fullAmount));
+            //     changeIdNo(getVal(res.idNo));
+            //     changePhone(getVal(res.phone));
+            //     // changeCode(getVal(res.code));
+            // });
+        }
+    }, [id]);
+
+    const canNext = React.useMemo(() => {
+        if (name && amount && startDate && endDate) {
+            return true;
+        } else {
+            return false;
+        }
+    }, [name, amount, fullAmount, id, startDate, endDate]);
+
+    const submit = () => {
+        saveInfo({ id, name, amount, fullAmount, startDate, endDate }).then(
+            res => {
+                navigation.goBack();
+            }
+        );
+    };
+
+    const remove = () => {
+        removeInfo(id).then(res => {
+            navigation.goBack();
+        });
+    };
+
+    return (
+        <>
+            <NavHeaderBar title='编辑(新增)优惠券' />
+
+            <Layout style={styles.form}>
+                {/* 优惠券名称 */}
+                <FormInput
+                    label='优惠券名称'
+                    labelStyle={styles.label}
+                    key={1}
+                    placeholder='输入优惠券名称'
+                    value={name}
+                    onChange={changeName}
+                />
+                {/* 优惠券金额 */}
+                <FormInput
+                    label='优惠券金额'
+                    labelStyle={styles.label}
+                    key={2}
+                    placeholder='输入金额'
+                    type='money'
+                    value={amount}
+                    onChange={changeAmount}
+                />
+
+                <Divider />
+                {/* 优惠券门槛金额 */}
+                <FormInput
+                    label='优惠券门槛金额'
+                    labelStyle={styles.label}
+                    key={3}
+                    placeholder='输入门槛金额'
+                    type='money'
+                    value={fullAmount}
+                    onChange={changeFullAmount}
+                />
+
+                {/* 优惠券开始时间 */}
+                <FormInput
+                    label='优惠券开始时间'
+                    labelStyle={styles.label}
+                    key={4}
+                    placeholder=''
+                    type='date'
+                    value={startDate}
+                    onChange={changeStartDate}
+                />
+
+                {/* 优惠券结束时间 */}
+                <FormInput
+                    label='优惠券结束时间'
+                    labelStyle={styles.label}
+                    key={5}
+                    placeholder=''
+                    type='date'
+                    value={endDate}
+                    onChange={changeEndDate}
+                />
+
+                <Layout style={styles.btnList}>
+                    <Button
+                        style={styles.btn}
+                        disabled={!canNext}
+                        onPress={submit}
+                    >
+                        确定
+                    </Button>
+                    {id != null && (
+                        <Button
+                            appearance='ghost'
+                            status='info'
+                            onPress={remove}
+                        >
+                            删除
+                        </Button>
+                    )}
+                </Layout>
+            </Layout>
+        </>
+    );
+}
+
+const styles = StyleSheet.create({
+    form: {
+        paddingHorizontal: 10,
+        flex: 1,
+        marginTop: 10,
+    },
+    radio: {
+        paddingVertical: 15,
+        paddingHorizontal: 15,
+    },
+    btn: {
+        marginHorizontal: 15,
+        marginVertical: 10,
+    },
+    btnList: {
+        alignItems: "center",
+    },
+    label: {
+        width: 105,
+    },
+});

+ 15 - 0
screens/Coupon/index.js

@@ -0,0 +1,15 @@
+import * as WebBrowser from "expo-web-browser";
+import * as React from "react";
+import listScreen from "./listScreen";
+import CouponAddScreen from "./AddScreen";
+
+export default function Set(Screen) {
+    return (
+        <>
+            {/* 优惠券列表 */}
+            <Screen name='CouponList' component={listScreen} />
+            {/* 新增优惠券 */}
+            <Screen name='CouponAdd' component={CouponAddScreen} />
+        </>
+    );
+}

+ 103 - 0
screens/Coupon/listScreen.js

@@ -0,0 +1,103 @@
+import * as WebBrowser from "expo-web-browser";
+import * as React from "react";
+import {
+    Image,
+    Platform,
+    StyleSheet,
+    TouchableOpacity,
+    View,
+    ImageBackground,
+} from "react-native";
+import { useModel } from "flooks";
+import {
+    Layout,
+    Tab,
+    TabView,
+    Text,
+    useTheme,
+    Button,
+    Card,
+    List,
+    Select,
+    SelectItem,
+    IndexPath,
+    Avatar,
+    Divider,
+} from "@ui-kitten/components";
+import { useFocusEffect } from "@react-navigation/native";
+import ScrollPage from "../../components/ScrollPage";
+import NavHeaderBar from "../../components/NavHeaderBar";
+import Coupon from "../../components/Coupon";
+
+import ListComponent from "../../components/ListComponent";
+
+// 余额
+const data = ["2020-03", "2020-04", "2020-05"];
+const ItemSeparatorComponent = props => <Divider />;
+
+export default function CouponListScreen({ navigation, route }) {
+    const theme = useTheme();
+    const { changeBackground } = useModel("barModel");
+    const { getUserInfo, money } = useModel("appUserModel");
+    const { httpPost, httpGet } = useModel("httpModel", true);
+    const [selectedIndex, setSelectedIndex] = React.useState(
+        new IndexPath(data.length - 1)
+    );
+
+    const {
+        userTitle6,
+        storeAudioText1,
+        storeAudioText2,
+        storeAudioText3,
+        storeAudioText4,
+        complete,
+    } = useModel("wordsModel");
+    const { getMyList } = useModel("couponModel");
+
+    useFocusEffect(
+        React.useCallback(() => {
+            changeBackground(theme["color-primary-500"]);
+        }, [])
+    );
+
+    const walletItem = ({ item, index }) => <Coupon key={index} info={item} />;
+
+    return (
+        <>
+            <NavHeaderBar title='优惠券管理' />
+            <View style={styles.top}>
+                <Button
+                    appearance='outline'
+                    onPress={() => {
+                        navigation.navigate("CouponAdd");
+                    }}
+                >
+                    新增优惠券
+                </Button>
+            </View>
+            <ListComponent
+                getInfo={getMyList}
+                renderItem={walletItem}
+                style={styles.list}
+                separatorStyle={styles.separatorStyle}
+                showEmpty={true}
+            />
+        </>
+    );
+}
+
+const styles = StyleSheet.create({
+    top: {
+        alignItems: "center",
+        paddingVertical: 10,
+        marginBottom: 10,
+    },
+    list: {
+        flex: 1,
+        backgroundColor: "rgb(242, 242, 242)",
+        paddingHorizontal: 15,
+    },
+    separatorStyle: {
+        marginHorizontal: 13,
+    },
+});

+ 8 - 1
screens/EditGoods.js

@@ -46,6 +46,7 @@ export default function EditGoods({ navigation, route }) {
         uplaodImg,
         removeTips,
     } = useModel("wordsModel");
+
     useFocusEffect(
         React.useCallback(() => {
             changeBackground(theme["color-primary-500"]);
@@ -54,7 +55,7 @@ export default function EditGoods({ navigation, route }) {
     );
 
     function getAllGoods() {
-        httpGet("/goods/my").then((res) => {
+        httpGet("/goods/my").then(res => {
             changeGoods(res);
         });
     }
@@ -72,6 +73,12 @@ export default function EditGoods({ navigation, route }) {
                     id: item.id,
                 });
             }}
+            changeInfo={info => {
+                var _goods = [...goods];
+                _goods.splice(index, 1, info);
+                console.log(_goods);
+                changeGoods(_goods);
+            }}
         />
     );
 

+ 4 - 5
screens/Guide1Screen.js

@@ -60,7 +60,6 @@ export default function Guide1Screen({ navigation }) {
     const { showDialog } = useModel("dialogModel");
     const route = useRoute();
     const routeName = route.name;
-    console.log(routeName);
     const [id, changeId] = React.useState("");
 
     const [name, changeName] = React.useState("");
@@ -275,10 +274,10 @@ export default function Guide1Screen({ navigation }) {
                                         { body: "json" },
                                         true
                                     ).then(res => {
-                                        success(id ? "修改" : "添加" + "成功");
-                                        if (id) {
-                                            getInfo(res);
-                                        } else if (routeName != "AddGoods") {
+                                        success(
+                                            (id ? "修改" : "添加") + "成功"
+                                        );
+                                        if (routeName != "AddGoods") {
                                             changeGuideStep(2);
                                         } else {
                                             navigation.goBack();

+ 1 - 1
screens/HomeScreenPage1.js

@@ -243,7 +243,7 @@ export default function HomePage1(props) {
 const StarIcon = props => <Icon {...props} name='plus' />;
 
 const goodsItem = ({ item, index }) => (
-    <GoodsCardLarge appearance='classification' info={item} />
+    <GoodsCardLarge key={index} appearance='classification' info={item} />
 );
 
 const styles = StyleSheet.create({

+ 1 - 0
screens/MoneyListScreen.js

@@ -133,6 +133,7 @@ export default function MoneyListScreen({ navigation, route }) {
                 ListHeaderComponent={selectElement}
                 style={styles.list}
                 separatorStyle={styles.separatorStyle}
+                showEmpty={true}
             />
         </>
     );

+ 1 - 2
screens/Set/AutomaticScreen.js

@@ -27,7 +27,6 @@ import NavHeaderBar from "../../components/NavHeaderBar";
 import { useModel } from "flooks";
 import Textarea from "react-native-textarea";
 export default function AutomaticScreen({ navigation, route }) {
-    const theme = useTheme();
     const { httpPost, httpGet } = useModel("httpModel", true);
     const { userId } = useModel("userModel");
     const { loading, success } = useModel("loadingModel");
@@ -85,7 +84,7 @@ export default function AutomaticScreen({ navigation, route }) {
     return (
         <>
             <NavHeaderBar title={automaticText1} />
-            <ScrollPage enabledFresh={true} refreshEvent={refreshEvent}>
+            <ScrollPage enabledFresh={true} refreshEvent={refreshEvent} statusType='primary'>
                 <Layout style={styles.lay}>
                     <Text style={styles.text}>{automaticText2}</Text>
                     <Textarea

+ 229 - 0
screens/Set/ClassificationEditScreen.js

@@ -0,0 +1,229 @@
+import * as WebBrowser from "expo-web-browser";
+import * as React from "react";
+import {
+    Image,
+    Platform,
+    StyleSheet,
+    TouchableOpacity,
+    View,
+    ImageBackground,
+} from "react-native";
+import { useModel } from "flooks";
+import {
+    Layout,
+    Tab,
+    TabView,
+    Text,
+    useTheme,
+    Button,
+    Card,
+} from "@ui-kitten/components";
+import FormInput from "../../components/FormInput";
+import { useFocusEffect, useRoute } from "@react-navigation/native";
+import ScrollPage from "../../components/ScrollPage";
+
+export default function ClassificationEdit({ navigation }) {
+    const route = useRoute();
+    const theme = useTheme();
+    const { changeBackground } = useModel("barModel");
+    const { httpGet, httpPost } = useModel("httpModel", true);
+    const { registerSecend, changeGuideStep, mid } = useModel(
+        "userModel",
+        true
+    );
+    const { success } = useModel("loadingModel", true);
+
+    const {
+        guide2_title1,
+        guide2_title2,
+        guide2_form_1,
+        guide2_pla_1,
+        guide2_pla_2,
+        guide1_pla_2,
+        guide2_form_2,
+        guide2_form_3,
+        guide1_form_4,
+        guide1_pla_4,
+        guide1_form_5,
+        guide1_pla_5,
+        next,
+        pass,
+        passTips,
+    } = useModel("wordsModel");
+    const { showDialog } = useModel("dialogModel", true);
+    const { removeCLass } = useModel("goodsModel", true);
+    const [pageName, changePageName] = React.useState("");
+    const [id, changeId] = React.useState("");
+    const [name, changeName] = React.useState("");
+    const [sort, changeSort] = React.useState("");
+    const [goodsIds, changeGoodsIds] = React.useState("");
+    const { selectInfos, changeSelect } = useModel("goodsModel");
+
+    React.useEffect(() => {
+        if (selectInfos.length > 0) {
+            let _ids = selectInfos.map(item => {
+                return item.id;
+            });
+            changeGoodsIds(_ids.join(","));
+        }
+    }, [selectInfos]);
+
+    const canNext = React.useMemo(() => {
+        if (name && sort) {
+            return true;
+        } else {
+            return false;
+        }
+    }, [name, sort, goodsIds]);
+
+    const addClass = () => {
+        return httpPost(
+            "/classification/save",
+            {
+                id,
+                name,
+                sort,
+                goodsIds,
+                merchantId: mid,
+            },
+            { body: "json" },
+            true
+        );
+    };
+
+    const refreshEvent = () => {
+        let { classifyId, classifyTitle } = route.params || {};
+        changeId(classifyId || 0);
+        changePageName(classifyTitle);
+        return httpGet("/classification/get/" + classifyId, {}, true).then(
+            res => {
+                changeName(res.name || "");
+                changeSort(res.sort || 1);
+                changeGoodsIds(res.goodsIds || "");
+            }
+        );
+    };
+
+    function delEvent() {
+        removeCLass({ id, goodsIds }, () => {
+            navigation.goBack();
+        });
+    }
+
+    return (
+        <>
+            <ScrollPage
+                statusType='primary'
+                navHeaderBarTitle={pageName}
+                enabledFresh={true}
+                refreshEvent={refreshEvent}
+            >
+                <Layout style={styles.container}>
+                    <Card appearance='formFilled'>
+                        {/* 类别名称 */}
+                        <FormInput
+                            label={guide2_form_1}
+                            placeholder={guide2_pla_1}
+                            value={name}
+                            onChange={changeName}
+                            style={{ paddingVertical: 3 }}
+                        />
+                        {/* 显示排序 */}
+                        <FormInput
+                            label={guide2_form_2}
+                            value={sort}
+                            type='actionSheet'
+                            list={[1, 2, 3, 4, 5, 6, 7, 8, 9]}
+                            onChange={changeSort}
+                            textAlign='right'
+                        />
+
+                        {/* 商品 */}
+                        <FormInput
+                            label={guide2_form_3}
+                            value={goodsIds}
+                            type='url'
+                            changePath={() => {
+                                navigation.navigate("AddClassification", {
+                                    type: "classification",
+                                    classificationId: id,
+                                });
+                            }}
+                            textAlign='right'
+                        />
+                        <Layout style={styles.layoutLeft} level='1'>
+                            <Button
+                                status='primary'
+                                disabled={!canNext}
+                                onPress={() => {
+                                    addClass().then(_ => {
+                                        success("添加成功");
+                                        navigation.goBack();
+                                    });
+                                }}
+                            >
+                                确定
+                            </Button>
+                            <Button
+                                style={{ marginLeft: 20 }}
+                                appearance='outline'
+                                status='info'
+                                onPress={delEvent}
+                            >
+                                删除
+                            </Button>
+                        </Layout>
+                    </Card>
+                </Layout>
+            </ScrollPage>
+        </>
+    );
+}
+
+const styles = StyleSheet.create({
+    container: {
+        flex: 1,
+        paddingBottom: 33,
+    },
+    tabContent: {
+        backgroundColor: "#fff",
+        marginTop: 20,
+    },
+    img: {
+        width: 100,
+        height: 100,
+        alignSelf: "center",
+    },
+    img2: {
+        width: 97,
+        height: 21,
+        alignSelf: "center",
+        marginTop: 2,
+    },
+    text: {
+        marginTop: 16,
+    },
+    layoutLeft: {
+        flexDirection: "row",
+        paddingVertical: 10,
+        justifyContent: "center",
+        alignItems: "center",
+    },
+    form: {
+        paddingHorizontal: 26,
+        paddingVertical: 20,
+    },
+    textareaContainer: {
+        backgroundColor: "#F0F0F0",
+        height: 100,
+        borderRadius: 4,
+    },
+    textarea: {
+        textAlignVertical: "top", // hack android
+        fontSize: 13,
+        color: "#333",
+        paddingHorizontal: 14,
+        paddingVertical: 10,
+        height: 100,
+    },
+});

+ 149 - 0
screens/Set/ClassificationManageScreen.js

@@ -0,0 +1,149 @@
+import * as WebBrowser from "expo-web-browser";
+import * as React from "react";
+import ListComponent from "../../components/ListComponent";
+import TipNavHeader from "../../components/TipNavHeader";
+import { useModel } from "flooks";
+import {
+    Layout,
+    Input,
+    Button,
+    Text,
+    ListItem,
+    Icon,
+} from "@ui-kitten/components";
+import { StyleSheet, View } from "react-native";
+import ListUtil from "../../Utils/ListUtil";
+import { ClassificationUtil } from "../../Utils/SystemRuleUtil";
+const ForwardIcon = props => (
+    <Icon
+        {...props}
+        name='arrow-ios-forward'
+        fill='#B4B4B4'
+        style={{ width: 15, height: 15, fontWeight: 500 }}
+    />
+);
+//分类设置
+export default function ClassificationManageScreen({ navigation, route }) {
+    const {
+        ClassificationManage,
+        ClassificationManageText1,
+        ClassificationManageText2,
+        ClassificationManageText3,
+        ClassificationManageText4,
+        ClassificationManageText5,
+    } = useModel("wordsModel");
+
+    const {
+        getUserInfo,
+        startingAmount,
+        preparationTime,
+        updateMerchant,
+    } = useModel("userModel");
+    const { success } = useModel("loadingModel");
+
+    const { httpGet } = useModel("httpModel");
+
+    function getList() {
+        return httpGet("/classification/my").then(res => {
+            return Promise.resolve({
+                content: res,
+                last: true,
+            });
+        });
+    }
+
+    const renderItem = ({ item, index }) => (
+        <ListItem
+            title={item.name}
+            key={index}
+            onPress={() => {
+                if (new ClassificationUtil(item).checkSystem()) {
+                    navigation.navigate("SystemClassificationEdit", {
+                        classifyId: item.id,
+                        classifyTitle: item.name,
+                    });
+                } else {
+                    navigation.navigate("ClassificationEdit", {
+                        classifyId: item.id,
+                        classifyTitle: item.name,
+                    });
+                }
+            }}
+            accessoryRight={props => (
+                <View style={styles.right}>
+                    {new ClassificationUtil(item).checkSystem() ? (
+                        <Text category='c1' status='info'>
+                            {item.isOpen ? "已启动" : "未启动"}
+                        </Text>
+                    ) : (
+                        <Text category='c1' status='info'>
+                            {new ListUtil(item.goodsIds).getLength()}件商品
+                        </Text>
+                    )}
+                    <ForwardIcon {...props} />
+                </View>
+            )}
+        />
+    );
+
+    return (
+        <>
+            <TipNavHeader title={ClassificationManage}>
+                <Text>{ClassificationManageText1}</Text>
+                <Text style={styles.text1}>{ClassificationManageText2}</Text>
+                <Text style={styles.text1}>{ClassificationManageText3}</Text>
+                <Text style={styles.text1}>{ClassificationManageText4}</Text>
+            </TipNavHeader>
+            <Layout style={styles.top}>
+                <Text category='h6'>{ClassificationManageText5}</Text>
+            </Layout>
+            <ListComponent
+                getInfo={getList}
+                renderItem={renderItem}
+                separatorStyle={styles.separatorStyle}
+                showEmpty={true}
+                style={styles.list}
+                ListFooterComponent={() => (
+                    <Button
+                        style={styles.addGoods}
+                        appearance='classification'
+                        status='danger'
+                        accessoryLeft={StarIcon}
+                        onPress={() => {
+                            navigation.navigate("AddNewClass");
+                        }}
+                    />
+                )}
+            />
+        </>
+    );
+}
+
+const StarIcon = props => <Icon {...props} name='plus' />;
+const styles = StyleSheet.create({
+    text1: {
+        marginTop: 10,
+        marginLeft: 57,
+        maxWidth: 200,
+    },
+    list: {
+        backgroundColor: "#fff",
+    },
+    separatorStyle: {
+        height: 0,
+    },
+    right: {
+        flexDirection: "row",
+        alignItems: "center",
+    },
+    addGoods: {
+        width: 33,
+        margin: 15,
+    },
+    top: {
+        marginTop: 7,
+        paddingTop: 20,
+        paddingBottom: 10,
+        paddingHorizontal: 13,
+    },
+});

+ 156 - 0
screens/Set/DistributionScreen.js

@@ -0,0 +1,156 @@
+import * as WebBrowser from "expo-web-browser";
+import * as React from "react";
+import ScrollPage from "../../components/ScrollPage";
+import { useModel } from "flooks";
+import { Layout, Input, Button, Text } from "@ui-kitten/components";
+import { StyleSheet } from "react-native";
+
+//配送设置
+export default function DistributionScreen({ navigation, route }) {
+    const {
+        distributionTitle,
+        minutes,
+        distributionText1,
+        distributionText2,
+        distributionText3,
+        distributionText4,
+        distributionText5,
+        distributionText6,
+        yuan,
+        confirm,
+    } = useModel("wordsModel");
+
+    const {
+        getUserInfo,
+        startingAmount,
+        preparationTime,
+        updateMerchant,
+    } = useModel("userModel");
+    const { success } = useModel("loadingModel");
+
+    const [amount, setAmount] = React.useState();
+    const [time, setTime] = React.useState();
+
+    React.useEffect(() => {
+        if (startingAmount) {
+            setAmount(startingAmount);
+        }
+        if (preparationTime) {
+            setTime(startingAmount);
+        }
+    }, [startingAmount, preparationTime]);
+
+    const Lable = props => (
+        <Text category='c1' style={styles.lab}>
+            {props.children}
+        </Text>
+    );
+    const Tip = props => (
+        <Text category='c1' status='info' style={styles.tip}>
+            {props.children}
+        </Text>
+    );
+
+    const canSubmit = React.useMemo(() => {
+        if (amount && time) {
+            return true;
+        } else {
+            return false;
+        }
+    }, [amount, time]);
+
+    return (
+        <ScrollPage statusType='primary' navHeaderBarTitle={distributionTitle}>
+            <Layout style={styles.lay}>
+                <Layout style={styles.item}>
+                    <Lable>{distributionText1}</Lable>
+                    <Input
+                        value={amount}
+                        onChangeText={text => {
+                            setAmount(text);
+                        }}
+                        key={2}
+                        keyboardType='numeric'
+                        maxLength={3}
+                        placeholder={distributionText3}
+                        style={styles.input}
+                    />
+                    <Tip>(0-100{yuan})</Tip>
+                </Layout>
+                <Layout style={styles.item}>
+                    <Lable>{distributionText2}</Lable>
+                    <Input
+                        value={time}
+                        key={1}
+                        onChangeText={text => {
+                            setTime(text);
+                        }}
+                        keyboardType='numeric'
+                        maxLength={2}
+                        placeholder={distributionText4}
+                        style={styles.input}
+                    />
+                    <Tip>(1-30{minutes})</Tip>
+                </Layout>
+
+                <Button
+                    disabled={!canSubmit}
+                    onPress={() => {
+                        updateMerchant({
+                            startingAmount: amount,
+                            preparationTime: time,
+                        }).then(() => {
+                            success("修改成功");
+                            navigation.goBack();
+                        });
+                    }}
+                    style={styles.btn}
+                >
+                    {confirm}
+                </Button>
+                <Text category='c1' status='info' style={styles.bottom}>
+                    {distributionText5}:
+                </Text>
+                <Text category='c1' status='info' style={styles.bottom}>
+                    {distributionText6}:
+                </Text>
+            </Layout>
+        </ScrollPage>
+    );
+}
+const styles = StyleSheet.create({
+    lay: {
+        flex: 1,
+        marginTop: 10,
+        paddingVertical: 20,
+    },
+    item: {
+        flexDirection: "row",
+        alignItems: "center",
+        marginBottom: 7,
+        alignSelf: "stretch",
+    },
+    lab: {
+        width: 119,
+        textAlign: "right",
+        marginRight: 38,
+        flexShrink: 0,
+    },
+    tip: {
+        width: 86,
+        paddingHorizontal: 8,
+        flexShrink: 0,
+    },
+    input: {
+        flexShrink: 1,
+        minWidth: 0,
+    },
+    btn: {
+        marginTop: 50,
+        marginBottom: 20,
+        alignSelf: "center",
+    },
+    bottom: {
+        paddingHorizontal: 70,
+    },
+});

+ 153 - 0
screens/Set/FirstOrderScreen.js

@@ -0,0 +1,153 @@
+import * as WebBrowser from "expo-web-browser";
+import * as React from "react";
+import {
+    Image,
+    Platform,
+    StyleSheet,
+    TouchableOpacity,
+    View,
+    ImageBackground,
+} from "react-native";
+import { useModel } from "flooks";
+import {
+    Layout,
+    Tab,
+    TabView,
+    Text,
+    useTheme,
+    Button,
+    Card,
+    List,
+    Input,
+    Icon,
+} from "@ui-kitten/components";
+import EmptyComponent from "../../components/EmptyComponent";
+import FormInput from "../../components/FormInput";
+import { useFocusEffect } from "@react-navigation/native";
+import ScrollPage from "../../components/ScrollPage";
+import NavHeaderBar from "../../components/NavHeaderBar";
+
+export default function FirstOrderScreen({ navigation, route }) {
+    const theme = useTheme();
+    const { changeBackground } = useModel("barModel", true);
+    const { httpGet, httpPost } = useModel("httpModel", true);
+    const { success, warnning } = useModel("loadingModel", true);
+    const { showDialog } = useModel("dialogModel");
+
+    const {
+        userTitle21,
+        fullReduction2,
+        fullReduction1,
+        delText,
+        editText,
+        confirm,
+        cancel,
+        complete,
+        successText,
+        removeTips,
+    } = useModel("wordsModel");
+    const [money, changeMoney] = React.useState();
+    useFocusEffect(
+        React.useCallback(() => {
+            changeBackground(theme["color-primary-500"]);
+        }, [])
+    );
+
+    const { mid, firstOrder, updateMerchant } = useModel("userModel");
+    React.useEffect(() => {
+        changeMoney(firstOrder || 0);
+    }, [firstOrder]);
+
+    return (
+        <>
+            <NavHeaderBar title="首单" />
+            <ScrollPage style={styles.lay}>
+                <Layout style={[styles.lay]}>
+                    <Layout style={styles.item}>
+                        <Layout style={[styles.text, styles.flexRow]}>
+                            <Text category='c2'>新用户立减</Text>
+                            <Input
+                                size='small'
+                                style={styles.input}
+                                value={money}
+                                keyboardType='numeric'
+                                onChangeText={changeMoney}
+                            />
+                            <Text category='c2'>元</Text>
+                        </Layout>
+
+                        <Button
+                            size='small'
+                            onPress={() => {
+                                updateMerchant({ firstOrder: money }).then(
+                                    () => {
+                                        success("保存成功");
+                                    }
+                                );
+                            }}
+                        >
+                            {confirm}
+                        </Button>
+                        <Button
+                            size='small'
+                            appearance='outline'
+                            style={styles.buttonlast}
+                            onPress={() => {
+                                updateMerchant({ firstOrder: 0 }).then(() => {
+                                    success("取消成功");
+                                });
+                            }}
+                        >
+                            {cancel}
+                        </Button>
+                    </Layout>
+                </Layout>
+            </ScrollPage>
+        </>
+    );
+}
+
+const PulsIcon = props => (
+    <Icon
+        {...props}
+        style={[props.style, { width: 33, height: 33 }]}
+        name='plus-circle'
+    />
+);
+const styles = StyleSheet.create({
+    lay: {
+        backgroundColor: "#fff",
+    },
+    padBot: {
+        paddingBottom: 100,
+    },
+    list: {
+        paddingVertical: 10,
+        paddingHorizontal: 15,
+        backgroundColor: "transparent",
+        flex: 0,
+    },
+    item: {
+        flexDirection: "row",
+        alignItems: "center",
+        paddingVertical: 10,
+        paddingHorizontal: 15,
+    },
+    input: {
+        marginHorizontal: 5,
+        minWidth: 49,
+    },
+    text: {
+        flex: 1,
+    },
+    flexRow: {
+        flexDirection: "row",
+        alignItems: "center",
+    },
+    buttonlast: {
+        marginLeft: 10,
+    },
+    button: {
+        alignSelf: "flex-start",
+    },
+});

+ 205 - 0
screens/Set/SystemClassificationEditScreen.js

@@ -0,0 +1,205 @@
+import * as WebBrowser from "expo-web-browser";
+import * as React from "react";
+import ListComponent from "../../components/ListComponent";
+import TipNavHeader from "../../components/TipNavHeader";
+import { useModel } from "flooks";
+import {
+    Layout,
+    Input,
+    Button,
+    Text,
+    ListItem,
+    Icon,
+    Toggle,
+} from "@ui-kitten/components";
+import { StyleSheet, View } from "react-native";
+import ListUtil from "../../Utils/ListUtil";
+import { ClassificationUtil } from "../../Utils/SystemRuleUtil";
+import { useRoute } from "@react-navigation/native";
+import GoodsCard from "../../components/GoodsCard";
+const ForwardIcon = props => (
+    <Icon
+        {...props}
+        name='arrow-ios-forward'
+        fill='#B4B4B4'
+        style={{ width: 15, height: 15, fontWeight: 500 }}
+    />
+);
+//系统分类编辑
+export default function SystemClassificationEditScreen({ navigation }) {
+    const {
+        ClassificationManage,
+        ClassificationManageText6,
+        getWordsStr,
+    } = useModel("wordsModel");
+
+    const {
+        getUserInfo,
+        startingAmount,
+        preparationTime,
+        updateMerchant,
+    } = useModel("userModel");
+    const route = useRoute();
+    const { success } = useModel("loadingModel");
+    const { httpGet } = useModel("httpModel");
+    const { clossClassTip, saveInfo, removeClassGoods } = useModel(
+        "goodsModel",
+        true
+    );
+
+    const [id, setId] = React.useState();
+    const [title, setTitle] = React.useState();
+    const [tips, setTipList] = React.useState([]);
+    const [classifyInfo, setClass] = React.useState(new ClassificationUtil());
+    const [delId, setDel] = React.useState(0);
+
+    const checkEvent = isChecked => {
+        if (!isChecked) {
+            clossClassTip(() => {
+                saveInfo({
+                    ...classifyInfo.allInfo,
+                    isOpen: isChecked,
+                }).then(res => {
+                    getInfo();
+                });
+            });
+        } else {
+            saveInfo({
+                ...classifyInfo.allInfo,
+                isOpen: isChecked,
+            }).then(res => {
+                getInfo();
+            });
+        }
+    };
+
+    function getList() {
+        let { classifyId, classifyTitle } = route.params || {};
+        setId(classifyId || 0);
+        setDel(0);
+        return getInfo(classifyId)
+            .then(_ => {
+                return httpGet("/classification/allGoods", {
+                    classificationId: classifyId,
+                });
+            })
+            .then(res => {
+                return Promise.resolve({
+                    content: res || [],
+                    last: true,
+                });
+            });
+    }
+
+    function getInfo(classifyId) {
+        return httpGet("/classification/get/" + classifyId, {}, true).then(
+            res => {
+                setTitle(res.name || "");
+                let classify = new ClassificationUtil(res);
+                setClass(classify);
+                setTipList(classify.getMenuTipsList());
+            }
+        );
+    }
+
+    const goodsItem = ({ item, index }) => (
+        <GoodsCard
+            appearance='classification'
+            key={index}
+            info={item}
+            removeEvent={() => remove(id, item.id)}
+        />
+    );
+
+    function remove(classId, goodsId) {
+        removeClassGoods(classId, goodsId, res => {
+            setDel(goodsId);
+        });
+    }
+
+    function TipsTexts() {
+        let _tips =
+            [...tips].map((item, index) => {
+                return <Text key={index}>{getWordsStr(item)}</Text>;
+            }) || [];
+
+        _tips.push(
+            <Toggle
+                key='Toggle'
+                checked={classifyInfo.isOpen}
+                onChange={checkEvent}
+                style={styles.toggle}
+            >
+                {classifyInfo.isOpen ? "开启" : "关闭"}
+            </Toggle>
+        );
+
+        return _tips;
+    }
+
+    return (
+        <>
+            <TipNavHeader title={title}>{TipsTexts()}</TipNavHeader>
+
+            <Layout style={styles.top}>
+                <Text category='h6'>{ClassificationManageText6}</Text>
+            </Layout>
+            <ListComponent
+                getInfo={getList}
+                renderItem={goodsItem}
+                separatorStyle={styles.separatorStyle}
+                showEmpty={true}
+                delId={delId}
+                style={styles.list}
+                extraData={{ id: id }}
+                ListFooterComponent={() => (
+                    <Button
+                        style={styles.addGoods}
+                        appearance='classification'
+                        status='danger'
+                        accessoryLeft={StarIcon}
+                        onPress={() => {
+                            navigation.navigate("AddClassification", {
+                                type: "classification",
+                                classificationId: id,
+                            });
+                        }}
+                    />
+                )}
+            />
+        </>
+    );
+}
+
+const StarIcon = props => <Icon {...props} name='plus' />;
+const styles = StyleSheet.create({
+    text1: {
+        marginTop: 10,
+        marginLeft: 57,
+        maxWidth: 200,
+    },
+    list: {
+        backgroundColor: "#fff",
+    },
+    separatorStyle: {
+        height: 0,
+    },
+    right: {
+        flexDirection: "row",
+        alignItems: "center",
+    },
+    addGoods: {
+        width: 33,
+        margin: 15,
+    },
+    toggle: {
+        alignSelf: "flex-start",
+        marginTop: 10,
+    },
+    top: {
+        backgroundColor: "rgb(238, 238, 238)",
+        paddingHorizontal: 13,
+        paddingVertical: 10,
+        marginTop: 10,
+    },
+});

+ 25 - 0
screens/Set/index.js

@@ -1,11 +1,36 @@
 import * as WebBrowser from "expo-web-browser";
 import * as React from "react";
 import AutomaticScreen from "./AutomaticScreen";
+import DistributionScreen from "./DistributionScreen";
+import ClassificationManageScreen from "./ClassificationManageScreen";
+import SystemClassificationEditScreen from "./SystemClassificationEditScreen";
+import ClassificationEditScreen from "./ClassificationEditScreen";
+import FirstOrderScreen from "./FirstOrderScreen";
 
 export default function Set(Screen) {
     return (
         <>
+            {/* 自动回复 */}
             <Screen name='Automatic' component={AutomaticScreen} />
+            {/* 物流设置 */}
+            <Screen name='Distribution' component={DistributionScreen} />
+            {/* 分类管理 */}
+            <Screen
+                name='ClassificationManage'
+                component={ClassificationManageScreen}
+            />
+            {/* 系统分类编辑 */}
+            <Screen
+                name='SystemClassificationEdit'
+                component={SystemClassificationEditScreen}
+            />
+            {/* 普通分类编辑 */}
+            <Screen
+                name='ClassificationEdit'
+                component={ClassificationEditScreen}
+            />
+            {/* 首单优惠 */}
+            <Screen name='FirstOrder' component={FirstOrderScreen} />
         </>
     );
 }

+ 6 - 0
screens/UserScreen.js

@@ -109,10 +109,16 @@ export default function UserScreen({ navigation }) {
                             <MenuItem
                                 title={userTitle23}
                                 accessoryRight={ForwardIcon}
+                                onPress={() => {
+                                    navigation.navigate("FirstOrder");
+                                }}
                             />
                             <MenuItem
                                 title={userTitle24}
                                 accessoryRight={ForwardIcon}
+                                onPress={() => {
+                                    navigation.navigate("CouponList");
+                                }}
                             />
                         </MenuGroup>