Leon 2 anos atrás
pai
commit
4c59c4754f

+ 10 - 8
ios/hola.xcodeproj/project.pbxproj

@@ -538,9 +538,10 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = hola/hola.entitlements;
-				CODE_SIGN_STYLE = Manual;
+				CODE_SIGN_IDENTITY = "Apple Development";
+				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = 2ULWQK4QBS;
+				DEVELOPMENT_TEAM = 8647787J63;
 				ENABLE_BITCODE = NO;
 				INFOPLIST_FILE = hola/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = (
@@ -553,9 +554,9 @@
 					"-lc++",
 				);
 				OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
-				PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
+				PRODUCT_BUNDLE_IDENTIFIER = com.hye.fast;
 				PRODUCT_NAME = hola;
-				PROVISIONING_PROFILE_SPECIFIER = taro_demo_dev_profile;
+				PROVISIONING_PROFILE_SPECIFIER = "";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_VERSION = 5.0;
 				VERSIONING_SYSTEM = "apple-generic";
@@ -569,9 +570,10 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = hola/hola.entitlements;
-				CODE_SIGN_STYLE = Manual;
+				CODE_SIGN_IDENTITY = "Apple Development";
+				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = 2ULWQK4QBS;
+				DEVELOPMENT_TEAM = 8647787J63;
 				INFOPLIST_FILE = hola/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
@@ -583,9 +585,9 @@
 					"-lc++",
 				);
 				OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
-				PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
+				PRODUCT_BUNDLE_IDENTIFIER = com.hye.fast;
 				PRODUCT_NAME = hola;
-				PROVISIONING_PROFILE_SPECIFIER = taro_demo_dev_profile;
+				PROVISIONING_PROFILE_SPECIFIER = "";
 				SWIFT_VERSION = 5.0;
 				VERSIONING_SYSTEM = "apple-generic";
 			};

+ 2 - 2
ios/hola/Info.plist

@@ -2,8 +2,6 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
-	<key>ITSAppUsesNonExemptEncryption</key>
-	<false/>
 	<key>CFBundleDevelopmentRegion</key>
 	<string>en</string>
 	<key>CFBundleDisplayName</key>
@@ -24,6 +22,8 @@
 	<string>????</string>
 	<key>CFBundleVersion</key>
 	<string>1</string>
+	<key>ITSAppUsesNonExemptEncryption</key>
+	<false/>
 	<key>LSRequiresIPhoneOS</key>
 	<true/>
 	<key>NSAppTransportSecurity</key>

+ 1 - 1
src/app.scss

@@ -184,7 +184,7 @@ page {
 
 .add_more{
     width: 320px;
-    height: 290px;
+    height: 314px;
     display: flex;
     flex-direction: column;
     align-items: center;

Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 0
src/components/basic/Icons.tsx


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

@@ -37,12 +37,12 @@
 @keyframes modalBgAnim {
 
     100% {
-        background-color: rgba($color: #000000, $alpha: 0.9);
+        background-color: rgba($color: #000000, $alpha: 0.95);
     }
 }
 
 .modal_dismiss {
-    background-color: rgba($color: #000000, $alpha: 0.9);
+    background-color: rgba($color: #000000, $alpha: 0.95);
     animation: modalBgHideAnim 0.2s linear forwards;
 }
 

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

@@ -3,6 +3,7 @@ import './layout.scss'
 import { NaviBarTitleShowType, TemplateType } from "@/utils/types";
 import { useEffect, useState } from "react";
 import Taro, { usePageScroll } from "@tarojs/taro";
+import { rpxToPx } from "@/utils/tools";
 
 let useNavigation;
 if (process.env.TARO_ENV == 'rn') {
@@ -75,13 +76,13 @@ export default function Layout(props: {
                     {
                         props.isFastSleepTheme ? <Text className='layout_title fast_sleep_text'
                             style={{
-                                fontSize: props.secondPage ? 28 : 36
+                                fontSize: props.secondPage ? rpxToPx(56) : rpxToPx(72)
                             }}
                         >{props.title}</Text> :
                             <Text className='layout_title'
                                 style={{
                                     color: props.titleColor ? props.titleColor : '#fff',
-                                    fontSize: props.secondPage ? 28 : 36
+                                    fontSize: props.secondPage ? rpxToPx(56) : rpxToPx(72)
                                 }}
                             >{props.title}</Text>
                     }

+ 20 - 0
src/components/view/MultiText.tsx

@@ -0,0 +1,20 @@
+import { Text } from "@tarojs/components"
+
+export default function Component(props: {
+    values: any,
+    units: any,
+    color:string,
+    valueSize:any,
+    unitSize:any
+}) {
+    return <Text  style={{color:props.color}}>
+        {
+            props.values.map((item, index) => {
+                return <Text>
+                    <Text style={{fontSize:props.valueSize,fontWeight:'bold',lineHeight:1,marginRight:1}}>{item}</Text>
+                    <Text  style={{fontSize:props.unitSize,opacity:0.8,lineHeight:1,marginRight:1,fontWeight:'bold'}}>{props.units[index]}</Text>
+                </Text>
+            })
+        }
+    </Text>
+}

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

@@ -310,7 +310,8 @@ export default {
             disable_switch_modal_btn:'我知道了'
         },
         workout:{
-            finish_current:'请先完成当前训练',
+            finish_title:'{{name}}计时训练中',
+            finish_current:'请先结束训练',
             add_more:'添加更多',
             choose_workout:'选择运动项',
             order:'调整排序',

+ 54 - 0
src/features/common/SpecBtns.tsx

@@ -164,6 +164,60 @@ export const ChooseScenarioBtn = (props: { onClick: Function, title: string, bac
     )
 }
 
+/*
+onClick={() => { props.onClick() }}
+            lowLight={props.lowLight ? props.lowLight : false}
+            lightLoading={true}
+            btnStyle={{
+                height: rpxToPx(100),
+                borderRadius: rpxToPx(50),
+                borderColor: global.sleepColor ? global.sleepColor : ColorType.sleep,
+                borderWidth: 2,
+                borderStyle: 'solid',
+                width: rpxToPx(320),
+                // paddingLeft: 40,
+                // paddingRight: 40,
+                color: global.sleepColor ? global.sleepColor : ColorType.sleep,
+                fontWeight: 'bold',
+                fontSize: 20,
+                display: 'flex',
+                alignItems: 'center',
+                justifyContent: 'center',
+                // lineHeight:20
+            }}
+*/ 
+
+export const WorkoutEndBtn = (props: { onClick: Function, title: string, background: string, disable?: boolean,longClick?:Function }) => {
+    return (
+        <Buttons title={props.title} type={ButtonType.outline}
+            onClick={() => { props.onClick() }}
+            lowLight={props.disable ? props.disable : false}
+            longClick={props.longClick}
+            disabled={props.disable}
+            btnStyle={{
+                height: 50,
+                width: 300,
+                boxSizing: 'border-box',
+                borderRadius: 25,
+                paddingLeft: 40,
+                paddingRight: 40,
+                color: props.background,
+                fontSize: 20,
+                fontWeight: 'bold',
+                display: 'flex',
+                alignItems: 'center',
+                justifyContent: 'center',
+
+                borderColor: props.background,
+                borderWidth: 2,
+                borderStyle: 'solid',
+
+
+            }}
+        />
+    )
+}
+
 export const RecordMetricBtn = (props: { onClick: Function, title: string, themeColor: string, isDisable?: boolean,longClick?:Function }) => {
     return (
         <PostBtn title={props.title} type={ButtonType.elevated}

+ 6 - 5
src/features/trackSomething/components/MetricItem.scss

@@ -17,15 +17,16 @@
 .metric_title {
     font-size: 36px;
     line-height: 36px;
-    height: 40px;
+    height: 36px;
     color: #ffffff;
     font-weight: 500;
 }
 
 .metric_value_bg{
     height: 50px;
-    margin-top: 10px;
-    margin-bottom: 10px;
+    margin-top: 20px;
+    margin-bottom: 12px;
+    margin-right: 2px;
 }
 .metric_value {
     font-size: 48px;
@@ -33,8 +34,8 @@
     height: 50px;
     font-weight: 500;
     color: #ffffff;
-    margin-top: 20px;
-    margin-bottom: 12px;
+    // margin-top: 20px;
+    // margin-bottom: 12px;
 }
 
 .metric_unit {

+ 6 - 2
src/features/trackSomething/components/MetricItem.tsx

@@ -1,6 +1,7 @@
 import { View, Text, Image } from "@tarojs/components";
 import './MetricItem.scss'
 import { RecordMetricBtn } from "@/features/common/SpecBtns";
+import { rpxToPx } from "@/utils/tools";
 
 export default function Component(props: {
     title: string,
@@ -12,6 +13,7 @@ export default function Component(props: {
     isDisabled?: boolean,
     onClickDetail: Function,
     onClick: Function,
+    valueView?: any,
     showBadge?: boolean,
     showDetail?: boolean,
     longClick?: Function,
@@ -37,7 +39,9 @@ export default function Component(props: {
     return <View className="metric_bg">
         <Text className="metric_title" style={{ color: props.themeColor }} onClick={() => props.onClickDetail()}>{props.title}</Text>
         <View className="metric_value_bg" onClick={() => props.onClickDetail()}>
-            <Text className="metric_value">{props.value}<Text className="metric_unit">{props.unit}</Text></Text>
+            {
+                props.valueView ? props.valueView : <Text className="metric_value">{props.value}<Text className="metric_unit">{props.unit}</Text></Text>
+            }
         </View>
         <View className="metric_desc_bg" onClick={() => props.onClickDetail()}>
             <Text className="mteric_desc">{props.desc}</Text>
@@ -46,7 +50,7 @@ export default function Component(props: {
             }
 
         </View>
-        <View style={{ position: 'relative', marginTop: 10 }} >
+        <View style={{ position: 'relative', marginTop: rpxToPx(36) }} >
             <RecordMetricBtn themeColor={props.themeColor}
                 title={props.btnText}
                 onClick={clickBtn}

+ 31 - 19
src/features/workout/Result.scss

@@ -1,13 +1,17 @@
-.result_detail_text{
+@import url('./WorkoutStopWatch.scss');
+
+.result_detail_text {
     color: #fff;
     font-size: 48px;
     line-height: 48px;
     font-weight: bold;
-    margin-left: 32px;
+    margin-left: 46px;
+    margin-top: 24px;
+    line-height: 72px;
 }
 
-.result_type{
-    margin-left: 32px;
+.result_type {
+    margin-left: 46px;
     margin-top: 20px;
     color: #fff;
     opacity: 0.4;
@@ -16,16 +20,16 @@
     line-height: 32px;
 }
 
-.result_group_text{
+.result_group_text {
     font-weight: bold;
     color: #fff;
     font-size: 40px;
     line-height: 40px;
     margin-top: 34px;
-    margin-left: 32px;
+    margin-left: 46px;
 }
 
-.result_summary_title{
+.result_summary_title {
     margin-top: 28px;
     color: #fff;
     font-size: 32px;
@@ -35,26 +39,26 @@
     margin-bottom: 10px;
 }
 
-.result_summary_total{
+.result_summary_total {
     font-size: 48px;
     line-height: 48px;
     font-weight: bold;
 }
 
-.result_count{
+.result_count {
     margin-top: 14px;
     color: #fff;
     opacity: 0.4;
     font-size: 32px;
     line-height: 32px;
     font-weight: bold;
-    margin-left: 32px;
+    margin-left: 46px;
     margin-bottom: 18px;
 }
 
-.result_item{
-    margin-left: 32px;
-    margin-right: 32px;
+.result_item {
+    margin-left: 46px;
+    margin-right: 46px;
     margin-bottom: 28px;
     background-color: #1c1c1c;
     border-radius: 26px;
@@ -68,18 +72,18 @@
     position: relative;
 }
 
-.result_item_rest{
+.result_item_rest {
     background-color: #121212;
 }
 
-.workout_result_value{
+.workout_result_value {
     font-weight: bold;
     font-size: 72px;
     line-height: 72px;
     margin-top: 40px;
 }
 
-.result_time{
+.result_time {
     position: absolute;
     right: 32px;
     bottom: 28px;
@@ -87,7 +91,7 @@
     opacity: 0.4;
 }
 
-.result_del{
+.result_del {
     position: absolute;
     left: 0;
     right: 0;
@@ -96,14 +100,22 @@
     text-align: center;
 }
 
-.result_summary_time{
+.resule_del_relative {
+    width: 100%;
+    margin-top: 100px;
+    margin-bottom: 100px;
+    color: #FA5151;
+    text-align: center;
+}
+
+.result_summary_time {
     font-size: 36px;
     line-height: 36px;
     font-weight: bold;
     margin-bottom: 12px;
 }
 
-.result_summary_desc{
+.result_summary_desc {
     color: #fff;
     opacity: 0.4;
     font-size: 20px;

+ 163 - 97
src/features/workout/Result.tsx

@@ -1,31 +1,50 @@
 import { ColorType } from "@/context/themes/color";
 import { View, Text } from "@tarojs/components";
 import { useRouter } from "@tarojs/taro";
-import { useEffect, useState } from "react";
+import { useEffect, useRef, useState } from "react";
 import './Result.scss';
 import Taro from "@tarojs/taro";
 import { useTranslation } from "react-i18next";
 import { deleteWorkoutRecord } from "@/services/workout";
 import { rpxToPx } from "@/utils/tools";
 import { TimeFormatter } from "@/utils/time_format";
+import Layout from "@/components/layout/layout";
+import { NaviBarTitleShowType, TemplateType } from "@/utils/types";
+import Box from "@/components/layout/Box";
+import MultiText from "@/components/view/MultiText";
+import { IconX } from "@/components/basic/Icons";
 
 export default function Component() {
     const router = useRouter();
     const [histories, setHistories] = useState<any>([])
     const [record, setRecord] = useState(null)
+    const [showDel, setShowDel] = useState(false)
+    const [delPosition, setDelPosition] = useState('absolute')
+    const myRef = useRef(null)
     const { t } = useTranslation()
 
     useEffect(() => {
         var data = JSON.parse(router.params.detail as any)
-        console.log(data)
         setRecord(data)
         var list = data.items[0].groups
         setHistories(list)
     }, [])
 
+    useEffect(() => {
+        setTimeout(() => {
+            const query = Taro.createSelectorQuery();
+            query.select('#footId').boundingClientRect((rect) => {
+                console.log('Element size:', rect);
+                console.log('screen height', Taro.getSystemInfoSync().windowHeight)
+                setShowDel(true)
+                setDelPosition(Taro.getSystemInfoSync().windowHeight - (rect as any).top > 100 ? 'absolute' : 'relative')
+            }).exec();
+        }, 100)
+    }, [])
+
     function twoTimeDuration(start, end) {
         var time = Math.floor((end - start) / 1000);
-        time = time<1?1:time
+        time = time < 1 ? 1 : time
         const hours = Math.floor(time / 3600);
         const minutes = Math.floor((time % 3600) / 60);
         const seconds = Math.floor(time % 60);
@@ -63,44 +82,47 @@ export default function Component() {
         return count;
     }
 
-    function getValue_backup(item) {
-        var list = item.values
-        if ((record as any).items[0].format == 'TIME_SECONDS') {
-            return ''
-            // return list[0].value+'小时'+list[1].value+'分钟'+list[2].value+'秒'
-        }
-        
-        var count = 1
-        var unit = ''
-        for (var i = 0; i < list.length; i++) {
-            count = count * (parseInt(list[i].value + ''))
-            unit = unit + list[i].unit + '·'
-        }
-        var result = count + unit
-        return result.substring(0, result.length - 1)
-    }
 
     function getValue(item) {
         var list = item.values
         if ((record as any).items[0].format == 'TIME_SECONDS') {
-            return ''
+            var time = Math.floor((item.end.timestamp - item.start.timestamp) / 1000);
+            time = time < 1 ? 1 : time
+            debugger
+            var obj = TimeFormatter.workoutTimeAndUnitList(time)
+            return <MultiText values={obj.values}
+                units={obj.units}
+                color={router.params.themeColor + ''}
+                valueSize={rpxToPx(48)}
+                unitSize={rpxToPx(32)} />
             // return list[0].value+'小时'+list[1].value+'分钟'+list[2].value+'秒'
         }
 
-        var  str = ''
-        for (var i = 0; i < list.length; i++) {
-            str += (list[i].value+list[i].unit+'·')
-        }
-        return str.substring(0, str.length - 1)
-        
-        // var count = 1
-        // var unit = ''
+        // var str = ''
         // for (var i = 0; i < list.length; i++) {
-        //     count = count * (parseInt(list[i].value + ''))
-        //     unit = unit + list[i].unit + '·'
+        //     str += (list[i].value + list[i].unit + '·')
         // }
-        // var result = count + unit
-        // return result.substring(0, result.length - 1)
+        // return str.substring(0, str.length - 1)
+
+        return <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
+            {
+                list.map((item, index) => {
+                    return <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
+                        <MultiText values={[item.value]}
+                            units={[item.unit]}
+                            color={router.params.themeColor + ''}
+                            valueSize={rpxToPx(48)}
+                            unitSize={rpxToPx(32)} />
+                        {
+                            index<list.length-1 && <IconX width={rpxToPx(32)} color={router.params.themeColor+''} />
+                        }
+                        {
+                            index<list.length-1 && <View style={{ width: 1 }} />
+                        }
+                    </View>
+                })
+            }
+        </View>
     }
 
     function del() {
@@ -125,29 +147,26 @@ export default function Component() {
         })
     }
 
-    function getTotalValue(){
+    function getTotalValue() {
         if (!record) return ''
-        if (!(record as any).items[0].summary_stats || (record as any).items[0].summary_stats.length==0){
+        if (!(record as any).items[0].summary_stats || (record as any).items[0].summary_stats.length == 0) {
             return ''
         }
         if ((record as any).items[0].format == 'TIME_SECONDS') {
             var time = (record as any).items[0].summary_stats[0].value
-            const hours = Math.floor(time / 3600);
-            const minutes = Math.floor((time % 3600) / 60);
-            const seconds = Math.floor(time % 60);
-            var str = ''
-            if (hours > 0) {
-                str = str + hours + '小时'
-            }
-            if (minutes > 0) {
-                str = str + minutes + '分钟'
-            }
-            if (seconds > 0) {
-                str = str + seconds + '秒'
-            }
-            return str
+            var obj = TimeFormatter.workoutTimeAndUnitList(time)
+            return <MultiText values={obj.values}
+                units={obj.units}
+                color={router.params.themeColor + ''}
+                valueSize={rpxToPx(48)}
+                unitSize={rpxToPx(32)} />
         }
-        return (record as any).items[0].summary_stats[0].value+(record as any).items[0].summary_stats[0].unit
+        return <MultiText values={[(record as any).items[0].summary_stats[0].value]}
+            units={[(record as any).items[0].summary_stats[0].unit]}
+            color={router.params.themeColor + ''}
+            valueSize={rpxToPx(48)}
+            unitSize={rpxToPx(32)} />
+        // return (record as any).items[0].summary_stats[0].value + (record as any).items[0].summary_stats[0].unit
         // var count = 0
         // histories.map(item=>{
         //     if (item.type=='WORK'){
@@ -157,66 +176,113 @@ export default function Component() {
         // return count
     }
 
-    function getRealDuration(){
+    function getRealDuration() {
         if (!record) return ''
 
         var seconds = 0
-        histories.map(item=>{
+        histories.map(item => {
             var time = Math.floor((item.end.timestamp - item.start.timestamp) / 1000);
-            if (time<1){
+            if (time < 1) {
                 time = 1
             }
-            seconds+=time
+            seconds += time
         })
         // var seconds = Math.floor((histories[histories.length-1].end.timestamp-histories[0].start.timestamp)/1000)
-        return TimeFormatter.workoutTime(seconds)
+        var obj = TimeFormatter.workoutTimeAndUnitList(seconds)
+        return <MultiText values={obj.values}
+            units={obj.units}
+            color={router.params.themeColor + ''}
+            valueSize={rpxToPx(48)}
+            unitSize={rpxToPx(32)} />
     }
 
-    function getPlanDuration(){
+    function getPlanDuration() {
         if (!record) return ''
-        var seconds = (record as any).items[0].duration/1000
-        return TimeFormatter.workoutTime(seconds)
-    }    
-
-    return <View style={{ color: '#fff', display: 'flex', flexDirection: 'column' }}>
-        <Text className="result_detail_text" style={{ color: router.params.themeColor }}>{router.params.title}</Text>
-        <Text className="result_type">计时训练</Text>
-        <Text className="result_group_text">训练统计</Text>
-        <View style={{ marginLeft: rpxToPx(32), display: 'flex', flexDirection: 'column',marginBottom:rpxToPx(56) }}>
-            <Text className="result_summary_title">总量</Text>
-            <Text className="result_summary_total" style={{ color: router.params.themeColor }}>{getTotalValue()}</Text>
-            <Text className="result_summary_title">用时</Text>
-            <View style={{ flexDirection: 'row', display: 'flex', width: '100%' }}>
-                <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
-                    <Text className="result_summary_time" style={{ color: router.params.themeColor }}>{getRealDuration()}</Text>
-                    <Text className="result_summary_desc">实际</Text>
-                </View>
-                <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginLeft:rpxToPx(90) }}>
-                    <Text className="result_summary_time" style={{ color: router.params.themeColor }}>{getPlanDuration()}</Text>
-                    <Text className="result_summary_desc">计划</Text>
-                </View>
+        var seconds = (record as any).items[0].duration / 1000
+        return TimeFormatter.formateDurationBySeconds(seconds)
+    }
+
+
+    function detail() {
+        return <View style={{ color: '#fff', display: 'flex', flexDirection: 'column' }}>
+            <Text className="result_detail_text" style={{ color: router.params.themeColor, fontSize: rpxToPx(56) }}>{router.params.title}</Text>
+            <View style={{ display: 'flex', flexDirection: 'column', color: '#fff', marginLeft: rpxToPx(46) }}>
+                <Text style={{ fontSize: rpxToPx(40), fontWeight: 'bold', marginBottom: rpxToPx(6) }}>训练统计</Text>
+                <Text className="train_summary_title">总量</Text>
+                {
+                    getTotalValue()
+                }
+                {/* <Text className="train_summary_value" style={{ color: workout.item.theme_color }}></Text> */}
+                <Text className="train_summary_title">用时</Text>
+                {
+                    getRealDuration()
+                }
+
             </View>
+            <Text className="result_group_text" style={{ marginBottom: rpxToPx(48), marginTop: rpxToPx(112) }}>详情</Text>
+
+            {/* <View style={{ position: 'relative' }}>
+                    <Box key={index} >
+                        <View>
+                            <Text className="working_index">{item.type == 'REST' ? `第${item.index}组` : '组间休息'}</Text>
+                            <View style={{  display: 'flex', flexDirection: 'row', alignItems: 'center', marginTop: item.type == 'REST' ? rpxToPx(60) : 0, marginBottom: item.type == 'REST' ? rpxToPx(28) : 0 }}>
+                                {item.type == 'REST' && workout.item.schemas[0].format != 'TIME_SECONDS' &&
+                                    <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
+                                        {
+                                            <MultiText values={[parseInt(item.value)]} units={[workout.item.schemas[0].values[0].unit]} color={workout.item.theme_color} valueSize={rpxToPx(48)} unitSize={rpxToPx(32)} />
+                                        }
+                                        {
+                                            item.value2 && <IconX width={rpxToPx(32)} color={workout.item.theme_color} />
+                                        }
+                                        {
+                                            item.value2 && <View style={{width:1}} />
+                                        }
+                                        {
+                                            item.value2 && <MultiText values={[parseInt(item.value2)]} units={[workout.item.schemas[0].values[1].unit]} color={workout.item.theme_color} valueSize={rpxToPx(48)} unitSize={rpxToPx(32)} />
+                                        }
+                                        {
+                                            item.value3 && <MultiText values={[parseInt(item.value3)]} units={[workout.item.schemas[0].values[2].unit]} color={workout.item.theme_color} valueSize={rpxToPx(48)} unitSize={rpxToPx(32)} />
+                                        }
+                                    </View>
+                                    // <Text className="working_group_value" style={{ color: workout.item.theme_color }}>{getGroupValue(item)}</Text>
+                                }
+                                {
+                                    item.type == 'REST' && workout.item.schemas[0].format == 'TIME_SECONDS' &&
+                                    <MultiText values={twoTimeFormateList(groups[index - 1].time,item.time).values} units={twoTimeFormateList(groups[index - 1].time,item.time).units} color={workout.item.theme_color} valueSize={rpxToPx(48)} unitSize={rpxToPx(32)} />
+                                }
+                                <View style={{ flex: 1 }} />
+
+                                <Text className="working_group_duration" style={{ opacity: item.type != 'REST' || workout.item.schemas[0].format != 'TIME_SECONDS' ? 0.4 : 0 }}>{twoTimeDuration(groups[index - 1].time, item.time)}</Text>
+
+                            </View>
+                        </View>
+                    </Box>
+                </View> */}
 
+            {
+                histories.map((item, index) => {
+                    return <View style={{ position: 'relative' }}>
+                        <Box key={index} >
+                            <View>
+                                <Text className="working_index">{item.type == 'WORK' ? `第${getIndex(index)}组` : '组间休息'}</Text>
+                                <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', marginTop: item.type == 'WORK' ? rpxToPx(60) : 0, marginBottom: item.type == 'WORK' ? rpxToPx(0) : 0 }}>
+                                    {item.type == 'WORK' && getValue(item)}
+                                    <View style={{ flex: 1 }} />
+                                    <Text className="working_group_duration" style={{ opacity: item.type == 'WORK' && (record as any).items[0].format == 'TIME_SECONDS' ? 0 : 0.4 }}>{twoTimeDuration(item.start.timestamp, item.end.timestamp)}</Text>
+                                </View>
+                            </View>
+                        </Box>
+                    </View>
+                })
+            }
+            <View style={{ width: 0, height: 0 }} ref={myRef} id='footId' />
+            <Text className={delPosition == 'absolute' ? "result_del" : 'resule_del_relative'} style={{ opacity: showDel ? 1 : 0 }} onClick={del}>删除训练记录</Text>
         </View>
-        {/* <View>
-            <Text>用时</Text>
-            <Text style={{ color: router.params.themeColor }}>111</Text>
-        </View> */}
-        <Text className="result_group_text" style={{marginBottom:rpxToPx(48),marginTop:0}}>训练详情</Text>
-        {/* {
-            histories.length > 0 && <Text className="result_count">共{getCount()}组</Text>
-        } */}
-
-
-        {
-            histories.map((item, index) => {
-                return <View key={index} className={item.type == 'WORK' ? 'result_item' : 'result_item result_item_rest'}>
-                    <Text>{item.type == 'WORK' ? `第${getIndex(index)}组` : '组间休息'}</Text>
-                    {item.type == 'WORK' && <Text className="workout_result_value" style={{ color: router.params.themeColor }}>{getValue(item)}</Text>}
-                    <Text className="result_time">{twoTimeDuration(item.start.timestamp, item.end.timestamp)}</Text>
-                </View>
-            })
-        }
-        <Text className="result_del" onClick={del}>删除训练记录</Text>
-    </View>
+    }
+
+    return <Layout children={detail()}
+        title={router.params.title}
+        type={TemplateType.customHeader}
+        titleShowStyle={NaviBarTitleShowType.scrollToShow}
+    />
 }

+ 15 - 6
src/features/workout/SetGoal.tsx

@@ -11,33 +11,39 @@ export default function Component(props: { start: Function, duration: number, th
     const [goalTime, setGoalTime] = useState(props.duration / 1000)
     const [showPicker, setShowPicker] = useState(false)
     const [sportPickerValue, setSportPickerValue] = useState([14])
+
+    const step = 5
     function minus() {
-        var t = goalTime - 60
+        var t = goalTime - 60 * step
+        if (t<5*60){
+            t = 5*60
+        }
         setSportPickerValue([t / 60 - 1])
         setGoalTime(t)
     }
 
     function plus() {
-        var t = goalTime + 60
+        var t = goalTime + 60 * step
         setSportPickerValue([t / 60 - 1])
         setGoalTime(t)
     }
 
     function disableMinus() {
-        if (goalTime <= 60) {
+        if (goalTime <= 5*60) {
             return true
         }
         return false
     }
 
     function disablePlus() {
-        if (goalTime >= 60 * 60) {
+        if (goalTime >= 24 * 60 * 60) {
             return true
         }
         return false
     }
 
     function showDurationPicker() {
+        return
         setShowPicker(true)
 
     }
@@ -74,14 +80,17 @@ export default function Component(props: { start: Function, duration: number, th
     }
 
     function durationFormate() {
-        return `${parseInt(goalTime / 60 + '')}分钟`
+        var count = goalTime/60
+        var hours = Math.floor(count/60)
+        var minutes = count%60
+        return `${hours>0?hours+'小时':''}${minutes>0?minutes+'分钟':''}`
     }
 
     function start() {
         props.start(goalTime)
     }
 
-    return <View style={{ color: props.themeColor,display:'flex',flexDirection:'column' }}>
+    return <View style={{ color: props.themeColor, display: 'flex', flexDirection: 'column' }}>
         <Text className="set_goal_title">设置训练时长</Text>
         <Stepper minus={minus} plus={plus}
             themeColor={props.themeColor}

+ 52 - 18
src/features/workout/Workout.tsx

@@ -25,6 +25,7 @@ import { setAuth } from "../trackSomething/hooks/werun";
 import MetricModalOrder from "../trackSomething/components/MetricModalOrder";
 import MetricModalChoose from "../trackSomething/components/MetricModalChoose";
 import { rpxToPx } from "@/utils/tools";
+import MultiText from "@/components/view/MultiText";
 // import { useNavigation } from "@react-navigation/native";
 
 let useNavigation;
@@ -242,9 +243,28 @@ export default function Component(props: any) {
                 }
                 else {
                     if (workout.status == 'ing') {
+                        var ingObj
+                        list.map((item2) => {
+                            if ((item2 as any).code == workout.code) {
+                                ingObj = item2
+
+                            }
+                        })
+
                         Taro.showModal({
+                            title: t('feature.workout.finish_title', { name: ingObj.name }),
                             content: t('feature.workout.finish_current'),
-                            showCancel: false
+                            showCancel: true,
+                            success: function (res) {
+                                if (res.confirm) {
+                                    setSelItem(ingObj)
+                                    dispatch(setCurrentWorkoutItem(ingObj))
+                                    var count = Taro.getStorageSync('lastWorkoutDuration') ?? 60 * 50
+                                    Taro.navigateTo({ url: '/pages/workout/Working?type=stop_watch&restore=true&count=' + count })
+                                } else if (res.cancel) {
+                                    console.log('用户点击取消')
+                                }
+                            }
                         })
                         return
                     }
@@ -494,6 +514,10 @@ export default function Component(props: any) {
         setShowModal(true)
     }
 
+    function valueViewContent(values, units) {
+        return <MultiText values={values} units={units} color='#fff' valueSize={rpxToPx(48)} unitSize={rpxToPx(32)} />
+    }
+
     function detail() {
         return <View className="activity_container" style={{ marginBottom: 50 }}>
             {
@@ -544,6 +568,9 @@ export default function Component(props: any) {
                     }
 
                     var strTitle = btnTitle;
+                    var isTime = false
+                    var timeValues: any = []
+                    var timeUnits: any = []
                     if (item.code != '_walk') {
                         isEnable = true
                         strTitle = '计时训练'
@@ -565,6 +592,7 @@ export default function Component(props: any) {
                                 unit = ''
                                 if (item.latest_record.items[0].summary_stats) {
                                     if (item.latest_record.items[0].format == 'TIME_SECONDS') {
+                                        isTime = true
                                         var time = item.latest_record.items[0].summary_stats[0].value
                                         const hours = Math.floor(time / 3600);
                                         const minutes = Math.floor((time % 3600) / 60);
@@ -572,12 +600,18 @@ export default function Component(props: any) {
                                         var str = ''
                                         if (hours > 0) {
                                             str = str + hours + '小时'
+                                            timeValues.push(hours)
+                                            timeUnits.push('小时')
                                         }
                                         if (minutes > 0) {
                                             str = str + minutes + '分钟'
+                                            timeValues.push(minutes)
+                                            timeUnits.push('分钟')
                                         }
-                                        if (seconds > 0) {
+                                        if (seconds > 0 && hours==0) {
                                             str = str + seconds + '秒'
+                                            timeValues.push(seconds)
+                                            timeUnits.push('秒')
                                         }
                                         value = str
                                     }
@@ -595,6 +629,7 @@ export default function Component(props: any) {
                     return <MetricItem title={item.name}
                         // value={allowRun ? stepInfo ? (stepInfo as any).step : '' : '未开启'}
                         value={value}
+                        valueView={isTime ? valueViewContent(timeValues, timeUnits) : null}
                         unit={unit}
                         desc={desc}
                         btnText={strTitle}
@@ -605,21 +640,20 @@ export default function Component(props: any) {
                         showDetail={showDetail}
                         longClick={() => {
 
-                            if (item.code != '_walk' && user.isLogin && workout.status != 'ing') {
-                                Taro.showActionSheet({
-                                    itemList: ['content only mode'],
-                                }).then(res => {
-                                    switch (res.tapIndex) {
-                                        case 0:
-                                            setSelItem(item)
-                                            dispatch(setCurrentWorkoutItem(item))
-                                            Taro.navigateTo({ url: '/pages/workout/Working?type=content' })
-                                            break
-                                    }
-                                })
-                            }
+                            // if (item.code != '_walk' && user.isLogin && workout.status != 'ing') {
+                            //     Taro.showActionSheet({
+                            //         itemList: ['content only mode'],
+                            //     }).then(res => {
+                            //         switch (res.tapIndex) {
+                            //             case 0:
+                            //                 setSelItem(item)
+                            //                 dispatch(setCurrentWorkoutItem(item))
+                            //                 Taro.navigateTo({ url: '/pages/workout/Working?type=content' })
+                            //                 break
+                            //         }
+                            //     })
+                            // }
 
-                            // console.log('long press')
                         }}
                         onClick={() => {
                             tapBtn(item)
@@ -628,7 +662,7 @@ export default function Component(props: any) {
                 })
             }
 
-            {
+            {/* {
                 user.isLogin && list.length > 0 && <MetricItem title='TABATA'
                     value={'wait'}
                     unit={''}
@@ -644,7 +678,7 @@ export default function Component(props: any) {
                         timeStart()
                     }}
                 />
-            }
+            } */}
 
             {/* <MetricItem title='Content only'
                 value={'wait'}

+ 12 - 10
src/features/workout/WorkoutHistory.scss

@@ -1,6 +1,6 @@
 @import '@/utils/common.scss';
 
-.workout_record_item{
+.workout_record_item {
     display: flex;
     margin-left: 46px;
     margin-right: 46px;
@@ -14,7 +14,8 @@
     padding-top: 40px;
     padding-bottom: 60px;
 }
-.workout_history_time{
+
+.workout_history_time {
     font-size: 28px;
     color: rgba($color: #ffffff, $alpha: 0.4);
     font-weight: 400;
@@ -23,14 +24,14 @@
     bottom: 20px;
 }
 
-.workout_history_content{
+.workout_history_content {
     display: flex;
-    flex-direction: row;
+    flex-direction: column;
     width: 100%;
 
 }
 
-.workout_history_item{
+.workout_history_item {
     display: flex;
     flex: 1;
     flex-direction: column;
@@ -38,7 +39,7 @@
     color: rgba($color: #ffffff, $alpha: 0.4);
 }
 
-.workout_item_value{
+.workout_item_value {
     font-size: 40px;
     line-height: 40px;
     color: #EEC01F;
@@ -46,22 +47,23 @@
     margin-top: 10px;
 }
 
-.workout_summary{
+.workout_summary {
     display: flex;
     flex-direction: column;
-    padding-left: 38px;
+    padding-left: 46px;
     flex: 1;
 }
 
-.workout_summary_title{
+.workout_summary_title {
     color: #fff;
     opacity: 0.8;
     font-weight: bold;
     font-size: 32px;
     line-height: 32px;
+    margin-bottom: 10px;
 }
 
-.workout_summary_value{
+.workout_summary_value {
     margin-top: 10px;
     font-size: 48px;
     line-height: 48px;

+ 62 - 52
src/features/workout/WorkoutHistory.tsx

@@ -6,8 +6,10 @@ import { deleteWorkoutRecord } from "@/services/workout";
 import { TimeFormatter } from "@/utils/time_format";
 import './WorkoutHistory.scss';
 import Taro, { useRouter } from "@tarojs/taro";
+import MultiText from "@/components/view/MultiText";
+import { rpxToPx } from "@/utils/tools";
 
-export default function Component(props: { records: any, count: number,summary_stats:any }) {
+export default function Component(props: { records: any, count: number, summary_stats: any }) {
     const user = useSelector((state: any) => state.user);
     const [list, setList] = useState(props.records)
     const [selRecord, setSelRecord] = useState(null)
@@ -81,8 +83,8 @@ export default function Component(props: { records: any, count: number,summary_s
             return str
         }
 
-        var obj  =  record.items[0].summary_stats[0]
-        return obj.value+obj.unit
+        var obj = record.items[0].summary_stats[0]
+        return obj.value + obj.unit
 
 
         // var list = record.items[0].groups
@@ -103,26 +105,31 @@ export default function Component(props: { records: any, count: number,summary_s
         // var start = list[0].start.timestamp
         // var end = list[list.length - 1].end.timestamp
         // var left = (end - start) / 1000
-        var  left = 0
-        list.map(item=>{
+        var left = 0
+        list.map(item => {
             var time = Math.floor((item.end.timestamp - item.start.timestamp) / 1000);
-            if (time<1){
+            if (time < 1) {
                 time = 1
             }
-            left+=time
+            left += time
         })
 
-        const hours = Math.floor(left / (60 * 60));
-        const minutes = Math.floor((left % (60 * 60)) / 60);
-        const seconds = Math.floor(left % 60);
+        return left
 
-        var str = hours >= 10 ? hours : '0' + hours
-        str += ':'
-        str += (minutes >= 10 ? minutes : '0' + minutes) + ''
-        str += ':'
-        str += (seconds >= 10 ? seconds : '0' + seconds) + ''
+        // var str = TimeFormatter.formateDurationBySeconds(left)
+        // return str
 
-        return str
+        // const hours = Math.floor(left / (60 * 60));
+        // const minutes = Math.floor((left % (60 * 60)) / 60);
+        // const seconds = Math.floor(left % 60);
+
+        // var str = hours >= 10 ? hours : '0' + hours
+        // str += ':'
+        // str += (minutes >= 10 ? minutes : '0' + minutes) + ''
+        // str += ':'
+        // str += (seconds >= 10 ? seconds : '0' + seconds) + ''
+
+        // return str
     }
 
     function goDetail(record) {
@@ -132,29 +139,10 @@ export default function Component(props: { records: any, count: number,summary_s
         })
     }
 
-    function summaryTotal(){
-        if (props.summary_stats[0].format=='TIME_SECONDS'){
-            var time = props.summary_stats[0].value
-            const hours = Math.floor(time / 3600);
-            const minutes = Math.floor((time % 3600) / 60);
-            const seconds = Math.floor(time % 60);
-            var str = ''
-            if (hours > 0) {
-                str = str + hours + '小时'
-            }
-            if (minutes > 0) {
-                str = str + minutes + '分钟'
-            }
-            if (seconds > 0) {
-                str = str + seconds + '秒'
-            }
-            return str
-        }
-        else {
-            return props.summary_stats[0].value+props.summary_stats[0].unit
-        }
-    }
 
+    function durationArray(time) {
+        return TimeFormatter.workoutTimeAndUnitList(time)
+    }
 
     var lastYearStr = '2024年'
     return <View style={{ display: 'flex', flexDirection: 'column' }}>
@@ -162,14 +150,30 @@ export default function Component(props: { records: any, count: number,summary_s
             user.test_user && <Text style={{ color: '#fff', position: 'absolute', right: 50, top: 0 }} onClick={() => global.clearHistory()}>删除全部</Text>
         }
         {
-            props.count>0&&<View style={{ display: 'flex', flexDirection: 'row' }}>
+            props.count > 0 && <View style={{ display: 'flex', flexDirection: 'row' }}>
                 <View className="workout_summary">
-                    <Text className="workout_summary_title">累积训练总量</Text>
-                    <Text className="workout_summary_value" style={{ color: router.params.themeColor ?? 'white' }}>{summaryTotal()}</Text>
+                    <Text className="workout_summary_title">累计训练总量</Text>
+                    {
+                        props.summary_stats[0].format == 'TIME_SECONDS' ?
+                            <MultiText values={durationArray(props.summary_stats[0].value).values}
+                                units={durationArray(props.summary_stats[0].value).units}
+                                color={router.params.themeColor + ''}
+                                valueSize={rpxToPx(48)}
+                                unitSize={rpxToPx(32)} /> :
+                            <MultiText values={[props.summary_stats[0].value]}
+                                units={[props.summary_stats[0].unit]}
+                                color={router.params.themeColor + ''}
+                                valueSize={rpxToPx(48)}
+                                unitSize={rpxToPx(32)} />
+                    }
+
+
+                    {/* <Text className="workout_summary_value" style={{ color: router.params.themeColor ?? 'white' }}>{summaryTotal()}</Text> */}
                 </View>
                 <View className="workout_summary">
                     <Text className="workout_summary_title">累积次数</Text>
-                    <Text className="workout_summary_value" style={{ color: router.params.themeColor ?? 'white' }}>{props.summary_stats[0].count}次</Text>
+                    <MultiText values={[props.summary_stats[0].count]} units={['次']} color={router.params.themeColor + ''} valueSize={rpxToPx(48)} unitSize={rpxToPx(32)} />
+                    {/* <Text className="workout_summary_value" style={{ color: router.params.themeColor ?? 'white' }}>{props.summary_stats[0].count}次</Text> */}
                 </View>
             </View>
         }
@@ -188,16 +192,22 @@ export default function Component(props: { records: any, count: number,summary_s
                             return <RecordItem delete={() => deleteRecord(record)} onClick={() => goDetail(record)}>
 
                                 <View className="workout_record_item">
-                                    <Text style={{ color: 'white' }}>第{record.index}次</Text>
+                                    <Text style={{ color: 'white',marginBottom:rpxToPx(28) }}>第{record.index}次</Text>
                                     <View className="workout_history_content">
-                                        <View className="workout_history_item">
-                                            <Text>训练总量</Text>
-                                            <Text className="workout_item_value" style={{ color: router.params.themeColor ?? 'white' }}>{getWorkoutCount(record)}</Text>
-                                        </View>
-                                        <View className="workout_history_item">
-                                            <Text>训练用时</Text>
-                                            <Text className="workout_item_value" style={{ color: router.params.themeColor ?? 'white' }}>{getDuration(record)}</Text>
-                                        </View>
+                                        {/* <Text className="workout_item_value" style={{ color: router.params.themeColor ?? 'white' }}>{getWorkoutCount(record)}</Text> */}
+                                        {
+                                            record.items[0].format == 'TIME_SECONDS' ?
+                                                <MultiText values={durationArray(record.items[0].summary_stats[0].value).values}
+                                                    units={durationArray(record.items[0].summary_stats[0].value).units}
+                                                    color={router.params.themeColor + ''}
+                                                    valueSize={rpxToPx(48)}
+                                                    unitSize={rpxToPx(32)} /> :
+                                                <MultiText values={[record.items[0].summary_stats[0].value]}
+                                                    units={[record.items[0].summary_stats[0].unit]}
+                                                    color={router.params.themeColor + ''}
+                                                    valueSize={rpxToPx(48)}
+                                                    unitSize={rpxToPx(32)} />
+                                        }
                                     </View>
                                     <Text className="workout_history_time">{formateHourMinutes(record.timestamp)}</Text>
 
@@ -208,7 +218,7 @@ export default function Component(props: { records: any, count: number,summary_s
                 </View>
             })
         }
-        <View style={{height:30}}/>
+        <View style={{ height: 30 }} />
 
     </View>
 }

+ 55 - 14
src/features/workout/WorkoutStopWatch.scss

@@ -2,7 +2,9 @@
     font-size: 48px;
     line-height: 48px;
     font-weight: bold;
-    margin-left: 32px;
+    margin-left: 46px;
+    margin-top: 24px;
+    line-height: 72px;
 }
 
 .working_subtitle {
@@ -10,28 +12,31 @@
     font-size: 32px;
     line-height: 32px;
     margin-top: 20px;
-    margin-left: 32px;
+    margin-left: 46px;
     margin-bottom: 36px;
 }
 
-.working_index{
-    font-size: 34px;
-    line-height: 40px;
+.working_index {
+    position: absolute;
+    left: 86px;
+    top: 40px;
+    font-size: 32px;
+    line-height: 32px;
     color: #fff;
 }
 
-.working_duration{
-    margin-top: 36px;
+.working_duration {
+    margin-top: 48px;
     font-size: 72px;
     line-height: 72px;
     color: #fff;
     font-weight: bold;
     width: 100%;
     text-align: center;
-    margin-bottom: 58px;
+    margin-bottom: 48px;
 }
 
-.working_end{
+.working_end {
     color: #FA5151;
     width: 100%;
     text-align: center;
@@ -40,21 +45,57 @@
     margin-top: 40px;
 }
 
-.item_group{
+.item_group {
     background-color: #1C1C1C;
-    margin-left: 32px;
-    margin-right: 32px;
+    margin-left: 46px;
+    margin-right: 46px;
     padding-left: 32px;
     padding-right: 32px;
     padding-top: 40px;
     padding-bottom: 40px;
     border-radius: 26px;
     display: flex;
-    flex-direction: row;
+    flex-direction: column;
     position: relative;
     margin-bottom: 28px;
+    color: #fff;
+}
+
+.working_group_value {
+    font-size: 72px;
+    line-height: 72px;
+    font-weight: bold;
+    margin-top: 36px;
 }
 
-.item_rest{
+.working_group_name {
+    font-size: 40px;
+    line-height: 40px;
+}
+
+.working_group_duration {
+    color: #fff;
+    opacity: 0.4;
+    font-size: 32px;
+    line-height: 32px;
+}
+
+.item_rest {
     background-color: #121212;
+}
+
+.train_summary_title {
+    font-size: 32px;
+    line-height: 32px;
+    color: #fff;
+    opacity: 0.8;
+    font-weight: bold;
+    margin-top: 24px;
+    margin-bottom: 10px;
+}
+
+.train_summary_value {
+    font-size: 48px;
+    line-height: 48px;
+    font-weight: bold;
 }

+ 171 - 43
src/features/workout/WorkoutStopWatch.tsx

@@ -2,7 +2,7 @@ import { ColorType } from "@/context/themes/color";
 import { TimeFormatter } from "@/utils/time_format";
 import { View, Text } from "@tarojs/components";
 import { useEffect, useState } from "react";
-import { ChooseScenarioBtn } from "../common/SpecBtns";
+import { ChooseScenarioBtn, WorkoutEndBtn } from "../common/SpecBtns";
 import Taro, { useRouter } from "@tarojs/taro";
 import { WorkoutType } from "@/utils/types";
 import Modal from "@/components/layout/Modal";
@@ -12,6 +12,10 @@ import { endSuccess, startSuccess } from "@/store/workout";
 import { uploadWorkout } from "@/services/workout";
 import './WorkoutStopWatch.scss'
 import Box from "@/components/layout/Box";
+import { rpxToPx } from "@/utils/tools";
+import MultiText from "@/components/view/MultiText";
+import { values } from "lodash";
+import { IconRadioCross, IconX } from "@/components/basic/Icons";
 
 
 var timer
@@ -30,7 +34,7 @@ export default function Component(props: { targetCount: any, end: Function }) {
     const [showModal, setShowModal] = useState(false)
     const [needTerminal, setNeedTerminal] = useState(false)
     const [isPaused, setIsPaused] = useState(false);
-    const [isPosting,setIsPosting] = useState(false)
+    const [isPosting, setIsPosting] = useState(false)
     const dispatch = useDispatch();
 
 
@@ -110,7 +114,7 @@ export default function Component(props: { targetCount: any, end: Function }) {
 
     function resume() {
         debugger
-        if (timer){
+        if (timer) {
             clearInterval(timer)
             timer = null
         }
@@ -149,8 +153,14 @@ export default function Component(props: { targetCount: any, end: Function }) {
         return strDuration.length == 0 ? '1秒' : strDuration
     }
 
+    function  twoTimeFormateList(start,end){
+        var time = Math.floor((end - start) / 1000);
+        debugger
+        return TimeFormatter.workoutTimeAndUnitList(time)
+    }
+
     function finish() {
-        
+
         setTempTime(new Date().getTime())
         var schema = workout.item.schemas[0]
         if (workout.item.schemas[0].values.length > 0 && schema.format != 'TIME_SECONDS') {
@@ -245,7 +255,7 @@ export default function Component(props: { targetCount: any, end: Function }) {
             groups.map(item => {
                 if (item.type == 'WORK') {
                     var t = Math.floor((item.end - item.start) / 1000)
-                    t = t<1?1:t
+                    t = t < 1 ? 1 : t
                     console.log(t)
                     count += t
                 }
@@ -391,14 +401,14 @@ export default function Component(props: { targetCount: any, end: Function }) {
 
             setTimeout(() => {
                 Taro.redirectTo({
-                    url: '/pages/workout/WorkoutDetail?detail=' + JSON.stringify((res as any).latest_record)
+                    url: '/pages/workout/WorkoutDetail?detail=' + JSON.stringify((res as any).latest_record) + '&title=' + workout.item.name + '&themeColor=' + workout.item.theme_color
                 })
             }, 0)
 
 
             props.end()
             global.refreshWorkout()
-        }).catch(e => { 
+        }).catch(e => {
             setIsPosting(false)
         })
 
@@ -532,9 +542,20 @@ export default function Component(props: { targetCount: any, end: Function }) {
         return item.value + (item.value2 ? 'x' + item.value2 : '') + (item.value3 ? 'x' + item.value3 : '')
     }
 
+    function needShowPicker() {
+        var schema = workout.item.schemas[0]
+        if (schema.format == 'TIME_SECONDS') {
+            return false;
+        }
+        if (schema.values.length == 0) {
+            return false;
+        }
+        return true;
+    }
+
     function pickerContent() {
         var color = workout.item.theme_color
-        var title = '本组训练'
+        var title = `第${index}组`
 
 
         return <View style={{ color: '#fff', backgroundColor: 'transparent' }}>
@@ -554,66 +575,173 @@ export default function Component(props: { targetCount: any, end: Function }) {
         </View>
     }
 
+    function totalSummary() {
+
+        var multiValues: any = []
+        var multiUnits: any = []
+        var schema = workout.item.schemas[0]
+        if (schema.format == 'TIME_SECONDS') {
+            var count = 0
+            for (var i = 0; i < groups.length; i++) {
+                var obj = groups[i]
+                if (obj.type == 'REST') {
+                    count += Math.floor((obj.time - groups[i - 1].time) / 1000)
+                }
+            }
+            if (!count) {
+                multiValues.push(0)
+                multiValues.push(0)
+                multiValues.push(0)
+                multiUnits.push('小时')
+                multiUnits.push('分钟')
+                multiUnits.push('秒')
+            }
+            else {
+                var obj = TimeFormatter.workoutTimeAndUnitList(count) as any
+                multiValues = obj.values
+                multiUnits = obj.units
+            }
+        }
+        else {
+
+
+            var count = 0
+            for (var i = 0; i < groups.length; i++) {
+                var obj = groups[i]
+                if (obj.type == 'REST') {
+                    var temp = 0
+                    if (obj.value) {
+                        temp = parseInt(obj.value + '')
+                    }
+                    if (obj.value2) {
+                        temp *= parseInt(obj.value2 + '')
+                    }
+                    if (obj.value3) {
+                        temp *= parseInt(obj.value3 + '')
+                    }
+                    count += temp
+                }
+            }
+            var array = workout.item.schemas[0].values
+            var unit = array.map(obj => obj.unit).join('·')
+            multiUnits = [unit]
+            multiValues = [count]
+        }
+        return <MultiText values={multiValues} units={multiUnits} color={workout.item.theme_color} valueSize={rpxToPx(48)} unitSize={rpxToPx(32)} />
+    }
+
     return <View style={{ color: workout.item.theme_color, flexDirection: 'column', display: 'flex' }}>
-        <Text className="working_title">{workout.item.name}</Text>
+        <Text className="working_title" style={{fontSize:rpxToPx(56)}}>{workout.item.name}</Text>
         <Text className="working_subtitle">计时训练</Text>
         {
             groups.length > 1 && groups.map((item, index) => {
                 if (index == 0) {
                     return <View />
                 }
-                return <View key={index} className={item.type == 'REST' ? 'item_group' : 'item_group item_rest'} style={{ justifyContent: 'space-between', color: '#fff' }}>
-                    <Text>{item.type == 'REST' ? `第${item.index}组` : '组间休息'}</Text>
-                    {item.type == 'REST' && <Text style={{ color: workout.item.theme_color }}>{getGroupValue(item)}</Text>}
-                    <Text>{twoTimeDuration(groups[index - 1].time, item.time)}</Text>
+                return <View style={{ position: 'relative' }}>
+                    <Box key={index} >
+                        <View>
+                            <Text className="working_index">{item.type == 'REST' ? `第${item.index}组` : '组间休息'}</Text>
+                            <View style={{  display: 'flex', flexDirection: 'row', alignItems: 'center', marginTop: item.type == 'REST' ? rpxToPx(60) : 0, marginBottom: item.type == 'REST' ? rpxToPx(0) : 0 }}>
+                                {item.type == 'REST' && workout.item.schemas[0].format != 'TIME_SECONDS' &&
+                                    <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
+                                        {
+                                            <MultiText values={[parseInt(item.value)]} units={[workout.item.schemas[0].values[0].unit]} color={workout.item.theme_color} valueSize={rpxToPx(48)} unitSize={rpxToPx(32)} />
+                                        }
+                                        {
+                                            item.value2 && <IconX width={rpxToPx(32)} color={workout.item.theme_color} />
+                                        }
+                                        {
+                                            item.value2 && <View style={{width:1}} />
+                                        }
+                                        {
+                                            item.value2 && <MultiText values={[parseInt(item.value2)]} units={[workout.item.schemas[0].values[1].unit]} color={workout.item.theme_color} valueSize={rpxToPx(48)} unitSize={rpxToPx(32)} />
+                                        }
+                                        {
+                                            item.value3 && <MultiText values={[parseInt(item.value3)]} units={[workout.item.schemas[0].values[2].unit]} color={workout.item.theme_color} valueSize={rpxToPx(48)} unitSize={rpxToPx(32)} />
+                                        }
+                                    </View>
+                                    // <Text className="working_group_value" style={{ color: workout.item.theme_color }}>{getGroupValue(item)}</Text>
+                                }
+                                {
+                                    item.type == 'REST' && workout.item.schemas[0].format == 'TIME_SECONDS' &&
+                                    <MultiText values={twoTimeFormateList(groups[index - 1].time,item.time).values} units={twoTimeFormateList(groups[index - 1].time,item.time).units} color={workout.item.theme_color} valueSize={rpxToPx(48)} unitSize={rpxToPx(32)} />
+                                }
+                                <View style={{ flex: 1 }} />
+
+                                <Text className="working_group_duration" style={{ opacity: item.type != 'REST' || workout.item.schemas[0].format != 'TIME_SECONDS' ? 0.4 : 0 }}>{twoTimeDuration(groups[index - 1].time, item.time)}</Text>
+
+                            </View>
+                        </View>
+                    </Box>
                 </View>
             })
         }
-        <View className="item_group">
-            {
-                isDoing ? <View style={{ display: 'flex', flexDirection: 'column' }}>
-                    <Text className="working_index">第{index}组</Text>
-                    <Text className="working_duration">{isPosting?lastStrTime:durationTime()}</Text>
-                    <ChooseScenarioBtn onClick={finish} disable={isPosting} title="完成本组" background={workout.item.theme_color} />
-                </View> :
-                    <View style={{ display: 'flex', flexDirection: 'column' }}>
-                        <Text className="working_index">组间休息</Text>
-                        <Text className="working_duration" >{isPosting?lastStrTime:durationTime()}</Text>
-                        <ChooseScenarioBtn onClick={start} disable={isPosting} title="开始下一组" background={workout.item.theme_color} />
-                    </View>
-            }
+        <View style={{ position: 'relative' }}>
+            <Box>
+                {
+                    isDoing ? <View style={{ display: 'flex', flexDirection: 'column', width: '100%' }}>
+                        <Text className="working_index">第{index}组</Text>
+                        <Text className="working_duration">{isPosting ? lastStrTime : durationTime()}</Text>
+                        <View style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
+                            <WorkoutEndBtn onClick={finish} disable={isPosting} title={needShowPicker() ? "完成本组, 去记录" : "完成本组"} background={workout.item.theme_color} />
+                        </View>
+
+                    </View> :
+                        <View style={{ display: 'flex', flexDirection: 'column', width: '100%' }}>
+                            <Text className="working_index">组间休息</Text>
+                            <Text className="working_duration" >{isPosting ? lastStrTime : durationTime()}</Text>
+                            <View style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
+                                <ChooseScenarioBtn onClick={start} disable={isPosting} title="开始下一组" background={workout.item.theme_color} />
+                            </View>
+                        </View>
+                }
+            </Box>
         </View>
 
         <Text className="working_end" onClick={terminal}>结束训练</Text>
         <View style={{ height: 50 }} />
 
 
-        {
-            !router.params.content_only && <View style={{ display: 'flex', flexDirection: 'column' }}>
-                <Text>实时训练统计</Text>
-                <Text>总量</Text>
-                <Text>{total()}</Text>
-                <Text>总用时</Text>
+        <View style={{ display: 'flex', flexDirection: 'column', color: '#fff', marginLeft: rpxToPx(46) }}>
+            <Text style={{ fontSize: rpxToPx(40), fontWeight: 'bold', marginBottom: rpxToPx(6) }}>训练统计</Text>
+            <Text className="train_summary_title">总量</Text>
+            {
+                totalSummary()
+            }
+            {/* <Text className="train_summary_value" style={{ color: workout.item.theme_color }}></Text> */}
+            <Text className="train_summary_title">用时</Text>
+            <Text className="train_summary_value" style={{ color: workout.item.theme_color }}>{groups.length > 0 && TimeFormatter.formateTimeNow(groups[0].time)}</Text>
+            <Text className="train_summary_title">{groups.length > 0 && new Date().getTime() > groups[0].time + props.targetCount * 1000 ? '已超时' : '距结束'}</Text>
+            <Text className="train_summary_value" style={{ color: workout.item.theme_color }}>{groups.length > 0 && TimeFormatter.countdown(groups[0].time + props.targetCount * 1000)}</Text>
+        </View>
+
+
+        {/* {
+            !router.params.content_only && <View style={{ display: 'flex', flexDirection: 'column', color: '#fff', marginLeft: rpxToPx(46) }}>
+                <Text style={{ fontSize: rpxToPx(40), fontWeight: 'bold' }}>实时训练统计</Text>
+                <Text style={{ opacity: 0.8, fontSize: rpxToPx(32), fontWeight: 'bold' }}>总量</Text>
+                <Text style={{ fontSize: rpxToPx(48), fontWeight: 'bold', marginTop: rpxToPx(10) }}>{total()}</Text>
+                <Text style={{ marginTop: 20 }}>计时</Text>
+                <Text style={{ fontWeight: 'bold', fontSize: rpxToPx(40) }}>{planTime()}</Text>
             </View>
         }
 
 
         {
-            !router.params.content_only && <View style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', width: '100%' }}>
-                <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
-                    <Text>计划用时</Text>
-                    <Text>{planTime()}</Text>
-                </View>
+            !router.params.content_only && <View style={{ display: 'flex', flexDirection: 'row', color: '#fff', marginLeft: rpxToPx(46), marginBottom: 100, marginTop: rpxToPx(20) }}>
                 <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
-                    <Text>已进行</Text>
-                    <Text>{groups.length > 0 && TimeFormatter.formateTimeNow(groups[0].time)}</Text>
+
+                    <Text style={{ color: workout.item.theme_color, fontSize: rpxToPx(36), fontWeight: 'bold' }}>{groups.length > 0 && TimeFormatter.formateTimeNow(groups[0].time)}</Text>
+                    <Text style={{ fontSize: rpxToPx(20), color: '#fff', opacity: 0.4 }}>已进行</Text>
                 </View>
-                <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
-                    <Text>{groups.length > 0 && new Date().getTime() > groups[0].time + props.targetCount * 1000 ? '已超时' : '距结束'}</Text>
-                    <Text>{groups.length > 0 && TimeFormatter.countdown(groups[0].time + props.targetCount * 1000)}</Text>
+                <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginLeft: rpxToPx(80) }}>
+
+                    <Text style={{ color: workout.item.theme_color, fontSize: rpxToPx(36), fontWeight: 'bold' }}>{groups.length > 0 && TimeFormatter.countdown(groups[0].time + props.targetCount * 1000)}</Text>
+                    <Text style={{ fontSize: rpxToPx(20), color: '#fff', opacity: 0.4 }}>{groups.length > 0 && new Date().getTime() > groups[0].time + props.targetCount * 1000 ? '已超时' : '距结束'}</Text>
                 </View>
             </View>
-        }
+        } */}
 
         {
             showModal && <Modal dismiss={() => {

+ 2 - 1
src/pages/account/ChooseAuth.tsx

@@ -135,7 +135,8 @@ export default function Page() {
         <Text className="slogan">{t('page.choose_auth.slogan')}</Text>
         {
             process.env.TARO_ENV == 'weapp' ? <ChooseScenarioBtn disable={btnDisable} title={t('page.choose_auth.btn_wechat')} onClick={getCode} background={ColorType.fast} /> :
-                <ChooseScenarioBtn disable={btnDisable} title={t('page.choose_auth.btn_signup')} onClick={createAccount1} background={ColorType.fast} />
+                // <ChooseScenarioBtn disable={btnDisable} title={t('page.choose_auth.btn_signup')} onClick={createAccount1} background={ColorType.fast} />
+                <Text style={{color:'red'}} onClick={createAccount1}>{t('page.choose_auth.btn_signup')}</Text>
         }
         {/* <ChooseScenarioBtn title={t('page.choose_auth.btn_wechat')} onClick={login} background={ColorType.fast} /> */}
         {/* <View style={{ height: 100 }} /> */}

+ 1 - 1
src/pages/account/Setting.tsx

@@ -35,7 +35,7 @@ export default function Page() {
 
     return <View style={{ color: '#fff',display:'flex',flexDirection:'column' }}>
         <View style={{height:20}}/>
-        <TableCell title={t('page.setting.version')} ><Text style={{ opacity: 0.8 }}>1.3.0</Text></TableCell>
+        <TableCell title={t('page.setting.version')} ><Text style={{ opacity: 0.8 }}>1.2.10</Text></TableCell>
         {/* <Text style={{color:'#9E9E9E',textAlign:'center',fontSize:14}}>v1.2.2</Text> */}
         
         <Footer>

+ 0 - 0
src/pages/clock/Clock111.rn.tsx → src/pages/clock/Clock.rn.tsx


+ 0 - 0
src/pages/clock/Clock.tsx → src/pages/clock/Clock.weapp.tsx


+ 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'
+import Clock from '../clock/Clock.weapp'
 import Metric from '../metric/Metric'
 import Activity from '../activity/Activity'
 import Profile from '../account/Profile'

+ 9 - 0
src/pages/workout/Working.config.ts

@@ -0,0 +1,9 @@
+export default definePageConfig({
+    usingComponents:{
+      // 'ec-canvas': '../../lib/ec-canvas/ec-canvas',
+      // 'demo':'../../components/demo'
+    },
+    "enablePullDownRefresh":false,
+    "navigationBarTitleText":""
+  })
+  

+ 25 - 12
src/pages/workout/Working.tsx

@@ -1,22 +1,35 @@
+import Layout from "@/components/layout/layout";
 import WorkoutContent from "@/features/workout/WorkoutContent";
 import WorkoutStopWatch from "@/features/workout/WorkoutStopWatch";
 import WorkoutTimer from "@/features/workout/WorkoutTimer";
-import { WorkoutType } from "@/utils/types";
+import { NaviBarTitleShowType, TemplateType, WorkoutType } from "@/utils/types";
 import { View } from "@tarojs/components";
 import { useRouter } from "@tarojs/taro";
+import { useSelector } from "react-redux";
 
 export default function Page() {
+    const workout = useSelector((state: any) => state.workout);
     const router = useRouter();
-    return <View>
-        {
-            router.params.type == 'timer' && <WorkoutTimer />
-        }
-        {
-            router.params.type == 'stop_watch' && <WorkoutStopWatch targetCount={router.params.count??0} end={(e) => { }} />
-        }
-        {
-            router.params.type == 'content' && <WorkoutContent />
-        }
 
-    </View>
+    function detail() {
+        return <View>
+            {
+                router.params.type == 'timer' && <WorkoutTimer />
+            }
+            {
+                router.params.type == 'stop_watch' && <WorkoutStopWatch targetCount={router.params.count ?? 0} end={(e) => { }} />
+            }
+            {
+                router.params.type == 'content' && <WorkoutContent />
+            }
+
+        </View>
+    }
+
+    return <Layout children={detail()}
+        title={workout.item.name}
+        type={TemplateType.customHeader}
+        titleShowStyle={NaviBarTitleShowType.scrollToShow}
+    />
+
 }

+ 42 - 0
src/utils/time_format.ts

@@ -333,6 +333,48 @@ export class TimeFormatter {
     return `${TimeFormatter.padZero(hour)}:${TimeFormatter.padZero(minute)}`;
   }
 
+  static formateDurationBySeconds = (left: number) => {
+    const hours = Math.floor(left / 3600);
+    const minutes = Math.floor((left % 3600) / 60);
+    const seconds = Math.floor(left % 60);
+    var str = ''
+    if (hours > 0) {
+      str = str + hours + '小时'
+    }
+    if (minutes > 0) {
+      str = str + minutes + '分钟'
+    }
+    if (seconds > 0) {
+      str = str + seconds + '秒'
+    }
+    return str
+  }
+
+  static workoutTimeAndUnitList = (count: number) => {
+    const hours = Math.floor(count / 3600);
+    const minutes = Math.floor((count % 3600) / 60);
+    const seconds = Math.floor(count % 60);
+    var values: any = []
+    var units: any = []
+    if (hours > 0) {
+      values.push(hours)
+      units.push('小时')
+    }
+    if (minutes > 0) {
+      values.push(minutes)
+      units.push('分钟')
+    }
+    if (seconds > 0) {
+      values.push(seconds)
+      units.push('秒')
+    }
+
+    return {
+      values: values,
+      units: units
+    }
+  }
+
   //获取今天的日期和星期几
   static getDateAndWeek = (timestamp: number, ignore = false) => {
     const now = new Date();

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff