Leon 2 gadi atpakaļ
vecāks
revīzija
eef78e5042

+ 88 - 81
ios/hola/Info.plist

@@ -1,90 +1,97 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
-<dict>
-	<key>CFBundleDevelopmentRegion</key>
-	<string>en</string>
-	<key>CFBundleDisplayName</key>
-	<string>hola</string>
-	<key>CFBundleExecutable</key>
-	<string>$(EXECUTABLE_NAME)</string>
-	<key>CFBundleIdentifier</key>
-	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
-	<key>CFBundleInfoDictionaryVersion</key>
-	<string>6.0</string>
-	<key>CFBundleName</key>
-	<string>$(PRODUCT_NAME)</string>
-	<key>CFBundlePackageType</key>
-	<string>APPL</string>
-	<key>CFBundleShortVersionString</key>
-	<string>1.0</string>
-	<key>CFBundleSignature</key>
-	<string>????</string>
-	<key>CFBundleURLTypes</key>
-	<array>
-		<dict>
-			<key>CFBundleTypeRole</key>
-			<string>Editor</string>
-			<key>CFBundleURLSchemes</key>
-			<array>
-				<string>prefs</string>
-			</array>
-		</dict>
-	</array>
-	<key>CFBundleVersion</key>
-	<string>1</string>
-	<key>ITSAppUsesNonExemptEncryption</key>
-	<false/>
-	<key>LSRequiresIPhoneOS</key>
-	<true/>
-	<key>NSAppTransportSecurity</key>
 	<dict>
-		<key>NSExceptionDomains</key>
+		<key>CFBundleDevelopmentRegion</key>
+		<string>en</string>
+		<key>CFBundleDisplayName</key>
+		<string>hola</string>
+		<key>CFBundleExecutable</key>
+		<string>$(EXECUTABLE_NAME)</string>
+		<key>CFBundleIdentifier</key>
+		<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+		<key>CFBundleInfoDictionaryVersion</key>
+		<string>6.0</string>
+		<key>CFBundleName</key>
+		<string>$(PRODUCT_NAME)</string>
+		<key>CFBundlePackageType</key>
+		<string>APPL</string>
+		<key>CFBundleShortVersionString</key>
+		<string>1.0</string>
+		<key>CFBundleSignature</key>
+		<string>????</string>
+		<key>CFBundleURLTypes</key>
+		<array>
+			<dict>
+				<key>CFBundleTypeRole</key>
+				<string>Editor</string>
+				<key>CFBundleURLSchemes</key>
+				<array>
+					<string>prefs</string>
+				</array>
+			</dict>
+		</array>
+		<key>CFBundleVersion</key>
+		<string>1</string>
+		<key>ITSAppUsesNonExemptEncryption</key>
+		<false />
+		<key>LSRequiresIPhoneOS</key>
+		<true />
+		<key>NSAppTransportSecurity</key>
 		<dict>
-			<key>localhost</key>
+			<key>NSExceptionDomains</key>
 			<dict>
-				<key>NSExceptionAllowsInsecureHTTPLoads</key>
-				<true/>
+				<key>localhost</key>
+				<dict>
+					<key>NSExceptionAllowsInsecureHTTPLoads</key>
+					<true />
+				</dict>
 			</dict>
 		</dict>
+		<key>NSCameraUsageDescription</key>
+		<string>Allow $(PRODUCT_NAME) to use your camera</string>
+		<key>NSContactsUsageDescription</key>
+		<string>Allow $(PRODUCT_NAME) to access your contacts</string>
+		<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
+		<string>Allow $(PRODUCT_NAME) to use your location</string>
+		<key>NSLocationAlwaysUsageDescription</key>
+		<string>Allow $(PRODUCT_NAME) to use your location</string>
+		<key>NSLocationWhenInUseUsageDescription</key>
+		<string>Allow $(PRODUCT_NAME) to use your location</string>
+		<key>NSMicrophoneUsageDescription</key>
+		<string>Allow $(PRODUCT_NAME) to access your microphone</string>
+		<key>NSMotionUsageDescription</key>
+		<string>Allow $(PRODUCT_NAME) to access your device's accelerometer</string>
+		<key>NSPhotoLibraryAddUsageDescription</key>
+		<string>Give $(PRODUCT_NAME) permission to save photos</string>
+		<key>NSPhotoLibraryUsageDescription</key>
+		<string>Give $(PRODUCT_NAME) permission to access your photos</string>
+		<key>NSHealthShareUsageDescription</key>
+		<string>Read and understand health data.</string>
+		<key>NSHealthUpdateUsageDescription</key>
+		<string>Share workout data with other apps.</string>
+		<!-- Below is only required if requesting clinical health data -->
+		<key>NSHealthClinicalHealthRecordsShareUsageDescription</key>
+		<string>Read and understand clinical health data.</string>
+		<key>UILaunchStoryboardName</key>
+		<string>LaunchScreen</string>
+		<key>UIRequiredDeviceCapabilities</key>
+		<array>
+			<string>armv7</string>
+		</array>
+		<key>UISupportedInterfaceOrientations</key>
+		<array>
+			<string>UIInterfaceOrientationPortrait</string>
+		</array>
+		<key>UISupportedInterfaceOrientations~ipad</key>
+		<array>
+			<string>UIInterfaceOrientationLandscapeLeft</string>
+			<string>UIInterfaceOrientationLandscapeRight</string>
+			<string>UIInterfaceOrientationPortrait</string>
+		</array>
+		<key>UIUserInterfaceStyle</key>
+		<string>Light</string>
+		<key>UIViewControllerBasedStatusBarAppearance</key>
+		<false />
 	</dict>
-	<key>NSCameraUsageDescription</key>
-	<string>Allow $(PRODUCT_NAME) to use your camera</string>
-	<key>NSContactsUsageDescription</key>
-	<string>Allow $(PRODUCT_NAME) to access your contacts</string>
-	<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
-	<string>Allow $(PRODUCT_NAME) to use your location</string>
-	<key>NSLocationAlwaysUsageDescription</key>
-	<string>Allow $(PRODUCT_NAME) to use your location</string>
-	<key>NSLocationWhenInUseUsageDescription</key>
-	<string>Allow $(PRODUCT_NAME) to use your location</string>
-	<key>NSMicrophoneUsageDescription</key>
-	<string>Allow $(PRODUCT_NAME) to access your microphone</string>
-	<key>NSMotionUsageDescription</key>
-	<string>Allow $(PRODUCT_NAME) to access your device's accelerometer</string>
-	<key>NSPhotoLibraryAddUsageDescription</key>
-	<string>Give $(PRODUCT_NAME) permission to save photos</string>
-	<key>NSPhotoLibraryUsageDescription</key>
-	<string>Give $(PRODUCT_NAME) permission to access your photos</string>
-	<key>UILaunchStoryboardName</key>
-	<string>LaunchScreen</string>
-	<key>UIRequiredDeviceCapabilities</key>
-	<array>
-		<string>armv7</string>
-	</array>
-	<key>UISupportedInterfaceOrientations</key>
-	<array>
-		<string>UIInterfaceOrientationPortrait</string>
-	</array>
-	<key>UISupportedInterfaceOrientations~ipad</key>
-	<array>
-		<string>UIInterfaceOrientationLandscapeLeft</string>
-		<string>UIInterfaceOrientationLandscapeRight</string>
-		<string>UIInterfaceOrientationPortrait</string>
-	</array>
-	<key>UIUserInterfaceStyle</key>
-	<string>Light</string>
-	<key>UIViewControllerBasedStatusBarAppearance</key>
-	<false/>
-</dict>
-</plist>
+</plist>

+ 4 - 0
ios/hola/hola.entitlements

@@ -4,5 +4,9 @@
 <dict>
 	<key>aps-environment</key>
 	<string>development</string>
+	<key>com.apple.developer.healthkit</key>
+	<true/>
+	<key>com.apple.developer.healthkit.access</key>
+	<array/>
 </dict>
 </plist>

+ 1 - 0
package.json

@@ -93,6 +93,7 @@
 		"react-native": "^0.70.1",
 		"react-native-device-info": "~10.3.0",
 		"react-native-gesture-handler": "~2.9.0",
+		"react-native-health": "^1.18.0",
 		"react-native-linear-gradient": "^2.8.3",
 		"react-native-pager-view": "~6.0.1",
 		"react-native-safe-area-context": "~4.4.1",

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

@@ -220,7 +220,7 @@ export default function Component(props: any) {
                 {
                     user.isLogin && list.length > 0 && <View className="add_more" onClick={chooseMore}>
                         <Image style={{ width: rpxToPx(48), height: rpxToPx(48) }} src={require('@assets/images/add2.png')} />
-                        <Text className="add_more_text">添加更多</Text>
+                        <Text className="add_more_text">{t('feature.workout.add_more')}</Text>
                     </View>
                 }
 

+ 1 - 1
src/features/trackSomething/components/MetricModalOrder.scss

@@ -1,4 +1,4 @@
-
+@import './MetricModalChoose.scss';
 
 .modal_order_detail{
     margin-top: 64px;

+ 2 - 2
src/features/trackSomething/components/MetricModalOrder.tsx

@@ -48,11 +48,11 @@ export default function Component(props: { themeColor: string, cancel: Function,
         </View>
         <View className='modal_operate'>
             <View className='modal_btn' style={{ backgroundColor: color + alpha }} onClick={cancel}>
-                <Text className='modal_cancel_text' style={{ color: color }}>{global.metricAdd ? '上一步' : t('feature.common.picker_cancel_btn')}</Text>
+                <Text className='modal_cancel_text' style={{ color: color,fontWeight:'bold' }}>{global.metricAdd ? '上一步' : t('feature.common.picker_cancel_btn')}</Text>
             </View>
             <View className='btn_space' />
             <View className='modal_btn' style={{ backgroundColor: color }} onClick={confirm}>
-                <Text className='modal_confirm_text' style={{ color: '#000' }}>{global.metricAdd ? '完成' : t('feature.common.picker_confirm_btn')}</Text>
+                <Text className='modal_confirm_text' style={{ color: '#000',fontWeight:'bold' }}>{global.metricAdd ? '完成' : t('feature.common.picker_confirm_btn')}</Text>
             </View>
 
 

+ 4 - 3
src/features/trackSomething/components/MoveOrderList.tsx → src/features/trackSomething/components/MoveOrderList.rn.tsx

@@ -43,6 +43,7 @@ export default function Component(props: { array: any, itemHeight: number, color
     }, [])
 
     function longPress(e, index) {
+        alert('long press')
         setChangedIndex(index)
         setStartOffsetY(e.target.offsetTop)
         setStartPageY(e.touches[0].pageY)
@@ -186,7 +187,7 @@ export default function Component(props: { array: any, itemHeight: number, color
             <View>
                 {
                     list.map((item, index) => {
-                        return <View key={index} style={{ opacity: changedIndex == index && hiddenContent ? 0 : 1, height: props.itemHeight, width: rpxToPx(750) }}
+                        return <View key={index} style={{ opacity: changedIndex == index && hiddenContent ? 0 : 1, height: props.itemHeight, width: rpxToPx(750),backgroundColor:'pink' }}
                             onLongPress={(e) => longPress(e, index)}
                             onTouchMove={(e) => touchMove(e)}
                             onTouchEnd={(e) => touchEnd(e)}
@@ -198,7 +199,7 @@ export default function Component(props: { array: any, itemHeight: number, color
                                     width: '100%',
                                     alignItems: 'center', justifyContent: 'space-between'
                                 }}>
-                                    <Text style={{ color: props.color }}>{item.name}</Text>
+                                    <Text style={{ color: props.color,fontSize:rpxToPx(32) }}>{item.name}</Text>
                                     <IconDrag width={17} height={12} />
 
                                 </View>
@@ -208,7 +209,7 @@ export default function Component(props: { array: any, itemHeight: number, color
                     })
                 }
 
-                <MovableView style={{ height: changedIndex >= 0 ? props.itemHeight : 0, width: rpxToPx(750) }}
+                <MovableView style={{ height: changedIndex >= 0 ? props.itemHeight : 0, width: rpxToPx(750),backgroundColor:'red' }}
                     direction='vertical'
                     disabled
                     animation={false}

+ 230 - 0
src/features/trackSomething/components/MoveOrderList.weapp.tsx

@@ -0,0 +1,230 @@
+import { MovableArea, MovableView, View, ScrollView, Text, Image } from '@tarojs/components'
+import './MoveOrderList.scss'
+import { useEffect, useRef, useState } from 'react';
+import { ColorType } from '@/context/themes/color';
+import Taro from '@tarojs/taro';
+import { IconDrag } from '@/components/basic/Icons';
+import { rpxToPx } from '@/utils/tools';
+
+export default function Component(props: { array: any, itemHeight: number, color?: string, update: Function }) {
+    const [list, setList] = useState(props.array)
+    const [movaleViewY, setMovaleViewY] = useState(0)
+    const [dragElement, setDragElement] = useState(null)
+    const [lastTarget, setLastTarget] = useState(null)
+    const [startOffsetY, setStartOffsetY] = useState(0)
+    const [startPageY, setStartPageY] = useState(0)
+    const [dragIndex, setDragIndex] = useState(-1)
+    const [scrollThreshold, setScrollThreshold] = useState(0.5)
+    const upperThreshold = 100
+    const lowThreshold = 100
+    const [duration, setDuration] = useState(1000)
+    const [canScroll, setCanScroll] = useState(true)
+    const [changedIndex, setChangedIndex] = useState(-1)
+    const [hiddenContent, setHiddenContent] = useState(false)
+
+    const [scrollTop, setScrollTop] = useState(0)
+    const [contentY, setContentY] = useState(0)
+    const [contentHeight, setContentHeight] = useState(0)
+    const ref = useRef(null)
+
+    useEffect(() => {
+        if (process.env.TARO_ENV == 'weapp') {
+            const query = Taro.createSelectorQuery();
+            query.select('#myScrollView').boundingClientRect();
+            query.exec((res) => {
+                setContentY(res[0].top)
+                setContentHeight(res[0].height)
+            })
+        }
+        else {
+
+        }
+
+    }, [])
+
+    function longPress(e, index) {
+        alert('long press')
+        setChangedIndex(index)
+        setStartOffsetY(e.target.offsetTop)
+        setStartPageY(e.touches[0].pageY)
+        setDragIndex(index)
+        setDragElement(list[index])
+        setMovaleViewY(e.target.offsetTop)
+        setCanScroll(false)
+    }
+
+    function touchMove(e) {
+        if (dragElement) {
+            let clientY = e.touches[0].clientY;
+            pageScroll(clientY);
+            let pageY = e.touches[0].pageY;
+            let targetMoveDistance = pageY - startPageY
+            let movaleViewY2 = startOffsetY + targetMoveDistance
+
+            let targetIndex = computeFutureIndex(targetMoveDistance, dragIndex)
+            if (targetIndex !== false && targetIndex != changedIndex) {
+                var temps = swapListItems(list, targetIndex, changedIndex)
+                setList(temps)
+                setChangedIndex(targetIndex)
+
+            }
+
+            if (targetIndex === false && targetIndex != changedIndex) {
+                var temps = swapListItems(list, dragIndex, changedIndex)
+                setList(temps)
+                setChangedIndex(dragIndex)
+            }
+
+            setMovaleViewY(movaleViewY2)
+            setLastTarget(targetIndex as any)
+            setHiddenContent(true)
+        }
+    }
+
+    function pageScroll(clientY) {
+        return
+        // console.log(clientY,contentY,contentHeight)
+        if ((clientY - contentY) + upperThreshold >= contentHeight) {
+            // var scroll = ref.current
+            // debugger
+            // (ref.current as any).scrollTo({scrollTop:100})
+            // setScrollTop((clientY - contentY) + props.itemHeight)
+            // setScrollTop(2200)
+            // setCanScroll(true)
+            Taro.pageScrollTo({
+                selector: '#myScrollView',
+                scrollTop: (clientY - contentY) + props.itemHeight,
+                duration: 200
+            })
+        }
+        else if ((clientY - contentY) - lowThreshold <= 0) {
+            setScrollTop((clientY - contentY) - props.itemHeight)
+            // setCanScroll(true)
+        }
+        else {
+            // setCanScroll(true)
+        }
+    }
+
+    function swapListItems<T>(list: T[], index1: number, index2: number): T[] {
+        const newList = [...list];
+        const temp = newList[index1];
+        newList[index1] = newList[index2];
+        newList[index2] = temp;
+
+        return newList;
+    }
+
+
+    function touchEnd(e) {
+        if (dragElement) {
+            // let pageY = e.changedTouches[0].pageY
+            // let targetMoveDistance = pageY - startPageY;
+            // let dragElementIndex = dragIndex;
+            // const futrueIndex = computeFutureIndex(targetMoveDistance, dragElementIndex)
+            // if (futrueIndex !== false) {
+            //     var temps = list
+            //     temps.splice(futrueIndex, 0, temps.splice(dragIndex, 1)[0])
+
+            //     setList(temps)
+            // }
+            setDragElement(null)
+            setLastTarget(null)
+            setDragIndex(-1)
+
+        }
+        setChangedIndex(-1)
+        setCanScroll(true)
+        setHiddenContent(false)
+        setMovaleViewY(-100)
+
+        props.update(list)
+    }
+
+    function computeFutureIndex(targetMoveDistance, dragElementIndex) {
+        let willInsertAfter = getSwapDirection(targetMoveDistance);
+        if (willInsertAfter !== false) {
+            /** 偏移索引 */
+            let offsetElementIndex = dragElementIndex + willInsertAfter;
+            /** 移动步数 */
+            let step = targetMoveDistance / props.itemHeight;
+            /** 步数补偿,当只有移动距离超过单项 _scrollThreshold 时才算有效 */
+            if (step <= -1) {
+                step += scrollThreshold;
+            } else if (step >= 1) {
+                step -= scrollThreshold;
+            }
+            /** 目标索引 */
+            let futureIndex = parseInt(step) + offsetElementIndex;
+
+            // 避免越界
+            if (futureIndex < 0) {
+                futureIndex = 0;
+            } else if (futureIndex > list.length - 1) {
+                futureIndex = list.length - 1;
+            }
+
+            return futureIndex;
+        } else {
+            return willInsertAfter;
+        }
+    }
+
+    function getSwapDirection(targetMoveDistance) {
+        if (Math.abs(targetMoveDistance) < props.itemHeight / 2) {
+            // 轻轻拂动,滑动距离小于1/2单项高度
+            return false;
+        } else if (targetMoveDistance >= props.itemHeight / 2) {
+            // console.log('[_getSwapDirection] 👇👇👇');
+            return 1;  // 下滑
+        } else if (targetMoveDistance <= props.itemHeight / -2) {
+            // console.log('[_getSwapDirection] 👆👆👆');
+            return -1;  // 上滑
+        }
+    }
+    return <View id="myScrollView" ref={ref} style={{ height: '100%', overflow: canScroll ? 'scroll' : 'hidden' }} catchMove>
+        <MovableArea style={{ height: list.length * props.itemHeight, width: rpxToPx(750) }}>
+            <View>
+                {
+                    list.map((item, index) => {
+                        return <View key={index} style={{ opacity: changedIndex == index && hiddenContent ? 0 : 1, height: props.itemHeight, width: rpxToPx(750),backgroundColor:'pink' }}
+                            onLongPress={(e) => longPress(e, index)}
+                            onTouchMove={(e) => touchMove(e)}
+                            onTouchEnd={(e) => touchEnd(e)}
+                        >
+                            <View className='modal_order_item' style={{ height: 40, flexDirection: 'column' }}>
+                                <View style={{
+                                    height: 40,
+                                    display: 'flex', flexDirection: 'row',
+                                    width: '100%',
+                                    alignItems: 'center', justifyContent: 'space-between'
+                                }}>
+                                    <Text style={{ color: props.color,fontSize:rpxToPx(32) }}>{item.name}</Text>
+                                    <IconDrag width={17} height={12} />
+
+                                </View>
+                                <View className='seperate' />
+                            </View>
+                        </View>
+                    })
+                }
+
+                <MovableView style={{ height: changedIndex >= 0 ? props.itemHeight : 0, width: rpxToPx(750),backgroundColor:'red' }}
+                    direction='vertical'
+                    disabled
+                    animation={false}
+                    y={movaleViewY}
+                >
+                    <View className='drag_item' style={{ backgroundColor: props.color }}>
+                        {
+                            dragIndex >= 0 && <View className='modal_sel_item' style={{ height: 40, border: 'none' }}>
+                                <Text style={{ color: 'black', fontWeight: 'bold' }}>{list[changedIndex].name}</Text>
+                                <IconDrag width={17} height={12} />
+                            </View>
+                        }
+                    </View>
+                </MovableView>
+            </View>
+        </MovableArea>
+    </View>
+}

+ 58 - 6
src/features/trackTimeDuration/components/RecordFastSleep.tsx

@@ -6,7 +6,7 @@ import { delRecord } from "@/services/trackTimeDuration";
 import { ModalType } from "@/utils/types";
 import { View, Text, Image } from "@tarojs/components";
 import Taro from "@tarojs/taro";
-import { useState } from "react";
+import { useEffect, useState } from "react";
 import TimelineFastSleep from "./TimelineFastSleep";
 import { TimeFormatter } from "@/utils/time_format";
 import './RecordFastSleep.scss'
@@ -23,9 +23,38 @@ import { jumpPage } from "../hooks/Common";
 export default function RecordFastSleep(props: { data: any, type: string, delSuccess?: Function }) {
     const [showDetailModal, setShowDetailModal] = useState(false)
     const [segmentIndex, setSegmentIndex] = useState(0)
+    const [diffTimeZone, setDiffTimeZone] = useState(false)
     const { t } = useTranslation()
     const canvasId = props.data.id
     const record = props.data;
+
+    useEffect(() => {
+        var split = new Date().toString().split(' ');
+        var currentTZ = split[split.length - 2];
+        if (props.data.fast) {
+            if (props.data.fast.real_start_time_zone && props.data.fast.real_start_time_zone != currentTZ) {
+                setDiffTimeZone(true)
+                return
+            }
+            if (props.data.fast.real_end_time_zone && props.data.fast.real_end_time_zone != currentTZ) {
+                setDiffTimeZone(true)
+                return
+            }
+        }
+
+        if (props.data.sleep) {
+            if (props.data.sleep.real_start_time_zone && props.data.sleep.real_start_time_zone != currentTZ) {
+                setDiffTimeZone(true)
+                return
+            }
+            if (props.data.sleep.real_end_time_zone && props.data.sleep.real_end_time_zone != currentTZ) {
+                setDiffTimeZone(true)
+                return
+            }
+        }
+        setDiffTimeZone(false)
+
+    }, [props.data])
     function del() {
         var id = props.data.id
         delRecord(id
@@ -41,12 +70,35 @@ export default function RecordFastSleep(props: { data: any, type: string, delSuc
 
     function schedules() {
         var timestamp = props.data.first_real_check_time
-        if (props.data.first_time_zone){
-            timestamp = TimeFormatter.transferTimestamp(timestamp,props.data.first_time_zone)
-        }
+
+        // var split = new Date().toString().split(' ');
+        // var currentTZ = split[split.length - 2];
+        // var diffTimeZone = false
+        // if (props.data.fast) {
+        //     if (props.data.fast.real_start_time_zone && props.data.fast.real_start_time_zone != currentTZ) {
+        //         diffTimeZone = true
+        //     }
+        //     if (props.data.fast.real_end_time_zone && props.data.fast.real_end_time_zone != currentTZ) {
+        //         diffTimeZone = true
+        //     }
+        // }
+
+        // if (props.data.sleep) {
+        //     if (props.data.sleep.real_start_time_zone && props.data.sleep.real_start_time_zone != currentTZ) {
+        //         diffTimeZone = true
+        //     }
+        //     if (props.data.sleep.real_end_time_zone && props.data.sleep.real_end_time_zone != currentTZ) {
+        //         diffTimeZone = true
+        //     }
+        // }
+
+
+        // if (props.data.first_time_zone){
+        //     timestamp = TimeFormatter.transferTimestamp(timestamp,props.data.first_time_zone)
+        // }
         return <View style={{ display: 'flex', flexDirection: 'column' }}>
             <TimelineStage data={props.data} title={t('feature.track_time_duration.record_fast_sleep.pop_title')} 
-            subTitle={TimeFormatter.getDateAndWeek(timestamp)} first_real_check_time={timestamp}/>
+            subTitle={diffTimeZone?'Multiple time zones':TimeFormatter.getDateAndWeek(timestamp)} first_real_check_time={timestamp}/>
         </View>
     }
 
@@ -229,7 +281,7 @@ export default function RecordFastSleep(props: { data: any, type: string, delSuc
             {/* <Image className="arrow1" src={require('@/assets/images/arrow.png')} /> */}
             <View className="record_arrow_bg" style={{ backgroundColor: global.isDebug ? 'red' : 'transparent' }}>
                 <View style={{flex:1}}/>
-                <Text className='recordTime'>{recordTime()}</Text>
+                <Text className='recordTime'>{diffTimeZone?'Multiple time zones':recordTime()}</Text>
                 <Image className="arrow2" src={require('@/assets/images/arrow3.png')} />
             </View>
 

+ 78 - 27
src/features/trackTimeDuration/components/TimelineFastSleep.tsx

@@ -4,38 +4,89 @@ import { View } from "@tarojs/components";
 import getStatus from "../hooks/Record";
 import { ColorType } from "@/context/themes/color";
 import { useTranslation } from "react-i18next";
+import { useEffect, useState } from "react";
 
 export default function TimelineFastSleep(props: { data: any, title?: string, first_real_check_time?: number }) {
     const { t } = useTranslation()
+    const [diffTimeZone, setDiffTimeZone] = useState(false)
+
+    useEffect(() => {
+        var split = new Date().toString().split(' ');
+        var currentTZ = split[split.length - 2];
+        if (props.data.fast) {
+            if (props.data.fast.real_start_time_zone && props.data.fast.real_start_time_zone != currentTZ) {
+                setDiffTimeZone(true)
+                return
+            }
+            if (props.data.fast.real_end_time_zone && props.data.fast.real_end_time_zone != currentTZ) {
+                setDiffTimeZone(true)
+                return
+            }
+        }
+
+        if (props.data.sleep) {
+            if (props.data.sleep.real_start_time_zone && props.data.sleep.real_start_time_zone != currentTZ) {
+                setDiffTimeZone(true)
+                return
+            }
+            if (props.data.sleep.real_end_time_zone && props.data.sleep.real_end_time_zone != currentTZ) {
+                setDiffTimeZone(true)
+                return
+            }
+        }
+        setDiffTimeZone(false)
+
+    }, [props.data])
+
     function formateTime(obj: any, isEnd: boolean) {
         if (isEnd) {
             if (obj.real_end_time) {
-                if (obj.real_end_time_zone) {
-                    var newTimestamp = TimeFormatter.transferTimestamp(obj.real_end_time, obj.real_end_time_zone)
-                    return TimeFormatter.timelineFormatTime(newTimestamp)
-                }
-                return TimeFormatter.timelineFormatTime(obj.real_end_time)
+                return diffTimeZone?TimeFormatter.timelineFullFormatTime(obj.real_end_time):TimeFormatter.timelineFormatTime(obj.real_end_time)
             }
             else {
-                return TimeFormatter.timelineFormatTime(obj.target_end_time)
+                return diffTimeZone?TimeFormatter.timelineFullFormatTime(obj.target_end_time):TimeFormatter.timelineFormatTime(obj.target_end_time)
             }
         }
         else {
             if (obj.real_start_time) {
-                if (obj.real_end_time_zone) {
-                    var newTimestamp = TimeFormatter.transferTimestamp(obj.real_start_time, obj.real_start_time_zone)
-                    return TimeFormatter.timelineFormatTime(newTimestamp)
-                }
-
-                return TimeFormatter.timelineFormatTime(obj.real_start_time, obj.real_start_time_zone)
+                return diffTimeZone?TimeFormatter.timelineFullFormatTime(obj.real_start_time):TimeFormatter.timelineFormatTime(obj.real_start_time)
             }
             else {
-                return TimeFormatter.timelineFormatTime(obj.target_start_time)
+                return diffTimeZone?TimeFormatter.timelineFullFormatTime(obj.target_start_time):TimeFormatter.timelineFormatTime(obj.target_start_time)
             }
         }
 
     }
 
+    // function formateTime(obj: any, isEnd: boolean) {
+    //     if (isEnd) {
+    //         if (obj.real_end_time) {
+    //             if (obj.real_end_time_zone) {
+    //                 var newTimestamp = TimeFormatter.transferTimestamp(obj.real_end_time, obj.real_end_time_zone)
+    //                 return TimeFormatter.timelineFormatTime(newTimestamp)
+    //             }
+    //             return TimeFormatter.timelineFormatTime(obj.real_end_time)
+    //         }
+    //         else {
+    //             return TimeFormatter.timelineFormatTime(obj.target_end_time)
+    //         }
+    //     }
+    //     else {
+    //         if (obj.real_start_time) {
+    //             if (obj.real_end_time_zone) {
+    //                 var newTimestamp = TimeFormatter.transferTimestamp(obj.real_start_time, obj.real_start_time_zone)
+    //                 return TimeFormatter.timelineFormatTime(newTimestamp)
+    //             }
+
+    //             return TimeFormatter.timelineFormatTime(obj.real_start_time, obj.real_start_time_zone)
+    //         }
+    //         else {
+    //             return TimeFormatter.timelineFormatTime(obj.target_start_time)
+    //         }
+    //     }
+
+    // }
+
     function showDate(obj: any, isEnd: boolean) {
         var dt = 0
         if (isEnd) {
@@ -98,8 +149,8 @@ export default function TimelineFastSleep(props: { data: any, title?: string, fi
                 title: getStatus(true, true, props.data) == 'padding' ?
                     t('feature.track_time_duration.common.start_fast') :
                     t('feature.track_time_duration.common.started_fasting'),
-                content: formateTime(props.data.fast, false) + timeZone,
-                date: showDate(props.data.fast, false) ? formateDate(props.data.fast, false) : '',
+                content: formateTime(props.data.fast, false),
+                date: diffTimeZone?timeZone:showDate(props.data.fast, false) ? formateDate(props.data.fast, false) : '',
                 color: global.fastColor ? global.fastColor : ColorType.fast
             }
         )
@@ -113,10 +164,10 @@ export default function TimelineFastSleep(props: { data: any, title?: string, fi
             {
                 status: getStatus(false, true, props.data),
                 title: getStatus(false, true, props.data) == 'padding' ?
-                t('feature.track_time_duration.common.start_sleep'):
-                t('feature.track_time_duration.common.started_sleeping'),
-                content: formateTime(props.data.sleep, false) + timeZone,
-                date: showDate(props.data.sleep, false) ? formateDate(props.data.sleep, false) : '',
+                    t('feature.track_time_duration.common.start_sleep') :
+                    t('feature.track_time_duration.common.started_sleeping'),
+                content: formateTime(props.data.sleep, false),
+                date: diffTimeZone?timeZone:showDate(props.data.sleep, false) ? formateDate(props.data.sleep, false) : '',
                 color: global.sleepColor ? global.sleepColor : ColorType.sleep
             }
         )
@@ -130,10 +181,10 @@ export default function TimelineFastSleep(props: { data: any, title?: string, fi
             {
                 status: getStatus(false, false, props.data),
                 title: getStatus(false, false, props.data) == 'padding' ?
-                t('feature.track_time_duration.common.end_sleep'):
-                t('feature.track_time_duration.common.ended_sleeping'),
-                content: formateTime(props.data.sleep, true) + timeZone,
-                date: showDate(props.data.sleep, true) ? formateDate(props.data.sleep, true) : '',
+                    t('feature.track_time_duration.common.end_sleep') :
+                    t('feature.track_time_duration.common.ended_sleeping'),
+                content: formateTime(props.data.sleep, true),
+                date: diffTimeZone?timeZone:showDate(props.data.sleep, true) ? formateDate(props.data.sleep, true) : '',
                 color: global.sleepColor ? global.sleepColor : ColorType.sleep
             }
         )
@@ -147,10 +198,10 @@ export default function TimelineFastSleep(props: { data: any, title?: string, fi
             {
                 status: getStatus(true, false, props.data),
                 title: getStatus(true, false, props.data) == 'padding' ?
-                t('feature.track_time_duration.common.end_fast'):
-                t('feature.track_time_duration.common.ended_fasting'),
-                content: formateTime(props.data.fast, true) + timeZone,
-                date: showDate(props.data.fast, true) ? formateDate(props.data.fast, true) : '',
+                    t('feature.track_time_duration.common.end_fast') :
+                    t('feature.track_time_duration.common.ended_fasting'),
+                content: formateTime(props.data.fast, true),
+                date: diffTimeZone?timeZone:showDate(props.data.fast, true) ? formateDate(props.data.fast, true) : '',
                 color: global.fastColor ? global.fastColor : ColorType.fast
             }
         )

+ 1 - 1
src/features/workout/Workout.tsx

@@ -623,7 +623,7 @@ export default function Component(props: any) {
                         }
                         else {
                             if (!item.latest_record) {
-                                value = '暂无记录'
+                                value = t('feature.track_something.metric.no_record')
                                 desc = ''
                                 showDetail = false
                             }

+ 14 - 3
src/pages/account/EditPage.tsx

@@ -11,18 +11,25 @@ import { useTranslation } from "react-i18next";
 import { useDispatch, useSelector } from "react-redux";
 
 let useNavigation;
+let useRoute;
 if (process.env.TARO_ENV == 'rn') {
+    useRoute = require("@react-navigation/native").useRoute
     useNavigation = require("@react-navigation/native").useNavigation
 }
 
 export default function Page() {
-
+    let router
+    if (process.env.TARO_ENV == 'rn') {
+        router = useRoute()
+    }
+    else {
+        router = useRouter()
+    }
     const user = useSelector((state: any) => state.user);
     const [value, setValue] = useState('');
     const [btnDisable, setBtnDisable] = useState(false);
     const { t } = useTranslation()
     const dispatch = useDispatch();
-    const router = useRouter();
 
     let navigation;
     if (useNavigation) {
@@ -31,6 +38,10 @@ export default function Page() {
 
 
     useEffect(() => {
+        if (process.env.TARO_ENV=='rn'){
+            setValue(router.params.name as any)
+            return
+        }
         setTimeout(() => {
             setValue(router.params.name as any)
             // setValue(user.nickname)
@@ -76,7 +87,7 @@ export default function Page() {
     return <View style={{flex:1}}>
         <View style={{ height: 20 }}></View>
         {/* <Input type="nickname" placeholder="请输入昵称" style={{ color: '#fff' }} value={value} onInput={handleChange} /> */}
-        <Inputs placeholder={t('feature.common.toast.input_nickname')} value={value} onChange={handleChange} onConfirm={save}
+        <Inputs autoFocus placeholder={t('feature.common.toast.input_nickname')} value={value} onChange={handleChange} onConfirm={save}
             openType="nickname"
         />
         <View style={{flex:1}}/>

+ 9 - 5
src/pages/account/ProfileSetting.tsx

@@ -42,10 +42,14 @@ export default function Page() {
 
     function editNickname() {
         if (router.params.newuser == '1') {
-            jumpPage('/pages/account/EditPage?name=' + (name == user.nickname ? '' : user.nickname), 'EditPage', navigation)
+            jumpPage('/pages/account/EditPage?name=' + (name == user.nickname ? '' : user.nickname), 'EditPage', navigation, {
+                name: name == user.nickname ? '' : user.nickname
+            })
         }
         else {
-            jumpPage('/pages/account/EditPage?name=' + user.nickname, 'EditPage', navigation)
+            jumpPage('/pages/account/EditPage?name=' + user.nickname, 'EditPage', navigation, {
+                name: user.nickname
+            })
         }
 
     }
@@ -55,7 +59,7 @@ export default function Page() {
             Taro.chooseImage({
                 count: 1, // 默认9
                 sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
-                sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有,在H5浏览器端支持使用 `user` 和 `environment`分别指定为前后摄像头
+                sourceType: ['album'], // 可以指定来源是相册还是相机,默认二者都有,在H5浏览器端支持使用 `user` 和 `environment`分别指定为前后摄像头
                 success: function (res) {
                     // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
                     var tempFilePaths = res.tempFilePaths
@@ -130,7 +134,7 @@ export default function Page() {
                 </View>
                 <Button className="btn" openType="chooseAvatar" onChooseAvatar={chooseAvatar} ></Button>
                 {
-                    process.env.TARO_ENV=='rn' && <View style={{opacity:0,position:'absolute',left:0,top:0,right:0,bottom:0}} onClick={choose}/>
+                    process.env.TARO_ENV == 'rn' && <View style={{ opacity: 0, position: 'absolute', left: 0, top: 0, right: 0, bottom: 0 }} onClick={choose} />
                 }
             </View>
         </View>
@@ -138,7 +142,7 @@ export default function Page() {
 
         <View onClick={editNickname}>
             <TableCell onClick={editNickname} title={t('page.user_profile.nickname')} showArrow={true} showMarginBottom={true}>
-                <Text style={{ opacity: 0.8 }}>{router.params.newuser == '1' ? (user.nickname == name ? '取个名字' : user.nickname) : user.nickname}</Text>
+                <Text style={{ opacity: 0.8, color: '#fff' }}>{router.params.newuser == '1' ? (user.nickname == name ? '取个名字' : user.nickname) : user.nickname}</Text>
             </TableCell>
         </View>
         <View style={{ flex: 1 }} />

+ 0 - 453
src/pages/clock/Clock.rn.tsx

@@ -1,453 +0,0 @@
-import { Component, PropsWithChildren, useEffect, useRef, useState } from 'react'
-import { View, Text, Button, Input, Picker, Swiper, SwiperItem, Icon } from '@tarojs/components'
-import '../index/index.scss'
-import './Clock.scss'
-// import './context/locales/index'
-import '@/context/locales/index'
-import Taro, { useDidShow, usePageScroll, useReady, useRouter, useShareAppMessage } from '@tarojs/taro'
-// import ComponentA from './component'
-
-
-import { useDispatch, useSelector } from 'react-redux';
-import { getInfoSuccess, logoutSuccess } from '@/store/user';
-import { wxPubFollow } from '@/services/permission';
-import { gobalConfigs, staticResources, uploadSessionKey } from '@/services/common';
-import Clocks from '@/features/trackTimeDuration/components/Clock';
-import Console from '@/features/trackTimeDuration/components/Console';
-import Schedule from '@/features/trackTimeDuration/components/Schedule';
-import { getChecks, getClocks } from '@/services/trackTimeDuration';
-import { setScenario } from '@/store/scenario';
-import trackTimeService from '@/store/trackTimeMachine';
-import { setWXFollow } from '@/store/permission';
-import Tooltip from '@/components/view/Tooltip'
-import RequestType, { thirdPartRequest } from '@/services/thirdPartRequest'
-import { setConfigs } from '@/store/common'
-import RecordFastSleep from '@/features/trackTimeDuration/components/RecordFastSleep'
-import Box from '@/components/layout/Box'
-import Layout from '@/components/layout/layout'
-import { CheckBoxType, NaviBarTitleShowType, TemplateType } from '@/utils/types'
-import { updateScenario } from '@/store/time'
-import { showModal } from '@/store/modal'
-import { ConsoleType, changeConsoleStatus } from '@/store/console'
-import TitleView from '@/features/trackTimeDuration/components/TitleView'
-import StatusIndicator from '@/features/trackTimeDuration/components/StatusIndicator'
-import { useTranslation } from 'react-i18next'
-import TableCellHeader from '@/components/layout/TableCellHeader'
-import SectionHeader from '@/components/layout/SectionHeader'
-import Header from '@/components/layout/Header'
-import { TimeFormatter } from '@/utils/time_format'
-import NoData from '@/components/view/NoData'
-import { ColorType } from '@/context/themes/color'
-import { jumpPage } from '@/features/trackTimeDuration/hooks/Common'
-import { ScrollView } from 'react-native-gesture-handler'
-// import TabBar from '../../components/Tabbar';
-
-// import Rings from '@components/view/Rings';
-
-let useNavigation;
-if (process.env.TARO_ENV == 'rn') {
-    useNavigation = require("@react-navigation/native").useNavigation
-}
-
-
-export default function IndexPage() {
-    const dispatch = useDispatch();
-    const { t } = useTranslation()
-    const [checkData, setCheckData] = useState(null)
-    const user = useSelector((state: any) => state.user);
-    const time = useSelector((state: any) => state.time);
-    const common = useSelector((state: any) => state.common);
-    const consoleData = useSelector((state: any) => state.console);
-    const [counter, setCounter] = useState(0)
-    const [timerId, setTimerId] = useState(null)
-    const [needShowAddTip, setNeedShowAddTip] = useState(false)
-    const [showErrorPage, setErrorPage] = useState(false)
-
-    const [swiperIndex, setSwiperIndex] = useState(0)
-    const [autoPlay, setAutoPlay] = useState(false)
-
-    const [showModal, setShowModal] = useState(false)
-    const [modalDetail, setModalDetail] = useState<any>({})
-
-    const [showModal2, setShowModal2] = useState(false)
-    const [modalDetail2, setModalDetail2] = useState<any>({})
-    const [showSingleFastEnd, setShowSingleFastEnd] = useState(false)
-    const [consoleStatus, setConsoleStatus] = useState(consoleData.status)
-
-    let navigation;
-    if (useNavigation) {
-        navigation = useNavigation()
-    }
-
-    global.dispatch = dispatch;
-
-    global.checkData = () => {
-        console.log('refresh clock data')
-        getCheckData()
-    }
-
-    useEffect(() => {
-        global.consoleType = 'idle'
-        dispatch(staticResources() as any);
-    }, [])
-
-    useEffect(() => {
-        getCheckData()
-    }, [time.status])
-
-    useEffect(() => {
-        setConsoleStatus(consoleData.status)
-        switch (consoleData.status) {
-            case ConsoleType.end:
-                setTimeout(() => {
-                    dispatch(changeConsoleStatus({ status: ConsoleType.idle }))
-                }, 2000)
-
-                break
-        }
-    }, [consoleData.status])
-
-    useEffect(() => {
-        if (user.isLogin) {
-            //检查用户是否添加过小程序
-            checkAddToMini();
-            //检查session是否过期
-            checkSession()
-            getCheckData()
-        }
-    }, [user.isLogin])
-
-    function checkSession() {
-        if (process.env.TARO_ENV === 'weapp') {
-            thirdPartRequest(RequestType.RequestTypeCheckSession).then(res => {
-            }).catch(err => {
-                console.log('session_key 已经失效,需要更新登录code')
-                thirdPartRequest(RequestType.RequestTypeWXLogin).then(result => {
-                    uploadSessionKey({ type: 'WX_MP', code: (result as any).code });
-                })
-            })
-        }
-    }
-
-    function checkAddToMini() {
-        process.env.TARO_ENV == 'weapp' &&
-            wx.checkIsAddedToMyMiniProgram({
-                success: (res) => {
-                    if (!res.added) {
-                        setNeedShowAddTip(true)
-                    }
-                },
-                fail: (e) => {
-                }
-            });
-    }
-
-    useEffect(() => {
-        startTimer();
-        return () => {
-            // 在组件卸载时清除定时器
-            if (timerId) {
-                clearInterval(timerId);
-            }
-        };
-    }, [timerId]);
-
-    const startTimer = () => {
-        // 避免重复启动定时器
-        if (timerId) {
-            return;
-        }
-
-        const id = setInterval(() => {
-            setCounter((prevCounter) => prevCounter + 1);
-            //每天0点刷新一下打卡数据
-            var now = new Date()
-            if (now.getHours() == 0 && now.getMinutes() == 0) {
-                getCheckData()
-            }
-        }, 1000);
-
-        setTimerId(id as any);
-    };
-
-
-    useReady(async () => {
-
-        const userData = await getStorage('userData');
-        if (userData) {
-            dispatch(getInfoSuccess(JSON.parse(userData as string)) as any);
-            setTimeout(() => {
-                checkWXPubFollow()
-                getCheckData()
-
-            }, 200)
-
-        }
-    })
-
-    if (process.env.TARO_ENV == 'weapp') {
-        useShareAppMessage((e) => {
-            return {
-                title: t('share.title'),
-                path: 'pages/clock/Clock'
-            }
-        })
-    }
-
-    function clearTempScenarioCache() {
-        global.schedule_fast = null
-        global.schedule_sleep = null
-        Taro.removeStorage({
-            key: 'tempScenario',
-            success: function (res) {
-            }
-        })
-    }
-
-    usePageScroll((e) => {
-    })
-
-    useDidShow(() => {
-        if (process.env.TARO_ENV == 'weapp') {
-            // global.updateTab(0)
-            if (user.isLogin) {
-                checkWXPubFollow()
-            }
-        }
-
-        clearTempScenarioCache()
-    })
-
-    global.refreshTime = () => {
-        getCheckData()
-    }
-
-    global.showSingleFastEnd = () => {
-        setShowSingleFastEnd(true)
-    }
-
-    function tapClock() {
-        if (!user.isLogin) {
-            jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
-        }
-    }
-
-    function getCheckData() {
-        getClocks().then(res => {
-            setErrorPage(false)
-            dispatch(updateScenario((res as any).current_record))
-            dispatch(setConfigs((res as any).time_input_schema));
-            dispatch(setScenario((res as any).scenario));
-
-            if ((res as any).theme_color) {
-                global.fastColor = (res as any).theme_color.fast
-                global.sleepColor = (res as any).theme_color.sleep
-            }
-
-            global.scenario = (res as any).current_record.scenario;
-            const currentState = trackTimeService.getSnapshot();
-            let json = {};
-            var key = (res as any).current_record.scenario
-            var status = (res as any).current_record.status
-            json[key] = status
-            currentState.value = json;
-            setCheckData(res as any)
-
-            if ((res as any).current_record.status != 'ONGOING1') {
-                setSwiperIndex(0)
-            }
-            else {
-                if (global.consoleType == 'going') {
-                    setShowSingleFastEnd(true)
-                    setTimeout(() => {
-                        setShowSingleFastEnd(false)
-                        setSwiperIndex(1)
-                        setAutoPlay(true)
-                        global.consoleType = 'end'
-                        dispatch(changeConsoleStatus({ status: ConsoleType.end }))
-                        setTimeout(() => {
-                            global.consoleType = 'idle'
-                        }, 2000)
-                    }, 500)
-                }
-                else {
-                }
-            }
-
-        }).catch(e => {
-            console.log('aaa')
-            if (!checkData) {
-                console.log('this is a test')
-                setErrorPage(true)
-            }
-            else {
-                console.log('sss')
-            }
-        })
-    }
-
-    function checkWXPubFollow() {
-        var params;
-        if (global.forceRefreshWXPub) {
-            params = {
-                force_refresh: true
-            }
-        }
-        global.forceRefreshWXPub = false
-        wxPubFollow(params).then(res => {
-            dispatch(setWXFollow((res as any).wx_pub_followed));
-            console.log('当前的关注状态' + (res as any).wx_pub_followed);
-
-        })
-    }
-
-    async function getStorage(key: string) {
-        try {
-            const res = await Taro.getStorage({ key });
-            return res.data;
-        } catch {
-            return '';
-        }
-    }
-
-    function schedule() {
-        if (!user.isLogin) {
-            return <View />
-        }
-        return <Schedule data={(checkData as any).current_record} />
-    }
-
-    function needSwiper() {
-        var isNeed = time.scenario == 'FAST_SLEEP' &&
-            (time.status == 'WAIT_FOR_START' ||
-                time.status == 'ONGOING1' ||
-                time.status == 'ONGOING2')
-        if (showSingleFastEnd) {
-            return false;
-        }
-        return isNeed
-    }
-
-    global.showClockModal = (isShow: boolean, detail: any) => {
-        setShowModal(isShow)
-        setModalDetail(detail)
-    }
-
-    global.showClockModal2 = (isShow: boolean, detail: any) => {
-        setShowModal2(isShow)
-        setModalDetail2(detail)
-    }
-
-    function headerView() {
-        return <TitleView title={t('page.clock.title')} showAddBtn={true}>
-            <StatusIndicator />
-        </TitleView>
-    }
-
-    function errorView() {
-        if (showErrorPage) {
-            return <NoData refresh={() => { getCheckData() }} />
-        }
-        return <View />
-    }
-
-    function consoleView() {
-        if (!checkData) {
-            return <View />
-        }
-        return <View className='console_bg'>
-            {
-                needSwiper() ? <Swiper className='swiper' indicatorColor='#333'
-                    indicatorActiveColor='#999'
-                    current={swiperIndex}
-                    autoplay={autoPlay}
-                    duration={300}
-                    interval={300}
-                    indicator-offset={[0, -30]}
-                    indicator-height={30}
-                    indicatorDots={global.consoleType == 'idle'}
-                    onChange={(e) => {
-                        setSwiperIndex(e.detail.current)
-                        if (e.detail.current == 0)
-                            setAutoPlay(false)
-                    }}
-                >
-                    <SwiperItem className='swiperItem'>
-                        <Console />
-
-                    </SwiperItem>
-
-                    <SwiperItem className='swiperItem'>
-                        <Console isNextStep={true} />
-                    </SwiperItem>
-                </Swiper> :
-                    <Console isNextStep={showSingleFastEnd} />
-
-            }
-        </View>
-    }
-
-
-    function detail() {
-        return (
-            <Layout type={TemplateType.customHeader} header={headerView()} title={t('page.clock.title')} titleShowStyle={NaviBarTitleShowType.scrollToShow}>
-                <View style={{ flex: 1, flexDirection: 'column', display: 'flex', backgroundColor: '#000', color: '#fff' }}>
-                    {
-                        needShowAddTip && <Tooltip title="添加到我的小程序" closeTip={() => { setNeedShowAddTip(false) }} />
-                    }
-
-                    <Box>
-                        <View className='clock_bg' onClick={tapClock}>
-                            <Clocks showCoverView={!global.showModal} />
-                        </View>
-                    </Box>
-                    {
-                        errorView()
-                    }
-                    {
-                        user.isLogin && consoleView()
-                    }
-                    {
-                        user.isLogin && checkData && schedule()
-                    }
-
-                    {
-                        user.isLogin && <View style={{ backgroundColor: global.isDebug ? 'pink' : 'transparent' }}>
-                            {
-                                checkData && (checkData as any).latest_record &&
-                                <SectionHeader top={48} bottom={24} title={t('feature.track_time_duration.record_fast_sleep.header.latest_record')}>
-                                    <Header title='' action={() => {
-                                        jumpPage('/pages/common/RecordsHistory?type=time&title=time')
-                                    }} />
-                                </SectionHeader>
-                            }
-                        </View>
-                    }
-                    {
-                        user.isLogin && checkData && (checkData as any).latest_record &&
-                        <RecordFastSleep type='latest' data={(checkData as any).latest_record} delSuccess={getCheckData} />
-                    }
-                    <View style={{ height: 100 }} />
-                </View>
-
-                {
-                    showModal && modalDetail
-                }
-                {
-                    showModal2 && modalDetail2
-                }
-
-            </Layout>
-        )
-    }
-
-    // if (process.env.TARO_ENV == 'rn')
-    //     return <View />
-
-
-    return <ScrollView >
-        {
-            detail()
-        }
-    </ScrollView>
-}

+ 5 - 1
src/pages/clock/Clock.weapp.tsx → src/pages/clock/Clock.tsx

@@ -95,7 +95,10 @@ export default function IndexPage() {
   }
 
   useEffect(() => {
-    AppState.addEventListener('change', handleAppStateChange);
+    if (process.env.TARO_ENV=='rn'){
+      AppState.addEventListener('change', handleAppStateChange);
+    }
+    
     global.consoleType = 'idle'
     dispatch(staticResources() as any);
     // dispatch(gobalConfigs() as any);
@@ -521,6 +524,7 @@ export default function IndexPage() {
           onBeforeLeave={() => {
             Taro.showTabBar();
           }}
+          onClick={()=>{alert('b')}}
           onClickOverlay={() => { alert('a') }}
           onAfterLeave={() => { setShowModal(false); setShowModal2(false) }}
           show={showModal || showModal2} round={true} overlay={true} position='bottom'

+ 64 - 3
src/pages/clock/demoA.tsx

@@ -1,12 +1,70 @@
 import GradientText from "@/components/basic/GradientText";
-import { View, PickerView, PickerViewColumn } from "@tarojs/components";
+import { View, PickerView, PickerViewColumn, Text } from "@tarojs/components";
+import Taro from "@tarojs/taro";
 import { useEffect, useLayoutEffect, useRef, useState } from "react";
-import { LayoutChangeEvent, Text } from "react-native";
+import { LayoutChangeEvent } from "react-native";
+import AppleHealthKit, {
+    HealthValue,
+    HealthKitPermissions,
+} from 'react-native-health'
+
+/* Permission options */
+const permissions = {
+    permissions: {
+        read: [AppleHealthKit.Constants.Permissions.Steps],
+        write: [AppleHealthKit.Constants.Permissions.Steps],
+    },
+} as HealthKitPermissions
 
 export default function DemoA() {
+    const [steps, setSteps] = useState('')
     useEffect(() => {
+
     }, [])
 
+    function healthKit() {
+        AppleHealthKit.initHealthKit(permissions, (error: string) => {
+            /* Called after we receive a response from the system */
+
+            if (error) {
+                console.log('[ERROR] Cannot grant permissions!')
+            }
+            console.log(permissions)
+
+            /* Can now read or write to HealthKit */
+
+
+
+
+            // AppleHealthKit.getHeartRateSamples(
+            //     options,
+            //     (callbackError: string, results: HealthValue[]) => {
+            //         /* Samples are now collected from HealthKit */
+            //     },
+            // )
+        })
+    }
+
+    function getSteps() {
+        const options = {
+            startDate: new Date(2024, 1, 2).toISOString(),
+        }
+        AppleHealthKit.getStepCount(options, (error: string, results: HealthValue) => {
+            if (!error){
+                setSteps(results.value+'')
+                Taro.showModal({
+                    title:'返回原始数据',
+                    content:JSON.stringify(results)
+                })
+            }
+            console.log(error,results)
+        })
+    }
+
+    function checkAuth(){
+        
+    }
+
     const years = [0, 1, 2, 3, 4, 5]
     const months = [0, 1, 2, 3, 4, 5]
     const days = [0, 1, 2, 3, 4, 5]
@@ -37,7 +95,10 @@ export default function DemoA() {
                     })}
                 </PickerViewColumn>
             </PickerView>
-            <GradientText style={{fontSize:20}}>Hello world</GradientText>
+            <GradientText style={{ fontSize: 20 }}>Hello world</GradientText>
+            <Text style={{ color: 'red' }} onClick={healthKit}>Health Kit 授权</Text>
+            <Text style={{ color: 'red' }} onClick={getSteps}>获取当前步数:<Text>{steps}</Text> </Text>
+            
         </View>
     );
 }

+ 1 - 1
src/pages/rn/RNMain.tsx

@@ -3,7 +3,7 @@ import { NavigationContainer } from '@react-navigation/native';
 import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
 import { createStackNavigator } from '@react-navigation/stack';
 
-import Clock from '../clock/Clock.weapp'
+import Clock from '../clock/Clock'
 import Metric from '../metric/Metric'
 import Workout from '../workout/Workout'
 import Profile from '../account/Profile'

+ 12 - 1
src/utils/time_format.ts

@@ -112,8 +112,18 @@ export class TimeFormatter {
 
   }
 
+  //显示完整日期
+  static timelineFullFormatTime(timestamp:number):string{
+    var date = new Date(timestamp)
+    var str = `${TimeFormatter.formatNumber(date.getHours())}:${TimeFormatter.formatNumber(date.getMinutes())}`;
+    if (global.language=='en'){
+      return `${TimeFormatter.getDayOfWeek(date.getDay())} ${TimeFormatter.getMonth(date.getMonth()+1)} ${date.getDate()} ${str}`
+    }
+    return `${TimeFormatter.getMonth(date.getMonth()+1)}${date.getDate()}日${TimeFormatter.getDayOfWeek(date.getDay())} ${str}`
+  }
+
 
-  //1.只显示时间
+  //只显示时间
   static timelineFormatTime(timestamp: number, isTestUser?: boolean): string {
     if (!timestamp) {
       return '  '
@@ -127,6 +137,7 @@ export class TimeFormatter {
     }
     return str
   }
+
   //2.基于日期显示日期,省略今天描述
   static dateDescription(timestamp: number, showToday?: boolean): string {
     if (!timestamp) {

+ 78 - 4
yarn.lock

@@ -1447,11 +1447,39 @@
     xcode "^3.0.1"
     xml2js "0.4.23"
 
+"@expo/config-plugins@^7.2.2":
+  version "7.8.4"
+  resolved "https://registry.npmmirror.com/@expo/config-plugins/-/config-plugins-7.8.4.tgz#533b5d536c1dc8b5544d64878b51bda28f2e1a1f"
+  integrity sha512-hv03HYxb/5kX8Gxv/BTI8TLc9L06WzqAfHRRXdbar4zkLcP2oTzvsLEF4/L/TIpD3rsnYa0KU42d0gWRxzPCJg==
+  dependencies:
+    "@expo/config-types" "^50.0.0-alpha.1"
+    "@expo/fingerprint" "^0.6.0"
+    "@expo/json-file" "~8.3.0"
+    "@expo/plist" "^0.1.0"
+    "@expo/sdk-runtime-versions" "^1.0.0"
+    "@react-native/normalize-color" "^2.0.0"
+    chalk "^4.1.2"
+    debug "^4.3.1"
+    find-up "~5.0.0"
+    getenv "^1.0.0"
+    glob "7.1.6"
+    resolve-from "^5.0.0"
+    semver "^7.5.3"
+    slash "^3.0.0"
+    slugify "^1.6.6"
+    xcode "^3.0.1"
+    xml2js "0.6.0"
+
 "@expo/config-types@^47.0.0":
   version "47.0.0"
   resolved "https://registry.npmmirror.com/@expo/config-types/-/config-types-47.0.0.tgz#99eeabe0bba7a776e0f252b78beb0c574692c38d"
   integrity sha512-r0pWfuhkv7KIcXMUiNACJmJKKwlTBGMw9VZHNdppS8/0Nve8HZMTkNRFQzTHW1uH3pBj8jEXpyw/2vSWDHex9g==
 
+"@expo/config-types@^50.0.0-alpha.1":
+  version "50.0.0"
+  resolved "https://registry.npmmirror.com/@expo/config-types/-/config-types-50.0.0.tgz#b534d3ec997ec60f8af24f6ad56244c8afc71a0b"
+  integrity sha512-0kkhIwXRT6EdFDwn+zTg9R2MZIAEYGn1MVkyRohAd+C9cXOb5RA8WLQi7vuxKF9m1SMtNAUrf0pO+ENK0+/KSw==
+
 "@expo/config@7.0.3", "@expo/config@~7.0.2":
   version "7.0.3"
   resolved "https://registry.npmmirror.com/@expo/config/-/config-7.0.3.tgz#c9c634e76186de25e296485e51418f1e52966e6e"
@@ -1510,6 +1538,19 @@
     tmp "^0.0.33"
     tslib "^2.4.0"
 
+"@expo/fingerprint@^0.6.0":
+  version "0.6.0"
+  resolved "https://registry.npmmirror.com/@expo/fingerprint/-/fingerprint-0.6.0.tgz#77366934673d4ecea37284109b4dd67f9e6a7487"
+  integrity sha512-KfpoVRTMwMNJ/Cf5o+Ou8M/Y0EGSTqK+rbi70M2Y0K2qgWNfMJ1gm6sYO9uc8lcTr7YSYM1Rme3dk7QXhpScNA==
+  dependencies:
+    "@expo/spawn-async" "^1.5.0"
+    chalk "^4.1.2"
+    debug "^4.3.4"
+    find-up "^5.0.0"
+    minimatch "^3.0.4"
+    p-limit "^3.1.0"
+    resolve-from "^5.0.0"
+
 "@expo/image-utils@0.3.22":
   version "0.3.22"
   resolved "https://registry.npmmirror.com/@expo/image-utils/-/image-utils-0.3.22.tgz#3a45fb2e268d20fcc761c87bca3aca7fd8e24260"
@@ -1545,6 +1586,15 @@
     json5 "^2.2.2"
     write-file-atomic "^2.3.0"
 
+"@expo/json-file@~8.3.0":
+  version "8.3.0"
+  resolved "https://registry.npmmirror.com/@expo/json-file/-/json-file-8.3.0.tgz#fc84af77b532a4e9bfb5beafd0e3b7f692b6bd7e"
+  integrity sha512-yROUeXJXR5goagB8c3muFLCzLmdGOvoPpR5yDNaXrnTp4euNykr9yW0wWhJx4YVRTNOPtGBnEbbJBW+a9q+S6g==
+  dependencies:
+    "@babel/code-frame" "~7.10.4"
+    json5 "^2.2.2"
+    write-file-atomic "^2.3.0"
+
 "@expo/metro-config@~0.5.0", "@expo/metro-config@~0.5.1":
   version "0.5.2"
   resolved "https://registry.npmmirror.com/@expo/metro-config/-/metro-config-0.5.2.tgz#9474454dcf8c2e3d66231f36f8bbbae5e9e0c3dc"
@@ -1592,6 +1642,15 @@
     base64-js "^1.2.3"
     xmlbuilder "^14.0.0"
 
+"@expo/plist@^0.1.0":
+  version "0.1.0"
+  resolved "https://registry.npmmirror.com/@expo/plist/-/plist-0.1.0.tgz#eabc95f951d14e10c87fd0443ee01d567371f058"
+  integrity sha512-xWD+8vIFif0wKyuqe3fmnmnSouXYucciZXFzS0ZD5OV9eSAS1RGQI5FaGGJ6zxJ4mpdy/4QzbLdBjnYE5vxA0g==
+  dependencies:
+    "@xmldom/xmldom" "~0.7.7"
+    base64-js "^1.2.3"
+    xmlbuilder "^14.0.0"
+
 "@expo/prebuild-config@5.0.7":
   version "5.0.7"
   resolved "https://registry.npmmirror.com/@expo/prebuild-config/-/prebuild-config-5.0.7.tgz#4658b66126c4d32c7b6302571e458a71811b07aa"
@@ -3855,7 +3914,7 @@
   resolved "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99"
   integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==
 
-"@xmldom/xmldom@~0.7.0":
+"@xmldom/xmldom@~0.7.0", "@xmldom/xmldom@~0.7.7":
   version "0.7.13"
   resolved "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.7.13.tgz#ff34942667a4e19a9f4a0996a76814daac364cf3"
   integrity sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==
@@ -12393,7 +12452,7 @@ p-limit@^2.0.0, p-limit@^2.2.0:
   dependencies:
     p-try "^2.0.0"
 
-p-limit@^3.0.2:
+p-limit@^3.0.2, p-limit@^3.1.0:
   version "3.1.0"
   resolved "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
   integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
@@ -13624,6 +13683,13 @@ react-native-gradle-plugin@^0.70.3:
   resolved "https://registry.npmmirror.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.70.3.tgz#cbcf0619cbfbddaa9128701aa2d7b4145f9c4fc8"
   integrity sha512-oOanj84fJEXUg9FoEAQomA8ISG+DVIrTZ3qF7m69VQUJyOGYyDZmPqKcjvRku4KXlEH6hWO9i4ACLzNBh8gC0A==
 
+react-native-health@^1.18.0:
+  version "1.18.0"
+  resolved "https://registry.npmmirror.com/react-native-health/-/react-native-health-1.18.0.tgz#714f4f8445a51cb0c78fd576fef05b2f6bf1bf61"
+  integrity sha512-4CVLyBGrd6s/yPyb2/veZA0OobRP3SZ96eBZ2DunJr/1ZF3lKX3AuFFvGbCRNkycndni4VRr9T4b0MLqhXG+Hg==
+  dependencies:
+    "@expo/config-plugins" "^7.2.2"
+
 react-native-image-pan-zoom@^2.1.12:
   version "2.1.12"
   resolved "https://registry.npmmirror.com/react-native-image-pan-zoom/-/react-native-image-pan-zoom-2.1.12.tgz#eb98bf56fb5610379bdbfdb63219cc1baca98fd2"
@@ -14637,7 +14703,7 @@ semver@^6.0.0, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1:
   resolved "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
   integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
 
-semver@^7.0.0, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8:
+semver@^7.0.0, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3:
   version "7.5.4"
   resolved "https://registry.npmmirror.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
   integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
@@ -14884,7 +14950,7 @@ slice-ansi@^4.0.0:
     astral-regex "^2.0.0"
     is-fullwidth-code-point "^3.0.0"
 
-slugify@^1.3.4:
+slugify@^1.3.4, slugify@^1.6.6:
   version "1.6.6"
   resolved "https://registry.npmmirror.com/slugify/-/slugify-1.6.6.tgz#2d4ac0eacb47add6af9e04d3be79319cbcc7924b"
   integrity sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==
@@ -17190,6 +17256,14 @@ xml2js@0.4.23:
     sax ">=0.6.0"
     xmlbuilder "~11.0.0"
 
+xml2js@0.6.0:
+  version "0.6.0"
+  resolved "https://registry.npmmirror.com/xml2js/-/xml2js-0.6.0.tgz#07afc447a97d2bd6507a1f76eeadddb09f7a8282"
+  integrity sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==
+  dependencies:
+    sax ">=0.6.0"
+    xmlbuilder "~11.0.0"
+
 xml2js@^0.5.0:
   version "0.5.0"
   resolved "https://registry.npmmirror.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7"