leon 1 年之前
父節點
當前提交
a46f3191e6

+ 0 - 1
package.json

@@ -95,7 +95,6 @@
 		"intl": "^1.2.5",
 		"lodash": "^4.17.21",
 		"mathjs": "^12.3.0",
-		"miniprogram-recycle-view": "^0.1.5",
 		"moment": "^2.30.1",
 		"moment-timezone": "^0.5.45",
 		"react": "^18.1.0",

+ 2 - 1
src/_health/components/add_label.tsx

@@ -77,7 +77,8 @@ export default function AddLabel(props: {
         createSchedule({
             only_check: props.onlyCheck,
             schedules: array,
-            op_page: props.op_page ?? null
+            op_page: props.op_page ?? null,
+            sort_by:'EVENT'
         }).then(res => {
             if ((res as any).result) {
                 if (global.refreshWindow) {

+ 2 - 1
src/_health/components/new_header.tsx

@@ -9,9 +9,10 @@ export enum NewHeaderType {
     left = 'left',
     left_subtitle = 'left_subtitle'
 }
-export default function NewHeader(props: { type: NewHeaderType, title: string, subtitle?: string }) {
+export default function NewHeader(props: { type: NewHeaderType, title: string, subtitle?: string,whiteBg?:boolean }) {
     return <View className='new_header_bg' style={{
         alignItems: (props.type == NewHeaderType.center || props.type == NewHeaderType.center_subtitle) ? 'center' : 'flex-start',
+        backgroundColor:props.whiteBg?'#fff':'transparent'
     }}>
         <View className='h50 bold'>{props.title}</View>
         {

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

@@ -14,10 +14,12 @@ export default function StickyDateList(props: {
 }) {
 
     function headerDate() {
-        if (global.language == 'en') {
-            return props.date.substring(0, 4)
-        }
-        return props.date.substring(0, 5)
+        return props.date
+        // debugger
+        // if (global.language == 'en') {
+        //     return props.date.substring(0, 4)
+        // }
+        // return props.date.substring(0, 5)
     }
 
     return <View style={{ position: 'relative' }}>

+ 5 - 0
src/_health/components/timeline_date.scss

@@ -0,0 +1,5 @@
+.timeline_date_content {
+    width: 122px;
+    display: flex;
+    flex-direction: column;
+}

+ 89 - 0
src/_health/components/timeline_date.tsx

@@ -0,0 +1,89 @@
+import { View } from "@tarojs/components";
+import './timeline_date.scss'
+import dayjs from "dayjs";
+import { TimeFormatter } from "@/utils/time_format";
+import { rpxToPx } from "@/utils/tools";
+
+export default function TimelineDate(props: { timestamp: number, pre_timestamp?: number, isJournal?: boolean }) {
+    function isTimestampInThisWeek(timestamp) {
+        const date = new Date(timestamp);
+
+        // 获取当前日期
+        const now = new Date();
+
+        // 获取本周的第一天(周一)
+        const startOfWeek = new Date(now);
+        startOfWeek.setDate(now.getDate() - now.getDay() + 1); // 计算本周周一
+        startOfWeek.setHours(0, 0, 0, 0); // 设置为当天的开始时间
+
+        // 获取本周的最后一天(周日)
+        const endOfWeek = new Date(startOfWeek);
+        endOfWeek.setDate(startOfWeek.getDate() + 6); // 计算本周周日
+        endOfWeek.setHours(23, 59, 59, 999); // 设置为当天的结束时间
+
+        // 判断时间戳是否在本周范围内
+        return date >= startOfWeek && date <= endOfWeek;
+    }
+
+    function detail() {
+        if (props.pre_timestamp && dayjs(props.timestamp).format('YYYY-MM-DD') == dayjs(props.pre_timestamp).format('YYYY-MM-DD')) {
+            return ''
+        }
+        var title = ''
+        var subtitle = ''
+        var month = ''
+        if (TimeFormatter.isToday(props.timestamp)) {
+            if (props.isJournal) {
+                title = dayjs(props.timestamp).format('DD')
+                month = dayjs(props.timestamp).format('MMM')
+                subtitle = global.language == 'en' ? 'Today' : '今天'
+            }
+            else {
+                title = global.language == 'en' ? dayjs(props.timestamp).format('ddd') : '今天'
+                subtitle = global.language == 'en' ? 'Today' : dayjs(props.timestamp).format('ddd')
+            }
+
+            
+        }
+        else if (TimeFormatter.isYesterday(props.timestamp)) {
+            if (props.isJournal) {
+                title = dayjs(props.timestamp).format('DD')
+                month = dayjs(props.timestamp).format('MMM')
+                subtitle = global.language == 'en' ? 'Yesterday' : '昨天'
+            }
+            else {
+                title = global.language == 'en' ? dayjs(props.timestamp).format('ddd') : '昨天'
+                subtitle = global.language == 'en' ? 'Yesterday' : dayjs(props.timestamp).format('ddd')
+            }
+            
+        }
+        else if (isTimestampInThisWeek(props.timestamp)) {
+            if (props.isJournal) {
+                title = dayjs(props.timestamp).format('DD')
+                month = dayjs(props.timestamp).format('MMM')
+                subtitle = global.language == 'en' ?dayjs(props.timestamp).format('dddd'):dayjs(props.timestamp).format('ddd')
+            }
+            else {
+                title = dayjs(props.timestamp).format('ddd')
+            }
+        }
+        else {
+            title = dayjs(props.timestamp).format('DD')
+            month = dayjs(props.timestamp).format('MMM')
+        }
+        // title = 'Today'
+        return <View className="timeline_date_content">
+            <View style={{ display: 'flex', flexDirection: 'row' }}>
+                <View className="h42 w500" style={{ lineHeight: rpxToPx(60) + 'px' }}>{title}</View>
+                <View className="h24 w500" style={{ marginLeft: rpxToPx(6), marginTop: rpxToPx(13), lineHeight: rpxToPx(47) + 'px' }}>{month}</View>
+            </View>
+            <View className="h24 w300 g02">{subtitle}</View>
+        </View>
+    }
+
+    return <View className="timeline_date_content">
+        {
+            detail()
+        }
+    </View>
+}

+ 1 - 1
src/_health/pages/archive.tsx

@@ -215,7 +215,7 @@ export default function Archive() {
             list.forEach((item, index) => {
                 if (top >= itemLayouts[index] - 50) {
                     i = index
-                    date = dayjs(item.window_range.start_timestamp).format('YYYY年M月')
+                    date = global.language=='en'?dayjs(item.window_range.start_timestamp).format('MMMM YYYY'):dayjs(item.window_range.start_timestamp).format('YYYY年M月')
                 }
             })
 

+ 1 - 0
src/_health/pages/fast_sleep.tsx

@@ -24,6 +24,7 @@ let scrollTop = 0
 export default function FastSleep() {
     const health = useSelector((state: any) => state.health);
     const [showPopCard, setShowPopCard] = useState(false)
+    const [posting,setPosting] = useState(false)
     const [time, setTime] = useState(dayjs().format('HH:mm'))
     const [count, setCount] = useState(0)
 

+ 14 - 1
src/_health/pages/guide_active.tsx

@@ -42,6 +42,7 @@ export default function GuideActive() {
     const [highlight, setHighlight] = useState(true)
     const [showModal, setShowModal] = useState(false)
     const [labels, setLabels] = useState<any>([])
+    const [posting, setPosting] = useState(false)
     const { t } = useTranslation()
 
     let navigation, showActionSheetWithOptions;
@@ -64,6 +65,10 @@ export default function GuideActive() {
     }, [])
 
     function check(array, tapDone = false) {
+        if (tapDone) {
+            if (posting) return
+            setPosting(true)
+        }
         createSchedule({
             schedules: array,
             only_check: true,
@@ -85,6 +90,9 @@ export default function GuideActive() {
                 dispatch(setFooter((res as any).footer))
                 setErrors((res as any).error_messages ? (res as any).error_messages : [])
             }
+            setPosting(false)
+        }).catch(e => {
+            setPosting(false)
         })
     }
 
@@ -182,6 +190,10 @@ export default function GuideActive() {
                                 return
                             }
                             delSchedule(obj.id).then(res => {
+                                var temps = JSON.parse(JSON.stringify(health.schedules))
+                                var temps2 = temps.filter(item => item.id != obj.id)
+                                dispatch(setSchedules(temps2))
+
                                 dispatch(setFooter((res as any).footer))
                                 var array = JSON.parse(JSON.stringify(list))
                                 for (var j = 0; j < array.length; j++) {
@@ -228,7 +240,7 @@ export default function GuideActive() {
                 items.map((obj, i) => {
                     return <ScheduleItem
                         index={i}
-                        count={items.length + 1}
+                        count={items.length}
                         key={i * 100}
                         obj={obj}
                         highlight={false}
@@ -349,6 +361,7 @@ export default function GuideActive() {
                 disMiss={() => setShowModal(false)}
                 onlyCheck={true}
                 schedules={list}
+                op_page='SCHEDULE_WALKTHROUGH_4'
                 confirm={(res) => {
                     setShowModal(false)
                     if ((res as any).result) {

+ 44 - 5
src/_health/pages/guide_eat.tsx

@@ -42,6 +42,7 @@ export default function GuideEat() {
     const [highlight, setHighlight] = useState(true)
     const [showModal, setShowModal] = useState(false)
     const [labels, setLabels] = useState<any>([])
+    const [posting, setPosting] = useState(false)
     const { t } = useTranslation()
 
     let navigation, showActionSheetWithOptions;
@@ -64,7 +65,37 @@ export default function GuideEat() {
 
     }, [])
 
+    useEffect(() => {
+
+
+        var temps: any = []
+        list.map(item => {
+            if (item.id) {
+                var isFind = false
+                health.schedules.map(obj => {
+                    if (obj.id == item.id) {
+                        isFind = true
+                    }
+                })
+                if (!isFind) {
+                    temps.push(item)
+                }
+            }
+
+        })
+        var array = JSON.parse(JSON.stringify(list))
+        var filterArray = array.filter(item => !temps.some(itemA => itemA.id == item.id))
+        setList(filterArray)
+
+
+    }, [health.schedules])
+
     function check(array, tapDone = false) {
+        if (tapDone) {
+            if (posting) return
+            setPosting(true)
+        }
+
         createSchedule({
             schedules: array,
             only_check: true,
@@ -86,6 +117,9 @@ export default function GuideEat() {
                 dispatch(setFooter((res as any).footer))
                 setErrors((res as any).error_messages ? (res as any).error_messages : [])
             }
+            setPosting(false)
+        }).catch(e => {
+            setPosting(false)
         })
     }
 
@@ -165,14 +199,18 @@ export default function GuideEat() {
                                 })
                                 return
                             }
-                            if (errors.length>0){
+                            if (errors.length > 0) {
                                 Taro.showToast({
-                                    title:'请先解决冲突',
-                                    icon:'none'
+                                    title: '请先解决冲突',
+                                    icon: 'none'
                                 })
                                 return
                             }
                             delSchedule(obj.id).then(res => {
+                                var temps = JSON.parse(JSON.stringify(health.schedules))
+                                var temps2 = temps.filter(item => item.id != obj.id)
+                                dispatch(setSchedules(temps2))
+
                                 dispatch(setFooter((res as any).footer))
                                 var array = JSON.parse(JSON.stringify(list))
                                 for (var j = 0; j < array.length; j++) {
@@ -213,13 +251,13 @@ export default function GuideEat() {
     }
 
     function fastSleepItems() {
-        var items = list.filter(item => item.window == 'FAST' || item.window == 'SLEEP')
+        var items = list.filter(item => item.window == 'FAST')
         return <Card>
             {
                 items.map((obj, i) => {
                     return <ScheduleItem
                         index={i}
-                        count={items.length + 1}
+                        count={items.length}
                         key={i * 100}
                         obj={obj}
                         highlight={false}
@@ -326,6 +364,7 @@ export default function GuideEat() {
         {
             showModal && <AddLabel labels={labels}
                 window='EAT'
+                op_page='SCHEDULE_WALKTHROUGH_3'
                 disMiss={() => setShowModal(false)}
                 onlyCheck={true}
                 schedules={list}

+ 6 - 1
src/_health/pages/guide_full.tsx

@@ -27,7 +27,7 @@ export default function GuideFull() {
 
     const health = useSelector((state: any) => state.health);
     const [errors, setErrors] = useState<any>([])
-
+    const [posting,setPosting] = useState(false)
     const [selItem, setSelItem] = useState<any>(null)
     const { t } = useTranslation()
 
@@ -37,6 +37,8 @@ export default function GuideFull() {
     }, [])
 
     function commit() {
+        if (posting) return
+        setPosting(true)
         createSchedule({
             schedules: health.schedules,
             op_page: 'SCHEDULE_FINISH_SETUP'
@@ -49,6 +51,9 @@ export default function GuideFull() {
             }
             jumpPage('./post_result?type=schedule&data=' + JSON.stringify(data))
             global.refreshWindow()
+            setPosting(false)
+        }).catch(e=>{
+            setPosting(false)
         })
 
 

+ 37 - 4
src/_health/pages/guide_sleep.tsx

@@ -31,6 +31,7 @@ export default function GuideSleep() {
     const [highlight, setHighlight] = useState(true)
     const [list, setList] = useState<any>(health.schedules)
     const [showPopCard, setShowPopCard] = useState(false)
+    const [posting, setPosting] = useState(false)
     const { t } = useTranslation()
     const dispatch = useDispatch()
     const selMode = 'SLEEP'
@@ -40,7 +41,36 @@ export default function GuideSleep() {
         }, 2000)
     }, [])
 
+    useEffect(() => {
+
+
+        var temps: any = []
+        list.map(item => {
+            if (item.id) {
+                var isFind = false
+                health.schedules.map(obj => {
+                    if (obj.id == item.id) {
+                        isFind = true
+                    }
+                })
+                if (!isFind) {
+                    temps.push(item)
+                }
+            }
+
+        })
+        var array = JSON.parse(JSON.stringify(list))
+        var filterArray = array.filter(item => !temps.some(itemA => itemA.id == item.id))
+        setList(filterArray)
+
+
+    }, [health.schedules])
+
     function check(array, tapDone = false) {
+        if (tapDone) {
+            if (posting) return
+            setPosting(true)
+        }
         createSchedule({
             schedules: array,
             only_check: true,
@@ -62,6 +92,9 @@ export default function GuideSleep() {
                 dispatch(setFooter((res as any).footer))
                 setErrors((res as any).error_messages ? (res as any).error_messages : [])
             }
+            setPosting(false)
+        }).catch(e => {
+            setPosting(false)
         })
     }
 
@@ -87,10 +120,10 @@ export default function GuideSleep() {
     }
 
     function more() {
-        if (errors.length>0){
+        if (errors.length > 0) {
             Taro.showToast({
-                title:'请先解决冲突',
-                icon:'none'
+                title: '请先解决冲突',
+                icon: 'none'
             })
             return;
         }
@@ -177,7 +210,7 @@ export default function GuideSleep() {
         }
     }
 
-    function totalDetail(str){
+    function totalDetail(str) {
         return <View className="g02 h24 bold">{str}</View>
     }
 

二進制
src/assets/_health/compass.png


二進制
src/assets/_health/compass_sel.png


二進制
src/assets/_health/home.png


二進制
src/assets/_health/home_sel.png


二進制
src/assets/_health/user.png


二進制
src/assets/_health/user_sel.png


+ 21 - 6
src/components/navigation/TabBar.scss

@@ -28,25 +28,40 @@
 /* #endif */
 
 .tabbar-item{
-    color: rgba(255,255,255,0.4);
-    font-size: 36px;
-    line-height: 36px;
+    // color: rgba(255,255,255,0.4);
+    // font-size: 36px;
+    // line-height: 36px;
     display: flex;
+    flex-direction: column;
     flex: 1;
     align-items: center;
     justify-content: center;
-    font-weight: bold;
+    // font-weight: bold;
     position: relative;
 }
 
 .tabbar-item-sel{
     color: #ffffff;
-    font-size: 40px;
-    line-height: 40px;
+    // font-size: 40px;
+    // line-height: 40px;
     font-weight: bold;
     position: relative;
 }
 
+.tabbar-item-text{
+    font-weight: 500;
+    margin-top: 4px;
+    font-size: 20px;
+    color: #999999;
+}
+
+.tabbar-item-text-sel{
+    font-weight: 500;
+    margin-top: 4px;
+    font-size: 20px;
+    color: #000000;
+}
+
 .food-tab-badge{
     position: absolute;
     width: 20px;

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

@@ -5,10 +5,12 @@ import { useState } from 'react';
 import { useSelector } from 'react-redux';
 import { ColorType } from '@/context/themes/color';
 import { rpxToPx } from '@/utils/tools';
+import { useTranslation } from 'react-i18next';
 
 export default function Component(props: { index: number }) {
     const common = useSelector((state: any) => state.common);
     const [selIndex] = useState(props.index)
+    const {t} = useTranslation()
     function switchTab(index: number) {
         switch (index) {
             case 0:
@@ -53,12 +55,15 @@ export default function Component(props: { index: number }) {
         </View>
         <View className={selIndex == 0 ? 'tabbar-item tabbar-item-sel' : 'tabbar-item'} onClick={() => switchTab(0)}>
             <Image className='tabbar-icon' src={selIndex == 0 ?require('@assets/_health/home_sel.png'):require('@assets/_health/home.png')}/>
+            <View className={selIndex==0?'tabbar-item-text-sel':'tabbar-item-text'}>{t('health.today')}</View>
         </View>
         <View className={selIndex == 1 ? 'tabbar-item tabbar-item-sel' : 'tabbar-item'} onClick={() => switchTab(1)}>
-            <Image className='tabbar-icon' src={selIndex == 1 ?require('@assets/_health/home_sel.png'):require('@assets/_health/home.png')}/>
+            <Image className='tabbar-icon' src={selIndex == 1 ?require('@assets/_health/compass_sel.png'):require('@assets/_health/compass.png')}/>
+            <View className={selIndex==1?'tabbar-item-text-sel':'tabbar-item-text'}>{t('health.discover')}</View>
         </View>
         <View className={selIndex == 3 ? 'tabbar-item tabbar-item-sel' : 'tabbar-item'} onClick={() => switchTab(3)}>
             <Image className='tabbar-icon' src={selIndex == 3 ?require('@assets/_health/user_sel.png'):require('@assets/_health/user.png')}/>
+            <View className={selIndex==3?'tabbar-item-text-sel':'tabbar-item-text'}>{t('health.me')}</View>
         </View>
     </View>
 }

+ 2 - 0
src/context/locales/en.js

@@ -1016,5 +1016,7 @@ export default {
         settings:'Settings',
         
         discover:'Discover',
+        this_week:'This Week',
+        me:'Me'
     }
 }

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

@@ -1017,6 +1017,8 @@ export default {
         windows:'时段统计',
         settings:'设置',
 
-        discover:'发现'
+        discover:'发现',
+        this_week:'本周',
+        me:'我'
     }
 }

+ 3 - 2
src/features/health/HeaderCircadian.tsx

@@ -33,7 +33,8 @@ export default function HeaderCircadian() {
     }, [health])
 
     useEffect(() => {
-        checkTip()
+        if (health.mode != '')
+            checkTip()
     }, [health.mode])
 
     function checkTip() {
@@ -41,7 +42,7 @@ export default function HeaderCircadian() {
 
 
 
-        if (health && health.windows) {
+        if (health && health.windows && health.mode !='') {
             setShowTip(true)
             setIcon(health.mode)
 

+ 11 - 4
src/features/health/HistoryItem.tsx

@@ -22,6 +22,7 @@ import TargetProgress from "@/_health/components/target_progress";
 import Cell from "@/_health/base/cell";
 import { setFirstActiveId, setFirstEatId } from "@/store/health";
 import JournalCover from "../journal/components/journal_cover";
+import TimelineDate from "@/_health/components/timeline_date";
 
 export default function HistoryItem(props: {
     data: any,
@@ -277,10 +278,13 @@ export default function HistoryItem(props: {
 
     function temp() {
         return <View className="history_item2" onClick={goDetail}>
-            <View className="cell_date" >
+            {/* <View className="cell_date" >
                 <View className="h42 w500" style={{ lineHeight: rpxToPx(60) + 'px' }}>{historyDate()}</View>
                 <View className="h24 w500" style={{ marginLeft: rpxToPx(6), marginTop: rpxToPx(13), lineHeight: rpxToPx(47) + 'px' }}>{historyMonth()}</View>
-            </View>
+            </View> */}
+            <TimelineDate timestamp={props.data.window_range.start_timestamp}
+                pre_timestamp={props.preData?props.preData.window_range.start_timestamp:null}
+            />
             <View className="history_content" style={{ paddingTop: rpxToPx(4) }}>
                 {
                     props.data.dataArray.map((content, i) => {
@@ -638,10 +642,13 @@ export default function HistoryItem(props: {
     }
 
     return <View className="history_item2" onClick={goDetail}>
-        <View className="cell_date" >
+        {/* <View className="cell_date" >
             <View className="h42 w500" style={{ lineHeight: rpxToPx(60) + 'px' }}>{historyDate()}</View>
             <View className="h24 w500" style={{ marginLeft: rpxToPx(6), marginTop: rpxToPx(13), lineHeight: rpxToPx(47) + 'px' }}>{historyMonth()}</View>
-        </View>
+        </View> */}
+        <TimelineDate timestamp={props.data.window_range.start_timestamp}
+                pre_timestamp={props.preData?props.preData.window_range.start_timestamp:null}
+            />
         <View className="history_content" style={{ paddingTop: rpxToPx(0) }}>
             {
                 props.mode != 'EAT' && props.mode != 'ACTIVE' && props.data.dataArray.map((content, i) => {

+ 3 - 1
src/features/health/MainConsole.tsx

@@ -633,7 +633,7 @@ export default function MainConsole(props: { type: WindowType }) {
                 break;
             case 'ACTIVE':
                 list = active.timeline
-                if (active.onboard == false) {
+                if (active.onboard == false && active.status == 'WFS') {
                     var seconds = new Date().getSeconds()
 
                     // return <Swiper autoplay>
@@ -1013,6 +1013,8 @@ export default function MainConsole(props: { type: WindowType }) {
         // </View>
     }
 
+    if (health.mode=='') return <View />
+
     return <View className="main-console-bg">
         <Image className="main_arrow" src={require('@assets/images/center_arrow.png')} />
         <View className="main_summary">

+ 5 - 3
src/features/health/MainDayNightCard.tsx

@@ -25,10 +25,11 @@ export default function MainDayNightCard(props: {
     onClick: Function,
     scale: number
 }) {
-    const [isDay, setIsDay] = useState(true)
-    const [isDayMode, setIsDayMode] = useState(true)
-    const user = useSelector((state: any) => state.user);
     const health = useSelector((state: any) => state.health);
+    const [isDay, setIsDay] = useState(isCurrentTimeInRange(health.windows.night_day.day.period.start_time, health.windows.night_day.day.period.end_time))
+    const [isDayMode, setIsDayMode] = useState(isCurrentTimeInRange(health.windows.night_day.day.period.start_time, health.windows.night_day.day.period.end_time))
+    const user = useSelector((state: any) => state.user);
+    
     const dispatch = useDispatch();
     const {t} = useTranslation()
 
@@ -52,6 +53,7 @@ export default function MainDayNightCard(props: {
 
     useEffect(() => {
         if (health.mode == 'DAY') {
+            debugger
             setIsDayMode(true)
         }
         else if (health.mode == 'NIGHT') {

+ 46 - 11
src/features/health/MainHistory.tsx

@@ -144,7 +144,6 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
     }, [health.mode])
 
     function measureItemLayouts() {
-        console.log(new Date().getTime())
         const query = Taro.createSelectorQuery()
         list.forEach((item, index) => {
             query.select(`#history-${index}`).boundingClientRect()
@@ -160,12 +159,29 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
             });
             setItemLayouts(layouts)
             setItemHeights(heights)
-            debugger
-
-            console.log(new Date().getTime())
         })
     }
 
+    function isTimestampInThisWeek(timestamp) {
+        const date = new Date(timestamp);
+
+        // 获取当前日期
+        const now = new Date();
+
+        // 获取本周的第一天(周一)
+        const startOfWeek = new Date(now);
+        startOfWeek.setDate(now.getDate() - now.getDay() + 1); // 计算本周周一
+        startOfWeek.setHours(0, 0, 0, 0); // 设置为当天的开始时间
+
+        // 获取本周的最后一天(周日)
+        const endOfWeek = new Date(startOfWeek);
+        endOfWeek.setDate(startOfWeek.getDate() + 6); // 计算本周周日
+        endOfWeek.setHours(23, 59, 59, 999); // 设置为当天的结束时间
+
+        // 判断时间戳是否在本周范围内
+        return date >= startOfWeek && date <= endOfWeek;
+    }
+
     function onScroll(e) {
         // var top = e.detail.scrollTop
         // myScrollTop = top
@@ -180,7 +196,18 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
             list.forEach((item, index) => {
                 if (top >= itemLayouts[index] - 50) {
                     i = index
-                    date = dayjs(item.window_range.start_timestamp).format('YYYY年M月')
+                    if (isTimestampInThisWeek(item.window_range.start_timestamp)) {
+                        date = t('health.this_week')
+                    }
+                    else if (dayjs(item.window_range.start_timestamp).format('YYYY') == dayjs().format('YYYY')) {
+                        date = global.language == 'en' ? dayjs(item.window_range.start_timestamp).format('MMMM') : dayjs(item.window_range.start_timestamp).format('MMMM')
+                    }
+                    else {
+                        date = global.language == 'en' ? dayjs(item.window_range.start_timestamp).format('MMMM YYYY') : dayjs(item.window_range.start_timestamp).format('YYYY年M月')
+                    }
+
+
+
                 }
             })
             if (props.updateDate) {
@@ -202,6 +229,7 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
     }
 
     function refresh() {
+
         loadData(1)
         setPage(1)
     }
@@ -332,6 +360,13 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
 
 
     function loadData(index: number) {
+        // console.log('load data, page',index)
+        if (index == 1) {
+            Taro.setStorage({
+                key: 'lastRefresh',
+                data: new Date().getTime() + ''
+            })
+        }
         var params: any = {
             window: props.type ? props.type : health.mode,
             limit: 10,
@@ -579,12 +614,12 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
                         var data = list[0]
                         jumpPage(`/_health/pages/timeline_detail?window_id=${data.window_id}&type=recent&isfastsleep=0&timestamp=${data.publish.timestamp}`)
 
-                        getLatestJournal(false, {
-                            id: health.mode == 'EAT' ? global.eatTipId : global.activeTipId,
-                            user_confirmed: true
-                        }).then(res => {
+                        // getLatestJournal(false, {
+                        //     id: health.mode == 'EAT' ? global.eatTipId : global.activeTipId,
+                        //     user_confirmed: true
+                        // }).then(res => {
 
-                        })
+                        // })
                         setTimeout(() => {
                             if (health.mode == 'EAT') {
                                 dispatch(setEatTip(false))
@@ -752,7 +787,7 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
             list.length > 0 && <View style={{ minHeight: rpxToPx(464), backgroundColor: '#fff', paddingTop: rpxToPx(60) }}>
                 {
                     list.map((item, index) => {
-                        if (itemLayouts.length >= index + 1 && index>5) {
+                        if (itemLayouts.length >= index + 1 && index > 5) {
                             if (Math.abs(itemLayouts[index] - pageTop) > 2500) {
                                 return <View style={{ height: itemHeights[index] }} id={`history-${index}`} key={index}>
                                     {

+ 39 - 11
src/features/health/MainHistory2.tsx

@@ -71,7 +71,7 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
 
     useEffect(() => {
         // if (props.type == 'FAST,SLEEP' || (props.fast_type && props.fast_type == 'LF')) {
-            
+
         // }
         // else {
         //     global.refreshHistory = () => {
@@ -155,6 +155,26 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
         })
     }
 
+    function isTimestampInThisWeek(timestamp) {
+        const date = new Date(timestamp);
+
+        // 获取当前日期
+        const now = new Date();
+
+        // 获取本周的第一天(周一)
+        const startOfWeek = new Date(now);
+        startOfWeek.setDate(now.getDate() - now.getDay()+1); // 计算本周周一
+        startOfWeek.setHours(0, 0, 0, 0); // 设置为当天的开始时间
+
+        // 获取本周的最后一天(周日)
+        const endOfWeek = new Date(startOfWeek);
+        endOfWeek.setDate(startOfWeek.getDate() + 6); // 计算本周周日
+        endOfWeek.setHours(23, 59, 59, 999); // 设置为当天的结束时间
+
+        // 判断时间戳是否在本周范围内
+        return date >= startOfWeek && date <= endOfWeek;
+    }
+
     function onScroll(e) {
         // var top = e.detail.scrollTop
         // myScrollTop = top
@@ -167,7 +187,15 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
             list.forEach((item, index) => {
                 if (top >= itemLayouts[index] - 50) {
                     i = index
-                    date = dayjs(item.window_range.start_timestamp).format('YYYY年M月')
+                    if (isTimestampInThisWeek(item.window_range.start_timestamp)) {
+                        date = t('health.this_week')
+                    }
+                    else if (dayjs(item.window_range.start_timestamp).format('YYYY')==dayjs().format('YYYY')){
+                        date = global.language=='en'?dayjs(item.window_range.start_timestamp).format('MMMM'):dayjs(item.window_range.start_timestamp).format('MMMM')
+                    }
+                    else {
+                        date = global.language == 'en' ? dayjs(item.window_range.start_timestamp).format('MMMM YYYY') : dayjs(item.window_range.start_timestamp).format('YYYY年M月')
+                    }
                 }
             })
             if (props.updateDate) {
@@ -503,7 +531,7 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
             }
         }
         if (showDate) {
-            return <View className="history_year_month h42 bold" style={{marginBottom:rpxToPx(60)}}>{dateStr}</View>
+            return <View className="history_year_month h42 bold" style={{ marginBottom: rpxToPx(60) }}>{dateStr}</View>
         }
         return <View />
     }
@@ -609,12 +637,12 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
                         var data = list[0]
                         jumpPage(`/_health/pages/timeline_detail?window_id=${data.window_id}&type=recent&isfastsleep=0&timestamp=${data.publish.timestamp}`)
 
-                        getLatestJournal(false, {
-                            id: health.mode == 'EAT' ? global.eatTipId : global.activeTipId,
-                            user_confirmed: true
-                        }).then(res => {
+                        // getLatestJournal(false, {
+                        //     id: health.mode == 'EAT' ? global.eatTipId : global.activeTipId,
+                        //     user_confirmed: true
+                        // }).then(res => {
 
-                        })
+                        // })
                         setTimeout(() => {
                             if (health.mode == 'EAT') {
                                 dispatch(setEatTip(false))
@@ -710,10 +738,10 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
             list.length == 0 && <NoRecord />
         }
         {
-            list.length > 0 && <View style={{ minHeight: rpxToPx(464), backgroundColor: '#fff',paddingTop:rpxToPx(60) }}>
+            list.length > 0 && <View style={{ minHeight: rpxToPx(464), backgroundColor: '#fff', paddingTop: rpxToPx(60) }}>
                 {
                     list.map((item, index) => {
-                        if (itemLayouts.length >= index + 1 && index>5) {
+                        if (itemLayouts.length >= index + 1 && index > 5) {
                             if (Math.abs(itemLayouts[index] - pageTop) > 2500) {
                                 return <View style={{ height: itemHeights[index] }} id={`history-${index}`} key={index}>
                                     {
@@ -746,6 +774,6 @@ export default forwardRef((props: { type?: string, fast_type?: string, updateDat
 
 
         {/* <View style={{ height: rpxToPx(40), flexShrink: 0, backgroundColor: '#fff' }} /> */}
-        <ListFooter noMore={(list.length > 0) && (total == list.length)} loading={loading}/>
+        <ListFooter noMore={(list.length > 0) && (total == list.length)} loading={loading} />
     </View>
 })

+ 18 - 6
src/pages/account/Journal.tsx

@@ -20,6 +20,7 @@ import { useSelector } from "react-redux";
 import { IconClose } from "@/components/basic/Icons";
 import TargetProgress from "@/_health/components/target_progress";
 import NoRecord from "@/_health/components/no_record";
+import TimelineDate from "@/_health/components/timeline_date";
 
 let myScrollTop = 0
 let useRoute;
@@ -179,8 +180,7 @@ export default function Journal() {
             journals.forEach((item, index) => {
                 if (top >= itemLayouts[index] - 50) {
                     i = index
-                    var currentDate = (journals[index].date + '').substring(0, 6)
-                    dt = currentDate.substring(0, 4) + '年' + currentDate.substring(4, 6) + '月'
+                    dt = global.language=='en'?dayjs(item.timestamp).format('MMMM YYYY'):dayjs(item.timestamp).format('YYYY年M月')
                 }
             })
 
@@ -433,6 +433,7 @@ export default function Journal() {
                                 />
                             })
                         }
+                        {/* <Text style={{backgroundColor:'pink'}}>...</Text> */}
 
 
 
@@ -475,6 +476,13 @@ export default function Journal() {
         return t('health.title_journal')
     }
 
+    function pageYear(){
+        if (!loaded) return ''
+        if (journals.length==0) return global.language == 'en'?dayjs().format('YYYY'):dayjs().format('YYYY年')
+        if (journals[0].timestamp) return global.language == 'en'?dayjs(journals[0].timestamp).format('YYYY'):dayjs(journals[0].timestamp).format('YYYY年')
+        return ''
+    }
+
     function markDoneTip() {
         if (health.mode != 'EAT' && health.mode != 'ACTIVE') return
         var scenario = getScenario(health.windows, health.mode)
@@ -581,11 +589,15 @@ export default function Journal() {
         return <View className="history_item2" id={`history-${index}`} onClick={() => {
             jumpPage('/pages/account/JournalDetail?date=' + item.date + '&window=' + window) //JSON.stringify(item))
         }}>
-
-            <View className="cell_date" >
+            <TimelineDate 
+                timestamp={item.timestamp}
+                pre_timestamp={index>0?journals[index - 1].timestamp:null}
+                isJournal
+            />
+            {/* <View className="cell_date" >
                 <View className="h42 bold" style={{ lineHeight: rpxToPx(60) + 'px' }}>{historyDate(item, index)}</View>
                 <View className="h24 bold" style={{ marginLeft: rpxToPx(6), marginTop: rpxToPx(13), lineHeight: rpxToPx(47) + 'px' }}>{historyMonth(item, index)}</View>
-            </View>
+            </View> */}
             <View style={{ display: 'flex', flexDirection: 'column', flex: 1, width: rpxToPx(552), }}>
                 {
                     journalCell(item, index)
@@ -607,7 +619,7 @@ export default function Journal() {
         }}
     ><View style={{ display: 'flex', flexDirection: 'column', minHeight: rpxToPx(464), backgroundColor: '#f5f5f5' }}>
 
-            <NewHeader type={NewHeaderType.left} title={pageTitle()} />
+            <NewHeader type={NewHeaderType.left} title={pageYear()} whiteBg/>
             {
                 markDoneTip()
             }

+ 2 - 3
src/pages/clock/Clock.tsx

@@ -60,7 +60,6 @@ export default function Clock() {
     }
 
     useEffect(() => {
-        var aa = Taro.getSystemSetting()
         if (navigation) {
             navigation.setOptions({
                 headerTitle: '',
@@ -135,7 +134,7 @@ export default function Clock() {
     function haveStreaks() {
 
 
-        if (user.isLogin && health.windows) {
+        if (user.isLogin && health.windows && health.mode.length>0) {
             const scenario = getScenario(health.windows, health.mode)
             if (scenario.current_streak) {
                 return true
@@ -231,7 +230,7 @@ export default function Clock() {
     function onScroll(e) {
         scrollTop = e.detail.scrollTop
 
-        setShowStreak(scrollTop < 240)
+        setShowStreak(scrollTop < 20)
     }
 
     if (!loaded)

+ 32 - 53
src/pages/clock/ClockNew.tsx

@@ -74,7 +74,33 @@ export default function ClockNew(props: { children: any, onScroll: any }) {
 
     function refreshData() {
         global.refreshWindow()
-        global.refreshHistory()
+        Taro.getStorage({
+            key: 'lastRefresh',
+            success: function (res) {
+                if (res.data){
+                    var oldTimestamp = parseInt(res.data)
+                    var timestamp = new Date().getTime()
+                    for (var i=0;i<healthRef.current.refreshs.length;i++){
+                        var item = healthRef.current.refreshs[i]
+                        if (timestamp>item && item>oldTimestamp){
+                            global.refreshHistory()
+                            console.log('强制刷新')
+                            return
+                        }
+                    }
+                    console.log('暂不需要强制刷新')
+                }
+                
+            },
+            fail(res) {
+                console.log('load failed',res)
+                global.refreshHistory()
+            },
+            complete: function () {
+                
+            }
+        })
+        
     }
 
     function checkTimeZone() {
@@ -211,54 +237,6 @@ export default function ClockNew(props: { children: any, onScroll: any }) {
         }).catch(e => {
             setShowRetry(true)
         })
-        archived()
-    }
-
-    function archived() {
-        return
-        getLatestJournal(true, {
-            window: 'EAT',
-        }).then(res => {
-            if (!(res as any).user_confirmed && (res as any).id) {
-                global.eatTipId = (res as any).id
-                dispatch(setEatTip(true))
-            }
-        })
-        getLatestJournal(true, {
-            window: 'ACTIVE'
-        }).then(res => {
-            if (!(res as any).user_confirmed && (res as any).id) {
-                global.activeTipId = (res as any).id
-                dispatch(setActiveTip(true))
-            }
-        })
-
-        // if (health.mode == 'EAT' || health.mode == 'ACTIVE') {
-        //     getLatestJournal(true, health.mode).then(res => {
-        //         if (!(res as any).user_confirmed && (res as any).id) {
-        //             if (health.mode == 'EAT') {
-        //                 // dispatch(setEatArchived((res as any).latest))
-        //                 // dispatch(setEatArchivedTotal((res as any).archived_total))
-        //                 dispatch(setEatTip(true))
-        //             }
-        //             else if (health.mode == 'ACTIVE') {
-        //                 dispatch(setActiveTip(true))
-        //                 // dispatch(setActiveArchived((res as any).latest))
-        //                 // dispatch(setActiveArchivedTotal((res as any).archived_total))
-        //             }
-        //         }
-        //     })
-        //     // getArchived(health.mode).then(res => {
-        //     //     if (health.mode == 'EAT') {
-        //     //         dispatch(setEatArchived((res as any).latest))
-        //     //         dispatch(setEatArchivedTotal((res as any).archived_total))
-        //     //     }
-        //     //     else if (health.mode == 'ACTIVE') {
-        //     //         dispatch(setActiveArchived((res as any).latest))
-        //     //         dispatch(setActiveArchivedTotal((res as any).archived_total))
-        //     //     }
-        //     // })
-        // }
     }
 
     function checkAddToMini() {
@@ -283,8 +261,6 @@ export default function ClockNew(props: { children: any, onScroll: any }) {
         if (!user.isLogin) {
             return
         }
-        console.log('zzzzz',user.isLogin)
-        debugger
 
 
         const showAlert1 = await getStorage('148alert') || false;
@@ -361,8 +337,11 @@ export default function ClockNew(props: { children: any, onScroll: any }) {
             }}
             onScroll={e => {
                 props.onScroll(e)
-                if (e.detail.scrollTop > 240) {
-                    dispatch(setTitle(pageTitle()))
+                if (showDate && e.detail.scrollTop > 100){
+                    dispatch(setTitle(t('health.recents')))
+                }
+                else if (e.detail.scrollTop > 100) {
+                    dispatch(setTitle(t('health.today')))
                 }
                 else {
                     dispatch(setTitle(''))

+ 8 - 8
src/services/health.tsx

@@ -427,12 +427,12 @@ export const delRecord = ( params) => {
 }
 
 export const getLatestJournal = (isGet: boolean, params: any) => {
-    return new Promise((resolve) => {
-        request({
-            url: API_LASTEST_JOURNAL, method: isGet ? 'GET' : 'POST', data: { ...params }
-        }).then(res => {
-            resolve(res);
-            // dispatch(loginSuccess(res));
-        })
-    })
+    // return new Promise((resolve) => {
+    //     request({
+    //         url: API_LASTEST_JOURNAL, method: isGet ? 'GET' : 'POST', data: { ...params }
+    //     }).then(res => {
+    //         resolve(res);
+    //         // dispatch(loginSuccess(res));
+    //     })
+    // })
 }

+ 2 - 1
src/store/health.tsx

@@ -28,7 +28,7 @@ const initialState: HealthState = {
     windows: null,
     fast_with_sleep: null,
     long_fast: null,
-    mode: 'DAY',
+    mode: '',
     selTab: 0,
     refreshs: [],
     title: '',
@@ -95,6 +95,7 @@ const healthSlice = createSlice({
             state.isCompleted = isCompleted
         },
         setSchedules(state, action) {
+            debugger
             state.schedules = action.payload
         },
         setFooter(state, action) {

+ 28 - 8
yarn.lock

@@ -14752,11 +14752,6 @@ miniprogram-exparser@latest:
   resolved "https://registry.npmmirror.com/miniprogram-exparser/-/miniprogram-exparser-2.29.1.tgz#c8404b7182e7b1e7fb68e2d9d37abdae90db26b5"
   integrity sha512-f2LUVYcQ5O664nOHhrEbtR//hlqln88dRY0mIwuRncJfuXMCdK9FBk0vzNDG6EgaaeTt3iGLeFQLRHlhYktkXw==
 
-miniprogram-recycle-view@^0.1.5:
-  version "0.1.5"
-  resolved "https://registry.npmjs.org/miniprogram-recycle-view/-/miniprogram-recycle-view-0.1.5.tgz#854c2fe0df63c2165f739c8e0446aa35aa6c7d78"
-  integrity sha512-Pfm/u+jfg+b5zDhjXqm7QbR9IuViqX8JyzcHDgr6Zw9wSK0wmbXNzscA1WoSnGP5Z2nG2TIqtiNXvEbvsyrxXA==
-
 miniprogram-simulate@^1.1.5:
   version "1.6.1"
   resolved "https://registry.npmmirror.com/miniprogram-simulate/-/miniprogram-simulate-1.6.1.tgz#48b5e0e79c3a53525d38487a264a659ac5ca948d"
@@ -18567,7 +18562,7 @@ string-hash-64@1.0.3:
   resolved "https://registry.yarnpkg.com/string-hash-64/-/string-hash-64-1.0.3.tgz#0deb56df58678640db5c479ccbbb597aaa0de322"
   integrity sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw==
 
-"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.0":
   version "4.2.3"
   resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
   integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -18584,6 +18579,15 @@ string-width@^2.1.0, string-width@^2.1.1:
     is-fullwidth-code-point "^2.0.0"
     strip-ansi "^4.0.0"
 
+string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
+  version "4.2.3"
+  resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+  integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+  dependencies:
+    emoji-regex "^8.0.0"
+    is-fullwidth-code-point "^3.0.0"
+    strip-ansi "^6.0.1"
+
 string-width@^5.0.1, string-width@^5.1.2:
   version "5.1.2"
   resolved "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
@@ -18664,7 +18668,7 @@ stringify-entities@^1.0.1:
     is-alphanumerical "^1.0.0"
     is-hexadecimal "^1.0.0"
 
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
   version "6.0.1"
   resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
   integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -18692,6 +18696,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.2.0:
   dependencies:
     ansi-regex "^4.1.0"
 
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+  version "6.0.1"
+  resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+  integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+  dependencies:
+    ansi-regex "^5.0.1"
+
 strip-ansi@^7.0.1:
   version "7.1.0"
   resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
@@ -20580,7 +20591,7 @@ wonka@^6.3.2:
   resolved "https://registry.npmmirror.com/wonka/-/wonka-6.3.4.tgz#76eb9316e3d67d7febf4945202b5bdb2db534594"
   integrity sha512-CjpbqNtBGNAeyNS/9W6q3kSkKE52+FjIj7AkFlLr11s/VWGUu6a2CdYSdGxocIhIVjaW/zchesBQUKPVU69Cqg==
 
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
   version "7.0.0"
   resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
   integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -20598,6 +20609,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0:
     string-width "^4.1.0"
     strip-ansi "^6.0.0"
 
+wrap-ansi@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+  integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+  dependencies:
+    ansi-styles "^4.0.0"
+    string-width "^4.1.0"
+    strip-ansi "^6.0.0"
+
 wrap-ansi@^8.1.0:
   version "8.1.0"
   resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"