Leon пре 1 година
родитељ
комит
6aa2857278

+ 19 - 4
src/_health/components/add_label.tsx

@@ -10,6 +10,8 @@ import Taro from "@tarojs/taro";
 import { useSelector } from "react-redux";
 import { getThemeColor } from "@/features/health/hooks/health_hooks";
 import NewTimePicker from "../base/new_timepicker";
+import showAlert from "@/components/basic/Alert";
+import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
 
 export default function AddLabel(props: { labels: any, defaultValue?: string, disMiss?: any }) {
     const [showTimePicker, setShowTimePicker] = useState(false)
@@ -87,12 +89,25 @@ export default function AddLabel(props: { labels: any, defaultValue?: string, di
                 time_label: isFullday ? strTime : null
             }]
         }).then(res => {
-            if (global.refreshWindow) {
-                global.refreshWindow()
+            if ((res as any).result){
+                if (global.refreshWindow) {
+                    global.refreshWindow()
+                }
+                if (global.refreshSchedules) {
+                    global.refreshSchedules()
+                }
             }
-            if (global.refreshSchedules) {
-                global.refreshSchedules()
+            else {
+                showAlert({
+                    title: '弹窗标题',
+                    content: '冲突描述',
+                    showCancel: false,
+                    confirm: () => {
+                        jumpPage(`./schedules_conflict?schedules=${JSON.stringify((res as any).schedules)}&errors=${JSON.stringify((res as any).error_mesages)}`)
+                    }
+                })
             }
+            
 
 
             setShowTimePicker(false)

+ 18 - 0
src/_health/components/onboard.scss

@@ -0,0 +1,18 @@
+.onboard_title{
+    width: 590px;
+    color: #000;
+    font-size: 34px;
+    text-align: center;
+    margin-top: 72px;
+}
+
+.onboard_desc{
+    width: 590px;
+    font-size: 26px;
+    line-height: 39px;
+    color: #B2B2B2;
+    text-align: center;
+    margin-bottom: 40px;
+    margin-top: 10px;
+    
+}

+ 32 - 0
src/_health/components/onboard.tsx

@@ -0,0 +1,32 @@
+import { getThemeColor } from "@/features/health/hooks/health_hooks";
+import { rpxToPx } from "@/utils/tools";
+import { View, Text } from "@tarojs/components";
+import { useSelector } from "react-redux";
+import './onboard.scss'
+
+export default function OnBoard(props: { title: string, desc: string, btnTitle: string, onClick: any }) {
+    const health = useSelector((state: any) => state.health);
+    return <View style={{
+        display: 'flex',
+        flexDirection: 'column',
+        alignItems: 'center',
+        justifyContent: 'center',
+        position: 'relative'
+    }}>
+        <Text className="onboard_title">{props.title}</Text>
+        <Text className="onboard_desc">{props.desc}</Text>
+        <View onClick={props.onClick} style={{
+            display: 'flex',
+            flexDirection: 'column',
+            alignItems: 'center',
+            justifyContent: 'center',
+            color: '#fff',
+            backgroundColor: getThemeColor(health.mode),
+            width: rpxToPx(374),
+            height: rpxToPx(72),
+            borderRadius: 9,
+            marginBottom:rpxToPx(72)
+        }}>{props.btnTitle}</View>
+        <View className="border_footer_line" />
+    </View>
+}

+ 0 - 0
src/_health/pages/schedules_conflict.config.ts


+ 113 - 0
src/_health/pages/schedules_conflict.scss

@@ -0,0 +1,113 @@
+.title {
+    color: #000;
+    margin-top: 24px;
+    margin-left: 52px;
+    font-size: 50px;
+    line-height: 60px;
+    font-weight: bold;
+}
+
+.sub_title {
+    margin-top: 16px;
+    color: #999999;
+    margin-left: 52px;
+    font-size: 30px;
+    line-height: 48px;
+    font-weight: bold;
+    margin-bottom: 24px;
+}
+
+.conflict_item {
+    height: 128px;
+    background-color: #fff;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    padding-left: 40px;
+    padding-right: 40px;
+    box-sizing: border-box;
+    position: relative;
+}
+
+.conflict_index {
+    width: 48px;
+    height: 42px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: #B2B2B2;
+    font-size: 26px;
+    margin-right: 12px;
+}
+
+.conflict_title {
+    color: #000;
+    font-size: 32px;
+    flex: 1;
+}
+
+.conflict_tip {
+    color: #FF0000;
+    font-size: 20px;
+    margin-right: 12px;
+}
+
+.conflict_time {
+    width: 160px;
+    height: 84px;
+    color: #FF0000;
+    background-color: #FF00001A;
+    align-items: center;
+    justify-content: center;
+    display: flex;
+    font-size: 34px;
+    border-radius: 20px;
+}
+
+.normal_time {
+    width: 160px;
+    height: 84px;
+    color: #000;
+    background-color: #B2B2B21A;
+    align-items: center;
+    justify-content: center;
+    display: flex;
+    font-size: 34px;
+    border-radius: 20px;
+}
+
+.edit_footer_btn2 {
+    margin-top: 76px;
+    width: 670px;
+    height: 96px;
+    border-radius: 24px;
+    margin-bottom: 76px;
+    margin-left: 40px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.error_tip {
+    height: 72px;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    background-color: #FF00001A;
+    padding-left: 42px;
+    box-sizing: border-box;
+    color: #000;
+    font-size: 24px;
+}
+
+.success_tip {
+    height: 72px;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    background-color: #00B2181A;
+    padding-left: 42px;
+    box-sizing: border-box;
+    color: #000;
+    font-size: 24px;
+}

+ 157 - 0
src/_health/pages/schedules_conflict.tsx

@@ -0,0 +1,157 @@
+import { View, Text } from "@tarojs/components";
+import './schedules_conflict.scss'
+import { useState } from "react";
+import Taro, { useRouter } from "@tarojs/taro";
+import { rpxToPx } from "@/utils/tools";
+import Modal from "@/components/layout/Modal.weapp";
+import { getThemeColor } from "@/features/health/hooks/health_hooks";
+import TimePicker from "@/features/common/TimePicker";
+import { createSchedule } from "@/services/health";
+import { useSelector } from "react-redux";
+import showAlert from "@/components/basic/Alert";
+
+let useRoute;
+let useNavigation;
+let scenario = '';
+if (process.env.TARO_ENV == 'rn') {
+    useRoute = require("@react-navigation/native").useRoute
+    useNavigation = require("@react-navigation/native").useNavigation
+}
+
+export default function SchedulesConflict() {
+    let router
+    let navigation;
+    if (useNavigation) {
+        navigation = useNavigation()
+    }
+
+    if (process.env.TARO_ENV == 'rn') {
+        router = useRoute()
+    }
+    else {
+        router = useRouter()
+    }
+
+    const health = useSelector((state: any) => state.health);
+    const [schedules, setSchedules] = useState(JSON.parse(router.params.schedules))
+    const [errors, setErrors] = useState(JSON.parse(router.params.errors))
+    const count = JSON.parse(router.params.schedules).filter(obj => obj.is_all_day == true).length
+    const [showTimePicker, setShowTimePicker] = useState(false)
+    const [selItem, setSelItem] = useState<any>(null)
+    const [selIndex, setSelIndex] = useState(-1)
+    const [showErrorTip, setShowErrorTip] = useState(true)
+    debugger
+
+    function modalContent() {
+        const strTime = selItem.time
+
+        var title = selItem.title
+        var color = getThemeColor(selItem.window)
+
+        return <TimePicker time={strTime}
+            color={color}
+            title={title}
+            confirm={(e) => {
+                selItem.time = e
+                setSelItem(selItem)
+                setShowTimePicker(false)
+                var array = JSON.parse(JSON.stringify(schedules))
+                array[selIndex].time = e
+                setSchedules(array)
+                checkData(array)
+                // confirmPickerTime(e)
+            }}
+            cancel={() => {
+                setShowTimePicker(false)
+            }} />
+    }
+
+    function checkData(array) {
+        createSchedule({
+            schedules: array,
+            // only_check: true
+        }).then(res => {
+            setSchedules((res as any).schedules)
+            setErrors((res as any).error_messages?(res as any).error_messages:[])
+            if ((res as any).result) {
+                setShowErrorTip(false)
+                global.refreshWindow()
+                global.refreshSchedules()
+            }
+            else {
+                setShowErrorTip(true)
+            }
+        })
+    }
+
+    function done() {
+        createSchedule({
+            schedules: schedules
+        }).then(res => {
+            if ((res as any).result) {
+                global.refreshWindow()
+                global.refreshSchedules()
+                Taro.navigateBack({
+                    delta: router.params.isAdd == 1 ? 1 : 2
+                })
+            }
+            else {
+                setSchedules((res as any).schedules)
+                showAlert({
+                    title: '弹窗标题',
+                    content: '冲突描述',
+                    showCancel: false,
+                })
+            }
+        })
+    }
+
+
+
+    return <View style={{ display: 'flex', flex: 1, flexDirection: 'column' }}>
+        <Text className="title">Scheduling Conflict</Text>
+        <Text className="sub_title">Adjust your schedule to resolve</Text>
+        {
+            errors.map((item, index) => {
+                return <View key={index} className='error_tip'>{item}</View>
+            })
+        }
+        {
+            errors.length == 0 && <View className='success_tip'>时间冲突已解决,并保存</View>
+        }
+
+        {
+            schedules.map((item, index) => {
+                if (item.is_all_day) return <View key={index} />
+                return <View className="conflict_item" key={index}>
+                    <Text className="conflict_index">{index + 1 - count}</Text>
+                    <Text className="conflict_title">{item.title}</Text>
+                    {
+                        item.is_conflict && <Text className="conflict_tip">时间冲突,请调整</Text>
+                    }
+                    <View className={item.is_conflict ? 'conflict_time' : 'normal_time'} onClick={() => {
+                        setSelIndex(index)
+                        setSelItem(item)
+                        setShowTimePicker(true)
+                    }}>{item.time}</View>
+                    {
+                        index < schedules.length - 1 && <View className="border_footer_line" style={{ marginLeft: rpxToPx(40) }} />
+                    }
+                </View>
+            })
+        }
+        {/* <View className="edit_footer_btn2" style={{ color: getThemeColor(health.mode), backgroundColor: getThemeColor(health.mode) + '33' }} onClick={done}>Resolved</View> */}
+        {
+            showTimePicker && <Modal
+                testInfo={null}
+                dismiss={() => {
+                    setShowTimePicker(false)
+                }}
+                confirm={() => { }}>
+                {
+                    modalContent()
+                }
+            </Modal>
+        }
+    </View>
+}

+ 46 - 5
src/_health/pages/schedules_edit.tsx

@@ -10,6 +10,7 @@ import TimePicker from "@/features/common/TimePicker";
 import { AtSwipeAction } from "taro-ui"
 import Taro from "@tarojs/taro";
 import showAlert from "@/components/basic/Alert";
+import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
 
 export default function SchedulesEdit() {
     const [list, setList] = useState<any>([])
@@ -25,6 +26,10 @@ export default function SchedulesEdit() {
         schedules()
     }, [])
 
+    global.refreshSchedules = () => {
+        schedules()
+    }
+
     function schedules() {
         let windows = ''
         switch (health.mode) {
@@ -88,8 +93,10 @@ export default function SchedulesEdit() {
             title={title}
             confirm={(e) => {
                 selItem.time = e
+
                 setSelItem(selItem)
                 setShowTimePicker(false)
+                orderList(list)
                 // confirmPickerTime(e)
             }}
             cancel={() => {
@@ -97,6 +104,26 @@ export default function SchedulesEdit() {
             }} />
     }
 
+    function orderList(list) {
+        var array = JSON.parse(JSON.stringify(list))
+        array.map(item => {
+            if (item.window == 'EAT' || item.window == 'ACTIVE') {
+                // 自定义排序函数
+                const sortedArray = item.list.sort((a, b) => {
+                    // 如果 a 没有 time 字段,排在前面
+                    if (!a.time && !b.time) return 0; // 都没有时,返回相等
+                    if (!a.time) return -1; // a 没有 time,排在前面
+                    if (!b.time) return 1;  // b 没有 time,排在前面
+
+                    // 比较时间
+                    return a.time.localeCompare(b.time);
+                });
+                item.list = sortedArray
+            }
+        })
+        setList(array)
+    }
+
     function tapDone() {
         var array: any = []
         list.map((obj) => {
@@ -116,11 +143,25 @@ export default function SchedulesEdit() {
             schedules: array,
             delete_ids: delIds
         }).then(res => {
-            global.refreshWindow()
-            global.refreshSchedules()
-            if (process.env.TARO_ENV == 'weapp') {
-                Taro.navigateBack()
+            if ((res as any).result) {
+                global.refreshWindow()
+                global.refreshSchedules()
+                if (process.env.TARO_ENV == 'weapp') {
+                    Taro.navigateBack()
+                }
             }
+            else {
+                showAlert({
+                    title: '弹窗标题',
+                    content: '冲突描述',
+                    showCancel: false,
+                    confirm: () => {
+                        jumpPage(`./schedules_conflict?schedules=${JSON.stringify((res as any).schedules)}&errors=${JSON.stringify((res as any).error_mesages)}`)
+                    }
+                })
+
+            }
+
         })
     }
 
@@ -230,7 +271,7 @@ export default function SchedulesEdit() {
                                             }
 
 
-                                            {(!obj.is_all_day || health.mode=='DAY' || health.mode=='NIGHT') && <Switch checked={obj.reminder}
+                                            {(!obj.is_all_day || health.mode == 'DAY' || health.mode == 'NIGHT') && <Switch checked={obj.reminder}
                                                 color={getThemeColor(obj.window)}
                                                 onChange={e => {
                                                     if (process.env.TARO_ENV == 'weapp') {

+ 5 - 5
src/_health/pages/schedules_list.tsx

@@ -184,7 +184,7 @@ export default function SchedulesList() {
                 jumpPage('/_health/pages/schedules_reminder')
                 break;
             case 2:
-                jumpPage('/_health/pages/schedules_mark')
+                // jumpPage('/_health/pages/schedules_mark')
                 break;
             case 3:
                 jumpPage('/_health/pages/schedules_del')
@@ -228,12 +228,12 @@ export default function SchedulesList() {
     }
 
     return <View className='schedule_list_bg'>
-        {
+        {/* {
             selMode == '' && <View className='schedule_set_tabbar'>
                 <View onClick={()=>setSelTab(0)} className={selTab==0?'schedule_tab_sel':'schedule_tab_nor'}>按场景</View>
                 <View onClick={()=>setSelTab(1)} className={selTab==1?'schedule_tab_sel':'schedule_tab_nor'}>按时间</View>
             </View>
-        }
+        } */}
         <ScrollView enableFlex style={{ height: Taro.getSystemInfoSync().screenHeight - 220 - (selMode == '' ? rpxToPx(100) : 0) }} scrollY>
             <View style={{ display: 'flex', flexDirection: 'column' }}>
                 <View className='schedule_header_title'>{getTitle()}</View>
@@ -245,8 +245,8 @@ export default function SchedulesList() {
                                 item.list.map((obj, i) => {
                                     if (obj.add) {
                                         return <View key={i * 100} className='item_add'
-                                            hoverClass='cell_hover'
-                                            hoverStayTime={50}
+                                            // hoverClass='cell_hover'
+                                            // hoverStayTime={50}
                                             onClick={()=>add(item)}>
                                             <IconAdd color={item.list.length==5?'gray':getThemeColor(item.window)} width={rpxToPx(34)} />
                                             <View className='toolbar_btn' style={{ color: item.list.length==5?'gray':getThemeColor(item.window) }} >添加</View>

+ 0 - 74
src/_health/pages/schedules_mark.tsx

@@ -1,74 +0,0 @@
-import { getScenario, getThemeColor } from "@/features/health/hooks/health_hooks";
-import { createSchedule, getSchedules } from "@/services/health";
-import { View,Text, Input } from "@tarojs/components";
-import Taro from "@tarojs/taro";
-import { useEffect, useState } from "react";
-import { useSelector } from "react-redux";
-import './edit.scss'
-
-export default function SchedulesMark() {
-    const health = useSelector((state: any) => state.health);
-    const [scenario, setScenario] = useState(getScenario(health.windows, health.mode))
-    const [showTimePicker, setShowTimePicker] = useState(false)
-    const [list, setList] = useState<any>([])
-    const [selItem, setSelItem] = useState<any>(null)
-
-    useEffect(() => {
-        schedules()
-    }, [])
-
-    function schedules() {
-        getSchedules({ window: health.mode, is_all_day: false }).then(res => {
-            if ((res as any).data && (res as any).data.length > 0) {
-                setList((res as any).data)
-            }
-        }).catch(e => {
-
-        })
-    }
-
-    function save() {
-        var array:any = []
-        list.map((item)=>{
-            array.push({
-                id:item.id,
-                time:item.time,
-                event:item.event,
-                title:item.title,
-                reminder_enabled:item.reminder_enabled
-            })
-        })
-
-        createSchedule({
-
-            schedules: array
-        }).then(res => {
-            global.refreshWindow()
-            global.refreshSchedules()
-            if (process.env.TARO_ENV == 'weapp') {
-                Taro.navigateBack()
-            }
-        })
-    }
-
-    if (list.length == 0) return <View />
-
-    return <View>
-        {
-            list.map((item, index) => {
-                return <View className="edit_item_cell" key={index} >
-                    <Text className="cell_index">{index + 1}</Text>
-                    <Input value={item.title} style={{flex:1}} onInput={(e)=>{
-                        item.title = e.detail.value;
-                        setList([...list])
-                    }}/>
-
-                    {
-                        index<=list.length-1 && <View className='edit_item_cell_line' />
-                    }
-                </View>
-            })
-        }
-        <View className="edit_footer_btn" style={{ color: getThemeColor(health.mode), backgroundColor: getThemeColor(health.mode) + '33' }} onClick={save}>完成</View>
-    </View>
-}

+ 1 - 1
src/app.config.ts

@@ -52,9 +52,9 @@ const appConfig = defineAppConfig({
         'pages/add_moment',
         'pages/schedules_list',
         'pages/schedules_del',
-        'pages/schedules_mark',
         'pages/schedules_order',
         'pages/schedules_reminder',
+        'pages/schedules_conflict',
         'pages/schedules_time',
         'pages/schedules_edit',
         'pages/setting_reminder',

+ 44 - 24
src/features/health/MainConsole.tsx

@@ -19,6 +19,8 @@ import DurationPicker from "@/_health/components/duration_picker";
 import Taro from "@tarojs/taro";
 import { systemLocation } from "@/services/common";
 import { TimeFormatter } from "@/utils/time_format";
+import { clearLocation } from "@/services/user";
+import OnBoard from "@/_health/components/onboard";
 
 let useNavigation;
 let min = 0
@@ -383,7 +385,7 @@ export default function MainConsole(props: { type: WindowType }) {
                 date: dayjs(t1).format('YYYYMMDD'),
                 timestamp: t1,
                 extra: {
-                    set_time: global.set_time?global.set_time:new Date().getTime(),
+                    set_time: global.set_time ? global.set_time : new Date().getTime(),
                     confirm_time: new Date().getTime()
                 }
             }]
@@ -544,9 +546,23 @@ export default function MainConsole(props: { type: WindowType }) {
         switch (health.mode) {
             case 'DAY':
                 list = day.timeline
+                if (active.onboard == false) {
+                    return <OnBoard title='你还没有开启位置授权'
+                        desc="获取准确的日出日落信息需要您开启微信运动授权,点击下方按钮进行授权"
+                        btnTitle="去开启"
+                        onClick={chooseLocation}
+                    />
+                }
                 break;
             case 'NIGHT':
                 list = night.timeline
+                if (active.onboard == false) {
+                    return <OnBoard title='你还没有开启位置授权'
+                        desc='获取准确的日出日落信息需要您开启微信运动授权,点击下方按钮进行授权'
+                        btnTitle="去开启"
+                        onClick={chooseLocation}
+                    />
+                }
                 break;
             case 'FAST':
                 list = fast.timeline
@@ -560,28 +576,13 @@ export default function MainConsole(props: { type: WindowType }) {
             case 'ACTIVE':
                 list = active.timeline
                 if (active.onboard == false) {
-                    return <View style={{
-                        display: 'flex',
-                        flexDirection: 'column',
-                        alignItems: 'center',
-                        justifyContent: 'center',
-                    }}>
-                        <Text>{list[0].title}</Text>
-                        <Text>Subtitle</Text>
-                        <View onClick={() => {
+                    return <OnBoard title={list[0].title}
+                        desc="Subtitle"
+                        btnTitle="Action"
+                        onClick={() => {
                             jumpPage('/_health/pages/active_plan?schedule=' + JSON.stringify(list.length > 0 ? list[0] : '{}'))
-                        }} style={{
-                            display: 'flex',
-                            flexDirection: 'column',
-                            alignItems: 'center',
-                            justifyContent: 'center',
-                            color: getThemeColor(health.mode),
-                            backgroundColor: getThemeColor(health.mode) + '1A',
-                            width: rpxToPx(347),
-                            height: rpxToPx(72),
-                            borderRadius: 9
-                        }}>Action</View>
-                    </View>
+                        }}
+                    />
                 }
                 break;
         }
@@ -651,6 +652,22 @@ export default function MainConsole(props: { type: WindowType }) {
         return ''
     }
 
+    function tapClearLocation() {
+        Taro.showModal({
+            title: '提示',
+            content: '确认清除位置数据?',
+            success: function (res) {
+                if (res.confirm) {
+                    clearLocation().then(res => {
+                        global.refreshWindow()
+                    })
+                } else if (res.cancel) {
+                    console.log('用户点击取消')
+                }
+            }
+        })
+    }
+
     function chooseLocation() {
         Taro.chooseLocation({
             // latitude: authInfo && authInfo.lat ? authInfo.lat : undefined,
@@ -721,7 +738,7 @@ export default function MainConsole(props: { type: WindowType }) {
             }
             {
                 health.mode == 'ACTIVE' && <View onClick={() => {
-                    var list = getScenario(health.windows,health.mode).timeline
+                    var list = getScenario(health.windows, health.mode).timeline
                     jumpPage('/_health/pages/active_plan?schedule=' + JSON.stringify(list.length > 0 ? list[0] : '{}'))
                 }}>测试</View>
             }
@@ -731,8 +748,11 @@ export default function MainConsole(props: { type: WindowType }) {
             {/* {
                 (health.mode == 'EAT' || health.mode == 'ACTIVE') && <Text style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }} onClick={more}>更多</Text>
             } */}
-            {
+            {/* {
                 (health.mode == 'DAY' || health.mode == 'NIGHT') && <Text onClick={chooseLocation}>选择位置</Text>
+            } */}
+            {
+                (health.mode == 'DAY' || health.mode == 'NIGHT') && <Text onClick={tapClearLocation}>清除位置</Text>
             }
             <View className="main_footer_more" onClick={more}>
                 <IconMore color="#b2b2b2" width={17} />