Leon 2 anni fa
parent
commit
ae9a80ab80

+ 37 - 0
src/components/NoData.scss

@@ -0,0 +1,37 @@
+.no_data_bg{
+    display: flex;
+    flex-direction: column;
+    width: '100%';
+    height: '100%';
+    align-items: center;
+    justify-content: center;
+}
+
+.no_data_text{
+    font-size: 32px;
+    line-height: 32px;
+    height: 36px;
+    color: #ffffff;
+    opacity: 0.2;
+    margin-top: 20px;
+    margin-bottom: 20px;
+}
+
+.no_data_btn{
+    width: 320px;
+    height: 80px;
+    border-radius: 40px;
+    background-color: #ffffff;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: center;
+}
+
+.no_data_btn_text{
+    font-size: 32px;
+    line-height: 32px;
+    height: 36px;
+    color: #000000;
+    opacity: 0.8;
+}

+ 10 - 0
src/components/NoData.tsx

@@ -0,0 +1,10 @@
+import { View,Text } from "@tarojs/components";
+import './NoData.scss'
+export default function Component(props: { refresh: Function }) {
+    return <View className="no_data_bg">
+        <Text className="no_data_text">加载失败</Text>
+        <View className="no_data_btn" onClick={() => props.refresh()}>
+            <Text className="no_data_btn_text">重试</Text>
+        </View>
+    </View>
+}

+ 69 - 57
src/features/trackSomething/components/Activity.tsx

@@ -8,6 +8,7 @@ import Taro from "@tarojs/taro";
 import { activityCards, uploadSteps } from "@/services/trackSomething";
 import { TimeFormatter } from "@/utils/time_format";
 import MetricItem from "./MetricItem";
+import NoData from "@/components/NoData";
 import { ResultType, checkFail, checkRetry, checkStart, checkSuccess, resetStatus, setResult } from "@/store/action_results";
 import { uploadSessionKey } from "@/services/common";
 import RequestType, { thirdPartRequest } from "@/services/thirdPartRequest";
@@ -23,6 +24,8 @@ export default function Component(props: any) {
     const [returnLoginData, setReturnLoginData] = useState(false)
     const [showErrorBadge, setShowErrorBadge] = useState(false)
     const [latestRecord, setLatestRecord] = useState(null)
+
+    const [showErrorPage, setErrorPage] = useState(false)
     // const [title, setTitle] = useState('打卡')
 
     //未登录<->已登录 状态切换时,重新拉取一次列表数据
@@ -62,6 +65,7 @@ export default function Component(props: any) {
 
     function getCards() {
         activityCards().then(res => {
+            setErrorPage(false)
             checkAuth()
             setList((res as any).cards)
             for (var i = 0; i < (res as any).cards.length; i++) {
@@ -71,7 +75,10 @@ export default function Component(props: any) {
                 }
             }
         }).catch(e => {
-            console.log('请求超时')
+            if (list.length==0){
+                setErrorPage(true)
+            }
+            // console.log('请求超时')
         })
     }
 
@@ -302,73 +309,78 @@ export default function Component(props: any) {
         isEnable = true;
     }
 
-    return <View>
-        {
-            list.map((item: any, index) => {
-                var value = '0'
-                var desc = ''
-                var unit = ''
-                if (item.latest_record) {
-                    value = item.latest_record.items[0].value
-                    if (item.latest_record.timestamp == 0) {
-                        desc = '今天待打卡'
+    function detail() {
+        return <View>
+            {
+                list.map((item: any, index) => {
+                    var value = '0'
+                    var desc = ''
+                    var unit = ''
+                    if (item.latest_record) {
+                        value = item.latest_record.items[0].value
+                        if (item.latest_record.timestamp == 0) {
+                            desc = '今天待打卡'
+                        }
+                        else {
+                            desc = TimeFormatter.formatTimestamp(item.latest_record.timestamp)
+                        }
+
                     }
                     else {
-                        desc = TimeFormatter.formatTimestamp(item.latest_record.timestamp)
+                        desc = '今天待打卡'
                     }
 
-                }
-                else {
-                    desc = '今天待打卡'
-                }
-
 
 
-                if (!user.isLogin) {
-                    value = '未登录'
-                    desc = '登录后可开启打卡'
-                }
-                else {
-                    if (!allowRun) {
-                        value = '未开启'
-                        desc = '开启后可打卡步数'
+                    if (!user.isLogin) {
+                        value = '未登录'
+                        desc = '登录后可开启打卡'
                     }
                     else {
-                        // unit = '步'
-                        if (item.latest_record) {
-                            value = item.latest_record.items[0].value
-                            desc = TimeFormatter.formatTimestamp(item.latest_record.timestamp)
-                            unit = '步'
+                        if (!allowRun) {
+                            value = '未开启'
+                            desc = '开启后可打卡步数'
                         }
                         else {
-                            value = '今日待打卡'
-                            desc = '查看历史记录'
+                            // unit = '步'
+                            if (item.latest_record) {
+                                value = item.latest_record.items[0].value
+                                desc = TimeFormatter.formatTimestamp(item.latest_record.timestamp)
+                                unit = '步'
+                            }
+                            else {
+                                value = '今日待打卡'
+                                desc = '查看历史记录'
+                            }
                         }
                     }
-                }
 
-                // if (user.isLogin && !allowRun){
-                //     value = '0'
-                //     desc = '开启步数仅自己可见'
-                //     unit = ''
-                // }
-
-                return <MetricItem title={item.name}
-                    // value={allowRun ? stepInfo ? (stepInfo as any).step : '' : '未开启'}
-                    value={value}
-                    unit={unit}
-                    desc={desc}
-                    btnText={btnTitle}
-                    isDisabled={!isEnable}
-                    themeColor={item.theme_color}
-                    onClickDetail={goDetail}
-                    showBadge={showErrorBadge && checkResult.type == 'idle'}
-                    onClick={() => {
-                        tapBtn()
-                        // checkout()
-                    }}
-                />
-            })
-        }
-    </View>
+                    // if (user.isLogin && !allowRun){
+                    //     value = '0'
+                    //     desc = '开启步数仅自己可见'
+                    //     unit = ''
+                    // }
+
+                    return <MetricItem title={item.name}
+                        // value={allowRun ? stepInfo ? (stepInfo as any).step : '' : '未开启'}
+                        value={value}
+                        unit={unit}
+                        desc={desc}
+                        btnText={btnTitle}
+                        isDisabled={!isEnable}
+                        themeColor={item.theme_color}
+                        onClickDetail={goDetail}
+                        showBadge={showErrorBadge && checkResult.type == 'idle'}
+                        onClick={() => {
+                            tapBtn()
+                            // checkout()
+                        }}
+                    />
+                })
+            }
+        </View>
+    }
+
+    return showErrorPage ? <NoData refresh={() => { getCards() }} /> : detail()
+
 }

+ 77 - 66
src/features/trackSomething/components/Metric.tsx

@@ -13,6 +13,7 @@ import Modal from "@/components/Modal";
 import PickerViews from "@/components/PickerViews";
 import LimitPickers from "@/components/LimitPickers";
 import SlidngScale from "@/components/SlidngScale";
+import NoData from "@/components/NoData";
 
 export default function Component(props: any) {
     const user = useSelector((state: any) => state.user);
@@ -29,6 +30,8 @@ export default function Component(props: any) {
     const [strTime, setStrTime] = useState('')
     const [time, setTime] = useState(0)
 
+    const [showErrorPage, setErrorPage] = useState(false)
+
     //未登录<->已登录 状态切换时,执行一次授权检查
     useEffect(() => {
         getCards();
@@ -49,7 +52,13 @@ export default function Component(props: any) {
     function getCards() {
         console.log('get Cards')
         metricCards().then(res => {
+            setErrorPage(false)
             setList((res as any).cards)
+        }).catch(e => {
+            if (list.length == 0) {
+                setErrorPage(true)
+            }
+            // console.log('请求超时')
         })
     }
 
@@ -239,73 +248,75 @@ export default function Component(props: any) {
 
     const limit = new Date().getTime() - 180 * 3600 * 1000 * 24;
 
-    return <View className="metric_container">
-        {
-            list.map((item: any, index: number) => {
-                var unit = ''
-                var value = '无记录'
-                var desc = '记录解锁趋势'
-                if (item.latest_record) {
-                    unit = item.schemas[0].default_unit
-                    value = getValues(item.latest_record.items)
-                    desc = TimeFormatter.formatTimestamp(item.latest_record.timestamp)
-                }
-                return <MetricItem title={item.name}
-                    value={value}
-                    unit={unit}
-                    desc={desc}
-                    btnText='记录'
-                    isDisabled={false}
-                    themeColor={item.theme_color}
-                    onClickDetail={() => { goDetail(item) }}
-                    onClick={() => { record(item) }}
-                />
-            })
-        }
-        <View className="space_width" />
-        {
-            isModalOpen && <Modal dismiss={closeModal}>
-                <View style={{
-                    backgroundColor: 'white',
-                    display: 'flex', flexDirection: 'column',
-                    width: '100%', paddingBottom: 50, color: '#000'
-                }}>
-                    <Text style={{ textAlign: 'center' }}>{(metricItem as any).name}</Text>
-                    <Text style={{ textAlign: 'center', paddingTop: 10, paddingBottom: 10, color: 'black' }} onClick={showTimePicker}>{strTime}</Text>
-                    <View style={{ position: 'relative' }}>
-                        {
-                            (metricItem as any).schemas.map((item, index) => {
-                                return <View key={index}>
-                                    {
-                                        (metricItem as any).schemas.length > 1 && <Text style={{ textAlign: 'center', width: '100%', display: 'flex', justifyContent: 'center' }}>{item.name}</Text>
-                                    }
-                                    <SlidngScale step={item.step} min={item.min} max={item.max} default_value={item.default_value}
-                                        unit={item.default_unit}
-                                        changed={(e) => { item.tempValue = e }} />
-                                </View>
-                            })
-                        }
-                    </View>
-                    <View style={{ marginBottom: 20, marginTop: 20, display: 'flex', flexDirection: 'row', width: '100%' }}>
-                        <Text style={{ flex: 1, textAlign: 'center', height: 50 }} onClick={cancelModal}>取消</Text>
-                        <Text style={{ flex: 1, textAlign: 'center', height: 50 }} onClick={confirmModal}>确认</Text>
-                    </View>
-
-                </View>
-            </Modal>
-        }
-        {
-
-            isTimePickerOpen && <Modal dismiss={() => setIsTimePickerOpen(false)}>
-                <LimitPickers isRealTime={true} time={time} limit={limit} limitDay={180} onCancel={() => { setIsTimePickerOpen(false) }} onChange={(e) => {
-                    chooseTime(e)
-                    //  pickerConfirm(e)
-                    //  hidePicker()
-                }} />
-            </Modal>
-        }
-    </View>
+    function detail() {
+        return <View className="metric_container">
+            {
+                list.map((item: any, index: number) => {
+                    var unit = ''
+                    var value = '无记录'
+                    var desc = '记录解锁趋势'
+                    if (item.latest_record) {
+                        unit = item.schemas[0].default_unit
+                        value = getValues(item.latest_record.items)
+                        desc = TimeFormatter.formatTimestamp(item.latest_record.timestamp)
+                    }
+                    return <MetricItem title={item.name}
+                        value={value}
+                        unit={unit}
+                        desc={desc}
+                        btnText='记录'
+                        isDisabled={false}
+                        themeColor={item.theme_color}
+                        onClickDetail={() => { goDetail(item) }}
+                        onClick={() => { record(item) }}
+                    />
+                })
+            }
+            <View className="space_width" />
+            {
+                isModalOpen && <Modal dismiss={closeModal}>
+                    <View style={{
+                        backgroundColor: 'white',
+                        display: 'flex', flexDirection: 'column',
+                        width: '100%', paddingBottom: 50, color: '#000'
+                    }}>
+                        <Text style={{ textAlign: 'center' }}>{(metricItem as any).name}</Text>
+                        <Text style={{ textAlign: 'center', paddingTop: 10, paddingBottom: 10, color: 'black' }} onClick={showTimePicker}>{strTime}</Text>
+                        <View style={{ position: 'relative' }}>
+                            {
+                                (metricItem as any).schemas.map((item, index) => {
+                                    return <View key={index}>
+                                        {
+                                            (metricItem as any).schemas.length > 1 && <Text style={{ textAlign: 'center', width: '100%', display: 'flex', justifyContent: 'center' }}>{item.name}</Text>
+                                        }
+                                        <SlidngScale step={item.step} min={item.min} max={item.max} default_value={item.default_value}
+                                            unit={item.default_unit}
+                                            changed={(e) => { item.tempValue = e }} />
+                                    </View>
+                                })
+                            }
+                        </View>
+                        <View style={{ marginBottom: 20, marginTop: 20, display: 'flex', flexDirection: 'row', width: '100%' }}>
+                            <Text style={{ flex: 1, textAlign: 'center', height: 50 }} onClick={cancelModal}>取消</Text>
+                            <Text style={{ flex: 1, textAlign: 'center', height: 50 }} onClick={confirmModal}>确认</Text>
+                        </View>
 
+                    </View>
+                </Modal>
+            }
+            {
+
+                isTimePickerOpen && <Modal dismiss={() => setIsTimePickerOpen(false)}>
+                    <LimitPickers isRealTime={true} time={time} limit={limit} limitDay={180} onCancel={() => { setIsTimePickerOpen(false) }} onChange={(e) => {
+                        chooseTime(e)
+                        //  pickerConfirm(e)
+                        //  hidePicker()
+                    }} />
+                </Modal>
+            }
+        </View>
+    }
 
+    return showErrorPage ? <NoData refresh={() => { getCards() }} /> : detail()
 
 }

+ 7 - 4
src/services/http/request.ts

@@ -1,4 +1,5 @@
 import { logoutSuccess } from "@/store/user";
+import ToastUtil from "@/utils/toast_utils";
 import Taro from "@tarojs/taro";
 import { useDispatch } from "react-redux";
 
@@ -72,10 +73,12 @@ export async function request<T>(param: RequestParam): Promise<T> {
                 performRequest(resolve, reject);
                 return;
             }
-            Taro.showToast({
-                icon:'none',
-                title: method=='GET'?'网络连接失败,请检查网络':'操作失败,请检查网络',
-            })
+
+            ToastUtil.getInstance().showToast(method=='GET'?'网络连接失败,请检查网络':'操作失败,请检查网络');
+            // Taro.showToast({
+            //     icon:'none',
+            //     title: method=='GET'?'网络连接失败,请检查网络':'操作失败,请检查网络',
+            // })
             reject('timeout');
         }, kTimeout);
 

+ 4 - 1
src/services/trackSomething.tsx

@@ -1,3 +1,4 @@
+
 import { API_ACTIVITY_CARDS, API_ACTIVITY_RECORDS, API_METRIC_CARDS, API_METRIC_RECORDS, API_UPLOAD_STEPS } from './http/api';
 import { request } from './http/request';
 
@@ -77,12 +78,14 @@ export const uploadMetric = (params) => {
 }
 
 export const metricCards = () => {
-    return new Promise((resolve) => {
+    return new Promise((resolve, reject) => {
         request({
             url: API_METRIC_CARDS, method: 'GET', data: {}
         }).then(res => {
             resolve(res);
             // dispatch(loginSuccess(res));
+        }).catch(e => {
+            reject(e)
         })
     })
 }

+ 30 - 0
src/utils/toast_utils.ts

@@ -0,0 +1,30 @@
+import Taro from "@tarojs/taro";
+
+class ToastUtil {
+    private static instance: ToastUtil | null = null;
+    private constructor() { }
+    static getInstance(): ToastUtil {
+        if (!ToastUtil.instance) {
+            ToastUtil.instance = new ToastUtil();
+        }
+        return ToastUtil.instance;
+    }
+
+    private lastTime:number = 0;
+
+    showToast(message: string) {
+        if (new Date().getTime() - this.lastTime < 30*1000) {
+            return;
+        }
+        
+        Taro.showToast({
+            icon: "none",
+            title: message,
+        });
+
+        this.lastTime = new Date().getTime();
+    }
+
+}
+
+export default ToastUtil;