Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
L
learn-online-pc
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
learn-online-pc
Commits
3602241b
提交
3602241b
authored
5月 08, 2020
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
作业支持多道简答题
上级
506bd6c8
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
324 行增加
和
155 行删除
+324
-155
editor.vue
client/src/components/editor.vue
+135
-0
upload.vue
client/src/components/upload.vue
+81
-0
chapterWork.vue
client/src/pages/player/chapterWork/chapterWork.vue
+108
-155
没有找到文件。
client/src/components/editor.vue
0 → 100644
浏览文件 @
3602241b
<
template
>
<div
class=
"editor"
>
<textarea
name=
"editor"
:id=
"textareaElementId"
:disabled=
"disabled"
></textarea>
</div>
</
template
>
<
script
>
import
{
uniqueId
}
from
'lodash'
export
default
{
name
:
'VEditor'
,
props
:
{
value
:
{
type
:
String
},
disabled
:
{
type
:
Boolean
,
default
:
false
}
},
data
()
{
return
{
textareaElementId
:
uniqueId
(
'editor_'
),
ckEditor
:
null
}
},
methods
:
{
createEditor
()
{
const
editor
=
(
this
.
ckEditor
=
CKEDITOR
.
replace
(
this
.
textareaElementId
,
{
height
:
400
,
uiColor
:
'#eeeeee'
,
filebrowserImageUploadUrl
:
'/api/ckeditor/img/upload'
,
// resize_enabled: typeof this.props.resizable === 'boolean' ? this.props.resizable : true,
toolbar
:
[
// { name: 'document', items: ['Source', '-', 'Save', 'NewPage', 'Preview'] },
{
name
:
'styles'
,
items
:
[
'Styles'
,
'Format'
,
'Font'
,
'FontSize'
]
},
{
name
:
'colors'
,
items
:
[
'TextColor'
,
'BGColor'
]
},
{
name
:
'tools'
,
items
:
[
'Maximize'
,
'ShowBlocks'
]
},
// { name: 'clipboard', items: ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo'] },
{
name
:
'editing'
,
items
:
[
'Find'
,
'Replace'
]
},
// { name: 'forms', items: ['Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField'] },
'/'
,
{
name
:
'basicstyles'
,
items
:
[
'Bold'
,
'Italic'
,
'Underline'
,
'Strike'
,
'Subscript'
,
'Superscript'
,
'-'
,
'RemoveFormat'
]
},
{
name
:
'paragraph'
,
items
:
[
'NumberedList'
,
'BulletedList'
,
'-'
,
'Outdent'
,
'Indent'
,
'-'
,
'Blockquote'
,
'CreateDiv'
,
'-'
,
'JustifyLeft'
,
'JustifyCenter'
,
'JustifyRight'
,
'JustifyBlock'
,
'-'
,
'BidiLtr'
,
'BidiRtl'
]
},
{
name
:
'links'
,
items
:
[
'Link'
,
'Unlink'
,
'Anchor'
]
},
{
name
:
'insert'
,
items
:
[
'Image'
,
'Table'
,
'HorizontalRule'
]
}
]
}))
editor
.
on
(
'instanceReady'
,
()
=>
{
const
data
=
this
.
value
editor
.
fire
(
'lockSnapshot'
)
editor
.
setData
(
data
,
{
callback
:
()
=>
{
this
.
bindEvent
()
const
newData
=
editor
.
getData
()
// Locking the snapshot prevents the 'change' event.
// Trigger it manually to update the bound data.
if
(
data
!==
newData
)
{
this
.
$once
(
'input'
,
()
=>
{
this
.
$emit
(
'ready'
,
editor
)
})
this
.
$emit
(
'input'
,
newData
)
}
else
{
this
.
$emit
(
'ready'
,
editor
)
}
editor
.
fire
(
'unlockSnapshot'
)
}
})
})
},
bindEvent
()
{
const
editor
=
this
.
ckEditor
editor
.
on
(
'change'
,
evt
=>
{
const
data
=
editor
.
getData
()
if
(
this
.
value
!==
data
)
{
this
.
$emit
(
'input'
,
data
,
evt
,
editor
)
}
})
editor
.
on
(
'focus'
,
evt
=>
{
this
.
$emit
(
'focus'
,
evt
,
editor
)
})
editor
.
on
(
'blur'
,
evt
=>
{
this
.
$emit
(
'blur'
,
evt
,
editor
)
})
}
},
mounted
()
{
this
.
createEditor
()
},
beforeDestroy
()
{
this
.
ckEditor
&&
this
.
ckEditor
.
destroy
()
this
.
ckEditor
=
null
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
*
{
margin
:
0
;
padding
:
0
;
}
</
style
>
client/src/components/upload.vue
0 → 100644
浏览文件 @
3602241b
<
template
>
<div
class=
"upload"
>
<el-upload
action
:show-file-list=
"false"
:http-request=
"httpRequest"
>
<slot></slot>
<el-button
type=
"text"
size=
"small"
icon=
"el-icon-upload"
>
点击上传
</el-button>
<template
v-slot:tip
>
<div
class=
"el-upload__tips"
>
<slot
name=
"tip"
></slot>
</div>
</
template
>
</el-upload>
<div
class=
"file-list"
v-if=
"value"
>
<div
class=
"file-list-item"
>
<a
:href=
"value"
target=
"_blank"
>
<i
class=
"el-icon-document"
></i>
{{ fileName }}
</a>
<a
:href=
"value"
:download=
"fileName"
target=
"_blank"
>
<el-tooltip
effect=
"dark"
content=
"下载"
>
<i
class=
"el-icon-download"
></i>
</el-tooltip>
</a>
</div>
</div>
</div>
</template>
<
script
>
import
cAction
from
'@action'
export
default
{
name
:
'VUpload'
,
props
:
{
value
:
{
type
:
String
}
},
data
()
{
return
{}
},
computed
:
{
fileName
()
{
return
this
.
value
?
this
.
value
.
split
(
'/'
).
pop
()
:
''
}
},
methods
:
{
httpRequest
(
xhr
)
{
cAction
.
Player
.
uploadFile
({
file
:
xhr
.
file
})
.
then
(
response
=>
{
if
(
response
.
success
)
{
this
.
$emit
(
'input'
,
response
.
url
)
}
})
.
catch
(
error
=>
{
console
.
log
(
error
)
})
},
handleRemove
()
{
this
.
$emit
(
'input'
,
''
)
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.file-list-item
{
display
:
flex
;
margin-bottom
:
10px
;
padding
:
0
10px
;
justify-content
:
space-between
;
line-height
:
30px
;
background-color
:
#fff
;
border-radius
:
4px
;
a
{
text-decoration
:
none
;
color
:
#333
;
&
:hover
{
color
:
#b49441
;
}
}
}
</
style
>
client/src/pages/player/chapterWork/chapterWork.vue
浏览文件 @
3602241b
<
template
>
<
template
>
<div
class=
"play-paper"
>
<div
class=
"play-paper"
>
<div
class=
"play-paper-body"
>
<div
class=
"play-paper-body"
>
<div
class=
"play-paper-title"
><div><h3>
{{
chapterName
}}
</h3></div></div>
<div
class=
"play-paper-title"
>
<div>
<h3>
{{
chapterName
}}
</h3>
</div>
</div>
<div
class=
"play-paper-content play-chapter-work"
>
<div
class=
"play-paper-content play-chapter-work"
>
<template
v-if=
"chapterWork.questions && chapterWork.questions.length"
>
<ul>
<ul>
<template
v-for=
"(item, index) in chapterWork.questions"
>
<li
v-for=
"(item, index) in questions"
:key=
"index"
>
<li
v-bind:key=
"index"
>
<div
class=
"work-number"
>
{{
index
+
1
}}
.
</div>
<div
class=
"work-number"
>
{{
index
+
1
}}
.
</div>
<div
class=
"work-title"
>
<div
class=
"work-title"
>
<div
class=
"edit_html"
v-html=
"item.question_content"
></div>
<div
class=
"edit_html"
v-html=
"item.question_content"
></div>
</div>
</div>
<textarea
id=
"editor-chapterWork"
></textarea>
<!-- 文本内容 -->
<div
style=
"height: 20px;"
></div>
<v-editor
v-model=
"item.descreption"
></v-editor>
<!--
<el-upload
<!-- 上传附件 -->
ref=
"upFile"
<v-upload
v-model=
"item.file_url"
>
请上传对应的文件附件:
</v-upload>
class=
"upload-demo"
action=
""
:multiple=
"false"
:limit=
"1"
:show-file-list=
"false"
:on-change=
"handleChange"
:http-request=
"uploadFile"
:file-list=
"filesArr"
>
请上传对应的文件附件:
<el-button
type=
"text"
>
点击上传
</el-button>
<template
v-if=
"successFileUrl"
>
{{
successFileUrl
.
replace
(
/.*
\/([^\/]
*
\.
docx
)
$/gi
,
'$1'
)
}}
</
template
>
</el-upload>
-->
<
template
v-if=
"successFileUrl"
>
<a
:href=
"successFileUrl"
>
下载已上传文件
</a>
</
template
>
<!-- <div style="height: 20px;"></div> -->
<!-- <p class="help help-file">只支持docx格式的文件,文件小于10M</p> -->
<!-- {answer.file_url && <a style={{display: 'block', marginBottom: '20px', color: 'blue'}} href={answer.file_url} >下载附件</a> } -->
</li>
</li>
</template>
</ul>
</ul>
</template>
<template
v-if=
"deadLine"
>
<
template
v-else
>
<p
style=
"color: red"
>
请于截止日期
{{
deadLine
}}
前提交
</p>
<!--
<p
class=
"no-data"
>
暂无数据
</p>
-->
</
template
>
<!-- <p class="text-danger">{this.state.error}</p> -->
<
template
v-if=
"this.deadLine"
>
<p
style=
"color: red"
>
请于截止日期
{{
this
.
deadLine
}}
前提交
</p>
</
template
>
</
template
>
<div
class=
"area-btns"
>
<div
class=
"area-btns"
>
<el-button
type=
"primary"
@
click=
"submitWork"
:disabled=
"!!homeData.checker_time || deadLineFlag"
>
{{homeData.checker_time ? '已批改' : '提交'}}
</el-button>
<el-button
type=
"primary"
@
click=
"submitWork"
:disabled=
"!!homeData.checker_time || deadLineFlag"
>
{{homeData.checker_time ? '已批改' : '提交'}}
</el-button>
<span
class=
"help-info"
>
  
在获老师批改之前,可以多次提交,将以最后一次提交为准
</span>
<span
class=
"help-info"
>
  
在获老师批改之前,可以多次提交,将以最后一次提交为准
</span>
<
template
v-if=
"homeData.checker_time"
>
<
template
v-if=
"homeData.checker_time"
>
<div
class=
"play-paper-check"
>
<div
class=
"play-paper-check"
>
<h4>
已获批改
<small>
批改于
{{
homeData
.
checker_time
}}
</small></h4>
<h4>
<div
class=
"play-paper-check-item"
><b>
评分:
</b>
{{
homeData
.
score
}}
</div>
已获批改
<small>
批改于
{{
homeData
.
checker_time
}}
</small>
</h4>
<div
class=
"play-paper-check-item"
>
<b>
评分:
</b>
{{
homeData
.
score
}}
</div>
<div
class=
"play-paper-check-item"
>
<div
class=
"play-paper-check-item"
>
<b>
评语:
</b>
<b>
评语:
</b>
<div
class=
"edit_html"
v-html=
"homeData.check_comments"
></div>
<div
class=
"edit_html"
v-html=
"homeData.check_comments"
></div>
...
@@ -65,16 +51,18 @@
...
@@ -65,16 +51,18 @@
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
</template>
<
script
>
<
script
>
import
cAction
from
'@action'
import
cAction
from
'@action'
import
Base64
from
'Base64'
import
Base64
from
'Base64'
import
CKEDITOR
from
'CKEDITOR'
import
VEditor
from
'@/components/editor.vue'
import
VUpload
from
'@/components/upload.vue'
export
default
{
export
default
{
components
:
{
VEditor
,
VUpload
},
props
:
{
props
:
{
chapterId
:
{
type
:
String
,
require
:
false
},
chapterId
:
{
type
:
String
,
require
:
false
},
chapterWork
:
{
type
:
Object
,
require
:
false
},
chapterWork
:
{
type
:
Object
,
require
:
false
},
...
@@ -83,149 +71,114 @@ export default {
...
@@ -83,149 +71,114 @@ export default {
cid
:
{
type
:
String
,
require
:
false
},
cid
:
{
type
:
String
,
require
:
false
},
id
:
{
type
:
String
,
require
:
false
}
id
:
{
type
:
String
,
require
:
false
}
},
},
data
()
{
data
()
{
return
{
return
{
ckeditor
:
null
,
successFileUrl
:
''
,
filesArr
:
[],
file
:
{
id
:
'WU_FILE_0'
,
name
:
''
,
type
:
''
,
lastModifiedDate
:
''
,
size
:
''
,
file
:
''
},
homeData
:
{},
homeData
:
{},
/* 设置是否可以初始化 ckeditor */
setTime
:
null
,
isInit
:
false
,
deadLine
:
''
,
deadLine
:
''
,
deadLineFlag
:
false
deadLineFlag
:
false
,
questions
:
[]
}
}
},
},
/* 本组件 仅支持 单个 ckeditor 存在 */
watch
:
{
mounted
()
{
id
:
{
handler
()
{
this
.
loadAjax
()
this
.
loadAjax
()
}
},
},
updated
()
{},
chapterWork
:
{
destroyed
()
{
handler
(
data
)
{
/* 清空 ckeditor 需要调用方法删除 并 在DOM结构中也移除 */
this
.
questions
=
data
.
questions
.
map
(
item
=>
{
this
.
ckeditor
&&
this
.
ckeditor
.
destroy
(
true
)
return
Object
.
assign
({},
item
,
{
file_url
:
''
,
descreption
:
''
})
this
.
ckeditor
=
null
})
this
.
loadAjax
()
}
}
},
},
methods
:
{
methods
:
{
handleChange
(
file
,
filelist
)
{
loadAjax
()
{
this
.
file
.
name
=
file
.
raw
.
name
const
loading
=
this
.
$loading
({
this
.
file
.
type
=
file
.
raw
.
type
lock
:
true
,
this
.
file
.
lastModifiedDate
=
file
.
raw
.
lastModifiedDate
text
:
''
,
this
.
file
.
size
=
file
.
raw
.
size
spinner
:
''
,
this
.
file
.
file
=
file
.
raw
background
:
'rgba(255, 255, 255, 0.9)'
},
})
loadAjax
()
{
cAction
.
Player
.
getHomework
(
this
.
sid
,
this
.
cid
,
this
.
id
)
const
loading
=
this
.
$loading
({
lock
:
true
,
text
:
''
,
spinner
:
''
,
background
:
'rgba(255, 255, 255, 0.9)'
})
.
then
(
data
=>
{
cAction
.
Player
.
getHomework
(
this
.
sid
,
this
.
cid
,
this
.
id
).
then
(
data
=>
{
this
.
homeData
=
data
this
.
homeData
=
data
}).
catch
(
e
=>
{
this
.
filesArr
.
pop
();
this
.
$message
.
error
(
e
.
message
)
}).
finally
(()
=>
{
this
.
setTime
=
setInterval
(()
=>
{
const
parseAnswers
=
JSON
.
parse
(
data
.
work_contents
)
if
(
document
.
querySelector
(
'#editor-chapterWork'
))
{
this
.
questions
=
this
.
questions
.
map
(
item
=>
{
this
.
initckeditor
()
const
found
=
parseAnswers
.
find
(
if
(
this
.
homeData
.
work_contents
)
{
answer
=>
answer
.
question_id
===
item
.
id
const
json
=
JSON
.
parse
(
this
.
homeData
.
work_contents
)
)
if
(
json
[
0
].
is_encode
d
)
{
if
(
foun
d
)
{
json
[
0
].
descreption
=
Base64
.
decode
(
json
[
0
].
descreption
)
return
Object
.
assign
({},
item
,
{
}
file_url
:
found
.
file_url
,
this
.
successFileUrl
=
json
[
0
].
file_url
descreption
:
Base64
.
decode
(
found
.
descreption
)
this
.
ckeditor
.
setData
(
json
[
0
].
descreption
)
}
)
}
else
{
}
else
{
this
.
successFileUrl
=
''
return
item
this
.
ckeditor
.
setData
(
''
)
}
/* 滚动到头部 */
document
.
querySelector
(
'.play-paper'
).
scrollTop
=
0
clearInterval
(
this
.
setTime
)
}
}
},
50
)
})
})
.
catch
(
e
=>
{
this
.
filesArr
.
pop
()
this
.
$message
.
error
(
e
.
message
)
})
.
finally
(()
=>
{
loading
.
close
()
loading
.
close
()
})
})
setTimeout
(()
=>
{
setTimeout
(()
=>
{
cAction
.
Player
.
getHomeworkStopTime
(
this
.
sid
,
this
.
cid
,
this
.
chapterId
).
then
(
data
=>
{
cAction
.
Player
.
getHomeworkStopTime
(
this
.
sid
,
this
.
cid
,
this
.
chapterId
)
.
then
(
data
=>
{
this
.
deadLine
=
data
.
dead_line
||
''
this
.
deadLine
=
data
.
dead_line
||
''
const
deadLine
=
data
.
dead_line
?
new
Date
(
data
.
dead_line
).
getTime
()
:
''
const
deadLine
=
data
.
dead_line
// deadLine = new Date().getTime() - 100
?
new
Date
(
data
.
dead_line
).
getTime
()
this
.
deadLineFlag
=
((
new
Date
().
getTime
()
>
deadLine
)
&&
!!
deadLine
)
:
''
// console.log(this.deadLine)
this
.
deadLineFlag
=
new
Date
().
getTime
()
>
deadLine
&&
!!
deadLine
}).
catch
(
e
=>
{
this
.
$message
.
error
(
e
.
message
)
}).
finally
(()
=>
{})
})
.
catch
(
e
=>
{
this
.
$message
.
error
(
e
.
message
)
})
},
500
)
},
500
)
},
},
submitWork
()
{
submitWork
()
{
if
(
!
this
.
ckeditor
.
getData
())
{
const
loading
=
this
.
$loading
({
this
.
$message
.
error
(
'请填写内容'
)
lock
:
true
,
return
text
:
''
,
}
spinner
:
''
,
/* 只能提交 单个问题 */
background
:
'rgba(255, 255, 255, 0.9)'
const
loading
=
this
.
$loading
({
lock
:
true
,
text
:
''
,
spinner
:
''
,
background
:
'rgba(255, 255, 255, 0.9)'
})
})
const
str
=
JSON
.
stringify
([{
// 组装提交的数据
question_id
:
this
.
chapterWork
.
questions
[
0
].
id
,
const
answers
=
this
.
questions
.
map
(
item
=>
{
descreption
:
Base64
.
encode
(
this
.
ckeditor
.
getData
()),
return
{
file_url
:
this
.
successFileUrl
,
question_id
:
item
.
id
,
descreption
:
Base64
.
encode
(
item
.
descreption
),
file_url
:
item
.
file_url
,
is_encoded
:
1
is_encoded
:
1
}])
}
})
cAction
.
Player
.
updateHomework
({
cAction
.
Player
.
updateHomework
({
semester_id
:
this
.
sid
,
semester_id
:
this
.
sid
,
course_id
:
this
.
cid
,
course_id
:
this
.
cid
,
chapter_id
:
this
.
chapterId
,
chapter_id
:
this
.
chapterId
,
work_id
:
this
.
id
,
work_id
:
this
.
id
,
work_contents
:
str
,
work_contents
:
JSON
.
stringify
(
answers
)
,
duration
:
30
+
Math
.
floor
(
Math
.
random
()
*
1000
)
duration
:
30
+
Math
.
floor
(
Math
.
random
()
*
1000
)
}).
then
(
data
=>
{
})
.
then
(
data
=>
{
if
(
data
.
status
)
{
if
(
data
.
status
)
{
this
.
$message
({
type
:
'success'
,
message
:
'提交成功,等待批改'
})
this
.
$message
({
type
:
'success'
,
message
:
'提交成功,等待批改'
})
this
.
loadAjax
()
this
.
loadAjax
()
}
}
}).
catch
(
e
=>
{
this
.
filesArr
.
pop
();
this
.
$message
.
error
(
e
.
message
)
}).
finally
(()
=>
{
loading
.
close
()
})
})
},
.
catch
(
e
=>
{
uploadFile
()
{
if
(
!
/
\.(
docx
)
$/gi
.
test
(
this
.
file
.
name
))
{
this
.
$message
.
error
(
'文件格式不对,请重新上传'
)
this
.
filesArr
.
pop
()
return
}
const
loading
=
this
.
$loading
({
lock
:
true
,
text
:
''
,
spinner
:
''
,
background
:
'rgba(255, 255, 255, 0.9)'
})
cAction
.
Player
.
uploadFile
(
this
.
file
).
then
(
data
=>
{
this
.
successFileUrl
=
data
.
url
this
.
filesArr
.
pop
()
this
.
filesArr
.
pop
()
}).
catch
(
e
=>
{
this
.
filesArr
.
pop
();
this
.
$message
.
error
(
e
.
message
)
}).
finally
(()
=>
{
loading
.
close
()
})
this
.
$message
.
error
(
e
.
message
)
},
})
/* 初始化 ckeditor */
.
finally
(()
=>
{
initckeditor
()
{
loading
.
close
()
!
this
.
ckeditor
&&
(
this
.
ckeditor
=
CKEDITOR
.
replace
(
'editor-chapterWork'
,
{
})
height
:
300
,
uiColor
:
'#eeeeee'
,
filebrowserImageUploadUrl
:
'/api/ckeditor/img/upload'
,
// resize_enabled: typeof this.props.resizable === 'boolean' ? this.props.resizable : true,
toolbar
:
[
// { name: 'document', items: ['Source', '-', 'Save', 'NewPage', 'Preview'] },
{
name
:
'styles'
,
items
:
[
'Styles'
,
'Format'
,
'Font'
,
'FontSize'
]
},
{
name
:
'colors'
,
items
:
[
'TextColor'
,
'BGColor'
]
},
{
name
:
'tools'
,
items
:
[
'Maximize'
,
'ShowBlocks'
]
},
// { name: 'clipboard', items: ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo'] },
{
name
:
'editing'
,
items
:
[
'Find'
,
'Replace'
]
},
// { name: 'forms', items: ['Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField'] },
'/'
,
{
name
:
'basicstyles'
,
items
:
[
'Bold'
,
'Italic'
,
'Underline'
,
'Strike'
,
'Subscript'
,
'Superscript'
,
'-'
,
'RemoveFormat'
]
},
{
name
:
'paragraph'
,
items
:
[
'NumberedList'
,
'BulletedList'
,
'-'
,
'Outdent'
,
'Indent'
,
'-'
,
'Blockquote'
,
'CreateDiv'
,
'-'
,
'JustifyLeft'
,
'JustifyCenter'
,
'JustifyRight'
,
'JustifyBlock'
,
'-'
,
'BidiLtr'
,
'BidiRtl'
]
},
{
name
:
'links'
,
items
:
[
'Link'
,
'Unlink'
,
'Anchor'
]
},
{
name
:
'insert'
,
items
:
[
'Image'
,
'Table'
,
'HorizontalRule'
]
}
]
}))
}
},
watch
:
{
id
:
{
handler
()
{
this
.
loadAjax
()
}
}
}
}
}
}
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论