Leon 1 year ago
parent
commit
90e40246ff

+ 47 - 4
src/pages/clock/ClockIndex.tsx

@@ -29,6 +29,7 @@ import LogPublish from "./components/log_publish";
 import RecordTimeResult from "./components/record_time_result";
 import { setFastWithSleep, setWindows } from "@/store/health";
 import { MainColorType } from "@/context/themes/color";
+import DayNight from "./components/day_night";
 
 var timer
 let useNavigation, LinearGradient;
@@ -80,6 +81,7 @@ export default function ClockIndex() {
 
     const [current, setCurrent] = useState(-1)
     const currentRef = useRef(current)
+    const [showDayNight, setShowDayNight] = useState(false)
 
     const [swiperHeight] = useState(screenHeight - navigationBarHeight - rpxToPx(108) - rpxToPx(112) - bottomSafeAreaHeight + 4)
 
@@ -95,9 +97,9 @@ export default function ClockIndex() {
         getHomeData()
     }, [user.isLogin])
 
-    useEffect(()=>{
+    useEffect(() => {
         currentRef.current = current
-    },[current])
+    }, [current])
 
     useEffect(() => {
         startPickerRef.current = showDatePicker
@@ -106,7 +108,7 @@ export default function ClockIndex() {
     }, [showDatePicker, showDurationPicker, showEndDatePicker])
 
     useEffect(() => {
-        
+
         downloadFile()
     }, [])
 
@@ -325,7 +327,7 @@ export default function ClockIndex() {
         return ''
     }
 
-    function pickerColor(){
+    function pickerColor() {
         var obj = scenarios[current]
         if (obj.theme_color) {
             return obj.theme_color
@@ -400,6 +402,39 @@ export default function ClockIndex() {
             end={{ x: 0, y: 1 }} pointerEvents="none" />
     }
 
+    function navibar() {
+        return <View style={{ position: 'absolute', left: 0, top: 0, right: 0, height: navigationBarHeight }}>
+            <View style={{
+                position: 'absolute',
+                left: 0,
+                right: 0,
+                bottom: 0,
+                height: 44,
+                display: 'flex',
+                alignItems: 'center',
+                justifyContent: 'center',
+                zIndex: 200
+            }}>
+                <View style={{
+                    position: 'absolute',
+                    width: rpxToPx(92),
+                    height: rpxToPx(64),
+                    left: 22,
+                    top: 22 - rpxToPx(32)
+                }}
+                    onClick={() => {
+                        if (!user.isLogin) {
+                            jumpPage('/_account/pages/ChooseAuth', 'ChooseAuth', navigation)
+                            return
+                        }
+                        setShowDayNight(true)
+                    }}>
+                    <IconClose color={"#000"} width={rpxToPx(64)} height={rpxToPx(64)} />
+                </View>
+            </View>
+        </View>
+    }
+
     // function swiperHeight() {
     //     return screenHeight - navigationBarHeight - rpxToPx(108) - rpxToPx(112) - bottomSafeAreaHeight + 4
     // }
@@ -410,6 +445,9 @@ export default function ClockIndex() {
         {
             bgView()
         }
+        {
+            navibar()
+        }
         <View style={{ height: navigationBarHeight }} />
         <IndexTab items={tabs} current={current} onChanged={(index) => {
             setCurrent(index)
@@ -610,6 +648,11 @@ export default function ClockIndex() {
                 />
             }
         </Block>
+        {
+            showDayNight && <DayNight onClose={() => {
+                setShowDayNight(false)
+            }} data={home.daylight} />
+        }
         {
             process.env.TARO_ENV == 'weapp' && <TabBar index={0} />
         }

+ 49 - 0
src/pages/clock/components/day_night.scss

@@ -0,0 +1,49 @@
+.day_night_bg {
+    position: fixed;
+    left: 0;
+    top: 0;
+    width: 100vw;
+    height: 100vh;
+    z-index: 1000000;
+    background-color: rgba($color: #000000, $alpha: 0.5);
+}
+
+.day_night_content {
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    display: flex;
+    flex-direction: column;
+    // align-items: center;
+    // z-index: 1000001;
+    border-bottom-right-radius: 28px;
+    border-bottom-left-radius: 28px;
+    padding-bottom: 52px;
+}
+
+.location_card {
+    width: 320px;
+    height: 260px;
+    border-radius: 42px;
+    display: flex;
+    flex-direction: column;
+    box-sizing: border-box;
+    padding-top: 36px;
+    padding-left: 40px;
+    background-color: rgba($color: #fff, $alpha: 0.25);
+}
+
+.polar_tag{
+    background-color: rgba(89, 89, 89, 0.1);
+    border-radius: 12px;
+    height: 44px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 0 10px;
+    color: #595959;
+    font-size: 26px;
+    font-weight: bold;
+    margin-right: 12px;
+}

+ 280 - 0
src/pages/clock/components/day_night.tsx

@@ -0,0 +1,280 @@
+import { View } from "@tarojs/components";
+import './day_night.scss'
+import { useSelector } from "react-redux";
+import Taro from "@tarojs/taro";
+import { rpxToPx } from "@/utils/tools";
+import { IconClose } from "@/components/basic/Icons";
+import SunsetCanvas from "./sunset-canvas";
+import { useEffect, useState } from "react";
+import NewButton, { NewButtonType } from "@/_health/base/new_button";
+import { MainColorType } from "@/context/themes/color";
+import { TimeFormatter } from "@/utils/time_format";
+import { systemLocation } from "@/services/common";
+import { useTranslation } from "react-i18next";
+import dayjs from "dayjs";
+import { clearLocation } from "@/services/user";
+
+export default function DayNight(props: { onClose: any, data: any }) {
+    const record = useSelector((state: any) => state.record);
+    const user = useSelector((state: any) => state.user);
+    const systemInfo: any = Taro.getWindowInfo ? Taro.getWindowInfo() : Taro.getSystemInfoSync();
+    const navigationBarHeight = systemInfo.statusBarHeight + 44;
+    const screenHeight = systemInfo.screenHeight
+    const safeAreaInsets = systemInfo.safeArea; // 获取安全区域信息
+
+    const [info, setInfo] = useState(props.data)
+    const [events, setEvents] = useState<any>(null)
+    const { t } = useTranslation()
+
+    useEffect(() => {
+        setInfo(props.data)
+        if (props.data.events) {
+            var array = props.data.events.filter((item) => {
+                return item.sub_type != 'SUN_SOLAR_MIDNIGHT' && item.sub_type != 'SUN_SOLAR_NOON'
+            })
+            setEvents(array)
+        }
+        else {
+            setEvents([])
+        }
+
+    }, [props.data])
+
+    function getBackground() {
+        var time = record.time
+        if (!time) return '#fff'
+        const { background_colors } = time
+        if (!background_colors) {
+            return '#fff'
+        }
+        else if (background_colors.length == 1) {
+            return background_colors[0]
+        }
+        return `linear-gradient(to bottom, ${background_colors[0]}, ${background_colors[1]})`
+    }
+
+    function chooseLocation() {
+        Taro.chooseLocation({
+            latitude: info.choose_location ? parseFloat(info.location.lat + '') : undefined,
+            longitude: info.choose_location ? parseFloat(info.location.lng + '') : undefined,
+            success: function (res) {
+                console.log('choose location,', res)
+                uploadLocation(res)
+            },
+            fail(res) {
+                Taro.showToast({
+                    title: '位置修改失败!\n请重新选择就近位置',
+                    icon: 'none'
+                })
+            },
+            complete(res) {
+
+            }
+        })
+    }
+
+    function uploadLocation(res) {
+        var today = new Date()
+        var yesterday = new Date(today.getTime() - 24 * 3600 * 1000)
+        var tomorrow = new Date(today.getTime() + 24 * 3600 * 1000 * 5)
+        var strYesterday = `${yesterday.getFullYear()}-${TimeFormatter.padZero(yesterday.getMonth() + 1)}-${TimeFormatter.padZero(yesterday.getDate())}`
+        var strTomorrow = `${tomorrow.getFullYear()}-${TimeFormatter.padZero(tomorrow.getMonth() + 1)}-${TimeFormatter.padZero(tomorrow.getDate())}`
+        Taro.showLoading({
+            title: global.language == 'en' ? 'Loading' : '加载中'
+        })
+        systemLocation({
+            lat: res.latitude,
+            lng: res.longitude,
+            name: res.name,
+            address: res.address,
+            date_start: strYesterday,
+            date_end: strTomorrow,
+            coordinate_system_standard: process.env.TARO_ENV == 'weapp' ? 'GCJ-02' : 'WGS-84'
+        }).then(data => {
+            // global.refreshWindow()
+            Taro.eventCenter.trigger('refreshClockIndex')
+            Taro.hideLoading()
+        }).catch((e) => {
+            Taro.hideLoading()
+        })
+    }
+
+    function tapClearLocation() {
+        Taro.showModal({
+            title: t('feature.location.clear_alert_title'),
+            content: t('feature.location.clear_alert_content'),
+            success: function (res) {
+                if (res.confirm) {
+                    clearLocation().then(res => {
+                        Taro.eventCenter.trigger('refreshClockIndex')
+                    })
+                } else if (res.cancel) {
+                    console.log('用户点击取消')
+                }
+            }
+        })
+    }
+
+    function currentStatus() {
+        var now = new Date().getTime()
+        for (var i = 0; i < events.length - 1; i++) {
+            if (events[i].time.start_timestamp <= now && events[i + 1].time.start_timestamp > now) {
+                if (events[i].sub_type == 'SUN_SET') {
+                    return '夜晚'
+                }
+                return '白天'
+            }
+        }
+        return ''
+    }
+
+    function durationView() {
+        var start: any;
+        var end: any;
+        var now = new Date().getTime()
+        for (var i = 0; i < events.length - 1; i++) {
+            if (events[i].time.start_timestamp <= now && events[i + 1].time.start_timestamp > now) {
+                if (events[i].sub_type == 'SUN_SET') {
+                    start = events[i]
+                }
+                end = events[i + 1]
+            }
+        }
+        var str1 = dayjs(start.time.start_timestamp).format('MM-DD HH:mm')
+        var str2 = dayjs(end.time.start_timestamp).format('MM-DD HH:mm')
+        if (TimeFormatter.isToday(start.time.start_timestamp)) {
+            str1 = dayjs(start.time.start_timestamp).format('HH:mm')
+        }
+        if (TimeFormatter.isToday(end.time.start_timestamp)) {
+            str2 = dayjs(end.time.start_timestamp).format('HH:mm')
+        }
+
+        if (TimeFormatter.isYesterday(start.time.start_timestamp)) {
+            str1 = (global.language == 'en' ? 'Yesterday ' : '昨天 ') + dayjs(start.time.start_timestamp).format('HH:mm')
+        }
+        if (TimeFormatter.isYesterday(end.time.start_timestamp)) {
+            str2 = (global.language == 'en' ? 'Yesterday ' : '昨天 ') + dayjs(end.time.start_timestamp).format('HH:mm')
+        }
+
+        if (TimeFormatter.isTomorrowday(start.time.start_timestamp)) {
+            str1 = (global.language == 'en' ? 'Tomorrow ' : '明天 ') + dayjs(start.time.start_timestamp).format('HH:mm')
+        }
+        if (TimeFormatter.isTomorrowday(end.time.start_timestamp)) {
+            str2 = (global.language == 'en' ? 'Tomorrow ' : '明天 ') + dayjs(end.time.start_timestamp).format('HH:mm')
+        }
+
+        if (TimeFormatter.isToday(start.time.start_timestamp)) {
+            str1 = dayjs(start.time.start_timestamp).format('HH:mm')
+        }
+        if (TimeFormatter.isToday(end.time.start_timestamp)) {
+            str2 = dayjs(end.time.start_timestamp).format('HH:mm')
+        }
+
+        return <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', marginTop: rpxToPx(12), marginBottom: rpxToPx(52) }}>
+            {
+                info.is_polar_night && <View className="polar_tag">极夜</View>
+            }
+            {
+                info.is_polar_day && <View className="polar_tag">极昼</View>
+            }
+            <View className="h36 g01">{str1} - {str2}</View>
+        </View>
+    }
+
+    function pointCard() {
+        var start: any;
+        var end: any;
+        var now = new Date().getTime()
+        for (var i = 0; i < events.length - 1; i++) {
+            if (events[i].time.start_timestamp <= now && events[i + 1].time.start_timestamp > now) {
+                if (events[i].sub_type == 'SUN_SET') {
+                    start = events[i]
+                }
+                end = events[i + 1]
+            }
+        }
+        return <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
+            <View className="location_card" style={{ marginRight: rpxToPx(30) }}>
+                <View className="h36 bold">{start.title}</View>
+                <View className="h36 g01" style={{ marginTop: rpxToPx(8) }}>{dayjs(start.time.start_timestamp).format('HH:mm')}</View>
+            </View>
+            <View className="location_card">
+                <View className="h36 bold">{end.title}</View>
+                <View className="h36 g01" style={{ marginTop: rpxToPx(8) }}>{dayjs(end.time.start_timestamp).format('HH:mm')}</View>
+            </View>
+        </View>
+    }
+
+    if (!events) return <View />
+
+
+    return <View className="day_night_bg">
+        <View className="day_night_content" style={{ background: getBackground() }}>
+            <View style={{ height: navigationBarHeight }}>
+                <View style={{
+                    position: 'absolute',
+                    left: 0,
+                    right: 0,
+                    bottom: 0,
+                    height: 44,
+                    display: 'flex',
+                    alignItems: 'center',
+                    justifyContent: 'center',
+                    zIndex: 200
+                }}>
+                    <View style={{
+                        position: 'absolute',
+                        width: rpxToPx(92),
+                        height: rpxToPx(64),
+                        left: 22,
+                        top: 22 - rpxToPx(32)
+                    }}
+                        onClick={() => {
+                            props.onClose()
+                        }}>
+                        <IconClose color={"#000"} width={rpxToPx(44)} height={rpxToPx(44)} />
+                    </View>
+                    <View className="h34 bold">{global.language == 'en' ? dayjs().format('ddd MMM D, YYYY') : dayjs().format('YYYY年MMMD日 ddd')}</View>
+                </View>
+            </View>
+            <View style={{ width: rpxToPx(750), display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
+                {
+                    !info.choose_location && <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
+                        <View className="h50 bold" style={{ marginTop: rpxToPx(52), marginBottom: rpxToPx(12) }}>{new Date().getHours() >= 6 && new Date().getHours() < 18 ? t('health.sunrise_to_sunset') : t('health.sunset_to_sunrise')}</View>
+                        <View className="h26" style={{ marginBottom: rpxToPx(52) }}>{new Date().getHours() >= 6 && new Date().getHours() < 18 ? t('health.rise_to_set_desc') : t('health.set_to_rise_desc')}</View>
+                        <NewButton
+                            type={NewButtonType.fill}
+                            width={rpxToPx(374)}
+                            height={rpxToPx(96)}
+                            color={MainColorType.orange}
+                            title="选择位置"
+                            onClick={() => {
+                                chooseLocation()
+                            }}
+                        />
+                    </View>
+                }
+                {
+                    info.choose_location && <View style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
+                        <View className="h50 bold" style={{ marginTop: rpxToPx(52) }}>{currentStatus()}</View>
+                        {
+                            durationView()
+                        }
+                        {
+                            pointCard()
+                        }
+                        <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'center', marginTop: rpxToPx(26), position: 'relative', width: rpxToPx(750) }}>
+                            <View className="h26">{info.location.name}</View>
+                            <View className="h26" style={{ color: MainColorType.link, marginLeft: rpxToPx(12) }} onClick={chooseLocation}>更改位置</View>
+                            {
+                                user.test_user && <View style={{ position: 'absolute', right: 50 }} onClick={tapClearLocation}>清除位置</View>
+                            }
+                        </View>
+                    </View>
+                }
+            </View>
+            {/* <SunsetCanvas sunset="16:20" sunrise="07:41" width={600} height={300} /> */}
+        </View>
+
+    </View>
+}

+ 146 - 0
src/pages/clock/components/sunset-canvas.tsx

@@ -0,0 +1,146 @@
+import { rpxToPx } from "@/utils/tools"
+import { Canvas } from "@tarojs/components"
+import Taro, { useLoad } from "@tarojs/taro"
+import { useEffect, useState } from "react"
+
+interface SunsetProps {
+    sunset: string
+    sunrise: string
+    width?: number
+    height?: number
+}
+
+export default function SunsetCanvas({ sunset = "16:20", sunrise = "07:41", width = 600, height = 300 }: SunsetProps) {
+    useEffect(() => {
+        // drawSunsetCanvas()
+        initCanvas()
+    }, [sunset, sunrise])
+
+    function initCanvas() {
+        const query = Taro.createSelectorQuery();
+        query.select(`#sunsetCanvas`).fields({ node: true, size: true });
+        query.exec((res) => {
+            const dpr = Taro.getSystemInfoSync().pixelRatio
+            const _canvas = res[0].node;
+            _canvas.width = res[0].width * dpr;
+            _canvas.height = res[0].height * dpr;
+            const ctx = _canvas.getContext('2d');
+            ctx.scale(dpr, dpr)
+
+            drawSunsetCanvas(ctx)
+        })
+    }
+
+    const drawSunsetCanvas = async (ctx) => {
+        // const ctx = Taro.createCanvasContext("sunsetCanvas")
+        // const dpr = Taro.getSystemInfoSync().pixelRatio
+
+        // // Scale canvas for retina displays
+        // ctx.scale(dpr, dpr)
+
+        // Clear canvas
+        ctx.clearRect(0, 0, width, height)
+
+        ctx.beginPath()
+        ctx.moveTo(0, 150)
+        ctx.quadraticCurveTo(150, 0, 300, 150); // 画曲线
+        ctx.lineTo(300, 300);
+        ctx.lineTo(0, 300);
+        ctx.closePath();
+        ctx.fillStyle = '#FFA500'; // 设置填充颜色
+        ctx.fill();
+
+        ctx.beginPath();
+        ctx.moveTo(0, 150);
+        ctx.quadraticCurveTo(150, 300, 300, 150); // 画曲线
+        ctx.lineTo(300, 300);
+        ctx.lineTo(0, 300);
+        ctx.closePath();
+        ctx.fillStyle = '#1E90FF'; // 设置填充颜色
+        ctx.fill();
+
+        // Draw title
+        // ctx.setFontSize(24)
+        // ctx.setTextAlign("center")
+        // ctx.setFillStyle("#666")
+        ctx.font = `bold ${rpxToPx(48)}px sans-serif`
+        ctx.fillText("SUNSET & SUNRISE", width / 2, 40)
+
+        // Draw times
+        // ctx.setFontSize(48)
+        ctx.fillText(sunset, width / 4, 150)
+        ctx.fillText(sunrise, (width / 4) * 3, 150)
+
+        // ctx.setFontSize(20)
+        ctx.font = `bold ${rpxToPx(40)}px sans-serif`
+        ctx.fillText("Sunset", width / 4, 100)
+        ctx.fillText("Sunrise", (width / 4) * 3, 100)
+
+        // Draw horizon line
+        ctx.beginPath()
+        ctx.moveTo(50, height - 50)
+        ctx.lineTo(width - 50, height - 50)
+        ctx.strokeStyle = "#ccc"
+        ctx.stroke()
+
+        // Draw sunset curve
+        ctx.beginPath()
+        ctx.moveTo(50, height / 2)
+        ctx.quadraticCurveTo(width / 4, height - 50, width / 2, height - 50)
+
+        // Fill sunset gradient
+        const sunsetGradient = ctx.createLinearGradient(50, 0, width / 2, 0)
+        sunsetGradient.addColorStop(0, "#f6b93b")
+        sunsetGradient.addColorStop(1, "#fad390")
+        ctx.fillStyle = sunsetGradient
+        ctx.fill()
+
+        // Draw night curve
+        ctx.beginPath()
+        ctx.moveTo(width / 2, height - 50)
+        ctx.quadraticCurveTo(width / 2 + 100, height + 50, (width / 4) * 3, height - 50)
+
+        // Fill night gradient
+        const nightGradient = ctx.createLinearGradient(width / 2, 0, (width / 4) * 3, 0)
+        nightGradient.addColorStop(0, "#4a69bd")
+        nightGradient.addColorStop(1, "#6a89cc")
+        ctx.fillStyle = nightGradient
+        ctx.fill()
+
+        // Draw dotted lines
+        ctx.setLineDash([5, 5])
+        ctx.beginPath()
+        ctx.moveTo(width / 2, 60)
+        ctx.lineTo(width / 2, height - 50)
+        ctx.moveTo((width / 4) * 3, 60)
+        ctx.lineTo((width / 4) * 3, height - 50)
+        ctx.strokeStyle = "#ccc"
+        ctx.stroke()
+
+        // Draw sun icon
+        ctx.beginPath()
+        ctx.arc((width / 4) * 3, height - 40, 10, 0, Math.PI * 2)
+        ctx.fillStyle = "#f6b93b"
+        ctx.fill()
+
+        // Draw "HORIZON" text
+        // ctx.setFontSize(16)
+        ctx.fillStyle = "#999"
+        ctx.fillText("HORIZON", width - 70, height - 30)
+
+        // Render canvas
+        // ctx.draw()
+    }
+
+    return (
+        <Canvas
+            type="2d"
+            id="sunsetCanvas"
+            style={{
+                width: `${width}px`,
+                height: `${height}px`,
+            }}
+        />
+    )
+}
+