工具完成
This commit is contained in:
256
src/components/tools/TimestampConverter.vue
Normal file
256
src/components/tools/TimestampConverter.vue
Normal file
@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<div class="space-y-6">
|
||||
<!-- 当前时间戳 -->
|
||||
<div class="card p-4">
|
||||
<h3 class="text-lg font-semibold text-primary mb-3">{{ t('tools.timestamp_converter.current_timestamp') }}</h3>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center space-x-4">
|
||||
<span class="text-secondary">当前时间戳:</span>
|
||||
<span class="text-primary font-mono text-lg">{{ currentTimestamp }}</span>
|
||||
<button
|
||||
@click="copyTimestamp"
|
||||
class="btn-secondary px-3 py-1 text-sm"
|
||||
>
|
||||
<FontAwesomeIcon :icon="['fas', 'copy']" class="mr-1" />
|
||||
{{ t('tools.timestamp_converter.copy_timestamp') }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-center space-x-4">
|
||||
<span class="text-secondary">当前日期:</span>
|
||||
<span class="text-primary">{{ currentDateTime }}</span>
|
||||
<button
|
||||
@click="copyDateTime"
|
||||
class="btn-secondary px-3 py-1 text-sm"
|
||||
>
|
||||
<FontAwesomeIcon :icon="['fas', 'copy']" class="mr-1" />
|
||||
{{ t('tools.timestamp_converter.copy_date') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 转换工具 -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
<!-- 时间戳转日期 -->
|
||||
<div class="card p-4">
|
||||
<h3 class="text-lg font-semibold text-primary mb-3">{{ t('tools.timestamp_converter.timestamp_to_date') }}</h3>
|
||||
<div class="space-y-3">
|
||||
<input
|
||||
v-model="timestampInput"
|
||||
type="text"
|
||||
:placeholder="t('tools.timestamp_converter.timestamp_placeholder')"
|
||||
class="input-field"
|
||||
@input="convertTimestampToDate"
|
||||
>
|
||||
<button
|
||||
@click="useCurrentTimestamp"
|
||||
class="btn-secondary"
|
||||
>
|
||||
使用当前时间戳
|
||||
</button>
|
||||
<div v-if="timestampResult" class="space-y-2">
|
||||
<label class="block text-sm font-medium text-secondary">转换结果:</label>
|
||||
<div class="bg-block p-3 rounded font-mono text-sm">
|
||||
<div><strong>本地时间:</strong> {{ timestampResult.local }}</div>
|
||||
<div><strong>UTC时间:</strong> {{ timestampResult.utc }}</div>
|
||||
<div><strong>ISO格式:</strong> {{ timestampResult.iso }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 日期转时间戳 -->
|
||||
<div class="card p-4">
|
||||
<h3 class="text-lg font-semibold text-primary mb-3">{{ t('tools.timestamp_converter.date_to_timestamp') }}</h3>
|
||||
<div class="space-y-3">
|
||||
<input
|
||||
v-model="dateInput"
|
||||
type="datetime-local"
|
||||
class="input-field"
|
||||
@input="convertDateToTimestamp"
|
||||
>
|
||||
<button
|
||||
@click="useCurrentDate"
|
||||
class="btn-secondary"
|
||||
>
|
||||
使用当前时间
|
||||
</button>
|
||||
<div v-if="dateResult" class="space-y-2">
|
||||
<label class="block text-sm font-medium text-secondary">转换结果:</label>
|
||||
<div class="bg-block p-3 rounded font-mono text-sm">
|
||||
<div><strong>时间戳(秒):</strong> {{ dateResult.seconds }}</div>
|
||||
<div><strong>时间戳(毫秒):</strong> {{ dateResult.milliseconds }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 快速转换 -->
|
||||
<div class="card p-4">
|
||||
<h3 class="text-lg font-semibold text-primary mb-3">快速转换</h3>
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||
<button
|
||||
v-for="quick in quickOptions"
|
||||
:key="quick.label"
|
||||
@click="() => applyQuickTimestamp(quick.timestamp)"
|
||||
class="btn-secondary text-sm"
|
||||
>
|
||||
{{ quick.label }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { useLanguage } from '@/composables/useLanguage'
|
||||
|
||||
const { t } = useLanguage()
|
||||
|
||||
// 响应式状态
|
||||
const currentTimestamp = ref(0)
|
||||
const currentDateTime = ref('')
|
||||
const timestampInput = ref('')
|
||||
const dateInput = ref('')
|
||||
const timestampResult = ref<any>(null)
|
||||
const dateResult = ref<any>(null)
|
||||
|
||||
// 更新当前时间戳
|
||||
const updateCurrentTime = () => {
|
||||
const now = new Date()
|
||||
currentTimestamp.value = Math.floor(now.getTime() / 1000)
|
||||
currentDateTime.value = now.toLocaleString('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
})
|
||||
}
|
||||
|
||||
// 时间戳转日期
|
||||
const convertTimestampToDate = () => {
|
||||
const input = timestampInput.value.trim()
|
||||
if (!input) {
|
||||
timestampResult.value = null
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
let timestamp = parseInt(input)
|
||||
|
||||
// 判断是秒还是毫秒
|
||||
if (timestamp.toString().length === 10) {
|
||||
timestamp *= 1000
|
||||
}
|
||||
|
||||
const date = new Date(timestamp)
|
||||
|
||||
if (isNaN(date.getTime())) {
|
||||
timestampResult.value = { error: '无效的时间戳' }
|
||||
return
|
||||
}
|
||||
|
||||
timestampResult.value = {
|
||||
local: date.toLocaleString('zh-CN'),
|
||||
utc: date.toUTCString(),
|
||||
iso: date.toISOString()
|
||||
}
|
||||
} catch (error) {
|
||||
timestampResult.value = { error: '转换失败' }
|
||||
}
|
||||
}
|
||||
|
||||
// 日期转时间戳
|
||||
const convertDateToTimestamp = () => {
|
||||
if (!dateInput.value) {
|
||||
dateResult.value = null
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const date = new Date(dateInput.value)
|
||||
const timestamp = date.getTime()
|
||||
|
||||
if (isNaN(timestamp)) {
|
||||
dateResult.value = { error: '无效的日期' }
|
||||
return
|
||||
}
|
||||
|
||||
dateResult.value = {
|
||||
seconds: Math.floor(timestamp / 1000),
|
||||
milliseconds: timestamp
|
||||
}
|
||||
} catch (error) {
|
||||
dateResult.value = { error: '转换失败' }
|
||||
}
|
||||
}
|
||||
|
||||
// 使用当前时间戳
|
||||
const useCurrentTimestamp = () => {
|
||||
timestampInput.value = currentTimestamp.value.toString()
|
||||
convertTimestampToDate()
|
||||
}
|
||||
|
||||
// 使用当前日期
|
||||
const useCurrentDate = () => {
|
||||
const now = new Date()
|
||||
const year = now.getFullYear()
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(now.getDate()).padStart(2, '0')
|
||||
const hours = String(now.getHours()).padStart(2, '0')
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0')
|
||||
|
||||
dateInput.value = `${year}-${month}-${day}T${hours}:${minutes}`
|
||||
convertDateToTimestamp()
|
||||
}
|
||||
|
||||
// 复制时间戳
|
||||
const copyTimestamp = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(currentTimestamp.value.toString())
|
||||
} catch (error) {
|
||||
console.error('复制失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 复制日期时间
|
||||
const copyDateTime = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(currentDateTime.value)
|
||||
} catch (error) {
|
||||
console.error('复制失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 快速选项
|
||||
const quickOptions = [
|
||||
{ label: '1小时前', timestamp: () => Math.floor(Date.now() / 1000) - 3600 },
|
||||
{ label: '1天前', timestamp: () => Math.floor(Date.now() / 1000) - 86400 },
|
||||
{ label: '1周前', timestamp: () => Math.floor(Date.now() / 1000) - 604800 },
|
||||
{ label: '1月前', timestamp: () => Math.floor(Date.now() / 1000) - 2592000 }
|
||||
]
|
||||
|
||||
// 应用快速时间戳
|
||||
const applyQuickTimestamp = (timestampFn: () => number) => {
|
||||
timestampInput.value = timestampFn().toString()
|
||||
convertTimestampToDate()
|
||||
}
|
||||
|
||||
// 定时器
|
||||
let timer: NodeJS.Timeout
|
||||
|
||||
onMounted(() => {
|
||||
updateCurrentTime()
|
||||
timer = setInterval(updateCurrentTime, 1000)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (timer) {
|
||||
clearInterval(timer)
|
||||
}
|
||||
})
|
||||
</script>
|
Reference in New Issue
Block a user