Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Xts Acts
提交
d4688ab7
X
Xts Acts
项目概览
OpenHarmony
/
Xts Acts
1 年多 前同步成功
通知
9
Star
22
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
X
Xts Acts
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
d4688ab7
编写于
6月 09, 2022
作者:
F
fulizhong
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
modify audioPlayer and audioRecorder testcases Signed-off-by: FULIZHONG<fulizhong1@huawei.com>
Signed-off-by:
N
fulizhong
<
fulizhong@huawei.com
>
上级
33f1a568
变更
12
展开全部
隐藏空白更改
内联
并排
Showing
12 changed file
with
411 addition
and
1043 deletion
+411
-1043
multimedia/media/media_js_standard/AudioPlayerTestBase.js
multimedia/media/media_js_standard/AudioPlayerTestBase.js
+14
-2
multimedia/media/media_js_standard/MediaTestBase.js
multimedia/media/media_js_standard/MediaTestBase.js
+10
-0
multimedia/media/media_js_standard/VideoRecorderTestBase.js
multimedia/media/media_js_standard/VideoRecorderTestBase.js
+19
-8
multimedia/media/media_js_standard/audioPlayer/src/main/java/ohos/acts/multimedia/audio/audioplayer/MainAbility.java
...a/ohos/acts/multimedia/audio/audioplayer/MainAbility.java
+0
-35
multimedia/media/media_js_standard/audioPlayer/src/main/java/ohos/acts/multimedia/audio/audioplayer/MyApplication.java
...ohos/acts/multimedia/audio/audioplayer/MyApplication.java
+0
-29
multimedia/media/media_js_standard/audioPlayer/src/main/js/test/PlayerLocalTestAudioFUNC.test.js
...oPlayer/src/main/js/test/PlayerLocalTestAudioFUNC.test.js
+140
-659
multimedia/media/media_js_standard/audioRecorder/Test.json
multimedia/media/media_js_standard/audioRecorder/Test.json
+1
-0
multimedia/media/media_js_standard/audioRecorder/src/main/java/ohos/acts/multimedia/audio/audioplayer/MainAbility.java
...a/ohos/acts/multimedia/audio/audioplayer/MainAbility.java
+0
-35
multimedia/media/media_js_standard/audioRecorder/src/main/java/ohos/acts/multimedia/audio/audioplayer/MyApplication.java
...ohos/acts/multimedia/audio/audioplayer/MyApplication.java
+0
-29
multimedia/media/media_js_standard/audioRecorder/src/main/js/default/pages/index/index.js
...rd/audioRecorder/src/main/js/default/pages/index/index.js
+10
-2
multimedia/media/media_js_standard/audioRecorder/src/main/js/test/RecorderLocalTestAudioAPI.test.js
...corder/src/main/js/test/RecorderLocalTestAudioAPI.test.js
+18
-58
multimedia/media/media_js_standard/audioRecorder/src/main/js/test/RecorderLocalTestAudioFUNC.test.js
...order/src/main/js/test/RecorderLocalTestAudioFUNC.test.js
+199
-186
未找到文件。
multimedia/media/media_js_standard/AudioPlayerTestBase.js
浏览文件 @
d4688ab7
...
...
@@ -30,7 +30,13 @@ export function playAudioSource(src, duration, playTime, checkSeekTime, done) {
expect
().
assertFail
();
done
();
}
audioPlayer
.
src
=
src
;
if
(
typeof
(
src
)
==
'
string
'
)
{
console
.
error
(
'
case src test
'
);
audioPlayer
.
src
=
src
;
}
else
{
console
.
error
(
'
case fdsrc test
'
);
audioPlayer
.
fdSrc
=
src
;
}
audioPlayer
.
on
(
'
dataLoad
'
,
()
=>
{
console
.
info
(
'
case set source success
'
);
expect
(
audioPlayer
.
state
).
assertEqual
(
'
paused
'
);
...
...
@@ -89,7 +95,13 @@ export function playAudioSource(src, duration, playTime, checkSeekTime, done) {
console
.
info
(
'
case reset success
'
);
expect
(
audioPlayer
.
state
).
assertEqual
(
'
idle
'
);
// step 11: reset -> dataLoad
audioPlayer
.
src
=
src
;
if
(
typeof
(
src
)
==
'
string
'
)
{
console
.
error
(
'
case src test
'
);
audioPlayer
.
src
=
src
;
}
else
{
console
.
error
(
'
case fdsrc test
'
);
audioPlayer
.
fdSrc
=
src
;
}
});
audioPlayer
.
on
(
'
timeUpdate
'
,
(
seekDoneTime
)
=>
{
seekCount
++
;
...
...
multimedia/media/media_js_standard/MediaTestBase.js
浏览文件 @
d4688ab7
...
...
@@ -80,6 +80,16 @@ export function catchCallback(error) {
console
.
info
(
`case error called,errMessage is
${
error
.
message
}
`
);
}
export
function
checkDescription
(
actualDescription
,
descriptionKey
,
descriptionValue
)
{
for
(
let
i
=
0
;
i
<
descriptionKey
.
length
;
i
++
)
{
let
property
=
actualDescription
[
descriptionKey
[
i
]];
console
.
info
(
'
case key is
'
+
descriptionKey
[
i
]);
console
.
info
(
'
case actual value is
'
+
property
);
console
.
info
(
'
case hope value is
'
+
descriptionValue
[
i
]);
expect
(
property
).
assertEqual
(
descriptionValue
[
i
]);
}
}
export
function
printDescription
(
obj
)
{
let
description
=
""
;
for
(
let
i
in
obj
)
{
...
...
multimedia/media/media_js_standard/VideoRecorderTestBase.js
浏览文件 @
d4688ab7
...
...
@@ -21,9 +21,10 @@ import * as mediaTestBase from './MediaTestBase.js';
const
VIDEO_TRACK
=
'
video_track
'
;
const
AUDIO_TRACK
=
'
audio_track
'
;
const
AUDIO_VIDEO_TYPE
=
'
audio_video
'
;
const
ONLYVIDEO_TYPE
=
'
only_video
'
;
const
DELTA_TIME
=
1000
;
const
PLAY_TIME
=
1000
;
let
tarckType
=
new
Array
(
VIDEO_TRACK
,
AUDIO_TRACK
);
export
async
function
initCaptureSession
(
videoOutPut
,
cameraManager
,
cameras
,
cameraID
)
{
let
cameraInput
=
await
cameraManager
.
createCameraInput
(
cameras
[
cameraID
].
cameraId
);
...
...
@@ -53,11 +54,16 @@ export function getTrackArray(videoType, recorderConfigFile) {
recorderConfigFile
.
videoFrameWidth
);
let
trackArray
=
new
Array
(
videoTrack
,
audioTrack
);
return
trackArray
;
}
else
{
}
else
if
(
videoType
==
ONLYVIDEO_TYPE
)
{
let
videoTrack
=
new
Array
(
'
video/mpeg
'
,
recorderConfigFile
.
videoFrameHeight
,
recorderConfigFile
.
videoFrameWidth
);
let
trackArray
=
new
Array
(
videoTrack
);
return
trackArray
;
}
else
{
let
audioTrack
=
new
Array
(
recorderConfigFile
.
audioEncodeBitRate
,
recorderConfigFile
.
numberOfChannels
,
'
audio/mpeg
'
,
recorderConfigFile
.
audioSampleRate
);
let
trackArray
=
new
Array
(
audioTrack
);
return
trackArray
;
}
}
...
...
@@ -90,18 +96,23 @@ export async function checkVideos(playFdPath, duration, trackArray, playerSurfac
videoPlayer
=
video
;
expect
(
videoPlayer
.
state
).
assertEqual
(
'
idle
'
);
}
else
{
console
.
info
(
'
case createVideoPlayer is failed
'
);
console
.
info
(
'
case createVideoPlayer is failed
'
);
expect
().
assertFail
();
}
},
mediaTestBase
.
failureCallback
).
catch
(
mediaTestBase
.
catchCallback
);
console
.
info
(
'
[checkVideos] case checkVideos fdPath is :
'
+
playFdPath
);
videoPlayer
.
url
=
playFdPath
;
await
videoPlayer
.
setDisplaySurface
(
playerSurfaceId
).
then
(()
=>
{
console
.
info
(
'
case setDisplaySurface success
'
);
expect
(
videoPlayer
.
state
).
assertEqual
(
'
idle
'
);
},
mediaTestBase
.
failureCallback
).
catch
(
mediaTestBase
.
catchCallback
);
let
tarckType
=
undefined
;
if
(
playerSurfaceId
!=
null
)
{
tarckType
=
new
Array
(
VIDEO_TRACK
,
AUDIO_TRACK
);
await
videoPlayer
.
setDisplaySurface
(
playerSurfaceId
).
then
(()
=>
{
console
.
info
(
'
case setDisplaySurface success
'
);
expect
(
videoPlayer
.
state
).
assertEqual
(
'
idle
'
);
},
mediaTestBase
.
failureCallback
).
catch
(
mediaTestBase
.
catchCallback
);
}
else
{
tarckType
=
new
Array
(
AUDIO_TRACK
);
}
await
videoPlayer
.
prepare
().
then
(()
=>
{
expect
(
videoPlayer
.
state
).
assertEqual
(
'
prepared
'
);
expect
(
videoPlayer
.
duration
).
assertClose
(
duration
,
DELTA_TIME
);
...
...
multimedia/media/media_js_standard/audioPlayer/src/main/java/ohos/acts/multimedia/audio/audioplayer/MainAbility.java
已删除
100644 → 0
浏览文件 @
33f1a568
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
ohos.acts.multimedia.audio.audioplayer
;
import
ohos.ace.ability.AceAbility
;
import
ohos.aafwk.content.Intent
;
/*
* java MainAbility
*/
public
class
MainAbility
extends
AceAbility
{
@Override
public
void
onStart
(
Intent
intent
)
{
super
.
onStart
(
intent
);
}
@Override
public
void
onStop
()
{
super
.
onStop
();
}
}
multimedia/media/media_js_standard/audioPlayer/src/main/java/ohos/acts/multimedia/audio/audioplayer/MyApplication.java
已删除
100644 → 0
浏览文件 @
33f1a568
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
ohos.acts.multimedia.audio.audioplayer
;
import
ohos.aafwk.ability.AbilityPackage
;
/*
* java MyApplication
*/
public
class
MyApplication
extends
AbilityPackage
{
@Override
public
void
onInitialize
()
{
super
.
onInitialize
();
}
}
multimedia/media/media_js_standard/audioPlayer/src/main/js/test/PlayerLocalTestAudioFUNC.test.js
浏览文件 @
d4688ab7
此差异已折叠。
点击以展开。
multimedia/media/media_js_standard/audioRecorder/Test.json
浏览文件 @
d4688ab7
...
...
@@ -10,6 +10,7 @@
{
"type"
:
"ShellKit"
,
"run-command"
:
[
"rm -rf /storage/media/100/local/files/Videos/audio_*"
],
"teardown-command"
:[
]
...
...
multimedia/media/media_js_standard/audioRecorder/src/main/java/ohos/acts/multimedia/audio/audioplayer/MainAbility.java
已删除
100644 → 0
浏览文件 @
33f1a568
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
ohos.acts.multimedia.audio.audioplayer
;
import
ohos.ace.ability.AceAbility
;
import
ohos.aafwk.content.Intent
;
/*
* java MainAbility
*/
public
class
MainAbility
extends
AceAbility
{
@Override
public
void
onStart
(
Intent
intent
)
{
super
.
onStart
(
intent
);
}
@Override
public
void
onStop
()
{
super
.
onStop
();
}
}
multimedia/media/media_js_standard/audioRecorder/src/main/java/ohos/acts/multimedia/audio/audioplayer/MyApplication.java
已删除
100644 → 0
浏览文件 @
33f1a568
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
ohos.acts.multimedia.audio.audioplayer
;
import
ohos.aafwk.ability.AbilityPackage
;
/*
* java MyApplication
*/
public
class
MyApplication
extends
AbilityPackage
{
@Override
public
void
onInitialize
()
{
super
.
onInitialize
();
}
}
multimedia/media/media_js_standard/audioRecorder/src/main/js/default/pages/index/index.js
浏览文件 @
d4688ab7
...
...
@@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import
*
as
mediaTestBase
from
'
../../../../../../../MediaTestBase.js
'
;
import
{
Core
,
ExpectExtend
}
from
'
deccjsunit/index
'
export
default
{
...
...
@@ -22,8 +22,16 @@ export default {
onInit
()
{
this
.
title
=
this
.
$t
(
'
strings.world
'
);
},
onShow
()
{
async
onShow
()
{
console
.
info
(
'
onShow finish
'
)
let
applictionName
=
'
ohos.acts.multimedia.audio.audiorecorder
'
;
let
permissionName1
=
'
ohos.permission.MICROPHONE
'
;
let
permissionName2
=
'
ohos.permission.MEDIA_LOCATION
'
;
let
permissionName3
=
'
ohos.permission.READ_MEDIA
'
;
let
permissionName4
=
'
ohos.permission.WRITE_MEDIA
'
;
let
permissionNames
=
new
Array
(
permissionName1
,
permissionName2
,
permissionName3
,
permissionName4
);
await
mediaTestBase
.
applyPermission
(
applictionName
,
permissionNames
);
const
core
=
Core
.
getInstance
()
const
expectExtend
=
new
ExpectExtend
({
'
id
'
:
'
extend
'
...
...
multimedia/media/media_js_standard/audioRecorder/src/main/js/test/RecorderLocalTestAudioAPI.test.js
浏览文件 @
d4688ab7
...
...
@@ -14,7 +14,7 @@
*/
import
media
from
'
@ohos.multimedia.media
'
import
mediaLibrary
from
'
@ohos.multimedia.mediaLibrary
'
import
*
as
mediaTestBase
from
'
../../../../../MediaTestBase.js
'
;
import
{
describe
,
beforeAll
,
beforeEach
,
afterEach
,
afterAll
,
it
,
expect
}
from
'
deccjsunit/index
'
describe
(
'
RecorderLocalTestAudioAPI
'
,
function
()
{
...
...
@@ -28,29 +28,19 @@ describe('RecorderLocalTestAudioAPI', function () {
const
RESET_STATE
=
6
;
const
RELEASE_STATE
=
7
;
const
ERROR_STATE
=
8
;
const
FORMAT_M4A
=
6
;
const
SOURCE_TYPE
=
1
;
const
ENCORDER_AACLC
=
3
;
const
CHANNEL_TWO
=
2
;
const
RECORDER_TIME
=
3
000
;
const
RECORDER_TIME
=
1
000
;
let
fdPath
;
let
fileAsset
;
let
fdNumber
;
let
fdObject
;
let
audioConfig
=
{
audioSourceType
:
SOURCE_TYPE
,
audioEncoder
:
ENCORDER_AACLC
,
audioEncodeBitRate
:
22050
,
audioSampleRate
:
22050
,
audioEncodeBitRate
:
48000
,
audioSampleRate
:
48000
,
numberOfChannels
:
CHANNEL_TWO
,
format
:
FORMAT_M4A
,
uri
:
'
file:///data/accounts/account_0/appdata/recorder/testAPI.m4a
'
,
location
:
{
latitude
:
1
,
longitude
:
1
},
uri
:
'
fd://
'
,
location
:
{
latitude
:
30
,
longitude
:
30
},
audioEncoderMime
:
media
.
CodecMimeType
.
AUDIO_AAC
,
fileFormat
:
media
.
ContainerFormatType
.
CFT_MPEG_4A
,
}
function
sleep
(
time
)
{
for
(
let
t
=
Date
.
now
();
Date
.
now
()
-
t
<=
time
;);
}
function
initAudioRecorder
()
{
if
(
typeof
(
audioRecorder
)
!=
'
undefined
'
)
{
audioRecorder
.
release
();
...
...
@@ -112,7 +102,7 @@ describe('RecorderLocalTestAudioAPI', function () {
audioRecorder
.
on
(
'
start
'
,
()
=>
{
console
.
info
(
'
setCallback start() case callback is called
'
);
sleep
(
RECORDER_TIME
);
mediaTestBase
.
m
sleep
(
RECORDER_TIME
);
mySteps
.
shift
();
nextStep
(
mySteps
,
done
);
});
...
...
@@ -125,6 +115,7 @@ describe('RecorderLocalTestAudioAPI', function () {
audioRecorder
.
on
(
'
resume
'
,
()
=>
{
console
.
info
(
'
setCallback resume() case callback is called
'
);
mediaTestBase
.
msleep
(
RECORDER_TIME
);
mySteps
.
shift
();
nextStep
(
mySteps
,
done
);
});
...
...
@@ -158,7 +149,9 @@ describe('RecorderLocalTestAudioAPI', function () {
}
beforeAll
(
async
function
()
{
await
getFd
(
'
testAPI.m4a
'
);
fdObject
=
await
mediaTestBase
.
getFd
(
'
audio_api.mp4
'
);
fdPath
=
"
fd://
"
+
fdObject
.
fdNumber
.
toString
();
audioConfig
.
uri
=
fdPath
;
console
.
info
(
'
beforeAll case
'
);
})
...
...
@@ -171,42 +164,10 @@ describe('RecorderLocalTestAudioAPI', function () {
})
afterAll
(
async
function
()
{
await
closeFd
(
);
await
mediaTestBase
.
closeFd
(
fdObject
.
fileAsset
,
fdObject
.
fdNumber
);
console
.
info
(
'
afterAll case
'
);
})
async
function
getFd
(
pathName
)
{
let
displayName
=
pathName
;
const
mediaTest
=
mediaLibrary
.
getMediaLibrary
();
let
fileKeyObj
=
mediaLibrary
.
FileKey
;
let
mediaType
=
mediaLibrary
.
MediaType
.
VIDEO
;
let
publicPath
=
await
mediaTest
.
getPublicDirectory
(
mediaLibrary
.
DirectoryType
.
DIR_VIDEO
);
let
dataUri
=
await
mediaTest
.
createAsset
(
mediaType
,
displayName
,
publicPath
);
if
(
dataUri
!=
undefined
)
{
let
args
=
dataUri
.
id
.
toString
();
let
fetchOp
=
{
selections
:
fileKeyObj
.
ID
+
"
=?
"
,
selectionArgs
:
[
args
],
}
let
fetchFileResult
=
await
mediaTest
.
getFileAssets
(
fetchOp
);
fileAsset
=
await
fetchFileResult
.
getAllObject
();
fdNumber
=
await
fileAsset
[
0
].
open
(
'
Rw
'
);
fdPath
=
"
fd://
"
+
fdNumber
.
toString
();
}
}
async
function
closeFd
()
{
if
(
fileAsset
!=
null
)
{
await
fileAsset
[
0
].
close
(
fdNumber
).
then
(()
=>
{
console
.
info
(
'
[mediaLibrary] case close fd success
'
);
}).
catch
((
err
)
=>
{
console
.
info
(
'
[mediaLibrary] case close fd failed
'
);
});
}
else
{
console
.
info
(
'
[mediaLibrary] case fileAsset is null
'
);
}
}
/* *
* @tc.number : SUB_MEDIA_RECORDER_createAudioRecorder_API_0100
* @tc.name : Create an AudioRecoder Object by function of createAudioRecorder
...
...
@@ -231,7 +192,6 @@ describe('RecorderLocalTestAudioAPI', function () {
* @tc.level : Level2
*/
it
(
'
SUB_MEDIA_RECORDER_AudioRecorder_Prepare_API_0100
'
,
0
,
async
function
(
done
)
{
audioConfig
.
uri
=
fdPath
;
let
testAudioRecorder
=
media
.
createAudioRecorder
();
expect
(
testAudioRecorder
!=
null
).
assertTrue
();
testAudioRecorder
.
prepare
(
audioConfig
);
...
...
@@ -270,14 +230,14 @@ describe('RecorderLocalTestAudioAPI', function () {
})
/* *
* @tc.number : SUB_MEDIA_RECORDER_AudioRecorder_Prepare_API_0
2
00
* @tc.number : SUB_MEDIA_RECORDER_AudioRecorder_Prepare_API_0
4
00
* @tc.name : 04.resume->prepare
* @tc.desc : Reliability Test
* @tc.size : MediumTest
* @tc.type : Reliability
* @tc.level : Level2
*/
it
(
'
SUB_MEDIA_RECORDER_AudioRecorder_Prepare_API_0
2
00
'
,
0
,
async
function
(
done
)
{
it
(
'
SUB_MEDIA_RECORDER_AudioRecorder_Prepare_API_0
4
00
'
,
0
,
async
function
(
done
)
{
initAudioRecorder
();
let
mySteps
=
new
Array
(
PRE_STATE
,
START_STATE
,
PAUSE_STATE
,
RESUME_STATE
,
PRE_STATE
,
ERROR_STATE
,
RELEASE_STATE
,
END_STATE
);
...
...
@@ -646,7 +606,7 @@ describe('RecorderLocalTestAudioAPI', function () {
* @tc.type : Reliability
* @tc.level : Level2
*/
it
(
'
SUB_MEDIA_RECORDER_AudioRecorder_Pause_API_0
8
00
'
,
0
,
async
function
(
done
)
{
it
(
'
SUB_MEDIA_RECORDER_AudioRecorder_Pause_API_0
9
00
'
,
0
,
async
function
(
done
)
{
initAudioRecorder
();
let
mySteps
=
new
Array
(
PRE_STATE
,
START_STATE
,
PAUSE_STATE
,
PAUSE_STATE
,
PAUSE_STATE
,
RELEASE_STATE
,
END_STATE
);
...
...
multimedia/media/media_js_standard/audioRecorder/src/main/js/test/RecorderLocalTestAudioFUNC.test.js
浏览文件 @
d4688ab7
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录