在这里插入图片描述

文章概述

正则表达式(Regular Expression, Regex)是现代编程中最强大的文本处理工具之一。从数据验证到文本提取,从格式检查到内容替换,正则表达式无处不在。然而,正则表达式的语法复杂,调试困难,开发者经常需要一套工具来测试和验证正则表达式的正确性。

正则表达式工具在实际应用中有广泛的用途。在数据验证中,需要验证邮箱、电话号码、身份证等格式。在文本处理中,需要提取和替换特定模式的文本。在日志分析中,需要解析和提取日志中的信息。在数据清洗中,需要识别和处理异常数据。在内容过滤中,需要识别和过滤不适当的内容。

本文将深入探讨如何在KMP(Kotlin Multiplatform)框架下实现一套完整的正则表达式测试和验证工具,并展示如何在OpenHarmony鸿蒙平台上进行跨端调用。我们将提供多种正则表达式处理功能,包括匹配测试、提取、替换、分割等,帮助开发者高效处理正则表达式。

工具功能详解

核心功能

功能1:正则表达式匹配(Regex Matching)

测试字符串是否与正则表达式匹配。这是最基础的功能,用于验证字符串格式。

功能特点

  • 支持完全匹配和部分匹配
  • 支持大小写敏感/不敏感
  • 支持多行模式
  • 提供详细的匹配信息
功能2:正则表达式提取(Regex Extraction)

从字符串中提取与正则表达式匹配的部分。这对于数据提取非常重要。

功能特点

  • 支持单个匹配和多个匹配
  • 支持捕获组提取
  • 支持嵌套捕获
  • 返回详细的匹配位置
功能3:正则表达式替换(Regex Replacement)

使用替换字符串替换匹配的部分。这用于文本转换和格式化。

功能特点

  • 支持全局替换和单个替换
  • 支持捕获组引用
  • 支持函数式替换
  • 保留未匹配部分
功能4:正则表达式分割(Regex Splitting)

使用正则表达式作为分隔符分割字符串。这用于字符串解析。

功能特点

  • 支持多个分隔符
  • 支持限制分割次数
  • 支持保留分隔符
  • 处理空字符串
功能5:正则表达式验证(Regex Validation)

验证常见的数据格式,如邮箱、电话号码、URL等。

功能特点

  • 内置常见格式验证
  • 支持自定义验证规则
  • 提供详细的验证结果
  • 支持国际化格式

Kotlin实现

完整的Kotlin代码实现

/**
 * 正则表达式测试和验证工具 - KMP OpenHarmony
 * 提供正则表达式处理的多种功能
 */
object RegexToolUtils {
    
    /**
     * 功能1:正则表达式匹配
     * 测试字符串是否与正则表达式匹配
     */
    fun matches(pattern: String, text: String, ignoreCase: Boolean = false): Pair<Boolean, String> {
        return try {
            val regex = if (ignoreCase) {
                Regex(pattern, RegexOption.IGNORE_CASE)
            } else {
                Regex(pattern)
            }
            
            val isMatch = regex.containsMatchIn(text)
            val message = if (isMatch) "匹配成功" else "未找到匹配"
            
            Pair(isMatch, message)
        } catch (e: Exception) {
            Pair(false, "正则表达式错误:${e.message}")
        }
    }
    
    /**
     * 功能2:正则表达式提取
     * 从字符串中提取匹配的部分
     */
    fun extract(pattern: String, text: String, ignoreCase: Boolean = false): List<String> {
        return try {
            val regex = if (ignoreCase) {
                Regex(pattern, RegexOption.IGNORE_CASE)
            } else {
                Regex(pattern)
            }
            
            regex.findAll(text).map { it.value }.toList()
        } catch (e: Exception) {
            listOf("提取失败:${e.message}")
        }
    }
    
    /**
     * 功能3:正则表达式替换
     * 使用替换字符串替换匹配的部分
     */
    fun replace(pattern: String, text: String, replacement: String, 
                ignoreCase: Boolean = false, replaceAll: Boolean = true): String {
        return try {
            val regex = if (ignoreCase) {
                Regex(pattern, RegexOption.IGNORE_CASE)
            } else {
                Regex(pattern)
            }
            
            if (replaceAll) {
                regex.replace(text, replacement)
            } else {
                regex.replaceFirst(text, replacement)
            }
        } catch (e: Exception) {
            "替换失败:${e.message}"
        }
    }
    
    /**
     * 功能4:正则表达式分割
     * 使用正则表达式作为分隔符分割字符串
     */
    fun split(pattern: String, text: String, limit: Int = -1): List<String> {
        return try {
            val regex = Regex(pattern)
            if (limit > 0) {
                regex.split(text, limit)
            } else {
                regex.split(text)
            }
        } catch (e: Exception) {
            listOf("分割失败:${e.message}")
        }
    }
    
    /**
     * 功能5:正则表达式验证
     * 验证常见的数据格式
     */
    fun validate(type: String, text: String): Pair<Boolean, String> {
        val patterns = mapOf(
            "email" to "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$",
            "phone" to "^1[3-9]\\d{9}$",
            "url" to "^https?://[A-Za-z0-9.-]+\\.[A-Za-z]{2,}",
            "ipv4" to "^(\\d{1,3}\\.){3}\\d{1,3}$",
            "id_card" to "^\\d{18}|\\d{17}[X|x]$",
            "username" to "^[A-Za-z0-9_]{3,16}$",
            "password" to "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$",
            "date" to "^\\d{4}-\\d{2}-\\d{2}$"
        )
        
        val pattern = patterns[type] ?: return Pair(false, "未知的验证类型:$type")
        
        return try {
            val regex = Regex(pattern)
            val isValid = regex.matches(text)
            val message = if (isValid) "验证成功" else "验证失败"
            
            Pair(isValid, message)
        } catch (e: Exception) {
            Pair(false, "验证错误:${e.message}")
        }
    }
    
    /**
     * 获取正则表达式统计信息
     */
    fun getRegexStats(pattern: String, text: String): Map<String, Any> {
        val stats = mutableMapOf<String, Any>()
        
        try {
            val regex = Regex(pattern)
            val matches = regex.findAll(text).toList()
            
            stats["模式"] = pattern
            stats["文本长度"] = text.length
            stats["匹配次数"] = matches.size
            stats["匹配内容"] = matches.map { it.value }
            
            if (matches.isNotEmpty()) {
                stats["第一个匹配"] = matches[0].value
                stats["第一个匹配位置"] = matches[0].range.first
            }
        } catch (e: Exception) {
            stats["错误"] = e.message ?: "未知错误"
        }
        
        return stats
    }
    
    /**
     * 常见正则表达式模板
     */
    fun getCommonPatterns(): Map<String, String> {
        return mapOf(
            "邮箱" to "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$",
            "手机号" to "^1[3-9]\\d{9}$",
            "URL" to "^https?://[A-Za-z0-9.-]+\\.[A-Za-z]{2,}",
            "IPv4地址" to "^(\\d{1,3}\\.){3}\\d{1,3}$",
            "身份证" to "^\\d{18}|\\d{17}[X|x]$",
            "用户名" to "^[A-Za-z0-9_]{3,16}$",
            "密码" to "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$",
            "日期" to "^\\d{4}-\\d{2}-\\d{2}$",
            "十六进制颜色" to "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$",
            "整数" to "^-?\\d+$"
        )
    }
}

// 使用示例
fun main() {
    println("KMP OpenHarmony 正则表达式工具演示\n")
    
    val testCases = listOf(
        Triple("邮箱验证", "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$", "user@example.com"),
        Triple("电话号码", "^1[3-9]\\d{9}$", "13812345678"),
        Triple("提取数字", "\\d+", "abc123def456ghi789"),
        Triple("URL验证", "^https?://", "https://www.example.com")
    )
    
    for ((name, pattern, text) in testCases) {
        println("测试:$name")
        println("模式:$pattern")
        println("文本:$text")
        
        val (isMatch, message) = RegexToolUtils.matches(pattern, text)
        println("结果:$message\n")
    }
    
    // 显示常见模板
    println("常见正则表达式模板:")
    RegexToolUtils.getCommonPatterns().forEach { (name, pattern) ->
        println("  $name: $pattern")
    }
}

Kotlin实现的详细说明

Kotlin实现提供了五个核心功能。正则表达式匹配通过Regex类检查字符串是否匹配。正则表达式提取使用findAll方法获取所有匹配。正则表达式替换使用replace和replaceFirst方法。正则表达式分割使用split方法。正则表达式验证提供了常见格式的预定义模式。

JavaScript实现

完整的JavaScript代码实现

/**
 * 正则表达式测试和验证工具 - JavaScript版本
 */
class RegexToolJS {
    /**
     * 功能1:正则表达式匹配
     */
    static matches(pattern, text, ignoreCase = false) {
        try {
            const flags = ignoreCase ? 'gi' : 'g';
            const regex = new RegExp(pattern, flags);
            const isMatch = regex.test(text);
            const message = isMatch ? '匹配成功' : '未找到匹配';
            
            return { success: isMatch, message: message };
        } catch (e) {
            return { success: false, message: `正则表达式错误:${e.message}` };
        }
    }
    
    /**
     * 功能2:正则表达式提取
     */
    static extract(pattern, text, ignoreCase = false) {
        try {
            const flags = ignoreCase ? 'gi' : 'g';
            const regex = new RegExp(pattern, flags);
            const matches = text.match(regex);
            
            return matches || [];
        } catch (e) {
            return [`提取失败:${e.message}`];
        }
    }
    
    /**
     * 功能3:正则表达式替换
     */
    static replace(pattern, text, replacement, ignoreCase = false, replaceAll = true) {
        try {
            const flags = ignoreCase ? 'gi' : 'g';
            const regex = new RegExp(pattern, replaceAll ? flags : ignoreCase ? 'i' : '');
            
            return text.replace(regex, replacement);
        } catch (e) {
            return `替换失败:${e.message}`;
        }
    }
    
    /**
     * 功能4:正则表达式分割
     */
    static split(pattern, text, limit = -1) {
        try {
            const regex = new RegExp(pattern);
            const result = text.split(regex);
            
            if (limit > 0) {
                return result.slice(0, limit);
            }
            return result;
        } catch (e) {
            return [`分割失败:${e.message}`];
        }
    }
    
    /**
     * 功能5:正则表达式验证
     */
    static validate(type, text) {
        const patterns = {
            'email': '^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$',
            'phone': '^1[3-9]\\d{9}$',
            'url': '^https?://[A-Za-z0-9.-]+\\.[A-Za-z]{2,}',
            'ipv4': '^(\\d{1,3}\\.){3}\\d{1,3}$',
            'id_card': '^\\d{18}|\\d{17}[X|x]$',
            'username': '^[A-Za-z0-9_]{3,16}$',
            'password': '^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$',
            'date': '^\\d{4}-\\d{2}-\\d{2}$'
        };
        
        const pattern = patterns[type];
        if (!pattern) {
            return { success: false, message: `未知的验证类型:${type}` };
        }
        
        try {
            const regex = new RegExp(pattern);
            const isValid = regex.test(text);
            const message = isValid ? '验证成功' : '验证失败';
            
            return { success: isValid, message: message };
        } catch (e) {
            return { success: false, message: `验证错误:${e.message}` };
        }
    }
    
    /**
     * 获取正则表达式统计信息
     */
    static getRegexStats(pattern, text) {
        const stats = {};
        
        try {
            const regex = new RegExp(pattern, 'g');
            const matches = text.match(regex) || [];
            
            stats['模式'] = pattern;
            stats['文本长度'] = text.length;
            stats['匹配次数'] = matches.length;
            stats['匹配内容'] = matches;
            
            if (matches.length > 0) {
                stats['第一个匹配'] = matches[0];
            }
        } catch (e) {
            stats['错误'] = e.message;
        }
        
        return stats;
    }
    
    /**
     * 常见正则表达式模板
     */
    static getCommonPatterns() {
        return {
            '邮箱': '^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$',
            '手机号': '^1[3-9]\\d{9}$',
            'URL': '^https?://[A-Za-z0-9.-]+\\.[A-Za-z]{2,}',
            'IPv4地址': '^(\\d{1,3}\\.){3}\\d{1,3}$',
            '身份证': '^\\d{18}|\\d{17}[X|x]$',
            '用户名': '^[A-Za-z0-9_]{3,16}$',
            '密码': '^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$',
            '日期': '^\\d{4}-\\d{2}-\\d{2}$',
            '十六进制颜色': '^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$',
            '整数': '^-?\\d+$'
        };
    }
}

// 导出供Node.js使用
if (typeof module !== 'undefined' && module.exports) {
    module.exports = RegexToolJS;
}

JavaScript实现的详细说明

JavaScript版本充分利用了JavaScript内置的RegExp对象。匹配功能使用test方法检查是否匹配。提取功能使用match方法获取所有匹配。替换功能使用replace方法。分割功能使用split方法。验证功能提供了常见格式的预定义模式。这个实现比Kotlin版本更简洁,因为JavaScript对正则表达式有原生支持。

ArkTS调用实现

完整的ArkTS代码实现

/**
 * 正则表达式测试和验证工具 - ArkTS版本(OpenHarmony鸿蒙)
 */
import { webview } from '@kit.ArkWeb';
import { common } from '@kit.AbilityKit';

@Entry
@Component
struct RegexToolPage {
    @State pattern: string = '^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$';
    @State text: string = 'user@example.com';
    @State result: string = '';
    @State selectedTool: string = '匹配测试';
    @State isLoading: boolean = false;
    @State allResults: string = '';
    
    webviewController: webview.WebviewController = new webview.WebviewController();
    
    matches(pattern: string, text: string, ignoreCase: boolean = false): { success: boolean; message: string } {
        try {
            const flags = ignoreCase ? 'gi' : 'g';
            const regex = new RegExp(pattern, flags);
            const isMatch = regex.test(text);
            const message = isMatch ? '匹配成功' : '未找到匹配';
            
            return { success: isMatch, message: message };
        } catch (e) {
            return { success: false, message: `正则表达式错误:${e}` };
        }
    }
    
    extract(pattern: string, text: string, ignoreCase: boolean = false): string[] {
        try {
            const flags = ignoreCase ? 'gi' : 'g';
            const regex = new RegExp(pattern, flags);
            const matches = text.match(regex);
            
            return matches || [];
        } catch (e) {
            return [`提取失败:${e}`];
        }
    }
    
    replace(pattern: string, text: string, replacement: string, ignoreCase: boolean = false, replaceAll: boolean = true): string {
        try {
            const flags = ignoreCase ? 'gi' : 'g';
            const regex = new RegExp(pattern, replaceAll ? flags : ignoreCase ? 'i' : '');
            
            return text.replace(regex, replacement);
        } catch (e) {
            return `替换失败:${e}`;
        }
    }
    
    split(pattern: string, text: string, limit: number = -1): string[] {
        try {
            const regex = new RegExp(pattern);
            const result = text.split(regex);
            
            if (limit > 0) {
                return result.slice(0, limit);
            }
            return result;
        } catch (e) {
            return [`分割失败:${e}`];
        }
    }
    
    validate(type: string, text: string): { success: boolean; message: string } {
        const patterns: Record<string, string> = {
            'email': '^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$',
            'phone': '^1[3-9]\\d{9}$',
            'url': '^https?://[A-Za-z0-9.-]+\\.[A-Za-z]{2,}',
            'ipv4': '^(\\d{1,3}\\.){3}\\d{1,3}$',
            'date': '^\\d{4}-\\d{2}-\\d{2}$'
        };
        
        const pattern = patterns[type];
        if (!pattern) {
            return { success: false, message: `未知的验证类型:${type}` };
        }
        
        try {
            const regex = new RegExp(pattern);
            const isValid = regex.test(text);
            const message = isValid ? '验证成功' : '验证失败';
            
            return { success: isValid, message: message };
        } catch (e) {
            return { success: false, message: `验证错误:${e}` };
        }
    }
    
    getRegexStats(pattern: string, text: string): string {
        const stats: Record<string, any> = {};
        
        try {
            const regex = new RegExp(pattern, 'g');
            const matches = text.match(regex) || [];
            
            stats['模式'] = pattern;
            stats['文本长度'] = text.length;
            stats['匹配次数'] = matches.length;
            stats['匹配内容'] = matches;
            
            if (matches.length > 0) {
                stats['第一个匹配'] = matches[0];
            }
        } catch (e) {
            stats['错误'] = e.toString();
        }
        
        return JSON.stringify(stats, null, 2);
    }
    
    async executeRegexTool() {
        this.isLoading = true;
        
        try {
            let result = '';
            switch (this.selectedTool) {
                case '匹配测试':
                    const matchResult = this.matches(this.pattern, this.text);
                    result = `${matchResult.message}`;
                    break;
                case '提取内容':
                    const extracted = this.extract(this.pattern, this.text);
                    result = `提取结果: ${JSON.stringify(extracted)}`;
                    break;
                case '替换内容':
                    const replaced = this.replace(this.pattern, this.text, 'REPLACED');
                    result = `替换结果: ${replaced}`;
                    break;
                case '分割字符串':
                    const split = this.split(this.pattern, this.text);
                    result = `分割结果: ${JSON.stringify(split)}`;
                    break;
                case '统计信息':
                    result = this.getRegexStats(this.pattern, this.text);
                    break;
            }
            
            this.result = result;
            
            const results = [];
            const matchRes = this.matches(this.pattern, this.text);
            results.push(`匹配: ${matchRes.message}`);
            results.push(`提取: ${JSON.stringify(this.extract(this.pattern, this.text))}`);
            results.push(`替换: ${this.replace(this.pattern, this.text, 'REPLACED')}`);
            results.push(`统计:\n${this.getRegexStats(this.pattern, this.text)}`);
            
            this.allResults = `所有工具结果:\n${results.join('\n\n')}`;
        } catch (error) {
            this.result = '执行错误:' + error;
        }
        
        this.isLoading = false;
    }
    
    build() {
        Column() {
            Row() {
                Text('正则表达式测试和验证工具')
                    .fontSize(24)
                    .fontWeight(FontWeight.Bold)
                    .fontColor(Color.White)
            }
            .width('100%')
            .height(60)
            .backgroundColor('#1565C0')
            .justifyContent(FlexAlign.Center)
            
            Scroll() {
                Column({ space: 16 }) {
                    Column() {
                        Text('正则表达式:')
                            .fontSize(14)
                            .fontWeight(FontWeight.Bold)
                            .width('100%')
                        
                        TextInput({ placeholder: '请输入正则表达式' })
                            .value(this.pattern)
                            .onChange((value: string) => {
                                this.pattern = value;
                            })
                            .width('100%')
                            .height(60)
                            .padding(8)
                            .backgroundColor(Color.White)
                            .borderRadius(4)
                    }
                    .width('100%')
                    .padding(12)
                    .backgroundColor('#E3F2FD')
                    .borderRadius(8)
                    
                    Column() {
                        Text('测试文本:')
                            .fontSize(14)
                            .fontWeight(FontWeight.Bold)
                            .width('100%')
                        
                        TextInput({ placeholder: '请输入测试文本' })
                            .value(this.text)
                            .onChange((value: string) => {
                                this.text = value;
                            })
                            .width('100%')
                            .height(80)
                            .padding(8)
                            .backgroundColor(Color.White)
                            .borderRadius(4)
                    }
                    .width('100%')
                    .padding(12)
                    .backgroundColor('#E3F2FD')
                    .borderRadius(8)
                    
                    Column() {
                        Text('选择工具:')
                            .fontSize(14)
                            .fontWeight(FontWeight.Bold)
                            .width('100%')
                        
                        Select([
                            { value: '匹配测试' },
                            { value: '提取内容' },
                            { value: '替换内容' },
                            { value: '分割字符串' },
                            { value: '统计信息' }
                        ])
                            .value(this.selectedTool)
                            .onSelect((index: number, value: string) => {
                                this.selectedTool = value;
                            })
                            .width('100%')
                    }
                    .width('100%')
                    .padding(12)
                    .backgroundColor('#E3F2FD')
                    .borderRadius(8)
                    
                    if (this.result) {
                        Column() {
                            Text('结果:')
                                .fontSize(14)
                                .fontWeight(FontWeight.Bold)
                                .width('100%')
                            
                            Text(this.result)
                                .fontSize(12)
                                .width('100%')
                                .padding(8)
                                .backgroundColor('#F5F5F5')
                                .borderRadius(4)
                        }
                        .width('100%')
                        .padding(12)
                        .backgroundColor('#F5F5F5')
                        .borderRadius(8)
                    }
                    
                    if (this.allResults) {
                        Column() {
                            Text('所有结果:')
                                .fontSize(14)
                                .fontWeight(FontWeight.Bold)
                                .width('100%')
                            
                            Text(this.allResults)
                                .fontSize(12)
                                .width('100%')
                                .padding(8)
                                .backgroundColor('#E8F5E9')
                                .borderRadius(4)
                        }
                        .width('100%')
                        .padding(12)
                        .backgroundColor('#E8F5E9')
                        .borderRadius(8)
                    }
                    
                    Button('执行工具')
                        .width('100%')
                        .onClick(() => this.executeRegexTool())
                        .enabled(!this.isLoading)
                    
                    if (this.isLoading) {
                        LoadingProgress()
                            .width(40)
                            .height(40)
                    }
                }
                .width('100%')
                .padding(16)
            }
            .layoutWeight(1)
        }
        .width('100%')
        .height('100%')
        .backgroundColor('#FAFAFA')
    }
}

ArkTS实现的详细说明

ArkTS版本为OpenHarmony鸿蒙平台提供了完整的用户界面。通过@State装饰器,我们可以管理应用的状态。这个实现包含了正则表达式输入框、测试文本输入框、工具选择和结果显示功能。用户可以输入正则表达式和测试文本,选择不同的工具,查看处理结果。

应用场景分析

1. 数据验证

在数据验证中,需要验证邮箱、电话号码等格式。应用使用正则表达式工具来验证用户输入。

2. 文本处理

在文本处理中,需要提取和替换特定模式的文本。文本编辑器使用正则表达式工具来处理文本。

3. 日志分析

在日志分析中,需要解析和提取日志中的信息。日志分析工具使用正则表达式工具来处理日志。

4. 数据清洗

在数据清洗中,需要识别和处理异常数据。数据处理系统使用正则表达式工具来清洗数据。

5. 内容过滤

在内容过滤中,需要识别和过滤不适当的内容。内容管理系统使用正则表达式工具来过滤内容。

性能优化建议

1. 编译正则表达式

对于频繁使用的正则表达式,可以提前编译以提高性能。

2. 使用非捕获组

在不需要捕获的地方使用非捕获组可以提高性能。

3. 避免回溯

设计正则表达式时要避免过度的回溯。

4. 缓存匹配结果

对于相同的输入,可以缓存匹配结果。

总结

正则表达式测试和验证工具是现代应用开发中不可或缺的工具。通过在KMP框架下实现这套工具,我们可以在多个平台上使用同一套代码,提高开发效率。这个工具提供了匹配、提取、替换、分割和验证等多种功能,可以满足大多数正则表达式处理需求。

在OpenHarmony鸿蒙平台上,我们可以通过ArkTS调用这些工具,为用户提供完整的正则表达式测试体验。掌握这套工具,不仅能够帮助开发者高效处理正则表达式,更重要的是能够在实际项目中灵活应用,解决数据验证、文本处理等实际问题。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐