在这里插入图片描述

目录

  1. 概述
  2. 工具功能
  3. 核心实现
  4. Kotlin 源代码
  5. JavaScript 编译代码
  6. ArkTS 调用代码
  7. 实战案例
  8. 最佳实践

概述

本文档介绍如何在 Kotlin Multiplatform (KMP) 鸿蒙跨端开发中实现一个功能完整的长度单位转换工具系统。长度是物理学中的基本量,在日常生活、工程设计、地理测量等领域都有广泛应用。这个工具提供了对多种长度单位的全面转换支持,包括公制单位(毫米、厘米、米、千米)和英制单位(英寸、英尺、码、英里)等,以及长度转换的各种操作和分析。

在实际应用中,长度转换工具广泛应用于以下场景:地图应用、导航系统、建筑设计、工程计算、运动健身、国际贸易等。通过 KMP 框架的跨端能力,我们可以在不同平台上使用相同的长度转换逻辑,确保转换结果的准确性和一致性。

工具的特点

  • 完整的长度单位支持:支持公制和英制单位的相互转换
  • 精确的转换:使用标准的长度转换系数
  • 双向转换:支持任意两种长度单位之间的转换
  • 长度范围检查:检查长度值是否在合理范围内
  • 长度分析:提供长度数据的详细分析
  • 跨端兼容:一份 Kotlin 代码可同时服务多个平台

工具功能

1. 公制长度单位转换

公制长度单位是国际标准单位,基于 10 进制。毫米、厘米、米、千米是最常见的公制长度单位。公制长度转换需要处理小数点精度和单位之间的倍数关系。

  • 毫米到厘米:1 cm = 10 mm
  • 厘米到米:1 m = 100 cm
  • 米到千米:1 km = 1000 m
  • 跨单位转换:支持任意两个公制单位之间的转换

2. 英制长度单位转换

英制长度单位主要在美国和英国使用。英寸、英尺、码、英里是主要的英制长度单位。英制长度转换需要处理复杂的倍数关系。

  • 英寸到英尺:1 ft = 12 in
  • 英尺到码:1 yd = 3 ft
  • 码到英里:1 mi = 1760 yd
  • 跨单位转换:支持任意两个英制单位之间的转换

3. 公制与英制转换

公制和英制之间的转换需要使用标准的转换系数。这对于国际应用很重要。

  • 英寸到厘米:1 in = 2.54 cm
  • 英尺到米:1 ft = 0.3048 m
  • 英里到千米:1 mi = 1.60934 km
  • 精确转换:使用标准的国际转换系数

4. 长度范围检查

长度范围检查是验证长度值是否在合理范围内。不同的应用有不同的长度范围。长度范围检查对于数据质量控制很重要。

  • 正数检查:长度必须为正数
  • 合理范围检查:检查长度是否在常见范围内
  • 单位验证:检查长度单位是否有效
  • 错误报告:提供详细的错误信息

5. 长度描述和分类

长度描述是用自然语言描述长度的大小。长度分类是根据长度范围进行分类。长度描述和分类对于用户界面很有用。

  • 长度等级:极小、很小、小、中等、大、很大、极大
  • 距离描述:根据长度生成距离描述
  • 应用场景:根据长度推荐应用场景
  • 参考对象:提供长度的参考对象

6. 长度统计分析

长度统计分析是对长度数据进行统计和分析。长度统计分析对于工程计算和数据处理很有用。

  • 最大长度:找出最大的长度
  • 最小长度:找出最小的长度
  • 平均长度:计算长度的平均值
  • 长度分布:分析长度的分布

7. 长度转换历史

长度转换历史是记录之前的转换操作。长度转换历史对于用户查看和重复使用很有用。

  • 转换记录:记录所有的转换操作
  • 快速重复:快速重复之前的转换
  • 历史查询:查询之前的转换结果
  • 导出数据:导出转换历史

核心实现

1. 公制长度转换

fun millimeterToMeter(mm: Double): Double = mm / 1000
fun centimeterToMeter(cm: Double): Double = cm / 100
fun kilometerToMeter(km: Double): Double = km * 1000

fun meterToMillimeter(m: Double): Double = m * 1000
fun meterToCentimeter(m: Double): Double = m * 100
fun meterToKilometer(m: Double): Double = m / 1000

fun convertMetric(value: Double, fromUnit: String, toUnit: String): Double {
    val meters = when (fromUnit.lowercase()) {
        "mm" -> millimeterToMeter(value)
        "cm" -> centimeterToMeter(value)
        "m" -> value
        "km" -> kilometerToMeter(value)
        else -> 0.0
    }
    
    return when (toUnit.lowercase()) {
        "mm" -> meterToMillimeter(meters)
        "cm" -> meterToCentimeter(meters)
        "m" -> meters
        "km" -> meterToKilometer(meters)
        else -> 0.0
    }
}

代码说明: 公制长度转换通过米作为标准单位。先将源单位转换为米,再转换为目标单位。这种方法简洁且易于维护。

2. 英制长度转换

fun inchToFoot(inch: Double): Double = inch / 12
fun footToYard(foot: Double): Double = foot / 3
fun yardToMile(yard: Double): Double = yard / 1760

fun footToInch(foot: Double): Double = foot * 12
fun yardToFoot(yard: Double): Double = yard * 3
fun mileToYard(mile: Double): Double = mile * 1760

fun convertImperial(value: Double, fromUnit: String, toUnit: String): Double {
    val feet = when (fromUnit.lowercase()) {
        "in" -> inchToFoot(value)
        "ft" -> value
        "yd" -> yardToFoot(value)
        "mi" -> mileToYard(value) * 3
        else -> 0.0
    }
    
    return when (toUnit.lowercase()) {
        "in" -> footToInch(feet)
        "ft" -> feet
        "yd" -> footToYard(feet)
        "mi" -> feet / (1760 * 3)
        else -> 0.0
    }
}

代码说明: 英制长度转换通过英尺作为标准单位。先将源单位转换为英尺,再转换为目标单位。这种方法处理了英制单位复杂的倍数关系。

3. 公制与英制转换

fun inchToCentimeter(inch: Double): Double = inch * 2.54
fun centimeterToInch(cm: Double): Double = cm / 2.54

fun footToMeter(foot: Double): Double = foot * 0.3048
fun meterToFoot(m: Double): Double = m / 0.3048

fun mileToKilometer(mile: Double): Double = mile * 1.60934
fun kilometerToMile(km: Double): Double = km / 1.60934

fun convertBetweenSystems(value: Double, fromUnit: String, toUnit: String): Double {
    val meters = when (fromUnit.lowercase()) {
        "mm", "cm", "m", "km" -> convertMetric(value, fromUnit, "m")
        "in" -> inchToMeter(value)
        "ft" -> footToMeter(value)
        "yd" -> yardToMeter(value)
        "mi" -> mileToMeter(value)
        else -> 0.0
    }
    
    return when (toUnit.lowercase()) {
        "mm", "cm", "m", "km" -> convertMetric(meters, "m", toUnit)
        "in" -> meterToInch(meters)
        "ft" -> meterToFoot(meters)
        "yd" -> meterToYard(meters)
        "mi" -> meterToMile(meters)
        else -> 0.0
    }
}

代码说明: 公制与英制转换通过米作为中间单位。先将源单位转换为米,再转换为目标单位。这种方法统一了两个单位系统的转换。

4. 长度描述

fun describeLength(meters: Double): String {
    return when {
        meters < 0.001 -> "极小,微观级别"
        meters < 0.01 -> "很小,毫米级别"
        meters < 0.1 -> "小,厘米级别"
        meters < 1 -> "中等,分米级别"
        meters < 10 -> "大,米级别"
        meters < 100 -> "很大,十米级别"
        meters < 1000 -> "极大,百米级别"
        else -> "超大,千米级别"
    }
}

fun getLengthEmoji(meters: Double): String {
    return when {
        meters < 0.01 -> "🔬"
        meters < 0.1 -> "📏"
        meters < 1 -> "📐"
        meters < 10 -> "🚪"
        meters < 100 -> "🏠"
        meters < 1000 -> "🏘️"
        else -> "🌍"
    }
}

代码说明: 长度描述根据米的范围提供自然语言描述。通过使用 emoji,可以提供更加直观的长度表示。

5. 长度统计分析

fun analyzeLengths(lengths: List<Double>, unit: String): Map<String, Any> {
    if (lengths.isEmpty()) return mapOf("error" to "长度列表为空")
    
    val stats = mutableMapOf<String, Any>()
    stats["count"] = lengths.size
    stats["max"] = lengths.maxOrNull() ?: 0.0
    stats["min"] = lengths.minOrNull() ?: 0.0
    stats["average"] = String.format("%.2f", lengths.average())
    
    val sorted = lengths.sorted()
    stats["median"] = if (lengths.size % 2 == 0) {
        (sorted[lengths.size / 2 - 1] + sorted[lengths.size / 2]) / 2
    } else {
        sorted[lengths.size / 2]
    }
    
    stats["unit"] = unit
    
    return stats
}

代码说明: 长度统计分析计算多个统计指标,包括最大值、最小值、平均值、中位数等。这对于分析长度数据很有用。


Kotlin 源代码

// LengthConverter.kt

class LengthConverter {
    
    // 公制转换
    fun millimeterToMeter(mm: Double): Double = mm / 1000
    fun centimeterToMeter(cm: Double): Double = cm / 100
    fun kilometerToMeter(km: Double): Double = km * 1000
    
    fun meterToMillimeter(m: Double): Double = m * 1000
    fun meterToCentimeter(m: Double): Double = m * 100
    fun meterToKilometer(m: Double): Double = m / 1000
    
    // 英制转换
    fun inchToFoot(inch: Double): Double = inch / 12
    fun footToYard(foot: Double): Double = foot / 3
    fun yardToMile(yard: Double): Double = yard / 1760
    
    fun footToInch(foot: Double): Double = foot * 12
    fun yardToFoot(yard: Double): Double = yard * 3
    fun mileToYard(mile: Double): Double = mile * 1760
    
    // 公制与英制转换
    fun inchToCentimeter(inch: Double): Double = inch * 2.54
    fun centimeterToInch(cm: Double): Double = cm / 2.54
    
    fun footToMeter(foot: Double): Double = foot * 0.3048
    fun meterToFoot(m: Double): Double = m / 0.3048
    
    fun mileToKilometer(mile: Double): Double = mile * 1.60934
    fun kilometerToMile(km: Double): Double = km / 1.60934
    
    fun inchToMeter(inch: Double): Double = inchToCentimeter(inch) / 100
    fun meterToInch(m: Double): Double = centimeterToInch(m * 100)
    
    fun yardToMeter(yard: Double): Double = footToMeter(yardToFoot(yard))
    fun meterToYard(m: Double): Double = footToYard(meterToFoot(m))
    
    fun mileToMeter(mile: Double): Double = kilometerToMeter(mileToKilometer(mile))
    fun meterToMile(m: Double): Double = kilometerToMile(meterToKilometer(m))
    
    fun convertMetric(value: Double, fromUnit: String, toUnit: String): Double {
        val meters = when (fromUnit.lowercase()) {
            "mm" -> millimeterToMeter(value)
            "cm" -> centimeterToMeter(value)
            "m" -> value
            "km" -> kilometerToMeter(value)
            else -> 0.0
        }
        
        return when (toUnit.lowercase()) {
            "mm" -> meterToMillimeter(meters)
            "cm" -> meterToCentimeter(meters)
            "m" -> meters
            "km" -> meterToKilometer(meters)
            else -> 0.0
        }
    }
    
    fun convertImperial(value: Double, fromUnit: String, toUnit: String): Double {
        val feet = when (fromUnit.lowercase()) {
            "in" -> inchToFoot(value)
            "ft" -> value
            "yd" -> yardToFoot(value)
            "mi" -> mileToYard(value) * 3
            else -> 0.0
        }
        
        return when (toUnit.lowercase()) {
            "in" -> footToInch(feet)
            "ft" -> feet
            "yd" -> footToYard(feet)
            "mi" -> feet / (1760 * 3)
            else -> 0.0
        }
    }
    
    fun convertBetweenSystems(value: Double, fromUnit: String, toUnit: String): Double {
        val meters = when (fromUnit.lowercase()) {
            "mm", "cm", "m", "km" -> convertMetric(value, fromUnit, "m")
            "in" -> inchToMeter(value)
            "ft" -> footToMeter(value)
            "yd" -> yardToMeter(value)
            "mi" -> mileToMeter(value)
            else -> 0.0
        }
        
        return when (toUnit.lowercase()) {
            "mm", "cm", "m", "km" -> convertMetric(meters, "m", toUnit)
            "in" -> meterToInch(meters)
            "ft" -> meterToFoot(meters)
            "yd" -> meterToYard(meters)
            "mi" -> meterToMile(meters)
            else -> 0.0
        }
    }
    
    fun validateLength(length: Double): Pair<Boolean, String> {
        return if (length < 0) {
            Pair(false, "长度不能为负数")
        } else {
            Pair(true, "长度有效")
        }
    }
    
    fun describeLength(meters: Double): String {
        return when {
            meters < 0.001 -> "极小,微观级别"
            meters < 0.01 -> "很小,毫米级别"
            meters < 0.1 -> "小,厘米级别"
            meters < 1 -> "中等,分米级别"
            meters < 10 -> "大,米级别"
            meters < 100 -> "很大,十米级别"
            meters < 1000 -> "极大,百米级别"
            else -> "超大,千米级别"
        }
    }
    
    fun getLengthEmoji(meters: Double): String {
        return when {
            meters < 0.01 -> "🔬"
            meters < 0.1 -> "📏"
            meters < 1 -> "📐"
            meters < 10 -> "🚪"
            meters < 100 -> "🏠"
            meters < 1000 -> "🏘️"
            else -> "🌍"
        }
    }
    
    fun analyzeLengths(lengths: List<Double>, unit: String): Map<String, Any> {
        if (lengths.isEmpty()) return mapOf("error" to "长度列表为空")
        
        val stats = mutableMapOf<String, Any>()
        stats["count"] = lengths.size
        stats["max"] = lengths.maxOrNull() ?: 0.0
        stats["min"] = lengths.minOrNull() ?: 0.0
        stats["average"] = String.format("%.2f", lengths.average())
        
        val sorted = lengths.sorted()
        stats["median"] = if (lengths.size % 2 == 0) {
            (sorted[lengths.size / 2 - 1] + sorted[lengths.size / 2]) / 2
        } else {
            sorted[lengths.size / 2]
        }
        
        stats["unit"] = unit
        
        return stats
    }
    
    fun formatLength(length: Double, unit: String, decimals: Int = 2): String {
        return String.format("%.${decimals}f $unit", length)
    }
    
    fun getUnitInfo(unit: String): Map<String, String> {
        return when (unit.lowercase()) {
            "mm" -> mapOf("name" to "毫米", "system" to "公制", "symbol" to "mm")
            "cm" -> mapOf("name" to "厘米", "system" to "公制", "symbol" to "cm")
            "m" -> mapOf("name" to "米", "system" to "公制", "symbol" to "m")
            "km" -> mapOf("name" to "千米", "system" to "公制", "symbol" to "km")
            "in" -> mapOf("name" to "英寸", "system" to "英制", "symbol" to "in")
            "ft" -> mapOf("name" to "英尺", "system" to "英制", "symbol" to "ft")
            "yd" -> mapOf("name" to "码", "system" to "英制", "symbol" to "yd")
            "mi" -> mapOf("name" to "英里", "system" to "英制", "symbol" to "mi")
            else -> mapOf("error" to "不支持的长度单位")
        }
    }
}

fun main() {
    val converter = LengthConverter()
    
    println("=== 长度单位转换工具演示 ===\n")
    
    // 公制转换
    val cm = 100.0
    println("$cm cm 转换:")
    println("  米: ${converter.convertMetric(cm, "cm", "m")} m")
    println("  毫米: ${converter.convertMetric(cm, "cm", "mm")} mm\n")
    
    // 英制转换
    val ft = 10.0
    println("$ft ft 转换:")
    println("  英寸: ${converter.convertImperial(ft, "ft", "in")} in")
    println("  码: ${converter.convertImperial(ft, "ft", "yd")} yd\n")
    
    // 公制与英制转换
    println("100 cm 转英寸: ${converter.convertBetweenSystems(100.0, "cm", "in")} in")
    println("10 ft 转米: ${converter.convertBetweenSystems(10.0, "ft", "m")} m\n")
    
    // 长度描述
    val meters = converter.convertMetric(100.0, "cm", "m")
    println("${meters}m 的描述: ${converter.describeLength(meters)} ${converter.getLengthEmoji(meters)}")
}

Kotlin 代码说明: 这个实现提供了完整的长度转换功能。LengthConverter 类包含了公制转换、英制转换、系统间转换、验证、描述、分析等多个方法。通过使用标准的长度转换系数,确保了转换的准确性。


JavaScript 编译代码

// LengthConverter.js
class LengthConverter {
    // 公制转换
    millimeterToMeter(mm) { return mm / 1000; }
    centimeterToMeter(cm) { return cm / 100; }
    kilometerToMeter(km) { return km * 1000; }
    
    meterToMillimeter(m) { return m * 1000; }
    meterToCentimeter(m) { return m * 100; }
    meterToKilometer(m) { return m / 1000; }
    
    // 英制转换
    inchToFoot(inch) { return inch / 12; }
    footToYard(foot) { return foot / 3; }
    yardToMile(yard) { return yard / 1760; }
    
    footToInch(foot) { return foot * 12; }
    yardToFoot(yard) { return yard * 3; }
    mileToYard(mile) { return mile * 1760; }
    
    // 公制与英制转换
    inchToCentimeter(inch) { return inch * 2.54; }
    centimeterToInch(cm) { return cm / 2.54; }
    
    footToMeter(foot) { return foot * 0.3048; }
    meterToFoot(m) { return m / 0.3048; }
    
    mileToKilometer(mile) { return mile * 1.60934; }
    kilometerToMile(km) { return km / 1.60934; }
    
    inchToMeter(inch) { return this.inchToCentimeter(inch) / 100; }
    meterToInch(m) { return this.centimeterToInch(m * 100); }
    
    yardToMeter(yard) { return this.footToMeter(this.yardToFoot(yard)); }
    meterToYard(m) { return this.footToYard(this.meterToFoot(m)); }
    
    mileToMeter(mile) { return this.kilometerToMeter(this.mileToKilometer(mile)); }
    meterToMile(m) { return this.kilometerToMile(this.meterToKilometer(m)); }
    
    convertMetric(value, fromUnit, toUnit) {
        let meters;
        switch (fromUnit.toLowerCase()) {
            case "mm": meters = this.millimeterToMeter(value); break;
            case "cm": meters = this.centimeterToMeter(value); break;
            case "m": meters = value; break;
            case "km": meters = this.kilometerToMeter(value); break;
            default: meters = 0;
        }
        
        switch (toUnit.toLowerCase()) {
            case "mm": return this.meterToMillimeter(meters);
            case "cm": return this.meterToCentimeter(meters);
            case "m": return meters;
            case "km": return this.meterToKilometer(meters);
            default: return 0;
        }
    }
    
    convertImperial(value, fromUnit, toUnit) {
        let feet;
        switch (fromUnit.toLowerCase()) {
            case "in": feet = this.inchToFoot(value); break;
            case "ft": feet = value; break;
            case "yd": feet = this.yardToFoot(value); break;
            case "mi": feet = this.mileToYard(value) * 3; break;
            default: feet = 0;
        }
        
        switch (toUnit.toLowerCase()) {
            case "in": return this.footToInch(feet);
            case "ft": return feet;
            case "yd": return this.footToYard(feet);
            case "mi": return feet / (1760 * 3);
            default: return 0;
        }
    }
    
    convertBetweenSystems(value, fromUnit, toUnit) {
        let meters;
        switch (fromUnit.toLowerCase()) {
            case "mm":
            case "cm":
            case "m":
            case "km":
                meters = this.convertMetric(value, fromUnit, "m");
                break;
            case "in": meters = this.inchToMeter(value); break;
            case "ft": meters = this.footToMeter(value); break;
            case "yd": meters = this.yardToMeter(value); break;
            case "mi": meters = this.mileToMeter(value); break;
            default: meters = 0;
        }
        
        switch (toUnit.toLowerCase()) {
            case "mm":
            case "cm":
            case "m":
            case "km":
                return this.convertMetric(meters, "m", toUnit);
            case "in": return this.meterToInch(meters);
            case "ft": return this.meterToFoot(meters);
            case "yd": return this.meterToYard(meters);
            case "mi": return this.meterToMile(meters);
            default: return 0;
        }
    }
    
    validateLength(length) {
        if (length < 0) {
            return { valid: false, message: "长度不能为负数" };
        }
        return { valid: true, message: "长度有效" };
    }
    
    describeLength(meters) {
        if (meters < 0.001) return "极小,微观级别";
        if (meters < 0.01) return "很小,毫米级别";
        if (meters < 0.1) return "小,厘米级别";
        if (meters < 1) return "中等,分米级别";
        if (meters < 10) return "大,米级别";
        if (meters < 100) return "很大,十米级别";
        if (meters < 1000) return "极大,百米级别";
        return "超大,千米级别";
    }
    
    getLengthEmoji(meters) {
        if (meters < 0.01) return "🔬";
        if (meters < 0.1) return "📏";
        if (meters < 1) return "📐";
        if (meters < 10) return "🚪";
        if (meters < 100) return "🏠";
        if (meters < 1000) return "🏘️";
        return "🌍";
    }
    
    analyzeLengths(lengths, unit) {
        if (lengths.length === 0) return { error: "长度列表为空" };
        
        const stats = {};
        stats.count = lengths.length;
        stats.max = Math.max(...lengths);
        stats.min = Math.min(...lengths);
        stats.average = (lengths.reduce((a, b) => a + b, 0) / lengths.length).toFixed(2);
        
        const sorted = [...lengths].sort((a, b) => a - b);
        stats.median = lengths.length % 2 === 0 ?
            (sorted[lengths.length / 2 - 1] + sorted[lengths.length / 2]) / 2 :
            sorted[Math.floor(lengths.length / 2)];
        
        stats.unit = unit;
        
        return stats;
    }
    
    formatLength(length, unit, decimals = 2) {
        return length.toFixed(decimals) + " " + unit;
    }
    
    getUnitInfo(unit) {
        switch (unit.toLowerCase()) {
            case "mm": return { name: "毫米", system: "公制", symbol: "mm" };
            case "cm": return { name: "厘米", system: "公制", symbol: "cm" };
            case "m": return { name: "米", system: "公制", symbol: "m" };
            case "km": return { name: "千米", system: "公制", symbol: "km" };
            case "in": return { name: "英寸", system: "英制", symbol: "in" };
            case "ft": return { name: "英尺", system: "英制", symbol: "ft" };
            case "yd": return { name: "码", system: "英制", symbol: "yd" };
            case "mi": return { name: "英里", system: "英制", symbol: "mi" };
            default: return { error: "不支持的长度单位" };
        }
    }
}

// 使用示例
const converter = new LengthConverter();

console.log("=== 长度单位转换工具演示 ===\n");

const cm = 100;
console.log(`${cm} cm 转换:`);
console.log("  米:", converter.convertMetric(cm, "cm", "m"), "m");
console.log("  毫米:", converter.convertMetric(cm, "cm", "mm"), "mm");

const ft = 10;
console.log(`\n${ft} ft 转换:`);
console.log("  英寸:", converter.convertImperial(ft, "ft", "in"), "in");
console.log("  码:", converter.convertImperial(ft, "ft", "yd"), "yd");

console.log("\n100 cm 转英寸:", converter.convertBetweenSystems(100, "cm", "in"), "in");
console.log("10 ft 转米:", converter.convertBetweenSystems(10, "ft", "m"), "m");

const meters = converter.convertMetric(100, "cm", "m");
console.log(`\n${meters}m 的描述: ${converter.describeLength(meters)} ${converter.getLengthEmoji(meters)}`);

JavaScript 代码说明: JavaScript 版本是 Kotlin 代码的直接转译。由于 JavaScript 和 Kotlin 在语法上有差异,我们使用 switch 语句替代 when 表达式。整体逻辑和算法与 Kotlin 版本保持一致。


ArkTS 调用代码

// LengthConverterPage.ets
import { LengthConverter } from './LengthConverter';

@Entry
@Component
struct LengthConverterPage {
    @State inputValue: string = '100';
    @State fromUnit: string = 'cm';
    @State toUnit: string = 'in';
    @State result: string = '';
    @State showResult: boolean = false;
    @State isLoading: boolean = false;
    @State operationType: string = 'convert';
    
    private converter: LengthConverter = new LengthConverter();
    
    private unitOptions = [
        { label: '毫米 (mm)', value: 'mm' },
        { label: '厘米 (cm)', value: 'cm' },
        { label: '米 (m)', value: 'm' },
        { label: '千米 (km)', value: 'km' },
        { label: '英寸 (in)', value: 'in' },
        { label: '英尺 (ft)', value: 'ft' },
        { label: '码 (yd)', value: 'yd' },
        { label: '英里 (mi)', value: 'mi' }
    ];
    
    private operationOptions = [
        { label: '长度转换', value: 'convert' },
        { label: '长度验证', value: 'validate' },
        { label: '长度描述', value: 'describe' },
        { label: '单位信息', value: 'info' }
    ];
    
    performOperation() {
        this.isLoading = true;
        try {
            let resultText = '';
            const length = parseFloat(this.inputValue);
            
            switch (this.operationType) {
                case 'convert':
                    const convertResult = this.converter.convertBetweenSystems(length, this.fromUnit, this.toUnit);
                    resultText = `${length} ${this.fromUnit} = ${convertResult.toFixed(4)} ${this.toUnit}`;
                    break;
                case 'validate':
                    const validation = this.converter.validateLength(length);
                    resultText = validation.valid ? '✓ ' + validation.message : '✗ ' + validation.message;
                    break;
                case 'describe':
                    let meters = length;
                    if (this.fromUnit !== 'm') {
                        meters = this.converter.convertBetweenSystems(length, this.fromUnit, 'm');
                    }
                    const description = this.converter.describeLength(meters);
                    const emoji = this.converter.getLengthEmoji(meters);
                    resultText = `${emoji} ${description}`;
                    break;
                case 'info':
                    const info = this.converter.getUnitInfo(this.fromUnit);
                    resultText = `📊 ${info.name} 信息\n`;
                    resultText += `━━━━━━━━━━━━━━━━━━━━━\n`;
                    resultText += `符号: ${info.symbol}\n`;
                    resultText += `系统: ${info.system}`;
                    break;
                default:
                    resultText = '未知操作';
            }
            
            this.result = resultText;
            this.showResult = true;
        } catch (error) {
            this.result = '操作失败: ' + (error instanceof Error ? error.message : String(error));
            this.showResult = true;
        } finally {
            this.isLoading = false;
        }
    }
    
    build() {
        Column() {
            // 标题
            Text('长度单位转换工具')
                .fontSize(28)
                .fontWeight(FontWeight.Bold)
                .margin({ top: 20, bottom: 20 })
                .textAlign(TextAlign.Center)
                .width('100%')
            
            // 操作类型选择
            Column() {
                Text('操作类型')
                    .fontSize(14)
                    .fontColor('#666666')
                    .margin({ bottom: 10 })
                
                Select(this.operationOptions)
                    .value(this.operationType)
                    .onSelect((index: number, value?: string) => {
                        this.operationType = value || 'convert';
                    })
                    .width('100%')
                    .height(40)
            }
            .width('100%')
            .padding(15)
            .backgroundColor('#ffffff')
            .borderRadius(10)
            .border({ width: 1, color: '#eeeeee' })
            .margin({ bottom: 20 })
            
            // 长度单位选择
            Row() {
                Column() {
                    Text('源单位')
                        .fontSize(12)
                        .fontColor('#666666')
                        .margin({ bottom: 8 })
                    
                    Select(this.unitOptions)
                        .value(this.fromUnit)
                        .onSelect((index: number, value?: string) => {
                            this.fromUnit = value || 'cm';
                        })
                        .width('100%')
                        .height(40)
                }
                .width('48%')
                
                Text('→')
                    .fontSize(20)
                    .fontWeight(FontWeight.Bold)
                    .width('4%')
                    .textAlign(TextAlign.Center)
                
                Column() {
                    Text('目标单位')
                        .fontSize(12)
                        .fontColor('#666666')
                        .margin({ bottom: 8 })
                    
                    Select(this.unitOptions)
                        .value(this.toUnit)
                        .onSelect((index: number, value?: string) => {
                            this.toUnit = value || 'in';
                        })
                        .width('100%')
                        .height(40)
                }
                .width('48%')
            }
            .width('100%')
            .padding(15)
            .backgroundColor('#ffffff')
            .borderRadius(10)
            .border({ width: 1, color: '#eeeeee' })
            .margin({ bottom: 20 })
            
            // 输入框
            Column() {
                Text('输入长度值')
                    .fontSize(14)
                    .fontColor('#666666')
                    .margin({ bottom: 10 })
                
                TextInput({ placeholder: '输入长度值' })
                    .value(this.inputValue)
                    .onChange((value: string) => {
                        this.inputValue = value;
                    })
                    .width('100%')
                    .height(45)
                    .padding({ left: 10, right: 10 })
                    .border({ width: 1, color: '#cccccc', radius: 8 })
                    .fontSize(14)
            }
            .width('100%')
            .padding(15)
            .backgroundColor('#ffffff')
            .borderRadius(10)
            .border({ width: 1, color: '#eeeeee' })
            .margin({ bottom: 20 })
            
            // 操作按钮
            Button('执行操作')
                .width('100%')
                .height(45)
                .fontSize(16)
                .fontWeight(FontWeight.Bold)
                .backgroundColor('#1B7837')
                .fontColor('#ffffff')
                .onClick(() => {
                    this.performOperation();
                })
                .margin({ bottom: 20 })
            
            // 结果显示
            if (this.showResult) {
                Column() {
                    Text('结果')
                        .fontSize(16)
                        .fontWeight(FontWeight.Bold)
                        .fontColor('#FFFFFF')
                        .width('100%')
                        .padding(12)
                        .backgroundColor('#1B7837')
                        .borderRadius(8)
                        .margin({ bottom: 12 })
                    
                    Scroll() {
                        Text(this.result)
                            .fontSize(14)
                            .fontColor('#333333')
                            .width('100%')
                            .padding(12)
                            .backgroundColor('#f9f9f9')
                            .borderRadius(6)
                            .textAlign(TextAlign.Start)
                            .selectable(true)
                    }
                    .width('100%')
                    .height(120)
                }
                .width('100%')
                .padding(15)
                .backgroundColor('#ffffff')
                .borderRadius(10)
                .border({ width: 1, color: '#eeeeee' })
            }
            
            Blank()
        }
        .width('100%')
        .height('100%')
        .padding(15)
        .backgroundColor('#f5f5f5')
        .scrollable(ScrollDirection.Vertical)
    }
}

ArkTS 代码说明: ArkTS 调用代码展示了如何在 OpenHarmony 应用中使用长度转换工具。页面包含操作类型选择、源单位和目标单位选择、输入框、操作按钮和结果显示等功能。通过 @State 装饰器管理状态,实现了完整的用户交互流程。用户可以选择操作类型和长度单位,输入长度值,然后点击执行按钮获得结果。


实战案例

案例1:地图应用

在地图应用中,需要根据用户所在地区显示不同的距离单位。

fun displayDistance(meters: Double, region: String): Map<String, String> {
    val converter = LengthConverter()
    
    return when (region) {
        "US" -> mapOf(
            "distance" to converter.formatLength(converter.meterToFoot(meters), "ft"),
            "description" to converter.describeLength(meters),
            "emoji" to converter.getLengthEmoji(meters)
        )
        "UK" -> mapOf(
            "distance" to converter.formatLength(converter.meterToMile(meters), "mi"),
            "description" to converter.describeLength(meters),
            "emoji" to converter.getLengthEmoji(meters)
        )
        else -> mapOf(
            "distance" to converter.formatLength(meters, "m"),
            "description" to converter.describeLength(meters),
            "emoji" to converter.getLengthEmoji(meters)
        )
    }
}

案例2:建筑设计

在建筑设计中,需要将设计尺寸从公制转换为英制。

fun convertBlueprintDimensions(millimeters: Double): Map<String, String> {
    val converter = LengthConverter()
    
    val inches = converter.convertBetweenSystems(millimeters, "mm", "in")
    val feet = converter.convertBetweenSystems(millimeters, "mm", "ft")
    
    return mapOf(
        "millimeters" to converter.formatLength(millimeters, "mm"),
        "inches" to converter.formatLength(inches, "in"),
        "feet" to converter.formatLength(feet, "ft"),
        "description" to converter.describeLength(converter.convertMetric(millimeters, "mm", "m"))
    )
}

案例3:运动健身

在运动健身应用中,需要记录和转换运动距离。

fun trackRunningDistance(kilometers: Double): Map<String, Any> {
    val converter = LengthConverter()
    
    val miles = converter.convertBetweenSystems(kilometers, "km", "mi")
    val meters = converter.convertMetric(kilometers, "km", "m")
    
    return mapOf(
        "kilometers" to kilometers,
        "miles" to miles,
        "meters" to meters,
        "description" to converter.describeLength(meters),
        "emoji" to converter.getLengthEmoji(meters)
    )
}

最佳实践

1. 单位验证

始终验证长度值是否为正数。长度不能为负数。

2. 精度管理

根据应用需求选择合适的精度。建筑应用需要更高的精度。

3. 单位明确

始终明确显示长度单位,避免用户混淆。

4. 系统一致

在同一应用中保持长度单位的一致性。

5. 用户体验

提供长度描述和 emoji,提高用户体验。

6. 错误处理

提供清晰的错误消息,帮助用户理解问题。


总结

长度单位转换工具是现代应用开发中的重要组件。通过 KMP 框架,我们可以创建一个跨端的长度转换系统,在 Kotlin、JavaScript 和 ArkTS 中使用相同的转换逻辑。这不仅提高了代码的可维护性,还确保了不同平台上转换结果的一致性。

在实际应用中,合理使用长度转换工具可以提高应用的国际化程度和用户体验。无论是地图应用、建筑设计还是运动健身,长度转换工具都能发挥重要作用。通过提供完整的长度转换功能和人性化的长度描述,我们可以帮助用户更好地理解和使用长度数据。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐