refactor: harden deps, fix geo math, and add engineering tooling

Replace xlsx with exceljs, unify CRS/DMS logic, move pages to views with shared map/toast composables, and add Vitest/ESLint/Prettier plus docs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-12 09:26:15 +08:00
co-authored by Cursor
parent be48495dcf
commit 88e201e50b
29 changed files with 3270 additions and 2756 deletions
+168
View File
@@ -0,0 +1,168 @@
<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-3">
<!-- DMS Input -->
<div>
<h3 class="card-title">度分秒</h3>
<div class="input-group">
<label class="input-label"></label>
<input type="number" v-model.number="dms.degrees" class="input" @input="fromDms">
</div>
<div class="input-group">
<label class="input-label"></label>
<input type="number" v-model.number="dms.minutes" class="input" @input="fromDms" min="0"
max="59">
</div>
<div class="input-group">
<label class="input-label"></label>
<input type="number" v-model.number="dms.seconds" class="input" @input="fromDms" min="0"
max="59" step="0.01">
</div>
</div>
<!-- Decimal Input -->
<div>
<h3 class="card-title">十进制度数</h3>
<div class="input-group">
<label class="input-label">度数</label>
<input type="number" v-model.number="decimal" class="input" @input="fromDecimal" step="0.000001"
placeholder="例:45.5">
</div>
<div class="conversion-info">
<p class="hint">当前角度的其他表示形式会自动同步</p>
</div>
</div>
<!-- Radian Input -->
<div>
<h3 class="card-title">弧度</h3>
<div class="input-group">
<label class="input-label">弧度值</label>
<input type="number" v-model.number="radian" class="input" @input="fromRadian" step="0.000001"
placeholder="例:0.7854">
</div>
<div class="conversion-info">
<p class="hint">π 3.14159</p>
<p class="hint">180° = π 弧度</p>
</div>
</div>
</div>
<div class="result mt-xl">
<div class="result-label">完整转换结果</div>
<div class="conversion-results">
<div class="conversion-item">
<strong>度分秒</strong>
<span>{{ dms.degrees }}° {{ dms.minutes }}' {{ dms.seconds.toFixed(2) }}"</span>
</div>
<div class="conversion-item">
<strong>十进制:</strong>
<span>{{ decimal.toFixed(6) }}°</span>
</div>
<div class="conversion-item">
<strong>弧度:</strong>
<span>{{ radian.toFixed(6) }} rad</span>
</div>
<div class="conversion-item">
<strong>π表示:</strong>
<span>{{ (radian / Math.PI).toFixed(4) }}π</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { dmsToDecimal, decimalToDms } from '../utils/coordinate'
const dms = ref({ degrees: 45, minutes: 30, seconds: 0 })
const decimal = ref(45.5)
const radian = ref(0.7941)
const fromDms = () => {
decimal.value = dmsToDecimal(dms.value.degrees, dms.value.minutes, dms.value.seconds)
radian.value = decimal.value * Math.PI / 180
}
const fromDecimal = () => {
const converted = decimalToDms(decimal.value)
dms.value = converted
radian.value = decimal.value * Math.PI / 180
}
const fromRadian = () => {
decimal.value = radian.value * 180 / Math.PI
const converted = decimalToDms(decimal.value)
dms.value = converted
}
// Initialize
fromDms()
</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);
}
.conversion-info {
margin-top: var(--spacing-lg);
padding: var(--spacing-md);
background: var(--bg-secondary);
border-radius: var(--border-radius-sm);
}
.hint {
font-size: var(--font-size-sm);
color: var(--text-tertiary);
margin-bottom: var(--spacing-xs);
}
.conversion-results {
display: grid;
gap: var(--spacing-md);
margin-top: var(--spacing-md);
}
.conversion-item {
display: flex;
justify-content: space-between;
padding: var(--spacing-sm) var(--spacing-md);
background: var(--bg-secondary);
border-radius: var(--border-radius-sm);
font-size: var(--font-size-base);
}
.conversion-item span {
color: var(--primary);
font-weight: 600;
}
@media (max-width: 768px) {
.grid-3 {
grid-template-columns: 1fr;
}
}
</style>