Browse Source

fix: 显示和设置日期和时间

master
guoapeng 2 weeks ago
parent
commit
6157554ccb
  1. 3
      src/apis/system.ts
  2. 104
      src/assets/styles/element.scss
  3. 108
      src/components/home/DateTime/index.vue
  4. 64
      src/hooks/useServerTime.ts
  5. 6
      src/libs/http.ts
  6. 13
      src/libs/utils.ts
  7. 1
      src/stores/useSystemStore.ts
  8. 14
      src/views/main/index.vue

3
src/apis/system.ts

@ -15,3 +15,6 @@ export const getDeviceSelfTest = () => http.get('/self-test/status')
export const deviceSelfTestFinish = () => http.post('/self-test/finish')
export const getSprayStatus = () => http.get('/spray-task/status')
export const setParams = (params: any) => http.post('/spray-task/set-params', params)
export const getTime = (): Promise<{ epochMilli: number }> => http.get('/sys/get-datetime')
export const setTime = (epochMilli: number): Promise<null> => http.post('/sys/set-datetime', { epochMilli })

104
src/assets/styles/element.scss

@ -19,7 +19,7 @@
}
.el-input {
height: 80px;
height: 80px !important;
background: #E8ECF7;
.el-input__wrapper {
background: #E8ECF7;
@ -328,3 +328,105 @@
font-size: 30px;
padding: 20px;
}
.el-picker-panel {
width: 700px;
.el-picker-panel__body-wrapper {
width: 100%;
.el-picker-panel__body {
width: 100%;
.el-date-picker__time-header {
.el-date-picker__editor-wrap {
.el-input {
height: 60px !important;
.el-input__inner {
font-size: 30px;
}
}
.el-time-panel {
width: 330px;
.el-time-panel__content:before {
border: none
}
.el-time-spinner__list:after, .el-time-spinner__list:before {
height: 0;
}
.el-time-spinner__item {
font-size: 30px;
height: 80px;
line-height: 40px;
}
.el-time-panel__footer {
height: 70px;
line-height: 70px;
.el-time-panel__btn {
font-size: 30px;
}
}
}
}
}
.el-date-picker__header {
display: flex;
justify-content: space-between;
align-items: center;
.el-date-picker__header-label {
font-size: 30px;
}
.el-picker-panel__icon-btn {
.el-icon {
width: 30px;
}
}
}
.el-picker-panel__content {
width: 95%;
.el-year-table, .el-month-table {
height: 50px;
.el-date-table-cell {
height: 50px;
.el-date-table-cell__text {
font-size: 25px;
line-height: 50px;
width: 100px;
height: 50px;
}
}
}
.el-date-table {
font-size: 20px;
width: 100%;
.el-date-table__row {
line-height: 50px;
}
td {
padding: 10px 0;
width: 40px;
height: 30px;
.el-date-table-cell {
height: 50px;
.el-date-table-cell__text {
font-size: 25px;
line-height: 50px;
width: 50px;
height: 50px;
}
}
}
}
}
}
}
.el-picker-panel__footer {
height: 80px;
line-height: 80px;
.el-button {
height: 50px;
font-size: 30px;
}
}
}

108
src/components/home/DateTime/index.vue

@ -0,0 +1,108 @@
<script setup lang="ts">
import FtDialog from 'components/common/FTDialog/index.vue'
import { useServerTime } from 'hooks/useServerTime'
import { FtMessage } from 'libs/message'
import { ref, watch } from 'vue'
const emits = defineEmits(['ok', 'cancel'])
const { serverTime, setDateTime, closeDialog } = useServerTime()
console.log('serverTime', serverTime.value)
let onceFlag = false
watch(() => serverTime.value, () => {
if (!onceFlag) {
onceFlag = true
form.value.epochMilli = serverTime.value
}
})
const form = ref({ epochMilli: serverTime.value })
console.log(form.value)
const formRef = ref()
const okLoading = ref(false)
const okHandle = () => {
formRef.value.validate(async (valid: any) => {
if (!valid) {
return
}
console.log(form.value)
okLoading.value = true
await setDateTime(form.value.epochMilli as number)
setTimeout(() => {
okLoading.value = false
FtMessage.success('保存成功')
closeDialog()
}, 300)
})
}
const cancel = () => {
emits('cancel')
}
</script>
<template>
<FtDialog visible title="调整日期与时间" width="40%" :ok-handle="okHandle" @cancel="cancel">
<div class="dialog-content">
<el-form ref="formRef" label-width="120" :model="form">
<el-form-item
label="日期与时间" prop="epochMilli" :rules="[
{
required: true,
message: '请选择日期和时间',
trigger: 'change',
},
]"
>
<el-date-picker
v-model="form.epochMilli"
:editable="false"
:show-now="false"
style="width: 100%"
type="datetime"
format="YYYY/MM/DD HH:mm:ss"
value-format="x"
placeholder="请选择日期和时间"
/>
</el-form-item>
</el-form>
</div>
</FtDialog>
</template>
<style scoped lang="scss">
:deep(.el-form-item__error) {
font-size: 40px;
}
.dialog-content {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: 400px; /* 确保容器高度撑开 */
}
.el-select {
width: 80%;
}
.el-input {
width: 80%;
}
.unit-text {
font-size: 40px;
color: #0349A8;
font-weight: 500;
margin-left: 20px;
}
.select-box {
display: flex;
margin: 40px;
}
.route-img {
display: flex;
img {
width: 70px;
}
}
</style>

64
src/hooks/useServerTime.ts

@ -0,0 +1,64 @@
import { getTime, setTime } 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')
const editVisible = ref(false)
let interval: number | null = null
onMounted(async () => {
try {
await getDateTime()
}
// eslint-disable-next-line unused-imports/no-unused-vars
catch (error) {
// currentTime.value = formatDateTime(undefined, new Date())
console.error('获取服务器时间失败')
}
})
const openDialog = () => {
editVisible.value = true
}
const closeDialog = () => {
editVisible.value = false
}
const getDateTime = async () => {
serverTime.value = (await getTime())?.epochMilli
clientFetchTime.value = Date.now()
let num = 0
if (interval)
clearInterval(interval)
interval = window.setInterval(async () => {
if (num > 60) {
serverTime.value = (await getTime())?.epochMilli
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)
}
const setDateTime = async (time: number) => {
await setTime(time)
await getDateTime()
}
onUnmounted(() => {
if (interval)
clearInterval(interval)
})
return { currentTime, serverTime, editVisible, setDateTime, openDialog, closeDialog }
}

6
src/libs/http.ts

@ -51,13 +51,13 @@ http.interceptors.response.use(
}
else {
if (error.message.includes('timeout')) {
FtMessage.error('请求超时')
FtMessage.error(`请求超时: ${error.response.config.url}`)
}
else if (error.message.includes('Network')) {
FtMessage.error('网络连接错误')
FtMessage.error(`网络连接错误: ${error.response.config.url}`)
}
else {
FtMessage.error('接口请求失败')
FtMessage.error(`接口请求失败: ${error.response.config.url}`)
}
error.response = {
data: {

13
src/libs/utils.ts

@ -139,3 +139,16 @@ export const colors = [
export function isNumber(value: any) {
return typeof value === 'number' && !Number.isNaN(value)
}
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'),
DD: String(now.getDate()).padStart(2, '0'),
HH: String(now.getHours()).padStart(2, '0'),
mm: String(now.getMinutes()).padStart(2, '0'),
ss: String(now.getSeconds()).padStart(2, '0'),
}
return template.replace(/YYYY|MM|DD|HH|mm|ss/g, token => tokens[token]!)
}

1
src/stores/useSystemStore.ts

@ -20,6 +20,7 @@ export const useSystemStore = defineStore('system', {
slideTemperature: 0,
nozzleTemperature: 0,
},
currentTime: '0000-00-00 00:00:00',
isDebug: import.meta.env.FT_NODE_ENV === 'dev',
streamVisible: false,
systemList: [{ cmdCode: '' }],

14
src/views/main/index.vue

@ -2,9 +2,11 @@
import { getDeviceStatus } from 'apis/system'
import FtStream from 'components/common/FTStream/index.vue'
import Check from 'components/home/Check/index.vue'
import DatetimeEdit from 'components/home/DateTime/index.vue'
import Environment from 'components/home/Environment/index.vue'
import Stop from 'components/home/Stop/index.vue'
import { ElMessageBox } from 'element-plus'
import { useServerTime } from 'hooks/useServerTime'
import { isClose, reconnectCurrentCount, socket } from 'libs/socket'
import { useSystemStore } from 'stores/useSystemStore' // systemStore
import { computed, ref, watch } from 'vue'
@ -14,6 +16,8 @@ const route = useRoute()
const router = useRouter()
const systemStore = useSystemStore() // 使 systemStore
const { currentTime, openDialog, closeDialog, editVisible } = useServerTime()
const checkVisible = ref(false)
console.log(import.meta.env.FT_NODE_ENV)
const environmentVisible = ref(false)
@ -174,6 +178,9 @@ const backHandle = () => {
</div>
</div>
<div style="display: flex">
<div class="time" @click="openDialog">
{{ currentTime }}
</div>
<el-tooltip
class="box-item"
effect="dark"
@ -239,6 +246,7 @@ const backHandle = () => {
<Stop v-if="systemStore.systemStatus.stopPressed" />
<Check v-if="checkVisible" @ok="ok" @cancel="cancel" />
<Environment v-if="environmentVisible" @cancel="cancel" />
<DatetimeEdit v-if="editVisible" @cancel="closeDialog" />
</el-container>
</template>
@ -291,4 +299,10 @@ const backHandle = () => {
width: 50px;
margin: 0 50px;
}
.time {
color: #ddd;
display: flex;
align-items: center;
font-size: 45px;
}
</style>
Loading…
Cancel
Save