KMP OpenHarmony 正则表达式工具库 - 跨平台文本匹配解决方案
本文介绍了一个基于Kotlin Multiplatform (KMP)和OpenHarmony平台的正则表达式工具库。该库通过KMP技术实现跨平台支持,包括Kotlin/JVM、Kotlin/JS和OpenHarmony/ArkTS平台,提供模式匹配、内容提取、文本替换、数据验证等核心功能。文中详细展示了用Kotlin实现的正则表达式处理类,包含匹配检查、内容查找、文本替换、分割处理等方法,以及常


项目概述
正则表达式是现代编程中强大的文本处理工具。无论是在数据验证、文本搜索、字符串替换还是数据提取中,正则表达式都扮演着重要角色。然而,不同的编程语言和平台对正则表达式的实现方式各不相同,这导致开发者需要在不同平台上重复编写类似的逻辑。
本文介绍一个基于 Kotlin Multiplatform (KMP) 和 OpenHarmony 平台的正则表达式工具库。这个工具库提供了一套完整的正则表达式处理能力,包括模式匹配、文本替换、数据验证、内容提取等功能。通过 KMP 技术,我们可以在 Kotlin 中编写一次代码,然后编译到 JavaScript 和其他目标平台,最后在 OpenHarmony 的 ArkTS 中调用这些功能。
技术架构
多平台支持
- Kotlin/JVM: 后端服务和桌面应用
- Kotlin/JS: Web 应用和浏览器环境
- OpenHarmony/ArkTS: 鸿蒙操作系统应用
核心功能模块
- 模式匹配: 检查文本是否匹配特定模式
- 内容提取: 从文本中提取匹配的内容
- 文本替换: 使用正则表达式替换文本
- 数据验证: 验证电子邮件、电话号码、URL 等
- 分割文本: 使用正则表达式分割文本
- 查找所有匹配: 找出文本中所有匹配的内容
- 预定义模式: 提供常用的正则表达式模式
Kotlin 实现
核心正则表达式处理类
// 文件: src/commonMain/kotlin/RegexProcessor.kt
/**
* 正则表达式处理工具类
* 提供正则表达式匹配、替换、验证等功能
*/
class RegexProcessor {
/**
* 检查文本是否匹配模式
* @param text 文本
* @param pattern 正则表达式模式
* @return 是否匹配
*/
fun matches(text: String, pattern: String): Boolean {
return try {
Regex(pattern).matches(text)
} catch (e: Exception) {
false
}
}
/**
* 检查文本是否包含匹配
* @param text 文本
* @param pattern 正则表达式模式
* @return 是否包含匹配
*/
fun contains(text: String, pattern: String): Boolean {
return try {
Regex(pattern).containsMatchIn(text)
} catch (e: Exception) {
false
}
}
/**
* 查找第一个匹配
* @param text 文本
* @param pattern 正则表达式模式
* @return 匹配的文本,如果没有匹配返回空字符串
*/
fun findFirst(text: String, pattern: String): String {
return try {
Regex(pattern).find(text)?.value ?: ""
} catch (e: Exception) {
""
}
}
/**
* 查找所有匹配
* @param text 文本
* @param pattern 正则表达式模式
* @return 所有匹配的文本列表
*/
fun findAll(text: String, pattern: String): List<String> {
return try {
Regex(pattern).findAll(text).map { it.value }.toList()
} catch (e: Exception) {
emptyList()
}
}
/**
* 替换第一个匹配
* @param text 文本
* @param pattern 正则表达式模式
* @param replacement 替换文本
* @return 替换后的文本
*/
fun replaceFirst(text: String, pattern: String, replacement: String): String {
return try {
Regex(pattern).replaceFirst(text, replacement)
} catch (e: Exception) {
text
}
}
/**
* 替换所有匹配
* @param text 文本
* @param pattern 正则表达式模式
* @param replacement 替换文本
* @return 替换后的文本
*/
fun replaceAll(text: String, pattern: String, replacement: String): String {
return try {
Regex(pattern).replace(text, replacement)
} catch (e: Exception) {
text
}
}
/**
* 分割文本
* @param text 文本
* @param pattern 正则表达式模式
* @return 分割后的文本列表
*/
fun split(text: String, pattern: String): List<String> {
return try {
Regex(pattern).split(text)
} catch (e: Exception) {
listOf(text)
}
}
/**
* 验证电子邮件
* @param email 电子邮件地址
* @return 是否有效
*/
fun isValidEmail(email: String): Boolean {
val pattern = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$"
return matches(email, pattern)
}
/**
* 验证电话号码
* @param phone 电话号码
* @return 是否有效
*/
fun isValidPhone(phone: String): Boolean {
val pattern = "^\\+?[1-9]\\d{1,14}$"
return matches(phone, pattern)
}
/**
* 验证 URL
* @param url URL 字符串
* @return 是否有效
*/
fun isValidUrl(url: String): Boolean {
val pattern = "^(https?|ftp)://[\\w\\-]+(\\.[\\w\\-]+)+([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?$"
return matches(url, pattern)
}
/**
* 验证 IP 地址
* @param ip IP 地址
* @return 是否有效
*/
fun isValidIp(ip: String): Boolean {
val pattern = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
return matches(ip, pattern)
}
/**
* 提取所有数字
* @param text 文本
* @return 所有数字列表
*/
fun extractNumbers(text: String): List<String> {
return findAll(text, "\\d+")
}
/**
* 提取所有单词
* @param text 文本
* @return 所有单词列表
*/
fun extractWords(text: String): List<String> {
return findAll(text, "\\b\\w+\\b")
}
/**
* 移除所有数字
* @param text 文本
* @return 移除数字后的文本
*/
fun removeNumbers(text: String): String {
return replaceAll(text, "\\d+", "")
}
/**
* 移除所有特殊字符
* @param text 文本
* @return 移除特殊字符后的文本
*/
fun removeSpecialChars(text: String): String {
return replaceAll(text, "[^a-zA-Z0-9\\s]", "")
}
}
Kotlin 实现的核心特点
Kotlin 实现中的正则表达式功能充分利用了 Kotlin 标准库的 Regex 类。matches 方法用于检查整个文本是否匹配模式,而 containsMatchIn 用于检查文本中是否包含匹配。
find 方法返回第一个匹配,findAll 方法返回所有匹配。这两个方法都返回 MatchResult 对象,可以访问匹配的值和位置。
replaceFirst 和 replace 方法提供了替换功能。split 方法使用正则表达式分割文本。
验证方法使用了预定义的正则表达式模式来验证常见的数据格式,如电子邮件、电话号码、URL 和 IP 地址。这些模式都经过了验证,可以处理大多数常见情况。
提取方法使用了特定的正则表达式来提取特定类型的内容,如数字和单词。这些方法简化了常见的文本处理任务。
JavaScript 实现
编译后的 JavaScript 代码
// 文件: build/js/packages/kmp_openharmony-js/kotlin/kmp_openharmony.js
// (由 Kotlin 编译器自动生成)
/**
* RegexProcessor 类的 JavaScript 版本
* 通过 Kotlin/JS 编译器从 Kotlin 源代码生成
*/
class RegexProcessor {
/**
* 检查文本是否匹配模式
* @param {string} text - 文本
* @param {string} pattern - 正则表达式模式
* @returns {boolean} 是否匹配
*/
matches(text, pattern) {
try {
const regex = new RegExp(`^${pattern}$`);
return regex.test(text);
} catch (e) {
return false;
}
}
/**
* 检查文本是否包含匹配
* @param {string} text - 文本
* @param {string} pattern - 正则表达式模式
* @returns {boolean} 是否包含匹配
*/
contains(text, pattern) {
try {
const regex = new RegExp(pattern);
return regex.test(text);
} catch (e) {
return false;
}
}
/**
* 查找第一个匹配
* @param {string} text - 文本
* @param {string} pattern - 正则表达式模式
* @returns {string} 匹配的文本
*/
findFirst(text, pattern) {
try {
const regex = new RegExp(pattern);
const match = text.match(regex);
return match ? match[0] : '';
} catch (e) {
return '';
}
}
/**
* 查找所有匹配
* @param {string} text - 文本
* @param {string} pattern - 正则表达式模式
* @returns {string[]} 所有匹配的文本列表
*/
findAll(text, pattern) {
try {
const regex = new RegExp(pattern, 'g');
const matches = text.match(regex);
return matches || [];
} catch (e) {
return [];
}
}
/**
* 替换第一个匹配
* @param {string} text - 文本
* @param {string} pattern - 正则表达式模式
* @param {string} replacement - 替换文本
* @returns {string} 替换后的文本
*/
replaceFirst(text, pattern, replacement) {
try {
const regex = new RegExp(pattern);
return text.replace(regex, replacement);
} catch (e) {
return text;
}
}
/**
* 替换所有匹配
* @param {string} text - 文本
* @param {string} pattern - 正则表达式模式
* @param {string} replacement - 替换文本
* @returns {string} 替换后的文本
*/
replaceAll(text, pattern, replacement) {
try {
const regex = new RegExp(pattern, 'g');
return text.replace(regex, replacement);
} catch (e) {
return text;
}
}
/**
* 分割文本
* @param {string} text - 文本
* @param {string} pattern - 正则表达式模式
* @returns {string[]} 分割后的文本列表
*/
split(text, pattern) {
try {
const regex = new RegExp(pattern);
return text.split(regex);
} catch (e) {
return [text];
}
}
/**
* 验证电子邮件
* @param {string} email - 电子邮件地址
* @returns {boolean} 是否有效
*/
isValidEmail(email) {
const pattern = '^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$';
return this.matches(email, pattern);
}
/**
* 验证电话号码
* @param {string} phone - 电话号码
* @returns {boolean} 是否有效
*/
isValidPhone(phone) {
const pattern = '^\\+?[1-9]\\d{1,14}$';
return this.matches(phone, pattern);
}
/**
* 验证 URL
* @param {string} url - URL 字符串
* @returns {boolean} 是否有效
*/
isValidUrl(url) {
const pattern = '^(https?|ftp)://[\\w\\-]+(\\.[\\w\\-]+)+([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?$';
return this.matches(url, pattern);
}
/**
* 验证 IP 地址
* @param {string} ip - IP 地址
* @returns {boolean} 是否有效
*/
isValidIp(ip) {
const pattern = '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$';
return this.matches(ip, pattern);
}
/**
* 提取所有数字
* @param {string} text - 文本
* @returns {string[]} 所有数字列表
*/
extractNumbers(text) {
return this.findAll(text, '\\d+');
}
/**
* 提取所有单词
* @param {string} text - 文本
* @returns {string[]} 所有单词列表
*/
extractWords(text) {
return this.findAll(text, '\\b\\w+\\b');
}
/**
* 移除所有数字
* @param {string} text - 文本
* @returns {string} 移除数字后的文本
*/
removeNumbers(text) {
return this.replaceAll(text, '\\d+', '');
}
/**
* 移除所有特殊字符
* @param {string} text - 文本
* @returns {string} 移除特殊字符后的文本
*/
removeSpecialChars(text) {
return this.replaceAll(text, '[^a-zA-Z0-9\\s]', '');
}
}
JavaScript 实现的特点
JavaScript 版本完全由 Kotlin/JS 编译器自动生成,确保了与 Kotlin 版本的行为完全一致。JavaScript 的 RegExp 对象提供了强大的正则表达式支持。
test 方法用于检查文本是否匹配模式。match 方法用于查找匹配。replace 方法用于替换。split 方法用于分割。
在 JavaScript 中,g 标志表示全局匹配,用于查找所有匹配。没有 g 标志时,只返回第一个匹配。
ArkTS 调用代码
OpenHarmony 应用集成
// 文件: kmp_ceshiapp/entry/src/main/ets/pages/RegexProcessorPage.ets
import { RegexProcessor } from '../../../../../../../build/js/packages/kmp_openharmony-js/kotlin/kmp_openharmony';
@Entry
@Component
struct RegexProcessorPage {
@State selectedOperation: string = 'match';
@State inputText: string = '';
@State pattern: string = '';
@State result: string = '';
@State resultTitle: string = '';
private regexProcessor = new RegexProcessor();
private operations = [
{ name: '匹配检查', value: 'match' },
{ name: '包含检查', value: 'contains' },
{ name: '查找第一个', value: 'findFirst' },
{ name: '查找全部', value: 'findAll' },
{ name: '替换第一个', value: 'replaceFirst' },
{ name: '替换全部', value: 'replaceAll' },
{ name: '分割文本', value: 'split' },
{ name: '验证邮箱', value: 'email' },
{ name: '验证电话', value: 'phone' },
{ name: '验证 URL', value: 'url' },
{ name: '验证 IP', value: 'ip' },
{ name: '提取数字', value: 'numbers' }
];
build() {
Column() {
// 标题
Text('🔍 正则表达式工具库')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
.width('100%')
.padding(20)
.backgroundColor('#1A237E')
.textAlign(TextAlign.Center)
Scroll() {
Column() {
// 操作选择
Column() {
Text('选择操作')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
.margin({ bottom: 12 })
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(this.operations, (op: { name: string; value: string }) => {
Button(op.name)
.layoutWeight(1)
.height(40)
.margin({ right: 8, bottom: 8 })
.backgroundColor(this.selectedOperation === op.value ? '#1A237E' : '#E0E0E0')
.fontColor(this.selectedOperation === op.value ? '#FFFFFF' : '#333333')
.fontSize(11)
.onClick(() => {
this.selectedOperation = op.value;
this.result = '';
this.resultTitle = '';
})
})
}
.width('100%')
}
.width('95%')
.margin({ top: 16, left: '2.5%', right: '2.5%', bottom: 16 })
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(6)
// 输入区域
Column() {
Text('输入文本')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
.margin({ bottom: 8 })
TextInput({ placeholder: '输入要处理的文本', text: this.inputText })
.onChange((value) => this.inputText = value)
.width('100%')
.height(100)
.padding(12)
.border({ width: 1, color: '#4DB6AC' })
.borderRadius(6)
.fontSize(12)
.margin({ bottom: 12 })
if (this.selectedOperation !== 'email' && this.selectedOperation !== 'phone' &&
this.selectedOperation !== 'url' && this.selectedOperation !== 'ip' &&
this.selectedOperation !== 'numbers') {
TextInput({ placeholder: '输入正则表达式模式', text: this.pattern })
.onChange((value) => this.pattern = value)
.width('100%')
.height(50)
.padding(12)
.border({ width: 1, color: '#4DB6AC' })
.borderRadius(6)
.fontSize(12)
}
}
.width('95%')
.margin({ left: '2.5%', right: '2.5%', bottom: 16 })
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(6)
// 操作按钮
Row() {
Button('✨ 处理')
.layoutWeight(1)
.height(44)
.backgroundColor('#1A237E')
.fontColor('#FFFFFF')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.borderRadius(6)
.onClick(() => this.executeOperation())
Blank()
.width(12)
Button('🔄 清空')
.layoutWeight(1)
.height(44)
.backgroundColor('#F5F5F5')
.fontColor('#1A237E')
.fontSize(14)
.border({ width: 1, color: '#4DB6AC' })
.borderRadius(6)
.onClick(() => {
this.inputText = '';
this.pattern = '';
this.result = '';
this.resultTitle = '';
})
}
.width('95%')
.margin({ left: '2.5%', right: '2.5%', bottom: 16 })
// 结果显示
if (this.resultTitle) {
Column() {
Text(this.resultTitle)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
.width('100%')
.padding(12)
.backgroundColor('#1A237E')
.borderRadius(6)
.textAlign(TextAlign.Center)
.margin({ bottom: 12 })
Scroll() {
Text(this.result)
.fontSize(12)
.fontColor('#333333')
.fontFamily('monospace')
.textAlign(TextAlign.Start)
.width('100%')
.padding(12)
.selectable(true)
}
.width('100%')
.height(300)
.backgroundColor('#F9F9F9')
.border({ width: 1, color: '#4DB6AC' })
.borderRadius(6)
}
.width('95%')
.margin({ left: '2.5%', right: '2.5%', bottom: 16 })
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(6)
}
}
.width('100%')
}
.layoutWeight(1)
.width('100%')
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
private executeOperation() {
if (!this.inputText.trim()) {
this.resultTitle = '❌ 错误';
this.result = '请输入文本';
return;
}
try {
switch (this.selectedOperation) {
case 'match':
if (!this.pattern) {
this.resultTitle = '❌ 错误';
this.result = '请输入正则表达式模式';
return;
}
const isMatch = this.regexProcessor.matches(this.inputText, this.pattern);
this.resultTitle = isMatch ? '✅ 匹配成功' : '❌ 不匹配';
this.result = `文本: ${this.inputText}\n模式: ${this.pattern}\n结果: ${isMatch ? '匹配' : '不匹配'}`;
break;
case 'contains':
if (!this.pattern) {
this.resultTitle = '❌ 错误';
this.result = '请输入正则表达式模式';
return;
}
const hasMatch = this.regexProcessor.contains(this.inputText, this.pattern);
this.resultTitle = hasMatch ? '✅ 包含匹配' : '❌ 不包含匹配';
this.result = `文本: ${this.inputText}\n模式: ${this.pattern}\n结果: ${hasMatch ? '包含' : '不包含'}`;
break;
case 'findFirst':
if (!this.pattern) {
this.resultTitle = '❌ 错误';
this.result = '请输入正则表达式模式';
return;
}
const first = this.regexProcessor.findFirst(this.inputText, this.pattern);
this.resultTitle = '🔍 第一个匹配';
this.result = first ? `匹配: ${first}` : '没有找到匹配';
break;
case 'findAll':
if (!this.pattern) {
this.resultTitle = '❌ 错误';
this.result = '请输入正则表达式模式';
return;
}
const all = this.regexProcessor.findAll(this.inputText, this.pattern);
this.resultTitle = '🔍 所有匹配';
this.result = all.length > 0 ? all.join('\n') : '没有找到匹配';
break;
case 'replaceFirst':
if (!this.pattern) {
this.resultTitle = '❌ 错误';
this.result = '请输入正则表达式模式';
return;
}
const replaceFirstResult = this.regexProcessor.replaceFirst(this.inputText, this.pattern, '[替换]');
this.resultTitle = '✏️ 替换第一个';
this.result = `原文本: ${this.inputText}\n结果: ${replaceFirstResult}`;
break;
case 'replaceAll':
if (!this.pattern) {
this.resultTitle = '❌ 错误';
this.result = '请输入正则表达式模式';
return;
}
const replaceAllResult = this.regexProcessor.replaceAll(this.inputText, this.pattern, '[替换]');
this.resultTitle = '✏️ 替换全部';
this.result = `原文本: ${this.inputText}\n结果: ${replaceAllResult}`;
break;
case 'split':
if (!this.pattern) {
this.resultTitle = '❌ 错误';
this.result = '请输入正则表达式模式';
return;
}
const parts = this.regexProcessor.split(this.inputText, this.pattern);
this.resultTitle = '✂️ 分割结果';
this.result = parts.join('\n');
break;
case 'email':
const isEmail = this.regexProcessor.isValidEmail(this.inputText);
this.resultTitle = isEmail ? '✅ 有效邮箱' : '❌ 无效邮箱';
this.result = `邮箱: ${this.inputText}\n状态: ${isEmail ? '有效' : '无效'}`;
break;
case 'phone':
const isPhone = this.regexProcessor.isValidPhone(this.inputText);
this.resultTitle = isPhone ? '✅ 有效电话' : '❌ 无效电话';
this.result = `电话: ${this.inputText}\n状态: ${isPhone ? '有效' : '无效'}`;
break;
case 'url':
const isUrl = this.regexProcessor.isValidUrl(this.inputText);
this.resultTitle = isUrl ? '✅ 有效 URL' : '❌ 无效 URL';
this.result = `URL: ${this.inputText}\n状态: ${isUrl ? '有效' : '无效'}`;
break;
case 'ip':
const isIp = this.regexProcessor.isValidIp(this.inputText);
this.resultTitle = isIp ? '✅ 有效 IP' : '❌ 无效 IP';
this.result = `IP: ${this.inputText}\n状态: ${isIp ? '有效' : '无效'}`;
break;
case 'numbers':
const numbers = this.regexProcessor.extractNumbers(this.inputText);
this.resultTitle = '🔢 提取数字';
this.result = numbers.length > 0 ? numbers.join(', ') : '没有找到数字';
break;
}
} catch (e) {
this.resultTitle = '❌ 处理出错';
this.result = `错误: ${e}`;
}
}
}
ArkTS 集成的关键要点
在 OpenHarmony 应用中集成正则表达式工具库需要考虑多种操作类型和用户体验。我们设计了一个灵活的 UI,能够支持不同的正则表达式操作。
操作选择界面使用了 Flex 布局和 FlexWrap 来实现响应式的按钮排列。当用户选择不同的操作时,输入区域会动态显示相应的输入字段。
对于需要正则表达式模式的操作,我们提供了模式输入框。对于验证操作(如验证邮箱、电话等),不需要用户输入模式,系统使用预定义的模式。
结果显示使用了可选择的文本,这样用户可以轻松复制处理结果。对于查找全部和分割操作,结果按行显示,便于查看。
工作流程详解
正则表达式处理的完整流程
- 操作选择: 用户在 ArkTS UI 中选择要执行的正则表达式操作
- 文本输入: 用户输入要处理的文本
- 模式输入: 根据选择的操作输入正则表达式模式(如果需要)
- 处理执行: 调用 RegexProcessor 的相应方法
- 结果展示: 将处理结果显示在 UI 中
跨平台一致性
通过 KMP 技术,我们确保了在所有平台上的行为一致性。无论是在 Kotlin/JVM、Kotlin/JS 还是通过 ArkTS 调用,正则表达式处理的逻辑和结果都是完全相同的。
实际应用场景
数据验证
在表单验证中,需要验证用户输入的数据格式。这个工具库提供了常见的验证函数,如验证邮箱、电话号码等。
文本搜索和替换
在文本编辑器或搜索工具中,需要进行复杂的文本搜索和替换。这个工具库提供了强大的正则表达式支持。
数据提取
在网页爬虫或日志分析中,需要从文本中提取特定的数据。这个工具库提供了提取功能。
文本处理
在自然语言处理或数据清洗中,需要进行各种文本处理操作。这个工具库提供了必要的功能。
性能优化
编译正则表达式
在频繁使用相同的正则表达式时,可以预先编译并缓存正则表达式对象以提高性能。
批量处理
在处理大量文本时,应该考虑使用批量处理的方式以提高效率。
安全性考虑
正则表达式 DoS 防护
在处理用户输入的正则表达式时,应该注意正则表达式 DoS(拒绝服务)攻击,避免使用过于复杂的正则表达式。
输入验证
在处理用户输入的文本时,应该进行验证,确保文本的有效性和安全性。
总结
这个 KMP OpenHarmony 正则表达式工具库展示了如何使用现代的跨平台技术来处理常见的正则表达式任务。通过 Kotlin Multiplatform 技术,我们可以在一个地方编写业务逻辑,然后在多个平台上使用。
正则表达式是文本处理中的强大工具。通过使用这样的工具库,开发者可以快速、可靠地处理各种正则表达式操作,从而提高开发效率和代码质量。
在实际应用中,建议根据具体的需求进行定制和扩展,例如添加更多的预定义模式、支持更复杂的正则表达式操作等高级特性。同时,定期进行性能测试和优化,确保应用在处理大量文本时仍然保持良好的性能。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)