Leon 2 年 前
コミット
e2cf0e5bb1

+ 7 - 6
src/components/input/Stepper.scss

@@ -3,11 +3,12 @@
     flex-direction: row;
     align-items: center;
     background-color: #000;
-    height: 104px;
-    margin-top: 24px;
-    margin-bottom: 60px;
-    border-radius: 52px;
-    padding: 16px;
+    height: 128px;
+    margin-bottom: 40px;
+    border-radius: 36px;
+    padding-left: 20px;
+    padding-right: 20px;
+    // padding-top: 24px;
     box-sizing: border-box;
 }
 
@@ -20,7 +21,7 @@
     background-color: #1c1c1c;
     width: 72px;
     height: 72px;
-    border-radius: 36px;
+    border-radius: 24px;
     display: flex;
     align-items: center;
     justify-content: center;

+ 0 - 1
src/components/input/TimePickers.tsx

@@ -3,7 +3,6 @@ import { Picker, Text, PickerView, PickerViewColumn, View } from "@tarojs/compon
 import { useEffect, useState } from "react";
 
 export default function Component(props: { time: string, content: string, change: Function, isPickerView?: boolean }) {
-    debugger
     var [hour, minute] = props.time.split(':').map(x => parseInt(x))
     const m = Math.round(minute / 5) * 5;
     const v = [hour, m / 5];

+ 4 - 1
src/components/layout/Header.tsx

@@ -1,11 +1,14 @@
 import { View, Text } from "@tarojs/components";
 import './Header.scss'
 import { useTranslation } from "react-i18next";
+import { getThemeColor } from "@/features/trackTimeDuration/hooks/Common";
+import { useSelector } from "react-redux";
 
 export default function Component(props: { title: string, action?: Function }) {
+    const time = useSelector((state: any) => state.time);
     const {t} = useTranslation()
     return <View className="header">
         <Text className="header_title">{props.title}</Text>
-        <Text className="header_action" onClick={() => { props.action!() }}>{t('feature.track_time_duration.record_fast_sleep.header.btn_show_all')}</Text>
+        <Text className="header_action" style={{color:getThemeColor(time)}} onClick={() => { props.action!() }}>{t('feature.track_time_duration.record_fast_sleep.header.btn_show_all')}</Text>
     </View>
 }

+ 4 - 3
src/context/locales/zh.js

@@ -107,6 +107,7 @@ export default {
                 fast_end: '结束断食',
                 sleep_start: '开始睡眠',
                 sleep_end: '结束睡眠',
+                total_duration: '总时长',
                 countup: '已进行',             //indicator
                 countdown_not_due: '距结束',
                 timeout: '已超时',
@@ -175,9 +176,9 @@ export default {
 
             }
         },
-        track_something:{
-            btn_record:'记录',
-            picker_datetime:'记录时间'
+        track_something: {
+            btn_record: '记录',
+            picker_datetime: '记录时间'
         }
     }
 }

+ 0 - 1
src/features/trackSomething/components/Metric.tsx

@@ -219,7 +219,6 @@ export default function Component(props: any) {
                     (item as any).latest_record = (res as any).latest_record
                 }
             })
-            debugger
             setList(list)
             // getCards();
         })

+ 0 - 1
src/features/trackSomething/components/MetricHistory.tsx

@@ -73,7 +73,6 @@ export default function Component(props: { records: any[] }) {
                     <Text className="operate_day">{formateDate(item.date + '')}</Text>
                     {
                         item.records.map(record => {
-                            debugger
                             return <RecordItem delete={() => deleteRecord(record)}>
                                 <View className="operate_item1">
                                     <View className="status_bg">

+ 37 - 4
src/features/trackTimeDuration/components/ChooseScenario.scss

@@ -1,22 +1,55 @@
 @import '@/utils/common.scss';
-.item_row{
+
+.item_row {
     display: flex;
     flex-direction: row;
     align-items: center;
 
 }
 
-.item_txt_bg{
+.item_txt_bg {
     position: relative;
     margin-left: 60px;
 }
 
-.item_txt{
+.scenario_count {
+    position: absolute;
+    top: -34px;
+    right: -200px;
+    width: 200px;
+    display: flex;
+    flex-direction: row;
+}
+
+.badge_view1 {
+
+    display: flex;
+    height: 44px;
+    border-top-left-radius: 22px;
+    border-top-right-radius: 22px;
+    border-bottom-right-radius: 22px;
+    border-bottom-left-radius: 4px;
+    padding-left: 12px;
+    padding-right: 12px;
+    box-sizing: border-box;
+}
+
+.linear_badge_bg{
+    background: linear-gradient(90deg, $fastColor 0%, $sleepColor 100%);
+}
+
+.badge1 {
+    font-size: 20px;
+    line-height: 44px;
+    color: #000;
+}
+
+.item_txt {
     font-size: 48px;
     font-weight: 500;
 }
 
-.fast_sleep_text{
+.fast_sleep_text {
     background: linear-gradient(90deg, $fastColor 0%, $sleepColor 100%);
     -webkit-background-clip: text;
     background-clip: text;

+ 24 - 0
src/features/trackTimeDuration/components/ChooseScenario.tsx

@@ -196,6 +196,14 @@ export default function Component() {
                 <Rings2 common={common} bgRing={bgRing} targetRing={targetRing} canvasId='0' />
                 <View className="item_txt_bg">
                     <Text className="item_txt" style={{ color: ColorType.fast }}>{t('feature.track_time_duration.choose_scenario.list.item1.name')}</Text>
+                    {
+                        scenarios[0].count > 0 && <View className="scenario_count">
+                            <View className="badge_view1" style={{ backgroundColor: ColorType.fast }}>
+                                <Text className="badge1">x{scenarios[0].count}</Text>
+                            </View>
+
+                        </View>
+                    }
                 </View>
             </View>
         );
@@ -204,6 +212,14 @@ export default function Component() {
                 <Rings2 common={common} bgRing={bgRing} targetRing={targetRing2} canvasId='1' />
                 <View className="item_txt_bg">
                     <Text className="item_txt" style={{ color: ColorType.sleep }}>{t('feature.track_time_duration.choose_scenario.list.item2.name')}</Text>
+                    {
+                        scenarios[1].count > 0 && <View className="scenario_count">
+                        <View className="badge_view1" style={{ backgroundColor: ColorType.sleep }}>
+                            <Text className="badge1">x{scenarios[1].count}</Text>
+                        </View>
+
+                    </View>
+                    }
                 </View>
             </View>
         )
@@ -217,6 +233,14 @@ export default function Component() {
                 </View>
                 <View className="item_txt_bg">
                     <Text className="item_txt fast_sleep_text" >{t('feature.track_time_duration.choose_scenario.list.item3.name')}</Text>
+                    {
+                        scenarios[2].count > 0 && <View className="scenario_count">
+                        <View className="badge_view1 linear_badge_bg">
+                            <Text className="badge1">x{scenarios[2].count}</Text>
+                        </View>
+
+                    </View>
+                    }
                 </View>
             </View>
         )

+ 1 - 1
src/features/trackTimeDuration/components/Clock.tsx

@@ -97,7 +97,7 @@ export default function Component() {
                 </View>
                 <View style={{ display: 'flex', position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, alignItems: 'center', justifyContent: 'center' }}>
                     {
-                        (checkData as any).current_record.status == 'WAIT_FOR_START' && <Text className="clock_text" style={{ color: ColorType.fast }}>00:00:00</Text>
+                        (checkData as any).current_record.status == 'WAIT_FOR_START' && <Text className="clock_text" style={{ color: ColorType.fast }}>{TimeFormatter.getCurrentHourAndMinute()}</Text>
                     }
                     {
                         (checkData as any).current_record.status == 'ONGOING' && <Text className="clock_text" style={{ color: (checkData as any).current_record.scenario == 'FAST' ? ColorType.fast : ColorType.sleep }}>

+ 38 - 1
src/features/trackTimeDuration/components/Console.scss

@@ -33,6 +33,43 @@
 }
 
 .btn_bg{
-    margin-bottom: 32px;
+    margin-bottom: 12px;
     display: flex;
+}
+
+.console_time_bg{
+    width: 578px;
+    background-color: #000;
+    height: 128px;
+    border-radius: 36px;
+    display: flex;
+    flex-direction: row;
+    box-sizing: border-box;
+    padding-left: 46px;
+    padding-right: 46px;
+    padding-top: 30px;
+    padding-bottom: 30px;
+    margin-bottom: 40px;
+}
+
+.console_time_item{
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.console_time_value{
+    font-weight: 500;
+    font-size: 36px;
+    line-height: 36px;
+
+}
+
+.console_time_desc{
+    margin-top: 10px;
+    color: #fff;
+    opacity: 0.4;
+    font-size: 20px;
+    line-height: 20px;
 }

+ 46 - 38
src/features/trackTimeDuration/components/Console.tsx

@@ -31,7 +31,7 @@ export default function Component(props: { isNextStep?: boolean }) {
     const [sleepPickerValue, setSleepPickerValue] = useState([0, 0])
     const limitPickerRef = useRef(null)
     const durationPickerRef = useRef(null)
-    const {t} = useTranslation()
+    const { t } = useTranslation()
     const dispatch = useDispatch();
 
     useEffect(() => {
@@ -171,7 +171,7 @@ export default function Component(props: { isNextStep?: boolean }) {
             }
         }
 
-        var title = getTimePickerTitle(time,t)
+        var title = getTimePickerTitle(time, t)
         var color = getColor(time)
         if (props.isNextStep) {
             title = t('feature.track_time_duration.console.fast_end')
@@ -206,13 +206,14 @@ export default function Component(props: { isNextStep?: boolean }) {
         if (isFast) {
             if (time.status == 'WAIT_FOR_START') {
                 startFast(t, fastDuration).then(res => {
-                    dispatch(updateScenario((res as any).current_record));
+
                     if ((res as any).current_record.scenario == 'FAST_SLEEP' &&
                         (res as any).current_record.status == 'ONGOING1') {
                         global.consoleType = 'going'
+                        global.showSingleFastEnd()
                         dispatch(changeConsoleStatus({ status: ConsoleType.going }));
                     }
-
+                    dispatch(updateScenario((res as any).current_record));
                     global.postBtnUpdateStatus('idle');
                 });
             }
@@ -247,7 +248,7 @@ export default function Component(props: { isNextStep?: boolean }) {
                     <Text className="target_text" style={{ color: '#FA5151' }}>超出目标结束</Text>
                 </View>
             }
-            return <View className="target_view" style={{ backgroundColor: ColorType.fast+'1A', opacity: opacity }}>
+            return <View className="target_view" style={{ backgroundColor: ColorType.fast + '1A', opacity: opacity }}>
                 <Text className="target_text" style={{ color: ColorType.fast }}>距离目标结束</Text>
             </View>
         }
@@ -259,7 +260,7 @@ export default function Component(props: { isNextStep?: boolean }) {
                     <Text className="target_text" style={{ color: '#FA5151' }}>超出目标结束</Text>
                 </View>
             }
-            return <View className="target_view" style={{ backgroundColor: isFast ? ColorType.fast+'1A' : ColorType.sleep+'1A', opacity: opacity }}>
+            return <View className="target_view" style={{ backgroundColor: isFast ? ColorType.fast + '1A' : ColorType.sleep + '1A', opacity: opacity }}>
                 <Text className="target_text" style={{ color: isFast ? ColorType.fast : ColorType.sleep }}>距离目标结束</Text>
             </View>
         }
@@ -354,7 +355,7 @@ export default function Component(props: { isNextStep?: boolean }) {
 
     function durationPickerContent() {
         var color = getColor(time)
-        var title = getDurationTitle(time,t)
+        var title = getDurationTitle(time, t)
         return <View style={{ color: '#fff', backgroundColor: 'transparent' }}>
             <PickerViews ref={durationPickerRef}
                 onChange={durationChange}
@@ -459,23 +460,24 @@ export default function Component(props: { isNextStep?: boolean }) {
                     (time.status == 'WAIT_FOR_START') && <Stepper child={
                         <Text className="stepper_text" style={{ color: ColorType.sleep, opacity: textAlpha(time) }} onClick={showDurationPicker}>{durationFormate()}</Text>
                     } minus={minus} plus={plus}
-                    themeColor={ColorType.sleep} disableMinus={disableMinus()} disablePlus={disablePlus()} />
+                        themeColor={ColorType.sleep} disableMinus={disableMinus()} disablePlus={disablePlus()} />
                 }
                 {
-                    time.status == 'ONGOING1' && <View>
-                        <Text className="counter_text" style={{ color: textNextStepAlpha(time) == 1 ? '#FA5151' : ColorType.fast, opacity: textNextStepAlpha(time) }}>{TimeFormatter.countdown(time.fast.target_end_time)}</Text>
+                    (time.status == 'ONGOING1' || time.status == 'ONGOING2') &&
+                    <View className="console_time_bg">
+                        <View className="console_time_item">
+                            <Text className="console_time_value" style={{ color: ColorType.fast, opacity: textNextStepAlpha(time) }}>{
+                                TimeFormatter.calculateTimeDifference(time.fast.target_start_time,
+                                    time.fast.target_end_time, true)}</Text>
+                            <Text className="console_time_desc">{t('feature.track_time_duration.console.total_duration')}</Text>
+                        </View>
+                        <View className="console_time_item">
+                            <Text className="console_time_value" style={{ color: textNextStepAlpha(time) == 1 ? '#FA5151' : ColorType.fast, opacity: textNextStepAlpha(time) }}>{TimeFormatter.countdown(time.fast.target_end_time)}</Text>
+                            <Text className="console_time_desc">{textNextStepAlpha(time) == 1 ? t('feature.track_time_duration.console.timeout') : t('feature.track_time_duration.console.countdown_not_due')}</Text>
+                        </View>
                     </View>
                 }
 
-                {
-                    time.status == 'ONGOING2' && <View>
-                        <Text className="counter_text" style={{ color: textNextStepAlpha(time) == 1 ? '#FA5151' : ColorType.fast, opacity: textNextStepAlpha(time) }}>{TimeFormatter.countdown(time.fast.target_end_time)}</Text>
-                    </View>
-                }
-                {
-                    targetView()
-                }
-
                 <View>
                     {
                         nextStepBtns()
@@ -484,36 +486,42 @@ export default function Component(props: { isNextStep?: boolean }) {
             </View>
         </Box>
     }
+
+    function ongoing() {
+        if (time.status == 'ONGOING' || time.status == 'ONGOING2' || time.status == 'ONGOING3') {
+            var isFastData = time.scenario == 'FAST' || time.status == 'ONGOING3'
+            var duration = TimeFormatter.calculateTimeDifference(isFastData ? time.fast.target_start_time : time.sleep.target_start_time,
+                isFast ? time.fast.target_end_time : time.sleep.target_end_time, true);
+            return <View className="console_time_bg">
+                <View className="console_time_item">
+                    <Text className="console_time_value" style={{ color: isFastData ? ColorType.fast : ColorType.sleep, opacity: textAlpha(time) }}>{duration}</Text>
+                    <Text className="console_time_desc">{t('feature.track_time_duration.console.total_duration')}</Text>
+                </View>
+                <View className="console_time_item">
+                    <Text className="console_time_value" style={{ color: textColor, opacity: textAlpha(time) }}>{isFastData ?
+                        TimeFormatter.countdown(time.fast.target_end_time) :
+                        TimeFormatter.countdown(time.sleep.target_end_time)}</Text>
+                    <Text className="console_time_desc">{textAlpha(time) == 1 ? t('feature.track_time_duration.console.timeout') : t('feature.track_time_duration.console.countdown_not_due')}</Text>
+                </View>
+            </View>
+        }
+        return <View />
+    }
     return (
         <Box >
             <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', flexShrink: 0 }}>
                 {
-                    time.status == 'ONGOING' && <View>
-                        <Text className="counter_text" style={{ color: textColor, opacity: textAlpha(time) }}>{time.scenario == 'FAST' ?
-                            TimeFormatter.countdown(time.fast.target_end_time) :
-                            TimeFormatter.countdown(time.sleep.target_end_time)}</Text>
-                    </View>
+                    ongoing()
                 }
                 {
                     (time.status == 'ONGOING1' || time.status == 'WAIT_FOR_START') && <Stepper child={
                         <Text className="stepper_text" style={{ color: textColor, opacity: textAlpha(time) }} onClick={showDurationPicker}>{durationFormate()}</Text>
                     } minus={minus} plus={plus}
-                    themeColor={isFast?ColorType.fast:ColorType.sleep} disableMinus={disableMinus()} disablePlus={disablePlus()} />
-                }
-                {
-                    time.status == 'ONGOING2' && <View>
-                        <Text className="counter_text" style={{ color: textColor, opacity: textAlpha(time) }}>{TimeFormatter.countdown(time.sleep.target_end_time)}</Text>
-                    </View>
+                        themeColor={isFast ? ColorType.fast : ColorType.sleep} disableMinus={disableMinus()} disablePlus={disablePlus()} />
                 }
-
-                {
-                    time.status == 'ONGOING3' && <View>
-                        <Text className="counter_text" style={{ color: textColor, opacity: textAlpha(time) }}>{TimeFormatter.countdown(time.fast.target_end_time)}</Text>
-                    </View>
-                }
-                {
+                {/* {
                     targetView()
-                }
+                } */}
 
                 <View>
                     {

+ 533 - 0
src/features/trackTimeDuration/components/Console_backup.tsx

@@ -0,0 +1,533 @@
+
+import { View, Text, PickerView } from "@tarojs/components";
+import { useEffect, useRef, useState } from "react";
+import { TimeFormatter } from "@/utils/time_format";
+import { useDispatch, useSelector } from "react-redux";
+import Taro from "@tarojs/taro";
+import LimitPickers from '@/components/input/LimitPickers';
+import { endFast, endSleep, startFast, startSleep } from "../actions/TrackTimeActions";
+import { durationDatas, durationIndex, getColor, getDurationTitle, getTimePickerTitle, getTitle, textAlpha, textNextStepAlpha } from "../hooks/Console";
+import PickerViews from "@/components/input/PickerViews";
+import Modal from "@/components/layout/Modal";
+import Stepper from "@/components/input/Stepper";
+import { EndFastBtn, EndSleepBtn, StartFastBtn, StartSleepBtn } from "@/features/common/SpecBtns";
+import Box from "@/components/layout/Box";
+import './Console.scss'
+import { ConsoleType, changeConsoleStatus } from "@/store/console";
+import { updateScenario } from "@/store/time";
+import { useTranslation } from "react-i18next";
+import { ColorType } from "@/context/themes/color";
+
+export default function Component(props: { isNextStep?: boolean }) {
+    const scenario = useSelector((state: any) => state.scenario);
+    const time = useSelector((state: any) => state.time);
+    const user = useSelector((state: any) => state.user);
+    const common = useSelector((state: any) => state.common);
+    const [isFast, setIsFast] = useState(true);
+    const [fastDuration, setFastDuration] = useState<number>(0);
+    const [sleepDuration, setSleepDuration] = useState<number>(0);
+
+    const [fastPickerValue, setFastPickerValue] = useState([0, 0])
+    const [sleepPickerValue, setSleepPickerValue] = useState([0, 0])
+    const limitPickerRef = useRef(null)
+    const durationPickerRef = useRef(null)
+    const {t} = useTranslation()
+    const dispatch = useDispatch();
+
+    useEffect(() => {
+        getStateDetail();
+    }, [time.fast, time.sleep, time.status, time.scenario]);
+
+    function getStateDetail() {
+        if (time.fast) {
+            var fastCount = time.fast.target_end_time - time.fast.target_start_time
+            setFastDuration(fastCount)
+            setFastPickerValue(durationIndex(time.fast.target_start_time, time.fast.target_end_time, common))
+        }
+
+        if (time.sleep) {
+            var sleepCount = time.sleep.target_end_time - time.sleep.target_start_time
+            setSleepDuration(sleepCount)
+            setSleepPickerValue(durationIndex(time.sleep.target_start_time, time.sleep.target_end_time, common))
+        }
+
+        if (time.scenario == 'FAST') {
+            setIsFast(true)
+        }
+        else if (time.scenario == 'SLEEP') {
+            setIsFast(false)
+        }
+        else {
+            if (time.status == 'WAIT_FOR_START' || time.status == 'ONGOING3') {
+                setIsFast(true)
+            }
+            else {
+                setIsFast(false)
+            }
+        }
+    }
+
+
+    function showPicker() {
+        if (global.testInfotimer) {
+            return
+        }
+        global.set_time = new Date().getTime()
+        updateNodeInfo()
+        global.testInfotimer = setInterval(() => {
+            updateNodeInfo()
+
+        }, 1000)
+
+    }
+
+    function updateNodeInfo() {
+        var node = (<Modal testInfo={testLayout()} children={layoutContent()} dismiss={() => {
+            global.showClockModal(false, null);
+            hidePicker()
+        }} confirm={() => {
+            hidePicker()
+            var picker = limitPickerRef.current;
+            pickerConfirm((picker as any).getConfirmData());
+            global.showClockModal(false, null);
+        }} />);
+        global.showClockModal(true, node);
+    }
+
+    function hidePicker() {
+        global.showClockModal(false, null);
+        if (global.testInfotimer) {
+            clearInterval(global.testInfotimer)
+            global.testInfotimer = null
+        }
+        else {
+            console.log('global test info timer')
+        }
+    }
+
+    function testLayout() {
+        if (!user.test_user) {
+            return <View />
+        }
+        var isStart = false;
+        if (time.status == 'WAIT_FOR_START' || time.status == 'ONGOING1') {
+            isStart = true
+        }
+        var isFast = false;
+        switch (time.status) {
+            case 'WAIT_FOR_START':
+            case 'ONGOING':
+                {
+                    isFast = (scenario.name == 'FAST' || scenario.name == 'FAST_SLEEP')
+                }
+                break;
+            case 'ONGOING1':
+            case 'ONGOING2':
+                {
+                    isFast = false;
+                }
+                break
+            case 'ONGOING3':
+                {
+                    isFast = true;
+                }
+                break;
+
+
+        }
+
+        if (props.isNextStep) {
+            isFast = true
+            isStart = false
+        }
+
+        return <View style={{ color: '#fff', paddingTop: 30, paddingLeft: 30, display: 'flex', flexDirection: 'column' }}>
+            <Text>check scenario:{isFast ? 'fast' : 'sleep'}</Text>
+            <Text>check type:{isStart ? 'start' : 'end'}</Text>
+            <Text style={{ marginTop: 30 }}>picker restriction</Text>
+            <Text style={{ marginLeft: 50 }}>min:{TimeFormatter.formatTimestamp(global.limit)}</Text>
+            <Text style={{ marginLeft: 50 }}>pick:{TimeFormatter.formatTimestamp(global.picker_time)}</Text>
+            <Text style={{ marginLeft: 50 }}>max{TimeFormatter.formatTimestamp(global.set_time)}</Text>
+
+            <Text style={{ marginTop: 30 }}>now:{TimeFormatter.formatTimestamp(new Date().getTime())}</Text>
+            <Text>elapsed:{TimeFormatter.calculateTimeDifference(global.picker_time, new Date().getTime())}</Text>
+
+            <Text style={{ marginTop: 30 }}>real start:{isStart ? '-' : TimeFormatter.formatTimestamp(isFast ? time.fast.real_start_time : time.sleep.real_start_time)}</Text>
+            <Text>real duration:{isStart ? '-' : TimeFormatter.calculateTimeDifference(isFast ? time.fast.real_start_time : time.sleep.real_start_time, new Date().getTime())}</Text>
+        </View>
+    }
+
+
+    function layoutContent() {
+        var limit = global.set_time - 7 * 3600 * 1000 * 24;
+        global.limit = limit
+
+        if (time.last_real_check_time) {
+            limit = time.last_real_check_time
+            global.limit = limit
+            //当set_time秒数<=latest_record_time秒数时,最小限制时间戳需+1分钟
+            if (new Date(global.set_time).getSeconds() <= new Date(time.last_real_check_time).getSeconds()) {
+                limit = limit + 60 * 1000
+            }
+        }
+
+        var title = getTimePickerTitle(time,t)
+        var color = getColor(time)
+        if (props.isNextStep) {
+            title = t('feature.track_time_duration.console.fast_end')
+            color = ColorType.fast
+        }
+
+
+        return <LimitPickers ref={limitPickerRef} limit={limit} limitDay={8}
+            themeColor={color}
+            title={title}
+            onCancel={hidePicker} onChange={(e) => {
+                pickerConfirm(e)
+                hidePicker()
+            }} />
+    }
+
+    function pickerConfirm(t: number) {
+        var date = new Date(t)
+        var setDate = new Date(global.set_time);
+        date.setMilliseconds(setDate.getMilliseconds());
+        date.setSeconds(setDate.getSeconds());
+
+        t = date.getTime();
+
+        if (props.isNextStep) {
+            endFast(t)
+            return;
+        }
+
+        global.postBtnUpdateStatus('normal');
+
+        if (isFast) {
+            if (time.status == 'WAIT_FOR_START') {
+                startFast(t, fastDuration).then(res => {
+                    
+                    if ((res as any).current_record.scenario == 'FAST_SLEEP' &&
+                        (res as any).current_record.status == 'ONGOING1') {
+                        global.consoleType = 'going'
+                        global.showSingleFastEnd()
+                        dispatch(changeConsoleStatus({ status: ConsoleType.going }));
+                    }
+                    dispatch(updateScenario((res as any).current_record));
+                    global.postBtnUpdateStatus('idle');
+                });
+            }
+            else {
+                endFast(t).then(res => {
+                    dispatch(updateScenario((res as any).current_record));
+                    global.postBtnUpdateStatus('idle');
+                })
+            }
+        }
+        else {
+            if (time.status == 'WAIT_FOR_START' || time.status == 'ONGOING1') {
+                startSleep(t, sleepDuration).then(res => {
+                    dispatch(updateScenario((res as any).current_record));
+                    global.postBtnUpdateStatus('idle');
+                });
+            }
+            else {
+                endSleep(t).then(res => {
+                    dispatch(updateScenario((res as any).current_record));
+                    global.postBtnUpdateStatus('idle');
+                })
+            }
+        }
+    }
+
+    function targetView() {
+        if (props.isNextStep && (time.status == 'ONGOING1' || time.status == 'ONGOING2')) {
+            var opacity = textNextStepAlpha(time)
+            if (opacity == 1) {
+                return <View className="target_view" style={{ backgroundColor: '#FA51511A' }}>
+                    <Text className="target_text" style={{ color: '#FA5151' }}>超出目标结束</Text>
+                </View>
+            }
+            return <View className="target_view" style={{ backgroundColor: ColorType.fast+'1A', opacity: opacity }}>
+                <Text className="target_text" style={{ color: ColorType.fast }}>距离目标结束</Text>
+            </View>
+        }
+
+        if (time.status == 'ONGOING' || time.status == 'ONGOING2' || time.status == 'ONGOING3') {
+            var opacity = textAlpha(time)
+            if (opacity == 1) {
+                return <View className="target_view" style={{ backgroundColor: '#FA51511A' }}>
+                    <Text className="target_text" style={{ color: '#FA5151' }}>超出目标结束</Text>
+                </View>
+            }
+            return <View className="target_view" style={{ backgroundColor: isFast ? ColorType.fast+'1A' : ColorType.sleep+'1A', opacity: opacity }}>
+                <Text className="target_text" style={{ color: isFast ? ColorType.fast : ColorType.sleep }}>距离目标结束</Text>
+            </View>
+        }
+        return <View />
+    }
+
+    function mixedBtns() {
+        return <View className="btn_bg">
+            {
+                (time.status == 'WAIT_FOR_START' || time.status == 'DONE') &&
+                <StartFastBtn onClick={showPicker} />
+            }
+            {
+                (time.status == 'ONGOING' || time.status == 'ONGOING3') &&
+                <EndFastBtn onClick={showPicker} lowLight={time.fast.target_end_time > new Date().getTime()} />
+            }
+            {
+                time.status == 'ONGOING1' && <StartSleepBtn onClick={showPicker} />
+            }
+            {
+                time.status == 'ONGOING2' && <EndSleepBtn onClick={showPicker} lowLight={time.sleep.target_end_time > new Date().getTime()} />
+
+            }
+        </View>
+    }
+
+    function nextStepBtns() {
+        return <View className="btn_bg">
+            {
+                (time.status == 'WAIT_FOR_START') &&
+                <StartSleepBtn onClick={showPicker} />
+            }
+            {
+                time.status == 'ONGOING1' && <EndFastBtn onClick={showPicker} lowLight={time.fast.target_end_time > new Date().getTime()} />
+            }
+            {
+                time.status == 'ONGOING2' && <EndFastBtn onClick={showPicker} lowLight={time.fast.target_end_time > new Date().getTime()} />
+
+            }
+        </View>
+    }
+
+
+    function fastBtns() {
+        return <View className="btn_bg">
+            {
+                time.status == 'ONGOING' ? <EndFastBtn onClick={showPicker} lowLight={textAlpha(time) != 1} /> : <StartFastBtn onClick={showPicker} />
+            }
+        </View>
+    }
+
+    function sleepBtns() {
+        return <View className="btn_bg">
+            {
+                time.status == 'ONGOING' ? <EndSleepBtn onClick={showPicker} lowLight={textAlpha(time) != 1} /> : <StartSleepBtn onClick={showPicker} />
+            }
+        </View>
+    }
+
+    function durationChange(e) {
+        var count = (e[0] + common.duration.min) * 60 + e[1] * common.duration.step
+        isFast ? setFastDuration(count * 60000) : setSleepDuration(count * 60000);
+        isFast ? setFastPickerValue(e) : setSleepPickerValue(e)
+        global.showClockModal2(false, null)
+    }
+
+    function login() {
+        Taro.navigateTo({
+            url: '/pages/account/ChooseAuth'
+        })
+    }
+
+    function durationFormate() {
+        var t = isFast ? fastDuration / 60000 : sleepDuration / 60000
+        if (props.isNextStep) t = sleepDuration / 60000
+        var hour = Math.floor(t / 60)
+        var minute = Math.floor(t % 60)
+        return `${hour > 0 ? hour + '小时' : ''}${minute > 0 ? minute + '分钟' : ''}`
+    }
+
+    function showDurationPicker() {
+        var node = <Modal children={durationPickerContent()} dismiss={() => global.showClockModal2(false, null)} confirm={() => {
+            var picker = durationPickerRef.current;
+            durationChange((picker as any).getConfirmData());
+            global.showClockModal2(false, null);
+        }} />
+        global.showClockModal2(true, node);
+    }
+
+
+
+
+    function durationPickerContent() {
+        var color = getColor(time)
+        var title = getDurationTitle(time,t)
+        return <View style={{ color: '#fff', backgroundColor: 'transparent' }}>
+            <PickerViews ref={durationPickerRef}
+                onChange={durationChange}
+                items={durationDatas(common)}
+                value={isFast ? fastPickerValue : sleepPickerValue}
+                themeColor={color}
+                title={title}
+                showBtns={true} onCancel={() => { global.showClockModal2(false, null); }} />
+        </View>
+    }
+
+    function minus() {
+        if (isFast) {
+            var count = fastDuration - 5 * 60 * 1000
+            setFastDuration(count)
+            var hour = count / 60000 / 60
+            var minute = count / 60000 % 60
+
+            setFastPickerValue(durationIndex('00:00', `${hour > 10 ? hour : '0' + hour}:${minute > 10 ? minute : '0' + minute}`, common))
+        }
+        else {
+            var count = sleepDuration - 5 * 60 * 1000
+
+            setSleepDuration(count)
+            var hour = count / 60000 / 60
+            var minute = count / 60000 % 60
+
+            setSleepPickerValue(durationIndex('00:00', `${hour > 10 ? hour : '0' + hour}:${minute > 10 ? minute : '0' + minute}`, common))
+        }
+    }
+
+    function plus() {
+        if (isFast) {
+            var count = fastDuration + 5 * 60 * 1000
+            setFastDuration(count)
+            var hour = count / 60000 / 60
+            var minute = count / 60000 % 60
+
+            setFastPickerValue(durationIndex('00:00', `${hour > 10 ? hour : '0' + hour}:${minute > 10 ? minute : '0' + minute}`, common))
+        }
+        else {
+            var count = sleepDuration + 5 * 60 * 1000
+
+            setSleepDuration(count)
+            var hour = count / 60000 / 60
+            var minute = count / 60000 % 60
+
+            setSleepPickerValue(durationIndex('00:00', `${hour > 10 ? hour : '0' + hour}:${minute > 10 ? minute : '0' + minute}`, common))
+        }
+    }
+
+    function disableMinus() {
+        if (isFast) {
+            if (fastDuration <= 60 * 60 * 1000) {
+                return true;
+            }
+        }
+        else {
+            if (sleepDuration <= 60 * 60 * 1000) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    function disablePlus() {
+        if (isFast) {
+            if (fastDuration >= 23 * 60 * 60 * 1000) {
+                return true;
+            }
+        }
+        else {
+            if (sleepDuration >= 23 * 60 * 60 * 1000) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    var textColor = getColor(time)
+    if (time.status != 'ONGOING1' && time.status != 'WAIT_FOR_START') {
+        if (textAlpha(time) == 1) {
+            textColor = '#FA5151';
+        }
+    }
+
+    if (!user.isLogin) {
+        return <View style={{ display: 'flex', flexDirection: 'column', width: '100%', alignItems: 'center' }}>
+            <Text>16:00</Text>
+            <Text style={{ color: ColorType.fast }} onClick={login}>Start Fast</Text>
+        </View>
+    }
+
+    if (props.isNextStep) {
+        return <Box >
+            <View style={{
+                display: 'flex', flexDirection: 'column', alignItems: 'center', flexShrink: 0,
+                opacity: time.status == 'WAIT_FOR_START' ? 0.4 : 1,
+                pointerEvents: time.status == 'WAIT_FOR_START' ? 'none' : 'all'
+            }}>
+                {
+                    (time.status == 'WAIT_FOR_START') && <Stepper child={
+                        <Text className="stepper_text" style={{ color: ColorType.sleep, opacity: textAlpha(time) }} onClick={showDurationPicker}>{durationFormate()}</Text>
+                    } minus={minus} plus={plus}
+                    themeColor={ColorType.sleep} disableMinus={disableMinus()} disablePlus={disablePlus()} />
+                }
+                {
+                    time.status == 'ONGOING1' && <View>
+                        <Text className="counter_text" style={{ color: textNextStepAlpha(time) == 1 ? '#FA5151' : ColorType.fast, opacity: textNextStepAlpha(time) }}>{TimeFormatter.countdown(time.fast.target_end_time)}</Text>
+                    </View>
+                }
+
+                {
+                    time.status == 'ONGOING2' && <View>
+                        <Text className="counter_text" style={{ color: textNextStepAlpha(time) == 1 ? '#FA5151' : ColorType.fast, opacity: textNextStepAlpha(time) }}>{TimeFormatter.countdown(time.fast.target_end_time)}</Text>
+                    </View>
+                }
+                {
+                    targetView()
+                }
+
+                <View>
+                    {
+                        nextStepBtns()
+                    }
+                </View>
+            </View>
+        </Box>
+    }
+    return (
+        <Box >
+            <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', flexShrink: 0 }}>
+                {
+                    time.status == 'ONGOING' && <View>
+                        <Text className="counter_text" style={{ color: textColor, opacity: textAlpha(time) }}>{time.scenario == 'FAST' ?
+                            TimeFormatter.countdown(time.fast.target_end_time) :
+                            TimeFormatter.countdown(time.sleep.target_end_time)}</Text>
+                    </View>
+                }
+                {
+                    (time.status == 'ONGOING1' || time.status == 'WAIT_FOR_START') && <Stepper child={
+                        <Text className="stepper_text" style={{ color: textColor, opacity: textAlpha(time) }} onClick={showDurationPicker}>{durationFormate()}</Text>
+                    } minus={minus} plus={plus}
+                    themeColor={isFast?ColorType.fast:ColorType.sleep} disableMinus={disableMinus()} disablePlus={disablePlus()} />
+                }
+                {
+                    time.status == 'ONGOING2' && <View>
+                        <Text className="counter_text" style={{ color: textColor, opacity: textAlpha(time) }}>{TimeFormatter.countdown(time.sleep.target_end_time)}</Text>
+                    </View>
+                }
+
+                {
+                    time.status == 'ONGOING3' && <View>
+                        <Text className="counter_text" style={{ color: textColor, opacity: textAlpha(time) }}>{TimeFormatter.countdown(time.fast.target_end_time)}</Text>
+                    </View>
+                }
+                {
+                    targetView()
+                }
+
+                <View>
+                    {
+                        time.scenario === 'FAST_SLEEP' && mixedBtns()
+                    }
+                    {
+                        time.scenario === 'FAST' && fastBtns()
+                    }
+                    {
+                        time.scenario === 'SLEEP' && sleepBtns()
+                    }
+                </View>
+            </View>
+        </Box>
+    )
+}

+ 0 - 324
src/features/trackTimeDuration/components/Dial_backup.tsx

@@ -1,324 +0,0 @@
-import Taro from '@tarojs/taro';
-import { Canvas, View } from '@tarojs/components';
-import { useEffect, useRef, useState } from 'react';
-
-export default function Component(props: { current: { start: string, end: string }, updateDuration: (start: string, end: string) => void }) {
-    const canvasRef = useRef<any>(null);
-    const [currentContext, setCurrentContext] = useState(null)
-    const canvasWidth: number = 200;
-    const canvasHeight: number = 200;
-    const circleRadius: number = 100;
-    const ringWidth: number = 30;
-    const dotRadius: number = 10;
-    const dpr = Taro.getSystemInfoSync().pixelRatio; // 获取设备的像素比
-
-    const canvasId = 'canvasDialId';
-
-    var canStartDrag = false;
-    var canEndDrag = false;
-    var canRingDrag = false;
-
-    var startCount = parseInt((props.current.start.split(':') as any)[0]) * 60 + parseInt((props.current.start.split(':') as any)[1]);
-    var endCount = parseInt((props.current.end.split(':') as any)[0]) * 60 + parseInt((props.current.end.split(':') as any)[1]);
-    var startAngle1 = (startCount / 1440) * 2 * Math.PI - Math.PI / 2;
-    var endAngle1 = (endCount / 1440) * 2 * Math.PI - Math.PI / 2;
-    endAngle1 = endAngle1 > startAngle1 ? endAngle1 : endAngle1 + 2 * Math.PI;
-
-
-    const [startAngle,setStartAngle] = useState(startAngle1)
-    const [endAngle,setEndAngle] = useState(endAngle1)
-
-    var lastAngle;
-    var lastDuration = 0;
-
-    useEffect(() => {
-
-        const query = Taro.createSelectorQuery();
-        query.select(`.${canvasId}`).fields({ node: true, size: true });
-        query.exec((res) => {
-            if (res[0] == null) return;
-            const _canvas = res[0].node;
-            _canvas.width = res[0].width * dpr;
-            _canvas.height = res[0].height * dpr;
-            const ctx = _canvas.getContext('2d');
-            setCurrentContext(ctx)
-
-            // 设置画布尺寸
-            ctx.scale(dpr, dpr);
-
-
-            drawCanvas(ctx);
-        });
-    }, []);
-
-    const drawCanvas = (ctx: any) => {
-        ctx.clearRect(0, 0, canvasWidth, canvasHeight);
-
-        // 绘制圆环
-        const centerX = canvasWidth / 2;
-        const centerY = canvasHeight / 2;
-        const radius = Math.min(centerX, centerY) - 10;
-
-
-
-        ctx.clearRect(0, 0, canvasWidth, canvasHeight);
-
-
-        ctx.beginPath();
-        ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
-        ctx.strokeStyle = "rgba(0,0,0,0.5)";
-        ctx.lineWidth = 10;
-        ctx.stroke();
-
-        ctx.beginPath();
-        ctx.arc(centerX, centerY, radius, startAngle, endAngle);
-        ctx.strokeStyle = canRingDrag ? "red" : "rgba(255,0,0,0.5)";
-        ctx.lineWidth = 10;
-        ctx.stroke();
-
-        const pointX = centerX + Math.cos(startAngle) * radius;
-        const pointY = centerY + Math.sin(startAngle) * radius;
-
-        ctx.beginPath();
-        ctx.arc(pointX, pointY, 5, 0, 2 * Math.PI);
-        ctx.fillStyle = '#00ff00';
-        ctx.fill();
-
-
-
-        // 绘制蓝色终点圆点
-        const pointX2 = centerX + Math.cos(endAngle) * radius;
-        const pointY2 = centerY + Math.sin(endAngle) * radius;
-
-        ctx.beginPath();
-        ctx.arc(pointX2, pointY2, 5, 0, 2 * Math.PI);
-        ctx.fillStyle = 'blue';
-        ctx.fill();
-    };
-
-    function twoPointDistance(p1, p2) {
-        let dep = Math.sqrt(Math.pow((p1.x - p2.x), 2) + Math.pow((p1.y - p2.y), 2));
-        return dep;
-    }
-
-    function limitAngle(start, end) {
-        var angle1 = start < 0 ? start + 2 * Math.PI : start;
-        var angle2 = end < 0 ? end + 2 * Math.PI : end;
-        if (angle2 < angle1) {
-            angle2 = angle2 + 2 * Math.PI;
-        }
-
-        var leftAngle = angle2 - angle1;
-        if (leftAngle > Math.PI * 23 / 12) {
-            return 1;
-        }
-        else if (leftAngle < Math.PI / 12) {
-            return 2;
-        }
-        return 0;
-    }
-
-    function durationAngle(end, start) {
-        var angle1 = start < 0 ? start + 2 * Math.PI : start;
-        var angle2 = end < 0 ? end + 2 * Math.PI : end;
-        if (angle2 < angle1) {
-            angle2 = angle2 + 2 * Math.PI;
-        }
-
-        return angle2 - angle1;
-    }
-
-    const handleTouchMove = (e: any) => {
-        const ctx = currentContext;//canvasRef.current.getContext('2d');
-        if (!canStartDrag && !canEndDrag && !canRingDrag) {
-            drawCanvas(ctx);
-            return;
-        }
-
-        const { x, y } = e.touches[0];
-
-        let angle = Math.atan2(y - canvasWidth / 2.0, x - canvasWidth / 2.0)
-
-        if (canStartDrag) {
-            if (Math.abs(durationAngle(endAngle, angle) - lastDuration) > Math.PI) {
-                //禁止跨越
-                return;
-            }
-
-            var result = limitAngle(angle, endAngle);
-            switch (result) {
-                case 0:
-                    startAngle = angle;
-                    break;
-                case 1:
-                    startAngle = endAngle - 23 * Math.PI / 12;
-                    break;
-                case 2:
-                    startAngle = endAngle - Math.PI / 12;
-                    break;
-            }
-
-        }
-
-        if (canEndDrag) {
-            if (Math.abs(durationAngle(angle, startAngle) - lastDuration) > Math.PI) {
-                //禁止跨越
-                return;
-            }
-
-            var result = limitAngle(startAngle, angle);
-            switch (result) {
-                case 0:
-                    endAngle = angle;
-                    break;
-                case 1:
-                    endAngle = startAngle + 23 * Math.PI / 12;
-                    break;
-                case 2:
-                    endAngle = startAngle + Math.PI / 12;
-                    break;
-            }
-
-        }
-
-        if (canRingDrag) {
-            let delta = angle - lastAngle;
-            startAngle += delta;
-            endAngle += delta;
-            lastAngle = angle;
-        }
-
-
-        startAngle = normalizeAngle(startAngle);
-        endAngle = normalizeAngle(endAngle);
-
-        angleToTime();
-
-        drawCanvas(ctx);
-
-        lastDuration = durationAngle(endAngle, startAngle);
-    };
-
-    function angleToTime() {
-        var startCount = (startAngle + Math.PI / 2) / (2 * Math.PI) * 1440;
-        var endCount = (endAngle + Math.PI / 2) / (2 * Math.PI) * 1440;
-        startCount = startCount > 0 ? startCount : startCount + 1440;
-        endCount = endCount > 0 ? endCount : endCount + 1440;
-
-        startCount = roundToNearestFive(startCount);
-        endCount = roundToNearestFive(endCount);
-
-        var startHour = Math.floor(startCount / 60);
-        var startMinute = Math.floor(startCount % 60);
-        var endHour = Math.floor(endCount / 60);
-        var endMinute = Math.floor(endCount % 60);
-        startHour = startHour < 24 ? startHour : startHour - 24;
-        endHour = endHour < 24 ? endHour : endHour - 24;
-        var start = (startHour < 10 ? '0' + startHour : startHour) + ':' + (startMinute < 10 ? '0' + startMinute : startMinute);
-        var end = (endHour < 10 ? '0' + endHour : endHour) + ':' + (endMinute < 10 ? '0' + endMinute : endMinute);
-        props.updateDuration(start, end);
-    }
-
-    function roundToNearestFive(minutes: number): number {
-        const remainder = minutes % 5;
-        if (remainder === 0) {
-            return minutes;
-        } else if (remainder < 3) {
-            return minutes - remainder;
-        } else {
-            return minutes + (5 - remainder);
-        }
-    }
-
-    const handleClick = (e) => {
-
-        const scaleX = 1//dpr//canvasRect.width / canvasRect.width;
-        const scaleY = 1//dpr//canvasRect.height / canvasRect.height;
-        const canvasX = (e.touches[0].x - 0) * scaleX;
-        const canvasY = (e.touches[0].y - 0) * scaleY;
-
-        // 判断点击位置是否在圆点范围内
-        const centerX = canvasWidth / 2;
-        const centerY = canvasWidth / 2;
-        const radius = Math.min(centerX, centerY) - 10;
-
-
-        const pointX = centerX + Math.cos(startAngle) * radius;
-        const pointY = centerY + Math.sin(startAngle) * radius;
-        const distance = Math.sqrt(Math.pow(canvasX - pointX, 2) + Math.pow(canvasY - pointY, 2));
-
-        if (distance <= 12) {
-            canStartDrag = true;
-        } else {
-            canStartDrag = false;
-        }
-
-        const pointX2 = centerX + Math.cos(endAngle) * radius;
-        const pointY2 = centerY + Math.sin(endAngle) * radius;
-        const distance2 = Math.sqrt(Math.pow(canvasX - pointX2, 2) + Math.pow(canvasY - pointY2, 2));
-
-        if (distance2 <= 12) {
-            canEndDrag = true;
-        } else {
-            canEndDrag = false;
-        }
-
-        if (canStartDrag || canEndDrag) {
-            canRingDrag = false;
-            return;
-        }
-
-        const distance3 = twoPointDistance({ x: canvasX, y: canvasY }, { x: centerX, y: centerY });
-        let angle = Math.atan2(canvasY - canvasWidth / 2.0, canvasX - canvasWidth / 2.0)
-
-        if (distance3 > 70 && distance3 < 105 && isCenterAngle(startAngle, angle, endAngle)) {
-            canRingDrag = true;
-        }
-        lastAngle = angle;
-        startAngle = normalizeAngle(startAngle);
-        endAngle = normalizeAngle(endAngle);
-
-        drawCanvas(currentContext);
-    };
-
-    const normalizeAngle = (angle) => {
-        if (angle < 0) {
-            angle = angle + 2 * Math.PI;
-            normalizeAngle(angle);
-        }
-        if (angle > 2 * Math.PI) {
-            angle = angle - 2 * Math.PI;
-            normalizeAngle(angle);
-        }
-        return angle;
-    }
-
-    const isCenterAngle = (start, center, end) => {
-        start = normalizeAngle(start);
-        center = normalizeAngle(center);
-        end = normalizeAngle(end);
-        if (start > end) {
-            end += 2 * Math.PI;
-        }
-        if (end > 2 * Math.PI && center < start) {
-            center += 2 * Math.PI;
-        }
-        return start < center && center < end;
-    }
-
-    const handleTouchEnd = (e) => {
-        canStartDrag = false;
-        canEndDrag = false;
-        canRingDrag = false;
-        handleTouchMove(e)
-    }
-
-    return <View style={{ width: 200, height: 200, }}>
-        <Canvas canvasId={canvasId} id={canvasId} className={canvasId} type="2d"
-            style={{ width: 200, height: 200, zIndex: 0 }}
-            onTouchMove={handleTouchMove}
-            onTouchEnd={handleTouchEnd}
-            onTouchStart={handleClick}
-            ref={canvasRef} />
-    </View>
-}

+ 0 - 1
src/features/trackTimeDuration/components/RecordFastSleep.tsx

@@ -114,7 +114,6 @@ export default function RecordFastSleep(props: { data: any, type: string, delSuc
 
     function getDuration(obj) {
         if (!obj) {
-            debugger
         }
         if (obj.status == 'NOT_STARTED' || obj.status == 'NOT_COMPLETED') {
             return ''

+ 103 - 56
src/features/trackTimeDuration/components/Rings.tsx

@@ -1,7 +1,7 @@
 import { Canvas } from "@tarojs/components";
 import Taro from "@tarojs/taro";
 import { useDidShow, useReady } from "@tarojs/taro";
-import { useEffect, useRef } from "react";
+import { useEffect, useRef, useState } from "react";
 
 export type RingCommon = {
     useCase: string;
@@ -35,8 +35,12 @@ export type BgRing = {
 
 export default function Rings(props: {
     common: RingCommon; currentDot?: CurrentDot;
-    realRing?: RealRing; targetRing?: TargetRing; bgRing: BgRing; canvasId?: string;
+    realRing?: RealRing; targetRing?: TargetRing; 
+    breathAnimation?:boolean;
+    bgRing: BgRing; canvasId?: string;
 }) {
+    const [context,setContext] = useState(null)
+    const [canvas,setCanvas] = useState(null)
     const r = props.common.radius
     const strokeWidth = props.common.lineWidth;
     // const color = props.color || 'orange'
@@ -46,6 +50,18 @@ export default function Rings(props: {
     const radius = r; // 圆形进度条的半径
     const lineWidth = strokeWidth; // 圆形进度条的线宽
 
+    
+
+    useEffect(()=>{
+        // if (props.breathAnimation){
+        //     animation()
+        // }
+        // else {
+        //     global.breathAlpha = 1
+        //     animation()
+        // }
+    },[props.breathAnimation])
+
     useDidShow(() => {
         // drawCircle()
     })
@@ -55,6 +71,32 @@ export default function Rings(props: {
 
     })
 
+    function animation(){
+        const duration = 1000; // 动画执行时间(毫秒)
+        let animationId: number | null = null;
+        let startTime: number | null = null;
+        const animate = (timestamp: number) => {
+            if (!startTime) {
+              startTime = timestamp;
+            }
+      
+            const elapsed = timestamp - startTime;
+            const progress = elapsed / duration; // 动画进度(0 到 1)
+            global.breathAlpha = progress
+
+            if (elapsed < duration) {
+                animationId = requestAnimationFrame(animate);
+              } else {
+                // 动画完成后重新开始
+                startTime = null;
+                animationId = requestAnimationFrame(animate);
+              }
+        }
+        animationId = requestAnimationFrame(animate);
+    }
+
+    
+
     function drawCircle() {
         const query = Taro.createSelectorQuery();
         query.select(`.${canvasId}`).fields({ node: true, size: true });
@@ -64,71 +106,76 @@ export default function Rings(props: {
             _canvas.width = res[0].width * dpr;
             _canvas.height = res[0].height * dpr;
             const ctx = _canvas.getContext('2d');
+
+            setCanvas(_canvas)
+            setContext(ctx)
             // const ctx = Taro.createCanvasContext(canvasId);
+            drawContent(ctx)
+        });
+    }
 
+    function drawContent(ctx){
+        const center = radius + lineWidth / 2+3; // 圆心坐标
+        ctx.clearRect(0, 0, radius * 2, radius * 2); // 清除画布
 
-            const center = radius + lineWidth / 2+3; // 圆心坐标
-            ctx.clearRect(0, 0, radius * 2, radius * 2); // 清除画布
+        // 设置画布尺寸
+        ctx.scale(dpr, dpr);
 
-            // 设置画布尺寸
-            ctx.scale(dpr, dpr);
+        // 绘制背景圆
+        ctx.beginPath();
+        ctx.arc(center, center, radius, 0, 2 * Math.PI);
+        ctx.lineWidth = lineWidth;
+        ctx.strokeStyle = props.bgRing.color;
+        ctx.lineCap = 'round'; // 设置为圆角
+        ctx.stroke();
 
-            // 绘制背景圆
+        // 绘制target进度环
+        if (props.targetRing) {
             ctx.beginPath();
-            ctx.arc(center, center, radius, 0, 2 * Math.PI);
+            ctx.arc(center, center, radius, props.targetRing!.startArc,
+                props.targetRing!.startArc + props.targetRing!.durationArc);
             ctx.lineWidth = lineWidth;
-            ctx.strokeStyle = props.bgRing.color;
+            ctx.strokeStyle = props.targetRing!.color;
             ctx.lineCap = 'round'; // 设置为圆角
             ctx.stroke();
+        }
 
-            // 绘制target进度环
-            if (props.targetRing) {
-                ctx.beginPath();
-                ctx.arc(center, center, radius, props.targetRing!.startArc,
-                    props.targetRing!.startArc + props.targetRing!.durationArc);
-                ctx.lineWidth = lineWidth;
-                ctx.strokeStyle = props.targetRing!.color;
-                ctx.lineCap = 'round'; // 设置为圆角
-                ctx.stroke();
-            }
-
-            //绘制real进度环
-            if (props.realRing) {
-                if (props.realRing.durationArc <0.01) props.realRing.durationArc=0.01;
-                ctx.beginPath();
-                ctx.arc(center, center, radius, props.realRing!.startArc,
-                    props.realRing!.startArc + props.realRing!.durationArc);
-                ctx.lineWidth = lineWidth;
-                ctx.strokeStyle = props.realRing!.color;
-                ctx.lineCap = 'round'; // 设置为圆角
-                ctx.stroke();
-            }
-
-            //绘制current_dot点
-            if (props.currentDot) {
-                var time = new Date();
-                var seconds = time.getHours() * 3600 + time.getMinutes() * 60 + time.getSeconds();
-                var arc = seconds / 86400 * 2 * Math.PI - Math.PI / 2.0;
-                ctx.beginPath();
-                ctx.arc(center, center, radius, arc,
-                    arc + 0.001);
-                ctx.lineWidth = lineWidth+6;
-                ctx.strokeStyle = props.currentDot!.borderColor;
-                ctx.lineCap = 'round'; // 设置为圆角
-                ctx.stroke();
-
-                ctx.beginPath();
-                ctx.arc(center, center, radius, arc,
-                    arc + 0.001);
-                ctx.lineWidth = lineWidth;
-                ctx.strokeStyle = props.currentDot!.color;
-                ctx.lineCap = 'round'; // 设置为圆角
-                ctx.stroke();
-            }
-
+        //绘制real进度环
+        if (props.realRing) {
+            if (props.realRing.durationArc <0.01) props.realRing.durationArc=0.01;
+            ctx.beginPath();
+            ctx.arc(center, center, radius, props.realRing!.startArc,
+                props.realRing!.startArc + props.realRing!.durationArc);
+            ctx.lineWidth = lineWidth;
+            ctx.strokeStyle = props.realRing!.color;
+            ctx.lineCap = 'round'; // 设置为圆角
+            ctx.stroke();
+        }
 
-            // ctx.draw();
-        });
+        //绘制current_dot点
+        if (props.currentDot) {
+            var time = new Date();
+            var seconds = time.getHours() * 3600 + time.getMinutes() * 60 + time.getSeconds();
+            var arc = seconds / 86400 * 2 * Math.PI - Math.PI / 2.0;
+            ctx.beginPath();
+            ctx.arc(center, center, radius, arc,
+                arc + 0.001);
+            ctx.lineWidth = lineWidth+6;
+            ctx.strokeStyle = props.currentDot!.borderColor;
+            ctx.lineCap = 'round'; // 设置为圆角
+            ctx.stroke();
+            
+            ctx.save()
+            ctx.beginPath();
+            ctx.arc(center, center, radius, arc,
+                arc + 0.001);
+            ctx.lineWidth = lineWidth;
+            ctx.strokeStyle = props.currentDot!.color;
+            ctx.lineCap = 'round'; // 设置为圆角
+            // ctx.globalAlpha = global.breathAlpha
+            ctx.stroke();
+            ctx.restore()
+        }
     }
 
     useEffect(() => {

+ 2 - 1
src/features/trackTimeDuration/components/Schedule.tsx

@@ -17,6 +17,7 @@ import Modal from "@/components/layout/Modal";
 import Stage from "./Stage";
 import CenterContentTitleModal from "@/features/common/CenterContentTitleModal";
 import { ColorType } from "@/context/themes/color";
+import { getThemeColor } from "../hooks/Common";
 
 
 export default function Component(props: { type?: string, data?: any, delSuccess?: Function }) {
@@ -160,7 +161,7 @@ export default function Component(props: { type?: string, data?: any, delSuccess
             {
                 props.data.scenario == 'FAST_SLEEP' && <View className="schedule_more" onClick={showStage}>
                     <View style={{ flex: 1 }} />
-                    <Text style={{ textAlign: 'right' }}>{
+                    <Text style={{ textAlign: 'right',color:getThemeColor(time) }}>{
                         props.data.status == 'WAIT_FOR_START' ?
                             t('feature.track_time_duration.schedule.duration_goals_by_stage') :
                             t('feature.track_time_duration.schedule.current_stage')

+ 16 - 0
src/features/trackTimeDuration/hooks/Common.tsx

@@ -0,0 +1,16 @@
+import { ColorType } from "@/context/themes/color"
+
+export const getThemeColor = (time: any) => {
+    if (time.scenario == 'FAST') {
+        return ColorType.fast
+    }
+    else if (time.scenario == 'SLEEP') {
+        return ColorType.sleep
+    }
+    else {
+        if (time.status == 'WAIT_FOR_START' || time.status == 'ONGOING3') {
+            return ColorType.fast
+        }
+        return ColorType.sleep
+    }
+}

+ 2 - 2
src/pages/clock/Clock.scss

@@ -32,11 +32,11 @@
   }
 
   .swiper{
-    height: 400px;
+    height: 360px;
   }
 
   .console_bg{
-    height: 400px;
+    height: 360px;
     overflow: hidden;
     margin-bottom: 40px;
   }

+ 4 - 1
src/pages/clock/Clock.tsx

@@ -205,9 +205,12 @@ export default function IndexPage() {
     clearTempScenarioCache()
   })
 
+  global.showSingleFastEnd = ()=>{
+    setShowSingleFastEnd(true)
+  }
+
   function getCheckData() {
     getClocks().then(res => {
-      console.log(consoleStatus)
       dispatch(updateScenario((res as any).current_record))
       dispatch(setConfigs((res as any).time_input_schema));
       dispatch(setScenario((res as any).scenario));

+ 0 - 299
src/pages/demo_backup.tsx

@@ -1,299 +0,0 @@
-import Taro from '@tarojs/taro';
-import { Canvas, View } from '@tarojs/components';
-import { useEffect, useRef } from 'react';
-
-export default function Demo() {
-  const canvasRef = useRef<any>(null);
-  const canvasWidth: number = 200;
-  const canvasHeight: number = 200;
-  const circleRadius: number = 100;
-  const ringWidth: number = 30;
-  const dotRadius: number = 10;
-  const dpr = Taro.getSystemInfoSync().pixelRatio; // 获取设备的像素比
-
-  const canvasId = 'canvasId';
-
-  var canDrag = false;
-  var canStartDrag = false;
-  var canEndDrag = false;
-  var canRingDrag = false;
-
-  var currentContext;
-
-  var startAngle = 45*Math.PI/180;
-  var endAngle = 120*Math.PI/180;
-  var lastAngle;
-  var lastDuration = 0;
-
-  useEffect(() => {
-
-    const query = Taro.createSelectorQuery();
-    query.select(`.${canvasId}`).fields({ node: true, size: true });
-    query.exec((res) => {
-      if (res[0] == null) return;
-      const _canvas = res[0].node;
-      _canvas.width = res[0].width * dpr;
-      _canvas.height = res[0].height * dpr;
-      const ctx = _canvas.getContext('2d');
-      currentContext = ctx;
-
-      // 设置画布尺寸
-      ctx.scale(dpr, dpr);
-
-
-      drawCanvas(ctx);
-    });
-  }, []);
-
-  const drawCanvas = (ctx: any) => {
-    ctx.clearRect(0, 0, canvasWidth, canvasHeight);
-
-    // 绘制圆环
-    const centerX = canvasWidth / 2;
-    const centerY = canvasHeight / 2;
-    const radius = Math.min(centerX, centerY) - 10;
-
-    ctx.beginPath();
-    ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
-    ctx.strokeStyle = "rgba(0,0,0,0.5)";
-    ctx.lineWidth = 10;
-    ctx.stroke();
-
-    // 绘制绿色起点圆点
-    const pointX = centerX + Math.cos(startAngle) * radius;
-    const pointY = centerY + Math.sin(startAngle) * radius;
-
-    // 绘制蓝色终点圆点
-    const pointEndX = centerX + Math.cos(endAngle) * radius;
-    const pointEndY = centerY + Math.sin(endAngle) * radius;
-
-
-    ctx.beginPath();
-    ctx.arc(centerX, centerY, radius, startAngle, endAngle);
-    ctx.strokeStyle = canRingDrag?"red":"rgba(255,0,0,0.5)";
-    ctx.lineWidth = 10;
-    ctx.stroke();
-
-
-    ctx.beginPath();
-    ctx.arc(pointX, pointY, 5, 0, 2 * Math.PI);
-    ctx.fillStyle = '#00ff00';
-    ctx.fill();
-
-    
-
-    
-
-    ctx.beginPath();
-    ctx.arc(pointEndX, pointEndY, 5, 0, 2 * Math.PI);
-    ctx.fillStyle = 'blue';
-    ctx.fill();
-  };
-
-  function twoPointDistance(p1, p2) {
-    let dep = Math.sqrt(Math.pow((p1.x - p2.x), 2) + Math.pow((p1.y - p2.y), 2));
-    return dep;
-  }
-
-  function limitAngle(start,end) {
-    var angle1 = start<0?start+2*Math.PI:start;
-    var angle2 = end<0?end+2*Math.PI:end;
-    if (angle2<angle1){
-      angle2 = angle2+2*Math.PI;
-    }
-
-    var leftAngle = angle2-angle1;
-    if (leftAngle>Math.PI*23/12){
-      return 1;
-    }
-    else if (leftAngle<Math.PI/12){
-      return 2;
-    }
-    return 0;
-  }
-
-  function durationAngle(end,start) {
-    var angle1 = start<0?start+2*Math.PI:start;
-    var angle2 = end<0?end+2*Math.PI:end;
-    if (angle2<angle1){
-      angle2 = angle2+2*Math.PI;
-    }
-
-    return angle2-angle1;
-  }
-
-  const handleTouchMove = (e: any) => {
-    if (!canStartDrag && !canEndDrag && !canRingDrag){
-      return;
-    }
-    const ctx = currentContext;//canvasRef.current.getContext('2d');
-    
-    const { x, y } = e.touches[0];
-
-    const centerX = canvasWidth / 2;
-    const centerY = canvasHeight / 2;
-    const radius = Math.min(centerX, centerY) - 10;
-
-    let angle = Math.atan2(y-canvasWidth/2.0, x-canvasWidth/2.0)
-
-    if (canStartDrag){
-      if (Math.abs(durationAngle(endAngle,angle)-lastDuration)>Math.PI){
-        debugger
-        //禁止跨越
-        return;
-      }
-      console.log(durationAngle(endAngle,angle)+'    '+lastDuration)
-
-      var result = limitAngle(angle,endAngle);
-      switch (result){
-        case 0:
-          startAngle = angle;
-          break;
-        case 1:
-          debugger
-          startAngle = endAngle-23*Math.PI/12;
-          break;
-        case 2:
-          debugger
-          startAngle = endAngle-Math.PI/12;
-          break;
-      }
-      
-    }
-
-    if (canEndDrag){
-      if (Math.abs(durationAngle(angle,startAngle)-lastDuration)>Math.PI){
-        //禁止跨越
-        return;
-      }
-
-      var result = limitAngle(startAngle,angle);
-      switch (result){
-        case 0:
-          endAngle = angle;
-          break;
-        case 1:
-          endAngle = startAngle+23*Math.PI/12;
-          break;
-        case 2:
-          endAngle = startAngle+Math.PI/12;
-          break;
-      }
-      
-    }
-
-    // console.log(`startAngle:${startAngle}  endAngle:${endAngle}`)
-
-    if (canRingDrag){
-      // console.log(`lastAngle:${lastAngle}  angle:${angle}`)
-      let delta = angle - lastAngle;
-      startAngle += delta;
-      endAngle += delta;
-      lastAngle = angle;
-    }
-
-    ctx.clearRect(0, 0, canvasWidth, canvasHeight);
-      
-
-    ctx.beginPath();
-    ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
-    ctx.strokeStyle = "rgba(0,0,0,0.5)";
-    ctx.lineWidth = 10;
-    ctx.stroke();
-
-    ctx.beginPath();
-    ctx.arc(centerX, centerY, radius, startAngle, endAngle);
-    ctx.strokeStyle = canRingDrag?"red":"rgba(255,0,0,0.5)";
-    ctx.lineWidth = 10;
-    ctx.stroke();
-
-    const pointX = centerX + Math.cos(startAngle) * radius;
-    const pointY = centerY + Math.sin(startAngle) * radius;
-
-    ctx.beginPath();
-    ctx.arc(pointX, pointY, 5, 0, 2 * Math.PI);
-    ctx.fillStyle = '#00ff00';
-    ctx.fill();
-
-
-
-    // 绘制蓝色终点圆点
-    const pointX2 = centerX + Math.cos(endAngle) * radius;
-    const pointY2 = centerY + Math.sin(endAngle) * radius;
-
-    ctx.beginPath();
-    ctx.arc(pointX2, pointY2, 5, 0, 2 * Math.PI);
-    ctx.fillStyle = 'blue';
-    ctx.fill();
-
-    lastDuration = durationAngle(endAngle,startAngle);
-  };
-
-  const handleClick = (e) => {
-
-    const scaleX = 1//dpr//canvasRect.width / canvasRect.width;
-    const scaleY = 1//dpr//canvasRect.height / canvasRect.height;
-    const canvasX = (e.touches[0].x - 0) * scaleX;
-    const canvasY = (e.touches[0].y - 0) * scaleY;
-    console.log(`x:${canvasX}  y:${canvasY}`)
-
-    // const ctx = canvasRef.current.getContext('2d');
-
-    // 判断点击位置是否在圆点范围内
-    const centerX = canvasWidth / 2;
-    const centerY = canvasWidth / 2;
-    const radius = Math.min(centerX, centerY) - 10;
-
-
-    const pointX = centerX + Math.cos(startAngle) * radius;
-    const pointY = centerY + Math.sin(startAngle) * radius;
-    const distance = Math.sqrt(Math.pow(canvasX - pointX, 2) + Math.pow(canvasY - pointY, 2));
-
-    if (distance <= 8) {
-      canStartDrag = true;
-    } else {
-      canStartDrag = false;
-    }
-
-    const pointX2 = centerX + Math.cos(endAngle) * radius;
-    const pointY2 = centerY + Math.sin(endAngle) * radius;
-    const distance2 = Math.sqrt(Math.pow(canvasX - pointX2, 2) + Math.pow(canvasY - pointY2, 2));
-
-    if (distance2 <= 8) {
-      canEndDrag = true;
-    } else {
-      canEndDrag = false;
-    }
-
-    if (canStartDrag || canEndDrag){
-      canRingDrag = false;
-      return;
-    }
-
-    const distance3 = twoPointDistance({x:canvasX,y:canvasY},{x:centerX,y:centerY});
-    let angle = Math.atan2(canvasY-canvasWidth/2.0, canvasX-canvasWidth/2.0)
-    if (distance3>80&& distance3<105 && startAngle<angle && angle<endAngle){
-      canRingDrag = true;
-      console.log("canRingDrag")
-    }
-    console.log(distance3);
-    lastAngle = angle;
-  };
-
-  const handleTouchEnd = (e) =>{
-    canStartDrag = false;
-    canEndDrag = false;
-    canRingDrag = false;
-    console.log('end')
-    handleTouchMove(e)
-  }
-
-  return <View style={{ width: '100%', height: 600, backgroundColor: 'white' }}>
-    <Canvas canvasId={canvasId} id={canvasId} className={canvasId} type="2d"
-      style={{ width: 300, height: 300, zIndex: 0, backgroundColor: 'yellow' }}
-      onTouchMove={handleTouchMove}
-      onTouchEnd={handleTouchEnd}
-      onTouchStart={handleClick}
-      ref={canvasRef} />
-  </View>
-}

+ 0 - 1
src/store/action_results.tsx

@@ -80,7 +80,6 @@ export const setResult = createAsyncThunk('result/action', async (payload: {isSu
     else {
         dispatch(checkFail());
         setTimeout(()=>{
-            debugger
             dispatch(resetStatus());
         },resultTime*1000)
     }

+ 0 - 1
src/store/console.tsx

@@ -20,7 +20,6 @@ const consoleSlice = createSlice({
     reducers: {
         changeConsoleStatus: (state, action: PayloadAction<{ status: ConsoleType }>) => {
             state.status = action.payload.status;
-            debugger
         },
     },
 });

+ 0 - 1
src/store/modal.tsx

@@ -22,7 +22,6 @@ const modalSlice = createSlice({
       state.isOpen = true;
       state.title = action.payload.title;
       state.content = action.payload.content;
-      debugger
     },
     hideModal: (state) => {
       state.isOpen = false;

+ 6 - 0
src/utils/time_format.ts

@@ -184,4 +184,10 @@ export class TimeFormatter {
     var weeks = ['日', '一', '二', '三', '四', '五', '六']
     return `${now.getMonth() + 1}月${now.getDate()}日·星期${weeks[now.getDay()]}`
   }
+
+  //获取当前时间(hh:mm)
+  static getCurrentHourAndMinute = () =>{
+    var now = new Date()
+    return `${TimeFormatter.padZero(now.getHours())}:${TimeFormatter.padZero(now.getMinutes())}`;
+  }
 }