提交 f6db113b authored 作者: matian's avatar matian

updates

上级 6ae0e86f
...@@ -47,15 +47,18 @@ const handleBeforeUpload = async (file: any) => { ...@@ -47,15 +47,18 @@ const handleBeforeUpload = async (file: any) => {
fileList.value.filter((item: any) => item.name.includes('.jpeg')).length > fileList.value.filter((item: any) => item.name.includes('.jpeg')).length >
10 10
) { ) {
const videoList = fileList.value.filter((item: any) => item.name.includes('.mp4')) 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')).slice(0, 10) const imgList = fileList.value
.filter((item: any) => item.name.includes('.png') || item.name.includes('.jpg') || item.name.includes('.jpeg'))
.slice(0, 10)
fileList.value = [...videoList, ...imgList] fileList.value = [...videoList, ...imgList]
ElMessage.warning('支持最多上传10张图片,格式支持jpg,jpeg,png') ElMessage.warning('支持最多上传10张图片,格式支持jpg,jpeg,png')
} else if (fileList.value.filter((item: any) => item.name.includes('.mp4')).length > 1) { } 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 videoList = fileList.value.filter((item: any) => item.name.includes('.mp4')).slice(0, 1)
const imgList = fileList.value.filter((item: any) => !item.name.includes('.mp4')) const imgList = fileList.value
.filter((item: any) => item.name.includes('.png') || item.name.includes('.jpg') || item.name.includes('.jpeg'))
.slice(0, 10)
fileList.value = [...videoList, ...imgList] fileList.value = [...videoList, ...imgList]
console.log(fileList.value)
ElMessage.warning('视频最多长传1个') ElMessage.warning('视频最多长传1个')
} }
} }
...@@ -65,14 +68,15 @@ const handleBeforeUpload = async (file: any) => { ...@@ -65,14 +68,15 @@ const handleBeforeUpload = async (file: any) => {
const handleSuccess = (response: any, file: any, files: any) => { const handleSuccess = (response: any, file: any, files: any) => {
if (!files.every((item: any) => item.status === 'success')) return if (!files.every((item: any) => item.status === 'success')) return
if (showFileList.value) { if (showFileList.value) {
console.log(files)
emit( emit(
'update:modelValue', 'update:modelValue',
files.map((item: any) => { files.map((item: any) => {
return { return {
name: item.name, name: item.name,
url: item.url || item.raw.url, url: item.url || item.raw.url,
size: item.raw.size, size: item.size || item.raw.size,
type: item.raw.type || item.raw.url type: item.type || item.raw.type
} }
}) })
) )
......
...@@ -19,7 +19,6 @@ interface Emits { ...@@ -19,7 +19,6 @@ interface Emits {
(e: 'update:isShowAddDialog', isShowAddDialog: boolean): void (e: 'update:isShowAddDialog', isShowAddDialog: boolean): void
(e: 'create'): void (e: 'create'): void
} }
const form: any = reactive({ const form: any = reactive({
organ_id: '', organ_id: '',
semester_id: '', semester_id: '',
...@@ -244,8 +243,8 @@ const handleChangeCourse = () => { ...@@ -244,8 +243,8 @@ const handleChangeCourse = () => {
<div class="upload-box"> <div class="upload-box">
<AppUpload <AppUpload
accept=".mp4,.png,.jpeg,.jpg" accept=".mp4,.png,.jpeg,.jpg"
:limit="11"
:multiple="true" :multiple="true"
:limit="11"
v-model="form.files" v-model="form.files"
:isPost="'1'" :isPost="'1'"
></AppUpload> ></AppUpload>
......
<script lang="ts" setup> <script lang="ts" setup>
import { replyPosts, getReplyPostItem } from '../api' import { replyPosts, getReplyPostItem, delPosts } from '../api'
import { ElMessage, ElMessageBox } from 'element-plus'
const emit = defineEmits<Emits>() const emit = defineEmits<Emits>()
const props = defineProps({ const props = defineProps({
firstFloor: { firstFloor: {
...@@ -12,16 +13,23 @@ const props = defineProps({ ...@@ -12,16 +13,23 @@ const props = defineProps({
interface Emits { interface Emits {
(e: 'update'): void (e: 'update'): void
} }
const currentPage = ref(1)
const totalItem = ref(0)
const reply_content = ref('') const reply_content = ref('')
const isShowReply = ref(false) const isShowReply = ref(false)
const id = ref('') const id = ref('')
const postItem: any = ref({}) const postItem: any = ref({})
const postItemList = ref(JSON.parse(JSON.stringify(props.firstFloor?.comments))) const postItemList: any = ref([])
const previewList: any = ref([])
watchEffect(() => {
postItemList.value = props.firstFloor?.comments || []
totalItem.value = props.firstFloor?.comments_total || 0
})
// 最上面的回复 // 最上面的回复
const handleReply = (val: any) => { const handleReply = (val: any) => {
isShowReply.value = true isShowReply.value = true
id.value = val.id id.value = val.id
postItem.value = ''
} }
// 回复列表下面的回复 // 回复列表下面的回复
const handleReplyItem = (val: any) => { const handleReplyItem = (val: any) => {
...@@ -37,8 +45,9 @@ const handleReplySubmit = () => { ...@@ -37,8 +45,9 @@ const handleReplySubmit = () => {
reply_id: props.firstFloor?.id reply_id: props.firstFloor?.id
} }
replyPosts(params).then(() => { replyPosts(params).then(() => {
emit('update')
reply_content.value = '' reply_content.value = ''
isShowReply.value = false
emit('update')
}) })
} }
// 查看更多 // 查看更多
...@@ -48,10 +57,18 @@ const handleViewMore = (val: any) => { ...@@ -48,10 +57,18 @@ const handleViewMore = (val: any) => {
// 获取评论二级列表数据 // 获取评论二级列表数据
const handleGetItemFloor = (val: any) => { const handleGetItemFloor = (val: any) => {
const params: any = { const params: any = {
page: currentPage.value++,
['per-page']: 20,
reply_id: val reply_id: val
} }
getReplyPostItem(params).then(res => { getReplyPostItem(params).then(res => {
if (params.page === 1) {
postItemList.value = res.data.list postItemList.value = res.data.list
console.log(postItemList.value)
} else {
postItemList.value = postItemList.value.concat(res.data.list)
}
totalItem.value = res.data.total
}) })
} }
const imgUrl = computed(() => { const imgUrl = computed(() => {
...@@ -65,10 +82,30 @@ const imgUrl = computed(() => { ...@@ -65,10 +82,30 @@ const imgUrl = computed(() => {
return 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/xt.png' return 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/xt.png'
} }
}) })
// 图片预览
if (props.firstFloor?.files.length > 0) {
previewList.value = props.firstFloor?.files.map((it: any) => {
if (it?.name.includes('.png') || it?.name.includes('.jpg') || it?.name.includes('.jpeg')) {
return it.url
}
})
}
// 删除楼层
const handleDelFloor = (val: any) => {
ElMessageBox.confirm('确定要删除该楼层吗?', '提示').then(() => {
const params: any = { id: val, type: 'reply' }
delPosts(params).then(() => {
ElMessage.success('帖子删除成功')
emit('update')
})
})
}
</script> </script>
<template> <template>
<div class="main_post"> <div class="main_post">
<div class="post_left"> <div class="post_left">
<!-- <div class="left_logo" v-if="props.firstFloor?.floor === 1">楼主</div> -->
<img <img
:src=" :src="
props.firstFloor?.avatar || props.firstFloor?.avatar ||
...@@ -86,24 +123,39 @@ const imgUrl = computed(() => { ...@@ -86,24 +123,39 @@ const imgUrl = computed(() => {
</div> </div>
</div> </div>
<div class="post_right"> <div class="post_right">
<el-button
type="primary"
round
class="right_btn"
v-if="props.firstFloor?.floor > 1"
@click="handleDelFloor(props.firstFloor?.id)"
>删除当前楼层</el-button
>
<div class="right_con" v-html="props.firstFloor?.content"></div> <div class="right_con" v-html="props.firstFloor?.content"></div>
<template v-if="props.firstFloor?.files.length > 0"> <template v-if="props.firstFloor?.files.length > 0">
<div class="right_files" v-for="(it, index) in props.firstFloor?.files" :key="index"> <div class="right_files">
<img <template v-for="(it, index) in props.firstFloor?.files" :key="index">
<el-image
:src="it?.url" :src="it?.url"
alt=""
v-if="it?.name.includes('.png') || it?.name.includes('.jpg') || it?.name.includes('.jpeg')" v-if="it?.name.includes('.png') || it?.name.includes('.jpg') || it?.name.includes('.jpeg')"
style="width: 100px" style="width: 100px"
:preview-src-list="previewList"
:initial-index="4"
fit="cover"
/> />
<video :src="it?.url" v-if="it?.name.includes('.mp4')"></video> <video v-if="it?.name.includes('.mp4')" controls id="video">
<source :src="it?.url" />
</video>
</template>
</div> </div>
</template> </template>
<div class="right_time">发表于 {{ props.firstFloor?.updated_time }}</div> <div class="right_time">发表于&nbsp;&nbsp; {{ props.firstFloor?.updated_time }}</div>
<el-link :underline="false" class="right_btn" @click="handleReply(props.firstFloor)"> <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="" /> <img src="https://webapp-pub.ezijing.com/center_resource/reply_btn.png" alt="" />
<div class="btn_txt">回复</div> <div class="btn_txt">回复</div>
</el-link> </el-link>
<div class="right_list" v-if="props.firstFloor?.comments.length > 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
...@@ -122,26 +174,33 @@ const imgUrl = computed(() => { ...@@ -122,26 +174,33 @@ const imgUrl = computed(() => {
</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">
<div class="bottom_time">来自于{{ item.updated_time }}</div> <div class="bottom_time">来自于&nbsp;&nbsp;{{ item.updated_time }}</div>
<el-link :underline="false" class="bottom_reply" @click="handleReplyItem(item)"> <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="" /> <img src="https://webapp-pub.ezijing.com/center_resource/reply_btn.png" alt="" />
<div class="reply_txt" @click="handleReplyItem(item)">回复</div> <div class="reply_txt" @click="handleReplyItem(item)">回复</div>
</el-link> </el-link>
</div> </div>
</div> </div>
<div class="list_more" v-if="props.firstFloor?.comments_total > 3"> <div class="list_more" v-if="totalItem > 3">
<el-link :underline="false" type="primary" size="mini" @click="handleViewMore(props.firstFloor?.id)" <el-link
:underline="false"
type="primary"
size="mini"
@click="handleViewMore(props.firstFloor?.id)"
v-if="postItemList.length !== totalItem"
>查看更多</el-link >查看更多</el-link
> >
</div> </div>
</div> </div>
<!-- 回复框 -->
<div class="reply_input" v-if="isShowReply === true"> <div class="reply_input" v-if="isShowReply === true">
<div class="input_txt" v-if="postItem === ''">回复本楼</div>
<el-input <el-input
v-model="reply_content" v-model="reply_content"
:autosize="{ minRows: 2, maxRows: 4 }" :autosize="{ minRows: 4, maxRows: 6 }"
type="textarea" type="textarea"
style="width: 100%" style="width: 100%"
:placeholder="postItem.to_name ? `回复${postItem.to_name}` : ''" :placeholder="postItem.to_name ? `回复@${postItem.to_name}:` : ''"
/> />
<el-button class="input_btn" type="primary" @click="handleReplySubmit">发表回复</el-button> <el-button class="input_btn" type="primary" @click="handleReplySubmit">发表回复</el-button>
</div> </div>
...@@ -160,6 +219,20 @@ const imgUrl = computed(() => { ...@@ -160,6 +219,20 @@ const imgUrl = computed(() => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
position: relative;
.left_logo {
height: 0;
width: 0;
border-top: 29px solid #ba143e;
border-left: 29px solid #ba143e;
border-bottom: 29px solid transparent;
border-right: 29px solid transparent;
align-self: flex-start;
position: absolute;
top: 0;
left: 0;
}
.left_avatar { .left_avatar {
width: 100px; width: 100px;
height: 100px; height: 100px;
...@@ -198,7 +271,7 @@ const imgUrl = computed(() => { ...@@ -198,7 +271,7 @@ const imgUrl = computed(() => {
} }
.post_right { .post_right {
width: 100%; width: 100%;
padding: 40px 21px 0 40px; padding: 40px 21px 40px 40px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.right_con { .right_con {
...@@ -207,6 +280,19 @@ const imgUrl = computed(() => { ...@@ -207,6 +280,19 @@ const imgUrl = computed(() => {
color: #666666; color: #666666;
line-height: 27px; line-height: 27px;
} }
.right_files {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
video {
width: 300px;
height: 200px;
}
.el-image {
margin: 20px;
}
}
.right_time { .right_time {
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
...@@ -223,6 +309,10 @@ const imgUrl = computed(() => { ...@@ -223,6 +309,10 @@ const imgUrl = computed(() => {
} }
.btn_txt { .btn_txt {
margin-left: 9px; margin-left: 9px;
font-size: 16px;
font-weight: 400;
line-height: 27px;
color: #9b9b9b;
} }
} }
.reply_input { .reply_input {
...@@ -288,8 +378,8 @@ const imgUrl = computed(() => { ...@@ -288,8 +378,8 @@ const imgUrl = computed(() => {
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
img { img {
width: 20px; width: 22px;
height: 20px; height: 22px;
} }
.reply_txt { .reply_txt {
font-size: 16px; font-size: 16px;
...@@ -308,4 +398,13 @@ const imgUrl = computed(() => { ...@@ -308,4 +398,13 @@ const imgUrl = computed(() => {
height: 4px; height: 4px;
background: #e8e8e8; background: #e8e8e8;
} }
:deep(.el-textarea) {
.el-textarea__inner {
padding: 20px 0 0 20px;
font-size: 16px;
font-weight: 400;
line-height: 27px;
color: #999999;
}
}
</style> </style>
<script setup lang="ts"> <script setup lang="ts">
import { ElMessage } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { getConditionList, getPostsList, delPosts, setTopPosts } from '../api' import { getConditionList, getPostsList, delPosts, setTopPosts } from '../api'
import AddPostDialog from '../components/AddPostDialog.vue' import AddPostDialog from '../components/AddPostDialog.vue'
import { useProjectList } from '@/composables/useGetProjectList' import { useProjectList } from '@/composables/useGetProjectList'
...@@ -173,11 +173,13 @@ const handleGetchaptereList = () => { ...@@ -173,11 +173,13 @@ const handleGetchaptereList = () => {
} }
// 删除帖子 // 删除帖子
const handleDel = (row: any) => { const handleDel = (row: any) => {
ElMessageBox.confirm('确定要删除该帖子吗?', '提示').then(() => {
const params: any = { id: row.id, type: 'discussion' } const params: any = { id: row.id, type: 'discussion' }
delPosts(params).then(() => { delPosts(params).then(() => {
ElMessage.success('帖子删除成功') ElMessage.success('帖子删除成功')
handleRefresh() handleRefresh()
}) })
})
} }
// 置顶帖子 // 置顶帖子
const handleSetTop = (row: any) => { const handleSetTop = (row: any) => {
......
<script setup lang="ts"> <script setup lang="ts">
import ReplyPostDialog from '../components/ReplyPostDialog.vue' import ReplyPostDialog from '../components/ReplyPostDialog.vue'
import ReplyPostItem from '../components/ReplyPostItem.vue' import ReplyPostItem from '../components/ReplyPostItem.vue'
import { getPostFirst } from '../api' import { getPostFirst, delPosts } from '../api'
import { ElMessage, ElMessageBox } from 'element-plus'
const route = useRoute() const route = useRoute()
const isShowReplyDialog = ref(false) const isShowReplyDialog = ref(false)
const postInfo: any = ref({}) const postInfo: any = ref({})
const firstPostList: any = ref([]) const firstPostList: any = ref([])
const totalFloor: any = ref(0)
const discussionId: any = route.query.id const discussionId: any = route.query.id
const currentPage = ref(1) const currentPage = ref(1)
const page = reactive({ const page = reactive({
...@@ -16,23 +19,42 @@ onMounted(() => { ...@@ -16,23 +19,42 @@ onMounted(() => {
handleGetFirstFloor() handleGetFirstFloor()
}) })
const handleGetFirstFloor = () => { const handleGetFirstFloor = () => {
const params: any = { discussion_id: discussionId } const params: any = { discussion_id: discussionId, page: page.currentPage, ['per-page']: page.size }
getPostFirst(params).then(res => { getPostFirst(params).then(res => {
totalFloor.value = res.data.total
postInfo.value = res.data.info postInfo.value = res.data.info
firstPostList.value = res.data.list firstPostList.value = res.data.list
firstPostList.value.map((item: any) => { firstPostList.value.map((item: any) => {
if (item.files !== '') {
item.files = JSON.parse(item.files) item.files = JSON.parse(item.files)
}
}) })
}) })
} }
const handleReplyNewFloor = () => { const handleReplyNewFloor = () => {
isShowReplyDialog.value = true isShowReplyDialog.value = true
} }
const handleSizeChange = (val: any) => { const handleSizeChange = (val: any) => {
page.currentPage = 1
page.size = val page.size = val
handleFresh()
} }
const handleCurrentChange = (val: any) => { const handleCurrentChange = (val: any) => {
page.currentPage = val page.currentPage = val
handleFresh()
}
const handleDelPosts = () => {
ElMessageBox.confirm('确定要删除该帖子吗?', '提示').then(() => {
const params: any = { id: discussionId, type: 'discussion' }
delPosts(params).then(() => {
ElMessage.success('帖子删除成功')
history.go(-1)
})
})
}
const handleFresh = () => {
handleGetFirstFloor()
} }
</script> </script>
<template> <template>
...@@ -41,24 +63,25 @@ const handleCurrentChange = (val: any) => { ...@@ -41,24 +63,25 @@ const handleCurrentChange = (val: any) => {
<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>删除当前帖子</el-button> <el-button type="primary" round @click="handleDelPosts">删除当前帖子</el-button>
<el-button @click="handleReplyNewFloor" round>回复新楼层</el-button> <el-button @click="handleReplyNewFloor" round>回复新楼层</el-button>
</div> </div>
</div> </div>
<ReplyPostItem <ReplyPostItem
v-for="(item, index) in firstPostList.slice((page.currentPage - 1) * page.size, page.currentPage * page.size)" v-for="(item, index) in firstPostList"
:key="index" :key="index"
:firstFloor="item" :firstFloor="item"
:discussionId="discussionId" :discussionId="discussionId"
@update="handleGetFirstFloor" @update="handleFresh"
/> />
<el-pagination <el-pagination
class="pagination" class="pagination"
v-model:currentPage="currentPage" v-model:currentPage="currentPage"
:page-size="page.size" :page-size="page.size"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
:page-sizes="[5, 10, 20, 30, 50]" :page-sizes="[5, 10, 20, 30, 50]"
:total="firstPostList.length" :total="totalFloor"
@size-change="handleSizeChange" @size-change="handleSizeChange"
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
> >
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论