提交 3623e568 authored 作者: matian's avatar matian

帖子管理更新

上级 16076d23
...@@ -169,7 +169,7 @@ export const menus: IMenuItem[] = [ ...@@ -169,7 +169,7 @@ export const menus: IMenuItem[] = [
path: '/teach/posts', path: '/teach/posts',
children: [ children: [
{ {
// tag: 'v1-backend-lecturer-list', tag: 'v1-teaching-discussion',
icon: QuestionFilled, icon: QuestionFilled,
name: '帖子管理', name: '帖子管理',
path: '/teach/posts' path: '/teach/posts'
......
...@@ -54,6 +54,11 @@ const handleReplySubmit = () => { ...@@ -54,6 +54,11 @@ const handleReplySubmit = () => {
const handleViewMore = (val: any) => { const handleViewMore = (val: any) => {
handleGetItemFloor(val) handleGetItemFloor(val)
} }
// 收起帖子
const handleClosePosts = () => {
postItemList.value = props.firstFloor?.comments
currentPage.value = 1
}
// 获取评论二级列表数据 // 获取评论二级列表数据
const handleGetItemFloor = (val: any) => { const handleGetItemFloor = (val: any) => {
const params: any = { const params: any = {
...@@ -71,6 +76,7 @@ const handleGetItemFloor = (val: any) => { ...@@ -71,6 +76,7 @@ const handleGetItemFloor = (val: any) => {
totalItem.value = res.data.total totalItem.value = res.data.total
}) })
} }
// 用户标签图片
const imgUrl = computed(() => { const imgUrl = computed(() => {
if (props.firstFloor?.tag === '学者') { if (props.firstFloor?.tag === '学者') {
return 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/xz.png' return 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/xz.png'
...@@ -107,13 +113,7 @@ const handleDelFloor = (val: any) => { ...@@ -107,13 +113,7 @@ const handleDelFloor = (val: any) => {
<div class="post_left"> <div class="post_left">
<div class="left_logo" v-if="props.firstFloor?.floor === 1"></div> <div class="left_logo" v-if="props.firstFloor?.floor === 1"></div>
<div class="left_logo_txt">楼主</div> <div class="left_logo_txt">楼主</div>
<img <img :src="props.firstFloor?.avatar" class="left_avatar" />
: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_name">{{ props.firstFloor?.name }}</div>
<div class="left_remark" v-if="props.firstFloor?.tag !== '老师'"> <div class="left_remark" v-if="props.firstFloor?.tag !== '老师'">
<img :src="imgUrl" class="remark_img" /> <img :src="imgUrl" class="remark_img" />
...@@ -137,14 +137,16 @@ const handleDelFloor = (val: any) => { ...@@ -137,14 +137,16 @@ const handleDelFloor = (val: any) => {
<template v-if="props.firstFloor?.files.length > 0"> <template v-if="props.firstFloor?.files.length > 0">
<div class="right_files"> <div class="right_files">
<template v-for="(it, index) in props.firstFloor?.files" :key="index"> <template v-for="(it, index) in props.firstFloor?.files" :key="index">
<el-image <div class="files_img">
:src="it?.url" <el-image
v-if="it?.name.includes('.png') || it?.name.includes('.jpg') || it?.name.includes('.jpeg')" :src="it?.url"
style="width: 100px" v-if="it?.name.includes('.png') || it?.name.includes('.jpg') || it?.name.includes('.jpeg')"
:preview-src-list="previewList" :preview-src-list="previewList"
:initial-index="4" :initial-index="4"
fit="cover" fit="cover"
/> />
<div class="img_txt">查看大图</div>
</div>
<video v-if="it?.name.includes('.mp4')" controls id="video"> <video v-if="it?.name.includes('.mp4')" controls id="video">
<source :src="it?.url" /> <source :src="it?.url" />
</video> </video>
...@@ -159,19 +161,19 @@ const handleDelFloor = (val: any) => { ...@@ -159,19 +161,19 @@ const handleDelFloor = (val: any) => {
<div class="right_list" v-if="props.firstFloor?.comments_total > 0"> <div class="right_list" v-if="props.firstFloor?.comments_total > 0">
<div v-for="(item, index) in postItemList" :key="index"> <div v-for="(item, index) in postItemList" :key="index">
<div class="list_top"> <div class="list_top">
<img <img :src="item.avatar" alt="" class="top_img" />
:src="item.avatar || 'https://webapp-pub.ezijing.com/center_resource/avatar.png'" <!-- <div
alt=""
class="top_img"
/>
<div
class="top_name" class="top_name"
v-html=" v-html="
item.from_name !== item.to_name item.from_name !== item.to_name
? `${item.from_name} &nbsp;回复 &nbsp;${item.to_name}` ? `${item.from_name} &nbsp;回复 &nbsp; ${item.to_name} `
: `${item.to_name}` : `${item.to_name}`
" "
></div> ></div> -->
<div class="top_name" v-if="item.from_name !== item.to_name">
{{ item.from_name }}&nbsp;回复 &nbsp;<span style="color: #3571e0">{{ item.to_name }}</span>
</div>
<div class="top_name" v-else>{{ item.to_name }}</div>
</div> </div>
<div class="list_con" v-html="item.content"></div> <div class="list_con" v-html="item.content"></div>
<div class="list_bottom"> <div class="list_bottom">
...@@ -191,6 +193,7 @@ const handleDelFloor = (val: any) => { ...@@ -191,6 +193,7 @@ const handleDelFloor = (val: any) => {
v-if="postItemList.length !== totalItem" v-if="postItemList.length !== totalItem"
>查看更多</el-link >查看更多</el-link
> >
<el-link @click="handleClosePosts" v-else :underline="false" type="primary" size="mini">收起帖子</el-link>
</div> </div>
</div> </div>
<!-- 回复框 --> <!-- 回复框 -->
...@@ -294,14 +297,36 @@ const handleDelFloor = (val: any) => { ...@@ -294,14 +297,36 @@ const handleDelFloor = (val: any) => {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: flex-start; justify-content: flex-start;
.files_img {
position: relative;
width: 160px;
height: 90px;
margin: 20px;
.el-image {
width: 160px;
height: 90px;
}
.img_txt {
position: absolute;
right: 0;
bottom: 0;
width: 53px;
height: 18px;
background: rgba(0, 0, 0, 0.18);
opacity: 1;
border-radius: 2px 0px 0px 0px;
font-size: 12px;
font-weight: 400;
color: #ffffff;
cursor: pointer;
}
}
video { video {
width: 300px; width: 300px;
height: 200px; height: 200px;
} }
.el-image {
margin: 20px;
}
} }
.right_time { .right_time {
font-size: 14px; font-size: 14px;
......
...@@ -39,22 +39,11 @@ const listOptions = $computed(() => { ...@@ -39,22 +39,11 @@ const listOptions = $computed(() => {
name: '' name: ''
}, },
beforeRequest(params: any) { beforeRequest(params: any) {
if (params.organ_id !== '') { params.organ_id = organ_id.value
organ_id.value = params.organ_id params.semester_id = semester_id.value
} params.course_id = course_id.value
if (params.semester_id !== '') { params.chapter_id = chapter_id.value
semester_id.value = params.semester_id params.class_id = class_id.value
}
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 return params
}, },
httpRequest: getPostsList httpRequest: getPostsList
...@@ -106,15 +95,48 @@ const listOptions = $computed(() => { ...@@ -106,15 +95,48 @@ const listOptions = $computed(() => {
const handleAddPosts = () => { const handleAddPosts = () => {
isShowAddDialog.value = true isShowAddDialog.value = true
} }
const handleChangeOrgan = () => {
if (organ_id.value === '') {
semester_id.value = ''
course_id.value = ''
chapter_id.value = ''
class_id.value = ''
handleRefresh()
}
handleRefresh()
}
const handleChangeSemester = () => {
if (semester_id.value === '') {
course_id.value = ''
chapter_id.value = ''
class_id.value = ''
handleRefresh()
}
handleRefresh()
}
const handleChangeClass = () => {
if (class_id.value === '') {
course_id.value = ''
chapter_id.value = ''
handleRefresh()
}
handleRefresh()
}
const handleChangeCourse = () => {
if (course_id.value === '') {
chapter_id.value = ''
handleRefresh()
}
handleRefresh()
}
// 刷新页面 // 刷新页面
const handleRefresh = () => { const handleRefresh = () => {
appList.value.refetch() appList.value.refetch()
} }
console.log(listOptions)
watch( watch(
() => organ_id.value, () => organ_id.value,
value => { value => {
if (value !== undefined) { if (value !== '') {
handleGetSemesterList() handleGetSemesterList()
} }
} }
...@@ -122,8 +144,7 @@ watch( ...@@ -122,8 +144,7 @@ watch(
watch( watch(
() => semester_id.value, () => semester_id.value,
value => { value => {
console.log(value, '999') if (value !== '') {
if (value !== undefined) {
handleGetClassList() handleGetClassList()
} }
} }
...@@ -131,8 +152,7 @@ watch( ...@@ -131,8 +152,7 @@ watch(
watch( watch(
() => course_id.value, () => course_id.value,
value => { value => {
console.log(value, '1111') if (value !== '') {
if (value !== undefined && organ_id.value !== undefined && semester_id.value !== undefined) {
handleGetchaptereList() handleGetchaptereList()
} }
} }
...@@ -201,68 +221,83 @@ const handleReply = (row: any) => { ...@@ -201,68 +221,83 @@ const handleReply = (row: any) => {
<template> <template>
<AppCard title="帖子管理"> <AppCard title="帖子管理">
<AppList v-bind="listOptions" ref="appList" border stripe> <AppList v-bind="listOptions" ref="appList" border stripe>
<el-button type="primary" round @click="handleAddPosts" style="margin-bottom: 20px">新建帖子</el-button> <el-button
<template v-if="isAdmin" #filter-department="{ params }"> type="primary"
round
@click="handleAddPosts"
style="margin-bottom: 20px"
v-permission="'v1-teaching-discussion-create'"
>新建帖子</el-button
>
<template v-if="isAdmin" #filter-department>
<div class="name" style="font-size: 14px; color: #606266; padding-right: 12px">所属部门/学校:</div> <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-select @change="handleChangeOrgan" clearable v-model="organ_id" placeholder="请选择所属部门/学校">
<el-option v-for="item in departmentList" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in departmentList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</template> </template>
<template #filter-semester="{ params }"> <template #filter-semester>
<div class="name" style="font-size: 14px; color: #606266; padding-right: 12px">所属学期:</div> <div class="name" style="font-size: 14px; color: #606266; padding-right: 12px">所属学期:</div>
<el-select <el-select
@change="handleRefresh" @change="handleChangeSemester"
clearable clearable
v-model="params.semester_id" v-model="semester_id"
placeholder="请选择所属学期" placeholder="请选择所属学期"
no-data-text="请先选择所属部门/学校" no-data-text="请先选择所属部门/学校"
> >
<el-option v-for="item in semesterList" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in semesterList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</template> </template>
<template #filter-class="{ params }"> <template #filter-class>
<div class="name" style="font-size: 14px; color: #606266; padding-right: 12px">所属班级:</div> <div class="name" style="font-size: 14px; color: #606266; padding-right: 12px">所属班级:</div>
<el-select <el-select
@change="handleRefresh" @change="handleChangeClass"
clearable clearable
v-model="params.class_id" v-model="class_id"
placeholder="请选择所属班级" placeholder="请选择所属班级"
no-data-text="请先选择所属学期" no-data-text="请先选择所属学期"
> >
<el-option v-for="item in classList" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in classList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</template> </template>
<template #filter-course="{ params }"> <template #filter-course>
<div class="name" style="font-size: 14px; color: #606266; padding-right: 12px">所属课程:</div> <div class="name" style="font-size: 14px; color: #606266; padding-right: 12px">所属课程:</div>
<el-select <el-select
@change="handleRefresh" @change="handleChangeCourse"
clearable clearable
v-model="params.course_id" v-model="course_id"
placeholder="请选择所属课程" placeholder="请选择所属课程"
no-data-text="请先选择所属班级、学期" no-data-text="请先选择所属班级、学期"
> >
<el-option v-for="item in courseList" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in courseList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</template> </template>
<template #filter-chapter="{ params }"> <template #filter-chapter>
<div class="name" style="font-size: 14px; color: #606266; padding-right: 12px">所属章节:</div> <div class="name" style="font-size: 14px; color: #606266; padding-right: 12px">所属章节:</div>
<el-select <el-select
@change="handleRefresh" @change="handleRefresh"
clearable clearable
v-model="params.chapter_id" v-model="chapter_id"
placeholder="请选择所属章节" placeholder="请选择所属章节"
no-data-text="请先选择所属课程" no-data-text="请先选择所属课程"
> >
<el-option v-for="item in chapterList" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in chapterList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</template> </template>
<template #table-operate="{ row }"> <template #table-operate="{ row }">
<el-link type="primary" plain @click="handleReply(row)">添加回复</el-link> <el-link type="primary" plain @click="handleReply(row)" v-permission="'v1-teaching-discussion-list'"
<el-link type="primary" plain style="margin: 0 10px" @click="handleSetTop(row)">{{ >添加回复</el-link
row.is_top === '1' ? '取消置顶' : '置顶' >
}}</el-link> <el-link
<el-link type="primary" plain @click="handleDel(row)">删除</el-link> type="primary"
plain
style="margin: 0 10px"
@click="handleSetTop(row)"
v-permission="'v1-teaching-discussion-set-top'"
>{{ row.is_top === '1' ? '取消置顶' : '置顶' }}</el-link
>
<el-link type="primary" plain @click="handleDel(row)" v-permission="'v1-teaching-discussion-delete'"
>删除</el-link
>
</template> </template>
</AppList> </AppList>
</AppCard> </AppCard>
......
...@@ -56,6 +56,13 @@ const handleDelPosts = () => { ...@@ -56,6 +56,13 @@ const handleDelPosts = () => {
const handleFresh = () => { const handleFresh = () => {
handleGetFirstFloor() handleGetFirstFloor()
} }
const backToTop = () => {
window.scrollTo({
left: 0,
top: 0,
behavior: 'smooth'
})
}
</script> </script>
<template> <template>
<AppCard title="帖子详情"> <AppCard title="帖子详情">
...@@ -63,8 +70,12 @@ const handleFresh = () => { ...@@ -63,8 +70,12 @@ const handleFresh = () => {
<div class="card-header"> <div class="card-header">
<span>{{ postInfo.title }}</span> <span>{{ postInfo.title }}</span>
<div class="content_btn"> <div class="content_btn">
<el-button type="primary" round @click="handleDelPosts">删除当前帖子</el-button> <el-button type="primary" round @click="handleDelPosts" v-permission="'v1-teaching-discussion-delete'"
<el-button @click="handleReplyNewFloor" round>回复新楼层</el-button> >删除当前帖子</el-button
>
<el-button @click="handleReplyNewFloor" round v-permission="'v1-teaching-discussion-reply'"
>回复新楼层</el-button
>
</div> </div>
</div> </div>
<ReplyPostItem <ReplyPostItem
...@@ -74,7 +85,6 @@ const handleFresh = () => { ...@@ -74,7 +85,6 @@ const handleFresh = () => {
:discussionId="discussionId" :discussionId="discussionId"
@update="handleFresh" @update="handleFresh"
/> />
<el-pagination <el-pagination
class="pagination" class="pagination"
v-model:currentPage="currentPage" v-model:currentPage="currentPage"
...@@ -87,6 +97,13 @@ const handleFresh = () => { ...@@ -87,6 +97,13 @@ const handleFresh = () => {
> >
</el-pagination> </el-pagination>
</div> </div>
<div class="to_top" @click="backToTop">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/to_top.png" alt="" class="top_img" />
<div class="top_txt">
<div>返回</div>
<div>顶部</div>
</div>
</div>
</AppCard> </AppCard>
<ReplyPostDialog <ReplyPostDialog
v-model:isShowReplyDialog="isShowReplyDialog" v-model:isShowReplyDialog="isShowReplyDialog"
...@@ -102,6 +119,7 @@ const handleFresh = () => { ...@@ -102,6 +119,7 @@ const handleFresh = () => {
background: #ffffff; background: #ffffff;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative;
.card-header { .card-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
...@@ -116,4 +134,37 @@ const handleFresh = () => { ...@@ -116,4 +134,37 @@ const handleFresh = () => {
align-self: flex-end; align-self: flex-end;
} }
} }
.to_top {
width: 60px;
height: 60px;
background: #ffffff;
box-shadow: 1px 3px 12px rgba(0, 0, 0, 0.11);
border-radius: 50%;
opacity: 1;
text-align: center;
line-height: 60px;
position: fixed;
top: 60%;
right: 50px;
cursor: pointer;
.top_txt {
display: none;
}
&:hover {
background: #ba143e;
text-align: center;
.top_img {
display: none;
}
.top_txt {
display: block;
font-size: 14px;
font-weight: 400;
color: #ffffff;
line-height: 1.2;
padding-top: 15px;
}
}
}
</style> </style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论