Leon 2 tahun lalu
induk
melakukan
b3a3c7e515

TEMPAT SAMPAH
src/assets/images/arrow4.png


+ 61 - 13
src/components/input/Slider.scss

@@ -1,3 +1,5 @@
+@import '@/utils/common.scss';
+
 .slider-container {
     position: relative;
     width: 578px;
@@ -11,22 +13,22 @@
 
 .slider-item-bg {
     position: absolute;
-    min-width: 120px;
-    height: 120px;
-    border-radius: 60px;
-    left: 0;
-    top: 0;
+    min-width: 112px;
+    height: 112px;
+    border-radius: 56px;
+    left: 4px;
+    top: 6px;
     background-color: #ffffff66;
     overflow: hidden;
 }
 
 .slider-item {
     position: absolute;
-    left: 0;
-    top: 0;
-    min-width: 120px;
-    height: 120px;
-    border-radius: 60px;
+    left: 4px;
+    top: 6px;
+    min-width: 112px;
+    height: 112px;
+    border-radius: 56px;
     // width: 100%;
     // height: 100%;
 }
@@ -56,6 +58,17 @@
 }
 
 .slider-text-bg {
+    display: flex;
+    position: absolute;
+    left: 45px;
+    top: 0;
+    // width: 120px;
+    height: 120px;
+    align-items: center;
+    justify-content: center;
+}
+
+.slider-arrow-bg {
     display: flex;
     position: absolute;
     left: 0;
@@ -72,6 +85,11 @@
     font-weight: bold;
 }
 
+.slider-arrow {
+    width: 48px;
+    height: 48px;
+}
+
 .tooltip_bg {
     width: 578px;
     height: 200px;
@@ -84,7 +102,7 @@
     flex-direction: column;
 }
 
-.tooltip_content{
+.tooltip_content {
     width: 578px;
     padding-left: 40px;
     padding-right: 40px;
@@ -97,14 +115,14 @@
     flex-direction: column;
 }
 
-.tooltip_title{
+.tooltip_title {
     font-size: 28px;
     line-height: 40px;
     color: #fff;
     font-weight: bold;
 }
 
-.tooltip_desc{
+.tooltip_desc {
     font-size: 24px;
     line-height: 40px;
     color: #fff;
@@ -119,4 +137,34 @@
     border-right: 25px solid transparent;
     border-top: 20px solid #787878;
 
+}
+
+.slider-tip-bg {
+    position: absolute;
+    right: 0;
+    height: 120px;
+    top: 0;
+    min-width: 180px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    background-color: red;
+}
+
+.slider-tip-title {
+    font-size: 32px;
+    line-height: 32px;
+    font-weight: bold;
+    color: $foodColor;
+}
+
+.slider-tip-desc {
+    margin-top: 12px;
+    font-size: 20px;
+    line-height: 24px;
+    background: linear-gradient(90deg, #fff 0%, $foodColor 100%);
+    -webkit-background-clip: text;
+    background-clip: text;
+    color: transparent;
 }

+ 66 - 14
src/components/input/Slider.tsx

@@ -1,19 +1,21 @@
-import { View, Text } from '@tarojs/components'
+import { View, Text, Image } from '@tarojs/components'
 import './Slider.scss'
 import { ColorType } from '@/context/themes/color'
 import { useEffect, useRef, useState } from 'react';
 import { rpxToPx } from '@/utils/tools';
 import Taro from '@tarojs/taro';
 import { useSelector } from 'react-redux';
+import { useTranslation } from 'react-i18next';
 
 var currentValue = 0;
-export default function (props: { onChanged?: Function, value?: number, edit?: boolean }) {
+export default function (props: { onChanged?: Function, value?: number, edit?: boolean, isPreMeal?: boolean, id?: string }) {
     const sliderWidth = 578;
-    const [brightness, setBrightness] = useState(props.value ? props.value*10 : 0);
+    const [brightness, setBrightness] = useState(props.value ? props.value * 10 : 0);
     const [isSliding, setIsSliding] = useState(false);
     const [value, setValue] = useState(props.value ? props.value : 0)
     const [startX, setStartX] = useState(0);
     const common = useSelector((state: any) => state.common);
+    const { t } = useTranslation()
 
     useEffect(() => {
         // if (props.value) {
@@ -49,7 +51,31 @@ export default function (props: { onChanged?: Function, value?: number, edit?: b
     const handleTouchEnd = () => {
         setIsSliding(false);
         if (props.onChanged) {
-            props.onChanged(value);
+
+            var obj = common.food_scales.filter((item: any) => {
+                return item.point == value
+            })
+
+            Taro.showModal({
+                title: props.isPreMeal ? t('feature.food.pre_meal_confirm_title') : t('feature.food.post_meal_confirm_title'),
+                content: value + '分 - ' + obj[0].description ?? '暂无描述',
+                success: function (res) {
+                    if (res.confirm) {
+                        props.onChanged && props.onChanged(value);
+                    }
+                    else {
+                        if (props.isPreMeal) {
+                            setStartX(0);
+                            setBrightness(0)
+                            setValue(0)
+                        }
+                        else {
+                            setBrightness(props.value! * 10)
+                            setValue(props.value!)
+                        }
+                    }
+                }
+            })
         }
         if (props.edit) {
             if (startX != 0 && value != 0) {
@@ -57,12 +83,25 @@ export default function (props: { onChanged?: Function, value?: number, edit?: b
                 Taro.vibrateShort({
                     type: 'heavy'
                 })
-                Taro.showToast({
-                    icon: 'none',
-                    title: '请先上传!'
+                // Taro.showToast({
+                //     icon: 'none',
+                //     title: '请先上传!'
+                // })
+                Taro.showModal({
+                    title: '提示',
+                    content: t('feature.food.pre_meal_enforce_order_alert'),
+                    showCancel: false,
+                    confirmText: '好的',
+                    success: function (res) {
+                        if (res.confirm) {
+                            setStartX(0);
+                            setBrightness(0)
+                            setValue(0)
+                        }
+                    }
                 })
-                const animationId = requestAnimationFrame(moveToStart);
-                return () => cancelAnimationFrame(animationId);
+                // const animationId = requestAnimationFrame(moveToStart);
+                // return () => cancelAnimationFrame(animationId);
             }
         }
     };
@@ -135,20 +174,33 @@ export default function (props: { onChanged?: Function, value?: number, edit?: b
             onTouchStart={handleTouchStart}
             onTouchMove={handleTouchMove}
             onTouchEnd={handleTouchEnd}>
-            <View className='slider-item-bg' style={{ width: brightness * 0.01 * rpxToPx(sliderWidth - 120) + rpxToPx(120) }}>
+            <View className='slider-tip-bg' style={{ width: (100 - brightness) * 0.01 * rpxToPx(sliderWidth - 120) + rpxToPx(28) }}>
+                <Text className='slider-tip-title'>{props.isPreMeal || !props.onChanged ?
+                    t('feature.food.slider_tip_pre_meal_title') :
+                    t('feature.food.slider_tip_post_meal_title')}</Text>
+                <Text className='slider-tip-desc'>{props.isPreMeal || !props.onChanged ?
+                    t('feature.food.slider_tip_pre_meal_desc') :
+                    t('feature.food.slider_tip_post_meal_desc')}</Text>
+            </View>
+            <View className='slider-item-bg' style={{ width: brightness * 0.01 * rpxToPx(sliderWidth - 120) + rpxToPx(112) }}>
 
 
             </View>
             <View className='slider-item' style={{
-                width: brightness * 0.01 * rpxToPx(sliderWidth - 120) + rpxToPx(120),
+                width: brightness * 0.01 * rpxToPx(sliderWidth - 120) + rpxToPx(112),
                 backgroundColor: brightness <= 50 ? ColorType.fast : ColorType.food,
                 opacity: calculateOpacity(brightness),
             }}>
 
             </View>
-            <View className='slider-text-bg'>
-                <Text className='slider-text'>{value}</Text>
-            </View>
+            {
+                isSliding || value != 0 ? <View className='slider-text-bg'>
+                    <Text className='slider-text'>{value}</Text>
+                </View> :
+                    <View className='slider-arrow-bg'>
+                        <Image src={require('@assets/images/arrow4.png')} className='slider-arrow' />
+                    </View>
+            }
 
         </View>
         {

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

@@ -296,7 +296,15 @@ export default {
             prompt_detail:'日记列表顺序发生变化,点击刷新',
             sence_desc:'拍摄食物,记录餐前饥饿感\n记录餐后饱足感',
             sence_desc_off:'感知身体饥饱信号, 提升健康饮食直觉',
-            learn_more:'了解更多'
+            learn_more:'了解更多',
+            mindful_switch_on:'感知模式已开启',
+            pre_meal_enforce_order_alert:'请先拍摄食物,或从相册选择食物照片',
+            pre_meal_confirm_title:'餐前饥饿感',
+            post_meal_confirm_title:'餐后饱足感',
+            slider_tip_pre_meal_title:'饥饿感',
+            slider_tip_post_meal_title:'饱足感',
+            slider_tip_pre_meal_desc:'极度饥饿到不饿',
+            slider_tip_post_meal_desc:'不饱到十分饱',
         },
         track_something: {
             btn_record: '记录',

+ 1 - 1
src/features/food/FoodConsole.scss

@@ -13,7 +13,7 @@
     margin-right: 46px;
     padding-top: 32px;
     padding-bottom: 44px;
-    margin-bottom: 24px;
+    margin-bottom: 60px;
 }
 
 .food_console_title {

+ 55 - 24
src/features/food/FoodConsole.tsx

@@ -11,6 +11,7 @@ import { jumpPage } from '../trackTimeDuration/hooks/Common'
 import { IconShare } from '@/components/basic/Icons'
 import { useTranslation } from 'react-i18next'
 import { ColorType } from '@/context/themes/color'
+import { clearFoodCache, getFoodCache, saveFoodCache } from './hooks/ExtraData'
 let useNavigation;
 if (process.env.TARO_ENV == 'rn') {
     useNavigation = require("@react-navigation/native").useNavigation
@@ -67,6 +68,14 @@ export default function Component(props: { addItem: Function, firstItem: any })
             jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
             return;
         }
+
+        var params = {
+            event:'add_a_picture',
+            value:isAlbum?'choose_from_album':'use_camera',
+        }
+
+        saveFoodCache('create',params)
+
         clearFile()
         Taro.chooseMedia({
             count: 1,
@@ -74,6 +83,13 @@ export default function Component(props: { addItem: Function, firstItem: any })
             mediaType: ['image'],
             sourceType: [isAlbum ? 'album' : 'camera'],
             success: function (res) {
+                var params = {
+                    event:'add_a_picture',
+                    value:isAlbum?'choose_from_album_confirm':'use_camera_confirm',
+                }
+        
+                saveFoodCache('create',params)
+
                 var tempFilePath = res.tempFiles[0].tempFilePath
                 // Taro.editImage({
                 //     src:tempFilePath,
@@ -92,6 +108,14 @@ export default function Component(props: { addItem: Function, firstItem: any })
                         uploadFile(savedFilePath, isAlbum ? 'album' : 'camera')
                     }
                 })
+            },
+            fail:function(res){
+                var params = {
+                    event:'add_a_picture',
+                    value:isAlbum?'choose_from_album_cancel':'use_camera_cancel',
+                }
+        
+                saveFoodCache('create',params)
             }
         })
     }
@@ -113,28 +137,6 @@ export default function Component(props: { addItem: Function, firstItem: any })
         })
     }
 
-    function getCache(key: string) {
-        var value = Taro.getStorageSync(key)
-        if (value) {
-            return JSON.parse(value)
-        }
-        return null;
-    }
-
-    function saveCache(key: string) {
-        var strList = Taro.getStorageSync('food_operate')
-        var list: any = []
-        if (strList) {
-            list = JSON.parse(strList)
-        }
-        list.add({
-            key,
-            timestamp: new Date().getTime()
-        })
-        Taro.setStorageSync('food_operate', JSON.stringify(list)
-        )
-    }
-
     function uploadFile(path, source) {
         Taro.showLoading({
             title: '加载中'
@@ -197,7 +199,8 @@ export default function Component(props: { addItem: Function, firstItem: any })
                 timestamp: time,
                 date: strDate
             },
-            mindful_mode: modeOn ? 'AWARE' : 'NORMAL'
+            mindful_mode: modeOn ? 'AWARE' : 'NORMAL',
+            // extra:getFoodCache('create')
 
         }).then(res => {
             props.addItem(res)
@@ -206,6 +209,7 @@ export default function Component(props: { addItem: Function, firstItem: any })
             Taro.removeStorageSync('pic')
             Taro.hideLoading()
             setFirstData(res)
+            clearFoodCache('create')
             // if (modeOn) {
             //     setSwitchDisable(true)
             // }
@@ -217,6 +221,19 @@ export default function Component(props: { addItem: Function, firstItem: any })
     function modeChange(e) {
         setModeOn(e.detail.value)
         Taro.setStorageSync('food_switch', e.detail.value)
+        if (e.detail.value){
+            Taro.showToast({
+                icon:'success',
+                title:t('feature.food.mindful_switch_on')
+            })
+        }
+
+        var params = {
+            event:'switch_toggle',
+            value:e.detail.value?'on':'off',
+        }
+
+        saveFoodCache('create',params)
     }
 
     function more() {
@@ -227,6 +244,20 @@ export default function Component(props: { addItem: Function, firstItem: any })
         jumpPage('/pages/common/H5?title=' + '' + '&url=' + resource[0].url)
     }
 
+    function getLineBottom(){
+        if (user.isLogin){
+            return -rpxToPx(60)
+        }
+        else {
+            if (modeOn){
+                return -rpxToPx(60)
+            }
+            else {
+                return 0
+            }
+        }
+    }
+
     return <View style={{ marginBottom: rpxToPx(60) }}>
         <View className='food_console_box'>
             <View style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
@@ -260,7 +291,7 @@ export default function Component(props: { addItem: Function, firstItem: any })
                     }
                     {modeOn && <Slider edit={true} />}
                 </View>
-                <View className='center_line2' style={{bottom:-rpxToPx(60)}}/>
+                <View className='center_line2' style={{bottom:getLineBottom()}}/>
             </View>
         }
 

+ 12 - 11
src/features/food/FoodTimelineItem.scss

@@ -125,25 +125,26 @@
 }
 
 .food_item_point{
-    width: 20px;
-    height: 20px;
-    border-radius: 10px;
-    margin-left: -11px;
-    margin-right: 6px;
+    width: 16px;
+    height: 16px;
+    border-radius: 8px;
+    margin-left: -9px;
+    margin-right: 12px;
 }
 
 .food_item_score{
-    font-size: 32px;
-    line-height: 32px;
+    font-size: 28px;
+    line-height: 40px;
     font-weight: bold;
 }
 
 .food_timeline_more{
     position: absolute;
-    right: 0;
-    top: 0;
-    width: 72px;
-    height: 72px;
+    right: 22px;
+    width: 48px;
+    height: 48px;
+    top: 36px;
+
 }
 
 .center_line3{

+ 11 - 6
src/features/food/FoodTimelineItem.tsx

@@ -216,6 +216,8 @@ export default function Component(props: {
     }
 
     function updateFeel(value, isPreMeal) {
+
+
         var feel = isPreMeal ? { pre_meal: value } : { post_meal: value }
         var params = {
             feel: feel
@@ -386,17 +388,17 @@ export default function Component(props: {
         {
             detail.mindful_mode == 'AWARE' && detail.status != 'ABANDONED' && detail.feel.pre_meal && !detail.feel.post_meal &&
             <View style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: rpxToPx(60), position: 'relative' }}>
-                <Slider onChanged={(value) => { updateFeel(value, false) }} value={detail.feel.pre_meal} />
+                <Slider onChanged={(value) => { updateFeel(value, false) }} value={detail.feel.pre_meal} isPreMeal={false} />
                 <Image src={require('@assets/images/more-vertical.png')} className="food_timeline_more" onClick={more} />
             </View>
         }
         {
             detail.mindful_mode == 'AWARE' && detail.feel.post_meal &&
-            <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', marginBottom: rpxToPx(60) }}>
+            <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
                 <View style={{ width: rpxToPx(375) }} />
                 <View className="food_item_point" style={{ backgroundColor: ColorType.food }} />
                 <Text className="food_item_score" style={{ color: ColorType.food }}>{detail.feel.post_meal}
-                    <Text style={{ fontSize: rpxToPx(24) }}>分饱</Text></Text>
+                    <Text style={{ fontSize: rpxToPx(20) }}>分饱</Text></Text>
             </View>
         }
         <View className="food_timeline_item" onLongPress={showActionSheet}>
@@ -440,16 +442,19 @@ export default function Component(props: {
         {
             detail.mindful_mode == 'AWARE' && !detail.feel.pre_meal &&
             <View style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: rpxToPx(60) }}>
-                <Slider onChanged={(value) => { updateFeel(value, true) }} />
+                <Slider onChanged={(value) => { updateFeel(value, true) }} isPreMeal={true} />
             </View>
         }
         {
             detail.mindful_mode == 'AWARE' && detail.feel.pre_meal &&
-            <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', marginBottom: rpxToPx(60) }}>
+            <View style={{
+                display: 'flex', flexDirection: 'row', alignItems: 'center',
+                marginBottom: rpxToPx(60), marginTop: -rpxToPx(60)
+            }}>
                 <View style={{ width: rpxToPx(375) }} />
                 <View className="food_item_point" style={{ backgroundColor: ColorType.fast }} />
                 <Text className="food_item_score" style={{ color: ColorType.fast }}>{detail.feel.pre_meal}
-                    <Text style={{ fontSize: rpxToPx(24) }}>分饿</Text></Text>
+                    <Text style={{ fontSize: rpxToPx(20) }}>分饿</Text></Text>
             </View>
         }
         {

+ 72 - 0
src/features/food/hooks/ExtraData.tsx

@@ -0,0 +1,72 @@
+import Taro from "@tarojs/taro"
+
+export const saveFoodCache = (id: string, value: any) => {
+    var date = new Date()
+    value.timestamp = date.getTime()
+    value.date = formatDate(date)
+
+    var oldCache = getFoodCache(id)
+    if (oldCache == null) {
+        oldCache = []
+    }
+    oldCache.push(value)
+    var list = getFoodCacheList()
+    var isFound = false
+    for (var i = 0; i < list.length; i++) {
+        if (list[i].id == id) {
+            isFound = true
+            list[i].datas = oldCache
+        }
+    }
+
+    if (!isFound) {
+        list.push({
+            id: id,
+            datas: oldCache
+        })
+    }
+    Taro.setStorageSync('food_extra_data', JSON.stringify(list));
+}
+
+export const formatDate = (date) => {
+    const year = date.getFullYear();
+    const month = String(date.getMonth() + 1).padStart(2, '0');
+    const day = String(date.getDate()).padStart(2, '0');
+    const hours = String(date.getHours()).padStart(2, '0');
+    const minutes = String(date.getMinutes()).padStart(2, '0');
+    const seconds = String(date.getSeconds()).padStart(2, '0');
+
+    return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+}
+
+export const getFoodCacheList = () => {
+    var list = Taro.getStorageSync('food_extra_data')
+    if (!list) {
+        return []
+    }
+    return JSON.parse(list)
+}
+
+export const getFoodCache = (id: string) => {
+    var list = Taro.getStorageSync('food_extra_data')
+    if (!list) {
+        return null
+    }
+    list = JSON.parse(list)
+    for (var i = 0; i < list.length; i++) {
+        if (list[i].id == id) {
+            return list[i].datas
+        }
+    }
+    return null
+}
+
+export const clearFoodCache = (id: string) => {
+    var list = getFoodCacheList()
+    for (var i = 0; i < list.length; i++) {
+        if (list[i].id == id) {
+            list.splice(i, 1)
+        }
+    }
+    Taro.setStorageSync('food_extra_data', JSON.stringify(list));
+}

+ 1 - 0
src/utils/common.scss

@@ -3,6 +3,7 @@ $backgroundColor: #1C1C1C;
 $fastColor: #00ffff;
 $sleepColor: #8961F5;
 $alertColor: #ea6c6c;
+$foodColor: #FF7A4E;
 $alertFastColor: #00ffff66;
 $alertSleepColor: #8961F566;