Appearance
实现 综合单位换算 工具
分类:general | 标签:单位、换算、长度、重量、温度 长度 / 重量 / 温度 / 面积 / 体积 / 速度 等常用单位互转
2.1 功能说明
长度 / 重量 / 温度 / 面积 / 体积 / 速度 等常用单位互转
核心能力
- g.label
- 类型
- cats[key].label
- 数值
- name
2.1.1 使用指南
综合单位换算使用指南
基础类型
- 长度:米 / 千米 / 厘米 / 毫米 / 英里 / 码 / 英尺 / 英寸
- 重量:千克 / 克 / 毫克 / 吨 / 磅 / 盎司
- 温度:摄氏度 / 华氏度 / 开尔文
- 面积 / 体积 / 速度:常用公制与英制单位
物理量类型
- 压力:Pa / kPa / MPa / bar / psi / atm / mmHg,以帕斯卡为基准
- 功率:W / kW / MW / 公制马力(1 hp = 735.49875 W)/ 英制马力(1 hp = 745.6998716 W)
- 能量:J / kJ / cal / kcal / Wh / kWh / eV / BTU,以焦耳为基准
- 力:N / kN / kgf(1 kgf = 9.80665 N)/ lbf / dyn
- 密度:kg/m³ / g/cm³ / g/L / kg/L / lb/ft³ / lb/in³
生活换算类型
- 时间:毫秒 / 秒 / 分 / 小时 / 天 / 周 / 月 / 年,并含工作日折算:工作日按 8 小时、工作周按 5 个工作日(40 小时)、工作月按 21.75 个工作日(174 小时)计。月按 365.25/12 天、年按 365.25 天计算。
- 燃油效率:L/100km、km/L、mpg(US)、mpg(UK) 互转。该类别为反比关系,换算公式为 mpg(US) = 235.2145833 ÷ (L/100km)、mpg(UK) = 282.4809363 ÷ (L/100km)、km/L = 100 ÷ (L/100km)。
使用说明
先在顶部选择类别分组,再选择具体类型与单位,输入数值即可实时换算。温度采用公/英制公式换算,燃油效率采用反比公式换算,其余按线性系数换算。
2.2 代码实现
2.2.1 组件结构
本工具是一个基于 Vue 3 <script setup> 语法的单文件组件(SFC),统一包裹在 ToolPageShell 组件内,由它提供页面标题、工具 ID、分类与「使用指南」插槽等通用外壳;核心业务逻辑(响应式状态、计算属性、事件处理函数)全部写在 <script setup> 中,输入/输出通过 el-input、el-button 等 Element Plus 组件与用户交互,所有数据均在浏览器本地处理,不会上传服务器。
2.2.2 核心逻辑概览
<script setup> 中定义的主要函数/方法:
onCatChange()toCelsius()fromCelsius()fuelSwap()convert()formatNum()
2.2.3 关键实现代码
以下是该工具的完整 <script setup> 实现(核心代码)。模板(<template>)与样式(<style>)已省略。
vue
import { ref, computed, watch } from 'vue'
import ToolPageShell from '@/components/ToolPageShell.vue'
const cats = {
length: { label: '长度', units: { m: '米 (m)', km: '千米 (km)', cm: '厘米 (cm)', mm: '毫米 (mm)', mi: '英里 (mi)', yd: '码 (yd)', ft: '英尺 (ft)', in: '英寸 (in)' }, factor: { m: 1, km: 1000, cm: 0.01, mm: 0.001, mi: 1609.344, yd: 0.9144, ft: 0.3048, in: 0.0254 } },
weight: { label: '重量', units: { kg: '千克 (kg)', g: '克 (g)', mg: '毫克 (mg)', t: '吨 (t)', lb: '磅 (lb)', oz: '盎司 (oz)' }, factor: { kg: 1, g: 0.001, mg: 1e-6, t: 1000, lb: 0.45359237, oz: 0.028349523125 } },
area: { label: '面积', units: { m2: '平方米 (m²)', km2: '平方千米 (km²)', cm2: '平方厘米 (cm²)', ha: '公顷 (ha)', ft2: '平方英尺 (ft²)', acre: '英亩 (acre)' }, factor: { m2: 1, km2: 1e6, cm2: 1e-4, ha: 10000, ft2: 0.09290304, acre: 4046.8564224 } },
volume: { label: '体积', units: { L: '升 (L)', mL: '毫升 (mL)', m3: '立方米 (m³)', gal_us: '加仑(美) (gal)', gal_uk: '加仑(英) (gal)' }, factor: { L: 1, mL: 0.001, m3: 1000, gal_us: 3.785411784, gal_uk: 4.54609 } },
speed: { label: '速度', units: { mps: '米/秒 (m/s)', kmh: '千米/时 (km/h)', mph: '英里/时 (mph)', knot: '节 (knot)' }, factor: { mps: 1, kmh: 0.2777778, mph: 0.44704, knot: 0.514444 } },
temperature: { label: '温度', units: { C: '摄氏度 (°C)', F: '华氏度 (°F)', K: '开尔文 (K)' }, special: true },
pressure: {
label: '压力',
units: { Pa: '帕斯卡 (Pa)', kPa: '千帕 (kPa)', MPa: '兆帕 (MPa)', bar: '巴 (bar)', psi: '磅力/平方英寸 (psi)', atm: '标准大气压 (atm)', mmHg: '毫米汞柱 (mmHg)' },
factor: { Pa: 1, kPa: 1000, MPa: 1e6, bar: 1e5, psi: 6894.757293168, atm: 101325, mmHg: 133.322387415 }
},
power: {
label: '功率',
units: { W: '瓦 (W)', kW: '千瓦 (kW)', MW: '兆瓦 (MW)', hp_metric: '公制马力 (PS)', hp_imp: '英制马力 (hp)', kcal_h: '千卡/时 (kcal/h)' },
factor: { W: 1, kW: 1000, MW: 1e6, hp_metric: 735.49875, hp_imp: 745.6998715822702, kcal_h: 1.163 }
},
energy: {
label: '能量',
units: { J: '焦耳 (J)', kJ: '千焦 (kJ)', cal: '卡 (cal)', kcal: '千卡 (kcal)', Wh: '瓦时 (Wh)', kWh: '千瓦时 (kWh)', eV: '电子伏 (eV)', BTU: '英热单位 (BTU)' },
factor: { J: 1, kJ: 1000, cal: 4.184, kcal: 4184, Wh: 3600, kWh: 3.6e6, eV: 1.602176634e-19, BTU: 1055.05585262 }
},
force: {
label: '力',
units: { N: '牛顿 (N)', kN: '千牛 (kN)', kgf: '千克力 (kgf)', lbf: '磅力 (lbf)', dyn: '达因 (dyn)' },
factor: { N: 1, kN: 1000, kgf: 9.80665, lbf: 4.4482216152605, dyn: 1e-5 }
},
density: {
label: '密度',
units: { 'kg_m3': '千克/立方米 (kg/m³)', 'g_cm3': '克/立方厘米 (g/cm³)', 'g_L': '克/升 (g/L)', 'kg_L': '千克/升 (kg/L)', 'lb_ft3': '磅/立方英尺 (lb/ft³)', 'lb_in3': '磅/立方英寸 (lb/in³)' },
factor: { 'kg_m3': 1, 'g_cm3': 1000, 'g_L': 1, 'kg_L': 1000, 'lb_ft3': 16.018463373960142, 'lb_in3': 27679.904710203122 }
},
time: {
label: '时间',
units: { ms: '毫秒 (ms)', s: '秒 (s)', min: '分钟 (min)', h: '小时 (h)', day: '天 (day)', week: '周 (week)', month: '月 (平均 30.44 天)', year: '年 (365.25 天)', workday: '工作日 (8 小时)', workweek: '工作周 (5 个工作日)', workmonth: '工作月 (21.75 个工作日)' },
factor: { ms: 0.001, s: 1, min: 60, h: 3600, day: 86400, week: 604800, month: 2629800, year: 31557600, workday: 28800, workweek: 144000, workmonth: 626400 }
},
fuel: {
label: '燃油效率',
units: { l100km: '升/百公里 (L/100km)', kmpl: '公里/升 (km/L)', mpg_us: '英里/加仑(美) (mpg US)', mpg_uk: '英里/加仑(英) (mpg UK)' },
inverse: { l100km: 1, kmpl: 100, mpg_us: 235.2145833, mpg_uk: 282.4809363 }
}
}
const groups = [
{ key: 'basic', label: '基础', cats: ['length', 'weight', 'temperature', 'area', 'volume', 'speed'] },
{ key: 'physics', label: '物理量', cats: ['pressure', 'power', 'energy', 'force', 'density'] },
{ key: 'life', label: '生活换算', cats: ['time', 'fuel'] }
]
const CAT_TIPS = {
time: '工作日折算:1 工作日 = 8 小时,1 工作周 = 5 个工作日,1 工作月 = 21.75 个工作日。',
fuel: '燃油效率为反比关系:L/100km 数值越小越省油,mpg / km-L 数值越大越省油。',
temperature: '温度换算使用公式而非线性系数,0 °C = 32 °F = 273.15 K。'
}
const group = ref('basic')
const cat = ref('length')
const from = ref('m')
const to = ref('km')
const value = ref('')
const error = ref('')
const currentCatKeys = computed(() => (groups.find(g => g.key === group.value) || groups[0]).cats)
const unitOptions = computed(() => cats[cat.value].units)
const catTip = computed(() => CAT_TIPS[cat.value] || '')
watch(group, () => {
const keys = currentCatKeys.value
if (!keys.includes(cat.value)) {
cat.value = keys[0]
onCatChange()
}
})
function onCatChange() {
const us = Object.keys(cats[cat.value].units)
from.value = us[0]
to.value = us[1] || us[0]
convert()
}
function toCelsius(v, u) {
if (u === 'C') return v
if (u === 'F') return (v - 32) * 5 / 9
return v - 273.15
}
function fromCelsius(v, u) {
if (u === 'C') return v
if (u === 'F') return v * 9 / 5 + 32
return v + 273.15
}
// 燃油效率:先统一折算到 L/100km 基准,再折算到目标单位(两个方向公式相同,均为反比)
function fuelSwap(v, u, table) {
if (u === 'l100km') return v
return table[u] / v
}
const result = computed(() => {
error.value = ''
const raw = value.value.trim()
if (raw === '') return null
const num = Number(raw)
if (!isFinite(num)) {
error.value = '请输入有效的数值'
return null
}
const c = cats[cat.value]
if (c.inverse) {
if (num <= 0) {
error.value = '燃油效率必须为大于 0 的数值'
return null
}
const base = fuelSwap(num, from.value, c.inverse)
return fuelSwap(base, to.value, c.inverse)
}
if (c.special) {
return fromCelsius(toCelsius(num, from.value), to.value)
}
return num * c.factor[from.value] / c.factor[to.value]
})
function convert() {
// 触发 computed
void result.value
}
function formatNum(n) {
if (n === null) return ''
if (n === 0) return '0'
const abs = Math.abs(n)
if (abs >= 1e15 || abs < 1e-6) return n.toExponential(6)
return String(Number(n.toFixed(10)))
}2.3 效果截图
