Leon 1 年之前
父節點
當前提交
163bac4921
共有 33 個文件被更改,包括 914 次插入444 次删除
  1. 13 12
      src/_health/components/choose_date_time.tsx
  2. 39 0
      src/_health/components/console_cell.scss
  3. 48 0
      src/_health/components/console_cell.tsx
  4. 83 0
      src/_health/components/fast_sleep_console.tsx
  5. 11 0
      src/_health/components/icon_title_cell.scss
  6. 52 0
      src/_health/components/icon_title_cell.tsx
  7. 15 0
      src/_health/components/list_footer.scss
  8. 10 0
      src/_health/components/list_footer.tsx
  9. 46 4
      src/_health/components/post_moment_time.tsx
  10. 4 2
      src/_health/components/sticky_date_list.tsx
  11. 35 16
      src/_health/pages/add_moment.tsx
  12. 2 3
      src/_health/pages/archive.tsx
  13. 13 7
      src/_health/pages/fast_sleep.tsx
  14. 7 1
      src/_health/pages/long_fast.tsx
  15. 1 12
      src/_health/pages/move.scss
  16. 2 3
      src/_health/pages/move.tsx
  17. 2 1
      src/_health/pages/move_detail.tsx
  18. 0 11
      src/_health/pages/move_schedule.scss
  19. 46 47
      src/_health/pages/move_schedule.tsx
  20. 50 2
      src/_health/pages/move_setting_time.tsx
  21. 4 0
      src/_health/pages/schedules.tsx
  22. 47 5
      src/_health/pages/timeline_detail.tsx
  23. 22 0
      src/app.scss
  24. 0 23
      src/features/health/History.scss
  25. 1 1
      src/features/health/HistoryItem.tsx
  26. 77 124
      src/features/health/MainConsole.tsx
  27. 13 13
      src/features/health/MainHistory.tsx
  28. 1 13
      src/pages/account/Album.scss
  29. 36 21
      src/pages/account/Album.tsx
  30. 1 13
      src/pages/account/Journal.scss
  31. 162 42
      src/pages/account/Journal.tsx
  32. 66 68
      src/pages/account/Profile.tsx
  33. 5 0
      src/pages/clock/ClockNew.tsx

+ 13 - 12
src/_health/components/choose_date_time.tsx

@@ -13,7 +13,8 @@ export default function ChooseDateTime(props: {
     disable?: boolean,
     showError?: boolean,
     showLine?: boolean,
-    minTimestamp?:number,
+    minTimestamp?: number,
+    hideFooter?: boolean,
     footerTitle?: string,
     tapFooter?: any,
     color: string,
@@ -26,19 +27,19 @@ export default function ChooseDateTime(props: {
 }) {
     const [chooseDate, setChooseDate] = useState(false)
 
-    function dateTitle(){
+    function dateTitle() {
         var today = dayjs()
         const yesterday = today.subtract(1, 'day');
         var date = dayjs(props.date)
-        
-        if (today.format('YYYY-MM-DD') == date.format('YYYY-MM-DD')){
-            return global.languange=='en'?'Today':'今天'
+
+        if (today.format('YYYY-MM-DD') == date.format('YYYY-MM-DD')) {
+            return global.languange == 'en' ? 'Today' : '今天'
         }
-        if (yesterday.format('YYYY-MM-DD') == date.format('YYYY-MM-DD')){
-            return global.languange=='en'?'Yesterday':'昨天'
+        if (yesterday.format('YYYY-MM-DD') == date.format('YYYY-MM-DD')) {
+            return global.languange == 'en' ? 'Yesterday' : '昨天'
         }
         else {
-            return global.languange=='en'?date.format('MMM D'):date.format('MMMD日')
+            return global.languange == 'en' ? date.format('MMM D') : date.format('MMMD日')
         }
     }
 
@@ -111,7 +112,7 @@ export default function ChooseDateTime(props: {
             <View className='border_footer_line' style={{ left: rpxToPx(66) }} />
         </View>
         {
-            props.expand && chooseDate && <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', width: rpxToPx(698) }}>
+            props.expand && chooseDate && <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', width: rpxToPx(698), height: rpxToPx(340) }}>
                 {/* <NewDatePicker
                         type={NewDatePickerType.normal}
                         isToday={array[index].today}
@@ -124,7 +125,7 @@ export default function ChooseDateTime(props: {
                         color={iFast ? MainColorType.fast : MainColorType.sleep} /> */}
                 <NewDatePicker
                     type={NewDatePickerType.date}
-                    minTimestamp={props.minTimestamp?props.minTimestamp:new Date().getTime()-24*3600*1000}
+                    minTimestamp={props.minTimestamp ? props.minTimestamp : new Date().getTime() - 24 * 3600 * 1000}
                     value={props.date}
                     onChange={(e) => {
                         // var list = JSON.parse(JSON.stringify(array))
@@ -140,7 +141,7 @@ export default function ChooseDateTime(props: {
             props.expand && chooseDate && <View className='card_footer' />
         }
         {
-            props.expand && !chooseDate && <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', width: rpxToPx(698) }}>
+            props.expand && !chooseDate && <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', width: rpxToPx(698), height: rpxToPx(340) }}>
                 <NewTimePicker time={props.time} onChange={(e) => {
                     // var list = JSON.parse(JSON.stringify(array))
                     // list[index].time = e
@@ -152,7 +153,7 @@ export default function ChooseDateTime(props: {
         }
 
         {
-            props.expand && !chooseDate && <View className='card_footer'>
+            props.expand && !chooseDate && !props.hideFooter && <View className='card_footer'>
                 <NewButton type={NewButtonType.link}
                     title={props.footerTitle}
                     onClick={props.tapFooter}

+ 39 - 0
src/_health/components/console_cell.scss

@@ -0,0 +1,39 @@
+.timeline_item {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    padding-right: 40px;
+    position: relative;
+    padding-left: 52px;
+    background-color: #fff;
+    width: 750px;
+    box-sizing: border-box;
+    height: 172px;
+}
+
+.timeline_left {
+    display: flex;
+    flex-direction: column;
+    flex: 1;
+    overflow: hidden;
+}
+
+.timeline_desc {
+    font-size: 24px;
+    line-height: 34px;
+    // width: 500px;
+    flex: 1;
+    color: #B2B2B2;
+    // white-space: nowrap;
+    // display: -webkit-box;
+    // -webkit-box-orient: vertical;
+    // overflow: hidden;
+    // -webkit-line-clamp: 1; // 限制为一行
+    // text-overflow: ellipsis; // 超出部分显示省略号
+    white-space: nowrap;
+    /* 不换行 */
+    overflow: hidden;
+    /* 隐藏超出部分 */
+    text-overflow: ellipsis;
+    /* 显示省略号 */
+}

+ 48 - 0
src/_health/components/console_cell.tsx

@@ -0,0 +1,48 @@
+import { View, Text } from '@tarojs/components'
+import Cell from '../base/cell'
+import './console_cell.scss'
+import { rpxToPx } from '@/utils/tools'
+export default function ConsoleCell(props: {
+    status: any,
+    title?: any,
+    titleComponent?: any,
+    description?: string,
+    subDesc?: any,
+    right: any,
+    disable?: boolean,
+    onClick?: any,
+    showLine: boolean,
+    fullLine: boolean,
+    key?: any
+}) {
+    return <Cell disable={props.disable} onClick={props.onClick} key={props.key}>
+        <View className="timeline_item"
+            style={{ backgroundColor: 'transparent' }}>
+            <View className="timeline_left">
+                <View style={{
+                    height: props.description ? rpxToPx(28) : rpxToPx(36), flexShrink: 0
+                }} />
+                {
+                    props.status
+                }
+                {
+                    props.title ? <View className='h34' style={{ lineHeight: rpxToPx(46) + 'px' }}>{props.title}</View> : props.titleComponent
+                }
+
+                {
+                    props.description && <Text className='h24 g02 timeline_desc'>{props.description}{props.subDesc}</Text>
+                }
+                <View style={{
+                    height: props.description ? rpxToPx(28) : rpxToPx(54), flexShrink: 0,
+                }} />
+            </View>
+            {
+                props.right
+            }
+            {
+                props.showLine && <View className="border_footer_line" style={{ left: props.fullLine ? -rpxToPx(52) : rpxToPx(52) }} />
+            }
+
+        </View>
+    </Cell>
+}

+ 83 - 0
src/_health/components/fast_sleep_console.tsx

@@ -13,6 +13,7 @@ import { delRecord } from "@/services/health";
 import { TimeFormatter } from "@/utils/time_format";
 import showActionSheet from "@/components/basic/ActionSheet";
 import { useTranslation } from "react-i18next";
+import ConsoleCell from "./console_cell";
 
 export default function FastSleepConsole(props: { step: number, data: any, del: any }) {
     const health = useSelector((state: any) => state.health);
@@ -89,6 +90,16 @@ export default function FastSleepConsole(props: { step: number, data: any, del:
 
     }
 
+    function itemDisableStatus(index){
+        if (index == 0 && props.data.fast.status == 'OG') {
+            return false
+        }
+        else if (index == 1 && (props.data.sleep.status == 'OG' || props.data.status == 'OG3')) {
+            return false
+        }
+        return true
+    }
+
     function delConfirm() {
         const { fast, sleep } = props.data
         let array: any = []
@@ -245,6 +256,78 @@ export default function FastSleepConsole(props: { step: number, data: any, del:
         if (health.fast_with_sleep.status == 'OG2_MISALIGNED' && (index == 0 || index == 1)) {
             isError = true;
         }
+
+        function rightView() {
+            if (isError) {
+                return <View style={{
+                    borderColor: MainColorType.error,
+                    borderWidth: rpxToPx(2),
+                    borderRadius: rpxToPx(76 / 4),
+                    borderStyle: 'solid'
+                }}>
+                    <NewButton
+                        type={NewButtonType.gray}
+                        title='Correct'
+                        fontSize={rpxToPx(34)}
+                        width={rpxToPx(128)}
+                        height={rpxToPx(72)}
+                        onClick={() => {
+                            jumpPage(`/_health/pages/log_time?is_fast_with_sleep=1&index=${1}&single=0&initCheck=1&initIndex=${index}`)
+                        }}
+                    />
+                </View>
+            }
+            else {
+                if (item.action == 'POST_MOMENT' && item.timeline.real)
+                    return <IconArrow color={MainColorType.g03} width={rpxToPx(34)} />
+                if (item.moment && item.moment.media && item.moment.media.length > 0)
+                    return <Image
+                        src={item.moment.media[0].url}
+                        mode="aspectFill"
+                        className="console_item_img" />
+                if (showBtn)
+                    return <NewButton
+                        color={getThemeColor(item.mode)}
+                        type={NewButtonType.alpha}
+                        title={'Log'}
+                        width={rpxToPx(128)}
+                        height={rpxToPx(72)}
+                        bold={true}
+                        onClick={() => {
+                            tapLogBtn(index)
+                        }} />
+            }
+        }
+
+        return <ConsoleCell
+            status={<View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
+                <View style={{
+                    flexShrink: 0,
+                    width: rpxToPx(26),
+                    height: rpxToPx(26),
+                    borderRadius: rpxToPx(13),
+                    marginRight: rpxToPx(8),
+                    display: 'flex',
+                    alignItems: 'center',
+                    justifyContent: 'center',
+                    backgroundColor: isError ? MainColorType.error : getIconColor(index, finish)
+                }}>
+                    {
+                        processIcon(item, finish, isError)
+                    }
+                </View>
+                <Text className="timeline_time" style={{ color: isError ? MainColorType.error : MainColorType.g01 }}>{time}</Text>
+            </View>}
+            title={(item.moment && item.moment.title) ? item.moment.title : item.title}
+            description={hasDescription ? item.moment.description : null}
+            disable={itemDisableStatus(index)}
+            onClick={() => {
+                goDetail(index)
+            }}
+            right={rightView()}
+            showLine={true}
+            fullLine={count - 1 == index}
+        />
         return <View key={index}
             className="timeline_item"
             onClick={() => {

+ 11 - 0
src/_health/components/icon_title_cell.scss

@@ -0,0 +1,11 @@
+.icon_title_cell_container {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    height: 128px;
+    width: 750px;
+    padding-left: 40px;
+    padding-right: 40px;
+    box-sizing: border-box;
+    position: relative;
+}

+ 52 - 0
src/_health/components/icon_title_cell.tsx

@@ -0,0 +1,52 @@
+
+import { View } from "@tarojs/components"
+import Cell from "../base/cell"
+import { IconArrow } from "@/components/basic/Icons"
+import { rpxToPx } from "@/utils/tools"
+import { MainColorType } from "@/context/themes/color"
+import './icon_title_cell.scss'
+import { useSelector } from "react-redux"
+import { jumpPage } from "@/features/trackTimeDuration/hooks/Common"
+
+let useNavigation;
+
+if (process.env.TARO_ENV == 'rn') {
+    useNavigation = require("@react-navigation/native").useNavigation
+}
+export default function IconTitleCell(props: {
+    onClick: any,
+    title: string,
+    desc?: any,
+    icon: any,
+    showLine?: boolean
+}) {
+    const user = useSelector((state: any) => state.user);
+    let navigation
+    if (useNavigation) {
+        navigation = useNavigation()
+    }
+
+    return <Cell onClick={() => {
+        if (!user.isLogin) {
+            jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
+            return
+        }
+        props.onClick()
+    }}>
+        <View className="icon_title_cell_container">
+            {
+                props.icon
+            }
+            <View className="h34" style={{ flex: 1 }}>{props.title}</View>
+            {
+                props.desc
+            }
+            <View style={{ width: rpxToPx(12) }} />
+            <IconArrow width={rpxToPx(34)} color={MainColorType.g03} />
+            {
+                props.showLine && <View className="border_footer_line" style={{ left: rpxToPx(100) }} />
+            }
+
+        </View>
+    </Cell>
+}

+ 15 - 0
src/_health/components/list_footer.scss

@@ -0,0 +1,15 @@
+
+.list_footer{
+    height: 128px;
+    flex-shrink: 0;
+    margin-bottom: 10px;
+}
+.no_more {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 750px;
+    text-align: center;
+    height: 128px;
+    font-size: 26px;
+}

+ 10 - 0
src/_health/components/list_footer.tsx

@@ -0,0 +1,10 @@
+import { View,Text } from "@tarojs/components";
+import './list_footer.scss'
+
+export default function ListFooter(props:{noMore?:boolean}){
+    return <View className="list_footer">
+        {
+            props.noMore&&<Text className="no_more g02">没有更多了</Text>
+        }
+    </View>
+}

+ 46 - 4
src/_health/components/post_moment_time.tsx

@@ -3,7 +3,7 @@ import './post_moment_time.scss'
 import NewModal from '../base/new_modal'
 import { useState } from 'react'
 import { useSelector } from 'react-redux';
-import { getThemeColor } from '@/features/health/hooks/health_hooks';
+import { getScenario, getThemeColor } from '@/features/health/hooks/health_hooks';
 import { rpxToPx } from '@/utils/tools';
 import NewTimePicker from '../base/new_timepicker';
 import { IconCalendar, IconTarget } from '@/components/basic/Icons';
@@ -13,10 +13,13 @@ import dayjs from 'dayjs';
 import Card from './card';
 import CellFooter, { CellFooterType } from '../base/cell_footer';
 import CellFooterText from '../base/cell_footer_text';
+import ChooseDateTime from './choose_date_time';
+import { MainColorType } from '@/context/themes/color';
 
 let isYesterdayTarget = false
 export default function PostMomentTime(props: {
     title?: string,
+    date?:string,
     time: string,
     isTemp: boolean,
     onChange: any,
@@ -26,6 +29,7 @@ export default function PostMomentTime(props: {
     const health = useSelector((state: any) => state.health);
     const [showDurationPicker, setShowDurationPicker] = useState(false)
     const [isYesterday, setIsYesterday] = useState(false)
+    const [selDate, setSelDate] = useState(props.date?props.date:dayjs().format('YYYY-MM-DD'))
     const [showMore, setShowMore] = useState(false)
     const [time, setTime] = useState(props.time)
     const [minutes, setMinutes] = useState(30)
@@ -107,14 +111,19 @@ export default function PostMomentTime(props: {
 
                 </View>
             </Card>
-            <CellFooter 
+            <CellFooter
                 type={CellFooterType.center}
             >
-                <CellFooterText text={`Expect to finish at ${endTime()}`}/>
+                <CellFooterText text={`Expect to finish at ${endTime()}`} />
             </CellFooter>
         </View>
     }
 
+    function getMinTimestamp() {
+        var scenario = getScenario(health.windows, health.mode)
+        return scenario.picker_min_timestamp
+    }
+
     function scheduleTime() {
         if (props.moment) {
             var timestamp = props.moment.target.timestamp
@@ -141,6 +150,7 @@ export default function PostMomentTime(props: {
         dismiss={props.dismiss}
         confirm={() => {
             props.onChange({
+                date: selDate,
                 time: time,
                 duration: minutes,
                 isYesterday: isYesterday
@@ -148,6 +158,38 @@ export default function PostMomentTime(props: {
         }}
         themeColor={getThemeColor(health.mode)}>
         <Card>
+            <ChooseDateTime title={null}
+                disable={false}
+                color={getThemeColor(health.mode)}
+                expand={!showDurationPicker}
+                choose={() => {
+                    setShowDurationPicker(false)
+                }}
+                time={time}
+                timeChange={(e) => {
+                    setTime(e)
+                }}
+                minTimestamp={getMinTimestamp()}
+
+                footerTitle={scheduleTime()}
+                tapFooter={() => {
+                    if (time == dayjs(props.moment.target.timestamp).format('HH:mm')) {
+                        setSelDate(dayjs(global.set_time).format('YYYY-MM-DD'))
+                        setTime(dayjs(global.set_time).format('HH:mm'))
+                    }
+                    else {
+                        setSelDate(dayjs(props.moment.target.timestamp).format('YYYY-MM-DD'))
+                        setTime(dayjs(props.moment.target.timestamp).format('HH:mm'))
+                    }
+
+                }}
+                date={selDate}
+                dateChange={(e) => {
+                    setSelDate(e)
+                }}
+            />
+        </Card>
+        {/* <Card>
             <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
                 <View className='picker_time_card'>
                     <View className='picker_time_card_header'>
@@ -204,7 +246,7 @@ export default function PostMomentTime(props: {
 
             </View>
 
-        </Card>
+        </Card> */}
         <View style={{ marginTop: rpxToPx(36), display: 'flex', flexDirection: 'column', alignItems: showMore ? 'flex-start' : 'center' }}>
             {
                 showMore ? durationContent() :

+ 4 - 2
src/_health/components/sticky_date_list.tsx

@@ -6,6 +6,7 @@ export default function StickyDateList(props: {
     header?: any, children: any, footer?: any,
     onRefresherRefresh: any,
     isPulling: boolean,
+    loadMore?: any,
     onScroll: any,
     showDate: boolean,
     date: string
@@ -16,14 +17,14 @@ export default function StickyDateList(props: {
             left: 0,
             top: 0,
             right: 0,
-            height: props.showDate ?rpxToPx(84):0,
+            height: props.showDate ? rpxToPx(84) : 0,
             backgroundColor: '#f5f5f5',
             paddingLeft: rpxToPx(40),
             display: 'flex',
             boxSizing: 'border-box',
             flexDirection: 'row',
             alignItems: 'center',
-            zIndex:1,
+            zIndex: 1,
             opacity: props.showDate ? 1 : 0,
             color: MainColorType.g01
         }}>{props.date}</View>
@@ -34,6 +35,7 @@ export default function StickyDateList(props: {
             onRefresherRefresh={props.onRefresherRefresh}
             refresherTriggered={props.isPulling}
             onScroll={props.onScroll}
+            onScrollToLower={props.loadMore}
         >
             {
                 props.header

+ 35 - 16
src/_health/pages/add_moment.tsx

@@ -36,8 +36,6 @@ export default function AddMoment() {
     const [desc, setDesc] = useState('')
     const { t } = useTranslation()
     const [imgUrl, setImgUrl] = useState('')
-    const [startTime, setStartTime] = useState(0)
-    const [endTime, setEndTime] = useState(0)
     const [showPicker, setShowPicker] = useState(false)
     const [durationPicker, setDurationPicker] = useState(false)
     const [durationT, setDurationT] = useState(0)
@@ -65,6 +63,7 @@ export default function AddMoment() {
     }
 
     const [time, setTime] = useState(dayjs().format('HH:mm'))
+    const [selDate,setSelDate] = useState(dayjs().format('YYYY-MM-DD'))
     const [title, setTitle] = useState(router.params.title)
 
     const { event_id, is_temp, schedule_id } = router.params
@@ -129,24 +128,26 @@ export default function AddMoment() {
             })
             return
         }
-        var date = new Date(timestamp)
-        var hour = parseInt(time.split(':')[0] + '')
-        var minute = parseInt(time.split(':')[1] + '')
-        date.setHours(hour)
-        date.setMinutes(minute)
-        var timestamp1 = date.getTime()
-        if (isYesterday) {
-            timestamp1 -= 24 * 3600 * 1000
-        }
-        debugger
+        // var date = new Date(timestamp)
+        // var hour = parseInt(time.split(':')[0] + '')
+        // var minute = parseInt(time.split(':')[1] + '')
+        // date.setHours(hour)
+        // date.setMinutes(minute)
+        // var timestamp1 = date.getTime()
+        // if (isYesterday) {
+        //     timestamp1 -= 24 * 3600 * 1000
+        // }
+        // debugger
+
+        var date = new Date(selDate+' '+time+':00')
 
         var params: any = {
             schedule_id: schedule_id,
             title: title,
             description: desc,
             start: {
-                date: dayjs(timestamp1).format('YYYYMMDD'),
-                timestamp: timestamp1
+                date: dayjs(date.getTime()).format('YYYYMMDD'),
+                timestamp: date.getTime()
             }
         }
 
@@ -305,6 +306,22 @@ export default function AddMoment() {
         return <View></View>
     }
 
+    function getDate(){
+        var sel = dayjs(selDate)
+        var now = dayjs().format('YYYY-MM-DD')
+        const yesterday = dayjs().subtract(1, 'day');
+        if (sel.format('YYYY-MM-DD')==now){
+            return ''
+        }
+        if (yesterday.format('YYYY-MM-DD') == sel.format('YYYY-MM-DD')){
+            return global.languange=='en'?'Yesterday ':'昨天 '
+        }
+        else {
+            return global.languange=='en'?sel.format('MMM D '):sel.format('MMMD日 ')
+        }
+
+    }
+
 
     return <View>
         {/* {
@@ -333,7 +350,7 @@ export default function AddMoment() {
             <View className="addmoment_header">
                 <Text onClick={() => {
                     setShowTimePicker(true)
-                }} style={{ marginRight: rpxToPx(24), color: '#5C7099' }}>{time}</Text>
+                }} style={{ marginRight: rpxToPx(24), color: '#5C7099' }}>{getDate()}{time}</Text>
                 <Text
                     onClick={() => {
                         setShowTitlePicker(true)
@@ -385,11 +402,13 @@ export default function AddMoment() {
         {
             showTimePicker && <PostMomentTime
                 time={time}
+                date={selDate}
                 isTemp={is_temp}
                 moment={moment}
                 onChange={(e) => {
-                    const { duration, time, isYesterday } = e;
+                    const {date, duration, time, isYesterday } = e;
                     setTime(time)
+                    setSelDate(date)
                     setIsYesterday(isYesterday)
                     setDurationT(duration)
                     setShowTimePicker(false)

+ 2 - 3
src/_health/pages/archive.tsx

@@ -4,6 +4,7 @@ import { records } from "@/services/health";
 import { View,Text } from "@tarojs/components";
 import { useEffect, useRef, useState } from "react";
 import { useSelector } from "react-redux";
+import ListFooter from "../components/list_footer";
 
 export default function Archive() {
     const [list, setList] = useState<any>([])
@@ -90,8 +91,6 @@ export default function Archive() {
                 </View>
             })
         }
-        {
-            (list.length > 0) && (total == list.length) && <Text className="no_more">没有更多了</Text>
-        }
+        <ListFooter noMore={(list.length > 0) && (total == list.length)} />
     </View>
 }

+ 13 - 7
src/_health/pages/fast_sleep.tsx

@@ -20,7 +20,7 @@ import FastSleepPopup from "../components/fast_sleep_popup";
 
 export default function FastSleep() {
     const health = useSelector((state: any) => state.health);
-    const [showPopCard,setShowPopCard] = useState(false)
+    const [showPopCard, setShowPopCard] = useState(false)
     const [time, setTime] = useState(dayjs().format('HH:mm'))
     const [count, setCount] = useState(0)
 
@@ -88,7 +88,13 @@ export default function FastSleep() {
             if (historyRef) {
                 (historyRef.current as any).onScroll(e)
             }
-        }}>
+        }}
+        loadMore={() => {
+            if (historyRef) {
+                (historyRef.current as any).more()
+            }
+        }}
+    >
         <View className="page_container">
             <NewHeader type={health.fast_with_sleep.status != 'OG2_MISALIGNED' ? NewHeaderType.left_subtitle : NewHeaderType.left}
                 title="Fast with Sleep"
@@ -101,23 +107,23 @@ export default function FastSleep() {
                     onChange={e => setCurrent(e.detail.current)}
                     current={current}
                     indicatorDots>
-                    <SwiperItem onClick={()=>setShowPopCard(true)}>
+                    <SwiperItem onClick={() => setShowPopCard(true)}>
                         <Card>
                             <FastSleepCard step={0} data={data} />
 
                         </Card>
                     </SwiperItem>
-                    <SwiperItem onClick={()=>setShowPopCard(true)}>
+                    <SwiperItem onClick={() => setShowPopCard(true)}>
                         <Card>
                             <FastSleepCard step={1} data={data} />
                         </Card>
                     </SwiperItem>
-                    <SwiperItem onClick={()=>setShowPopCard(true)}>
+                    <SwiperItem onClick={() => setShowPopCard(true)}>
                         <Card>
                             <FastSleepCard step={2} data={data} />
                         </Card>
                     </SwiperItem>
-                    <SwiperItem onClick={()=>setShowPopCard(true)}>
+                    <SwiperItem onClick={() => setShowPopCard(true)}>
                         <Card>
                             <FastSleepCard step={3} data={data} />
                         </Card>
@@ -140,7 +146,7 @@ export default function FastSleep() {
                 setIsPulling(false)
             }} />
             {
-                showPopCard && <FastSleepPopup close={()=>{setShowPopCard(false)}} data={data}/>
+                showPopCard && <FastSleepPopup close={() => { setShowPopCard(false) }} data={data} />
             }
         </View>
     </StickyDateList>

+ 7 - 1
src/_health/pages/long_fast.tsx

@@ -231,7 +231,13 @@ export default function LongFast() {
             if (historyRef) {
                 (historyRef.current as any).onScroll(e)
             }
-        }}><View className="page_container">
+        }}
+        loadMore={() => {
+            if (historyRef) {
+                (historyRef.current as any).more()
+            }
+        }}
+    ><View className="page_container">
             <NewHeader type={NewHeaderType.left_subtitle}
                 title="Long Fast "
                 subtitle="Prolonged Fasting beyond 24 hours"

+ 1 - 12
src/_health/pages/move.scss

@@ -211,7 +211,7 @@
 }
 
 .history_item {
-    padding-left: 44px;
+    padding-left: 40px;
     padding-right: 40px;
     height: 152px;
     display: flex;
@@ -247,17 +247,6 @@
     margin: 20px;
 }
 
-.no_more {
-    color: #B2B2B2;
-    background-color: #f5f5f5;
-    width: 750px;
-    height: 128px;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    font-size: 26px;
-}
-
 .current_history_item {
     height: 172px;
     display: flex;

+ 2 - 3
src/_health/pages/move.tsx

@@ -19,6 +19,7 @@ import NewButton, { NewButtonType } from "../base/new_button";
 import { MainColorType } from "@/context/themes/color";
 import StatusIndicator, { StatusType } from "../base/status_indicator";
 import showActionSheet from "@/components/basic/ActionSheet";
+import ListFooter from "../components/list_footer";
 
 let timer
 export default function Move() {
@@ -733,9 +734,7 @@ export default function Move() {
                 }
             </View>
         }
-        {
-            (list.length > 0) && (total == list.length) && <Text className="no_more">没有更多了</Text>
-        }
+        <ListFooter noMore={(list.length > 0) && (total == list.length)} />
 
 
     </View>

+ 2 - 1
src/_health/pages/move_detail.tsx

@@ -9,6 +9,7 @@ import dayjs from "dayjs";
 import NewHeader, { NewHeaderType } from "../components/new_header";
 import NewButton, { NewButtonType } from "../base/new_button";
 import { MainColorType } from "@/context/themes/color";
+import ListFooter from "../components/list_footer";
 
 let useRoute;
 let useNavigation;
@@ -156,6 +157,6 @@ export default function MoveDetail() {
         {
             activeHour()
         }
-        <Text className="no_more">没有更多了</Text>
+        <ListFooter noMore={true} />
     </View>
 }

+ 0 - 11
src/_health/pages/move_schedule.scss

@@ -32,17 +32,6 @@
     color: #FF2E66;
 }
 
-.no_more{
-    color: #B2B2B2;
-    background-color: #f5f5f5;
-    width: 750px;
-    height: 128px;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    font-size: 26px;
-}
-
 .history_item_detail_icon{
     height: 32px;
     width: 32px;

+ 46 - 47
src/_health/pages/move_schedule.tsx

@@ -10,6 +10,7 @@ import NewHeader, { NewHeaderType } from "../components/new_header";
 import StatusIndicator, { StatusType } from "../base/status_indicator";
 import { MainColorType } from "@/context/themes/color";
 import { IconNotification, IconNotificationOff } from "@/components/basic/Icons";
+import ConsoleCell from "../components/console_cell";
 
 let useRoute;
 let useNavigation;
@@ -148,53 +149,51 @@ export default function MoveSchedule() {
 
                 open = (open + '').padStart(2, '0')
                 if (item.status != 'WFS') return <View key={index} />
-                return <View key={index} className="schedule_item">
-                    <View className="schedule_item_left">
-                        <StatusIndicator type={StatusType.normal}
-                            color={MainColorType.active}
-                            text={'WAKING HOUR ' + (index + 1)} />
-                        <View className="h34" style={{ marginLeft: rpxToPx(30) }}>Check in at {open}:50</View>
-                        <Text className="h22" style={{ color: MainColorType.g02, marginTop: rpxToPx(12), marginLeft: rpxToPx(30) }}>
-                            {parseInt(start) < new Date().getHours() ? '' : ''}{start}:00-{end}:00
-
-                            <Text className="schedule_item_time">  {firstTime(index)}</Text>
-                        </Text>
-                        {/* <Text className="schedule_item_target">{item.real_steps}/{item.target_steps} steps</Text> */}
-                    </View>
-                    <View style={{ flex: 1 }} />
-                    {
-                        item.reminder ? <IconNotification color={MainColorType.g03} width={rpxToPx(28)} /> : <IconNotificationOff color={MainColorType.g03} width={rpxToPx(28)} />
-                    }
-                    <View style={{ width: rpxToPx(12) }} />
-                    <Switch checked={item.reminder} color={getThemeColor('ACTIVE')} onChange={e => {
-                        console.log(item)
-
-                        createSchedule({
-                            schedules: [{
-                                id: item.schedule_id,
-                                reminder: e.detail.value
-                            }],
-                        }).then(res => {
-                            getData()
-                            if (global.refreshWindow) {
-                                global.refreshWindow()
-                            }
-                            if (global.refreshSchedules) {
-                                global.refreshSchedules()
-                            }
-                            if (global.updateMove) {
-                                global.updateMove()
-                            }
-                        })
-                    }} />
-                    {/* {
-                        item.status == 'WFS' && <Text className="schedule_item_open">{open}:50开放</Text>
-                    } */}
-
-                    {
-                        index < hours.length - 1 && <View className="border_footer_line" style={{ left: rpxToPx(72) }} />
-                    }
-                </View>
+                return <ConsoleCell key={index}
+                    status={<StatusIndicator type={StatusType.normal}
+                        color={MainColorType.active}
+                        text={'WAKING HOUR ' + (index + 1)} />}
+                    title={`Check in at ${open}:50`}
+                    description={`${parseInt(start) < new Date().getHours() ? '' : ''}${start}:00-${end}:00`}
+                    subDesc={<Text className="schedule_item_time">  {firstTime(index)}</Text>}
+                    right={<View style={{
+                        display: 'flex',
+                        flexDirection: 'row',
+                        alignItems: 'center'
+                    }}>
+                        {
+                            item.reminder ? <IconNotification color={MainColorType.g03} width={rpxToPx(28)} /> : <IconNotificationOff color={MainColorType.g03} width={rpxToPx(28)} />
+                        }
+                        <View style={{ width: rpxToPx(12) }} />
+                        <Switch checked={item.reminder} color={getThemeColor('ACTIVE')} onChange={e => {
+                            console.log(item)
+
+                            createSchedule({
+                                schedules: [{
+                                    id: item.schedule_id,
+                                    reminder: e.detail.value
+                                }],
+                            }).then(res => {
+                                getData()
+                                if (global.refreshWindow) {
+                                    global.refreshWindow()
+                                }
+                                if (global.refreshSchedules) {
+                                    global.refreshSchedules()
+                                }
+                                if (global.updateMove) {
+                                    global.updateMove()
+                                }
+                            })
+                        }} />
+                    </View>}
+                    disable={true}
+                    onClick={() => { }}
+                    showLine={true}
+                    fullLine={false}
+
+                />
+
             })
         }
         <Text className="no_more" style={{ color: '#5C7099' }} onClick={() => {

+ 50 - 2
src/_health/pages/move_setting_time.tsx

@@ -8,6 +8,7 @@ import NewHeader, { NewHeaderType } from "../components/new_header";
 import NewButton, { NewButtonType } from "../base/new_button";
 import StatusIndicator, { StatusType } from "../base/status_indicator";
 import { MainColorType } from "@/context/themes/color";
+import ConsoleCell from "../components/console_cell";
 
 export default function MoveSettingTime() {
     const [selIndex, setSelIndex] = useState(-1)
@@ -37,6 +38,53 @@ export default function MoveSettingTime() {
         />
         {
             detail.schedules.map((item, index) => {
+                return <ConsoleCell key={index}
+                    status={<StatusIndicator
+                        type={StatusType.normal}
+                        text={'WALKING HOUR ' + (index + 1)}
+                        color={MainColorType.active}
+                    />
+                    }
+                    right={selIndex != index ? <Text className="h26" style={{ color: MainColorType.link }} onClick={() => {
+                        setSelIndex(index)
+                    }}>更改目标</Text> : null}
+                    disable={true}
+                    showLine={true}
+                    fullLine={false}
+                    description={`${item.time}-${item.end_time}`}
+                    title={selIndex != index ? `Hit ${item.goal} Steps` : null}
+                    titleComponent={selIndex == index ? <Input className='item_name h34' style={{ flex: 1,  height: rpxToPx(46) }}
+                        value={item.goal}
+                        autoFocus={true}
+                        focus={true}
+                        type="number"
+                        onBlur={() => {
+                            setSelIndex(-1)
+                            createSchedule({
+                                schedules: [{
+                                    id: item.id,
+                                    goal: item.goal
+                                }],
+                            }).then(res => {
+                                if (global.refreshWindow) {
+                                    global.refreshWindow()
+                                }
+                                if (global.refreshSchedules) {
+                                    global.refreshSchedules()
+                                }
+                                if (global.updateMove) {
+                                    global.updateMove()
+                                }
+                                getDatas()
+                            })
+                        }}
+                        onInput={(e) => {
+                            // item.goal = e.detail.value
+                            var obj = JSON.parse(JSON.stringify(detail))
+                            obj.schedules[index].goal = e.detail.value
+                            setDetail(obj)
+                        }} /> : null}
+                />
                 return <View key={index} style={{
                     position: 'relative',
                     display: 'flex',
@@ -57,7 +105,7 @@ export default function MoveSettingTime() {
 
                         <View style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between' }}>
                             {
-                                selIndex == index ? <Input className='item_name h34' style={{ flex: 1, marginLeft: rpxToPx(30),height:rpxToPx(46) }}
+                                selIndex == index ? <Input className='item_name h34' style={{ flex: 1, marginLeft: rpxToPx(30), height: rpxToPx(46) }}
                                     value={item.goal}
                                     autoFocus={true}
                                     focus={true}
@@ -87,7 +135,7 @@ export default function MoveSettingTime() {
                                         var obj = JSON.parse(JSON.stringify(detail))
                                         obj.schedules[index].goal = e.detail.value
                                         setDetail(obj)
-                                    }} /> : <Text className="h34" style={{ marginLeft: rpxToPx(30),height:rpxToPx(46) }}>Hit {item.goal} Steps</Text>
+                                    }} /> : <Text className="h34" style={{ marginLeft: rpxToPx(30), height: rpxToPx(46) }}>Hit {item.goal} Steps</Text>
                             }
                             <View>
                                 {

+ 4 - 0
src/_health/pages/schedules.tsx

@@ -59,6 +59,7 @@ export default function Schedules() {
     const [btnEnable, setBtnEnable] = useState(true)
     const [selMode, setSleMode] = useState(router.params.mode);
     const [isEat, setIsEat] = useState(false)
+    const [loaded,setLoaded] = useState(false)
     const { t } = useTranslation()
 
     useEffect(() => {
@@ -111,6 +112,7 @@ export default function Schedules() {
         getSchedules({ window: windows }).then(res => {
             setList((res as any).data)
             setErrors([])
+            setLoaded(true)
             setTimeout(() => {
                 setHighlight(false)
             }, 2000)
@@ -341,6 +343,8 @@ export default function Schedules() {
         });
     }
 
+    if (!loaded) return <View />
+
 
     return <View>
         <View style={{ display: 'flex', flexDirection: 'column' }}>

+ 47 - 5
src/_health/pages/timeline_detail.tsx

@@ -13,6 +13,9 @@ import NewButton, { NewButtonType } from "../base/new_button";
 import { IconClose } from "@/components/basic/Icons";
 import { rpxToPx } from "@/utils/tools";
 import { MainColorType } from "@/context/themes/color";
+import NewModal from "../base/new_modal";
+import Card from "../components/card";
+import ChooseDateTime from "../components/choose_date_time";
 
 let timestamp = 0;
 let useRoute;
@@ -34,6 +37,10 @@ export default function TimelineDetail() {
     const [publish, setPublish] = useState<any>(null)
     const [bottom, setBottom] = useState(20)
     const [loaded, setLoaded] = useState(false)
+    const [showTimePicker, setShowTimePicker] = useState(false)
+    const [time, setTime] = useState(dayjs().format('HH:mm'))
+    const [selTime, setSelTime] = useState(dayjs().format('HH:mm'))
+    const [selDate, setSelDate] = useState(dayjs().format('YYYY-MM-DD'))
     let router
     let navigation;
     if (useNavigation) {
@@ -58,7 +65,7 @@ export default function TimelineDetail() {
 
     useEffect(() => {
         Taro.onKeyboardHeightChange(res => {
-            setBottom(res.height>0?res.height:20)
+            setBottom(res.height > 0 ? res.height : 20)
         })
 
         getDatas()
@@ -172,12 +179,13 @@ export default function TimelineDetail() {
             })
             return
         }
+        var dt = new Date(selDate+' '+time+':00')
         var params: any = {
             schedule_id: schedule_id,
             description: desc,
             start: {
-                date: dayjs(timestamp).format('YYYYMMDD'),
-                timestamp: timestamp
+                date: dayjs(dt.getTime()).format('YYYYMMDD'),
+                timestamp: dt.getTime()
             },
 
             // real_end_time: meal.target_end_time,
@@ -305,7 +313,7 @@ export default function TimelineDetail() {
                     }}>
                     <IconClose color="#fff" width={20} height={20} />
                 </NewButton>
-                <View style={{ height: rpxToPx(88), marginTop: rpxToPx(120), width: rpxToPx(80), color: MainColorType.link }}>{dayjs(timestamp).format('HH:mm')}
+                <View onClick={() => setShowTimePicker(true)} style={{ height: rpxToPx(88), marginTop: rpxToPx(120), width: rpxToPx(80), color: MainColorType.link }}>{time}
                 </View>
                 <Textarea className="myTextarea" placeholder="What's on your mind?" style={{ flex: 1, color: '#fff', caretColor: getThemeColor(health.mode) }} focus value={desc} onInput={(e) => {
                     setDesc(e.detail.value)
@@ -323,7 +331,7 @@ export default function TimelineDetail() {
                         </NewButton>
                     }
                     {
-                        imgUrl.length == 0 && <NewButton type={NewButtonType.img} onClick={() => addImage(false)}>
+                        imgUrl.length == 0 && <NewButton type={NewButtonType.img} onClick={() => addImage(true)}>
                             <Image src={require('@assets/_health/camera.png')} className="album"
                             /></NewButton>
                     }
@@ -335,5 +343,39 @@ export default function TimelineDetail() {
                 <View style={{ height: bottom, flexShrink: 0 }} />
             </View>
         }
+        {
+            showTimePicker && <NewModal
+                title='时间'
+                dismiss={() => setShowTimePicker(false)}
+                confirm={() => {
+                    // props.onChange({
+                    //     date: selDate,
+                    //     time: time,
+                    //     duration: minutes,
+                    //     isYesterday: isYesterday
+                    // })
+                    setTime(selTime)
+                    setShowTimePicker(false)
+                }}
+                themeColor={getThemeColor(health.mode)}>
+                <Card>
+                    <ChooseDateTime title={null}
+                        disable={false}
+                        color={getThemeColor(health.mode)}
+                        expand={true}
+                        time={time}
+                        hideFooter={true}
+                        timeChange={(e) => {
+                            setSelTime(e)
+                        }}
+                        minTimestamp={new Date().getTime()}
+                        date={selDate}
+                        dateChange={(e) => {
+                            setSelDate(e)
+                        }}
+                    />
+                </Card>
+            </NewModal>
+        }
     </View>
 }

+ 22 - 0
src/app.scss

@@ -573,4 +573,26 @@ page {
     text-overflow: ellipsis;
     /* 显示省略号 */
     width: 100%;
+}
+
+.cell_date {
+    margin-right: 24px;
+    width: 74px;
+    height: 68px;
+    flex-shrink: 0;
+    align-items: center;
+    justify-content: center;
+    display: flex;
+    color: #000;
+    font-size: 50px;
+    font-weight: bold;
+}
+
+.history_year_month{
+    height: 84px;
+    padding-left: 40px;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    background-color: #fff;
 }

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

@@ -20,18 +20,6 @@
     justify-content: center;
 }
 
-.history_date {
-    margin-right: 24px;
-    width: 74px;
-    height: 68px;
-    flex-shrink: 0;
-    align-items: center;
-    justify-content: center;
-    display: flex;
-    color: #000;
-    font-size: 50px;
-    font-weight: bold;
-}
 
 .history_content {
     display: flex;
@@ -58,17 +46,6 @@
     color: #000;
 }
 
-.no_more {
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    width: 750px;
-    text-align: center;
-    height: 128px;
-    font-size: 26px;
-    color: #B2B2B2;
-}
-
 .media {
     display: flex;
     flex-direction: row;

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

@@ -180,7 +180,7 @@ export default function HistoryItem(props: {
     }
 
     return <View className="history_item2">
-        <View className="history_date" >{historyDate()}</View>
+        <View className="cell_date" >{historyDate()}</View>
         <View className="history_content" >
 
             <View style={{ display: 'flex', flexDirection: 'column', marginBottom: rpxToPx(12), flex:1 }}>

+ 77 - 124
src/features/health/MainConsole.tsx

@@ -25,6 +25,8 @@ import NewButton, { NewButtonType } from "@/_health/base/new_button";
 import showAlert from "@/components/basic/Alert";
 import { useTranslation } from "react-i18next";
 import Cell from "@/_health/base/cell";
+import ConsoleCell from "@/_health/components/console_cell";
+import IconTitleCell from "@/_health/components/icon_title_cell";
 
 let useNavigation;
 let min = 0
@@ -207,7 +209,10 @@ export default function MainConsole(props: { type: WindowType }) {
         if (item.action && item.action == 'NA') {
             // if (health.mode == 'FAST' || health.mode == 'SLEEP') {
             if (item.moment && item.moment.media && item.moment.media.length > 0) {
-
+                return <Image
+                    src={item.moment.media[0].url}
+                    mode="aspectFill"
+                    className="console_item_img" />
             }
             else {
                 return <IconArrow width={rpxToPx(34)} color={MainColorType.g03} />
@@ -259,7 +264,7 @@ export default function MainConsole(props: { type: WindowType }) {
         if (timeline.real) {
             return MainColorType.g03
         }
-        if (timeline.target.timestamp<new Date().getTime()){
+        if (timeline.target.timestamp < new Date().getTime()) {
             return MainColorType.error
         }
         return color
@@ -281,62 +286,37 @@ export default function MainConsole(props: { type: WindowType }) {
     }
 
     function timelineItem(item: any, index: number, count: number) {
-        var hasDescription = item.moment && item.moment.description
-        return <Cell onClick={() => tapTimeline(item, index)} disable={!canTap(item)}>
-            <View key={index}
-                className="timeline_item"
-                style={{ backgroundColor: 'transparent' }}>
-                <View className="timeline_left">
-                    <View style={{
-
-                        height: hasDescription ? rpxToPx(28) : rpxToPx(36), flexShrink: 0
-                    }} />
-                    <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
-                        <View style={{
-                            flexShrink: 0,
-                            width: rpxToPx(26),
-                            height: rpxToPx(26),
-                            borderRadius: rpxToPx(13),
-                            marginRight: rpxToPx(8),
-                            display: 'flex',
-                            alignItems: 'center',
-                            justifyContent: 'center',
-                            backgroundColor: getIconColor(index)
-                        }}>
-                            {
-                                processIcon(index)
-                            }
-                        </View>
-                        <Text className="timeline_time" style={{ color: MainColorType.g01 }}>{itemTitle(item)}</Text>
-                    </View>
-
-
-                    <Text className="timeline_title"
-                        onClick={() => edit(item)}>{(item.moment && item.moment.title) ? item.moment.title : item.title}</Text>
-
+        function statusView() {
+            return <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
+                <View style={{
+                    flexShrink: 0,
+                    width: rpxToPx(26),
+                    height: rpxToPx(26),
+                    borderRadius: rpxToPx(13),
+                    marginRight: rpxToPx(8),
+                    display: 'flex',
+                    alignItems: 'center',
+                    justifyContent: 'center',
+                    backgroundColor: getIconColor(index),
+                }}>
                     {
-                        hasDescription && <Text className="timeline_desc" style={{ color: MainColorType.g02 }}>{item.moment.description}</Text>
+                        processIcon(index)
                     }
-                    {/* space */}
-                    <View style={{
-                        height: hasDescription ? rpxToPx(28) : rpxToPx(54), flexShrink: 0,
-
-                    }} />
-
                 </View>
-
-                {
-                    item.moment && item.moment.media && item.moment.media.length > 0 && <Image
-                        src={item.moment.media[0].url}
-                        mode="aspectFill"
-                        className="console_item_img" />
-                }
-                {
-                    itemValue(item)
-                }
-                <View className="border_footer_line" style={{ left: count - 1 == index ? -rpxToPx(52) : rpxToPx(52) }} />
+                <Text className="timeline_time" style={{ color: MainColorType.g01 }}>{itemTitle(item)}</Text>
             </View>
-        </Cell>
+        }
+
+        return <ConsoleCell
+            status={statusView()}
+            title={(item.moment && item.moment.title) ? item.moment.title : item.title}
+            description={item.moment ? item.moment.description : null}
+            right={itemValue(item)}
+            disable={!canTap(item)}
+            onClick={() => tapTimeline(item, index)}
+            showLine={true}
+            fullLine={count - 1 == index}
+        />
     }
 
     function timeContent() {
@@ -920,56 +900,44 @@ export default function MainConsole(props: { type: WindowType }) {
 
             </View>
         }
-
         {
             health.mode == 'ACTIVE' && <View>
-                <View className="main_column_space" />
-                <Cell onClick={() => {
-                    if (!user.isLogin) {
-                        jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
-                        return
-                    }
-                    jumpPage('/_health/pages/move')
-                }}>
-                    <View className="console_active" style={{ backgroundColor: 'transparent' }}>
-                        <Image className="active_icon" src={require('@assets/_health/walk.png')} />
-                        <Text className="active_text">Move More</Text>
-                        <IconArrow width={rpxToPx(34)} color={MainColorType.g03} />
-                    </View>
-                </Cell>
-            </View>
-
+                <View className="main_column_space" /><IconTitleCell
+                    icon={<Image className="active_icon" src={require('@assets/_health/walk.png')} />}
+                    title="Move More"
+                    onClick={() => {
+                        jumpPage('/_health/pages/move')
+                    }}
+                /></View>
         }
         {
             (health.mode == 'FAST' || health.mode == 'SLEEP') && <View >
                 <View className="main_column_space" />
-                <Cell onClick={() => {
-                    if (!user.isLogin) {
-                        jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
-                        return
-                    }
-                    if (health.long_fast.status == 'OG') {
-                        showAlert({
-                            title: '长断食进行中',
-                            content: '当前有一个正在进行的长断食记录,要转换为间歇性断食吗?',
-                            showCancel: true,
-                            cancelText: '取消',
-                            confirmText: '确定',
-                            confirm: () => {
-                                updateFast({ fast_type: 'IF' }).then(res => {
-                                    global.refreshWindow()
-                                    jumpPage('/_health/pages/fast_sleep')
-                                })
-                            }
-                        })
-                        return
-                    }
-                    jumpPage('/_health/pages/fast_sleep')
-                }}>
-                    <View className="console_active" style={{ backgroundColor: 'transparent' }}>
-                        <Image className="active_icon" src={require('@assets/_health/fast.png')} />
-                        <Text className="h34">Fast with sleep</Text>
-                        <View style={{ flex: 1 }} />
+                <IconTitleCell
+                    onClick={() => {
+
+                        if (health.long_fast.status == 'OG') {
+                            showAlert({
+                                title: '长断食进行中',
+                                content: '当前有一个正在进行的长断食记录,要转换为间歇性断食吗?',
+                                showCancel: true,
+                                cancelText: '取消',
+                                confirmText: '确定',
+                                confirm: () => {
+                                    updateFast({ fast_type: 'IF' }).then(res => {
+                                        global.refreshWindow()
+                                        jumpPage('/_health/pages/fast_sleep')
+                                    })
+                                }
+                            })
+                            return
+                        }
+                        jumpPage('/_health/pages/fast_sleep')
+                    }}
+                    showLine={health.mode == 'FAST'}
+                    icon={<Image className="active_icon" src={require('@assets/_health/fast.png')} />}
+                    title="Fast with sleep"
+                    desc={<View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
                         {
                             fastWithSleepStatus()
                         }
@@ -983,38 +951,23 @@ export default function MainConsole(props: { type: WindowType }) {
                                 marginRight: rpxToPx(12)
                             }} />
                         }
-                        <View style={{ width: rpxToPx(12) }} />
-                        <IconArrow width={rpxToPx(34)} color={MainColorType.g03} />
-                        {
-                            health.mode == 'FAST' && <View className="border_footer_line" style={{ left: rpxToPx(100) }} />
-                        }
-                    </View>
-                </Cell>
+                    </View>}
+                />
 
 
             </View>
         }
         {
-            health.mode == 'FAST' && <Cell onClick={() => {
-                if (!user.isLogin) {
-                    jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
-                    return
+            health.mode == 'FAST' && <IconTitleCell
+                onClick={() => {
+                    jumpPage('/_health/pages/long_fast')
+                }}
+                icon={<Image className="active_icon" src={require('@assets/_health/fast.png')} />}
+                title="Long fast"
+                desc={
+                    longFastStatus()
                 }
-                jumpPage('/_health/pages/long_fast')
-            }}><View>
-                    <View className="console_active" style={{ backgroundColor: 'transparent' }}>
-                        <Image className="active_icon" src={require('@assets/_health/fast.png')} />
-                        <Text className="h34">Long fast</Text>
-                        <View style={{ flex: 1 }} />
-                        {
-                            longFastStatus()
-                        }
-                        <View style={{ width: rpxToPx(12) }} />
-                        <IconArrow width={rpxToPx(34)} color={MainColorType.g03} />
-                    </View>
-
-                </View>
-            </Cell>
+            />
         }
         <View className="circle" />
         {

+ 13 - 13
src/features/health/MainHistory.tsx

@@ -14,6 +14,7 @@ import dayjs from "dayjs";
 import { MainColorType } from "@/context/themes/color";
 import { IconArrow, IconCellArrow } from "@/components/basic/Icons";
 import NoRecord from "@/_health/components/no_record";
+import ListFooter from "@/_health/components/list_footer";
 
 let lastMode = ''
 export default forwardRef((props: { type?: string, fast_type?: string, updateDate?: any, refreshSuccess?: any }, ref) => {
@@ -25,11 +26,13 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
     const refDemo = useRef()
     const health = useSelector((state: any) => state.health);
     const user = useSelector((state: any) => state.user);
+    const [loading, setLoading] = useState(false)
     const healthRef = useRef(health)
 
     useImperativeHandle(ref, () => ({
         onScroll: onScroll,
-        refresh: refresh
+        refresh: refresh,
+        more: more
     }))
 
     useEffect(() => {
@@ -117,6 +120,8 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
     }
 
     function more() {
+        if (loading) return;
+        if (total == list.length) return;
         var index = page;
         index++;
         setPage(index)
@@ -132,7 +137,10 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
         if (props.fast_type) {
             params.fast_type = props.fast_type
         }
+
+        setLoading(true)
         records(params).then(res => {
+            setLoading(false)
             setLoaded(true)
             if (index == 1) {
                 setList((res as any).data)
@@ -161,6 +169,8 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
             //     }, 1000)
             // }
 
+        }).catch(e => {
+            setLoading(false)
         })
     }
 
@@ -184,15 +194,7 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
             }
         }
         if (showDate) {
-            return <View className="h26" style={{
-                height: rpxToPx(84),
-                paddingLeft: rpxToPx(40),
-                display: 'flex',
-                flexDirection: 'row',
-                alignItems: 'center',
-                backgroundColor: '#fff',
-                color: MainColorType.g01
-            }}>{dateStr}</View>
+            return <View className="history_year_month h26 g01">{dateStr}</View>
         }
         return <View />
     }
@@ -287,8 +289,6 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
                 </View>
             })
         }
-        {
-            (list.length > 0) && (total == list.length) && <Text className="no_more">没有更多了</Text>
-        }
+        <ListFooter noMore={(list.length > 0) && (total == list.length)} />
     </View>
 })

+ 1 - 13
src/pages/account/Album.scss

@@ -25,23 +25,11 @@
     flex-direction: row;
     padding-top: 40px;
     padding-bottom: 44px;
+    padding-left: 40px;
     position: relative;
     background-color: #fff;
 }
 
-.album_date{
-    margin-left: 40px;
-    margin-right: 30px;
-    width: 68px;
-    height: 68px;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    color: #000;
-    font-size: 50px;
-    font-weight: bold;
-}
-
 .album_container{
     display: flex;
     flex-direction: row;

+ 36 - 21
src/pages/account/Album.tsx

@@ -12,6 +12,7 @@ import { getThemeColor } from "@/features/health/hooks/health_hooks";
 import dayjs from "dayjs";
 import Taro from "@tarojs/taro";
 import StickyDateList from "@/_health/components/sticky_date_list";
+import ListFooter from "@/_health/components/list_footer";
 
 export default function Album() {
 
@@ -22,30 +23,51 @@ export default function Album() {
     const [itemLayouts, setItemLayouts] = useState<any>([])
     const [showDate, setShowDate] = useState(false)
     const [date, setDate] = useState('')
+    const [page, setPage] = useState(1)
+    const [total, setTotal] = useState(0)
+    const [loading, setLoading] = useState(false)
 
     useEffect(() => {
         getAlbumsData('')
     }, [])
 
-    useEffect(()=>{
-        if (medias.length>0){
+    useEffect(() => {
+        if (medias.length > 0) {
             setTimeout(() => {
                 measureItemLayouts()
             }, 500)
         }
-    },[medias])
+    }, [medias])
+
+    function more() {
+        if (loading) return;
+        if (total == medias.length) return;
+        var index = page;
+        index++;
+        setPage(index)
+        getAlbumsData(window, index)
+    }
 
-    function getAlbumsData(str) {
+    function getAlbumsData(str, index = 1) {
         setIsPulling(true)
+        setLoading(true)
         getAlbums({
-            page: 1,
-            limit: 50,
+            page: index,
+            limit: 10,
             window: str
         }).then(res => {
-            setMedias((res as any).data)
+            if (index == 1) {
+                setMedias((res as any).data)
+                setTotal((res as any).total)
+            }
+            else {
+                setMedias([...medias, ...(res as any).data])
+            }
             setIsPulling(false)
+            setLoading(false)
 
-            
+        }).catch(e => {
+            setLoading(false)
         })
 
         getAlbumsStat().then(res => {
@@ -74,15 +96,7 @@ export default function Album() {
             }
         }
         if (showDate) {
-            return <View className="h26" style={{
-                height: rpxToPx(84),
-                paddingLeft: rpxToPx(40),
-                display: 'flex',
-                flexDirection: 'row',
-                alignItems: 'center',
-                backgroundColor: '#fff',
-                color: MainColorType.g01
-            }}>{dateStr}</View>
+            return <View className="history_year_month h26 g01">{dateStr}</View>
         }
         return <View />
     }
@@ -92,9 +106,7 @@ export default function Album() {
         medias.forEach((item, index) => {
             query.select(`#history-${index}`).boundingClientRect()
         });
-        debugger
         query.exec((res) => {
-            debugger
             var layouts: any = []
             res.forEach((rect, index) => {
                 if (rect) {
@@ -130,11 +142,13 @@ export default function Album() {
 
     return <StickyDateList onRefresherRefresh={() => {
         setIsPulling(true)
-        getAlbumsData(window)
+        setPage(1)
+        getAlbumsData(window,1)
     }} isPulling={isPulling}
         onScroll={onScroll}
         showDate={showDate}
         date={date}
+        loadMore={more}
     >
         <View style={{ display: 'flex', flexDirection: 'column' }}>
             <NewHeader type={NewHeaderType.left} title="Album" />
@@ -189,7 +203,7 @@ export default function Album() {
                         }
                         <View className="history_item2" >
 
-                            <Text className="history_date">{(item.date + '').substring(6, 9)}</Text>
+                            <Text className="cell_date">{(item.date + '').substring(6, 9)}</Text>
                             <View style={{ display: 'flex', flex: 1 }}>
                                 <View className="media" style={{ marginRight: item.images.length == 4 ? 80 : 0 }}>
                                     {
@@ -209,6 +223,7 @@ export default function Album() {
                     </View>
                 })
             }
+            <ListFooter noMore={(medias.length > 0) && (total == medias.length)} />
         </View>
     </StickyDateList>
 }

+ 1 - 13
src/pages/account/Journal.scss

@@ -22,25 +22,13 @@
 .album_item{
     display: flex;
     flex-direction: row;
+    padding-left: 40px;
     padding-top: 40px;
     padding-bottom: 28px;
     position: relative;
     background-color: #fff;
 }
 
-.album_date{
-    margin-left: 40px;
-    margin-right: 30px;
-    width: 68px;
-    height: 68px;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    color: #000;
-    font-size: 50px;
-    font-weight: bold;
-}
-
 .album_container{
     display: flex;
     flex-direction: row;

+ 162 - 42
src/pages/account/Journal.tsx

@@ -7,39 +7,118 @@ import dayjs from "dayjs";
 import { rpxToPx } from "@/utils/tools";
 import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
 import NewHeader, { NewHeaderType } from "@/_health/components/new_header";
+import Taro from "@tarojs/taro";
+import StickyDateList from "@/_health/components/sticky_date_list";
+import { MainColorType } from "@/context/themes/color";
+import ListFooter from "@/_health/components/list_footer";
 
 export default function Journal() {
     const [journals, setJournals] = useState<any>([])
+    const [isPulling, setIsPulling] = useState(false)
+    const [itemLayouts, setItemLayouts] = useState<any>([])
+    const [showDate, setShowDate] = useState(false)
+    const [date, setDate] = useState('')
+
+    const [page, setPage] = useState(1)
+    const [total, setTotal] = useState(0)
+    const [loading, setLoading] = useState(false)
+
     useEffect(() => {
-        getJounalsData()
+        getJounalsData(1)
     }, [])
 
-    function getJounalsData() {
+    useEffect(() => {
+        if (journals.length > 0) {
+            setTimeout(() => {
+                measureItemLayouts()
+            }, 500)
+        }
+    }, [journals])
+
+    function more() {
+        if (loading) return;
+        if (total == journals.length) return;
+        var index = page;
+        index++;
+        setPage(index)
+        getJounalsData(index)
+    }
+
+    function getJounalsData(index = 1) {
+        setLoading(true)
         getJournals({
-            page: 1,
-            limit: 50
+            page: index,
+            limit: 10
         }).then(res => {
-            let list = (res as any).data
-            list.forEach(element => {
-                let array: any = []
-                element.windows.map(item => {
-                    item.events.map(event => {
-                        event.moments && event.moments.map(moment => {
-                            if (moment.media && moment.media.length > 0) {
-                                moment.media.map(media => {
-                                    array.push(media.url)
-                                })
-                            }
-                        })
+            setLoading(false)
+            if (index == 1) {
+                let list = (res as any).data
+                // list.forEach(element => {
+                //     let array: any = []
+                //     element.windows.map(item => {
+                //         item.events.map(event => {
+                //             event.moments && event.moments.map(moment => {
+                //                 if (moment.media && moment.media.length > 0) {
+                //                     moment.media.map(media => {
+                //                         array.push(media.url)
+                //                     })
+                //                 }
+                //             })
 
-                    })
-                })
-                element.imgs = array
+                //         })
+                //     })
+                //     element.imgs = array
+                // });
+                setTotal((res as any).total)
+                setJournals((res as any).data)
+                setIsPulling(false)
+            }
+            else {
+                setJournals([...journals, ...(res as any).data])
+            }
+        }).catch(e => {
+            setLoading(false)
+        })
+    }
+
+    function measureItemLayouts() {
+        const query = Taro.createSelectorQuery()
+        journals.forEach((item, index) => {
+            query.select(`#history-${index}`).boundingClientRect()
+        });
+        query.exec((res) => {
+            var layouts: any = []
+            res.forEach((rect, index) => {
+                if (rect) {
+                    layouts[index] = rect.top
+                }
             });
-            setJournals((res as any).data)
+            setItemLayouts(layouts)
         })
     }
 
+    function onScroll(e) {
+        var top = e.detail.scrollTop
+        if (itemLayouts.length > 0) {
+            var i = -1
+            var date = ''
+            journals.forEach((item, index) => {
+                if (top >= itemLayouts[index] - 50) {
+                    i = index
+                    var currentDate = (journals[index].date + '').substring(0, 6)
+                    date = currentDate.substring(0, 4) + '年' + currentDate.substring(4, 6) + '月'
+                }
+            })
+
+            setShowDate(i != -1)
+            setDate(date)
+        }
+        else {
+            setShowDate(false)
+            setDate('')
+        }
+    }
+
     function getTitle(item) {
         if (item.title) {
             return item.title;
@@ -61,7 +140,7 @@ export default function Journal() {
                 }
             })
         })
-        return <View style={{ flex: 1, display: 'flex', flexDirection: 'row', marginBottom: rpxToPx(16),overflow:'hidden' }} key={index}>
+        return <View style={{ flex: 1, display: 'flex', flexDirection: 'row', marginBottom: rpxToPx(16), overflow: 'hidden' }} key={index}>
             {
                 array.length > 0 && <JournalCover imgs={array} />
             }
@@ -69,7 +148,7 @@ export default function Journal() {
                 display: 'flex',
                 flexDirection: 'column',
                 flex: 1,
-                overflow:'hidden',
+                overflow: 'hidden',
                 backgroundColor: array.length == 0 ? '#f5f5f5' : 'transparent',
                 padding: array.length == 0 ? rpxToPx(20) : 0,
                 marginRight: rpxToPx(40)
@@ -77,10 +156,10 @@ export default function Journal() {
                 {
 
                     window.events.map((item2, index2) => {
-                        return <Text className="line1" style={{width:array.length>0?rpxToPx(370):rpxToPx(532)}} key={index2 * 1000}>
+                        return <Text className="line1" style={{ width: array.length > 0 ? rpxToPx(370) : rpxToPx(532) }} key={index2 * 1000}>
                             <Text className="history_item_title" style={{ color: '#000' }}>{dayjs(item2.time.timestamp).format('HH:mm')} {getTitle(item2)} </Text>
                             {
-                                item2.moments && item2.moments.length>0 && item2.moments[0].description && <Text className="history_item_desc">{item2.moments[0].description}</Text>
+                                item2.moments && item2.moments.length > 0 && item2.moments[0].description && <Text className="history_item_desc">{item2.moments[0].description}</Text>
                             }
                         </Text>
                     })
@@ -92,25 +171,66 @@ export default function Journal() {
         </View>
     }
 
+    function historyMonth(index, preIndex) {
+        var showDate = false;
+        var dateStr = ''
+        if (index == 0) {
+            var currentDate = (journals[index].date + '').substring(0, 6)
+            var now = dayjs().format('YYYYMM')
+            if (currentDate != now) {
+                showDate = true
+                dateStr = currentDate.substring(0, 4) + '年' + currentDate.substring(4, 6) + '月'
+            }
+        }
+        else {
+            var currentDate = (journals[index].date + '').substring(0, 6)
+            var now = (journals[index - 1].date + '').substring(0, 6)
+            if (currentDate != now) {
+                showDate = true
+                // dateStr = currentDate
+                dateStr = currentDate.substring(0, 4) + '年' + currentDate.substring(4, 6) + '月'
+            }
+        }
+        if (showDate) {
+            return <View className="history_year_month h26 g01">{dateStr}</View>
+        }
+        return <View />
+    }
 
-    return <View style={{ display: 'flex', flexDirection: 'column' }}>
-        <NewHeader type={NewHeaderType.left} title="Journal" />
-        {
-            journals.map((item, index) => {
-                return <View className="album_item" key={index} onClick={() => {
-                    jumpPage('/pages/account/JournalDetail?detail=' + JSON.stringify(item))
-                }}>
-                    <Text className="album_date">{(item.date + '').substring(6, 9)}</Text>
-                    <View style={{ display: 'flex', flexDirection: 'column', flex: 1 }}>
+    return <StickyDateList onRefresherRefresh={() => {
+        setIsPulling(true)
+        getJounalsData()
+    }} isPulling={isPulling}
+        onScroll={onScroll}
+        showDate={showDate}
+        date={date}
+        loadMore={()=>{
+            more()
+        }}
+    ><View style={{ display: 'flex', flexDirection: 'column' }}>
+            <NewHeader type={NewHeaderType.left} title="Journal" />
+            {
+                journals.map((item, index) => {
+                    return <View key={index}>
                         {
-                            item.windows.map((window, i) => {
-                                return journalItem(window, i)
-                            })
+                            historyMonth(index, index - 1)
                         }
-                    </View>
-                    <View className="border_footer_line" />
-                </View>
-            })
-        }
-    </View>
+                        <View className="album_item" id={`history-${index}`} onClick={() => {
+                            jumpPage('/pages/account/JournalDetail?detail=' + JSON.stringify(item))
+                        }}>
+
+                            <Text className="cell_date">{(item.date + '').substring(6, 9)}</Text>
+                            <View style={{ display: 'flex', flexDirection: 'column', flex: 1 }}>
+                                {
+                                    item.windows.map((window, i) => {
+                                        return journalItem(window, i)
+                                    })
+                                }
+                            </View>
+                            <View className="border_footer_line" />
+                        </View></View>
+                })
+            }
+            <ListFooter noMore={(journals.length > 0) && (total == journals.length)} />
+        </View></StickyDateList>
 }

+ 66 - 68
src/pages/account/Profile.tsx

@@ -21,6 +21,7 @@ import dayjs from "dayjs";
 import { MainColorType } from "@/context/themes/color";
 import NewHeader, { NewHeaderType } from "@/_health/components/new_header";
 import { IconCellArrow, IconVip } from "@/components/basic/Icons";
+import IconTitleCell from "@/_health/components/icon_title_cell";
 
 let useNavigation, SwitchRN;
 if (process.env.TARO_ENV == 'rn') {
@@ -187,23 +188,14 @@ export default function Page() {
     }
 
     function goCalendar() {
-        if (!user.isLogin) {
-            jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
-        }
         jumpPage('/_health/pages/streak_calendar')
     }
 
     function goMetric() {
-        if (!user.isLogin) {
-            jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
-        }
         jumpPage('/pages/metric/Metric')
     }
 
     function goWeekly() {
-        if (!user.isLogin) {
-            jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
-        }
         jumpPage('/_health/pages/streak_weekly')
     }
 
@@ -293,13 +285,13 @@ export default function Page() {
                         color: user.isLogin ? '#000' : MainColorType.g02,
                         // marginLeft: rpxToPx(52),
                         // marginRight: rpxToPx(52),
-                        width:rpxToPx(640),
-                        textAlign:'center',
+                        width: rpxToPx(640),
+                        textAlign: 'center',
                         marginTop: rpxToPx(24),
                         marginBottom: rpxToPx(24),
-                        whiteSpace:'nowrap',
-                        overflow:'hidden',
-                        textOverflow:'ellipsis'
+                        whiteSpace: 'nowrap',
+                        overflow: 'hidden',
+                        textOverflow: 'ellipsis'
                     }}
                 >{user.isLogin ? user.nickname : t('page.more.un_login')}</Text>
                 <View className="avatar" style={{
@@ -329,69 +321,75 @@ export default function Page() {
                 }}
             >
                 <Image style={{ width: rpxToPx(228), height: rpxToPx(36), marginTop: rpxToPx(26) }} src={require('@assets/images/center_arrow.png')} />
-                <View className="profile_cell member_cell" style={{height:rpxToPx(172)}}>
+                <View className="profile_cell member_cell" style={{ height: rpxToPx(172) }}>
                     <View style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
-                        <View style={{display:'flex',flexDirection:'row',alignItems:'center',justifyContent:'center'}}>
-                            <IconVip width={rpxToPx(36)} color={MainColorType.blue}/>
-                            <View style={{width:rpxToPx(8)}}/>
+                        <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
+                            <IconVip width={rpxToPx(36)} color={MainColorType.blue} />
+                            <View style={{ width: rpxToPx(8) }} />
                             <View className="h34 bold" style={{ color: MainColorType.blue }}>成为 Pro 会员</View>
                         </View>
-                        
-                        <View className="h24" style={{ color: MainColorType.g02,marginTop:rpxToPx(12) }}>{isMember() ? memberdesc() : '解锁会员专项功能'}</View>
-                        <View style={{height:rpxToPx(18),flexShrink:0}}/>
+
+                        <View className="h24" style={{ color: MainColorType.g02, marginTop: rpxToPx(12) }}>{isMember() ? memberdesc() : '解锁会员专项功能'}</View>
+                        <View style={{ height: rpxToPx(18), flexShrink: 0 }} />
                     </View>
-                    <IconCellArrow color={MainColorType.g03} width={rpxToPx(34)}/>
+                    <IconCellArrow color={MainColorType.g03} width={rpxToPx(34)} />
                 </View>
             </View>
 
-            <View className="profile_cell profile_cell_space" onClick={goMetric}>
-                <Image src={require('@assets/_health/sit.png')} className="profile_cell_icon" />
-                <Text style={{ flex: 1 }}>Metric</Text>
-                <IconCellArrow color={MainColorType.g03} width={rpxToPx(34)}/>
-            </View>
-
-            <View className="profile_cell profile_cell_space" onClick={() => {
-                jumpPage('/pages/account/Album')
-            }}>
-                <Image src={require('@assets/_health/sit.png')} className="profile_cell_icon" />
-                <Text style={{ flex: 1 }}>Album</Text>
-                <IconCellArrow color={MainColorType.g03} width={rpxToPx(34)}/>
-                <View className="profile_cell_line" />
-            </View>
-            <View className="profile_cell" onClick={() => {
-                jumpPage('/pages/account/Journal')
-            }}>
-                <Image src={require('@assets/_health/sit.png')} className="profile_cell_icon" />
-                <Text style={{ flex: 1 }}>Journal</Text>
-                <IconCellArrow color={MainColorType.g03} width={rpxToPx(34)}/>
-            </View>
+            <View className="profile_cell_space" />
+            <IconTitleCell
+                onClick={goMetric}
+                title="Metric"
+                icon={<Image src={require('@assets/_health/sit.png')} className="profile_cell_icon" />}
+            />
 
-            <View className="profile_cell profile_cell_space" onClick={() => {
-                jumpPage("/_health/pages/schedules?mode=")
-            }}>
-                <Image src={require('@assets/_health/sit.png')} className="profile_cell_icon" />
-                <Text style={{ flex: 1 }}>Schedule</Text>
-                <IconCellArrow color={MainColorType.g03} width={rpxToPx(34)}/>
-                <View className="profile_cell_line" />
-            </View>
-            <View className="profile_cell" onClick={goCalendar}>
-                <Image src={require('@assets/_health/sit.png')} className="profile_cell_icon" />
-                <Text style={{ flex: 1 }}>Calendar</Text>
-                <IconCellArrow color={MainColorType.g03} width={rpxToPx(34)}/>
-                <View className="profile_cell_line" />
-            </View>
-            <View className="profile_cell" onClick={goWeekly}>
-                <Image src={require('@assets/_health/sit.png')} className="profile_cell_icon" />
-                <Text style={{ flex: 1 }}>Window</Text>
-                <IconCellArrow color={MainColorType.g03} width={rpxToPx(34)}/>
-            </View>
+            <View className="profile_cell_space" />
+            <IconTitleCell
+                onClick={() => {
+                    jumpPage('/pages/account/Album')
+                }}
+                title="Album"
+                showLine
+                icon={<Image src={require('@assets/_health/sit.png')} className="profile_cell_icon" />}
+            />
+            <IconTitleCell
+                onClick={() => {
+                    jumpPage('/pages/account/Journal')
+                }}
+                title="Journal"
+                icon={<Image src={require('@assets/_health/sit.png')} className="profile_cell_icon" />}
+            />
 
-            <View className="profile_cell profile_cell_space" onClick={goSetting}>
-                <Image src={require('@assets/_health/sit.png')} className="profile_cell_icon" />
-                <Text style={{ flex: 1 }}>Settings</Text>
-                <IconCellArrow color={MainColorType.g03} width={rpxToPx(34)}/>
-            </View>
-            <View style={{ height: 140,flexShrink:0 }}></View>
+            <View className="profile_cell_space" />
+            <IconTitleCell
+                onClick={() => {
+                    jumpPage('/_health/pages/schedules?mode=')
+                }}
+                title="Schedule"
+                showLine
+                icon={<Image src={require('@assets/_health/sit.png')} className="profile_cell_icon" />}
+            />
+            <IconTitleCell
+                onClick={goCalendar}
+                title="Calendar"
+                showLine
+                icon={<Image src={require('@assets/_health/sit.png')} className="profile_cell_icon" />}
+            />
+            <IconTitleCell
+                onClick={goWeekly}
+                title="Window"
+                showLine
+                icon={<Image src={require('@assets/_health/sit.png')} className="profile_cell_icon" />}
+            />
+
+            <View className="profile_cell_space" />
+            <IconTitleCell
+                onClick={goSetting}
+                title="Settings"
+                showLine
+                icon={<Image src={require('@assets/_health/sit.png')} className="profile_cell_icon" />}
+            />
+            <View style={{ height: 140, flexShrink: 0 }}></View>
 
         </View>
     }

+ 5 - 0
src/pages/clock/ClockNew.tsx

@@ -227,6 +227,11 @@ export default function ClockNew() {
                 global.refreshWindow()
                 setIsPulling(true)
             }}
+            loadMore={()=>{
+                if (historyRef) {
+                    (historyRef.current as any).more()
+                }
+            }}
             onScroll={e => {
                 if (e.detail.scrollTop > 240) {
                     dispatch(setTitle(pageTitle()))