Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DCloud
unidocs-uni-app-x-zh
提交
64780f86
U
unidocs-uni-app-x-zh
项目概览
DCloud
/
unidocs-uni-app-x-zh
通知
144
Star
2
Fork
33
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
9
列表
看板
标记
里程碑
合并请求
11
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
unidocs-uni-app-x-zh
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
9
Issue
9
列表
看板
标记
里程碑
合并请求
11
合并请求
11
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
64780f86
编写于
1月 31, 2024
作者:
DCloud-yinjiacheng
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
update: docs/plugin/uts-component.md
上级
b5810419
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
408 addition
and
297 deletion
+408
-297
docs/plugin/uts-component.md
docs/plugin/uts-component.md
+408
-297
未找到文件。
docs/plugin/uts-component.md
浏览文件 @
64780f86
...
@@ -121,27 +121,37 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
...
@@ -121,27 +121,37 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
> Android
> Android
```
ts
```
html
<template>
<template>
<
view
>
<view>
</view>
</view>
</template>
</template>
<script
lang=
"uts"
>
<script
lang=
"uts"
>
import
TextUtils
from
'
android.text.TextUtils
'
/**
import
Button
from
'
android.widget.Button
'
* 引用 Android 系统库
import
LinearLayout
from
'
android.widget.LinearLayout
'
* [可选实现,按需引入]
import
View
from
'
android.view.View
'
*/
import
TextUtils
from
'
android.text.TextUtils
'
;
import
Button
from
'
android.widget.Button
'
;
import
View
from
'
android.view.View
'
;
class
ButtonClickListsner
extends
View
.
OnClickListener
{
/**
constructor
()
{
* 引入三方库
super
()
* [可选实现,按需引入]
}
*
override
onClick
(
v
?
:
View
)
{
* 在 Android 平台引入三方库有以下两种方式:
console
.
log
(
v
)
* 1、[推荐] 通过 仓储 方式引入,将 三方库的依赖信息 配置到 config.json 文件下的 dependencies 字段下。详细配置方式[详见](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html#dependencies)
}
* 2、直接引入,将 三方库的aar或jar文件 放到libs目录下。更多信息[详见](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html#android%E5%B9%B3%E5%8F%B0%E5%8E%9F%E7%94%9F%E9%85%8D%E7%BD%AE)
}
*
* 在通过上述任意方式依赖三方库后,使用时需要在文件中 import
* import { LottieAnimationView } from 'com.airbnb.lottie.LottieAnimationView'
*/
/**
* UTSAndroid 为平台内置对象,不需要 import 可直接调用其API,[详见](https://uniapp.dcloud.net.cn/uts/utsandroid.html#utsandroid)
*/
//原生提供以下属性或方法的实现
//原生提供以下属性或方法的实现
export
default
{
export
default
{
...
@@ -152,16 +162,12 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
...
@@ -152,16 +162,12 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
/**
/**
* 组件涉及的事件声明,只有声明过的事件,才能被正常发送
* 组件涉及的事件声明,只有声明过的事件,才能被正常发送
*/
*/
emits
:
[
'
buttonC
lick
'
],
emits
:
[
'
buttonc
lick
'
],
/**
/**
* 属性声明,组件的使用者会传递这些属性值到组件
* 属性声明,组件的使用者会传递这些属性值到组件
*/
*/
props
:
{
props
:
{
/**
"
buttontext
"
:
{
* 字符串类型 属性:buttonText 需要设置默认值
* 目前仅支持,布尔,数字,字符串
*/
"
buttonText
"
:
{
type
:
String
,
type
:
String
,
default
:
"
点击触发
"
default
:
"
点击触发
"
}
}
...
@@ -176,33 +182,38 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
...
@@ -176,33 +182,38 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
* 属性变化监听器实现
* 属性变化监听器实现
*/
*/
watch
:
{
watch
:
{
"
buttonT
ext
"
:
{
"
buttont
ext
"
:
{
/**
/**
* 这里监听属性变化,并进行组件内部更新
* 这里监听属性变化,并进行组件内部更新
*/
*/
handler
(
newButtonText
:
string
)
{
handler
(
newValue
:
string
,
oldValue
:
string
)
{
if
(
this
.
$el
!=
null
)
{
if
(
!
TextUtils
.
isEmpty
(
newValue
)
&&
newValue
!=
oldValue
)
{
let
button
=
this
.
$el
!
.
findViewWithTag
(
"
centerButton
"
)
as
Button
this
.
$el
?.
setText
(
newValue
);
if
(
!
TextUtils
.
isEmpty
(
newButtonText
))
{
button
.
setText
(
newButtonText
)
}
}
}
},
},
immediate
:
false
//
创建时是否通过此方法更新属性,默认值为false
immediate
:
false
//
创建时是否通过此方法更新属性,默认值为false
},
},
},
},
/**
/**
* 规则:如果没有配置expose,则methods中的方法均对外暴露,如果配置了expose,则以expose的配置为准向外暴露
* 规则:如果没有配置expose,则methods中的方法均对外暴露,如果配置了expose,则以expose的配置为准向外暴露
* ['publicMethod'] 含义为:只有 `publicMethod` 在实例上可用
* ['publicMethod'] 含义为:只有 `publicMethod` 在实例上可用
*/
*/
expose
:
[
'
doSth
'
],
expose
:
[
'
doSomething
'
],
methods
:
{
methods
:
{
/**
/**
* 对外公开的组件方法
* 对外公开的组件方法
*
* uni-app中调用示例:
* this.$refs["组件ref"].doSomething("uts-button");
*
* uni-app x中调用示例:
* 1、引入对应Element
* import { UtsButtonElement(组件名称以upper camel case方式命名 + Element) } from 'uts.sdk.modules.utsComponent(组件目录名称以lower camel case方式命名)';
* 2、(this.$refs["组件ref"] as UtsButtonElement).doSomething("uts-button");
* 或 (uni.getElementById("组件id") as UtsButtonElement).doSomething("uts-button");
*/
*/
doSth
(
paramA
:
string
)
{
doSomething
(
param
:
string
)
{
// 这是组件的自定义方法
console
.
log
(
param
);
console
.
log
(
"
paramA
"
,
paramA
)
},
},
/**
/**
* 内部使用的组件方法
* 内部使用的组件方法
...
@@ -211,111 +222,145 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
...
@@ -211,111 +222,145 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
}
}
},
},
/**
/**
*
组件被创建,组件第一个生命周期,
* [可选实现]
组件被创建,组件第一个生命周期,
* 在内存中被占用的时候被调用,开发者可以在这里执行一些需要提前执行的初始化逻辑
* 在内存中被占用的时候被调用,开发者可以在这里执行一些需要提前执行的初始化逻辑
* [可选实现]
*/
*/
created
()
{
created
()
{
},
},
/**
/**
* 对应平台的view载体即将被创建,对应前端beforeMount
* [可选实现] 对应平台的view载体即将被创建,对应前端beforeMount
* [可选实现]
*/
*/
NVBeforeLoad
()
{
NVBeforeLoad
()
{
},
},
/**
/**
*
创建原生View,必须定义返回值类型
* [必须实现]
创建原生View,必须定义返回值类型
* 开发者需要重点实现这个函数,声明原生组件被创建出来的过程,以及最终生成的原生组件类型
* 开发者需要重点实现这个函数,声明原生组件被创建出来的过程,以及最终生成的原生组件类型
* (Android需要明确知道View类型,需特殊校验)
* (Android需要明确知道View类型,需特殊校验)
* todo 补充IOS平台限制
* [必须实现]
*/
*/
NVLoad
():
LinearLayout
{
NVLoad
()
:
Button
{
//必须实现
let
button
=
new
Button
(
$androidContext
!
);
let
contentLayout
=
new
LinearLayout
(
this
.
$androidContext
!
)
let
button
=
new
Button
(
this
.
$androidContext
!
)
button
.
setText
(
"
点击触发
"
);
button
.
setText
(
"
点击触发
"
);
button
.
setTag
(
"
centerButton
"
);
button
.
setOnClickListener
(
new
ButtonClickListener
(
this
));
contentLayout
.
addView
(
button
,
new
LinearLayout
.
LayoutParams
(
500
,
500
));
return
button
;
button
.
setOnClickListener
(
new
ButtonClickListsner
())
return
contentLayout
},
},
/**
/**
* 原生View已创建
* [可选实现] 原生View已创建
* [可选实现]
*/
*/
NVLoaded
()
{
NVLoaded
()
{
},
},
/**
/**
* 原生View布局完成
* [可选实现] 原生View布局完成
* [可选实现]
*/
*/
NVLayouted
()
{
NVLayouted
()
{
},
},
/**
/**
* 原生View将释放
* [可选实现] 原生View将释放
* [可选实现]
*/
*/
NVBeforeUnload
()
{},
NVBeforeUnload
()
{
},
/**
/**
* 原生View已释放,这里可以做释放View之后的操作
* [可选实现] 原生View已释放,这里可以做释放View之后的操作
* [可选实现]
*/
*/
NVUnloaded
()
{
NVUnloaded
()
{
},
},
/**
/**
* 组件销毁
* [可选实现] 组件销毁
* [可选实现]
*/
*/
unmounted
()
{},
unmounted
()
{
},
/**
* [可选实现] 自定组件布局尺寸,用于告诉排版系统,组件自身需要的宽高
* 一般情况下,组件的宽高应该是由终端系统的排版引擎决定,组件开发者不需要实现此函数
* 但是部分场景下,组件开发者需要自己维护宽高,则需要开发者重写此函数
*/
NVMeasure
(
size
:
UTSSize
)
:
UTSSize
{
// size.width = 300.0.toFloat();
// size.height = 200.0.toFloat();
return
size
;
}
}
/**
/**
* 自定组件布局尺寸
* 定义按钮点击后触发回调的类
* [可选实现]
* [可选实现]
*/
*/
NVMeasure
(
size
:
UTSSize
):
UTSSize
{
class
ButtonClickListener
extends
View
.
OnClickListener
{
size
.
width
=
120.0
.
toFloat
()
/**
size
.
height
=
800.0
.
toFloat
()
* 如果需要在回调类或者代理类中对组件进行操作,比如调用组件方法,发送事件等,需要在该类中持有组件对应的原生类的对象
return
size
* 组件原生类的基类为 UTSComponent,该类是一个泛型类,需要接收一个类型变量,该类型变量就是原生组件的类型
*/
private
comp
:
UTSComponent
<
Button
>
;
constructor
(
comp
:
UTSComponent
<
Button
>
)
{
super
();
this
.
comp
=
comp
;
}
/**
* 按钮点击回调方法
*/
override
onClick
(
v
?:
View
)
{
console
.
log
(
"
按钮被点击
"
);
// 发送事件
this
.
comp
.
$emit
(
"
buttonclick
"
);
}
}
}
}
</script>
</script>
<style>
<style>
</style>
</style>
```
```
> iOS
> iOS
```
ts
```
html
<template>
<template>
<view
class=
"defaultStyles"
>
<view
class=
"defaultStyles"
>
</view>
</view>
</template>
</template>
<script
lang=
"uts"
>
<script
lang=
"uts"
>
/**
* 引用 iOS 系统库
* [可选实现,按需引入]
*/
import
{
import
{
UIButton
UIButton
,
UIControl
}
from
"
UIKit
"
}
from
"
UIKit
"
// 定义按钮点击后触发回调的类
/**
class
ButtonClickListsner
{
* 引入三方库
// 按钮点击回调方法
* [可选实现,按需引入]
@
objc
buttonClick
()
{
*
console
.
log
(
"
按钮被点击
"
)
* 在 iOS 平台引入三方库有以下两种方式:
}
* 1、通过引入三方库framework 或者.a 等方式,需要将 .framework 放到 ./Frameworks 目录下,将.a 放到 ./Libs 目录下。更多信息[详见](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html#ios-平台原生配置)
}
* 2、通过 cocoaPods 方式引入,将要引入的 pod 信息配置到 config.json 文件下的 dependencies-pods 字段下。详细配置方式[详见](https://uniapp.dcloud.net.cn/plugin/uts-ios-cocoapods.html)
*
* 在通过上述任意方式依赖三方库后,使用时需要在文件中 import:
* 示例:import { LottieAnimationView, LottieAnimation, LottieLoopMode } from 'Lottie'
*/
/**
* UTSiOS、UTSComponent 为平台内置对象,不需要 import 可直接调用其API,[详见](https://uniapp.dcloud.net.cn/uts/utsios.html)
*/
import
{
UTSComponent
}
from
"
DCloudUTSFoundation
"
//原生提供以下属性或方法的实现
//原生提供以下属性或方法的实现
export
default
{
export
default
{
data
()
{
return
{
};
},
/**
/**
* 组件名称,也就是开发者使用的标签
* 组件名称,也就是开发者使用的标签
*/
*/
...
@@ -323,15 +368,15 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
...
@@ -323,15 +368,15 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
/**
/**
* 组件涉及的事件声明,只有声明过的事件,才能被正常发送
* 组件涉及的事件声明,只有声明过的事件,才能被正常发送
*/
*/
emits
:
[
'
buttonC
lick
'
],
emits
:
[
'
buttonc
lick
'
],
/**
/**
* 属性声明,组件的使用者会传递这些属性值到组件
* 属性声明,组件的使用者会传递这些属性值到组件
*/
*/
props
:
{
props
:
{
/**
/**
* 字符串类型 属性:buttonT
ext 需要设置默认值
* 字符串类型 属性:buttont
ext 需要设置默认值
*/
*/
"
buttonT
ext
"
:
{
"
buttont
ext
"
:
{
type
:
String
,
type
:
String
,
default
:
"
点击触发
"
default
:
"
点击触发
"
}
}
...
@@ -339,36 +384,40 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
...
@@ -339,36 +384,40 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
/**
/**
* 组件内部变量声明
* 组件内部变量声明
*/
*/
data
()
{
return
{}
},
/**
/**
* 属性变化监听器实现
* 属性变化监听器实现
*/
*/
watch
:
{
watch
:
{
"
buttonT
ext
"
:
{
"
buttont
ext
"
:
{
/**
/**
* 这里监听属性变化,并进行组件内部更新
* 这里监听属性变化,并进行组件内部更新
*/
*/
handler
(
newButtonText
:
string
,
oldButtonText
)
{
handler
(
newValue
:
String
,
oldValue
:
String
)
{
this
.
$el
.
setTitle
(
newButtonText
,
for
=
UIControl
.
State
.
normal
)
this
.
$el
.
setTitle
(
newValue
,
for
=
UIControl
.
State
.
normal
)
},
},
immediate
:
false
//创建时是否通过此方法更新属性,默认值为false
/**
* 创建时是否通过此方法更新属性,默认值为false
*/
immediate
:
false
},
},
},
},
/**
/**
* 规则:如果没有配置expose,则methods中的方法均对外暴露,如果配置了expose,则以expose的配置为准向外暴露
* 规则:如果没有配置expose,则methods中的方法均对外暴露,如果配置了expose,则以expose的配置为准向外暴露
* ['publicMethod'] 含义为:只有 `publicMethod` 在实例上可用
* ['publicMethod'] 含义为:只有 `publicMethod` 在实例上可用
*/
*/
expose
:
[
'
doSth
'
],
expose
:
[
'
doSomething
'
],
methods
:
{
methods
:
{
/**
/**
* 对外公开的组件方法
* 对外公开的组件方法
* 在uni-app中调用组件方法,可以通过指定ref的方式,例如指定uts-button 标签的ref 为 ’button‘, 调用时使用:this.$refs["button"].doSomething('message');
*/
*/
doSth
(
paramA
:
string
)
{
doSomething
(
paramA
:
string
)
{
// 这是组件的自定义方法
// 这是组件的自定义方法
console
.
log
(
"
paramA
"
)
console
.
log
(
paramA
,
'
this is in uts-button component
'
)
},
},
/**
/**
* 内部使用的组件方法
* 内部使用的组件方法
*/
*/
...
@@ -395,13 +444,17 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
...
@@ -395,13 +444,17 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
* 开发者需要重点实现这个函数,声明原生组件被创建出来的过程,以及最终生成的原生组件类型
* 开发者需要重点实现这个函数,声明原生组件被创建出来的过程,以及最终生成的原生组件类型
* [必须实现]
* [必须实现]
*/
*/
NVLoad
()
:
UIButton
{
NVLoad
()
:
UIButton
{
//必须实现
//必须实现
buttonClickListsner
=
new
ButtonClickListsner
(
this
)
let
button
=
new
UIButton
()
let
button
=
new
UIButton
()
button
.
setTitle
(
this
.
buttonText
,
for
=
UIControl
.
State
.
normal
)
button
.
setTitle
(
this
.
buttontext
,
for
=
UIControl
.
State
.
normal
)
const
target
=
new
ButtonClickListsner
()
// 在 swift target-action 对应的方法需要以OC的方式来调用,那么OC语言中用Selector来表示一个方法的名称(又称方法选择器),创建一个Selector可以使用 Selector("functionName") 的方式。
const
method
=
Selector
(
"
buttonClick
"
)
const
method
=
Selector
(
"
buttonClickAction
"
)
button
.
addTarget
(
target
,
action
=
method
,
for
=
UIControl
.
Event
.
touchUpInside
)
if
(
buttonClickListsner
!=
null
)
{
button
.
addTarget
(
buttonClickListsner
!
,
action
=
method
,
for
=
UIControl
.
Event
.
touchUpInside
)
}
return
button
return
button
},
},
...
@@ -410,7 +463,10 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
...
@@ -410,7 +463,10 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
* [可选实现]
* [可选实现]
*/
*/
NVLoaded
()
{
NVLoaded
()
{
/**
* 通过 this.$el 来获取原生控件。
*/
this
.
$el
.
setTitle
(
this
.
buttontext
,
for
=
UIControl
.
State
.
normal
)
},
},
/**
/**
* 原生View布局完成
* 原生View布局完成
...
@@ -423,7 +479,7 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
...
@@ -423,7 +479,7 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
* 原生View将释放
* 原生View将释放
* [可选实现]
* [可选实现]
*/
*/
NVBeforeUnload
()
{
},
NVBeforeUnload
()
{
},
/**
/**
* 原生View已释放,这里可以做释放View之后的操作
* 原生View已释放,这里可以做释放View之后的操作
* [可选实现]
* [可选实现]
...
@@ -435,16 +491,51 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
...
@@ -435,16 +491,51 @@ UTS组件的优势在于,它秉承了UTS的跨平台特性,统一的UTS语
* 组件销毁
* 组件销毁
* [可选实现]
* [可选实现]
*/
*/
unmounted
()
{}
unmounted
()
{
}
/**
* 更多组件开发的信息详见:https://uniapp.dcloud.net.cn/plugin/uts-component.html
*/
}
/**
* 定义按钮点击后触发回调的类
* [可选实现]
*/
class
ButtonClickListsner
{
/**
* 如果需要在回调类或者代理类中对组件进行操作,比如调用组件方法,发送事件等,需要在该类中持有组件对应的原生类的对象。
* 组件原生类的基类为 UTSComponent,该类是一个泛型类,需要接收一个类型变量,该类型变量就是原生组件的类型。
*/
private
component
:
UTSComponent
<
UIButton
>
constructor
(
component
:
UTSComponent
<
UIButton
>
)
{
this
.
component
=
component
super
.
init
()
}
/**
/**
* 自定组件布局尺寸
* 按钮点击回调方法
* 在 swift 中,所有target-action (例如按钮的点击事件,NotificationCenter 的通知事件等)对应的 action 函数前面都要使用 @objc 进行标记。
* [可选实现]
* [可选实现]
*/
*/
NVMeasure
(
size
:
UTSSize
):
UTSSize
{
@
objc
buttonClickAction
()
{
return
new
UTSSize
(
120
,
45
);
console
.
log
(
"
按钮被点击
"
)
// 发送事件
this
.
component
.
__$$emit
(
"
buttonclick
"
);
}
}
}
}
/**
* 定义回调类或者代理类的实例
* [可选实现]
*/
let
buttonClickListsner
:
ButtonClickListsner
|
null
=
null
</script>
</script>
<style>
</style>
```
```
:::
:::
...
@@ -521,6 +612,7 @@ NVMeasure 用于告诉排版系统,组件自身需要的宽高,具体的调
...
@@ -521,6 +612,7 @@ NVMeasure 用于告诉排版系统,组件自身需要的宽高,具体的调
但是部分场景下,组件开发者需要自己维护宽高,则需要开发者重写此函数
但是部分场景下,组件开发者需要自己维护宽高,则需要开发者重写此函数
**注意:只有非容器组件生效,容器组件不应该重写此函数**
+
NVUpdateStyles
+
NVUpdateStyles
...
@@ -536,10 +628,29 @@ NVUpdateStyles(styles: Map<String, any>){
...
@@ -536,10 +628,29 @@ NVUpdateStyles(styles: Map<String, any>){
}
}
```
```
+
NVRecycler
HBuilderX 4.0版本起支持,仅uni-app x App-Android平台支持
当UTS组件在
`list-view`
组件中使用时,由于
[
复用机制
](
../component/list-view.md
)
,UTS组件可能表现异常(UI、事件回调等),因此,组件开发者需要在此函数中进行相应的逻辑处理。
**注意:只有非容器组件生效,容器组件不应该重写此函数**
比如我们使用UTS组件封装了一个Android原生的
`EditText`
控件(输入框),代码如下
```
html
NVLoad() : EditText {
let editText = new EditText($androidContext!);
return editText;
}
```
然后我们在
`list-view`
组件中使用该UTS组件,当我们在第一个输入框中随机输入几个字符后,开始滚动列表,会发现之前输入的字符又出现在下面某个
`list-item`
中,这就是一个典型的由于复用机制导致的UI状态异常问题。此时我们就需要在NVRecycler()函数中处理该问题,代码如下
```
html
NVRecycler() {
// 发生复用时置空输入框内容
this.$el?.setText("")
}
```
[
vue3 生命周期暂不支持
](
https://uniapp.dcloud.net.cn/tutorial/vue3-api.html#%E9%80%89%E9%A1%B9-%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E9%92%A9%E5%AD%90
)
[
vue3 生命周期暂不支持
](
https://uniapp.dcloud.net.cn/tutorial/vue3-api.html#%E9%80%89%E9%A1%B9-%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E9%92%A9%E5%AD%90
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录