初次提交

This commit is contained in:
2026-01-28 23:39:11 +08:00
commit 5ee9aef865
27 changed files with 4449 additions and 0 deletions

View File

@@ -0,0 +1,176 @@
<template>
<div class="container">
<div class="tool-header">
<router-link to="/" class="back-link"> 返回首页</router-link>
<h2>🌍 坐标转换工具</h2>
<p>经纬度格式转换度分秒 十进制度数</p>
</div>
<div class="card">
<div class="grid grid-2">
<!-- DMS to Decimal -->
<div>
<h3 class="card-title">度分秒 十进制</h3>
<div class="input-group">
<label class="input-label">纬度度分秒</label>
<div class="dms-input">
<input type="number" v-model.number="dms.lat.degrees" class="input" placeholder="度">
<input type="number" v-model.number="dms.lat.minutes" class="input" placeholder="分">
<input type="number" v-model.number="dms.lat.seconds" class="input" placeholder="秒">
<select v-model="dms.lat.direction" class="input">
<option value="N">N</option>
<option value="S">S</option>
</select>
</div>
</div>
<div class="input-group">
<label class="input-label">经度度分秒</label>
<div class="dms-input">
<input type="number" v-model.number="dms.lon.degrees" class="input" placeholder="度">
<input type="number" v-model.number="dms.lon.minutes" class="input" placeholder="分">
<input type="number" v-model.number="dms.lon.seconds" class="input" placeholder="秒">
<select v-model="dms.lon.direction" class="input">
<option value="E">E</option>
<option value="W">W</option>
</select>
</div>
</div>
<button @click="convertToDecimal" class="btn btn-primary">转换为十进制</button>
</div>
<!-- Decimal to DMS -->
<div>
<h3 class="card-title">十进制 度分秒</h3>
<div class="input-group">
<label class="input-label">纬度十进制</label>
<input type="number" v-model.number="decimal.lat" class="input" placeholder="例39.9075"
step="0.000001">
<small class="hint">正数为北纬负数为南纬</small>
</div>
<div class="input-group">
<label class="input-label">经度十进制</label>
<input type="number" v-model.number="decimal.lon" class="input" placeholder="例116.3972"
step="0.000001">
<small class="hint">正数为东经负数为西经</small>
</div>
<button @click="convertToDms" class="btn btn-primary">转换为度分秒</button>
</div>
</div>
<!-- Results -->
<div v-if="result" class="result mt-xl">
<div class="result-label">转换结果</div>
<div class="result-content">
<div v-if="result.type === 'decimal'">
<p><strong>纬度</strong>{{ result.lat }}°</p>
<p><strong>经度</strong>{{ result.lon }}°</p>
</div>
<div v-else>
<p><strong>纬度</strong>{{ result.lat }}</p>
<p><strong>经度</strong>{{ result.lon }}</p>
</div>
</div>
<button @click="copyResult" class="btn btn-secondary mt-md">📋 复制结果</button>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { dmsToDecimal, decimalToDms, formatCoordinate } from '../utils/coordinate'
const dms = ref({
lat: { degrees: 39, minutes: 54, seconds: 27, direction: 'N' },
lon: { degrees: 116, minutes: 23, seconds: 50, direction: 'E' }
})
const decimal = ref({
lat: 39.9075,
lon: 116.3972
})
const result = ref(null)
const convertToDecimal = () => {
const latDecimal = dmsToDecimal(dms.value.lat.degrees, dms.value.lat.minutes, dms.value.lat.seconds)
const lonDecimal = dmsToDecimal(dms.value.lon.degrees, dms.value.lon.minutes, dms.value.lon.seconds)
result.value = {
type: 'decimal',
lat: (dms.value.lat.direction === 'S' ? -latDecimal : latDecimal).toFixed(6),
lon: (dms.value.lon.direction === 'W' ? -lonDecimal : lonDecimal).toFixed(6)
}
}
const convertToDms = () => {
result.value = {
type: 'dms',
lat: formatCoordinate(decimal.value.lat, 'lat'),
lon: formatCoordinate(decimal.value.lon, 'lon')
}
}
const copyResult = () => {
const text = result.value.type === 'decimal'
? `纬度: ${result.value.lat}°, 经度: ${result.value.lon}°`
: `纬度: ${result.value.lat}, 经度: ${result.value.lon}`
navigator.clipboard.writeText(text).then(() => {
alert('已复制到剪贴板!')
})
}
</script>
<style scoped>
.tool-header {
text-align: center;
margin-bottom: var(--spacing-xl);
}
.back-link {
display: inline-block;
color: var(--text-secondary);
text-decoration: none;
margin-bottom: var(--spacing-md);
transition: color var(--transition-base);
}
.back-link:hover {
color: var(--primary);
}
.dms-input {
display: grid;
grid-template-columns: 1fr 1fr 1fr 0.6fr;
gap: var(--spacing-sm);
}
.hint {
display: block;
margin-top: var(--spacing-xs);
font-size: var(--font-size-xs);
color: var(--text-tertiary);
}
.result-content {
font-size: var(--font-size-lg);
line-height: 1.8;
}
.result-content p {
margin-bottom: var(--spacing-sm);
}
@media (max-width: 768px) {
.dms-input {
grid-template-columns: 1fr 1fr;
}
}
</style>