Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DCloud
hello uni-app x
提交
b88adc20
H
hello uni-app x
项目概览
DCloud
/
hello uni-app x
通知
6018
Star
91
Fork
164
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
18
列表
看板
标记
里程碑
合并请求
1
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
H
hello uni-app x
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
18
Issue
18
列表
看板
标记
里程碑
合并请求
1
合并请求
1
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
b88adc20
编写于
4月 22, 2024
作者:
WOSHIMAHAIFENG
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'alpha-filenew' into 'alpha'
Alpha filenew See merge request
!27
上级
76c459a9
48020c74
变更
3
显示空白变更内容
内联
并排
Showing
3 changed file
with
149 addition
and
233 deletion
+149
-233
pages/API/get-file-system-manager/get-file-system-manager.test.js
...I/get-file-system-manager/get-file-system-manager.test.js
+52
-139
pages/API/get-file-system-manager/get-file-system-manager.uvue
.../API/get-file-system-manager/get-file-system-manager.uvue
+97
-94
static/filemanager/1.txt.br
static/filemanager/1.txt.br
+0
-0
未找到文件。
pages/API/get-file-system-manager/get-file-system-manager.test.js
浏览文件 @
b88adc20
...
...
@@ -10,6 +10,10 @@ describe('ExtApi-FileManagerTest', () => {
return
}
let
page
;
let
mBasePath
;
let
mGlobalTempPath
;
let
mGlobalRootPath
function
getData
(
key
=
''
)
{
return
new
Promise
(
async
(
resolve
,
reject
)
=>
{
...
...
@@ -37,6 +41,9 @@ describe('ExtApi-FileManagerTest', () => {
it
(
'
USER_DATA_PATH test
'
,
async
()
=>
{
// 测试 USER_DATA_PATH
let
globalUserDataPath
=
await
getData
(
'
globalUserDataPath
'
)
mBasePath
=
await
getData
(
'
basePath
'
)
mGlobalRootPath
=
await
getData
(
'
globalRootPath
'
)
mGlobalTempPath
=
await
getData
(
'
globalTempPath
'
)
await
page
.
setData
({
logAble
:
false
,
...
...
@@ -944,8 +951,10 @@ describe('ExtApi-FileManagerTest', () => {
}
let
basePath
=
await
getData
(
'
basePath
'
)
await
page
.
setData
({
basePath
:
mBasePath
,
recursiveVal
:
true
,
logAble
:
false
,
rmDirFile
:
'
appendfile
'
,
...
...
@@ -974,14 +983,14 @@ describe('ExtApi-FileManagerTest', () => {
await
btnMkdDirButton
.
tap
()
await
isDone
()
//
//
先用utf-8 写入内容
// 先用utf-8 写入内容
const
btnWriteFileButton
=
await
page
.
$
(
'
#btn-write-file
'
)
await
btnWriteFileButton
.
tap
()
await
isDone
()
//
//
追加内容
//追加内容
const
btnAppendFileButton
=
await
page
.
$
(
'
#btn-append-file
'
)
await
btnAppendFileButton
.
tap
()
await
isDone
()
...
...
@@ -1002,6 +1011,7 @@ describe('ExtApi-FileManagerTest', () => {
await
page
.
setData
({
basePath
:
mBasePath
,
recursiveVal
:
false
,
logAble
:
false
,
rmDirFile
:
'
sync
'
,
...
...
@@ -1019,18 +1029,7 @@ describe('ExtApi-FileManagerTest', () => {
renameToFile
:
'
sync/sync.txt
'
,
renameFromFile
:
'
sync/sync.txt
'
,
})
// 先清除文件,需要清除全部可能存在的历史测试文件,避免运行失败
const
btnUnLinkFileButton
=
await
page
.
$
(
'
#btn-unlink-file-sync
'
)
await
btnUnLinkFileButton
.
tap
()
await
isDone
()
//清除文件夹
const
btnRmDirButton
=
await
page
.
$
(
'
#btn-remove-dir-sync
'
)
await
btnRmDirButton
.
tap
()
await
isDone
()
await
clearDir
(
'
sync
'
)
// 重新创建测试目录,期望通过 recursive = true的 文件夹删除,得到一个空的 目录
const
btnMkdDirButton
=
await
page
.
$
(
'
#btn-mkdir-sync
'
)
await
btnMkdDirButton
.
tap
()
...
...
@@ -1098,6 +1097,8 @@ describe('ExtApi-FileManagerTest', () => {
// 测试 copyfile
await
page
.
setData
({
basePath
:
mBasePath
,
copyToBasePath
:
mBasePath
,
copyFromFile
:
"
sync/sync.txt
"
,
copyToFile
:
"
sync/syncto.txt
"
,
accessFile
:
"
sync/syncto.txt
"
...
...
@@ -1111,7 +1112,7 @@ describe('ExtApi-FileManagerTest', () => {
accessFileRet
=
await
getData
(
"
accessFileRet
"
)
expect
(
accessFileRet
).
toEqual
(
'
access:ok
'
)
clearDir
(
'
sync
'
)
await
clearDir
(
'
sync
'
)
});
async
function
createFile
()
{
...
...
@@ -1131,7 +1132,11 @@ describe('ExtApi-FileManagerTest', () => {
await
page
.
setData
({
rmDirFile
:
dir
,
})
const
btnClear
=
await
page
.
$
(
'
#btn-clear-file
'
)
const
btnUnLinkFileButton
=
await
page
.
$
(
'
#btn-clear-file
'
)
await
btnUnLinkFileButton
.
tap
()
await
isDone
()
const
btnClear
=
await
page
.
$
(
'
#btn-remove-dir
'
)
await
btnClear
.
tap
()
await
isDone
()
}
...
...
@@ -1148,77 +1153,29 @@ describe('ExtApi-FileManagerTest', () => {
return
true
}
it
(
'
saveFileSyncTest
'
,
async
()
=>
{
if
(
!
isAndroid
())
{
return
}
console
.
log
(
'
saveFileSyncTest
'
,
'
start
'
)
let
globalTempPath
=
await
getData
(
'
globalTempPath
'
)
let
basePath
=
await
getData
(
'
basePath
'
)
await
page
.
setData
({
logAble
:
false
,
basePath
:
basePath
})
await
clearDir
(
''
)
console
.
log
(
'
saveFileSyncTest
'
,
'
1
'
)
await
page
.
setData
({
logAble
:
false
,
basePath
:
globalTempPath
,
temFile
:
'
save/2.txt
'
,
mkdirFile
:
'
save
'
,
writeFile
:
'
save/2.txt
'
,
accessFile
:
'
2.txt
'
})
await
createFile
()
console
.
log
(
'
saveFileSyncTest
'
,
'
2
'
)
await
page
.
setData
({
basePath
:
basePath
,
writeFile
:
'
save/2.txt
'
,
})
btnSaveFile
=
await
page
.
$
(
'
#btn-save-file-sync
'
)
await
btnSaveFile
.
tap
()
let
btnRemoveSavedFileRet
=
await
page
.
$
(
'
#btn-remove-saved-file
'
)
await
btnRemoveSavedFileRet
.
tap
()
await
isDone
()
console
.
log
(
'
saveFileSyncTest
'
,
'
3
'
)
let
removeSavedFileRet
=
await
getData
(
"
removeSavedFileRet
"
)
console
.
log
(
'
saveFileSyncTest
'
,
'
4
'
)
expect
(
removeSavedFileRet
).
toEqual
(
'
removeSavedFile:ok
'
)
console
.
log
(
'
saveFileSyncTest
'
,
'
5
'
)
await
page
.
setData
({
removeSavedFileRet
:
''
})
console
.
log
(
'
saveFileSyncTest
'
,
'
6
'
)
});
it
(
'
getSavedFileListTest
'
,
async
()
=>
{
if
(
!
isAndroid
())
{
return
}
let
globalTempPath
=
await
getData
(
'
globalTempPath
'
)
let
basePath
=
await
getData
(
'
basePath
'
)
await
page
.
setData
({
logAble
:
false
,
basePath
:
basePath
})
// await page.setData({
// logAble: false,
// basePath: mBasePath
// })
// console.log('getSavedFileListTest', 'start')
// await clearDir('')
// console.log('getSavedFileListTest', 'end')
await
page
.
setData
({
logAble
:
false
,
basePath
:
g
lobalTempPath
,
temFile
:
'
save/2.txt
'
,
mkdirFile
:
'
save
'
,
writeFile
:
'
save/2.txt
'
,
basePath
:
mG
lobalTempPath
,
temFile
:
'
save
3
/2.txt
'
,
mkdirFile
:
'
save
3
'
,
writeFile
:
'
save
3
/2.txt
'
,
accessFile
:
'
2.txt
'
})
await
createFile
()
await
page
.
setData
({
basePath
:
b
asePath
,
basePath
:
mB
asePath
,
writeFile
:
'
save/2.txt
'
,
})
btnSaveFile
=
await
page
.
$
(
'
#btn-save-file-sync
'
)
...
...
@@ -1236,37 +1193,26 @@ describe('ExtApi-FileManagerTest', () => {
if
(
!
isAndroid
())
{
return
}
let
globalTempPath
=
await
getData
(
'
globalTempPath
'
)
let
basePath
=
await
getData
(
'
basePath
'
)
await
page
.
setData
({
logAble
:
false
,
basePath
:
b
asePath
basePath
:
mB
asePath
})
// await clearDir('
')
await
clearDir
(
'
save4
'
)
await
page
.
setData
({
logAble
:
false
,
basePath
:
g
lobalTempPath
,
temFile
:
'
save
/2
.txt
'
,
mkdirFile
:
'
save
'
,
writeFile
:
'
save
/2
.txt
'
,
accessFile
:
'
2
.txt
'
basePath
:
mG
lobalTempPath
,
temFile
:
'
save
4/saveSync
.txt
'
,
mkdirFile
:
'
save
4
'
,
writeFile
:
'
save
4/saveSync
.txt
'
,
accessFile
:
'
saveSync
.txt
'
})
await
createFile
()
await
page
.
setData
({
basePath
:
basePath
,
writeFile
:
'
save/2.txt
'
,
})
btnSaveFile
=
await
page
.
$
(
'
#btn-save-file-sync
'
)
await
btnSaveFile
.
tap
()
await
isDone
()
let
btnRemoveSavedFileRet
=
await
page
.
$
(
'
#btn-remove-saved-file
'
)
await
btnRemoveSavedFileRet
.
tap
()
await
isDone
()
let
removeSavedFileRet
=
await
getData
(
"
removeSavedFileRet
"
)
expect
(
removeSavedFileRet
).
toEqual
(
'
removeSavedFile:ok
'
)
});
//openFiletest openFileSynctest closeTest closeTestSync writeTest writeSyncTest
...
...
@@ -1275,15 +1221,16 @@ describe('ExtApi-FileManagerTest', () => {
return
}
// await clearDir('')
await
page
.
setData
({
basePath
:
mBasePath
,
logAble
:
false
,
mkdirFile
:
'
fd
'
,
writeFile
:
'
fd/1.txt
'
,
readFile
:
'
fd/1.txt
'
})
await
clearDir
(
'
fd
'
)
await
createFile
()
console
.
log
(
'
openFiletest
'
,
'
2
'
)
//openFiletest
let
btnOpenFile
=
await
page
.
$
(
'
#btn-open-file
'
)
await
btnOpenFile
.
tap
()
...
...
@@ -1293,13 +1240,14 @@ describe('ExtApi-FileManagerTest', () => {
await
page
.
setData
({
fd
:
''
,
})
console
.
log
(
'
openFiletest
'
,
'
3
'
)
//openFileSynctest
btnOpenFile
=
await
page
.
$
(
'
#btn-open-file-sync
'
)
await
btnOpenFile
.
tap
()
await
isDone
()
fd
=
await
getData
(
"
fd
"
)
expect
(
fd
).
not
.
toBe
(
''
);
console
.
log
(
'
openFiletest
'
,
'
4
'
)
});
// closeTest closeTestSync
it
(
'
closeTest
'
,
async
()
=>
{
...
...
@@ -1308,13 +1256,15 @@ describe('ExtApi-FileManagerTest', () => {
}
// await clearDir('')
await
page
.
setData
({
basePath
:
mBasePath
,
logAble
:
false
,
mkdirFile
:
'
fd
'
,
writeFile
:
'
fd/1.txt
'
,
readFile
:
'
fd/1.txt
'
})
await
clearDir
(
'
fd
'
)
await
createFile
()
//closeTest
let
btnCloseFile
=
await
page
.
$
(
'
#btn-close-file
'
)
...
...
@@ -1339,14 +1289,16 @@ describe('ExtApi-FileManagerTest', () => {
return
}
console
.
log
(
'
writeTest
'
,
'
start
'
)
// await clearDir('')
await
page
.
setData
({
basePath
:
mBasePath
,
logAble
:
false
,
mkdirFile
:
'
fd
'
,
writeFile
:
'
fd/1.txt
'
,
readFile
:
'
fd/1.txt
'
,
writeData
:
'
我是一只小小鸟
'
})
await
clearDir
(
'
fd
'
)
await
createFile
()
console
.
log
(
'
writeTest
'
,
'
1
'
)
let
btnWrite
=
await
page
.
$
(
'
#btn-write
'
)
...
...
@@ -1409,14 +1361,16 @@ describe('ExtApi-FileManagerTest', () => {
return
}
console
.
log
(
'
ftruncateFileTest
'
,
'
start
'
)
// await clearDir('')
await
page
.
setData
({
basePath
:
mBasePath
,
logAble
:
false
,
mkdirFile
:
'
fd
'
,
writeFile
:
'
fd/1.txt
'
,
readFile
:
'
fd/1.txt
'
,
writeData
:
'
我是一只小小鸟我是
'
})
await
clearDir
(
'
fd
'
)
await
createFile
()
console
.
log
(
'
ftruncateFileTest
'
,
'
1
'
)
btnWrite
=
await
page
.
$
(
'
#btn-write-sync
'
)
...
...
@@ -1444,45 +1398,4 @@ describe('ExtApi-FileManagerTest', () => {
expect
(
ftruncateRet
).
toEqual
(
'
ftruncate:ok
'
)
console
.
log
(
'
ftruncateFileTest
'
,
'
7
'
)
});
//saveFileTest saveFileSyncTest getSavedFileListTest removeSavedFileTest
it
(
'
savefile test
'
,
async
()
=>
{
if
(
!
isAndroid
())
{
return
}
let
globalTempPath
=
await
getData
(
'
globalTempPath
'
)
let
basePath
=
await
getData
(
'
basePath
'
)
await
page
.
setData
({
logAble
:
false
,
basePath
:
basePath
})
// await clearDir('')
await
page
.
setData
({
basePath
:
globalTempPath
,
temFile
:
'
save/1.txt
'
,
mkdirFile
:
'
save
'
,
writeFile
:
'
save/1.txt
'
,
accessFile
:
'
1.txt
'
})
await
createFile
()
await
page
.
setData
({
basePath
:
basePath
,
temFile
:
'
save/1.txt
'
,
})
let
btnSaveFile
=
await
page
.
$
(
'
#btn-save-file
'
)
await
btnSaveFile
.
tap
()
await
isDone
()
let
saveFileRet
=
await
getData
(
"
saveFileRet
"
)
expect
(
saveFileRet
).
not
.
toBe
(
''
);
await
page
.
setData
({
saveFileRet
:
''
})
// await clearDir('')
});
});
pages/API/get-file-system-manager/get-file-system-manager.uvue
浏览文件 @
b88adc20
...
...
@@ -60,7 +60,7 @@
<button class="btnstyle" type="primary" @tap="readCompressedFileSyncTest"
id="btn-compressed-file-sync">同步读取指定压缩类型的本地文件内容</button>
<button class="btnstyle" type="primary" @tap="openFileTest" id="btn-open-file">打开文件{{readFile}},返回描述符</button>
<button class="btnstyle" type="primary" @tap="openFileSyncTest"
<button class="btnstyle" type="primary" @tap="openFileSyncTest
('r')
"
id="btn-open-file-sync">同步打开文件{{readFile}},返回描述符</button>
<button class="btnstyle" type="primary" @tap="closeTest" id="btn-close-file">通过文件描述符关闭文件{{readFile}}</button>
<button class="btnstyle" type="primary" @tap="closeSyncTest"
...
...
@@ -483,8 +483,14 @@
console.log("success to readdir", res)
res.files.forEach(element => {
console.log(element)
let filePath : string
if (this.rmDirFile.length <= 0) {
filePath = `${this.basePath}${element}`
} else {
filePath = `${this.basePath}${this.rmDirFile}/${element}`
}
fileManager.unlink({
filePath:
`${this.basePath}${this.rmDirFile}/${element}`
,
filePath:
filePath
,
success: (res : FileManagerSuccessResult) => {
if (this.logAble) {
this.log += 'unlinkAllFileTest success:' + JSON.stringify(res) + '\n\n'
...
...
@@ -768,7 +774,7 @@
const fileManager = uni.getFileSystemManager()
try {
fileManager.saveFileSync(
`${this.globalTempPath}${this.temFile}`, `${this.basePath}
local
/`)
`${this.globalTempPath}${this.temFile}`, `${this.basePath}/`)
// filePath:`${this.basePath}local/`,)
this.done = true
...
...
@@ -780,20 +786,23 @@
}
},
unzipFileTest: function (_ : any) {
uni.downloadFile({
url: 'https://b2c-store.oss-ap-southeast-1.aliyuncs.com/ceshi/FRT.zip',
success: (res) => {
console.log(res)
const fileManager = uni.getFileSystemManager()
fileManager.unzip({
zipFilePath: `${this.basePath}${this.unzipFile}`
,
zipFilePath: res.tempFilePath
,
targetPath: `${this.basePath}${this.targetZip}`,
success: (res : FileManagerSuccessResult) => {
if (this.logAble) {
this.log += 'save
FileTest success:' + JSON.stringify(res) + '\n\n'
this.log += 'unzip
FileTest success:' + JSON.stringify(res) + '\n\n'
}
console.log('success', res)
},
fail: (res : UniError) => {
if (this.logAble) {
this.log += 'save
FileTest fail:' + JSON.stringify(res) + '\n\n'
this.log += 'unzip
FileTest fail:' + JSON.stringify(res) + '\n\n'
}
console.log('fail', res)
this.lastFailError = res
...
...
@@ -803,6 +812,11 @@
}
} as UnzipFileOptions)
},
fail: (e) => {
console.log(e)
}
})
},
getSavedFileListTest: function () {
const fileManager = uni.getFileSystemManager()
...
...
@@ -875,7 +889,7 @@
readCompressedFileTest() {
const fileManager = uni.getFileSystemManager()
fileManager.readCompressedFile({
filePath:
`${this.basePath}${this.brFile}`
,
filePath:
'/static/filemanager/1.txt.br'
,
compressionAlgorithm: "br",
success: (res : ReadCompressedFileResult) => {
if (this.logAble) {
...
...
@@ -900,7 +914,7 @@
const fileManager = uni.getFileSystemManager()
try {
let data = fileManager.readCompressedFileSync(
`${this.basePath}${this.brFile}`
,
'/static/filemanager/1.txt.br'
,
"br")
if (this.logAble) {
this.log += data
...
...
@@ -982,12 +996,12 @@
}
} as OpenFileOptions)
},
openFileSyncTest() : string {
openFileSyncTest(
param : string
) : string {
const fileManager = uni.getFileSystemManager()
try {
let fd = fileManager.openSync({
filePath: `${this.basePath}${this.readFile}`,
flag:
"r"
,
flag:
param
,
} as OpenFileSyncOptions)
if (this.logAble) {
this.log += 'openFileSyncTest success:' + fd + '\n\n'
...
...
@@ -1010,7 +1024,7 @@
try {
console.log('closeSync')
fileManager.closeSync({
fd: this.openFileSyncTest()
fd: this.openFileSyncTest(
'r'
)
} as CloseSyncOptions)
if (this.logAble) {
this.log += 'closeSyncTest success:' + '\n\n'
...
...
@@ -1028,7 +1042,7 @@
closeTest() {
const fileManager = uni.getFileSystemManager()
fileManager.close({
fd: this.openFileSyncTest(),
fd: this.openFileSyncTest(
'r'
),
success: (res : FileManagerSuccessResult) => {
if (this.logAble) {
this.log += 'closeTest success:' + JSON.stringify(res) + '\n\n'
...
...
@@ -1051,17 +1065,14 @@
},
writeTest() {
const fileManager = uni.getFileSystemManager()
fileManager.open({
filePath: `${this.basePath}${this.readFile}`,
flag: "r+",
success: (res : OpenFileSuccessResult) => {
console.log("success", res)
if (res.fd.length <= 0) {
this.done = true
return
try {
fileManager.mkdirSync(`${this.basePath}${this.mkdirFile}`, true)
} catch (e) {
console.error(e)
}
fileManager.write({
fd: res.fd
,
fd: this.openFileSyncTest('w+')
,
data: this.writeData,
encoding: "utf-8",
success: (res : WriteResult) => {
...
...
@@ -1084,18 +1095,13 @@
} as WriteOptions)
},
fail: (res : UniError) => {
if (this.logAble) {
this.log += 'openFileTest fail:' + JSON.stringify(res) + '\n\n'
}
console.log('fail', res)
this.lastFailError = res
this.done = true
}
} as OpenFileOptions)
},
writeSyncTest() {
const fileManager = uni.getFileSystemManager()
try {
fileManager.mkdirSync(`${this.basePath}${this.mkdirFile}`, true)
} catch (e) {
console.error(e)
}
fileManager.open({
filePath: `${this.basePath}${this.readFile}`,
flag: "r+",
...
...
@@ -1139,7 +1145,7 @@
fstatTest() {
const fileManager = uni.getFileSystemManager()
fileManager.fstat({
fd: this.openFileSyncTest(),
fd: this.openFileSyncTest(
'r'
),
success: (res : FStatSuccessResult) => {
if (this.logAble) {
this.log += 'fstatTest success:' + JSON.stringify(res) + '\n\n'
...
...
@@ -1165,7 +1171,7 @@
try {
let stat =
fileManager.fstatSync({
fd: this.openFileSyncTest(),
fd: this.openFileSyncTest(
'r'
),
} as FStatSyncOptions)
if (this.logAble) {
this.log += 'fstatSyncTest success:' + JSON.stringify(stat) + '\n\n'
...
...
@@ -1182,7 +1188,7 @@
ftruncateFileTest() {
const fileManager = uni.getFileSystemManager()
fileManager.ftruncate({
fd: this.openFileSyncTest(),
fd: this.openFileSyncTest(
'r+'
),
length: 6,
success: (res : FileManagerSuccessResult) => {
if (this.logAble) {
...
...
@@ -1210,7 +1216,7 @@
const fileManager = uni.getFileSystemManager()
try {
fileManager.ftruncateSync({
fd: this.openFileSyncTest(),
fd: this.openFileSyncTest(
'r+'
),
length: 4
} as FTruncateFileSyncOptions)
if (this.logAble) {
...
...
@@ -1226,25 +1232,17 @@
}
},
readZipEntry() {
uni.downloadFile({
url: 'https://b2c-store.oss-ap-southeast-1.aliyuncs.com/ceshi/FRT.zip',
success: (res) => {
console.log(res)
const fileManager = uni.getFileSystemManager()
fileManager.readZipEntry({
filePath: `${this.basePath}${this.readZipFile}`
,
filePath: res.tempFilePath
,
encoding: 'utf-8',
entries: [{
path: 'kkkk',
encoding: 'utf-8'
} as EntryItem,
{
path: 'log/log1.txt',
encoding: 'utf-8'
} as EntryItem,
{
path: 'hello.txt',
encoding: 'utf-8'
} as EntryItem],
success: (res : EntriesResult) => {
if (this.logAble) {
this.log += 'readZipEntry success:' + JSON.stringify(res)
+ '\n\n'
this.log += 'readZipEntry success:size=' + res.result.size
+ '\n\n'
}
console.log("success", res)
},
...
...
@@ -1257,6 +1255,11 @@
}
} as ReadZipEntryOptions)
},
fail: (e) => {
console.log(e)
}
})
},
},
...
...
static/filemanager/1.txt.br
0 → 100644
浏览文件 @
b88adc20
文件已添加
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录