Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
C
center-resource
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
center-resource
Commits
6ae0e86f
提交
6ae0e86f
authored
10月 20, 2022
作者:
matian
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore:帖子管理部分开发
上级
301e4d40
隐藏空白字符变更
内嵌
并排
正在显示
11 个修改的文件
包含
1185 行增加
和
8 行删除
+1185
-8
menus.ts
src/assets/menus.ts
+4
-4
AppUpload.vue
src/components/base/AppUpload.vue
+21
-1
CardListItem.vue
src/components/base/CardListItem.vue
+0
-1
ImportStudent.vue
src/modules/admin/student/components/ImportStudent.vue
+0
-2
api.ts
src/modules/teach/posts/api.ts
+63
-0
AddPostDialog.vue
src/modules/teach/posts/components/AddPostDialog.vue
+293
-0
ReplyPostDialog.vue
src/modules/teach/posts/components/ReplyPostDialog.vue
+116
-0
ReplyPostItem.vue
src/modules/teach/posts/components/ReplyPostItem.vue
+311
-0
index.ts
src/modules/teach/posts/index.ts
+13
-0
List.vue
src/modules/teach/posts/views/List.vue
+268
-0
View.vue
src/modules/teach/posts/views/View.vue
+96
-0
没有找到文件。
src/assets/menus.ts
浏览文件 @
6ae0e86f
...
@@ -166,13 +166,13 @@ export const menus: IMenuItem[] = [
...
@@ -166,13 +166,13 @@ export const menus: IMenuItem[] = [
{
{
tag
:
'v1-teaching'
,
tag
:
'v1-teaching'
,
name
:
'教学管理'
,
name
:
'教学管理'
,
path
:
'/teach'
,
path
:
'/teach
/posts
'
,
children
:
[
children
:
[
{
{
tag
:
'v1-backend-lecturer-list'
,
//
tag: 'v1-backend-lecturer-list',
icon
:
QuestionFilled
,
icon
:
QuestionFilled
,
name
:
'
问答
管理'
,
name
:
'
帖子
管理'
,
path
:
'/teach/
qa
'
path
:
'/teach/
posts
'
},
},
{
{
tag
:
'v1-teaching-paper-paper-list'
,
tag
:
'v1-teaching-paper-paper-list'
,
...
...
src/components/base/AppUpload.vue
浏览文件 @
6ae0e86f
...
@@ -5,7 +5,7 @@ import type { UploadProps, UploadUserFile } from 'element-plus'
...
@@ -5,7 +5,7 @@ import type { UploadProps, UploadUserFile } from 'element-plus'
import
md5
from
'blueimp-md5'
import
md5
from
'blueimp-md5'
import
{
getSignature
}
from
'@/api/base'
import
{
getSignature
}
from
'@/api/base'
const
props
=
withDefaults
(
defineProps
<
{
modelValue
:
string
|
[];
prefix
?:
string
}
>
(),
{
const
props
=
withDefaults
(
defineProps
<
{
modelValue
:
string
|
[];
prefix
?:
string
;
isPost
?:
string
}
>
(),
{
prefix
:
'upload/admin/'
prefix
:
'upload/admin/'
})
})
const
emit
=
defineEmits
([
'update:modelValue'
])
const
emit
=
defineEmits
([
'update:modelValue'
])
...
@@ -27,6 +27,7 @@ const showFileList = computed(() => {
...
@@ -27,6 +27,7 @@ const showFileList = computed(() => {
// 上传之前
// 上传之前
const
handleBeforeUpload
=
async
(
file
:
any
)
=>
{
const
handleBeforeUpload
=
async
(
file
:
any
)
=>
{
console
.
log
(
uploadData
.
value
)
const
fileName
=
file
.
name
const
fileName
=
file
.
name
const
key
=
props
.
prefix
+
md5
(
fileName
+
new
Date
().
getTime
())
+
fileName
.
substr
(
fileName
.
lastIndexOf
(
'.'
))
const
key
=
props
.
prefix
+
md5
(
fileName
+
new
Date
().
getTime
())
+
fileName
.
substr
(
fileName
.
lastIndexOf
(
'.'
))
const
response
:
Record
<
string
,
any
>
=
await
getSignature
()
const
response
:
Record
<
string
,
any
>
=
await
getSignature
()
...
@@ -39,6 +40,25 @@ const handleBeforeUpload = async (file: any) => {
...
@@ -39,6 +40,25 @@ const handleBeforeUpload = async (file: any) => {
url
:
`
${
response
.
host
}
/
${
key
}
`
url
:
`
${
response
.
host
}
/
${
key
}
`
}
}
file
.
url
=
`
${
response
.
host
}
/
${
key
}
`
file
.
url
=
`
${
response
.
host
}
/
${
key
}
`
if
(
props
.
isPost
)
{
if
(
fileList
.
value
.
filter
((
item
:
any
)
=>
item
.
name
.
includes
(
'.png'
)).
length
+
fileList
.
value
.
filter
((
item
:
any
)
=>
item
.
name
.
includes
(
'.jpg'
)).
length
+
fileList
.
value
.
filter
((
item
:
any
)
=>
item
.
name
.
includes
(
'.jpeg'
)).
length
>
10
)
{
const
videoList
=
fileList
.
value
.
filter
((
item
:
any
)
=>
item
.
name
.
includes
(
'.mp4'
))
const
imgList
=
fileList
.
value
.
filter
((
item
:
any
)
=>
!
item
.
name
.
includes
(
'.mp4'
)).
slice
(
0
,
10
)
fileList
.
value
=
[...
videoList
,
...
imgList
]
ElMessage
.
warning
(
'支持最多上传10张图片,格式支持jpg,jpeg,png'
)
}
else
if
(
fileList
.
value
.
filter
((
item
:
any
)
=>
item
.
name
.
includes
(
'.mp4'
)).
length
>
1
)
{
const
videoList
=
fileList
.
value
.
filter
((
item
:
any
)
=>
item
.
name
.
includes
(
'.mp4'
)).
slice
(
0
,
1
)
const
imgList
=
fileList
.
value
.
filter
((
item
:
any
)
=>
!
item
.
name
.
includes
(
'.mp4'
))
fileList
.
value
=
[...
videoList
,
...
imgList
]
console
.
log
(
fileList
.
value
)
ElMessage
.
warning
(
'视频最多长传1个'
)
}
}
}
}
// 上传成功
// 上传成功
...
...
src/components/base/CardListItem.vue
浏览文件 @
6ae0e86f
...
@@ -71,7 +71,6 @@ const bytesToSize = (bytes: number) => {
...
@@ -71,7 +71,6 @@ const bytesToSize = (bytes: number) => {
overflow
:
hidden
;
overflow
:
hidden
;
margin-right
:
20px
;
margin-right
:
20px
;
margin-bottom
:
20px
;
margin-bottom
:
20px
;
// box-shadow: #666666;
box-shadow
:
0
0
10px
0
rgb
(
0
0
0
/
10%
);
box-shadow
:
0
0
10px
0
rgb
(
0
0
0
/
10%
);
background
:
#fff
;
background
:
#fff
;
.card-item-top
{
.card-item-top
{
...
...
src/modules/admin/student/components/ImportStudent.vue
浏览文件 @
6ae0e86f
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
ElMessage
}
from
'element-plus'
import
{
ElMessage
}
from
'element-plus'
import
{
UploadFilled
}
from
'@element-plus/icons-vue'
import
{
splitStrLast
}
from
'@/utils/util'
import
{
splitStrLast
}
from
'@/utils/util'
import
{
importStudent
}
from
'../api'
import
{
importStudent
}
from
'../api'
const
emit
=
defineEmits
<
Emits
>
()
const
emit
=
defineEmits
<
Emits
>
()
...
@@ -20,7 +19,6 @@ interface Emits {
...
@@ -20,7 +19,6 @@ interface Emits {
// 取消
// 取消
const
handleCancel
=
()
=>
{
const
handleCancel
=
()
=>
{
emit
(
'update:isShowImportDialog'
,
false
)
emit
(
'update:isShowImportDialog'
,
false
)
}
}
const
beforeUpload
=
(
file
:
any
)
=>
{
const
beforeUpload
=
(
file
:
any
)
=>
{
...
...
src/modules/teach/posts/api.ts
0 → 100644
浏览文件 @
6ae0e86f
import
httpRequest
from
'@/utils/axios'
// 获取搜索条件
export
function
getConditionList
(
params
?:
{
type
:
string
organ_id
?:
string
semester_id
:
string
course_id
?:
string
})
{
return
httpRequest
.
get
(
'/api/resource/v1/teaching/discussion/search-list'
,
{
params
})
}
// 搜索帖子列表
export
function
getPostsList
(
params
?:
{
organ_id
?:
string
semester_id
?:
string
class_id
?:
string
course_id
?:
string
chapter_id
?:
string
type
?:
string
is_top
?:
string
title
?:
string
name
?:
string
page
?:
string
[
'per-page'
]:
string
})
{
return
httpRequest
.
get
(
'/api/resource/v1/teaching/discussion/list'
,
{
params
})
}
// 搜索帖子列表
export
function
createPosts
(
data
?:
{
organ_id
:
string
semester_id
:
string
class_id
:
string
course_id
:
string
chapter_id
:
string
type
:
string
is_top
:
string
title
:
string
name
:
string
content
:
string
files
:
string
})
{
return
httpRequest
.
post
(
'/api/resource/v1/teaching/discussion/create'
,
data
)
}
// 删除帖子
export
function
delPosts
(
data
?:
{
type
:
string
;
id
:
string
})
{
return
httpRequest
.
post
(
'/api/resource/v1/teaching/discussion/delete'
,
data
)
}
// 置顶帖子
export
function
setTopPosts
(
data
?:
{
discussion_id
:
string
})
{
return
httpRequest
.
post
(
'/api/resource/v1/teaching/discussion/set-top'
,
data
)
}
// 帖子楼层的列表(一级评论列表)
export
function
getPostFirst
(
params
?:
{
discussion_id
:
string
;
page
?:
string
;
[
'per-page'
]:
string
})
{
return
httpRequest
.
get
(
'/api/resource/v1/teaching/discussion/replies'
,
{
params
})
}
// 回复帖子
export
function
replyPosts
(
data
?:
{
discussion_id
:
string
;
reply_type
:
string
;
content
:
string
;
reply_id
:
string
})
{
return
httpRequest
.
post
(
'/api/resource/v1/teaching/discussion/reply'
,
data
)
}
// 帖子楼层回复的列表(二级评论列表)
export
function
getReplyPostItem
(
params
?:
{
reply_id
:
string
;
page
?:
string
;
[
'per-page'
]:
string
})
{
return
httpRequest
.
get
(
'/api/resource/v1/teaching/discussion/comments'
,
{
params
})
}
src/modules/teach/posts/components/AddPostDialog.vue
0 → 100644
浏览文件 @
6ae0e86f
<
script
lang=
"ts"
setup
>
import
AppUpload
from
'@/components/base/AppUpload.vue'
import
VEditor
from
'@/components/tinymce/Index.vue'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
{
useProjectList
}
from
'@/composables/useGetProjectList'
import
{
createPosts
,
getConditionList
}
from
'../api'
import
{
useMapStore
}
from
'@/stores/map'
const
store
=
useMapStore
()
const
typeList
=
store
.
getMapValuesByKey
(
'learning_discussion_type'
)
const
departmentList
:
any
=
useProjectList
(
''
,
'79806610719731712'
).
departmentList
const
ruleFormRef
=
ref
<
FormInstance
>
()
const
emit
=
defineEmits
<
Emits
>
()
defineProps
({
isShowAddDialog
:
{
type
:
Boolean
}
})
interface
Emits
{
(
e
:
'update:isShowAddDialog'
,
isShowAddDialog
:
boolean
):
void
(
e
:
'create'
):
void
}
const
form
:
any
=
reactive
({
organ_id
:
''
,
semester_id
:
''
,
class_id
:
''
,
course_id
:
''
,
chapter_id
:
''
,
type
:
''
,
title
:
''
,
content
:
''
,
files
:
[]
})
const
rules
=
reactive
<
FormRules
>
({
organ_id
:
[{
required
:
true
,
message
:
'请选择所属机构'
,
trigger
:
'change'
}],
semester_id
:
[{
required
:
true
,
message
:
'请选择所属学期'
,
trigger
:
'change'
}],
class_id
:
[{
required
:
true
,
message
:
'请选择所属班级'
,
trigger
:
'change'
}],
course_id
:
[{
required
:
true
,
message
:
'请选择所属课程'
,
trigger
:
'change'
}],
chapter_id
:
[{
required
:
true
,
message
:
'请选择所属章节'
,
trigger
:
'change'
}],
type
:
[{
required
:
true
,
message
:
'请选择类型'
,
trigger
:
'change'
}],
title
:
[{
required
:
true
,
message
:
'请填写标题'
,
trigger
:
'change'
}],
content
:
[{
required
:
true
,
message
:
'请填写正文内容'
,
trigger
:
'blur'
}]
})
const
semesterList
:
any
=
ref
([])
const
classList
:
any
=
ref
([])
const
courseList
:
any
=
ref
([])
const
chapterList
:
any
=
ref
([])
watch
(
()
=>
form
.
organ_id
,
value
=>
{
if
(
value
!==
undefined
||
value
!==
''
)
{
handleGetSemesterList
()
}
}
)
watch
(
()
=>
form
.
semester_id
,
value
=>
{
console
.
log
(
value
,
'999'
)
if
((
form
.
organ_id
!==
undefined
&&
value
!==
undefined
)
||
(
form
.
organ_id
!==
''
&&
value
!==
''
))
{
handleGetClassList
()
}
}
)
watch
(
()
=>
form
.
class_id
,
value
=>
{
console
.
log
(
value
,
'1111'
)
if
(
value
!==
undefined
&&
form
.
organ_id
!==
undefined
&&
form
.
semester_id
!==
undefined
)
{
handleGetCourseList
()
}
}
)
watch
(
()
=>
form
.
course_id
,
value
=>
{
console
.
log
(
value
,
'1111'
)
if
(
value
!==
undefined
&&
form
.
organ_id
!==
undefined
&&
form
.
semester_id
!==
undefined
&&
form
.
course_id
!==
undefined
)
{
handleGetChapterList
()
}
}
)
// 获取学期列表
const
handleGetSemesterList
=
()
=>
{
if
(
form
.
organ_id
!==
''
)
{
const
params
:
any
=
{
type
:
'semester'
,
organ_id
:
form
.
organ_id
}
getConditionList
(
params
).
then
((
res
:
any
)
=>
{
semesterList
.
value
=
res
.
data
})
}
}
// 获取班级列表
const
handleGetClassList
=
()
=>
{
if
(
form
.
organ_id
!==
''
&&
form
.
semester_id
!==
''
)
{
const
params
:
any
=
{
type
:
'class'
,
organ_id
:
form
.
organ_id
,
semester_id
:
form
.
semester_id
}
getConditionList
(
params
).
then
((
res
:
any
)
=>
{
classList
.
value
=
res
.
data
})
}
}
// 获取课程列表
const
handleGetCourseList
=
()
=>
{
if
(
form
.
organ_id
!==
''
&&
form
.
semester_id
!==
''
&&
form
.
class_id
!==
''
)
{
const
params
:
any
=
{
type
:
'course'
,
organ_id
:
form
.
organ_id
,
semester_id
:
form
.
semester_id
}
getConditionList
(
params
).
then
((
res
:
any
)
=>
{
courseList
.
value
=
res
.
data
})
}
}
// 获取课程章节列表
const
handleGetChapterList
=
()
=>
{
if
(
form
.
organ_id
!==
''
&&
form
.
semester_id
!==
''
&&
form
.
class_id
!==
''
&&
form
.
course_id
!==
''
)
{
const
params
:
any
=
{
type
:
'chapter'
,
organ_id
:
form
.
organ_id
,
semester_id
:
form
.
semester_id
,
course_id
:
form
.
course_id
}
getConditionList
(
params
).
then
((
res
:
any
)
=>
{
chapterList
.
value
=
res
.
data
})
}
}
// 取消
const
handleCancel
=
()
=>
{
emit
(
'update:isShowAddDialog'
,
false
)
}
// 确认
const
handleConfirm
=
async
(
formEl
:
FormInstance
|
undefined
)
=>
{
if
(
!
formEl
)
return
await
formEl
.
validate
(
valid
=>
{
if
(
valid
)
{
form
.
files
=
JSON
.
stringify
(
form
.
files
)
const
params
:
any
=
Object
.
assign
({},
form
)
createPosts
(
params
).
then
(()
=>
{
emit
(
'update:isShowAddDialog'
,
false
)
emit
(
'create'
)
})
}
})
}
const
handleChangeOrgan
=
()
=>
{
form
.
semester_id
=
''
form
.
class_id
=
''
form
.
course_id
=
''
form
.
chapter_id
=
''
}
const
handleChangeSemester
=
()
=>
{
form
.
class_id
=
''
form
.
course_id
=
''
form
.
chapter_id
=
''
}
const
handleChangeClass
=
()
=>
{
form
.
course_id
=
''
form
.
chapter_id
=
''
}
const
handleChangeCourse
=
()
=>
{
form
.
chapter_id
=
''
}
</
script
>
<
template
>
<el-dialog
:model-value=
"isShowAddDialog"
draggable
title=
"新建帖子"
:before-close=
"handleCancel"
>
<div
style=
"height: 60vh; overflow-y: auto"
>
<el-form
:model=
"form"
label-position=
"right"
label-width=
"auto"
:rules=
"rules"
ref=
"ruleFormRef"
label-suffix=
":"
>
<el-form-item
label=
"所属机构"
prop=
"organ_id"
>
<el-select
clearable
v-model=
"form.organ_id"
placeholder=
"所属机构"
style=
"width: 100%"
@
change=
"handleChangeOrgan"
>
<el-option
v-for=
"item in departmentList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"所属学期"
prop=
"semester_id"
>
<el-select
clearable
v-model=
"form.semester_id"
placeholder=
"所属学期"
style=
"width: 100%"
@
change=
"handleChangeSemester"
>
<el-option
v-for=
"item in semesterList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"所属班级"
prop=
"class_id"
>
<el-select
clearable
v-model=
"form.class_id"
placeholder=
"所属班级"
style=
"width: 100%"
@
change=
"handleChangeClass"
>
<el-option
v-for=
"item in classList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"所属课程"
prop=
"course_id"
>
<el-select
clearable
v-model=
"form.course_id"
placeholder=
"所属课程"
style=
"width: 100%"
@
change=
"handleChangeCourse"
>
<el-option
v-for=
"item in courseList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"所属章节"
prop=
"chapter_id"
>
<el-select
clearable
v-model=
"form.chapter_id"
placeholder=
"所属章节"
style=
"width: 100%"
>
<el-option
v-for=
"item in chapterList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"类型"
prop=
"type"
>
<el-select
clearable
v-model=
"form.type"
placeholder=
"类型"
style=
"width: 100%"
>
<el-option
v-for=
"item in typeList"
:key=
"item.id"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"标题"
prop=
"title"
>
<el-input
v-model=
"form.title"
/>
</el-form-item>
<el-form-item
label=
"正文内容"
prop=
"content"
>
<v-editor
v-model=
"form.content"
class=
"editor"
:height=
"200"
></v-editor>
</el-form-item>
<el-form-item>
<div>
<div
class=
"upload-video"
>
<div
class=
"upload-box"
>
<AppUpload
accept=
".mp4,.png,.jpeg,.jpg"
:limit=
"11"
:multiple=
"true"
v-model=
"form.files"
:isPost=
"'1'"
></AppUpload>
</div>
</div>
<div
class=
"tips"
>
支持最多上传10张图片,格式支持jpg,jpeg,png,2MB以内
<br
/>
视频最多长传1个,100Mb以内
</div>
</div>
</el-form-item>
</el-form>
</div>
<template
#
footer
>
<span>
<el-button
@
click=
"handleCancel"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleConfirm(ruleFormRef)"
>
确认
</el-button>
</span>
</
template
>
</el-dialog>
</template>
<
style
lang=
"scss"
scoped
>
.upload-video
{
display
:
flex
;
align-items
:
center
;
.upload-btn
{
position
:
absolute
;
top
:
0
;
left
:
0
;
width
:
94px
;
line-height
:
36px
;
background
:
rgba
(
250
,
223
,
230
,
0
.39
);
border
:
1px
solid
#aa1941
;
border-radius
:
20px
;
font-size
:
14px
;
color
:
#aa1941
;
margin-right
:
30px
;
text-align
:
center
;
}
}
.tips
{
font-size
:
12px
;
color
:
#989898
;
}
</
style
>
src/modules/teach/posts/components/ReplyPostDialog.vue
0 → 100644
浏览文件 @
6ae0e86f
<
script
lang=
"ts"
setup
>
import
AppUpload
from
'@/components/base/AppUpload.vue'
import
VEditor
from
'@/components/tinymce/Index.vue'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
{
replyPosts
}
from
'../api'
const
ruleFormRef
=
ref
<
FormInstance
>
()
const
emit
=
defineEmits
<
Emits
>
()
const
props
=
defineProps
({
isShowReplyDialog
:
{
type
:
Boolean
},
discussionId
:
{
type
:
String
}
})
interface
Emits
{
(
e
:
'update:isShowReplyDialog'
,
isShowReplyDialog
:
boolean
):
void
(
e
:
'create'
):
void
}
const
form
:
any
=
reactive
({
content
:
''
,
files
:
[]
})
const
rules
=
reactive
<
FormRules
>
({
content
:
[{
required
:
true
,
message
:
'请填写正文内容'
,
trigger
:
'blur'
}]
})
// 取消
const
handleCancel
=
()
=>
{
emit
(
'update:isShowReplyDialog'
,
false
)
}
// 确认
const
handleConfirm
=
async
(
formEl
:
FormInstance
|
undefined
)
=>
{
if
(
!
formEl
)
return
await
formEl
.
validate
(
valid
=>
{
if
(
valid
)
{
form
.
files
=
JSON
.
stringify
(
form
.
files
)
const
params
:
any
=
Object
.
assign
({
discussion_id
:
props
.
discussionId
,
reply_type
:
'1'
,
reply_id
:
''
},
form
)
replyPosts
(
params
).
then
(()
=>
{
emit
(
'update:isShowReplyDialog'
,
false
)
emit
(
'create'
)
})
}
})
}
</
script
>
<
template
>
<el-dialog
:model-value=
"isShowReplyDialog"
draggable
title=
"回复新楼层"
:before-close=
"handleCancel"
>
<div
style=
"height: 60vh; overflow-y: auto"
>
<el-form
:model=
"form"
label-position=
"right"
label-width=
"auto"
:rules=
"rules"
ref=
"ruleFormRef"
label-suffix=
":"
>
<el-form-item
label=
"正文内容"
prop=
"content"
>
<v-editor
v-model=
"form.content"
class=
"editor"
:height=
"200"
></v-editor>
</el-form-item>
<el-form-item>
<div>
<div
class=
"upload-video"
>
<div
class=
"upload-box"
>
<AppUpload
accept=
".mp4,.png,.jpeg,.jpg"
:limit=
"11"
:multiple=
"true"
v-model=
"form.files"
:isPost=
"'1'"
></AppUpload>
</div>
</div>
<div
class=
"tips"
>
支持最多上传10张图片,格式支持jpg,jpeg,png,2MB以内
<br
/>
视频最多长传1个,100Mb以内
</div>
</div>
</el-form-item>
</el-form>
</div>
<template
#
footer
>
<span>
<el-button
@
click=
"handleCancel"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleConfirm(ruleFormRef)"
>
确认
</el-button>
</span>
</
template
>
</el-dialog>
</template>
<
style
lang=
"scss"
scoped
>
.upload-video
{
display
:
flex
;
align-items
:
center
;
.upload-btn
{
position
:
absolute
;
top
:
0
;
left
:
0
;
width
:
94px
;
line-height
:
36px
;
background
:
rgba
(
250
,
223
,
230
,
0
.39
);
border
:
1px
solid
#aa1941
;
border-radius
:
20px
;
font-size
:
14px
;
color
:
#aa1941
;
margin-right
:
30px
;
text-align
:
center
;
}
}
.tips
{
font-size
:
12px
;
color
:
#989898
;
}
</
style
>
src/modules/teach/posts/components/ReplyPostItem.vue
0 → 100644
浏览文件 @
6ae0e86f
<
script
lang=
"ts"
setup
>
import
{
replyPosts
,
getReplyPostItem
}
from
'../api'
const
emit
=
defineEmits
<
Emits
>
()
const
props
=
defineProps
({
firstFloor
:
{
type
:
Object
},
discussionId
:
{
type
:
String
}
})
interface
Emits
{
(
e
:
'update'
):
void
}
const
reply_content
=
ref
(
''
)
const
isShowReply
=
ref
(
false
)
const
id
=
ref
(
''
)
const
postItem
:
any
=
ref
({})
const
postItemList
=
ref
(
JSON
.
parse
(
JSON
.
stringify
(
props
.
firstFloor
?.
comments
)))
// 最上面的回复
const
handleReply
=
(
val
:
any
)
=>
{
isShowReply
.
value
=
true
id
.
value
=
val
.
id
}
// 回复列表下面的回复
const
handleReplyItem
=
(
val
:
any
)
=>
{
isShowReply
.
value
=
true
postItem
.
value
=
val
}
// 提交回复
const
handleReplySubmit
=
()
=>
{
const
params
:
any
=
{
discussion_id
:
props
.
discussionId
,
reply_type
:
'2'
,
content
:
reply_content
.
value
,
reply_id
:
props
.
firstFloor
?.
id
}
replyPosts
(
params
).
then
(()
=>
{
emit
(
'update'
)
reply_content
.
value
=
''
})
}
// 查看更多
const
handleViewMore
=
(
val
:
any
)
=>
{
handleGetItemFloor
(
val
)
}
// 获取评论二级列表数据
const
handleGetItemFloor
=
(
val
:
any
)
=>
{
const
params
:
any
=
{
reply_id
:
val
}
getReplyPostItem
(
params
).
then
(
res
=>
{
postItemList
.
value
=
res
.
data
.
list
})
}
const
imgUrl
=
computed
(()
=>
{
if
(
props
.
firstFloor
?.
tag
===
'学者'
)
{
return
'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/xz.png'
}
else
if
(
props
.
firstFloor
?.
tag
===
'大师'
)
{
return
'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/ds.png'
}
else
if
(
props
.
firstFloor
?.
tag
===
'智者'
)
{
return
'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/zz.png'
}
else
if
(
props
.
firstFloor
?.
tag
===
'学徒'
)
{
return
'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/xt.png'
}
})
</
script
>
<
template
>
<div
class=
"main_post"
>
<div
class=
"post_left"
>
<img
:src=
"
props.firstFloor?.avatar ||
'https://img2.baidu.com/it/u=655740671,4003943401&fm=253&fmt=auto&app=138&f=JPEG?w=400&h=400'
"
class=
"left_avatar"
/>
<div
class=
"left_name"
>
{{
props
.
firstFloor
?.
name
}}
</div>
<div
class=
"left_remark"
v-if=
"props.firstFloor?.tag !== '老师'"
>
<img
:src=
"imgUrl"
class=
"remark_img"
/>
<div
class=
"remark_name"
>
{{
props
.
firstFloor
?.
tag
}}
</div>
</div>
<div
class=
"left_remark"
v-else
>
<div
class=
"remark_name1"
>
{{
props
.
firstFloor
?.
tag
}}
</div>
</div>
</div>
<div
class=
"post_right"
>
<div
class=
"right_con"
v-html=
"props.firstFloor?.content"
></div>
<template
v-if=
"props.firstFloor?.files.length > 0"
>
<div
class=
"right_files"
v-for=
"(it, index) in props.firstFloor?.files"
:key=
"index"
>
<img
:src=
"it?.url"
alt=
""
v-if=
"it?.name.includes('.png') || it?.name.includes('.jpg') || it?.name.includes('.jpeg')"
style=
"width: 100px"
/>
<video
:src=
"it?.url"
v-if=
"it?.name.includes('.mp4')"
></video>
</div>
</
template
>
<div
class=
"right_time"
>
发表于 {{ props.firstFloor?.updated_time }}
</div>
<el-link
:underline=
"false"
class=
"right_btn"
@
click=
"handleReply(props.firstFloor)"
>
<img
src=
"https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/reply_btn.png"
alt=
""
/>
<div
class=
"btn_txt"
>
回复
</div>
</el-link>
<div
class=
"right_list"
v-if=
"props.firstFloor?.comments.length > 0"
>
<div
v-for=
"(item, index) in postItemList"
:key=
"index"
>
<div
class=
"list_top"
>
<img
:src=
"item.avatar || 'https://webapp-pub.ezijing.com/center_resource/avatar.png'"
alt=
""
class=
"top_img"
/>
<div
class=
"top_name"
v-html=
"
item.from_name !== item.to_name
? `${item.from_name} 回复 ${item.to_name}`
: `${item.to_name}`
"
></div>
</div>
<div
class=
"list_con"
v-html=
"item.content"
></div>
<div
class=
"list_bottom"
>
<div
class=
"bottom_time"
>
来自于{{ item.updated_time }}
</div>
<el-link
:underline=
"false"
class=
"bottom_reply"
@
click=
"handleReplyItem(item)"
>
<img
src=
"https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/reply_btn.png"
alt=
""
/>
<div
class=
"reply_txt"
@
click=
"handleReplyItem(item)"
>
回复
</div>
</el-link>
</div>
</div>
<div
class=
"list_more"
v-if=
"props.firstFloor?.comments_total > 3"
>
<el-link
:underline=
"false"
type=
"primary"
size=
"mini"
@
click=
"handleViewMore(props.firstFloor?.id)"
>
查看更多
</el-link
>
</div>
</div>
<div
class=
"reply_input"
v-if=
"isShowReply === true"
>
<el-input
v-model=
"reply_content"
:autosize=
"{ minRows: 2, maxRows: 4 }"
type=
"textarea"
style=
"width: 100%"
:placeholder=
"postItem.to_name ? `回复${postItem.to_name}` : ''"
/>
<el-button
class=
"input_btn"
type=
"primary"
@
click=
"handleReplySubmit"
>
发表回复
</el-button>
</div>
</div>
</div>
<div
class=
"line"
></div>
</template>
<
style
lang=
"scss"
scoped
>
.main_post
{
width
:
100%
;
display
:
flex
;
.post_left
{
width
:
240px
;
padding
:
40px
;
background
:
#f9f9fc
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
.left_avatar
{
width
:
100px
;
height
:
100px
;
}
.left_name
{
font-size
:
16px
;
font-weight
:
400
;
color
:
#333333
;
margin-top
:
14px
;
}
.left_remark
{
text-align
:
center
;
margin-top
:
8px
;
.remark_img
{
width
:
40px
;
height
:
40px
;
}
.remark_name
{
font-size
:
10px
;
font-weight
:
400
;
color
:
#666666
;
margin-top
:
2px
;
}
.remark_name1
{
width
:
42px
;
height
:
20px
;
border
:
1px
solid
#ba143e
;
border-radius
:
10px
;
font-size
:
10px
;
font-weight
:
400
;
color
:
#ba143e
;
line-height
:
20px
;
text-align
:
center
;
}
}
}
.post_right
{
width
:
100%
;
padding
:
40px
21px
0
40px
;
display
:
flex
;
flex-direction
:
column
;
.right_con
{
font-size
:
16px
;
font-weight
:
400
;
color
:
#666666
;
line-height
:
27px
;
}
.right_time
{
font-size
:
14px
;
font-weight
:
400
;
line-height
:
24px
;
color
:
#b4b4b4
;
margin-top
:
20px
;
}
.right_btn
{
align-self
:
flex-end
;
display
:
flex
;
img
{
width
:
22px
;
height
:
22px
;
}
.btn_txt
{
margin-left
:
9px
;
}
}
.reply_input
{
margin-top
:
20px
;
display
:
flex
;
flex-direction
:
column
;
.input_txt
{
font-size
:
18px
;
font-weight
:
400
;
line-height
:
31px
;
color
:
#333333
;
margin
:
20px
0
;
}
.input_btn
{
align-self
:
flex-end
;
margin
:
20px
0
;
}
}
.right_list
{
padding
:
20px
;
background
:
#f4f5f8
;
margin
:
20px
0
40px
0
;
border-radius
:
6px
;
display
:
flex
;
flex-direction
:
column
;
.list_more
{
align-self
:
center
;
}
.list_top
{
display
:
flex
;
.top_img
{
width
:
30px
;
height
:
30px
;
}
.top_name
{
font-size
:
16px
;
font-weight
:
400
;
line-height
:
27px
;
color
:
#666666
;
margin
:
0
10px
;
}
}
.list_con
{
font-size
:
16px
;
font-weight
:
400
;
line-height
:
27px
;
color
:
#666666
;
padding-left
:
40px
;
}
.list_bottom
{
display
:
flex
;
justify-content
:
space-between
;
padding-left
:
40px
;
.bottom_time
{
font-size
:
12px
;
font-weight
:
400
;
line-height
:
20px
;
color
:
#b4b4b4
;
}
.bottom_reply
{
display
:
flex
;
align-items
:
center
;
cursor
:
pointer
;
img
{
width
:
20px
;
height
:
20px
;
}
.reply_txt
{
font-size
:
16px
;
font-weight
:
400
;
line-height
:
27px
;
color
:
#9b9b9b
;
margin-left
:
9px
;
}
}
}
}
}
}
.line
{
width
:
99%
;
height
:
4px
;
background
:
#e8e8e8
;
}
</
style
>
src/modules/teach/posts/index.ts
0 → 100644
浏览文件 @
6ae0e86f
import
type
{
RouteRecordRaw
}
from
'vue-router'
import
AppLayout
from
'@/components/layout/Index.vue'
export
const
routes
:
Array
<
RouteRecordRaw
>
=
[
{
path
:
'/teach/posts'
,
component
:
AppLayout
,
children
:
[
{
path
:
''
,
component
:
()
=>
import
(
'./views/List.vue'
)
},
{
path
:
'/teach/posts/detail'
,
component
:
()
=>
import
(
'./views/View.vue'
)
}
]
}
]
src/modules/teach/posts/views/List.vue
0 → 100644
浏览文件 @
6ae0e86f
<
script
setup
lang=
"ts"
>
import
{
ElMessage
}
from
'element-plus'
import
{
getConditionList
,
getPostsList
,
delPosts
,
setTopPosts
}
from
'../api'
import
AddPostDialog
from
'../components/AddPostDialog.vue'
import
{
useProjectList
}
from
'@/composables/useGetProjectList'
import
{
useUserStore
}
from
'@/stores/user'
import
{
useMapStore
}
from
'@/stores/map'
const
router
=
useRouter
()
const
store
=
useMapStore
()
const
typeList
=
store
.
getMapValuesByKey
(
'learning_discussion_type'
)
console
.
log
(
typeList
,
'123'
)
const
departmentList
:
any
=
useProjectList
(
''
,
'79806610719731712'
).
departmentList
// 判断当前用户是不是超级管理员
const
user
=
useUserStore
().
roles
const
isAdmin
=
!!
user
.
find
((
item
:
any
)
=>
item
.
name
===
'超级管理员'
)
const
appList
=
ref
()
const
isShowAddDialog
=
ref
(
false
)
const
organ_id
=
ref
(
''
)
const
semester_id
=
ref
(
''
)
const
course_id
=
ref
(
''
)
const
class_id
=
ref
(
''
)
const
chapter_id
=
ref
(
''
)
const
semesterList
:
any
=
ref
([])
const
classList
:
any
=
ref
([])
const
courseList
:
any
=
ref
([])
const
chapterList
:
any
=
ref
([])
const
listOptions
=
$computed
(()
=>
{
return
{
remote
:
{
params
:
{
organ_id
:
''
,
semester_id
:
''
,
class_id
:
''
,
course_id
:
''
,
chapter_id
:
''
,
type
:
''
,
is_top
:
''
,
title
:
''
,
name
:
''
},
beforeRequest
(
params
:
any
)
{
if
(
params
.
organ_id
!==
''
)
{
organ_id
.
value
=
params
.
organ_id
}
if
(
params
.
semester_id
!==
''
)
{
semester_id
.
value
=
params
.
semester_id
}
if
(
params
.
course_id
!==
''
)
{
course_id
.
value
=
params
.
course_id
}
if
(
params
.
chapter_id
!==
''
)
{
chapter_id
.
value
=
params
.
chapter_id
}
if
(
params
.
class_id
!==
''
)
{
class_id
.
value
=
params
.
class_id
}
return
params
},
httpRequest
:
getPostsList
},
filters
:
[
{
type
:
'select'
,
prop
:
'organ_id'
,
slots
:
'filter-department'
},
{
type
:
'select'
,
prop
:
'semester_id'
,
slots
:
'filter-semester'
},
{
type
:
'select'
,
prop
:
'class_id'
,
slots
:
'filter-class'
},
{
type
:
'select'
,
prop
:
'course_id'
,
slots
:
'filter-course'
},
{
type
:
'select'
,
prop
:
'chapter_id'
,
slots
:
'filter-chapter'
},
{
type
:
'select'
,
prop
:
'type'
,
label
:
'帖子类型:'
,
placeholder
:
'帖子类型'
,
options
:
typeList
,
labelKey
:
'label'
,
valueKey
:
'value'
},
{
type
:
'select'
,
prop
:
'is_top'
,
label
:
'是否置顶:'
,
placeholder
:
'是否置顶'
,
options
:
[
{
label
:
'是'
,
value
:
'1'
},
{
label
:
'否'
,
value
:
'0'
}
]
},
{
type
:
'input'
,
prop
:
'title'
,
label
:
'帖子标题:'
,
placeholder
:
'帖子标题'
},
{
type
:
'input'
,
prop
:
'name'
,
label
:
'发帖人:'
,
placeholder
:
'发帖人'
}
],
columns
:
[
{
label
:
'序号'
,
type
:
'index'
,
align
:
'center'
,
width
:
'100px'
},
{
label
:
'帖子标题'
,
prop
:
'title'
,
align
:
'center'
},
{
label
:
'帖子类型'
,
prop
:
'type_name'
,
align
:
'center'
},
{
label
:
'发帖人'
,
prop
:
'sso_name'
,
align
:
'center'
},
{
label
:
'所属课程'
,
prop
:
'course_name'
,
align
:
'center'
},
{
label
:
'所属班级'
,
prop
:
'class_name'
,
align
:
'center'
},
{
label
:
'所属学期'
,
prop
:
'semester_name'
,
align
:
'center'
},
{
label
:
'所属机构/院校'
,
prop
:
'organ_name'
,
align
:
'center'
},
{
label
:
'回复数量'
,
prop
:
'reply_count'
,
align
:
'center'
},
{
label
:
'更新时间'
,
prop
:
'updated_time'
,
align
:
'center'
},
{
label
:
'操作'
,
slots
:
'table-operate'
,
align
:
'center'
,
fixed
:
'right'
,
width
:
300
}
]
}
})
const
handleAddPosts
=
()
=>
{
isShowAddDialog
.
value
=
true
}
// 刷新页面
const
handleRefresh
=
()
=>
{
appList
.
value
.
refetch
()
}
console
.
log
(
listOptions
)
watch
(
()
=>
organ_id
.
value
,
value
=>
{
if
(
value
!==
undefined
)
{
handleGetSemesterList
()
}
}
)
watch
(
()
=>
semester_id
.
value
,
value
=>
{
console
.
log
(
value
,
'999'
)
if
(
value
!==
undefined
)
{
handleGetClassList
()
}
}
)
watch
(
()
=>
course_id
.
value
,
value
=>
{
console
.
log
(
value
,
'1111'
)
if
(
value
!==
undefined
&&
organ_id
.
value
!==
undefined
&&
semester_id
.
value
!==
undefined
)
{
handleGetchaptereList
()
}
}
)
// 获取学期列表
const
handleGetSemesterList
=
()
=>
{
const
params
:
any
=
{
type
:
'semester'
,
organ_id
:
organ_id
.
value
}
getConditionList
(
params
).
then
((
res
:
any
)
=>
{
semesterList
.
value
=
res
.
data
})
}
// 获取班级列表
const
handleGetClassList
=
()
=>
{
const
params
:
any
=
{
type
:
'class'
,
organ_id
:
organ_id
.
value
,
semester_id
:
semester_id
.
value
}
getConditionList
(
params
).
then
((
res
:
any
)
=>
{
classList
.
value
=
res
.
data
handleGetCourseList
()
})
}
// 获取课程列表
const
handleGetCourseList
=
()
=>
{
const
params
:
any
=
{
type
:
'course'
,
organ_id
:
organ_id
.
value
,
semester_id
:
semester_id
.
value
}
getConditionList
(
params
).
then
((
res
:
any
)
=>
{
courseList
.
value
=
res
.
data
})
}
// 获取课程章节列表
const
handleGetchaptereList
=
()
=>
{
const
params
:
any
=
{
type
:
'chapter'
,
organ_id
:
organ_id
.
value
,
semester_id
:
semester_id
.
value
,
course_id
:
course_id
.
value
}
getConditionList
(
params
).
then
((
res
:
any
)
=>
{
chapterList
.
value
=
res
.
data
})
}
// 删除帖子
const
handleDel
=
(
row
:
any
)
=>
{
const
params
:
any
=
{
id
:
row
.
id
,
type
:
'discussion'
}
delPosts
(
params
).
then
(()
=>
{
ElMessage
.
success
(
'帖子删除成功'
)
handleRefresh
()
})
}
// 置顶帖子
const
handleSetTop
=
(
row
:
any
)
=>
{
setTopPosts
({
discussion_id
:
row
.
id
}).
then
(()
=>
{
ElMessage
.
success
(
'帖子置顶成功'
)
handleRefresh
()
})
}
const
handleReply
=
(
row
:
any
)
=>
{
router
.
push
({
path
:
'/teach/posts/detail'
,
query
:
{
id
:
row
.
id
}
})
}
</
script
>
<
template
>
<AppCard
title=
"帖子管理"
>
<AppList
v-bind=
"listOptions"
ref=
"appList"
border
stripe
>
<el-button
type=
"primary"
round
@
click=
"handleAddPosts"
style=
"margin-bottom: 20px"
>
新建帖子
</el-button>
<template
v-if=
"isAdmin"
#
filter-department=
"
{ params }">
<div
class=
"name"
style=
"font-size: 14px; color: #606266; padding-right: 12px"
>
所属部门/学校:
</div>
<el-select
@
change=
"handleRefresh"
clearable
v-model=
"params.organ_id"
placeholder=
"请选择所属部门/学校"
>
<el-option
v-for=
"item in departmentList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</
template
>
<
template
#
filter-semester=
"{ params }"
>
<div
class=
"name"
style=
"font-size: 14px; color: #606266; padding-right: 12px"
>
所属学期:
</div>
<el-select
@
change=
"handleRefresh"
clearable
v-model=
"params.semester_id"
placeholder=
"请选择所属学期"
no-data-text=
"请先选择所属部门/学校"
>
<el-option
v-for=
"item in semesterList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</
template
>
<
template
#
filter-class=
"{ params }"
>
<div
class=
"name"
style=
"font-size: 14px; color: #606266; padding-right: 12px"
>
所属班级:
</div>
<el-select
@
change=
"handleRefresh"
clearable
v-model=
"params.class_id"
placeholder=
"请选择所属班级"
no-data-text=
"请先选择所属学期"
>
<el-option
v-for=
"item in classList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</
template
>
<
template
#
filter-course=
"{ params }"
>
<div
class=
"name"
style=
"font-size: 14px; color: #606266; padding-right: 12px"
>
所属课程:
</div>
<el-select
@
change=
"handleRefresh"
clearable
v-model=
"params.course_id"
placeholder=
"请选择所属课程"
no-data-text=
"请先选择所属班级、学期"
>
<el-option
v-for=
"item in courseList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</
template
>
<
template
#
filter-chapter=
"{ params }"
>
<div
class=
"name"
style=
"font-size: 14px; color: #606266; padding-right: 12px"
>
所属章节:
</div>
<el-select
@
change=
"handleRefresh"
clearable
v-model=
"params.chapter_id"
placeholder=
"请选择所属章节"
no-data-text=
"请先选择所属课程"
>
<el-option
v-for=
"item in chapterList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</
template
>
<
template
#
table-operate=
"{ row }"
>
<el-link
type=
"primary"
plain
@
click=
"handleReply(row)"
>
添加回复
</el-link>
<el-link
type=
"primary"
plain
style=
"margin: 0 10px"
@
click=
"handleSetTop(row)"
>
{{
row
.
is_top
===
'1'
?
'取消置顶'
:
'置顶'
}}
</el-link>
<el-link
type=
"primary"
plain
@
click=
"handleDel(row)"
>
删除
</el-link>
</
template
>
</AppList>
</AppCard>
<AddPostDialog
v-model:isShowAddDialog=
"isShowAddDialog"
v-if=
"isShowAddDialog"
@
create=
"handleRefresh"
/>
</template>
src/modules/teach/posts/views/View.vue
0 → 100644
浏览文件 @
6ae0e86f
<
script
setup
lang=
"ts"
>
import
ReplyPostDialog
from
'../components/ReplyPostDialog.vue'
import
ReplyPostItem
from
'../components/ReplyPostItem.vue'
import
{
getPostFirst
}
from
'../api'
const
route
=
useRoute
()
const
isShowReplyDialog
=
ref
(
false
)
const
postInfo
:
any
=
ref
({})
const
firstPostList
:
any
=
ref
([])
const
discussionId
:
any
=
route
.
query
.
id
const
currentPage
=
ref
(
1
)
const
page
=
reactive
({
size
:
10
,
currentPage
:
1
})
onMounted
(()
=>
{
handleGetFirstFloor
()
})
const
handleGetFirstFloor
=
()
=>
{
const
params
:
any
=
{
discussion_id
:
discussionId
}
getPostFirst
(
params
).
then
(
res
=>
{
postInfo
.
value
=
res
.
data
.
info
firstPostList
.
value
=
res
.
data
.
list
firstPostList
.
value
.
map
((
item
:
any
)
=>
{
item
.
files
=
JSON
.
parse
(
item
.
files
)
})
})
}
const
handleReplyNewFloor
=
()
=>
{
isShowReplyDialog
.
value
=
true
}
const
handleSizeChange
=
(
val
:
any
)
=>
{
page
.
size
=
val
}
const
handleCurrentChange
=
(
val
:
any
)
=>
{
page
.
currentPage
=
val
}
</
script
>
<
template
>
<AppCard
title=
"帖子详情"
>
<div
class=
"card"
>
<div
class=
"card-header"
>
<span>
{{
postInfo
.
title
}}
</span>
<div
class=
"content_btn"
>
<el-button
type=
"primary"
round
>
删除当前帖子
</el-button>
<el-button
@
click=
"handleReplyNewFloor"
round
>
回复新楼层
</el-button>
</div>
</div>
<ReplyPostItem
v-for=
"(item, index) in firstPostList.slice((page.currentPage - 1) * page.size, page.currentPage * page.size)"
:key=
"index"
:firstFloor=
"item"
:discussionId=
"discussionId"
@
update=
"handleGetFirstFloor"
/>
<el-pagination
class=
"pagination"
v-model:currentPage=
"currentPage"
:page-size=
"page.size"
layout=
"total, sizes, prev, pager, next, jumper"
:page-sizes=
"[5, 10, 20, 30, 50]"
:total=
"firstPostList.length"
@
size-change=
"handleSizeChange"
@
current-change=
"handleCurrentChange"
>
</el-pagination>
</div>
</AppCard>
<ReplyPostDialog
v-model:isShowReplyDialog=
"isShowReplyDialog"
v-if=
"isShowReplyDialog"
:discussionId=
"discussionId"
@
create=
"handleGetFirstFloor"
/>
</
template
>
<
style
lang=
"scss"
scoped
>
.card
{
border
:
1px
solid
#e5e5e5
;
border-radius
:
6px
;
background
:
#ffffff
;
display
:
flex
;
flex-direction
:
column
;
.card-header
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
padding-left
:
19px
;
background
:
rgba
(
255
,
255
,
255
,
0
.39
);
padding
:
20px
46px
20px
19px
;
box-shadow
:
0
0
10px
0
#e4e4e4
;
}
.pagination
{
margin
:
30px
20px
50px
0
;
align-self
:
flex-end
;
}
}
</
style
>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论