Leon 2 yıl önce
ebeveyn
işleme
107b45f2ca

+ 3 - 1
src/app.config.ts

@@ -17,6 +17,7 @@ const appConfig = defineAppConfig({
     'pages/account/ProfileSetting',
     'pages/account/Setting',
     'pages/account/EditPage',
+    'pages/workout/Workout',
     'pages/workout/WorkoutDetail',
     'pages/workout/Working',
     'pages/workout/History'
@@ -84,7 +85,8 @@ process.env.TARO_ENV === 'weapp' && (appConfig.tabBar = {
       text: '饮食',
     },
     {
-      pagePath: 'pages/activity/Activity',
+      // pagePath: 'pages/activity/Activity',
+      pagePath:'pages/workout/Workout',
       text: '运动',
     },
     {

+ 2 - 1
src/components/navigation/TabBar.tsx

@@ -24,7 +24,8 @@ export default function Component(props: { index: number }) {
             case 2:
 
                 Taro.switchTab({
-                    url: '/pages/activity/Activity'
+                    // url: '/pages/activity/Activity'
+                    url:'/pages/workout/Workout'
                 })
                 break;
             case 3:

+ 43 - 11
src/features/trackSomething/components/Activity.tsx

@@ -22,6 +22,8 @@ import MoveList from "./MoveList";
 import { ColorType } from "@/context/themes/color";
 import SetGoal from "@/features/workout/SetGoal";
 import Working from "@/features/workout/Working";
+import { startSuccess } from "@/store/workout";
+import { workoutGroups } from "@/services/workout";
 // import { useNavigation } from "@react-navigation/native";
 
 let useNavigation;
@@ -31,16 +33,17 @@ if (process.env.TARO_ENV == 'rn') {
 
 // 
 
+let timer
 export default function Component(props: any) {
     const { t } = useTranslation()
     const user = useSelector((state: any) => state.user);
     const checkResult = useSelector((state: any) => state.checkResult);
+    const workout = useSelector((state: any) => state.workout);
     const [allowRun, setAllowRun] = useState(false)
     const [stepInfo, setStepInfo] = useState(null)
     const [lastTime, setLastTime] = useState(new Date().getTime())
     const [list, setList] = useState([])
     const dispatch = useDispatch();
-    const [returnLoginData, setReturnLoginData] = useState(false)
     const [showErrorBadge, setShowErrorBadge] = useState(false)
     const [latestRecord, setLatestRecord] = useState(null)
     const [triggered, setTriggered] = useState(true)
@@ -61,7 +64,9 @@ export default function Component(props: any) {
 
     //未登录<->已登录 状态切换时,重新拉取一次列表数据
     useEffect(() => {
-
+        if (user.isLogin) {
+            loadWorkoutCache()
+        }
         dispatch(resetStatus())
         getCards();
         const now = new Date();
@@ -83,8 +88,7 @@ export default function Component(props: any) {
                 setAllowRun(res.data ? res.data : false)
             }
         });
-    }, [
-    ])
+    }, [])
 
     //页面渲染完成后执行一次授权检查
     useReady(() => {
@@ -97,6 +101,27 @@ export default function Component(props: any) {
         }
     })
 
+    function loadWorkoutCache() {
+        Taro.getStorage({
+            key: 'lastWorkout', success: function (res) {
+                var workouts = JSON.parse(res.data)
+                if (workouts &&  workouts.length>0){
+                    var workoutObj = workouts[0]
+                    dispatch(startSuccess({
+                        start:workoutObj.time,
+                        id:1
+                    }));
+
+                    timer = setInterval(()=>{
+                        setCount(count=>count+1)
+                    },1000)
+                }
+            },fail:function(err){
+                console.log(err,'no cache')
+            }
+        })
+    }
+
     global.refreshActivity = () => {
         getCards()
     }
@@ -122,6 +147,11 @@ export default function Component(props: any) {
             }
             setLoaded(true)
         })
+
+        workoutGroups().then(res=>{
+
+            
+        })
     }
 
     global.activityCardsFunc = getCards
@@ -349,7 +379,7 @@ export default function Component(props: any) {
         </TitleView>
     }
 
-    function workout() {
+    function workoutStart() {
         setShowModal(true)
     }
 
@@ -429,13 +459,15 @@ export default function Component(props: any) {
                 btnText={'计时训练'}
                 isDisabled={false}
                 themeColor={ColorType.workout}
-                onClickDetail={() => { Taro.navigateTo({
-                    url:'/pages/workout/History'
-                }) }}
+                onClickDetail={() => {
+                    Taro.navigateTo({
+                        url: '/pages/workout/History'
+                    })
+                }}
                 showBadge={showErrorBadge && checkResult.type == 'idle'}
                 showDetail={false}
                 onClick={() => {
-                    workout()
+                    workoutStart()
                 }}
             />
         </View>
@@ -455,13 +487,13 @@ export default function Component(props: any) {
                 setShowModal(false)
             }} confirm={() => { }} modalType={ModalType.center}>
                 {
-                    !isStart && <SetGoal start={(count) => { setTargetTime(count); setShowModal(false);Taro.navigateTo({url:'/pages/workout/Working?count='+count}) }} />
+                    !isStart && <SetGoal start={(count) => { setTargetTime(count); setShowModal(false); Taro.navigateTo({ url: '/pages/workout/Working?count=' + count }) }} />
                 }
                 {
                     isStart && <Working targetCount={targetTime} type={WorkoutType.multi} end={() => {
                         setIsStart(false)
                         setShowModal(false)
-                    }}/>
+                    }} />
                 }
             </Modal>
         }

+ 38 - 7
src/features/workout/Working.tsx

@@ -7,10 +7,13 @@ import Taro from "@tarojs/taro";
 import { WorkoutType } from "@/utils/types";
 import Modal from "@/components/layout/Modal";
 import PickerViews from "@/components/input/PickerViews";
+import { useDispatch } from "react-redux";
+import { startSuccess } from "@/store/workout";
+
 
 var timer
 var lastStrTime
-export default function Component(props: { targetCount: any, type: WorkoutType,end:Function }) {
+export default function Component(props: { targetCount: any, type: WorkoutType, end: Function }) {
     const [index, setIndex] = useState(1)
     const [count, setCount] = useState(0)
     const [startTime, setStartTime] = useState(new Date().getTime())
@@ -20,6 +23,8 @@ export default function Component(props: { targetCount: any, type: WorkoutType,e
     const [isDoing, setIsDoing] = useState(true)
     const [showModal, setShowModal] = useState(false)
     const [needTerminal, setNeedTerminal] = useState(false)
+    const [isPaused, setIsPaused] = useState(false);
+    const dispatch = useDispatch();
 
     const items = [[1, 2, 3, 4, 5, 6]]
     const [selIndex, setSelIndex] = useState([1])
@@ -27,17 +32,29 @@ export default function Component(props: { targetCount: any, type: WorkoutType,e
     const multiSel = [1, 1]
 
     useEffect(() => {
-        timer = setInterval(() => {
-            setCount((count) => count + 1)
-        }, 1000)
-        setGroups([{
+        var array = [{
             index: index,
             time: startTime,
             type: 'start'
-        }])
-        return () => clearInterval(timer)
+        }]
+        setGroups(array)
+        saveCache(array)
+        dispatch(startSuccess({
+            start: startTime,
+            id: 1
+        }))
     }, [])
 
+    useEffect(() => {
+        if (!isPaused) {
+            timer = setInterval(() => {
+                setCount((count) => count + 1)
+            }, 1000)
+        }
+
+        return () => clearInterval(timer)
+    }, [isPaused])
+
     function resume() {
         timer = setInterval(() => {
             setCount((count) => count + 1)
@@ -92,6 +109,7 @@ export default function Component(props: { targetCount: any, type: WorkoutType,e
         setIsDoing(false)
         setStartTime(time)
         setGroups(array)
+        saveCache(array)
     }
 
     function start() {
@@ -106,6 +124,18 @@ export default function Component(props: { targetCount: any, type: WorkoutType,e
         setIndex(index + 1)
         setIsDoing(true)
         setGroups(array)
+        saveCache(array)
+    }
+
+    function saveCache(array) {
+        Taro.setStorage({
+            key: 'lastWorkout',
+            data: JSON.stringify(array)
+        })
+    }
+
+    function clearCache() {
+        Taro.removeStorage({ key: 'lastWorkout' })
     }
 
     function checkEnd() {
@@ -118,6 +148,7 @@ export default function Component(props: { targetCount: any, type: WorkoutType,e
         }
         setNeedTerminal(true)
         setShowModal(true)
+        clearCache()
     }
 
     function terminal() {

+ 8 - 0
src/features/workout/Workout.scss

@@ -0,0 +1,8 @@
+.activity_container{
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+    justify-content: space-between;
+    margin-left: 46px;
+    margin-right: 46px;
+}

+ 503 - 0
src/features/workout/Workout.tsx

@@ -0,0 +1,503 @@
+import { View, Text, ScrollView } from "@tarojs/components";
+import './Workout.scss'
+import { useDidShow, useReady } from "@tarojs/taro";
+import { useDispatch, useSelector } from "react-redux";
+import { useEffect, useState } from "react";
+import Taro from "@tarojs/taro";
+import { activityCards, uploadSteps } from "@/services/trackSomething";
+import { TimeFormatter } from "@/utils/time_format";
+import MetricItem from "../trackSomething/components/MetricItem";
+import Layout from '@/components/layout/layout'
+import NoData from "@/components/view/NoData";
+import { ResultType, checkFail, checkRetry, checkStart, checkSuccess, resetStatus, setResult } from "@/store/action_results";
+import RequestType, { thirdPartRequest } from "@/services/thirdPartRequest";
+import { ModalType, NaviBarTitleShowType, TemplateType, WorkoutType } from "@/utils/types";
+import { useTranslation } from "react-i18next";
+import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
+import TitleView from "@/features/trackTimeDuration/components/TitleView";
+import Modal from "@/components/layout/Modal";
+import { ColorType } from "@/context/themes/color";
+import SetGoal from "@/features/workout/SetGoal";
+import Working from "@/features/workout/Working";
+import { startSuccess } from "@/store/workout";
+import { workoutGroups } from "@/services/workout";
+import { setAuth } from "../trackSomething/hooks/werun";
+// import { useNavigation } from "@react-navigation/native";
+
+let useNavigation;
+if (process.env.TARO_ENV == 'rn') {
+    useNavigation = require("@react-navigation/native").useNavigation
+}
+
+// 
+
+let timer
+export default function Component(props: any) {
+    const { t } = useTranslation()
+    const user = useSelector((state: any) => state.user);
+    const checkResult = useSelector((state: any) => state.checkResult);
+    const workout = useSelector((state: any) => state.workout);
+    const [allowRun, setAllowRun] = useState(false)
+    const [stepInfo, setStepInfo] = useState(null)
+    const [lastTime, setLastTime] = useState(new Date().getTime())
+    const [list, setList] = useState([])
+    const dispatch = useDispatch();
+    const [showErrorBadge, setShowErrorBadge] = useState(false)
+    const [latestRecord, setLatestRecord] = useState(null)
+    const [triggered, setTriggered] = useState(true)
+    const [showErrorPage, setErrorPage] = useState(false)
+    const [showModal, setShowModal] = useState(false)
+    const [loaded, setLoaded] = useState(false)
+    const [count, setCount] = useState(0)
+    const [isStart, setIsStart] = useState(false)
+    const [targetTime, setTargetTime] = useState(0)
+    let navigation;
+    if (useNavigation) {
+        navigation = useNavigation()
+    }
+
+    // const navigation = useNavigation();
+    // const [title, setTitle] = useState('打卡')
+
+
+    //未登录<->已登录 状态切换时,重新拉取一次列表数据
+    useEffect(() => {
+        if (user.isLogin) {
+            loadWorkoutCache()
+        }
+        dispatch(resetStatus())
+        getCards();
+        const now = new Date();
+        const nextMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 0, 0, 0);
+        const timeUntilMidnight = nextMidnight.getTime() - now.getTime();
+
+        setTimeout(() => {
+            setCount(count + 1)
+        }, timeUntilMidnight);
+    }, [user.isLogin])
+
+    // useEffect(() => {
+    //     Taro.setStorage({key:'auth',data:allowRun})
+    // },[allowRun])
+
+    useEffect(() => {
+        Taro.getStorage({
+            key: 'auth', success: function (res) {
+                setAllowRun(res.data ? res.data : false)
+            }
+        });
+    }, [])
+
+    //页面渲染完成后执行一次授权检查
+    useReady(() => {
+
+    })
+
+    useDidShow(() => {
+        if (list.length > 0) {
+            checkAuth()
+        }
+    })
+
+    function loadWorkoutCache() {
+        Taro.getStorage({
+            key: 'lastWorkout', success: function (res) {
+                var workouts = JSON.parse(res.data)
+                if (workouts && workouts.length > 0) {
+                    var workoutObj = workouts[0]
+                    dispatch(startSuccess({
+                        start: workoutObj.time,
+                        id: 1
+                    }));
+
+                    timer = setInterval(() => {
+                        setCount(count => count + 1)
+                    }, 1000)
+                }
+            }, fail: function (err) {
+                console.log(err, 'no cache')
+            }
+        })
+    }
+
+    global.refreshActivity = () => {
+        getCards()
+    }
+
+    function getCards() {
+        setTriggered(true)
+        activityCards().then(res => {
+            setErrorPage(false)
+            setTriggered(false)
+            checkAuth()
+            setList((res as any).cards)
+            for (var i = 0; i < (res as any).cards.length; i++) {
+                var obj = (res as any).cards[i];
+                if (obj.code == '_walk') {
+                    setLatestRecord(obj.latest_record)
+                }
+            }
+            setLoaded(true)
+        }).catch(e => {
+            setTriggered(false)
+            if (list.length == 0) {
+                setErrorPage(true)
+            }
+            setLoaded(true)
+        })
+
+        workoutGroups().then(res => {
+
+
+        })
+    }
+
+    global.activityCardsFunc = getCards
+
+    function checkAuth() {
+        if (user.isLogin) {
+            Taro.getSetting({
+                success: res => {
+                    //第一步,检测是否有授权 - 没有授权
+                    if (!res.authSetting['scope.werun']) {
+                        setAllowRun(false)
+                        Taro.setStorage({ key: 'auth', data: false })
+                    }
+                    else {
+                        setAllowRun(true)
+                        Taro.setStorage({ key: 'auth', data: true })
+                    }
+                }
+            })
+        }
+        else {
+            setAllowRun(false)
+            Taro.setStorage({ key: 'auth', data: false })
+        }
+    }
+
+    function tapBtn() {
+        if (user.isLogin) {
+            if (allowRun) {
+                checkout()
+            }
+            else {
+                setAuth(successAuth, refuseAuth, t)
+            }
+        }
+        else {
+            jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
+        }
+    }
+
+    function successAuth() {
+        Taro.setStorage({ key: 'auth', data: true })
+        setAllowRun(true)
+    }
+
+    function refuseAuth() {
+        // setTitle('开启');
+        Taro.setStorage({ key: 'auth', data: false })
+        setAllowRun(false)
+    }
+
+    function checkout() {
+        dispatch(checkStart());
+        getWeRunData(false)
+    }
+
+    function getWeRunData(autoCheck = false) {
+        if (autoCheck) {
+            return
+        }
+        else {
+            dispatch(checkStart());
+        }
+
+        // setTitle('打卡');
+        setAllowRun(true)
+        var date = new Date();
+        var time = date.getTime()
+        var strDate = (date.getFullYear() + '') + (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : (date.getMonth() + 1)) + (date.getDate() < 10 ? '0' + date.getDate() : date.getDate());
+
+
+        thirdPartRequest(RequestType.RequestTypeWXRunData).then(res => {
+            var params = {
+                is_manual: autoCheck ? 0 : 1,
+                timestamp: time,
+                encryptedData: (res as any).encryptedData,
+                iv: (res as any).iv,
+                date: strDate,
+                cloudID: (res as any).cloudID,
+            }
+            uploadSteps(params).then(res => {
+                if ((res as any).error_code == 'WX_STEP_PARSE_FAIL') {
+                    retry(params, autoCheck, time)
+                    dispatch(checkRetry())
+                }
+                else {
+
+                    setShowErrorBadge(false)
+                    uploadSuccess(res, autoCheck, time)
+                    setTimeout(() => {
+                        setCount(count + 1)
+                    }, 31000)
+                }
+
+            }).catch(e => {
+                retry(params, autoCheck, time)
+            });
+        }).catch(_ => {
+            dispatch(setResult({ isSuccess: false }) as any)
+        })
+
+
+    }
+
+    function retry(params, autoCheck, time) {
+        Taro.login().then(res => {
+            Taro.getWeRunData({
+                success: res2 => {
+                    params.code = res.code;
+                    params.encryptedData = res2.encryptedData
+                    params.iv = res2.iv
+                    params.cloudID = res2.cloudID
+                    uploadSteps(params).then(res => {
+                        if ((res as any).error_code == 'WX_STEP_PARSE_FAIL') {
+                            if (!autoCheck) {
+                                dispatch(setResult({ isSuccess: false }) as any);
+                                setShowErrorBadge(true)
+                            }
+
+                        }
+                        else {
+
+                            setShowErrorBadge(false)
+                            uploadSuccess(res, autoCheck, time)
+                            setTimeout(() => {
+                                setCount(count + 1)
+                            }, 31000)
+                        }
+
+                    }).catch(e => {
+                        if (!autoCheck) {
+                            dispatch(setResult({ isSuccess: false }) as any);
+                            setShowErrorBadge(true)
+                        }
+
+                    })
+                }
+            })
+        })
+    }
+
+    function uploadSuccess(res, autoCheck, time) {
+        Taro.setStorageSync('lastUploadStepsTime', time)
+        if (!autoCheck)
+            dispatch(setResult({ isSuccess: true }) as any)
+        setStepInfo((res as any)[(res as any).length - 1])
+        setLastTime(time)
+
+        for (var i = 0; i < list.length; i++) {
+            var obj = list[i];
+            if ((obj as any).code == '_walk') {
+                (obj as any).latest_record = res.latest_record
+            }
+        }
+        // getCards();
+    }
+
+
+
+    function goDetail(item) {
+        if (user.isLogin) {
+            if (!allowRun) {
+                return;
+            }
+            jumpPage('/pages/common/RecordsHistory?type=activity&refreshList=getCards&title=' + item.name + '&themeColor=' + item.theme_color)
+        }
+        else {
+            jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
+        }
+
+    }
+
+    // checkResult.type == 'ing' && setStrBtnTitle('打卡中...')
+    var btnTitle = '';
+    var isEnable = true;
+    if (allowRun) {
+        switch (checkResult.type) {
+            case ResultType.idle:
+                {
+                    btnTitle = t('feature.track_something.activity.btn_status.idle')
+                    isEnable = true
+                }
+                break;
+            case ResultType.ing:
+                {
+                    btnTitle = t('feature.track_something.activity.btn_status.ing')
+                    isEnable = false
+                }
+                break;
+            case ResultType.retry:
+                {
+                    btnTitle = t('feature.track_something.activity.btn_status.retry')
+                    isEnable = false
+                }
+                break;
+            case ResultType.success:
+                {
+                    btnTitle = t('feature.track_something.activity.btn_status.success')
+                    isEnable = false
+                }
+                break;
+            case ResultType.fail:
+                {
+                    btnTitle = t('feature.track_something.activity.btn_status.fail')
+                    isEnable = false
+                }
+                break;
+            case ResultType.countdown:
+                {
+                    btnTitle = checkResult.title + 's'
+                    isEnable = false
+                }
+                break;
+            default:
+                break;
+        }
+    }
+    else {
+        btnTitle = t('feature.track_something.activity.open');
+        isEnable = true;
+    }
+
+    function addBtnClick(){
+        
+    }
+
+    function headerView() {
+        return <TitleView title={t('page.activity.title')} showAddBtn={loaded && !showErrorPage ? true : false} onClick={addBtnClick}>
+        </TitleView>
+    }
+
+    function workoutStart() {
+        setShowModal(true)
+    }
+
+    function detail() {
+        return <View className="activity_container">
+            {
+                list.map((item: any, index) => {
+                    var value = '0'
+                    var desc = ''
+                    var unit = ''
+                    var showDetail = false;
+                    if (item.latest_record) {
+                        showDetail = true
+                        value = item.latest_record.items[0].value
+                        if (item.latest_record.timestamp == 0) {
+                            desc = t('feature.track_something.activity.today_un_check')
+                        }
+                        else {
+                            desc = TimeFormatter.datetimeDescription(item.latest_record.timestamp)
+                        }
+
+                    }
+                    else {
+                        desc = t('feature.track_something.activity.today_un_check')
+                    }
+
+
+
+                    if (!user.isLogin) {
+                        value = t('feature.track_something.activity.un_login')
+                        desc = t('feature.track_something.activity.login_then_check')//登录后可开启打卡'
+                    }
+                    else {
+                        if (!allowRun) {
+                            value = t('feature.track_something.activity.un_open')
+                            desc = t('feature.track_something.activity.open_then_check')
+                        }
+                        else {
+                            // unit = '步'
+                            showDetail = true
+                            if (item.latest_record) {
+                                value = item.latest_record.items[0].value
+                                desc = TimeFormatter.datetimeDescription(item.latest_record.timestamp)
+                                unit = '步'
+                            }
+                            else {
+                                value = t('feature.track_something.activity.today_un_check')
+                                desc = t('feature.track_something.activity.check_history')//'查看历史记录'
+                            }
+                        }
+                    }
+
+
+                    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(item) }}
+                        showBadge={showErrorBadge && checkResult.type == 'idle'}
+                        showDetail={showDetail}
+                        onClick={() => {
+                            tapBtn()
+                        }}
+                    />
+                })
+            }
+
+            <MetricItem title='平板支撑'
+                // value={allowRun ? stepInfo ? (stepInfo as any).step : '' : '未开启'}
+                value={10}
+                unit={'分钟'}
+                desc={'昨天'}
+                btnText={'计时训练'}
+                isDisabled={false}
+                themeColor={ColorType.workout}
+                onClickDetail={() => {
+                    Taro.navigateTo({
+                        url: '/pages/workout/History'
+                    })
+                }}
+                showBadge={showErrorBadge && checkResult.type == 'idle'}
+                showDetail={false}
+                onClick={() => {
+                    workoutStart()
+                }}
+            />
+        </View>
+    }
+
+    return <View style={{ position: 'relative' }}>
+        <Layout type={TemplateType.customHeader} header={headerView()} children={showErrorPage ? <NoData refresh={() => { getCards() }} /> : detail()}
+            title={t('page.activity.title')}
+            // type={process.env.TARO_ENV == 'rn' ? TemplateType.flex : TemplateType.grid}
+            refresh={() => { getCards() }}
+            triggered={triggered}
+            titleShowStyle={NaviBarTitleShowType.scrollToShow}
+        />
+        {
+            showModal && <Modal dismiss={() => {
+                setIsStart(false)
+                setShowModal(false)
+            }} confirm={() => { }} modalType={ModalType.center}>
+                {
+                    !isStart && <SetGoal start={(count) => { setTargetTime(count); setShowModal(false); Taro.navigateTo({ url: '/pages/workout/Working?count=' + count }) }} />
+                }
+                {
+                    isStart && <Working targetCount={targetTime} type={WorkoutType.multi} end={() => {
+                        setIsStart(false)
+                        setShowModal(false)
+                    }} />
+                }
+            </Modal>
+        }
+    </View>
+}

+ 9 - 0
src/pages/workout/Workout.config.ts

@@ -0,0 +1,9 @@
+export default definePageConfig({
+    usingComponents:{
+      // 'ec-canvas': '../../lib/ec-canvas/ec-canvas',
+      // 'demo':'../../components/demo'
+    },
+    "disableScroll": true,
+    "navigationBarTitleText":""
+  })
+  

+ 5 - 0
src/pages/workout/Workout.scss

@@ -0,0 +1,5 @@
+.activity{
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+}

+ 37 - 0
src/pages/workout/Workout.tsx

@@ -0,0 +1,37 @@
+import { View, Text } from "@tarojs/components";
+import { useDidShow, useReady, useShareAppMessage } from "@tarojs/taro";
+import Tabbar from "@/components/navigation/TabBar";
+import { useTranslation } from "react-i18next";
+import Workout from "@/features/workout/Workout";
+
+export default function Page() {
+
+    const { t } = useTranslation()
+    // useReady(()=>{
+    //     activityCards().then(res=>{
+
+    //     })
+    // })
+    if (process.env.TARO_ENV == 'weapp') {
+        useShareAppMessage((e) => {
+          return {
+            title: t('share.title'),
+            path: 'pages/clock/Clock'
+          }
+        })
+      }
+
+    useDidShow(() => {
+        // global.updateTab(2)
+    })
+
+    function refresh() {
+        console.log('refresh')
+    }
+    return (
+        <View>
+            <Workout />
+            <Tabbar index={2} />
+        </View>
+    )
+}

+ 4 - 0
src/services/http/api.js

@@ -48,5 +48,9 @@ export const API_FOOD = `${baseUrl}/api/food/journals`
 export const API_FOOD_TAGS = `${baseUrl}/api/system/tags`
 export const API_FOOD_SCALE = `${baseUrl}/api/system/scales`
 
+//workout
+export const API_WORKOUT_GROUPS = `${baseUrl}/api/workout/groups`
+export const API_WORKOUT_FOLLOWS = `${baseUrl}/api/workout/follows`
+
 //permissions
 export const API_WX_PUB_FOLLOWED = `${baseUrl}/api/fast/user/wx-pub-followed`

+ 14 - 0
src/services/workout.tsx

@@ -0,0 +1,14 @@
+import { API_WORKOUT_GROUPS } from "./http/api";
+import { request } from "./http/request";
+
+
+export const workoutGroups = ()=>{
+    return new Promise((resolve) => {
+        request({
+            url: API_WORKOUT_GROUPS, method: 'GET', data: {}
+        }).then(res => {
+            resolve(res);
+            // dispatch(loginSuccess(res));
+        })
+    })
+}

+ 3 - 1
src/store/store.tsx

@@ -7,6 +7,7 @@ import resultReducer from './action_results';
 import timeReducer from './time';
 import modalReducer from './modal';
 import consoleReducer from './console';
+import workoutReducer from './workout';
 
 const store = configureStore({
   reducer: {
@@ -19,7 +20,8 @@ const store = configureStore({
     codeResult: resultReducer,
     time: timeReducer,
     modal:modalReducer,
-    console:consoleReducer
+    console:consoleReducer,
+    workout:workoutReducer,
   },
 });
 

+ 36 - 0
src/store/workout.tsx

@@ -0,0 +1,36 @@
+import { createSlice } from "@reduxjs/toolkit";
+
+interface WorkoutState {
+    start: number;
+    id: number;
+    status: string;
+}
+
+const initialState: WorkoutState = {
+    start: 0,
+    id: 0,
+    status: 'idle'
+}
+
+const worktoutSlice = createSlice({
+    name: 'workout',
+    initialState,
+    reducers: {
+        startSuccess(state, action) {
+            state.status = 'ing'
+            state.start = action.payload.start;
+            state.id = action.payload.id;
+        },
+
+        endSuccess(state) {
+            state.status = 'idle'
+        }
+
+    }
+})
+
+
+
+
+export const { startSuccess, endSuccess } = worktoutSlice.actions;
+export default worktoutSlice.reducer;