Leon 1 gadu atpakaļ
vecāks
revīzija
39230fcd83

+ 97 - 0
src/_health/pages/archive.tsx

@@ -0,0 +1,97 @@
+import HistoryItem from "@/features/health/HistoryItem";
+import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
+import { records } from "@/services/health";
+import { View,Text } from "@tarojs/components";
+import { useEffect, useRef, useState } from "react";
+import { useSelector } from "react-redux";
+
+export default function Archive() {
+    const [list, setList] = useState<any>([])
+    const [page, setPage] = useState(1)
+    const [total, setTotal] = useState(0)
+    const [loaded, setLoaded] = useState(false)
+    const refDemo = useRef()
+    const health = useSelector((state: any) => state.health);
+
+
+    global.refreshHistory = () => {
+        refresh()
+    }
+
+
+    useEffect(() => {
+        loadData(1)
+
+
+    }, [])
+
+    function refresh() {
+        loadData(1)
+        setPage(1)
+    }
+
+    function more() {
+        var index = page;
+        index++;
+        setPage(index)
+        loadData(index)
+    }
+
+    function loadData(index: number) {
+        // return
+        records({
+            window: health.mode,
+            limit: 10,
+            page: index,
+            archived: true
+        }).then(res => {
+            setLoaded(true)
+            if (index == 1) {
+                setList((res as any).data)
+                setTotal((res as any).total)
+            }
+            else {
+                setList([...list, ...(res as any).data])
+            }
+
+            // if ((res as any).data.length > 0) {
+            //     setTimeout(() => {
+            //         const query = Taro.createSelectorQuery();
+            //         query.select(('#demo1')).boundingClientRect((rect) => {
+            //             console.log(rect)
+            //         }).exec();
+            //     }, 1000)
+            // }
+
+        })
+    }
+
+    if (!loaded)
+        return <View />
+    return <View>
+        {
+            list.map((item, index) => {
+                return <View ref={refDemo} id="demo1" key={index}>
+                    <HistoryItem data={item} index={index} isArchived={true} onClick={() => {
+                        jumpPage('/_health/pages/moment_detail')
+                    }} refresh={refresh}/>
+                    {/* {
+                        props.type == 'EAT' && <HistoryEatItem data={item} index={index} />
+                    }
+                    {
+                        props.type == 'FAST' && <HistoryFastItem data={item} index={index} />
+                    }
+                    {
+                        props.type == 'ACTIVE' && <HistoryActiveItem data={item} index={index} />
+                    }
+                    {
+                        props.type == 'SLEEP' && <HistorySleepItem data={item} index={index} />
+                    } */}
+                </View>
+            })
+        }
+        {
+            (list.length > 0) && (total == list.length) && <Text className="no_more">没有更多了</Text>
+        }
+    </View>
+}

+ 9 - 0
src/_health/pages/move.scss

@@ -0,0 +1,9 @@
+.log_btn{
+    color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 160px;
+    height: 72px;
+    border-radius: 21px;
+}

+ 133 - 0
src/_health/pages/move.tsx

@@ -0,0 +1,133 @@
+import { View, Text } from "@tarojs/components";
+import './move.scss'
+import { useDispatch, useSelector } from "react-redux";
+import { getScenario, getThemeColor } from "@/features/health/hooks/health_hooks";
+import { useEffect, useState } from "react";
+import Taro from "@tarojs/taro";
+import { checkStart, setResult } from "@/store/action_results";
+import RequestType, { thirdPartRequest } from "@/services/thirdPartRequest";
+import { setAuth } from "@/features/trackSomething/hooks/werun";
+import { useTranslation } from "react-i18next";
+import { uploadActiveMoves } from "@/services/health";
+import dayjs from "dayjs";
+
+export default function Move() {
+    const health = useSelector((state: any) => state.health);
+    const [allowRun, setAllowRun] = useState(false)
+    const { t } = useTranslation()
+    const dispatch = useDispatch()
+
+    useEffect(() => {
+        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 })
+                }
+            }
+        })
+    }, [])
+
+
+    function tapLog() {
+        if (allowRun) {
+            checkout()
+        }
+        else {
+            setAuth(successAuth, refuseAuth, t)
+        }
+    }
+
+    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,
+            }
+
+            uploadActiveMoves({
+                wechat_run:{
+                    encryptedData:(res as any).encryptedData,
+                    iv:(res as any).iv,
+                },
+                date:dayjs().format('YYYYMMDD'),
+                timestamp:new Date().getTime(),
+                schedule_id:getScenario(health.windows,health.mode).window_id
+            }).then(res=>{
+                Taro.showToast({
+                    title:'上报成功',
+                    icon:'none'
+                })
+            })
+            // 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)
+        })
+
+
+    }
+
+
+    return <View>
+        <Text>Move Every Hour</Text>
+        <View className="log_btn" style={{ backgroundColor: getThemeColor(health.mode) }} onClick={tapLog}>
+            Log
+        </View>
+    </View>
+}

+ 3 - 1
src/app.config.ts

@@ -53,7 +53,9 @@ const appConfig = defineAppConfig({
         'pages/schedules_reminder',
         'pages/schedules_time',
         'pages/setting_reminder',
-        'pages/moment_detail'
+        'pages/moment_detail',
+        'pages/archive',
+        'pages/move'
       ]
     }
   ],

BIN
src/assets/_health/archive.png


BIN
src/assets/_health/cell_arrow.png


BIN
src/assets/_health/walk.png


+ 47 - 0
src/features/health/History.scss

@@ -87,6 +87,8 @@
     padding-left: 52px;
     padding-right: 40px;
     display: flex;
+    flex-direction: row;
+    justify-content: space-between;
     align-items: center;
 }
 
@@ -105,4 +107,49 @@
     height: 68px;
     padding-left: 26px;
     width: 572px;
+}
+
+.archive{
+    width: 34px;
+    height: 34px;
+}
+
+.archived_bg{
+    background-color: #B2B2B21A;
+    height: 68px;
+    border-radius: 34px;
+    padding-left: 44px;
+    padding-right:30px;
+    display: flex;
+    align-items: center;
+    flex-direction: row;
+
+}
+
+.archived_text{
+    margin-right: 8px;
+    font-size: 26px;
+}
+
+.archived_img{
+    width: 34px;
+    height: 34px;
+    margin-right: 4px;
+}
+
+.history_archived_row{
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-end;
+    margin-top: 30px;
+}
+
+.history_archived{
+    background-color: #B2B2B21a;
+    display: flex;
+    width: 74px;
+    height: 44px;
+    align-items: center;
+    justify-content: center;
+    border-radius: 11px;
 }

+ 36 - 1
src/features/health/HistoryItem.tsx

@@ -8,9 +8,13 @@ import { getThemeColor } from "./hooks/health_hooks";
 import Rings, { RingCommon, BgRing, TargetRing, CurrentDot } from "@/features/trackTimeDuration/components/Rings";
 import { MainColorType } from "@/context/themes/color";
 import { durationArc, startArc } from "./util";
+import { IconMore } from "@/components/basic/Icons";
+import showActionSheet from "@/components/basic/ActionSheet";
+import { makeDone } from "@/services/health";
 
-export default function HistoryItem(props: { data: any, index: number, onClick: Function }) {
+export default function HistoryItem(props: { data: any, index: number, onClick: Function, isArchived?: boolean, refresh?: Function }) {
     const health = useSelector((state: any) => state.health);
+    let showActionSheetWithOptions;
     function preview(obj) {
         var list: any = []
         props.data.events.map((item) => {
@@ -113,6 +117,37 @@ export default function HistoryItem(props: { data: any, index: number, onClick:
                     props.data.window_range.end_timestamp && <Text className="history_item_duration">{formatMilliseconds(props.data.window_range.end_timestamp - props.data.window_range.start_timestamp)}</Text>
                 }
             </View>
+            {
+                props.isArchived && <View className="history_archived_row">
+                    <View className="history_archived" onClick={(e) => {
+                        if (process.env.TARO_ENV == 'weapp') {
+                            e.stopPropagation()
+                        }
+                        showActionSheet({
+                            showActionSheetWithOptions: showActionSheetWithOptions,
+                            title: 'Oprate Title',
+                            itemList: ['标记完成', '补记'],
+                            success: (res) => {
+                                // tapActionSheet(res)
+                                switch (res) {
+                                    case 1:
+                                        break;
+                                    case 0:
+                                        makeDone(props.data.window_id).then(res => {
+                                            global.refreshWindow()
+                                            global.refreshHistory()
+                                            if (props.refresh)
+                                                props.refresh()
+                                        })
+                                        break;
+                                }
+                            }
+                        });
+                    }}>
+                        <IconMore width={17} color="#b2b2b2" />
+                    </View>
+                </View>
+            }
         </View>
         <View className="border_footer_line" />
     </View>

+ 35 - 0
src/features/health/MainConsole.scss

@@ -130,3 +130,38 @@
     flex-shrink: 0;
 }
 
+.console_active_bg{
+    background-color: #f5f5f5;
+    padding-top: 36px;
+
+}
+
+.console_active{
+    background-color: #fff;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    height: 128px;
+    width: 750px;
+    padding-left: 52px;
+    padding-right: 42px;
+    box-sizing: border-box;
+}
+
+.active_icon{
+    width: 48px;
+    height: 48px;
+    margin-right: 12px;
+}
+
+.active_text{
+    color: #000000;
+    font-size: 34px;
+    flex: 1;
+}
+
+.cell_arrow{
+    width: 34px;
+    height: 34px;
+}
+

+ 12 - 0
src/features/health/MainConsole.tsx

@@ -589,6 +589,18 @@ export default function MainConsole(props: { type: WindowType }) {
             </View>
 
         </View>
+        {
+            health.mode == 'ACTIVE' && <View className="console_active_bg" onClick={()=>{
+                jumpPage('/_health/pages/move')
+            }}>
+                <View className="console_active">
+                    <Image className="active_icon" src={require('@assets/_health/walk.png')}/>
+                    <Text className="active_text">Move More</Text>
+                    <Image className="cell_arrow" src={require('@assets/_health/cell_arrow.png')}/>
+                </View>
+
+            </View>
+        }
 
         {
             showTimePicker && modalContent()

+ 1 - 1
src/features/health/MainDayNightCard.tsx

@@ -40,7 +40,7 @@ export default function MainDayNightCard(props: {
             setIsDay(false)
             setIsDayMode(false)
         }
-    }, [health.windows])
+    }, [])
 
     useEffect(() => {
         if (health.selTab == 0) {

+ 34 - 10
src/features/health/MainHistory.tsx

@@ -1,4 +1,4 @@
-import { View, Text } from "@tarojs/components";
+import { View, Text, Image } from "@tarojs/components";
 import { useEffect, useRef, useState } from "react";
 import HistoryEatItem from "./HistoryEatItem";
 import HistoryFastItem from "./HistoryFastItem";
@@ -12,6 +12,7 @@ import HistoryItem from "./HistoryItem";
 import { rpxToPx } from "@/utils/tools";
 import { jumpPage } from "../trackTimeDuration/hooks/Common";
 import Taro from "@tarojs/taro";
+import { getThemeColor } from "./hooks/health_hooks";
 
 let lastMode = ''
 export default function MainHistory(props: { type: string }) {
@@ -65,13 +66,13 @@ export default function MainHistory(props: { type: string }) {
                 setList([...list, ...(res as any).data])
             }
 
-            if ((res as any).data.length>0){
-                setTimeout(()=>{
+            if ((res as any).data.length > 0) {
+                setTimeout(() => {
                     const query = Taro.createSelectorQuery();
                     query.select(('#demo1')).boundingClientRect((rect) => {
                         console.log(rect)
                     }).exec();
-                },1000)
+                }, 1000)
             }
 
         })
@@ -80,7 +81,7 @@ export default function MainHistory(props: { type: string }) {
     if (!loaded)
         return <View />
 
-    return <View style={{ width: rpxToPx(750),marginTop:rpxToPx(35) }}>
+    return <View style={{ width: rpxToPx(750), marginTop: rpxToPx(35) }}>
         {/* <Calendar year={2024} month={8}/> */}
         {/* <View style={{
             // position: 'sticky',
@@ -90,17 +91,40 @@ export default function MainHistory(props: { type: string }) {
             zIndex: 100
         }} /> */}
         {
-            list.length>0 && <View className="recent">
+            list.length > 0 && <View className="recent">
                 <Text className="recent_text">Recent</Text>
-                <View className="border_footer_line"/>
+                {
+                    health.mode == 'EAT' && <View onClick={() => {
+                        jumpPage('/_health/pages/archive')
+                    }}>
+                        <Image className="archive" src={require('@assets/_health/archive.png')} />
+                    </View>
+                }
+
+                <View className="border_footer_line" />
+            </View>
+        }
+        {
+            health.mode == 'EAT' && health.eatArchived && health.eatArchived.archived && <View className="recent" style={{justifyContent:'center'}}>
+                <View className="archived_bg" onClick={() => {
+                        jumpPage('/_health/pages/archive')
+                    }}>
+                    <Text className="archived_text" style={{color:getThemeColor(health.mode)}}>[{health.eatArchived.real_count}/{health.eatArchived.target_count} Meals] Archived Yesterday</Text>
+                    {
+                        health.eatArchived.images.map((item,index)=>{
+                            return <Image src={item} key={index} className="archived_img" mode="aspectFill"/>
+                        })
+                    }
+                </View>
+                <View className="border_footer_line" />
             </View>
         }
         {
             list.map((item, index) => {
                 return <View ref={refDemo} id="demo1" key={index}>
-                    <HistoryItem data={item} index={index} onClick={()=>{
+                    <HistoryItem data={item} index={index} onClick={() => {
                         jumpPage('/_health/pages/moment_detail')
-                    }}/>
+                    }} />
                     {/* {
                         props.type == 'EAT' && <HistoryEatItem data={item} index={index} />
                     }
@@ -117,7 +141,7 @@ export default function MainHistory(props: { type: string }) {
             })
         }
         {
-            (list.length>0)&&(total == list.length) && <Text className="no_more">没有更多了</Text>
+            (list.length > 0) && (total == list.length) && <Text className="no_more">没有更多了</Text>
         }
     </View>
 }

+ 1 - 1
src/features/health/MainSleepActiveCard.tsx

@@ -41,7 +41,7 @@ export default function MainSleepActiveCard(props: {
         else {
             setIsSleepMode(false)
         }
-    }, [health.windows])
+    }, [])
 
 
     useEffect(() => {

+ 17 - 2
src/pages/clock/ClockNew.tsx

@@ -10,9 +10,9 @@ import MainSwiper from "@/features/health/MainSwiper";
 import MainConsole from "@/features/health/MainConsole";
 import MainHistory from "@/features/health/MainHistory";
 import { WindowType } from "@/utils/types";
-import { windows } from "@/services/health";
+import { getArchived, windows } from "@/services/health";
 import { useDispatch, useSelector } from "react-redux";
-import health, { setRefreshs, setTitle, setWindows } from "@/store/health";
+import health, { setEatArchived, setRefreshs, setTitle, setWindows } from "@/store/health";
 import dayjs from "dayjs";
 import Modal from "@/components/layout/Modal.weapp";
 import Streak from "@/features/health/Streak";
@@ -34,6 +34,10 @@ export default function ClockNew() {
         healthRef.current = health;
     }, [health])
 
+    useEffect(()=>{
+        archived()
+    },[health.mode])
+
     useEffect(() => {
         setInterval(() => {
             setCount(index => index + 1)
@@ -62,6 +66,17 @@ export default function ClockNew() {
             dispatch(setWindows((res as any).windows))
             dispatch(setRefreshs((res as any).refresh_timestamps))
         })
+        archived()
+    }
+
+    function archived(){
+        if (health.mode == 'EAT'||health.mode == 'ACTIVE'){
+            getArchived(health.mode).then(res=>{
+                if (health.mode == 'EAT'){
+                    dispatch(setEatArchived((res as any).latest))
+                }
+            })
+        }
     }
 
     function tapScroll(index) {

+ 25 - 1
src/services/health.tsx

@@ -1,4 +1,4 @@
-import { API_HEALTH_CLOCK, API_HEALTH_EVENTS, API_HEALTH_LABELS, API_HEALTH_MOMENT, API_HEALTH_RECORD, API_HEALTH_SCHEDULES, API_HEALTH_STREAKS, API_HEALTH_TARGET, API_HEALTH_WINDOWS } from "./http/api";
+import { API_ACTIVE_MOVES, API_HEALTH_ARCHIVED, API_HEALTH_CLOCK, API_HEALTH_EVENTS, API_HEALTH_LABELS, API_HEALTH_MOMENT, API_HEALTH_RECORD, API_HEALTH_SCHEDULES, API_HEALTH_STREAKS, API_HEALTH_TARGET, API_HEALTH_WINDOWS } from "./http/api";
 import { request } from "./http/request";
 
 export const getLabels = (params) => {
@@ -131,6 +131,19 @@ export const windows = ()=>{
     })
 }
 
+export const getArchived = (mode)=>{
+    return new Promise((resolve, reject) => {
+        request({
+            url: API_HEALTH_ARCHIVED, method: 'GET', data: {window:mode}
+        }).then(res => {
+            resolve(res);
+            // dispatch(loginSuccess(res));
+        }).catch(e => {
+            reject(e)
+        })
+    })
+}
+
 export const createMoment = (params) =>{
     return new Promise((resolve) => {
         request({
@@ -173,4 +186,15 @@ export const makeDone = (id)=>{
             // dispatch(loginSuccess(res));
         })
     })
+}
+
+export const uploadActiveMoves = (params) =>{
+    return new Promise((resolve) => {
+        request({
+            url: API_ACTIVE_MOVES, method: 'POST', data: { ...params }
+        }).then(res => {
+            resolve(res);
+            // dispatch(loginSuccess(res));
+        })
+    })
 }

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

@@ -103,4 +103,7 @@ export const API_HEALTH_RECORD = `${baseUrl}/api/health/records`
 export const API_HEALTH_STREAKS = `${baseUrl}/api/health/streaks`
 export const API_HEALTH_WINDOWS = `${baseUrl}/api/health/windows`
 export const API_HEALTH_CLOCK = `${baseUrl}/api/health/clocks`
-export const API_HEALTH_EVENTS = `${baseUrl}/api/health/events`
+export const API_HEALTH_EVENTS = `${baseUrl}/api/health/events`
+export const API_HEALTH_ARCHIVED = `${baseUrl}/api/health/archived`
+
+export const API_ACTIVE_MOVES = `${baseUrl}/api/health/active/moves`

+ 7 - 2
src/store/health.tsx

@@ -6,6 +6,7 @@ interface HealthState {
     selTab: number;
     refreshs: any; //刷新数据时间点
     title: string;
+    eatArchived:any;
 }
 
 const initialState: HealthState = {
@@ -13,7 +14,8 @@ const initialState: HealthState = {
     mode: 'DAY',
     selTab: 0,
     refreshs: [],
-    title: ''
+    title: '',
+    eatArchived:null,
 }
 
 const healthSlice = createSlice({
@@ -36,6 +38,9 @@ const healthSlice = createSlice({
         setTitle(state, action) {
             state.title = action.payload
         },
+        setEatArchived(state,action){
+            state.eatArchived = action.payload
+        }
 
     }
 })
@@ -43,5 +48,5 @@ const healthSlice = createSlice({
 
 
 
-export const { setWindows, setMode, setTab, setRefreshs,setTitle } = healthSlice.actions;
+export const { setWindows, setMode, setTab, setRefreshs,setTitle,setEatArchived } = healthSlice.actions;
 export default healthSlice.reducer;