You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js秒表页面刷新后自动增加6小时的技术求助

秒表刷新后自动额外增加6小时问题

我用Vue.js开发了一款秒表功能,点击按钮可启动计时,停止后将计时数据提交至Django模型。日常计时功能正常,但刷新页面后,秒表会自动额外增加6小时。

Vue.js 脚本

var NavbarApp = {
    data() {
        return {
            seconds: {{ active_entry_seconds }},
            trackingTime: false,
            showTrackingModal: false,
            timer: null,
            entryID: 0,
            startTime: '{{ start_time }}'
        }
    },
    delimiters: ['[[', ']]'],
    methods: {
        startTimer() {
            fetch('/apps/api/start_timer/', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRFToken': '{{ csrf_token }}'
                }
            })
            .then((response) => {
                return response.json()
            })
            .then((result) => {
                this.startTime = new Date()
                this.trackingTime = true

                this.timer = setInterval(() => {
                    this.seconds = (new Date() - this.startTime) / 1000
                }, 1000)
            })
        },
        stopTimer() {
            fetch('/apps/api/stop_timer/', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRFToken': '{{ csrf_token }}'
                }
            })
            .then((response) => {
                return response.json()
            })
            .then((result) => {
                this.entryID = result.entryID
                this.showTrackingModal = true
                this.trackingTime = false

                window.clearTimeout(this.timer)
            })
        },
        discardTimer() {
            fetch('/apps/api/discard_timer/', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRFToken': '{{ csrf_token }}'
                }
            })
            .then((response) => {
                this.seconds = 0
                this.showTrackingModal = false
            })
        },
        addLater() {
            this.seconds = 0
            this.showTrackingModal = false
        },
        addToTask() {
            console.log('addToTask')
            window.location.href = '/apps/track_entry/' + this.entryID + '/'
        }
    },
    mounted() {
        if (this.seconds !== 0) {
            this.trackingTime = true
            this.timer = setInterval(() => {
                this.seconds = (new Date() - new Date(this.startTime)) / 1000
            }, 1000)
        }
    },
    computed: {
        readableSeconds() {
            const d = Number(this.seconds);
            const h = Math.floor(d / 3600);
            const m = Math.floor(d % 3600 / 60);
            const s = Math.floor(d % 3600 % 60);

            const hDisplay = h > 0 ? h + (h == 1 ? "h, " : "h, ") : "";
            const mDisplay = m > 0 ? m + (m == 1 ? "m, " : "m, ") : "";
            const sDisplay = s >= 0 ? s + (s == 1 ? "s" : "s") : "";

            return hDisplay + mDisplay + sDisplay; 
        }
    }
}

Vue.createApp(NavbarApp).mount('#navbar-app')

HTML 代码

<div class="col-md-auto mt-md-0 mt-4" id="navbar-app">
    <div class="hstack gap-1 flex-wrap">
        <div class="navbar-item" v-if="!trackingTime">
            <div class="buttons">
                <button class="btn btn-success add-btn" @click="startTimer()">
                   Start Timer
                </button>
            </div>
        </div>

        <div class="navbar-item" v-else>
            <div class="buttons">
                <div class="buttons">
                    <button class="btn btn-warning add-btn" @click="stopTimer()">
                        [[ readableSeconds ]] (stop)
                    </button>
                </div>
            </div>
        </div>

现象说明

  • 正常计时状态:点击启动后,秒表显示正确,例如显示 0h, 0m, 5s
  • 刷新页面后:秒表自动增加6小时,例如原本5秒变成 6h, 0m, 5s

问题分析与解决方案

核心原因

问题出在startTime的时区处理上:

  1. Django后端传递的{{ start_time }}是服务器时区的时间字符串,前端用new Date(this.startTime)解析时,默认按照本地时区处理,导致时间差计算出现6小时的偏差(正好对应服务器与本地的时区差)。
  2. mounted钩子中直接用本地时间与解析后的服务器时间计算差值,时区不统一导致秒数计算错误。

解决步骤

步骤1:后端传递UTC标准时间

修改Django后端,将start_time以UTC时间戳(毫秒)或带Z标识的ISO 8601格式字符串返回:

  • 时间戳示例:start_time = int(entry.start_time.timestamp() * 1000)
  • ISO格式示例:start_time = entry.start_time.isoformat() + 'Z'(Z代表UTC时区)

步骤2:前端统一用UTC时间计算差值

修改Vue代码,确保所有时间计算基于绝对UTC时间,避免时区解析误差:

data() {
    return {
        // ...其他数据
        startTime: {{ start_time_timestamp }} // 后端传递的UTC时间戳(数字类型)
        // 若用ISO格式则改为:startTime: '{{ start_time_iso_utc }}'
    }
},
mounted() {
    if (this.seconds !== 0) {
        this.trackingTime = true
        const startTimeDate = typeof this.startTime === 'number' 
            ? new Date(this.startTime) 
            : new Date(this.startTime);
        this.timer = setInterval(() => {
            // 用Date.now()获取当前UTC时间戳,减去起始时间戳计算秒数
            this.seconds = (Date.now() - startTimeDate.getTime()) / 1000
        }, 1000)
    }
},
startTimer() {
    // ...fetch请求部分
    .then((result) => {
        this.startTime = Date.now() // 直接存储本地UTC时间戳
        this.trackingTime = true

        this.timer = setInterval(() => {
            this.seconds = (Date.now() - this.startTime) / 1000
        }, 1000)
    })
}

步骤3:验证逻辑一致性

确保启动计时、页面刷新恢复计时的逻辑,都使用UTC时间戳计算差值,彻底避免时区带来的时间偏差。

内容的提问来源于stack exchange,提问作者Langutang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 01:55:21