Leon 2 år sedan
förälder
incheckning
996fad1626
36 ändrade filer med 1627 tillägg och 767 borttagningar
  1. 16 5
      src/components/basic/Buttons.scss
  2. 15 3
      src/components/basic/Buttons.tsx
  3. 4 0
      src/components/input/LimitPickers.scss
  4. 2 1
      src/components/input/LimitPickers.tsx
  5. 7 0
      src/components/input/Switch.tsx
  6. 23 2
      src/components/layout/Box.scss
  7. 23 4
      src/components/layout/Box.tsx
  8. 7 2
      src/components/layout/Modal.scss
  9. 11 7
      src/components/layout/Modal.tsx
  10. 2 0
      src/components/layout/layout.tsx
  11. 1 1
      src/components/view/Timeline.scss
  12. 4 1
      src/components/view/Timeline.tsx
  13. 0 1
      src/custom-tab-bar/index.js
  14. 2 1
      src/features/common/SpecBtns.tsx
  15. 0 1
      src/features/trackSomething/components/Activity.tsx
  16. 75 23
      src/features/trackSomething/components/ActivityHistory.tsx
  17. 1 1
      src/features/trackTimeDuration/components/Clock.tsx
  18. 12 0
      src/features/trackTimeDuration/components/Console.scss
  19. 69 22
      src/features/trackTimeDuration/components/Console.tsx
  20. 5 1
      src/features/trackTimeDuration/components/More.tsx
  21. 26 0
      src/features/trackTimeDuration/components/RecordFastSleep.scss
  22. 220 0
      src/features/trackTimeDuration/components/RecordFastSleep.tsx
  23. 81 650
      src/features/trackTimeDuration/components/Schedule.tsx
  24. 697 0
      src/features/trackTimeDuration/components/Schedule_backup.tsx
  25. 28 0
      src/features/trackTimeDuration/components/TimelineFastSleep.scss
  26. 67 0
      src/features/trackTimeDuration/components/TimelineFastSleep.tsx
  27. 27 0
      src/features/trackTimeDuration/hooks/Console.tsx
  28. 77 0
      src/features/trackTimeDuration/hooks/Record.tsx
  29. 16 9
      src/pages/account/Profile.scss
  30. 25 15
      src/pages/account/Profile.tsx
  31. 13 0
      src/pages/clock/Clock.scss
  32. 41 10
      src/pages/clock/Clock.tsx
  33. 10 1
      src/pages/common/RecordsHistory.tsx
  34. 1 0
      src/services/trackTimeDuration.tsx
  35. 7 0
      src/utils/time_format.ts
  36. 12 6
      src/utils/types.ts

+ 16 - 5
src/components/basic/Buttons.scss

@@ -43,18 +43,29 @@
 
 
 
-// .outline_btn::after{
-//     border: none;
-// }
+.texted {
+    // background: linear-gradient(to right, red, blue);
+    -webkit-background-clip: text;
+    background-clip: text;
+    color: transparent;
+
+}
+
+.mixed {
+    background: linear-gradient(90deg, #AAFF00 0%, #00FFFF 100%);
+    -webkit-background-clip: text;
+    background-clip: text;
+    color: transparent;
+}
 
 
-.elevated{
+.elevated {
     display: flex;
     align-items: center;
     justify-content: center;
 }
 
-.textClass{
+.textClass {
     height: '100%';
     line-height: '100%';
 }

+ 15 - 3
src/components/basic/Buttons.tsx

@@ -21,6 +21,7 @@ export default function Buttons(props: { title: string, type?: ButtonType, statu
 export default function Buttons(props: {
     title: string,
     type?: ButtonType,
+    className?:any,
     onClick: () => void,
     disabled?: boolean,
     lowLight?: boolean,
@@ -36,14 +37,25 @@ export default function Buttons(props: {
 
     var mainClass = 'elevated'
     var textClass = 'elevated_text'
+
+    if (props.type == ButtonType.text) {
+        mainClass = 'texted'
+        return <View style={{ opacity: (props.lowLight || props.disabled) ? 0.4 : 1 }} onClick={onClick}>
+            <Text
+                style={{
+                    ...props.btnStyle
+                }} className={props.className?props.className:''}>{props.title}</Text>
+        </View>
+    }
+
     if (props.type == ButtonType.outline) {
         mainClass = 'outlined'
         textClass = 'outlined_text'
 
         return (
-            <View className={mainClass} style={{ ...props.btnStyle,opacity:props.lowLight?0.4:1 }} onClick={onClick}>
+            <View className={mainClass} style={{ ...props.btnStyle, opacity: props.lowLight ? 0.4 : 1 }} onClick={onClick}>
                 <Text
-                    
+
                     style={{
                         color: props.btnStyle.color,
                         fontSize: props.btnStyle.fontSize
@@ -56,7 +68,7 @@ export default function Buttons(props: {
         textClass = 'puretext_text'
     }
     return (
-        <View className={mainClass} style={{ ...props.btnStyle }} onClick={onClick}>
+        <View className={mainClass} style={{ ...props.btnStyle, opacity: props.lowLight ? 0.4 : 1  }} onClick={onClick}>
             <Text
                 // onClick={onClick}
                 style={{

+ 4 - 0
src/components/input/LimitPickers.scss

@@ -28,4 +28,8 @@
     align-items: center;
     justify-content: center;
     background-color: transparent;
+}
+
+.picker-sel{
+    background-color: #00ffff;
 }

+ 2 - 1
src/components/input/LimitPickers.tsx

@@ -210,9 +210,10 @@ const Component = forwardRef((props: {
             <PickerView value={values}
                 className="picker"
                 maskClass="picker-mask"
+                // indicatorClass = 'picker-sel'
                 onChange={onPickerChange}
                 immediateChange={true}
-                indicatorStyle='height: 50px;'>
+                indicatorStyle='height: 50px;color:red;'>
                 <PickerViewColumn style='flex:0 0 45%'>
                     {days.map(item => {
                         return (

+ 7 - 0
src/components/input/Switch.tsx

@@ -0,0 +1,7 @@
+import { View,Image } from "@tarojs/components";
+
+export default function Component(props:{isOn:boolean,onClick:Function}){
+    return <View onClick={()=>props.onClick()}>
+        <Image style={{width:42,height:26}} src={require(props.isOn?'@/assets/images/notice_switch_select.png':'@/assets/images/notice_switch_unselect.png')}/>
+    </View>
+}

+ 23 - 2
src/components/layout/Box.scss

@@ -1,16 +1,37 @@
-.box-container{
+.box-container {
     background-color: #1C1C1C;
     border-radius: 56px;
     padding: 40px;
     margin-left: 46px;
     margin-right: 46px;
+    width: 658px;
+    box-sizing: border-box;
     display: flex;
     flex-direction: column;
     margin-bottom: 20px;
+    flex-shrink: 0;
     // position: relative;
 }
 
-.box-title{
+.box-outline {
+    background-color: transparent;
+    display: flex;
+    flex-direction: column;
+    padding-left: 40px;
+    padding-right: 40px;
+    padding-top: 34px;
+    padding-bottom: 34px;
+    border-radius: 36px;
+    border-color: #323232;
+    border-width: 1px;
+    border-style: solid;
+    margin-left: 46px;
+    margin-right: 46px;
+    margin-bottom: 40px;
+    position: relative;
+}
+
+.box-title {
     font-size: 40px;
     line-height: 40px;
     color: #fff;

+ 23 - 4
src/components/layout/Box.tsx

@@ -1,10 +1,29 @@
-import { View,Text } from "@tarojs/components";
+import { View, Text } from "@tarojs/components";
 import './Box.scss'
+import { BoxType } from "@/utils/types";
 
-export default function Component(props: { children: React.ReactNode,title?:string, header?: React.ReactNode }) {
-    return <View>
+export default function Component(props: {
+    children: React.ReactNode,
+    title?: string,
+    header?: React.ReactNode,
+    style?: any,
+    type?: BoxType
+}) {
+    switch (props.type) {
+        case BoxType.outline:
+            return <View style={{display:'flex',flexShrink:0}}>
+                {props.header ? props.header : null}
+                <View className="box-outline" style={{ ...props.style }}>
+                    {
+                        props.title && <Text className="box-title">{props.title}</Text>
+                    }
+                    {props.children}
+                </View>
+            </View>
+    }
+    return <View  style={{display:'flex',flexShrink:0}}>
         {props.header ? props.header : null}
-        <View className="box-container">
+        <View className="box-container" style={{ ...props.style }}>
             {
                 props.title && <Text className="box-title">{props.title}</Text>
             }

+ 7 - 2
src/components/layout/Modal.scss

@@ -29,12 +29,17 @@
 .modal_center_container{
     align-items: center;
     justify-content: center;
+    // margin-bottom: 560px;
 }
 
+.center_modal_detail{
+    margin-bottom: 192px;
+}
 .modal_center_content{
-    background-color: #1c1c1c;
-    border-radius: 36rpx;
+    // background-color: #1c1c1c;
+    // border-radius: 36rpx;
     width: 658px;
+    
 }
 
 

+ 11 - 7
src/components/layout/Modal.tsx

@@ -2,28 +2,32 @@ import { View, Text } from '@tarojs/components'
 import './Modal.scss'
 import React from 'react';
 import { ModalType } from '@/utils/types';
+import Box from './Box';
 
 export default function Modal(props: {
     children: React.ReactNode,
-    testInfo?:React.ReactNode,
+    testInfo?: React.ReactNode,
     title?: string, dismiss: Function,
     confirm: Function,
     themeColor?: string,
-    modalType?:ModalType
+    modalType?: ModalType
 }) {
 
     //阻止中间内容点击事件穿透
-    function click(e){
+    function click(e) {
         e.stopPropagation();
     }
 
     switch (props.modalType) {
         case ModalType.center:
             return <View className='modal modal_center_container' catchMove onClick={() => props.dismiss()}>
-                <View className='modal_center_content' onClick={click}>
-                    {
-                        props.children
-                    }
+                <View className='center_modal_detail'>
+                    <Box><View onClick={click}>
+                        {
+                            props.children
+                        }
+                    </View>
+                    </Box>
                 </View>
             </View>
     }

+ 2 - 0
src/components/layout/layout.tsx

@@ -54,6 +54,7 @@ export default function Layout(props: {
                     props.title && <Text className='layout_title'>{props.title}</Text>
                 }
                 {children}
+                <View style={{height:50}}/>
             </ScrollView>
         case TemplateType.grid:
             return <ScrollView className="layout_container"
@@ -72,6 +73,7 @@ export default function Layout(props: {
                 }
                 <View className="grid_bg">
                     {children}
+                    <View style={{height:50}}/>
                 </View>
             </ScrollView>
         case TemplateType.flex:

+ 1 - 1
src/components/view/Timeline.scss

@@ -1,7 +1,7 @@
 .timeline {
     display: flex;
     flex-direction: column;
-    
+    color: #fff;
   }
   
   .timeline-item {

+ 4 - 1
src/components/view/Timeline.tsx

@@ -8,8 +8,11 @@ import './Timeline.scss'
 // }
 
 
-export default function Component(props: { items: any[] }) {
+export default function Component(props: { items: any[], title?: string }) {
     return <View className="timeline">
+        {
+            props.title && <Text>{props.title}</Text>
+        }
         {props.items.map((item, index) => (
             <View className="timeline-item" key={index}>
                 <View className={`timeline-icon ${item.status}`} />

+ 0 - 1
src/custom-tab-bar/index.js

@@ -22,7 +22,6 @@ Component({
   },
   methods: {
     update(index){
-      console.log(index)
       this.setData({
         selected: index
       })

+ 2 - 1
src/features/common/SpecBtns.tsx

@@ -23,10 +23,11 @@ export const StartFastBtn = (props: { onClick: Function }) => {
     )
 }
 
-export const StartSleepBtn = (props: { onClick: Function }) => {
+export const StartSleepBtn = (props: { onClick: Function,lowLight?:boolean }) => {
     return (
         <Buttons title="开始睡眠" type={ButtonType.elevated}
             onClick={() => { props.onClick() }}
+            lowLight={props.lowLight?props.lowLight:false}
             btnStyle={{
                 height: 50, 
                 borderRadius: 25,

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

@@ -92,7 +92,6 @@ export default function Component(props: any) {
     global.activityCardsFunc = getCards
 
     function checkAuth() {
-        console.log(new Date().getTime())
         if (user.isLogin) {
             Taro.getSetting({
                 success: res => {

+ 75 - 23
src/features/trackSomething/components/ActivityHistory.tsx

@@ -4,6 +4,10 @@ import RecordItem from "@/features/common/RecordItem";
 import { deleteActivityRecord } from "@/services/trackSomething";
 import { useEffect, useState } from "react";
 import { useSelector } from "react-redux";
+import Modal from "@/components/layout/Modal";
+import { ModalType } from "@/utils/types";
+import Timeline from "@/components/view/Timeline";
+import { TimeFormatter } from "@/utils/time_format";
 
 export default function Component(props: { records: any[] }) {
     const user = useSelector((state: any) => state.user);
@@ -52,38 +56,86 @@ export default function Component(props: { records: any[] }) {
         })
     }
 
+    function schedules(item) {
+        var timelineItems: any = [];
+        for (var i = item.records.length - 1; i > 0; i--) {
+            var type = item.records[i].type == 'total' ? '总计' : item.records[i].type == 'sync' ? '同步' : '打卡'
+            timelineItems.push(
+                {
+                    status: 'done',
+                    title: type + item.records[i].items[0].value + '步',
+                    content: TimeFormatter.formatTimestamp(item.records[i].timestamp),
+                }
+            )
+        }
+        return <View>
+            <Timeline items={timelineItems} title={formateDate(item.date + '')} />
+        </View>
+    }
+
+    function showDetail(item) {
+        var node = (<Modal children={schedules(item)}
+            modalType={ModalType.center}
+            dismiss={() => {
+                global.showModal(false, null)
+            }}
+            confirm={() => { }} />);
+        global.showModal(true, node);
+    }
+
     return <View style={{ display: 'flex', flexDirection: 'column' }}>
         {
-            user.test_user && <Text style={{ color: '#fff', position: 'absolute', right: 50, top: 0 }} onClick={()=>global.clearHistory()}>删除全部</Text>
+            user.test_user && <Text style={{ color: '#fff', position: 'absolute', right: 50, top: 0 }} onClick={() => global.clearHistory()}>删除全部</Text>
         }
-        {/* <View className="operate_view">
-            <Text>时间倒序</Text>
-            <Text style={{ marginLeft: 5, marginRight: 5 }}> | </Text>
-            <Text>时间正序</Text>
-            <View style={{flex:1}}/>
-        </View> */}
         {
             (list as any).map(item => {
                 return <View style={{ display: 'flex', flexDirection: 'column' }}>
                     <Text className="operate_day">{formateDate(item.date + '')}</Text>
-                    {
-                        item.records.map(record => {
-                            return <RecordItem delete={() => deleteRecord(record)}>
-                                <View className="operate_item">
-                                    <View className="status_bg">
-                                        <Text className="status_text">{record.type == 'total' ? '总计' : record.type == 'sync' ? '同步' : '打卡'}</Text>
-                                    </View>
-                                    <View style={{ width: 12 }} />
-                                    <Text className="value">{record.items[0].value}</Text>
-                                    <Text className="unit">步</Text>
-                                    <View style={{ flex: 1 }} />
-                                    <Text className="time">{formateHourMinutes(record.timestamp)}</Text>
-                                </View>
-                            </RecordItem>
-                        })
-                    }
+
+                    <RecordItem onClick={() => showDetail(item)} delete={() => deleteRecord(item.records[0])}>
+                        <View className="operate_item">
+                            <View className="status_bg">
+                                <Text className="status_text">{item.records[0].type == 'total' ? '总计' : item.records[0].type == 'sync' ? '同步' : '打卡'}</Text>
+                            </View>
+                            <View style={{ width: 12 }} />
+                            <Text className="value">{item.records[0].items[0].value}</Text>
+                            <Text className="unit">步</Text>
+                            <View style={{ flex: 1 }} />
+                            <Text className="time">{formateHourMinutes(item.records[0].timestamp)}</Text>
+                        </View>
+                    </RecordItem>
+
                 </View>
             })
         }
     </View>
+
+    // return <View style={{ display: 'flex', flexDirection: 'column' }}>
+    //     {
+    //         user.test_user && <Text style={{ color: '#fff', position: 'absolute', right: 50, top: 0 }} onClick={()=>global.clearHistory()}>删除全部</Text>
+    //     }
+    //     {
+    //         (list as any).map(item => {
+    //             return <View style={{ display: 'flex', flexDirection: 'column' }}>
+    //                 <Text className="operate_day">{formateDate(item.date + '')}</Text>
+    //                 {
+    //                     item.records.map(record => {
+    //                         return <RecordItem delete={() => deleteRecord(record)}>
+    //                             <View className="operate_item">
+    //                                 <View className="status_bg">
+    //                                     <Text className="status_text">{record.type == 'total' ? '总计' : record.type == 'sync' ? '同步' : '打卡'}</Text>
+    //                                 </View>
+    //                                 <View style={{ width: 12 }} />
+    //                                 <Text className="value">{record.items[0].value}</Text>
+    //                                 <Text className="unit">步</Text>
+    //                                 <View style={{ flex: 1 }} />
+    //                                 <Text className="time">{formateHourMinutes(record.timestamp)}</Text>
+    //                             </View>
+    //                         </RecordItem>
+    //                     })
+    //                 }
+    //             </View>
+    //         })
+    //     }
+    // </View>
 }

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

@@ -82,7 +82,7 @@ export default function Component() {
             }
         </View>
     return (
-        <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', width: '100%', marginTop: 20 }}>
+        <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', width: '100%' }}>
             <View style={{ position: 'relative', zIndex: 1 }}>
                 {
                     bigRing()

+ 12 - 0
src/features/trackTimeDuration/components/Console.scss

@@ -0,0 +1,12 @@
+.stepper_text {
+    font-size: 48px;
+    font-weight: 500;
+    width: 300px;
+    text-align: center;
+}
+
+.counter_text{
+    font-size: 48px;
+    font-weight: 500;
+    text-align: center;
+}

+ 69 - 22
src/features/trackTimeDuration/components/Console.tsx

@@ -8,11 +8,13 @@ import { 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, pickerDurations } from "../hooks/Console";
+import { durationDatas, durationIndex, getTitle, pickerDurations } 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'
 
 export default function Component() {
     const scenario = useSelector((state: any) => state.scenario);
@@ -203,11 +205,23 @@ export default function Component() {
             }
         }
 
+        var color = isFast ? '#aaff00' : '#00ffff'
+        if (value == 'ONGOING2') {
+            color = '#00ffff'
+        }
+
+        var checkData = machine.context.checkData;
+        var current = (checkData as any).current_record
+        var title = getTitle(current)
+
 
-        return <LimitPickers ref={limitPickerRef} limit={limit} limitDay={8} onCancel={hidePicker} onChange={(e) => {
-            pickerConfirm(e)
-            hidePicker()
-        }} />
+        return <LimitPickers ref={limitPickerRef} limit={limit} limitDay={8}
+            themeColor={color}
+            title={title}
+            onCancel={hidePicker} onChange={(e) => {
+                pickerConfirm(e)
+                hidePicker()
+            }} />
     }
 
     function pickerConfirm(t: number) {
@@ -255,16 +269,36 @@ export default function Component() {
                 value == 'ONGOING1' && <StartSleepBtn onClick={showPicker} />
             }
             {
-                value == 'ONGOING2' && <EndSleepBtn onClick={showPicker} lowLight={current.sleep.target_end_time > new Date().getTime()}/>
+                value == 'ONGOING2' && <EndSleepBtn onClick={showPicker} lowLight={current.sleep.target_end_time > new Date().getTime()} />
 
             }
         </View>
     }
 
+    function textAlpha() {
+        var checkData = machine.context.checkData;
+        var current = (checkData as any).current_record
+        if (value == 'WAIT_FOR_START' || value == 'DONE') {
+            return 1;
+        }
+
+        if (value == 'ONGOING' || value == 'ONGOING3') {
+            if (current.scenario == 'SLEEP') {
+                return current.sleep.target_end_time > new Date().getTime() ? 0.4 : 1
+            }
+            return current.fast.target_end_time > new Date().getTime() ? 0.4 : 1
+        }
+        if (value == 'ONGOING1')
+            return 1//current.sleep.target_start_time > new Date().getTime()?0.4:1
+        if (value == 'ONGOING2')
+            return current.sleep.target_end_time > new Date().getTime() ? 0.4 : 1
+        return 1
+    }
+
     function fastBtns() {
         return <View style={{ display: 'flex', marginTop: 22 }}>
             {
-                value == 'ONGOING' ? <EndSleepBtn onClick={showPicker} /> : <StartFastBtn onClick={showPicker} />
+                value == 'ONGOING' ? <EndFastBtn onClick={showPicker} lowLight={textAlpha() != 1} /> : <StartFastBtn onClick={showPicker} />
             }
         </View>
     }
@@ -272,7 +306,7 @@ export default function Component() {
     function sleepBtns() {
         return <View style={{ display: 'flex', marginTop: 22 }}>
             {
-                value == 'ONGOING' ? <EndSleepBtn onClick={showPicker} /> : <StartSleepBtn onClick={showPicker} />
+                value == 'ONGOING' ? <EndSleepBtn onClick={showPicker} lowLight={textAlpha() != 1} /> : <StartSleepBtn onClick={showPicker} />
             }
         </View>
     }
@@ -327,8 +361,21 @@ export default function Component() {
 
 
     function durationPickerContent() {
+        var color = isFast ? '#aaff00' : '#00ffff'
+        if (value == 'ONGOING2') {
+            color = '#00ffff'
+        }
+        var checkData = machine.context.checkData;
+        var current = (checkData as any).current_record
+        var title = getTitle(current)
         return <View style={{ color: '#fff', backgroundColor: 'transparent' }}>
-            <PickerViews ref={durationPickerRef} onChange={durationChange} items={durationDatas(common)} value={isFast ? fastPickerValue : sleepPickerValue} showBtns={true} onCancel={() => { setIsOpenDurationPicker(false) }} />
+            <PickerViews ref={durationPickerRef}
+                onChange={durationChange}
+                items={durationDatas(common)}
+                value={isFast ? fastPickerValue : sleepPickerValue}
+                themeColor={color}
+                title={title}
+                showBtns={true} onCancel={() => { setIsOpenDurationPicker(false) }} />
         </View>
     }
 
@@ -399,36 +446,36 @@ export default function Component() {
         }
         return false;
     }
+
+    var textColor = '#AAFF00'
+    if (!isFast) {
+        textColor = '#00FFFF'
+    }
+
     return (
-        <View style={{ display: 'flex', flexDirection: 'column', width: '100%', alignItems: 'center' }}>
-            {
-                machine.context.checkData && (machine.context.checkData as any).current_record.last_real_check_time &&
-                <Text style={{ width: '100%', textAlign: 'center', color: 'red' }}>
-                    {TimeFormatter.formateTime((machine.context.checkData as any).current_record.last_real_check_time)}
-                </Text>
-            }
+        <Box style={{ flexDirection: 'column', alignItems: 'center',flexShrink:0 }}>
             {
                 value == 'ONGOING' && <View>
-                    <Text>{(machine.context.checkData as any).current_record.scenario == 'FAST' ?
+                    <Text className="counter_text" style={{ color: textColor, opacity: textAlpha() }}>{(machine.context.checkData as any).current_record.scenario == 'FAST' ?
                         TimeFormatter.countdown((machine.context.checkData as any).current_record.fast.target_end_time) :
                         TimeFormatter.countdown((machine.context.checkData as any).current_record.sleep.target_end_time)}</Text>
                 </View>
             }
             {
-                (value == 'ONGOING1' || value == 'WAIT_FOR_START') && <Stepper style={{ marginBottom: 10 }} child={
-                    <Text style={{ width: 150, textAlign: 'center' }} onClick={showDurationPicker}>{durationFormate()}</Text>
+                (value == 'ONGOING1' || value == 'WAIT_FOR_START') && <Stepper child={
+                    <Text className="stepper_text" style={{ color: textColor, opacity: textAlpha() }} onClick={showDurationPicker}>{durationFormate()}</Text>
                 } minus={minus} plus={plus} disableMinus={disableMinus()} disablePlus={disablePlus()} />
                 // <Text style={{marginBottom:10}} onClick={showDurationPicker}>时长:{durationFormate()}</Text>
             }
             {
                 machine.context.checkData && value == 'ONGOING2' && <View>
-                    <Text>{TimeFormatter.countdown((machine.context.checkData as any).current_record.sleep.target_end_time)}</Text>
+                    <Text className="counter_text" style={{ color: '#00ffff', opacity: textAlpha() }}>{TimeFormatter.countdown((machine.context.checkData as any).current_record.sleep.target_end_time)}</Text>
                 </View>
             }
 
             {
                 machine.context.checkData && value == 'ONGOING3' && <View>
-                    <Text>{TimeFormatter.countdown((machine.context.checkData as any).current_record.fast.target_end_time)}</Text>
+                    <Text className="counter_text" style={{ color: textColor, opacity: textAlpha() }}>{TimeFormatter.countdown((machine.context.checkData as any).current_record.fast.target_end_time)}</Text>
                 </View>
             }
 
@@ -458,6 +505,6 @@ export default function Component() {
                 }} />
             }
 
-        </View>
+        </Box>
     )
 }

+ 5 - 1
src/features/trackTimeDuration/components/More.tsx

@@ -131,7 +131,11 @@ const Component = forwardRef((props, ref) => {
         }
 
         
-        return <LimitPickers ref={limitPickerRef} limit={limit} onCancel={() => { setIsOpen(false); setShowModal(false) }} onChange={(e) => {
+        return <LimitPickers ref={limitPickerRef}
+        title = '结束断食'
+        themeColor="#AAFF00"
+        limit={limit} onCancel={() => { setIsOpen(false); setShowModal(false) }} 
+        onChange={(e) => {
             endFast(e)
             setIsOpen(false)
         }} />

+ 26 - 0
src/features/trackTimeDuration/components/RecordFastSleep.scss

@@ -0,0 +1,26 @@
+.duration_bg{
+    margin-left: 50px;
+    display: flex;
+    flex-direction: column;
+    flex: 1;
+}
+
+.duration_title{
+    font-size: 32px;
+    line-height: 32px;
+    color: #fff;
+    opacity: 0.6;
+    font-weight: 400;
+}
+
+.duration_value{
+    font-size: 36px;
+    line-height: 36px;
+    font-weight: 500;
+    margin-bottom: 12px;
+}
+
+.arrow1{
+    width: 48px;
+    height: 48px;
+}

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

@@ -0,0 +1,220 @@
+import Box from "@/components/layout/Box";
+import Header from "@/components/layout/Header";
+import Modal from "@/components/layout/Modal";
+import RecordItem from "@/features/common/RecordItem";
+import { delRecord } from "@/services/trackTimeDuration";
+import { ModalType } from "@/utils/types";
+import { View, Text, Image } from "@tarojs/components";
+import Taro from "@tarojs/taro";
+import { useState } from "react";
+import TimelineFastSleep from "./TimelineFastSleep";
+import { TimeFormatter } from "@/utils/time_format";
+import './RecordFastSleep.scss'
+import { getBgRing, getCommon, getDot, getReal, getTarget } from "../hooks/RingData";
+import Rings from "./Rings";
+
+export default function RecordFastSleep(props: { data: any, type: string, delSuccess?: Function }) {
+    const [showDetailModal, setShowDetailModal] = useState(false)
+    const canvasId = props.data.id
+    const record = props.data;
+    function header() {
+        if (props.type == 'latest') {
+            return <Header title="最近记录" action={() => {
+                Taro.navigateTo({
+                    url: '/pages/common/RecordsHistory?type=time&title=time'
+                })
+            }} />
+        }
+        return null
+    }
+    function del() {
+        var id = props.data.id
+        delRecord(id
+        ).then(res => {
+            Taro.showToast({
+                title: '删除成功'
+            })
+            props.delSuccess && props.delSuccess(props.data)
+            // Taro.navigateBack()
+        })
+    }
+
+    function schedules() {
+        return <TimelineFastSleep data={props.data} title="Timeline" />
+    }
+
+    function showDetail() {
+        if (props.type == 'latest') {
+            setShowDetailModal(true)
+            return;
+        }
+        // 
+        var node = (<Modal children={schedules()}
+            modalType={ModalType.center}
+            dismiss={() => {
+                global.showModal(false, null)
+            }}
+            confirm={() => { }} />);
+        global.showModal(true, node);
+    }
+
+    function getDuration(obj) {
+        if (!obj) {
+            debugger
+        }
+        if (obj.status == 'NOT_STARTED' || obj.status == 'NOT_COMPLETED') {
+            return ''
+        }
+        var start = obj.real_start_time
+        var end = obj.real_end_time
+        if (!end) {
+            end = (new Date()).getTime()
+        }
+        return TimeFormatter.calculateTimeDifference(start, end)
+    }
+
+    function durationArc(start_time: number, end_time: number) {
+        var duration = (end_time - start_time) / 1000;
+        return duration / (24 * 3600) * 2 * Math.PI;
+    }
+
+    function bigRing() {
+        var common = getCommon(null, true)
+        var bgRing = getBgRing()
+
+        if (props.type == 'record' || props.type == 'latest') {
+            var realRing = getReal(record, true, true)
+            return <Rings common={common} bgRing={bgRing} canvasId={canvasId} realRing={realRing} />
+        }
+        else {
+            var currentDot1 = getDot(record, true)
+            var targetBigRing1 = getTarget(record, true)
+            if (record.status == 'ONGOING') {
+                var realRing1 = getReal(record, true, false)
+
+                return <Rings common={common} bgRing={bgRing} currentDot={currentDot1} realRing={realRing1} targetRing={targetBigRing1} canvasId={canvasId} />
+            }
+            if (record.status == 'WAIT_FOR_START') {
+                return <Rings common={common} bgRing={bgRing} currentDot={currentDot1} canvasId={canvasId} />
+            }
+            var realRing1 = getReal(record, true, false)
+            return <Rings common={common} bgRing={bgRing} realRing={realRing1} currentDot={currentDot1} targetRing={targetBigRing1} canvasId={canvasId} />
+        }
+    }
+
+    function smallRing() {
+        if (record.scenario == 'FAST_SLEEP') {
+            var common = getCommon(null, false)
+            var bgRing = getBgRing()
+            var realRing = getReal(record, false, false)
+            if (props.type == 'record' || props.type == 'latest') {
+                if (record.sleep.status == 'WAIT_FOR_END') {
+                    realRing.durationArc = durationArc(record.sleep.target_start_time, (new Date()).getTime())
+                    return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing} />
+                }
+                else if (record.sleep.status == 'NOT_COMPLETED') {
+                    realRing.durationArc = 0.01
+                    return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing} />
+                }
+                else if (record.sleep.status == 'COMPLETED') {
+                    realRing = getReal(record, false, true)
+                    return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing} />
+                }
+                return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} />
+            }
+            else {
+
+
+                var currentDot = getDot(record, false)
+                var targetRing = getTarget(record, false)
+                if (record.status == 'ONGOING2') {
+                    var realRing = getReal(record, false, false)
+                    return <Rings common={common} bgRing={bgRing} realRing={realRing} currentDot={currentDot} targetRing={targetRing} canvasId={canvasId + 'small'} />
+                }
+                if (record.status == 'ONGOING3') {
+                    currentDot.color = 'rgba(0, 255, 255, 0.5)'
+                }
+                return <Rings common={common} bgRing={bgRing} currentDot={currentDot} canvasId={canvasId + 'small'} />
+            }
+        }
+        return null
+    }
+
+    function rings() {
+        return <View style={{ position: 'relative', zIndex: 1 }}>
+            {
+                bigRing()
+            }
+            <View style={{ display: 'flex', position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, alignItems: 'center', justifyContent: 'center' }}>
+                {
+                    smallRing()
+                }
+            </View>
+        </View>
+    }
+
+    function recordDetail() {
+        var fastDuration = ''
+        var sleepDuration = ''
+        var showFast = false;
+        var showSleep = false;
+        if (record.scenario == 'FAST_SLEEP') {
+            fastDuration = getDuration(record.fast)
+            sleepDuration = getDuration(record.sleep)
+            if (record.status == 'ONGOING3'){
+                fastDuration = '待结束'
+            }
+
+            if (record.sleep.status ==  "NOT_STARTED"){
+                sleepDuration = '未开始'
+            }
+            else if (record.sleep.status == 'NOT_COMPLETED'){
+                sleepDuration = '未完成'
+            }
+            showFast = true
+            showSleep = true
+        }
+        else if (record.scenario == 'FAST') {
+            fastDuration = getDuration(record.fast)
+            showFast = true
+        }
+        else {
+            sleepDuration = getDuration(record.sleep)
+            showSleep = true
+        }
+        return <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
+            {
+                rings()
+            }
+            <View className="duration_bg">
+                {
+                    showFast && <Text className="duration_title">断食</Text>
+                }
+                {
+                    showFast && <Text className="duration_value" style={{ color: '#AAFF00' }}>{fastDuration}</Text>
+                }
+                {
+                    showSleep && <Text className="duration_title">睡眠</Text>
+                }
+                {
+                    showSleep && <Text className="duration_value" style={{ color: '#00FFFF' }}>{sleepDuration}</Text>
+                }
+            </View>
+            <Image className="arrow1" src={require('@/assets/images/arrow.png')} />
+        </View>
+    }
+
+
+    return <Box header={header()}>
+        <RecordItem canDel={record.status == 'COMPLETED'} delete={del}
+            onClick={() => { showDetail() }}
+        >{recordDetail()}
+        </RecordItem>
+        {
+            showDetailModal && <Modal children={schedules()}
+                modalType={ModalType.center}
+                dismiss={() => setShowDetailModal(false)}
+                confirm={() => { }} />
+        }
+    </Box>
+}

+ 81 - 650
src/features/trackTimeDuration/components/Schedule.tsx

@@ -1,390 +1,24 @@
-import { View, Text, Image } from "@tarojs/components";
+import { View, Text } from "@tarojs/components";
 import trackTimeService, { machine } from "@/store/trackTimeMachine"
 import { useEffect, useState } from "react";
 import Taro from "@tarojs/taro";
-import { TimeFormatter } from "@/utils/time_format";
-// import "taro-ui/dist/style/components/float-layout.scss";
-import { delRecord } from "@/services/trackTimeDuration";
-import Modal from "@/components/layout/Modal";
-import Rings, { BgRing, CurrentDot, RealRing, RingCommon } from './Rings';
-import { getBgRing, getCommon, getDot, getReal, getTarget } from "../hooks/RingData";
-import Timeline from "@/components/view/Timeline";
-import RecordItem from "@/features/common/RecordItem";
 import Box from "@/components/layout/Box";
 import './Schedule.scss'
-import { ModalType } from "@/utils/types";
-import Header from "@/components/layout/Header";
 import { useTranslation } from "react-i18next";
+import TimelineFastSleep from "./TimelineFastSleep";
+import Switch from "@/components/input/Switch";
+import { useDispatch, useSelector } from "react-redux";
+import { TimeFormatter } from "@/utils/time_format";
+import Buttons from "@/components/basic/Buttons";
+import { ButtonType } from "@/utils/types";
+import { setStep } from "@/store/scenario";
 
 
 export default function Component(props: { type?: string, data?: any, delSuccess?: Function }) {
-    const [checkData, setCheckData] = useState(null)
     const { t } = useTranslation()
-    const [key, setKey] = useState('');
-    const [value, setValue] = useState('');
-    const [isOpen, setIsOpen] = useState(false);
-    const [isLatest, setIsLatest] = useState(props.type == 'latest');
-    const [showDetailModal, setShowDetailModal] = useState(false)
-    const canvasId = props.type == 'latest' ? 'latest' : props.type == 'record' ? props.data.id : 'current'
-
-    useEffect(() => {
-        getStateDetail();
-    }, [machine.context.currentStatus])
-
-    useEffect(() => {
-        if (machine.context.checkData) {
-            setCheckData(machine.context.checkData as any);
-        }
-        getStateDetail();
-    }, [machine.context.checkData]);
-    useEffect(() => {
-        trackTimeService.onTransition(state => {
-            getStateDetail();
-        });
-    }, []);
-
-
-    function getStateDetail() {
-        if (props.type == 'latest') {
-            if (machine.context.checkData) {
-                setKey((machine.context.checkData as any).latest_record.scenario);
-                setValue((machine.context.checkData as any).latest_record.status);
-            }
-            return
-        }
-
-        var state = trackTimeService.getSnapshot().value
-        if ((state as any).FAST_SLEEP) {
-            setKey('FAST_SLEEP');
-            setValue((state as any).FAST_SLEEP);
-        }
-        if ((state as any).FAST) {
-            setKey('FAST');
-            setValue((state as any).FAST);
-        }
-        if ((state as any).SLEEP) {
-            setKey('SLEEP');
-            setValue((state as any).SLEEP);
-        }
-
-    }
-
-    function editSchedule() {
-        Taro.navigateTo({
-            url: '/pages/clock/SetSchedule'
-        })
-    }
-
-    function showStage(e) {
-        setIsLatest(false);
-        setIsOpen(true)
-        debugger
-        e.stopPropagation()
-    }
-
-    function showLatest(e) {
-        // startTimer();
-        setIsLatest(true)
-        setIsOpen(true)
-        debugger
-        e.stopPropagation()
-    }
-
-    function getTime(t1: number, t2: number) {
-        return TimeFormatter.calculateTimeDifference(t1, t2)
-    }
-
-
-
-    function getStepATime(obj) {
-        if (obj.status == 'COMPLETED' && obj.sleep.status == 'NOT_STARTED') {
-            return '未知'
-        }
-        return obj.status == 'ONGOING1' ?
-            getTime(obj.fast.real_start_time, (new Date()).getTime()) :
-            obj.sleep.real_start_time ? getTime(obj.sleep.real_start_time, obj.fast.real_start_time ? obj.fast.real_start_time : obj.fast.target_start_time) :
-                getTime(obj.sleep.target_start_time, obj.fast.real_start_time ? obj.fast.real_start_time : obj.fast.target_start_time)
-    }
-
-    function getStepBTime(obj) {
-        if (obj.status == 'ONGOING1') return 'Next up'
-        if (obj.status == 'ONGOING2') return getTime(obj.sleep.real_start_time, (new Date()).getTime())
-        if (obj.status == 'WAIT_FOR_START') return getTime(obj.sleep.target_end_time, obj.sleep.target_start_time)
-        if (obj.sleep.status == 'NOT_COMPLETED' || obj.sleep.status == 'NOT_STARTED') return '未知'
-        return getTime(obj.sleep.real_end_time, obj.sleep.real_start_time)
-
-    }
-
-    function getStepCTime(obj) {
-        if (obj.status == 'ONGOING1') return 'Final stage'
-        if (obj.status == 'ONGOING2') return 'Next up'
-        if (obj.status == 'ONGOING3') return getTime(obj.sleep.real_end_time, (new Date()).getTime())
-        if (obj.status == 'WAIT_FOR_START') return getTime(obj.fast.target_end_time, obj.sleep.target_end_time)
-        if (obj.sleep.status == 'NOT_COMPLETED' || obj.sleep.status == 'NOT_STARTED') return '未知'
-        return getTime(obj.fast.real_end_time, obj.sleep.real_end_time)
-    }
-
-    function layoutContent() {
-        debugger
-        //当前断食阶段
-        var obj = isLatest ? (checkData as any).latest_record : (checkData as any).current_record
-        if (props.type == 'record') {
-            obj = props.data
-        }
-        return <View style={{ flexDirection: 'column', display: 'flex', color: '#000', backgroundColor: '#fff', paddingTop: 50, paddingBottom: 50, position: 'relative' }}>
-            <Text style={{ position: 'absolute', top: 5, right: 20 }} onClick={() => setIsOpen(false)}>关闭</Text>
-            {
-                obj.status == 'WAIT_FOR_START' ? <Text>断食阶段目标</Text> :
-                    obj.status == 'COMPLETED' ? <Text>断食阶段</Text> :
-                        <Text>当前断食阶段</Text>
-            }
-            <View style={{ flexDirection: 'row', display: 'flex' }}>
-                <Text>阶段A</Text>
-                <Text style={{ color: obj.status == 'ONGOING1' ? '#AAFF00' : '', marginLeft: 20, marginRight: 20 }}> 睡前断食</Text>
-                <Text style={{ color: obj.status == 'ONGOING1' ? '#AAFF00' : '' }}> {
-                    getStepATime(obj)
-                }</Text>
-            </View>
-            <View style={{ flexDirection: 'row', display: 'flex' }}>
-                <Text>阶段B</Text>
-                <Text style={{ color: obj.status == 'ONGOING2' ? '#AAFF00' : '', marginLeft: 20, marginRight: 20 }}> 睡眠中断食</Text>
-
-                <Text style={{ color: obj.status == 'ONGOING2' ? '#AAFF00' : '' }}>
-                    {
-                        getStepBTime(obj)
-                    }
-                </Text>
-            </View>
-            <View style={{ flexDirection: 'row', display: 'flex' }}>
-                <Text>阶段C</Text>
-                <Text style={{ color: obj.status == 'ONGOING3' ? '#AAFF00' : '', marginLeft: 20, marginRight: 20 }}> 起床后断食</Text>
-                <Text style={{ color: obj.status == 'ONGOING3' ? '#AAFF00' : '' }}>
-                    {
-                        getStepCTime(obj)
-                    }
-                </Text>
-            </View>
-        </View>
-    }
-
-    //🚫❌⭕️✅
-    function statusString(isFast: boolean, isStart: boolean, data: any) {
-        if (props.type == 'latest' || props.type == 'record') {
-            if (isFast) {
-                if (data.fast.status == 'COMPLETED') {
-                    return '✅'
-                }
-            }
-            else {
-                if (data.sleep.status == 'COMPLETED') {
-                    return '✅'
-                }
-                else if (data.sleep.status == 'NOT_STARTED') {
-                    return '🚫'
-                }
-                else if (data.sleep.status == 'NOT_COMPLETED') {
-                    return isStart ? '✅' : '🚫'
-                }
-            }
-        }
-        if (value == 'WAIT_FOR_START') {
-            return '⭕️'
-        }
-        else if (value == 'ONGOING') {
-            if (isFast && isStart) {
-                return '✅'
-            }
-            else if (!isFast && isStart) {
-                return '✅'
-            }
-        }
-        else if (value == 'ONGOING1') {
-            if (isFast && isStart) {
-                return '✅'
-            }
-        }
-        else if (value == 'ONGOING2') {
-            if (isStart) {
-                return '✅'
-            }
-        }
-        else if (value == 'ONGOING3') {
-            if (isFast && !isStart) {
-                return '⭕️'
-            }
-            else {
-                return '✅'
-            }
-        }
-
-        return '⭕️'
-    }
-
-    function getStatus(isFast: boolean, isStart: boolean, data: any) {
-        if (props.type == 'latest' || props.type == 'record') {
-            if (isFast) {
-                if (data.fast.status == 'COMPLETED') {
-                    return 'done'
-                }
-            }
-            else {
-                if (data.sleep.status == 'COMPLETED') {
-                    return 'done'
-                }
-                else if (data.sleep.status == 'NOT_STARTED') {
-                    return 'un_done'
-                }
-                else if (data.sleep.status == 'NOT_COMPLETED') {
-                    return isStart ? 'done' : 'un_done'
-                }
-            }
-        }
-        if (value == 'WAIT_FOR_START') {
-            return 'padding'
-        }
-        else if (value == 'ONGOING') {
-            if (isFast && isStart) {
-                return 'done'
-            }
-            else if (!isFast && isStart) {
-                return 'done'
-            }
-        }
-        else if (value == 'ONGOING1') {
-            if (isFast && isStart) {
-                return 'done'
-            }
-        }
-        else if (value == 'ONGOING2') {
-            if (isStart) {
-                return 'done'
-            }
-        }
-        else if (value == 'ONGOING3') {
-            if (isFast && !isStart) {
-                return 'padding'
-            }
-            else {
-                return 'done'
-            }
-        }
-
-        return 'padding'
-    }
-
-    function scheduleItems(data) {
-        if (!data) {
-            return <View></View>
-        }
-        var obj = props.type == 'latest' ? (data as any).latest_record : (data as any).current_record;
-        if (props.type == 'record') {
-            obj = data//(data as any).latest_record
-        }
-
-        var timelineItems: any = [];
-        if (obj.fast) {
-            timelineItems.push(
-                {
-                    status: getStatus(true, true, obj),
-                    title: '开始断食',
-                    content: formateTime(obj.fast, false),
-                }
-            )
-        }
-        if (obj.sleep) {
-            timelineItems.push(
-                {
-                    status: getStatus(false, true, obj),
-                    title: '开始睡眠',
-                    content: formateTime(obj.sleep, false),
-                }
-            )
-        }
-        if (obj.sleep) {
-            timelineItems.push(
-                {
-                    status: getStatus(false, false, obj),
-                    title: '结束睡眠',
-                    content: formateTime(obj.sleep, true),
-                }
-            )
-        }
-        if (obj.fast) {
-            timelineItems.push(
-                {
-                    status: getStatus(true, false, obj),
-                    title: '结束断食',
-                    content: formateTime(obj.fast, true),
-                }
-            )
-        }
-
-        return <Timeline items={timelineItems} />
-
-        // return <View>
-        //     {
-        //         obj && <View style={{ flexDirection: 'column', display: 'flex' }}>
-        //             {obj.fast && <Text>{statusString(true, true, obj)}开始断食:{formateTime(obj.fast, false)}</Text>}
-        //             {obj.sleep && <Text>{statusString(false, true, obj)}开始睡眠:{formateTime(obj.sleep, false)}</Text>}
-        //             {obj.sleep && <Text>{statusString(false, false, obj)}结束睡眠:{formateTime(obj.sleep, true)}</Text>}
-        //             {obj.fast && <Text>{statusString(true, false, obj)}结束断食:{formateTime(obj.fast, true)}</Text>}
-        //         </View>
-        //     }
-        // </View>
-    }
-
-    function formateTime(obj: any, isEnd: boolean) {
-
-        if (isEnd) {
-            if (obj.real_end_time) {
-                return TimeFormatter.formatTimestamp(obj.real_end_time)
-            }
-            else {
-                return TimeFormatter.formatTimestamp(obj.target_end_time)
-            }
-        }
-        else {
-            if (obj.real_start_time) {
-                return TimeFormatter.formatTimestamp(obj.real_start_time)
-            }
-            else {
-                return TimeFormatter.formatTimestamp(obj.target_start_time)
-            }
-        }
-
-    }
-
-    function more(e) {
-        Taro.showActionSheet({
-            itemList: ['删除', '分享']
-        })
-            .then(res => {
-                console.log(res.tapIndex)
-                switch (res.tapIndex) {
-                    case 0:
-                        {
-                            del()
-                        }
-                        break;
-                }
-            })
-            .catch(err => {
-                console.log(err.errMsg)
-            })
-        e.stopPropagation()
-    }
-
-    function del() {
-        var id = props.type == 'record' ? props.data.id : (checkData as any).latest_record.id
-        delRecord(id
-        ).then(res => {
-            Taro.showToast({
-                title: '删除成功'
-            })
-            props.delSuccess && props.delSuccess(props.data)
-            // Taro.navigateBack()
-        })
-    }
+    const permission = useSelector((state: any) => state.permission);
+    const common = useSelector((state: any) => state.common);
+    const dispatch = useDispatch();
 
     function all() {
         if (props.type == 'latest') {
@@ -394,309 +28,106 @@ export default function Component(props: { type?: string, data?: any, delSuccess
         }
     }
 
-    // const common: RingCommon = {
-    //     useCase: 'Record',
-    //     radius: 50,
-    //     lineWidth: 8,
-    //     isFast: true,
-    //     status: getRecord()?getRecord().status:'WAIT_FOR_START'
-    // }
+    function showStage() {
 
-    // const common2: RingCommon = {
-    //     useCase: 'Record',
-    //     radius: 40,
-    //     lineWidth: 8,
-    //     isFast: true,
-    //     status: getRecord()?getRecord().status:'WAIT_FOR_START'
-    // }
-
-    // const bgRing: BgRing = {
-    //     color: '#262626'
-    // }
-
-    // const realRing: RealRing = {
-    //     color: '#AAFF00',
-    //     startArc: 0,
-    //     durationArc: 0
-    // }
-
-    // const realRing2: RealRing = {
-    //     color: '#00FFFF',
-    //     startArc: 0,
-    //     durationArc: 0
-    // }
-
-    // const currentDot: CurrentDot = {
-    //     color: '#AAFF00',
-    //     lineWidth: 8,
-    //     borderColor: 'black'
-    // }
-
-    // const currentDot2: CurrentDot = {
-    //     color: '#00FFFF',
-    //     lineWidth: 8,
-    //     borderColor: 'black'
-    // }
-
-    // function startArc(time: number) {
-    //     var date = new Date(time);
-    //     var hour = date.getHours();
-    //     var minute = date.getMinutes();
-    //     var second = date.getSeconds();
-    //     return (hour * 3600 + minute * 60 + second) / (24 * 3600) * 2 * Math.PI - Math.PI / 2.0;
-    // }
-
-    function durationArc(start_time: number, end_time: number) {
-        var duration = (end_time - start_time) / 1000;
-        return duration / (24 * 3600) * 2 * Math.PI;
     }
 
-    function getRecord() {
-        var detail = props.type == 'record' ? props.data : checkData
-        if (detail) {
-            var record = detail;
-            if (props.type == 'latest') {
-                record = detail.latest_record
-            }
-            else if (props.type != 'record') {
-                record = detail.current_record
-            }
+    function followWxPub() {
+        const resource = common.resources.filter((item: any) => {
+            return item.code == 'follow_wx_pub'
+        })
 
-            return record;
-        }
-        return
+        Taro.showModal({
+            title: '提示',
+            content: '关注公众号后可接收提醒\n点击确定,前往关注',
+            showCancel: true,
+            success(result) {
+                if (result.confirm) {
+                    Taro.navigateTo({
+                        url: '/pages/common/H5?title=fast16cc 关注服务号&url=' + resource[0].url,
+                    })
+                }
+            },
+        })
     }
 
-
-
-    function bigRing() {
-        var record = getRecord()
-        if (!record) return null
-
-        var common = getCommon(null, true)
-        var bgRing = getBgRing()
-
-        if (props.type == 'record' || props.type == 'latest') {
-            var realRing = getReal(record, true, true)
-            return <Rings common={common} bgRing={bgRing} canvasId={canvasId} realRing={realRing} />
-        }
-        else {
-            var currentDot1 = getDot(record, true)
-            var targetBigRing1 = getTarget(record, true)
-            if (record.status == 'ONGOING') {
-                var realRing1 = getReal(record, true, false)
-
-                return <Rings common={common} bgRing={bgRing} currentDot={currentDot1} realRing={realRing1} targetRing={targetBigRing1} canvasId={canvasId} />
+    function detailHeader() {
+        var btnStyle;
+        if (props.data.scenario == 'SLEEP') {
+            btnStyle = {
+                fontSize: 14,
+                lineHeight: 18,
+                color: '#00FFFF'
             }
-            if (record.status == 'WAIT_FOR_START') {
-                return <Rings common={common} bgRing={bgRing} currentDot={currentDot1} canvasId={canvasId} />
-            }
-            var realRing1 = getReal(record, true, false)
-            return <Rings common={common} bgRing={bgRing} realRing={realRing1} currentDot={currentDot1} targetRing={targetBigRing1} canvasId={canvasId} />
         }
-    }
-
-    function smallRing() {
-        if (!checkData) return null
-        var record = getRecord()
-        if (record.scenario == 'FAST_SLEEP') {
-            var common = getCommon(null, false)
-            var bgRing = getBgRing()
-            var realRing = getReal(record, false, false)
-            if (props.type == 'record' || props.type == 'latest') {
-                if (record.sleep.status == 'WAIT_FOR_END') {
-                    realRing.durationArc = durationArc(record.sleep.target_start_time, (new Date()).getTime())
-                    return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing} />
-                }
-                else if (record.sleep.status == 'NOT_COMPLETED') {
-                    realRing.durationArc = 0.01
-                    return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing} />
-                }
-                else if (record.sleep.status == 'COMPLETED') {
-                    realRing = getReal(record, false, true)
-                    return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing} />
-                }
-                return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} />
+        else if (props.data.scenario == 'FAST') {
+            btnStyle = {
+                fontSize: 14,
+                lineHeight: 18,
+                color: '#AAFF00'
             }
-            else {
-
-
-                var currentDot = getDot(record, false)
-                var targetRing = getTarget(record, false)
-                if (record.status == 'ONGOING2') {
-                    var realRing = getReal(record, false, false)
-                    return <Rings common={common} bgRing={bgRing} realRing={realRing} currentDot={currentDot} targetRing={targetRing} canvasId={canvasId + 'small'} />
-                }
-                if (record.status == 'ONGOING3') {
-                    currentDot.color = 'rgba(0, 255, 255, 0.5)'
-                }
-                return <Rings common={common} bgRing={bgRing} currentDot={currentDot} canvasId={canvasId + 'small'} />
+        }
+        else if (props.data.scenario == 'FAST_SLEEP') {
+            btnStyle = {
+                fontSize: 14,
+                lineHeight: 18,
+                // background: 'linear-gradient(90deg, #AAFF00 0%, #00FFFF 100%)',
+                // WebkitBackgroundClip: 'text',
+                // backgroundClip: 'text',
+                // color: 'transparent'
             }
-            // if (record.sleep.status == 'WAIT_FOR_END') {
-            //     realRing2.startArc = startArc(record.sleep.target_start_time)
-            //     realRing2.durationArc = durationArc(record.sleep.target_start_time, (new Date()).getTime())
-            //     return <Rings common={common2} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing2} />
-            // }
-            // else if (record.sleep.status == 'NOT_COMPLETED') {
-            //     realRing2.startArc = startArc(record.sleep.target_start_time)
-            //     realRing2.durationArc = 0.01
-            //     return <Rings common={common2} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing2} />
-            // }
-            // else if (record.status == 'WAIT_FOR_START') {
-            //     common2.useCase = 'Clock'
-            //     return <Rings common={common2} bgRing={bgRing} currentDot={currentDot2} canvasId={canvasId + 'small'} />
-            // }
-
-            // return <Rings common={common2} bgRing={bgRing} canvasId={canvasId + 'small'} />
         }
-        return null
-    }
-
-    function rings() {
-        return <View style={{ position: 'relative', zIndex: 1 }}>
+        return <View style={{
+            // background:LinearGradient
+            height: 40,
+            display: 'flex', flexDirection: 'row', width: '100%',
+            justifyContent: 'space-between', alignItems: 'center'
+        }}>
+            <Text>{permission.wxPubFollow ? TimeFormatter.getDateAndWeek() : '日程提醒'}</Text>
             {
-                bigRing()
+                !permission.wxPubFollow && <View >
+                    <Switch isOn={permission.wxPubFollow} onClick={() => followWxPub()} />
+                </View>
+            }
+            {
+                permission.wxPubFollow && <Buttons disabled={props.data.status != 'WAIT_FOR_START'} 
+                className={props.data.scenario == 'FAST_SLEEP'?'mixed':''}
+                btnStyle={btnStyle} type={ButtonType.text} title="调整日程" onClick={() => {
+                    if (props.data.name == 'FAST_SLEEP') {
+                        dispatch(setStep('fast'))
+                    }
+                    else if (props.data.name == 'SLEEP') {
+                        dispatch(setStep('sleep'))
+                    }
+                    else {
+                        dispatch(setStep('fast'))
+                    }
+                    Taro.navigateTo({
+                        url: '/pages/clock/SetSchedule'
+                    })
+                }} />
             }
-            <View style={{ display: 'flex', position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, alignItems: 'center', justifyContent: 'center' }}>
-                {
-                    smallRing()
-                }
-            </View>
         </View>
     }
 
-    function schedules() {
-        return scheduleItems(props.type == 'record' ? props.data : checkData)
-    }
-
     function detail() {
         return <View style={{ flexDirection: 'column', display: 'flex', alignItems: 'center', position: 'relative' }} onClick={all}>
             {
-                (props.type == 'latest' || props.type == 'record') && rings()
-            }
-            {
-                schedules()
+                detailHeader()
             }
-            {/* {
-                (props.type != 'record' && value == 'WAIT_FOR_START') && <Text onClick={editSchedule}>调整日程</Text>
-            } */}
             {
-                ((props.type == 'record' && props.data.scenario == 'FAST_SLEEP') || (props.type == 'latest' && key == 'FAST_SLEEP')) && <Text onClick={showLatest}>Durations by stage</Text>
+                <TimelineFastSleep data={props.data} />
             }
             {
-                props.type != 'record' && props.type != 'latest' && key == 'FAST_SLEEP' && (value == 'WAIT_FOR_START' ? <Text onClick={showStage}>Duration goals by stage</Text> : <Text onClick={showStage}>Current stage</Text>)
-            }
-            {/* {
-                key == 'FAST_SLEEP' && isOpen && props.type != 'record' && checkData && <Modal children={layoutContent()} dismiss={() => setIsOpen(false)} confirm={() => { }} />
-            } */}
-            {/* {
-                key == 'FAST_SLEEP' && isOpen && props.type == 'record' && props.data.scenario == 'FAST_SLEEP' && <Modal children={layoutContent()} dismiss={() => setIsOpen(false)} confirm={() => { }} />
-            } */}
-
-            {
-                props.type == 'record' && <Text style={{ position: 'absolute', right: 20, top: 20 }} onClick={more}>More</Text>
+                props.data.scenario == 'FAST_SLEEP' && (props.data.status == 'WAIT_FOR_START' ? <Text onClick={showStage}>Duration goals by stage</Text> : <Text onClick={showStage}>Current stage</Text>)
             }
 
 
         </View >
     }
 
-    function getDuration(obj) {
-        if (!obj) {
-            debugger
-        }
-        if (obj.status == 'NOT_STARTED' || obj.status == 'NOT_COMPLETED') {
-            return ''
-        }
-        var start = obj.real_start_time
-        var end = obj.real_end_time
-        if (!end) {
-            end = (new Date()).getTime()
-        }
-        return TimeFormatter.calculateTimeDifference(start, end)
-    }
-
-    function showDetail(record) {
-        if (props.type == 'latest'){
-            setShowDetailModal(true)
-            return;
-        }
-        // 
-        var node = (<Modal children={schedules()}
-            modalType={ModalType.center}
-            dismiss={() => {
-                global.showModal(false,null)
-            }}
-            confirm={() => { }} />);
-        global.showModal(true, node);
-    }
-
-    function recordDetail() {
-        var record = getRecord()
-        var fastDuration = ''
-        var sleepDuration = ''
-        if (record.scenario == 'FAST_SLEEP') {
-            fastDuration = getDuration(record.fast)
-            sleepDuration = getDuration(record.sleep)
-        }
-        else if (record.scenario == 'FAST') {
-            fastDuration = getDuration(record.fast)
-        }
-        else {
-            sleepDuration = getDuration(record.sleep)
-        }
-        return <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
-            {
-                rings()
-            }
-            <View className="duration_bg">
-                {
-                    fastDuration.length > 0 && <Text className="duration_title">断食</Text>
-                }
-                {
-                    fastDuration.length > 0 && <Text className="duration_value" style={{ color: '#AAFF00' }}>{fastDuration}</Text>
-                }
-                {
-                    sleepDuration.length > 0 && <Text className="duration_title">睡眠</Text>
-                }
-                {
-                    sleepDuration.length > 0 && <Text className="duration_value" style={{ color: '#00FFFF' }}>{sleepDuration}</Text>
-                }
-            </View>
-            <Image className="arrow1" src={require('@/assets/images/arrow.png')} />
-        </View>
-    }
-
-    function header() {
-        if (props.type == 'latest') {
-            return <Header title="最近记录" action={() => {
-                Taro.navigateTo({
-                    url: '/pages/common/RecordsHistory?type=time&title=time'
-                })
-            }} />
-        }
-        return null
-    }
-
-    if (props.type == 'record' || props.type == 'latest') {
-        var record = getRecord()
-        if (!record) return <View />
-        return <Box header={header()}>
-            <RecordItem canDel={record.status == 'COMPLETED'} delete={del}
-                onClick={() => { showDetail(record) }}
-            >{recordDetail()}
-            </RecordItem>
-            {
-                showDetailModal && <Modal children={schedules()}
-                    modalType={ModalType.center}
-                    dismiss={() => setShowDetailModal(false)}
-                    confirm={() => { }} />
-            }
-        </Box>
-        // return <RecordItem canDel={record.status == 'COMPLETED'} delete={del}>{detail()}</RecordItem>
-    }
 
-    return <Box title={t('page.clock.schedule.title')}>
+    return <Box>
         {
             detail()
         }

+ 697 - 0
src/features/trackTimeDuration/components/Schedule_backup.tsx

@@ -0,0 +1,697 @@
+import { View, Text, Image } from "@tarojs/components";
+import trackTimeService, { machine } from "@/store/trackTimeMachine"
+import { useEffect, useState } from "react";
+import Taro from "@tarojs/taro";
+import { TimeFormatter } from "@/utils/time_format";
+// import "taro-ui/dist/style/components/float-layout.scss";
+import { delRecord } from "@/services/trackTimeDuration";
+import Modal from "@/components/layout/Modal";
+import Rings, { BgRing, CurrentDot, RealRing, RingCommon } from './Rings';
+import { getBgRing, getCommon, getDot, getReal, getTarget } from "../hooks/RingData";
+import Timeline from "@/components/view/Timeline";
+import RecordItem from "@/features/common/RecordItem";
+import Box from "@/components/layout/Box";
+import './Schedule.scss'
+import { ModalType } from "@/utils/types";
+import Header from "@/components/layout/Header";
+import { useTranslation } from "react-i18next";
+
+
+export default function Component(props: { type?: string, data?: any, delSuccess?: Function }) {
+    const [checkData, setCheckData] = useState(null)
+    const { t } = useTranslation()
+    const [key, setKey] = useState('');
+    const [value, setValue] = useState('');
+    const [isOpen, setIsOpen] = useState(false);
+    const [isLatest, setIsLatest] = useState(props.type == 'latest');
+    const [showDetailModal, setShowDetailModal] = useState(false)
+    const canvasId = props.type == 'latest' ? 'latest' : props.type == 'record' ? props.data.id : 'current'
+
+    useEffect(() => {
+        getStateDetail();
+    }, [machine.context.currentStatus])
+
+    useEffect(() => {
+        if (machine.context.checkData) {
+            setCheckData(machine.context.checkData as any);
+        }
+        getStateDetail();
+    }, [machine.context.checkData]);
+    useEffect(() => {
+        trackTimeService.onTransition(state => {
+            getStateDetail();
+        });
+    }, []);
+
+
+    function getStateDetail() {
+        if (props.type == 'latest') {
+            if (machine.context.checkData) {
+                setKey((machine.context.checkData as any).latest_record.scenario);
+                setValue((machine.context.checkData as any).latest_record.status);
+            }
+            return
+        }
+
+        var state = trackTimeService.getSnapshot().value
+        if ((state as any).FAST_SLEEP) {
+            setKey('FAST_SLEEP');
+            setValue((state as any).FAST_SLEEP);
+        }
+        if ((state as any).FAST) {
+            setKey('FAST');
+            setValue((state as any).FAST);
+        }
+        if ((state as any).SLEEP) {
+            setKey('SLEEP');
+            setValue((state as any).SLEEP);
+        }
+
+    }
+
+    function editSchedule() {
+        Taro.navigateTo({
+            url: '/pages/clock/SetSchedule'
+        })
+    }
+
+    function showStage(e) {
+        setIsLatest(false);
+        setIsOpen(true)
+        debugger
+        e.stopPropagation()
+    }
+
+    function showLatest(e) {
+        // startTimer();
+        setIsLatest(true)
+        setIsOpen(true)
+        debugger
+        e.stopPropagation()
+    }
+
+    function getTime(t1: number, t2: number) {
+        return TimeFormatter.calculateTimeDifference(t1, t2)
+    }
+
+
+
+    function getStepATime(obj) {
+        if (obj.status == 'COMPLETED' && obj.sleep.status == 'NOT_STARTED') {
+            return '未知'
+        }
+        return obj.status == 'ONGOING1' ?
+            getTime(obj.fast.real_start_time, (new Date()).getTime()) :
+            obj.sleep.real_start_time ? getTime(obj.sleep.real_start_time, obj.fast.real_start_time ? obj.fast.real_start_time : obj.fast.target_start_time) :
+                getTime(obj.sleep.target_start_time, obj.fast.real_start_time ? obj.fast.real_start_time : obj.fast.target_start_time)
+    }
+
+    function getStepBTime(obj) {
+        if (obj.status == 'ONGOING1') return 'Next up'
+        if (obj.status == 'ONGOING2') return getTime(obj.sleep.real_start_time, (new Date()).getTime())
+        if (obj.status == 'WAIT_FOR_START') return getTime(obj.sleep.target_end_time, obj.sleep.target_start_time)
+        if (obj.sleep.status == 'NOT_COMPLETED' || obj.sleep.status == 'NOT_STARTED') return '未知'
+        return getTime(obj.sleep.real_end_time, obj.sleep.real_start_time)
+
+    }
+
+    function getStepCTime(obj) {
+        if (obj.status == 'ONGOING1') return 'Final stage'
+        if (obj.status == 'ONGOING2') return 'Next up'
+        if (obj.status == 'ONGOING3') return getTime(obj.sleep.real_end_time, (new Date()).getTime())
+        if (obj.status == 'WAIT_FOR_START') return getTime(obj.fast.target_end_time, obj.sleep.target_end_time)
+        if (obj.sleep.status == 'NOT_COMPLETED' || obj.sleep.status == 'NOT_STARTED') return '未知'
+        return getTime(obj.fast.real_end_time, obj.sleep.real_end_time)
+    }
+
+    function layoutContent() {
+        debugger
+        //当前断食阶段
+        var obj = isLatest ? (checkData as any).latest_record : (checkData as any).current_record
+        if (props.type == 'record') {
+            obj = props.data
+        }
+        return <View style={{ flexDirection: 'column', display: 'flex', color: '#000', backgroundColor: '#fff', paddingTop: 50, paddingBottom: 50, position: 'relative' }}>
+            <Text style={{ position: 'absolute', top: 5, right: 20 }} onClick={() => setIsOpen(false)}>关闭</Text>
+            {
+                obj.status == 'WAIT_FOR_START' ? <Text>断食阶段目标</Text> :
+                    obj.status == 'COMPLETED' ? <Text>断食阶段</Text> :
+                        <Text>当前断食阶段</Text>
+            }
+            <View style={{ flexDirection: 'row', display: 'flex' }}>
+                <Text>阶段A</Text>
+                <Text style={{ color: obj.status == 'ONGOING1' ? '#AAFF00' : '', marginLeft: 20, marginRight: 20 }}> 睡前断食</Text>
+                <Text style={{ color: obj.status == 'ONGOING1' ? '#AAFF00' : '' }}> {
+                    getStepATime(obj)
+                }</Text>
+            </View>
+            <View style={{ flexDirection: 'row', display: 'flex' }}>
+                <Text>阶段B</Text>
+                <Text style={{ color: obj.status == 'ONGOING2' ? '#AAFF00' : '', marginLeft: 20, marginRight: 20 }}> 睡眠中断食</Text>
+
+                <Text style={{ color: obj.status == 'ONGOING2' ? '#AAFF00' : '' }}>
+                    {
+                        getStepBTime(obj)
+                    }
+                </Text>
+            </View>
+            <View style={{ flexDirection: 'row', display: 'flex' }}>
+                <Text>阶段C</Text>
+                <Text style={{ color: obj.status == 'ONGOING3' ? '#AAFF00' : '', marginLeft: 20, marginRight: 20 }}> 起床后断食</Text>
+                <Text style={{ color: obj.status == 'ONGOING3' ? '#AAFF00' : '' }}>
+                    {
+                        getStepCTime(obj)
+                    }
+                </Text>
+            </View>
+        </View>
+    }
+
+    //🚫❌⭕️✅
+    function statusString(isFast: boolean, isStart: boolean, data: any) {
+        if (props.type == 'latest' || props.type == 'record') {
+            if (isFast) {
+                if (data.fast.status == 'COMPLETED') {
+                    return '✅'
+                }
+            }
+            else {
+                if (data.sleep.status == 'COMPLETED') {
+                    return '✅'
+                }
+                else if (data.sleep.status == 'NOT_STARTED') {
+                    return '🚫'
+                }
+                else if (data.sleep.status == 'NOT_COMPLETED') {
+                    return isStart ? '✅' : '🚫'
+                }
+            }
+        }
+        if (value == 'WAIT_FOR_START') {
+            return '⭕️'
+        }
+        else if (value == 'ONGOING') {
+            if (isFast && isStart) {
+                return '✅'
+            }
+            else if (!isFast && isStart) {
+                return '✅'
+            }
+        }
+        else if (value == 'ONGOING1') {
+            if (isFast && isStart) {
+                return '✅'
+            }
+        }
+        else if (value == 'ONGOING2') {
+            if (isStart) {
+                return '✅'
+            }
+        }
+        else if (value == 'ONGOING3') {
+            if (isFast && !isStart) {
+                return '⭕️'
+            }
+            else {
+                return '✅'
+            }
+        }
+
+        return '⭕️'
+    }
+
+    function getStatus(isFast: boolean, isStart: boolean, data: any) {
+        if (props.type == 'latest' || props.type == 'record') {
+            if (isFast) {
+                if (data.fast.status == 'COMPLETED') {
+                    return 'done'
+                }
+            }
+            else {
+                if (data.sleep.status == 'COMPLETED') {
+                    return 'done'
+                }
+                else if (data.sleep.status == 'NOT_STARTED') {
+                    return 'un_done'
+                }
+                else if (data.sleep.status == 'NOT_COMPLETED') {
+                    return isStart ? 'done' : 'un_done'
+                }
+            }
+        }
+        if (value == 'WAIT_FOR_START') {
+            return 'padding'
+        }
+        else if (value == 'ONGOING') {
+            if (isFast && isStart) {
+                return 'done'
+            }
+            else if (!isFast && isStart) {
+                return 'done'
+            }
+        }
+        else if (value == 'ONGOING1') {
+            if (isFast && isStart) {
+                return 'done'
+            }
+        }
+        else if (value == 'ONGOING2') {
+            if (isStart) {
+                return 'done'
+            }
+        }
+        else if (value == 'ONGOING3') {
+            if (isFast && !isStart) {
+                return 'padding'
+            }
+            else {
+                return 'done'
+            }
+        }
+
+        return 'padding'
+    }
+
+    function scheduleItems(data) {
+        if (!data) {
+            return <View></View>
+        }
+        var obj = props.type == 'latest' ? (data as any).latest_record : (data as any).current_record;
+        if (props.type == 'record') {
+            obj = data//(data as any).latest_record
+        }
+
+        var timelineItems: any = [];
+        if (obj.fast) {
+            timelineItems.push(
+                {
+                    status: getStatus(true, true, obj),
+                    title: '开始断食',
+                    content: formateTime(obj.fast, false),
+                }
+            )
+        }
+        if (obj.sleep) {
+            timelineItems.push(
+                {
+                    status: getStatus(false, true, obj),
+                    title: '开始睡眠',
+                    content: formateTime(obj.sleep, false),
+                }
+            )
+        }
+        if (obj.sleep) {
+            timelineItems.push(
+                {
+                    status: getStatus(false, false, obj),
+                    title: '结束睡眠',
+                    content: formateTime(obj.sleep, true),
+                }
+            )
+        }
+        if (obj.fast) {
+            timelineItems.push(
+                {
+                    status: getStatus(true, false, obj),
+                    title: '结束断食',
+                    content: formateTime(obj.fast, true),
+                }
+            )
+        }
+
+        return <Timeline items={timelineItems} />
+
+        // return <View>
+        //     {
+        //         obj && <View style={{ flexDirection: 'column', display: 'flex' }}>
+        //             {obj.fast && <Text>{statusString(true, true, obj)}开始断食:{formateTime(obj.fast, false)}</Text>}
+        //             {obj.sleep && <Text>{statusString(false, true, obj)}开始睡眠:{formateTime(obj.sleep, false)}</Text>}
+        //             {obj.sleep && <Text>{statusString(false, false, obj)}结束睡眠:{formateTime(obj.sleep, true)}</Text>}
+        //             {obj.fast && <Text>{statusString(true, false, obj)}结束断食:{formateTime(obj.fast, true)}</Text>}
+        //         </View>
+        //     }
+        // </View>
+    }
+
+    function formateTime(obj: any, isEnd: boolean) {
+
+        if (isEnd) {
+            if (obj.real_end_time) {
+                return TimeFormatter.formatTimestamp(obj.real_end_time)
+            }
+            else {
+                return TimeFormatter.formatTimestamp(obj.target_end_time)
+            }
+        }
+        else {
+            if (obj.real_start_time) {
+                return TimeFormatter.formatTimestamp(obj.real_start_time)
+            }
+            else {
+                return TimeFormatter.formatTimestamp(obj.target_start_time)
+            }
+        }
+
+    }
+
+    function more(e) {
+        Taro.showActionSheet({
+            itemList: ['删除', '分享']
+        })
+            .then(res => {
+                console.log(res.tapIndex)
+                switch (res.tapIndex) {
+                    case 0:
+                        {
+                            del()
+                        }
+                        break;
+                }
+            })
+            .catch(err => {
+                console.log(err.errMsg)
+            })
+        e.stopPropagation()
+    }
+
+    function del() {
+        var id = props.type == 'record' ? props.data.id : (checkData as any).latest_record.id
+        delRecord(id
+        ).then(res => {
+            Taro.showToast({
+                title: '删除成功'
+            })
+            props.delSuccess && props.delSuccess(props.data)
+            // Taro.navigateBack()
+        })
+    }
+
+    function all() {
+        if (props.type == 'latest') {
+            Taro.navigateTo({
+                url: '/pages/common/RecordsHistory?type=time&title=Time'
+            })
+        }
+    }
+
+    // const common: RingCommon = {
+    //     useCase: 'Record',
+    //     radius: 50,
+    //     lineWidth: 8,
+    //     isFast: true,
+    //     status: getRecord()?getRecord().status:'WAIT_FOR_START'
+    // }
+
+    // const common2: RingCommon = {
+    //     useCase: 'Record',
+    //     radius: 40,
+    //     lineWidth: 8,
+    //     isFast: true,
+    //     status: getRecord()?getRecord().status:'WAIT_FOR_START'
+    // }
+
+    // const bgRing: BgRing = {
+    //     color: '#262626'
+    // }
+
+    // const realRing: RealRing = {
+    //     color: '#AAFF00',
+    //     startArc: 0,
+    //     durationArc: 0
+    // }
+
+    // const realRing2: RealRing = {
+    //     color: '#00FFFF',
+    //     startArc: 0,
+    //     durationArc: 0
+    // }
+
+    // const currentDot: CurrentDot = {
+    //     color: '#AAFF00',
+    //     lineWidth: 8,
+    //     borderColor: 'black'
+    // }
+
+    // const currentDot2: CurrentDot = {
+    //     color: '#00FFFF',
+    //     lineWidth: 8,
+    //     borderColor: 'black'
+    // }
+
+    // function startArc(time: number) {
+    //     var date = new Date(time);
+    //     var hour = date.getHours();
+    //     var minute = date.getMinutes();
+    //     var second = date.getSeconds();
+    //     return (hour * 3600 + minute * 60 + second) / (24 * 3600) * 2 * Math.PI - Math.PI / 2.0;
+    // }
+
+    function durationArc(start_time: number, end_time: number) {
+        var duration = (end_time - start_time) / 1000;
+        return duration / (24 * 3600) * 2 * Math.PI;
+    }
+
+    function getRecord() {
+        var detail = props.type == 'record' ? props.data : checkData
+        if (detail) {
+            var record = detail;
+            if (props.type == 'latest') {
+                record = detail.latest_record
+            }
+            else if (props.type != 'record') {
+                record = detail.current_record
+            }
+
+            return record;
+        }
+        return
+    }
+
+
+
+    function bigRing() {
+        var record = getRecord()
+        if (!record) return null
+
+        var common = getCommon(null, true)
+        var bgRing = getBgRing()
+
+        if (props.type == 'record' || props.type == 'latest') {
+            var realRing = getReal(record, true, true)
+            return <Rings common={common} bgRing={bgRing} canvasId={canvasId} realRing={realRing} />
+        }
+        else {
+            var currentDot1 = getDot(record, true)
+            var targetBigRing1 = getTarget(record, true)
+            if (record.status == 'ONGOING') {
+                var realRing1 = getReal(record, true, false)
+
+                return <Rings common={common} bgRing={bgRing} currentDot={currentDot1} realRing={realRing1} targetRing={targetBigRing1} canvasId={canvasId} />
+            }
+            if (record.status == 'WAIT_FOR_START') {
+                return <Rings common={common} bgRing={bgRing} currentDot={currentDot1} canvasId={canvasId} />
+            }
+            var realRing1 = getReal(record, true, false)
+            return <Rings common={common} bgRing={bgRing} realRing={realRing1} currentDot={currentDot1} targetRing={targetBigRing1} canvasId={canvasId} />
+        }
+    }
+
+    function smallRing() {
+        if (!checkData) return null
+        var record = getRecord()
+        if (record.scenario == 'FAST_SLEEP') {
+            var common = getCommon(null, false)
+            var bgRing = getBgRing()
+            var realRing = getReal(record, false, false)
+            if (props.type == 'record' || props.type == 'latest') {
+                if (record.sleep.status == 'WAIT_FOR_END') {
+                    realRing.durationArc = durationArc(record.sleep.target_start_time, (new Date()).getTime())
+                    return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing} />
+                }
+                else if (record.sleep.status == 'NOT_COMPLETED') {
+                    realRing.durationArc = 0.01
+                    return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing} />
+                }
+                else if (record.sleep.status == 'COMPLETED') {
+                    realRing = getReal(record, false, true)
+                    return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing} />
+                }
+                return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} />
+            }
+            else {
+
+
+                var currentDot = getDot(record, false)
+                var targetRing = getTarget(record, false)
+                if (record.status == 'ONGOING2') {
+                    var realRing = getReal(record, false, false)
+                    return <Rings common={common} bgRing={bgRing} realRing={realRing} currentDot={currentDot} targetRing={targetRing} canvasId={canvasId + 'small'} />
+                }
+                if (record.status == 'ONGOING3') {
+                    currentDot.color = 'rgba(0, 255, 255, 0.5)'
+                }
+                return <Rings common={common} bgRing={bgRing} currentDot={currentDot} canvasId={canvasId + 'small'} />
+            }
+            // if (record.sleep.status == 'WAIT_FOR_END') {
+            //     realRing2.startArc = startArc(record.sleep.target_start_time)
+            //     realRing2.durationArc = durationArc(record.sleep.target_start_time, (new Date()).getTime())
+            //     return <Rings common={common2} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing2} />
+            // }
+            // else if (record.sleep.status == 'NOT_COMPLETED') {
+            //     realRing2.startArc = startArc(record.sleep.target_start_time)
+            //     realRing2.durationArc = 0.01
+            //     return <Rings common={common2} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing2} />
+            // }
+            // else if (record.status == 'WAIT_FOR_START') {
+            //     common2.useCase = 'Clock'
+            //     return <Rings common={common2} bgRing={bgRing} currentDot={currentDot2} canvasId={canvasId + 'small'} />
+            // }
+
+            // return <Rings common={common2} bgRing={bgRing} canvasId={canvasId + 'small'} />
+        }
+        return null
+    }
+
+    function rings() {
+        return <View style={{ position: 'relative', zIndex: 1 }}>
+            {
+                bigRing()
+            }
+            <View style={{ display: 'flex', position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, alignItems: 'center', justifyContent: 'center' }}>
+                {
+                    smallRing()
+                }
+            </View>
+        </View>
+    }
+
+    function schedules() {
+        return scheduleItems(props.type == 'record' ? props.data : checkData)
+    }
+
+    function detail() {
+        return <View style={{ flexDirection: 'column', display: 'flex', alignItems: 'center', position: 'relative' }} onClick={all}>
+            {
+                (props.type == 'latest' || props.type == 'record') && rings()
+            }
+            {
+                schedules()
+            }
+            {
+                ((props.type == 'record' && props.data.scenario == 'FAST_SLEEP') || (props.type == 'latest' && key == 'FAST_SLEEP')) && <Text onClick={showLatest}>Durations by stage</Text>
+            }
+            {
+                props.type != 'record' && props.type != 'latest' && key == 'FAST_SLEEP' && (value == 'WAIT_FOR_START' ? <Text onClick={showStage}>Duration goals by stage</Text> : <Text onClick={showStage}>Current stage</Text>)
+            }
+
+            {
+                props.type == 'record' && <Text style={{ position: 'absolute', right: 20, top: 20 }} onClick={more}>More</Text>
+            }
+
+
+        </View >
+    }
+
+    function getDuration(obj) {
+        if (!obj) {
+            debugger
+        }
+        if (obj.status == 'NOT_STARTED' || obj.status == 'NOT_COMPLETED') {
+            return ''
+        }
+        var start = obj.real_start_time
+        var end = obj.real_end_time
+        if (!end) {
+            end = (new Date()).getTime()
+        }
+        return TimeFormatter.calculateTimeDifference(start, end)
+    }
+
+    function showDetail(record) {
+        if (props.type == 'latest') {
+            setShowDetailModal(true)
+            return;
+        }
+        // 
+        var node = (<Modal children={schedules()}
+            modalType={ModalType.center}
+            dismiss={() => {
+                global.showModal(false, null)
+            }}
+            confirm={() => { }} />);
+        global.showModal(true, node);
+    }
+
+    function recordDetail() {
+        var record = getRecord()
+        var fastDuration = ''
+        var sleepDuration = ''
+        if (record.scenario == 'FAST_SLEEP') {
+            fastDuration = getDuration(record.fast)
+            sleepDuration = getDuration(record.sleep)
+        }
+        else if (record.scenario == 'FAST') {
+            fastDuration = getDuration(record.fast)
+        }
+        else {
+            sleepDuration = getDuration(record.sleep)
+        }
+        return <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
+            {
+                rings()
+            }
+            <View className="duration_bg">
+                {
+                    fastDuration.length > 0 && <Text className="duration_title">断食</Text>
+                }
+                {
+                    fastDuration.length > 0 && <Text className="duration_value" style={{ color: '#AAFF00' }}>{fastDuration}</Text>
+                }
+                {
+                    sleepDuration.length > 0 && <Text className="duration_title">睡眠</Text>
+                }
+                {
+                    sleepDuration.length > 0 && <Text className="duration_value" style={{ color: '#00FFFF' }}>{sleepDuration}</Text>
+                }
+            </View>
+            <Image className="arrow1" src={require('@/assets/images/arrow.png')} />
+        </View>
+    }
+
+    function header() {
+        if (props.type == 'latest') {
+            return <Header title="最近记录" action={() => {
+                Taro.navigateTo({
+                    url: '/pages/common/RecordsHistory?type=time&title=time'
+                })
+            }} />
+        }
+        return null
+    }
+
+    if (props.type == 'record' || props.type == 'latest') {
+        var record = getRecord()
+        if (!record) return <View />
+        return <Box header={header()}>
+            <RecordItem canDel={record.status == 'COMPLETED'} delete={del}
+                onClick={() => { showDetail(record) }}
+            >{recordDetail()}
+            </RecordItem>
+            {
+                showDetailModal && <Modal children={schedules()}
+                    modalType={ModalType.center}
+                    dismiss={() => setShowDetailModal(false)}
+                    confirm={() => { }} />
+            }
+        </Box>
+        // return <RecordItem canDel={record.status == 'COMPLETED'} delete={del}>{detail()}</RecordItem>
+    }
+
+    return <Box title={t('page.clock.schedule.title')}>
+        {
+            detail()
+        }
+    </Box>
+
+
+}

+ 28 - 0
src/features/trackTimeDuration/components/TimelineFastSleep.scss

@@ -0,0 +1,28 @@
+.box{
+    margin-left: 32px;
+    margin-right: 32px;
+    background: #1C1C1C;
+    border-radius: 56px;
+    display: flex;
+    flex-direction: column;
+    height: 1000px;
+}
+
+.header{
+    margin-top: 40px;
+    display: flex;
+    flex-direction: row;
+}
+
+.item{
+    display: flex;
+    flex: 1;
+    align-items: center;
+    justify-content: center;
+}
+
+.duration{
+    font-size: 48px;
+    margin-bottom: 40px;
+    text-align: center;
+}

+ 67 - 0
src/features/trackTimeDuration/components/TimelineFastSleep.tsx

@@ -0,0 +1,67 @@
+import Timeline from "@/components/view/Timeline";
+import { TimeFormatter } from "@/utils/time_format";
+import { View } from "@tarojs/components";
+import getStatus from "../hooks/Record";
+
+export default function TimelineFastSleep(props: { data: any,title?:string }) {
+
+    function formateTime(obj: any, isEnd: boolean) {
+        if (isEnd) {
+            if (obj.real_end_time) {
+                return TimeFormatter.formatTimestamp(obj.real_end_time)
+            }
+            else {
+                return TimeFormatter.formatTimestamp(obj.target_end_time)
+            }
+        }
+        else {
+            if (obj.real_start_time) {
+                return TimeFormatter.formatTimestamp(obj.real_start_time)
+            }
+            else {
+                return TimeFormatter.formatTimestamp(obj.target_start_time)
+            }
+        }
+
+    }
+
+    var timelineItems: any = [];
+    if (props.data.fast) {
+        timelineItems.push(
+            {
+                status: getStatus(true, true, props.data),
+                title: '开始断食',
+                content: formateTime(props.data.fast, false),
+            }
+        )
+    }
+    if (props.data.sleep) {
+        timelineItems.push(
+            {
+                status: getStatus(false, true, props.data),
+                title: '开始睡眠',
+                content: formateTime(props.data.sleep, false),
+            }
+        )
+    }
+    if (props.data.sleep) {
+        timelineItems.push(
+            {
+                status: getStatus(false, false, props.data),
+                title: '结束睡眠',
+                content: formateTime(props.data.sleep, true),
+            }
+        )
+    }
+    if (props.data.fast) {
+        timelineItems.push(
+            {
+                status: getStatus(true, false, props.data),
+                title: '结束断食',
+                content: formateTime(props.data.fast, true),
+            }
+        )
+    }
+
+    return <Timeline items={timelineItems} title={props.title}/>
+}

+ 27 - 0
src/features/trackTimeDuration/hooks/Console.tsx

@@ -91,4 +91,31 @@ export const durationTime = (start: string, end: string) => {
     // leftHour = leftHour < 1 ? 1 : leftHour
     // leftHour = leftHour > 23 ? 23 : leftHour
     return [leftHour, leftMinute]
+}
+
+export const getTitle = (data)=>{
+    if (data.scenario == 'FAST'){
+        if (data.status == 'WAIT_FOR_START'){
+            return '开始断食'
+        } 
+        return '结束断食'
+    }
+    else if (data.scenario == 'SLEEP'){
+        if (data.status == 'WAIT_FOR_START'){
+            return '开始睡眠'
+        } 
+        return '结束睡眠'
+    }
+    else {
+        if (data.status == 'WAIT_FOR_START'){
+            return '开始断食'
+        } 
+        else if (data.status == 'ONGOING1'){
+            return '开始睡眠'
+        }
+        else if (data.state == 'ONGOING2'){
+            return '结束睡眠'
+        }
+        return '结束睡眠'
+    }
 }

+ 77 - 0
src/features/trackTimeDuration/hooks/Record.tsx

@@ -0,0 +1,77 @@
+export default function getStatus(isFast: boolean, isStart: boolean, data: any) {
+    if (isFast) {
+        if (data.fast.status == 'COMPLETED') {
+            return 'done'
+        }
+        else if (data.fast.status == 'NOT_STARTED') {
+            return 'un_done'
+        }
+        else if (data.fast.status == 'NOT_COMPLETED') {
+            return isStart ? 'done' : 'un_done'
+        }
+        else if (data.fast.status == 'WAIT_FOR_END') {
+            return isStart ? 'done' : 'padding'
+        }
+    }
+    else {
+        if (data.sleep.status == 'COMPLETED') {
+            return 'done'
+        }
+        else if (data.sleep.status == 'NOT_STARTED') {
+            return 'un_done'
+        }
+        else if (data.sleep.status == 'NOT_COMPLETED') {
+            return isStart ? 'done' : 'un_done'
+        }
+        else if (data.sleep.status == 'WAIT_FOR_END') {
+            return isStart ? 'done' : 'padding'
+        }
+    }
+    // if (isFast) {
+    //     if (data.fast.status == 'COMPLETED') {
+    //         return 'done'
+    //     }
+    // }
+    // else {
+    //     if (data.sleep.status == 'COMPLETED') {
+    //         return 'done'
+    //     }
+    //     else if (data.sleep.status == 'NOT_STARTED') {
+    //         return 'un_done'
+    //     }
+    //     else if (data.sleep.status == 'NOT_COMPLETED') {
+    //         return isStart ? 'done' : 'un_done'
+    //     }
+    // }
+    // if (value == 'WAIT_FOR_START') {
+    //     return 'padding'
+    // }
+    // else if (value == 'ONGOING') {
+    //     if (isFast && isStart) {
+    //         return 'done'
+    //     }
+    //     else if (!isFast && isStart) {
+    //         return 'done'
+    //     }
+    // }
+    // else if (value == 'ONGOING1') {
+    //     if (isFast && isStart) {
+    //         return 'done'
+    //     }
+    // }
+    // else if (value == 'ONGOING2') {
+    //     if (isStart) {
+    //         return 'done'
+    //     }
+    // }
+    // else if (value == 'ONGOING3') {
+    //     if (isFast && !isStart) {
+    //         return 'padding'
+    //     }
+    //     else {
+    //         return 'done'
+    //     }
+    // }
+
+    return 'padding'
+}

+ 16 - 9
src/pages/account/Profile.scss

@@ -1,4 +1,4 @@
-.card{
+.card {
     display: flex;
     flex-direction: column;
     padding-left: 40px;
@@ -15,11 +15,18 @@
     position: relative;
 }
 
-.profile_card{
+.profile_card {
+    display: flex;
+    flex-direction: column;
     align-items: center;
 }
 
-.avatar{
+.balance {
+    display: flex;
+    flex-direction: column;
+}
+
+.avatar {
     width: 180px;
     height: 180px;
     border-radius: 90px;
@@ -30,12 +37,12 @@
 
 }
 
-.avatar_placeholder{
+.avatar_placeholder {
     width: 100px;
     height: 100px;
 }
 
-.nickname{
+.nickname {
     font-size: 40px;
     color: #fff;
     margin-top: 24px;
@@ -43,7 +50,7 @@
     height: 40px;
 }
 
-.username{
+.username {
     color: #9E9E9E;
     font-size: 28px;
     line-height: 32px;
@@ -51,18 +58,18 @@
     margin-top: 10px;
 }
 
-.title{
+.title {
     font-size: 28px;
     line-height: 28px;
     color: #fff;
 
 }
 
-.desc{
+.desc {
     margin-top: 20px;
     color: #FFFFFF;
     opacity: 0.4;
     font-size: 24px;
     line-height: 32px;
-    
+
 }

+ 25 - 15
src/pages/account/Profile.tsx

@@ -5,6 +5,8 @@ import { View, Text, Image } from "@tarojs/components";
 import Taro, { useDidShow } from "@tarojs/taro";
 import { useDispatch, useSelector } from "react-redux";
 import './Profile.scss'
+import Box from "@/components/layout/Box";
+import { BoxType } from "@/utils/types";
 
 export default function Page() {
     const dispatch = useDispatch();
@@ -66,22 +68,30 @@ export default function Page() {
 
     return <View className="container">
         <View style={{ height: 20 }} />
-        <View className="profile_card card" onClick={tapProfile}>
-            <View className="avatar" style={{ opacity: user.isLogin ? 1 : 0.4 }}>
-                {
-                    user.isLogin ? <Image src={user.avatar} className="avatar" /> : <Image src={require('@/assets/images/user.png')} className="avatar_placeholder" />
-                }
+        <Box type={BoxType.outline}>
+            <View className="profile_card" onClick={tapProfile}>
+                <View className="avatar" style={{ opacity: user.isLogin ? 1 : 0.4 }}>
+                    {
+                        user.isLogin ? <Image src={user.avatar} className="avatar" /> : <Image src={require('@/assets/images/user.png')} className="avatar_placeholder" />
+                    }
+                </View>
+                <Text className="nickname">{user.isLogin ? user.nickname : '未登录'}</Text>
+                <Text className="username">{user.isLogin ? '用户名未设置' : ''}</Text>
+            </View>
+        </Box>
+
+        <Box type={BoxType.outline}>
+            <View className="balance" onClick={tapBalance}>
+                <Text className="title">逆龄石</Text>
+                <Text className="desc">{'会员体系升级中,期间指标记录限时免逆龄石记录\n敬请期待'}</Text>
             </View>
-            <Text className="nickname">{user.isLogin ? user.nickname : '未登录'}</Text>
-            <Text className="username">{user.isLogin ? '用户名未设置' : ''}</Text>
-        </View>
-        <View className="card" onClick={tapBalance}>
-            <Text className="title">逆龄石</Text>
-            <Text className="desc">{'会员体系升级中,期间指标记录限时免逆龄石记录\n敬请期待'}</Text>
-        </View>
-        {user.isLogin && <View className="card" onClick={goSetting}>
-            <Text className="title">设置</Text>
-        </View>}
+        </Box>
+        {user.isLogin && <Box type={BoxType.outline}>
+            <View onClick={goSetting}>
+                <Text className="title">设置</Text>
+            </View>
+        </Box>
+        }
         {
             user.isLogin && user.test_user && <Text>用户名:{user.nickname}</Text>
         }

+ 13 - 0
src/pages/clock/Clock.scss

@@ -22,4 +22,17 @@
     justify-content: center;
     align-items: center;
     background-color: rgba($color: #000000, $alpha: 0.5);
+  }
+  .clock_bg{
+    width: 578px;
+    height: 578px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .swiperItem{
+    // height: 300px !important;
+    // height: auto !important;
+    // overflow: visible !important;
   }

+ 41 - 10
src/pages/clock/Clock.tsx

@@ -1,5 +1,5 @@
 import { Component, PropsWithChildren, useEffect, useRef, useState } from 'react'
-import { View, Text, Button, Input, Picker } from '@tarojs/components'
+import { View, Text, Button, Input, Picker, Swiper, SwiperItem } from '@tarojs/components'
 import '../index/index.scss'
 import './Clock.scss'
 import Taro, { useDidShow, useReady, useRouter } from '@tarojs/taro'
@@ -25,6 +25,8 @@ import { setWXFollow } from '@/store/permission';
 import Tooltip from '@/components/view/Tooltip'
 import RequestType, { thirdPartRequest } from '@/services/thirdPartRequest'
 import { setConfigs } from '@/store/common'
+import RecordFastSleep from '@/features/trackTimeDuration/components/RecordFastSleep'
+import Box from '@/components/layout/Box'
 // import TabBar from '../../components/Tabbar';
 
 export default function IndexPage() {
@@ -271,11 +273,19 @@ export default function IndexPage() {
     }
 
     // if ((checkData as any).current_record.scenario == 'FAST_SLEEP') {
-    return <Schedule />
+    return <Schedule data={(checkData as any).current_record} />
     // }
     // return <View />
   }
 
+  function needSwiper() {
+    var isNeed = checkData &&
+      (checkData as any).current_record &&
+      (checkData as any).current_record.scenario == 'FAST_SLEEP' &&
+      (checkData as any).current_record.status == 'WAIT_FOR_START'
+    return isNeed
+  }
+
   return (
     <View style={{ flex: 1, flexDirection: 'column', display: 'flex', backgroundColor: '#000', color: '#fff' }}>
       {
@@ -283,23 +293,44 @@ export default function IndexPage() {
       }
 
       <TitleBar />
-      <Clocks />
-      <View className='console_box'>
-        <Console />
-      </View>
+      <Box>
+        <View className='clock_bg'>
+          <Clocks />
+        </View>
+
+      </Box>
 
-      <More ref={global.moreRef} />
       {
-        !permission.wxPubFollow && user.isLogin && <Text style={{ textAlign: 'center', width: '100%' }} onClick={() => followWxPub()}>去关注公众号</Text>
+        needSwiper() ? <Swiper style={{ flexShrink: 0, display: 'flex', height: 173 }} indicatorColor='#999'
+          indicatorActiveColor='#333'
+          indicatorDots>
+          <SwiperItem className='swiperItem'>
+            <Console />
+
+          </SwiperItem>
+
+          <SwiperItem className='swiperItem'>
+            <Console />
+          </SwiperItem>
+        </Swiper> :
+          <Console />
+
       }
- 
+
+
+      <More ref={global.moreRef} />
+      {/* {
+        !permission.wxPubFollow && user.isLogin && <Text style={{ textAlign: 'center', width: '100%' }} onClick={() => followWxPub()}>去关注公众号</Text>
+      } */}
+
       {
         checkData && schedule()
       }
 
 
       {
-        checkData && (checkData as any).latest_record && <Schedule type='latest' delSuccess={getCheckData}/>
+        checkData && (checkData as any).latest_record && <RecordFastSleep type='latest' data={(checkData as any).latest_record} delSuccess={getCheckData} />
+        // <Schedule type='latest' delSuccess={getCheckData} />
       }
       {/* <Picker mode="time" start="07:00" end="20:00">
         <Text style="color: #fff;">test picker</Text>

+ 10 - 1
src/pages/common/RecordsHistory.tsx

@@ -11,6 +11,7 @@ import Layout from "@/components/layout/layout";
 import NoData from "@/components/view/NoData";
 import { NaviBarTitleShowType, TemplateType } from "@/utils/types";
 import { useSelector } from "react-redux";
+import RecordFastSleep from "@/features/trackTimeDuration/components/RecordFastSleep";
 
 export default function Page() {
     const router = useRouter();
@@ -26,6 +27,7 @@ export default function Page() {
     const [modalDetail, setModalDetail] = useState<any>({})
     const [total, setTotal] = useState(0)
     const [isLoading, setIsLoading] = useState(false)
+    const user = useSelector((state: any) => state.user);
 
 
     global.showModal = (isShow: boolean, detail: any) => {
@@ -185,14 +187,21 @@ export default function Page() {
                 // Taro.getCurrentPages()[0].refresh()
             })
         }
+        else if (router.params.type == 'time') {
+
+        }
     }
 
     function detail() {
         if (router.params.type == 'time') {
             return <View>
+                {
+                    user.test_user && <Text style={{ color: '#fff', position: 'absolute', right: 50, top: 0 }} onClick={() => global.clearHistory()}>删除全部</Text>
+                }
                 {
                     records.map((item, index) => {
-                        return <Schedule key={index} data={item} type="record" delSuccess={(item) => removeItem(item)} />
+                        return <RecordFastSleep key={index} data={item} type='record' delSuccess={(item) => removeItem(item)} />
+                        // return <Schedule key={index} data={item} type="record" delSuccess={(item) => removeItem(item)} />
                     })
                 }
             </View>

+ 1 - 0
src/services/trackTimeDuration.tsx

@@ -58,6 +58,7 @@ export const getClockRecords = (params:any)=>{
 }
 
 export const recordCheck = (params: Record<string, any> | undefined) => {
+    debugger
     return new Promise((resolve) => {
         request({
             url: API_FAST_CLOCKS, method: 'POST', data: { ...params }

+ 7 - 0
src/utils/time_format.ts

@@ -122,4 +122,11 @@ export class TimeFormatter {
     var minute = time % 60;
     return `${TimeFormatter.padZero(hour)}:${TimeFormatter.padZero(minute)}`;
   }
+
+  //获取今天的日期和星期几
+  static getDateAndWeek = ()=>{
+    var now = new Date()
+    var weeks = ['日','一','二','三','四','五','六']
+    return `${now.getMonth()+1}月${now.getDate()}日·星期${weeks[now.getDay()]}`
+  }
 }

+ 12 - 6
src/utils/types.ts

@@ -2,10 +2,10 @@ export enum ButtonType {
     elevated = 'elevated', //实心bg+文字
     outline = 'outline',    //描边跟按钮文字一致
     text = 'text',          //纯文字
-    
-} 
 
-export enum TextType{
+}
+
+export enum TextType {
     primary = 'primary',
     secondary = 'secondary',
     big = 'big',
@@ -17,7 +17,7 @@ export enum ComponentStatus {
     disable = 'disable'
 }
 
-export enum ScenarioType{
+export enum ScenarioType {
     fast = 'fast',
     sleep = 'sleep',
     fastSleep = 'fastSleep',
@@ -29,13 +29,19 @@ export enum TemplateType {
     flex = 'flex',
 }
 
-export enum NaviBarTitleShowType{
+export enum NaviBarTitleShowType {
     alwayShow = 'alwayShow',
     alwayHide = 'alwayHide',
     scrollToShow = 'scrollToShow',
 }
 
-export enum ModalType{
+export enum ModalType {
     center = 'center',
     bottom = 'bottom',
+}
+
+export enum BoxType {
+    big = 'big',
+    small = 'small',
+    outline = 'outline'
 }