Browse Source

fix: 计时器和倒计时

master
guoapeng 2 months ago
parent
commit
bdd00dfe23
  1. 1
      src/apis/system.ts
  2. 103
      src/components/common/Countdown.vue
  3. 2
      src/components/home/Tube/index.vue
  4. 43
      src/hooks/useServerTime.ts
  5. 14
      src/layouts/default.vue
  6. 3
      src/libs/utils.ts
  7. 2
      src/types/system.d.ts

1
src/apis/system.ts

@ -6,3 +6,4 @@ export const getStatus = (): Promise<System.SystemStatus> => http.get('/sys/devi
export const getPoint = (motor: string): Promise<string> => http.get(`/motor/position/${motor}`)
export const requireOutTray = (): Promise<{ moduleCode: string }[]> => http.get('/self-test/require-out-tray')
export const setIgnoreItem = (params: { ignoreSelfTestType: string, ignore: boolean }): Promise<null> => http.post('/self-test/set-ignore-item', params)
export const getTime = (): Promise<number> => http.get('/sys/datetime')

103
src/components/common/Countdown.vue

@ -0,0 +1,103 @@
<script setup lang="ts">
import { useSystemStore } from 'stores/systemStore'
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
const props = defineProps<{
current: number
startTime: number
duration: number //
}>()
const systemStore = useSystemStore()
const remaining = ref(0)
let timer: number | null = null
const calculateRemaining = () => {
//
const endTime = props.startTime + props.duration * 1000
// = - -
remaining.value = Math.max(0, endTime - new Date(systemStore.currentTime).getTime())
console.log('remaining', remaining.value)
}
const updateCountdown = () => {
if (remaining.value <= 0) {
stopTimer()
return
}
remaining.value -= 1000
}
const startTimer = () => {
updateCountdown() //
timer = window.setInterval(() => {
calculateRemaining()
updateCountdown()
}, 1000)
}
const stopTimer = () => {
if (timer) {
clearInterval(timer)
timer = null
}
}
onMounted(() => {
startTimer()
})
onBeforeUnmount(() => {
stopTimer()
})
//
const days = ref(0)
const hours = ref('00')
const minutes = ref('00')
const seconds = ref('00')
const visible = ref(true)
//
watch(
() => remaining.value,
(newVal) => {
if (newVal <= 0 || !newVal) {
visible.value = false
days.value = 0
hours.value = '00'
minutes.value = '00'
seconds.value = '00'
return
}
days.value = Math.floor(newVal / (1000 * 60 * 60 * 24))
const hoursNum = Math.floor((newVal % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
hours.value = hoursNum.toString().padStart(2, '0')
const minutesNum = Math.floor((newVal % (1000 * 60 * 60)) / (1000 * 60))
minutes.value = minutesNum.toString().padStart(2, '0')
const secondsNum = Math.floor((newVal % (1000 * 60)) / 1000)
seconds.value = secondsNum.toString().padStart(2, '0')
},
)
</script>
<template>
<div v-if="visible" class="countdown">
<span v-if="days">{{ days }}</span>
{{ hours }}:{{ minutes }}:{{ seconds }}
</div>
</template>
<style scoped>
.countdown {
text-align: center;
font-size: 12px;
color: #FF4500;
}
</style>

2
src/components/home/Tube/index.vue

@ -5,6 +5,7 @@ import errorIcon from 'assets/images/error.svg'
import ingIcon from 'assets/images/ing.svg'
import successIcon from 'assets/images/success.svg'
import waitIcon from 'assets/images/wait.svg'
import CountDown from 'components/common/Countdown.vue'
import { useHomeStore } from 'stores/homeStore'
import { useSystemStore } from 'stores/systemStore'
import { computed, ref } from 'vue'
@ -167,6 +168,7 @@ defineExpose({
<span v-show="data.heatingType === 'drying'" style="color: #F2652D;font-weight: bold ">烘干中</span>
<span v-show="data.heatingType === 'annealing'" style="color: #1677FF;font-weight: bold ">退火中</span>
</div>
<CountDown v-if="data.startHeatTime && data.targetTime" :current="new Date().getTime()" :start-time="data.startHeatTime" :duration="data.targetTime" />
<div class="footer">
<div class="tem-box" @click="setTemperature">
<span :class="{ 'active-footer': hearInfo?.selected }"> {{ data.targetTemperature || '--' }}</span>

43
src/hooks/useServerTime.ts

@ -0,0 +1,43 @@
import { getTime } from 'apis/system'
import { formatDateTime } from 'libs/utils'
import { onMounted, onUnmounted, ref } from 'vue'
export function useServerTime() {
const serverTime = ref<number | null>(null) // 初始服务器时间戳
const clientFetchTime = ref<number | null>(null) // 获取服务器时间时的客户端时间戳
const currentTime = ref<string>('0000-00-00 00:00:00')
let interval: number | null = null
onMounted(async () => {
try {
serverTime.value = await getTime()
clientFetchTime.value = Date.now()
let num = 0
interval = window.setInterval(async () => {
if (num > 60) {
serverTime.value = await getTime()
clientFetchTime.value = Date.now()
num = 0
}
if (serverTime.value && clientFetchTime.value) {
const elapsed = Date.now() - clientFetchTime.value
const currentServerTime = serverTime.value + elapsed
currentTime.value = formatDateTime(undefined, new Date(currentServerTime))
num++
}
}, 1000)
}
// eslint-disable-next-line unused-imports/no-unused-vars
catch (error) {
console.error('获取服务器时间失败')
}
})
onUnmounted(() => {
if (interval)
clearInterval(interval)
})
return { currentTime }
}

14
src/layouts/default.vue

@ -6,25 +6,20 @@ import Check from 'components/check/index.vue'
import Liquid from 'components/home/Liquid/index.vue'
import Stop from 'components/Stop/index.vue'
import { useActivateDebug } from 'hooks/useActivateDebug'
import { useServerTime } from 'hooks/useServerTime'
import { isClose } from 'libs/socket'
import { formatDateTime } from 'libs/utils'
import { authRoutes } from 'router/routes'
import { useDebugStore } from 'stores/debugStore'
import { useSystemStore } from 'stores/systemStore'
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { computed, onMounted, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
const { handleLogoClick } = useActivateDebug()
const { currentTime } = useServerTime()
const systemStore = useSystemStore()
const router = useRouter()
const currentTime = ref(formatDateTime())
const timeInterval = setInterval(() => {
currentTime.value = formatDateTime()
}, 1000)
onMounted(async () => {
if (!systemStore.systemStatus.selfTest && systemStore.systemStatus.currentUser?.username !== 'test') {
isCheck.value = true
@ -32,9 +27,6 @@ onMounted(async () => {
solutionList.value = (await getSolsList()).list
})
onUnmounted(() => {
clearInterval(timeInterval)
})
// metaisDefault=true isDebug=true,debug
const menuList = computed(() => {
return authRoutes.filter((item) => {

3
src/libs/utils.ts

@ -102,8 +102,7 @@ export function isNumber(value: any) {
return typeof value === 'number' && !Number.isNaN(value)
}
export function formatDateTime(template: string = 'YYYY-MM-DD HH:mm:ss'): string {
const now = new Date()
export function formatDateTime(template: string = 'YYYY-MM-DD HH:mm:ss', now: Date = new Date()): string {
const tokens: Record<string, string> = {
YYYY: String(now.getFullYear()),
MM: String(now.getMonth() + 1).padStart(2, '0'),

2
src/types/system.d.ts

@ -71,6 +71,8 @@ declare namespace System {
heatTemperature?: number
targetTemperature?: number
temperature: number
targetTime?: number
startHeatTime?: number
}
interface SolutionContainer {
containerCode: number

Loading…
Cancel
Save