forked from github/dataease
feat(数据大屏): 增加时钟组件
This commit is contained in:
parent
1ef59bb87b
commit
97288c14cb
213
core/core-frontend/src/custom-component/de-date/Attr.vue
Normal file
213
core/core-frontend/src/custom-component/de-date/Attr.vue
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import CommonAttr from '@/custom-component/common/CommonAttr.vue'
|
||||||
|
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||||
|
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
|
||||||
|
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
import { ElIcon, ElMessage } from 'element-plus-secondary'
|
||||||
|
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
|
||||||
|
import { beforeUploadCheck, uploadFileResult } from '@/api/staticResource'
|
||||||
|
import { imgUrlTrans } from '@/utils/imgUtils'
|
||||||
|
import eventBus from '@/utils/eventBus'
|
||||||
|
import ImgViewDialog from '@/custom-component/ImgViewDialog.vue'
|
||||||
|
|
||||||
|
withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
themes?: EditorTheme
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
themes: 'dark'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const dvMainStore = dvMainStoreWithOut()
|
||||||
|
const snapshotStore = snapshotStoreWithOut()
|
||||||
|
|
||||||
|
const { curComponent } = storeToRefs(dvMainStore)
|
||||||
|
|
||||||
|
const fileList = ref([])
|
||||||
|
const dialogImageUrl = ref('')
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const uploadDisabled = ref(false)
|
||||||
|
const files = ref(null)
|
||||||
|
const maxImageSize = 15000000
|
||||||
|
|
||||||
|
const handlePictureCardPreview = file => {
|
||||||
|
dialogImageUrl.value = file.url
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRemove = (_, fileList) => {
|
||||||
|
uploadDisabled.value = false
|
||||||
|
curComponent.value.propValue.url = null
|
||||||
|
fileList.value = []
|
||||||
|
snapshotStore.recordSnapshotCache()
|
||||||
|
}
|
||||||
|
async function upload(file) {
|
||||||
|
uploadFileResult(file.file, fileUrl => {
|
||||||
|
snapshotStore.recordSnapshotCache()
|
||||||
|
curComponent.value.propValue.url = fileUrl
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const goFile = () => {
|
||||||
|
files.value.click()
|
||||||
|
}
|
||||||
|
|
||||||
|
const reUpload = e => {
|
||||||
|
const file = e.target.files[0]
|
||||||
|
if (file.size > maxImageSize) {
|
||||||
|
sizeMessage()
|
||||||
|
}
|
||||||
|
uploadFileResult(file, fileUrl => {
|
||||||
|
snapshotStore.recordSnapshotCache()
|
||||||
|
curComponent.value.propValue.url = fileUrl
|
||||||
|
fileList.value = [{ url: imgUrlTrans(curComponent.value.propValue.url) }]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const sizeMessage = () => {
|
||||||
|
ElMessage.success('图片大小不符合')
|
||||||
|
}
|
||||||
|
const init = () => {
|
||||||
|
if (curComponent.value.propValue.url) {
|
||||||
|
fileList.value = [{ url: imgUrlTrans(curComponent.value.propValue.url) }]
|
||||||
|
} else {
|
||||||
|
fileList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => curComponent.value.propValue.url,
|
||||||
|
() => {
|
||||||
|
init()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
init()
|
||||||
|
eventBus.on('uploadImg', goFile)
|
||||||
|
})
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
eventBus.off('uploadImg', goFile)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="attr-list de-collapse-style">
|
||||||
|
<CommonAttr
|
||||||
|
:themes="themes"
|
||||||
|
:element="curComponent"
|
||||||
|
:background-color-picker-width="197"
|
||||||
|
:background-border-select-width="197"
|
||||||
|
>
|
||||||
|
</CommonAttr>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.de-collapse-style {
|
||||||
|
:deep(.ed-collapse-item__header) {
|
||||||
|
height: 36px !important;
|
||||||
|
line-height: 36px !important;
|
||||||
|
font-size: 12px !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
font-weight: 500 !important;
|
||||||
|
|
||||||
|
.ed-collapse-item__arrow {
|
||||||
|
margin: 0 6px 0 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ed-collapse-item__content) {
|
||||||
|
padding: 16px 8px 0;
|
||||||
|
}
|
||||||
|
:deep(.ed-form-item) {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
:deep(.ed-form-item__label) {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.disabled :deep(.el-upload--picture-card) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-uploader :deep(.ed-upload) {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
line-height: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-uploader :deep(.ed-upload-list li) {
|
||||||
|
width: 80px !important;
|
||||||
|
height: 80px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ed-upload--picture-card) {
|
||||||
|
background: #eff0f1;
|
||||||
|
border: 1px dashed #dee0e3;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
.ed-icon {
|
||||||
|
color: #1f2329;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.ed-icon {
|
||||||
|
color: var(--ed-color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.img-area {
|
||||||
|
height: 80px;
|
||||||
|
width: 80px;
|
||||||
|
margin-top: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.img-area_dark {
|
||||||
|
:deep(.ed-upload-list__item).is-success {
|
||||||
|
border-color: #434343;
|
||||||
|
}
|
||||||
|
:deep(.ed-upload--picture-card) {
|
||||||
|
background: #373737;
|
||||||
|
border-color: #434343;
|
||||||
|
.ed-icon {
|
||||||
|
color: #ebebeb;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
.ed-icon {
|
||||||
|
color: var(--ed-color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.img-area_light {
|
||||||
|
:deep(.ed-upload-list__item).is-success {
|
||||||
|
border-color: #dee0e3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-hint {
|
||||||
|
color: #8f959e;
|
||||||
|
size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
font-weight: 400;
|
||||||
|
margin-top: 2px;
|
||||||
|
&.image-hint_dark {
|
||||||
|
color: #757575;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.re-update-span {
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--ed-color-primary);
|
||||||
|
size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,53 @@
|
|||||||
|
<template>
|
||||||
|
<div style="height: 100%">
|
||||||
|
<time-default
|
||||||
|
v-if="element?.formatInfo?.openMode === '0'"
|
||||||
|
:ref="element.id"
|
||||||
|
:element="element"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<time-elec v-if="element?.formatInfo?.openMode === '1'" :ref="element.id" :element="element" />
|
||||||
|
|
||||||
|
<time-simple
|
||||||
|
v-if="element?.formatInfo?.openMode === '2'"
|
||||||
|
:ref="element.id"
|
||||||
|
:element="element"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<time-complex
|
||||||
|
v-if="element?.formatInfo?.openMode === '3'"
|
||||||
|
:ref="element.id"
|
||||||
|
:element="element"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, nextTick, toRefs } from 'vue'
|
||||||
|
import { getCurrentInstance, onMounted } from 'vue/dist/vue'
|
||||||
|
const props = defineProps({
|
||||||
|
element: {
|
||||||
|
type: Object
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const { element } = toRefs(props)
|
||||||
|
|
||||||
|
|
||||||
|
let currentInstance
|
||||||
|
const timeMargin = computed(() => {
|
||||||
|
return element.value.style.time_margin
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
currentInstance = getCurrentInstance()
|
||||||
|
})
|
||||||
|
|
||||||
|
const chartResize = () => {
|
||||||
|
const dataRefs = currentInstance.proxy
|
||||||
|
nextTick(() => {
|
||||||
|
dataRefs.$refs[element.value.id] &&
|
||||||
|
dataRefs.$refs[element.value.id].resize &&
|
||||||
|
dataRefs.$refs[element.value.id].resize()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
257
core/core-frontend/src/custom-component/de-date/TimeComplex.vue
Normal file
257
core/core-frontend/src/custom-component/de-date/TimeComplex.vue
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<canvas :id="'complex_canvas' + element.id" width="500" height="500" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { toRefs } from 'vue/dist/vue'
|
||||||
|
import { getCurrentInstance, onMounted, reactive } from 'vue'
|
||||||
|
|
||||||
|
let milliseconds = 0
|
||||||
|
let minutes = 0
|
||||||
|
let hour = 0
|
||||||
|
let date = ''
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
element: {
|
||||||
|
type: Object
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const { element } = toRefs(props)
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
time: '',
|
||||||
|
date: '',
|
||||||
|
week: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
|
||||||
|
canvas: null,
|
||||||
|
ctx: null,
|
||||||
|
ctxBack: null,
|
||||||
|
numBack: null,
|
||||||
|
timer: null
|
||||||
|
})
|
||||||
|
|
||||||
|
const currentTime = () => {
|
||||||
|
state.timer = setInterval(pageInit, 500)
|
||||||
|
}
|
||||||
|
const initCtx = () => {
|
||||||
|
state.ctx = state.canvas.getContext('2d')
|
||||||
|
state.ctx.strokeStyle = '#7FFFD4'
|
||||||
|
state.ctx.lineWidth = 3
|
||||||
|
state.ctx.shadowBlur = 5
|
||||||
|
state.ctx.shadowColor = '#7FFFD4'
|
||||||
|
}
|
||||||
|
const initCtxBack = () => {
|
||||||
|
state.ctxBack = state.canvas.getContext('2d')
|
||||||
|
state.ctxBack.lineWidth = 1
|
||||||
|
state.ctxBack.shadowBlur = 0
|
||||||
|
state.ctxBack.shadowColor = '#F0F8FF'
|
||||||
|
}
|
||||||
|
const initNumBack = () => {
|
||||||
|
state.numBack = state.canvas.getContext('2d')
|
||||||
|
}
|
||||||
|
const pageInit = () => {
|
||||||
|
showTime()
|
||||||
|
showBack()
|
||||||
|
drawSecPin()
|
||||||
|
drawMinPin()
|
||||||
|
drawHouPin()
|
||||||
|
setPoint()
|
||||||
|
setNum()
|
||||||
|
},
|
||||||
|
setNum = () => {
|
||||||
|
state.numBack.save()
|
||||||
|
state.numBack.translate(250, 250)
|
||||||
|
state.numBack.beginPath()
|
||||||
|
state.numBack.fillStyle = '#7FFFD4'
|
||||||
|
state.numBack.font = '30px Helvetica'
|
||||||
|
for (let i = 0; i < 60; i++) {
|
||||||
|
if (i % 5 === 0) {
|
||||||
|
state.numBack.lineWidth = 5
|
||||||
|
let xPoint = Math.sin((i * 6 * 2 * Math.PI) / 360) * 195
|
||||||
|
let yPoint = -Math.cos((i * 6 * 2 * Math.PI) / 360) * 195
|
||||||
|
state.numBack.fillText(
|
||||||
|
i === 0 ? 12 : i / 5,
|
||||||
|
i === 0 ? -15 : xPoint - 10,
|
||||||
|
i === 0 ? -185 : i <= 30 ? yPoint + 5 : yPoint + 10
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.numBack.stroke()
|
||||||
|
state.numBack.closePath()
|
||||||
|
state.numBack.restore()
|
||||||
|
}
|
||||||
|
|
||||||
|
const drawSecPin = () => {
|
||||||
|
state.ctxBack.save()
|
||||||
|
state.ctxBack.translate(250, 250)
|
||||||
|
state.ctxBack.rotate((milliseconds / 60) * 2 * Math.PI)
|
||||||
|
state.ctxBack.beginPath()
|
||||||
|
state.ctxBack.strokeStyle = '#AFEEEE'
|
||||||
|
state.ctxBack.lineWidth = 1
|
||||||
|
state.ctxBack.lineJoin = 'bevel'
|
||||||
|
state.ctxBack.miterLimit = 10
|
||||||
|
state.ctxBack.moveTo(0, 30)
|
||||||
|
state.ctxBack.lineTo(3, -175)
|
||||||
|
state.ctxBack.lineTo(13, -165)
|
||||||
|
state.ctxBack.lineTo(0, -210)
|
||||||
|
state.ctxBack.lineTo(-13, -165)
|
||||||
|
state.ctxBack.lineTo(-3, -175)
|
||||||
|
state.ctxBack.lineTo(0, 30)
|
||||||
|
state.ctxBack.stroke()
|
||||||
|
state.ctxBack.closePath()
|
||||||
|
state.ctxBack.restore()
|
||||||
|
}
|
||||||
|
|
||||||
|
const drawMinPin = () => {
|
||||||
|
state.ctxBack.save()
|
||||||
|
state.ctxBack.translate(250, 250)
|
||||||
|
state.ctxBack.rotate((minutes * 6 * Math.PI) / 180)
|
||||||
|
state.ctxBack.beginPath()
|
||||||
|
state.ctxBack.strokeStyle = '#20B2AA'
|
||||||
|
state.ctxBack.lineWidth = 1
|
||||||
|
state.ctxBack.lineJoin = 'bevel'
|
||||||
|
state.ctxBack.miterLimit = 10
|
||||||
|
state.ctxBack.moveTo(0, 20)
|
||||||
|
state.ctxBack.lineTo(3, -145)
|
||||||
|
state.ctxBack.lineTo(10, -135)
|
||||||
|
state.ctxBack.lineTo(0, -180)
|
||||||
|
state.ctxBack.lineTo(-10, -135)
|
||||||
|
state.ctxBack.lineTo(-3, -145)
|
||||||
|
state.ctxBack.lineTo(0, 20)
|
||||||
|
state.ctxBack.stroke()
|
||||||
|
state.ctxBack.closePath()
|
||||||
|
state.ctxBack.restore()
|
||||||
|
}
|
||||||
|
|
||||||
|
const drawHouPin = () => {
|
||||||
|
state.ctxBack.save()
|
||||||
|
state.ctxBack.translate(250, 250)
|
||||||
|
state.ctxBack.rotate((hour * 30 * Math.PI) / 180)
|
||||||
|
state.ctxBack.beginPath()
|
||||||
|
state.ctxBack.strokeStyle = '#87CEFA'
|
||||||
|
state.ctxBack.lineWidth = 1
|
||||||
|
state.ctxBack.lineJoin = 'bevel'
|
||||||
|
state.ctxBack.miterLimit = 10
|
||||||
|
state.ctxBack.moveTo(0, 20)
|
||||||
|
state.ctxBack.lineTo(3, -110)
|
||||||
|
state.ctxBack.lineTo(10, -100)
|
||||||
|
state.ctxBack.lineTo(0, -150)
|
||||||
|
state.ctxBack.lineTo(-10, -100)
|
||||||
|
state.ctxBack.lineTo(-3, -110)
|
||||||
|
state.ctxBack.lineTo(0, 20)
|
||||||
|
state.ctxBack.stroke()
|
||||||
|
state.ctxBack.closePath()
|
||||||
|
state.ctxBack.restore()
|
||||||
|
}
|
||||||
|
|
||||||
|
const setPoint = () => {
|
||||||
|
state.ctxBack.beginPath()
|
||||||
|
state.ctxBack.fillStyle = 'black'
|
||||||
|
state.ctxBack.arc(250, 250, 3, 0, 2 * Math.PI)
|
||||||
|
state.ctxBack.stroke()
|
||||||
|
}
|
||||||
|
|
||||||
|
const showBack = () => {
|
||||||
|
for (let i = 0; i < 60; i++) {
|
||||||
|
state.ctxBack.save()
|
||||||
|
state.ctxBack.translate(250, 250)
|
||||||
|
state.ctxBack.rotate((i / 60) * 2 * Math.PI)
|
||||||
|
state.ctxBack.beginPath()
|
||||||
|
state.ctxBack.strokeStyle = '#7FFFD4'
|
||||||
|
state.ctxBack.moveTo(0, -250)
|
||||||
|
state.ctxBack.lineWidth = i % 5 === 0 ? 5 : 2
|
||||||
|
state.ctxBack.lineTo(0, -230)
|
||||||
|
state.ctxBack.stroke()
|
||||||
|
state.ctxBack.closePath()
|
||||||
|
state.ctxBack.restore()
|
||||||
|
}
|
||||||
|
state.ctxBack.beginPath()
|
||||||
|
state.ctxBack.arc(250, 250, 230, 0, 2 * Math.PI)
|
||||||
|
state.ctxBack.stroke()
|
||||||
|
}
|
||||||
|
|
||||||
|
const degToRad = degree => {
|
||||||
|
let result
|
||||||
|
let factor = Math.PI / 180
|
||||||
|
if (degree === 0) {
|
||||||
|
result = 270 * factor
|
||||||
|
} else {
|
||||||
|
result = degree * factor
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
const showTime = () => {
|
||||||
|
let now = new Date()
|
||||||
|
let today = now.toLocaleDateString()
|
||||||
|
let time = now.toLocaleTimeString()
|
||||||
|
let day = now.getDay()
|
||||||
|
let hrs = now.getHours()
|
||||||
|
let min = now.getMinutes()
|
||||||
|
let sec = now.getSeconds()
|
||||||
|
let mil = now.getMilliseconds()
|
||||||
|
let smoothsec = sec + mil / 1000
|
||||||
|
let smoothmin = min + smoothsec / 60
|
||||||
|
let hours = hrs + smoothmin / 60
|
||||||
|
milliseconds = smoothsec
|
||||||
|
minutes = smoothmin
|
||||||
|
hour = hours
|
||||||
|
switch (day) {
|
||||||
|
case 1:
|
||||||
|
date = '一'
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
date = '二'
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
date = '三'
|
||||||
|
break
|
||||||
|
case 4:
|
||||||
|
date = '四'
|
||||||
|
break
|
||||||
|
case 5:
|
||||||
|
date = '五'
|
||||||
|
break
|
||||||
|
case 6:
|
||||||
|
date = '六'
|
||||||
|
break
|
||||||
|
case 0:
|
||||||
|
date = '日'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
const gradient = state.ctx.createRadialGradient(250, 250, 5, 250, 250, 300)
|
||||||
|
gradient.addColorStop(0, '#03303a')
|
||||||
|
gradient.addColorStop(1, 'black')
|
||||||
|
state.ctx.fillStyle = gradient
|
||||||
|
state.ctx.fillRect(0, 0, 500, 500)
|
||||||
|
state.ctx.beginPath()
|
||||||
|
state.ctx.strokeStyle = '#87CEFA'
|
||||||
|
state.ctx.arc(250, 250, 215, degToRad(0), degToRad(hours * 30 - 90))
|
||||||
|
state.ctx.stroke()
|
||||||
|
state.ctx.beginPath()
|
||||||
|
state.ctx.strokeStyle = '#20B2AA'
|
||||||
|
state.ctx.arc(250, 250, 220, degToRad(0), degToRad(smoothmin * 6 - 90))
|
||||||
|
state.ctx.stroke()
|
||||||
|
state.ctx.beginPath()
|
||||||
|
state.ctx.strokeStyle = '#AFEEEE'
|
||||||
|
state.ctx.arc(250, 250, 225, degToRad(0), degToRad(smoothsec * 6 - 90))
|
||||||
|
state.ctx.stroke()
|
||||||
|
state.ctx.font = '25px Helvetica Bold'
|
||||||
|
state.ctx.fillStyle = '#7FFFD4'
|
||||||
|
state.ctx.fillText(today + '/星期' + date, 150, 230)
|
||||||
|
state.ctx.font = '23px Helvetica Bold'
|
||||||
|
state.ctx.fillStyle = '#7FFFD4'
|
||||||
|
state.ctx.fillText(time, 190, 280)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
state.canvas = document.getElementById('complex_canvas' + element.value.id)
|
||||||
|
initCtx()
|
||||||
|
initCtxBack()
|
||||||
|
initNumBack()
|
||||||
|
currentTime()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
@ -0,0 +1,67 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
style="display: flex; align-items: center"
|
||||||
|
:style="{ height: containerHeight, margin: timeMargin + 'px' }"
|
||||||
|
>
|
||||||
|
<p style="width: 100%; margin: auto">{{ nowDate }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, getCurrentInstance, onMounted, onUnmounted, reactive, toRefs } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
element: {
|
||||||
|
type: Object
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { element } = toRefs(props)
|
||||||
|
const state = reactive({
|
||||||
|
nowDate: '', // 当前日期
|
||||||
|
nowWeek: '',
|
||||||
|
timer: null
|
||||||
|
})
|
||||||
|
const timeMargin = computed(() => {
|
||||||
|
return element.value.style.time_margin
|
||||||
|
})
|
||||||
|
|
||||||
|
const containerHeight = computed(() => {
|
||||||
|
return 'calc(100% - ' + element.value.style.time_margin * 2 + 'px)'
|
||||||
|
})
|
||||||
|
|
||||||
|
const currentTime = () => {
|
||||||
|
state.timer = setInterval(formatDate, 500)
|
||||||
|
}
|
||||||
|
const formatDate = () => {
|
||||||
|
const weekArr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
||||||
|
let timeFormat = element.value.formatInfo.timeFormat
|
||||||
|
const showWeek = element.value.formatInfo.showWeek
|
||||||
|
const showDate = element.value.formatInfo.showDate
|
||||||
|
const dateFormat = element.value.formatInfo.dateFormat || 'yyyy-MM-dd'
|
||||||
|
if (showDate && dateFormat) {
|
||||||
|
timeFormat = dateFormat + ' ' + timeFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
const date = new Date()
|
||||||
|
|
||||||
|
state.nowDate = date.format(timeFormat)
|
||||||
|
|
||||||
|
if (showWeek) {
|
||||||
|
state.nowWeek = weekArr[date.getDay()]
|
||||||
|
state.nowDate = state.nowDate + ' ' + state.nowWeek
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
currentTime()
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (state.timer) {
|
||||||
|
clearInterval(state.timer) // 在Vue实例销毁前,清除时间定时器
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
Loading…
Reference in New Issue
Block a user