提交 43bde8c6 authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 cdcb443e
差异被折叠。
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^2.0.6", "@element-plus/icons-vue": "^2.0.6",
"@tinymce/tinymce-vue": "^5.0.0", "@tinymce/tinymce-vue": "^5.0.0",
"@vueuse/core": "^9.1.0",
"axios": "^0.27.2", "axios": "^0.27.2",
"blueimp-md5": "^2.19.0", "blueimp-md5": "^2.19.0",
"element-plus": "^2.2.12", "element-plus": "^2.2.12",
......
...@@ -24,13 +24,11 @@ withDefaults(defineProps<{ sidebar?: boolean; hasTitle?: boolean }>(), { ...@@ -24,13 +24,11 @@ withDefaults(defineProps<{ sidebar?: boolean; hasTitle?: boolean }>(), {
<style lang="scss"> <style lang="scss">
.app-layout { .app-layout {
display: flex;
flex-direction: column;
min-height: 100vh; min-height: 100vh;
background-color: #f8f8f8; background-color: #f8f8f8;
} }
.app-layout-container { .app-layout-container {
flex: 1; height: calc(100vh - 70px);
display: flex; display: flex;
} }
</style> </style>
...@@ -22,7 +22,7 @@ export function getExperimentVideoPlayInfo(params: { source_id: string }) { ...@@ -22,7 +22,7 @@ export function getExperimentVideoPlayInfo(params: { source_id: string }) {
// 获取实验讨论交流 // 获取实验讨论交流
export function getExperimentDiscussList(params: { export function getExperimentDiscussList(params: {
experiment_id: string experiment_id: string
tag: string tag: number
page?: number page?: number
'per-page'?: number 'per-page'?: number
}) { }) {
......
<script setup lang="ts"> <script setup lang="ts">
import type { ExperimentDiscussType } from '../types' import type { ExperimentDiscussType } from '../types'
import { getExperimentDiscussList } from '../api' import { Loading } from '@element-plus/icons-vue'
import { useInfiniteScroll } from '@vueuse/core'
import DiscussItem from './DiscussItem.vue' import DiscussItem from './DiscussItem.vue'
import { getExperimentDiscussList } from '../api'
const DiscussAddDialog = defineAsyncComponent(() => import('./DiscussAddDialog.vue')) const DiscussAddDialog = defineAsyncComponent(() => import('./DiscussAddDialog.vue'))
interface Props { interface Props {
experiment_id?: string experiment_id?: string
} }
const props = defineProps<Props>() const props = defineProps<Props>()
const discussTag = $ref('1') const params = reactive({ tag: 3, page: 0, 'per-page': 10 })
let list = $ref<ExperimentDiscussType[]>([]) let list = $ref<ExperimentDiscussType[]>([])
let hasMore = $ref(false)
let isLoading = $ref(false)
function fetchInfo() { function fetchInfo() {
if (!props.experiment_id) return if (!props.experiment_id) return
getExperimentDiscussList({ experiment_id: props.experiment_id, tag: discussTag }).then(res => { isLoading = true
list = res.data.list getExperimentDiscussList({ ...params, experiment_id: props.experiment_id })
}) .then(res => {
list = params.page ? [...list, ...res.data.list] : res.data.list
hasMore = !!res.data.list.length
})
.finally(() => {
isLoading = false
})
} }
watchEffect(() => { onMounted(() => {
fetchInfo() fetchInfo()
}) })
...@@ -25,25 +35,78 @@ const isEmpty = $computed(() => { ...@@ -25,25 +35,78 @@ const isEmpty = $computed(() => {
}) })
const dialogVisible = $ref(false) const dialogVisible = $ref(false)
// 刷新
function handleRefetch() {
params.page = 0
fetchInfo()
}
// 滚动加载
const scrollRef = ref<HTMLElement>()
useInfiniteScroll(
scrollRef,
() => {
if (!hasMore) return
params.page++
fetchInfo()
},
{ distance: 10 }
)
</script> </script>
<template> <template>
<el-radio-group v-model="discussTag"> <div class="discuss">
<el-radio :label="1">我发起的</el-radio> <el-radio-group v-model="params.tag" @change="handleRefetch">
<el-radio :label="2">我回复的</el-radio> <el-radio :label="1">我发起的</el-radio>
<el-radio :label="3">我的小组</el-radio> <el-radio :label="2">我回复的</el-radio>
<el-radio :label="4">我的班级</el-radio> <el-radio :label="3">我的小组</el-radio>
</el-radio-group> <el-radio :label="4">我的班级</el-radio>
<el-row justify="end"> </el-radio-group>
<el-button round type="primary" @click="dialogVisible = true">发表新话题</el-button> <el-row justify="end">
</el-row> <el-button round type="primary" @click="dialogVisible = true">发表新话题</el-button>
<el-empty description="暂无数据" v-if="isEmpty" /> </el-row>
<template v-else> <el-empty description="暂无数据" v-if="isEmpty" />
<DiscussItem v-for="item in list" :key="item.id" :data="item"></DiscussItem> <template v-else>
</template> <div class="discuss-scroll" ref="scrollRef">
<DiscussItem v-for="item in list" :key="item.id" :data="item" @update="handleRefetch"></DiscussItem>
<div class="tips" v-if="isLoading">
<el-icon class="is-loading">
<Loading />
</el-icon>
加载中...
</div>
</div>
</template>
</div>
<!-- 发表新话题 --> <!-- 发表新话题 -->
<DiscussAddDialog v-model="dialogVisible" v-if="dialogVisible"></DiscussAddDialog> <DiscussAddDialog
v-model="dialogVisible"
:experiment_id="experiment_id"
@update="handleRefetch"
v-if="dialogVisible && experiment_id"
></DiscussAddDialog>
</template> </template>
<style lang="scss" scoped></style> <style lang="scss" scoped>
.discuss {
display: flex;
height: 100%;
flex-direction: column;
.el-radio {
margin-right: 12px;
}
}
.discuss-scroll {
flex: 1;
overflow-y: auto;
}
.tips {
padding: 40px;
color: #555;
text-align: center;
}
.el-icon.is-loading {
animation: rotating 2s linear infinite;
}
</style>
<script setup lang="ts"> <script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
// import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { addExperimentDiscuss } from '../api'
interface Props { interface Props {
data?: any experiment_id: string
} }
const props = defineProps<Props>() const props = defineProps<Props>()
defineEmits<{ const emit = defineEmits<{
(e: 'update'): void (e: 'update'): void
(e: 'update:modelValue', visible: boolean): void (e: 'update:modelValue', visible: boolean): void
}>() }>()
const formRef = $ref<FormInstance>() const formRef = $ref<FormInstance>()
const form = reactive({ title: '', content: '' }) const form = reactive({ title: '', content: '' })
watchEffect(() => {
Object.assign(form, props.data)
})
const rules = ref<FormRules>({ const rules = ref<FormRules>({
title: [{ required: true, message: '请输入话题标题', trigger: 'blur' }], title: [{ required: true, message: '请输入话题标题', trigger: 'blur' }],
content: [{ required: true, message: '请输入话题描述', trigger: 'blur' }] content: [{ required: true, message: '请输入话题描述', trigger: 'blur' }]
}) })
// 提交 // 提交
function handleSubmit() { function handleSubmit() {
formRef?.validate().then(update) formRef?.validate().then(handleAdd)
} }
// 修改 // 创建话题
const update = () => { function handleAdd() {
// submitSuggestion(form).then(() => { const params = { ...form, experiment_id: props.experiment_id }
// ElMessage({ message: '提交成功', type: 'success' }) addExperimentDiscuss(params).then(() => {
// emit('update') ElMessage({ message: '发表成功', type: 'success' })
// formRef?.resetFields() emit('update')
// }) emit('update:modelValue', false)
})
} }
</script> </script>
<template> <template>
<el-dialog title="发表新话题" :close-on-click-modal="false" width="600px"> <el-dialog
title="发表新话题"
:close-on-click-modal="false"
width="600px"
@update:modelValue="$emit('update:modelValue')"
>
<el-form ref="formRef" :model="form" :rules="rules"> <el-form ref="formRef" :model="form" :rules="rules">
<el-form-item label="话题标题" prop="title"> <el-form-item label="话题标题" prop="title">
<el-input v-model="form.title"></el-input> <el-input v-model="form.title"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="话题描述" prop="content"> <el-form-item label="话题描述" prop="content">
<el-input type="textarea" v-model="form.content" /> <el-input type="textarea" v-model="form.content" :autosize="{ minRows: 4, maxRows: 6 }" />
</el-form-item> </el-form-item>
<el-row justify="center"> <el-row justify="center">
<el-button round auto-insert-space @click="$emit('update:modelValue', false)">取消</el-button> <el-button round auto-insert-space @click="$emit('update:modelValue', false)">取消</el-button>
......
<script setup lang="ts"> <script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
// import { ElMessage } from 'element-plus' import type { ExperimentDiscussType } from '../types'
import { ElMessage } from 'element-plus'
import { addExperimentDiscussComment } from '../api'
interface Props { interface Props {
data?: any data: ExperimentDiscussType
} }
const props = defineProps<Props>() const props = defineProps<Props>()
defineEmits<{ const emit = defineEmits<{
(e: 'update'): void (e: 'update'): void
(e: 'update:modelValue', visible: boolean): void (e: 'update:modelValue', visible: boolean): void
}>() }>()
const formRef = $ref<FormInstance>() const formRef = $ref<FormInstance>()
const form = reactive({ content: '' }) const form = reactive({ content: '' })
watchEffect(() => {
Object.assign(form, props.data)
})
const rules = ref<FormRules>({ const rules = ref<FormRules>({
content: [{ required: true, message: '请输入话题评论内容', trigger: 'blur' }] content: [{ required: true, message: '请输入话题评论内容', trigger: 'blur' }]
}) })
// 提交 // 提交
function handleSubmit() { function handleSubmit() {
formRef?.validate().then(update) formRef?.validate().then(handleAdd)
} }
// 修改 // 发布评论
const update = () => { function handleAdd() {
// submitSuggestion(form).then(() => { const params = { ...form, discussion_id: props.data.id }
// ElMessage({ message: '提交成功', type: 'success' }) addExperimentDiscussComment(params).then(() => {
// emit('update') ElMessage({ message: '评论成功', type: 'success' })
// formRef?.resetFields() emit('update')
// }) emit('update:modelValue', false)
})
} }
</script> </script>
<template> <template>
<el-dialog title="话题评论" :close-on-click-modal="false" width="600px"> <el-dialog
title="话题评论"
:close-on-click-modal="false"
width="600px"
@update:modelValue="$emit('update:modelValue')"
>
<el-form ref="formRef" :model="form" :rules="rules"> <el-form ref="formRef" :model="form" :rules="rules">
<el-form-item prop="content"> <el-form-item prop="content">
<el-input type="textarea" v-model="form.content" /> <el-input type="textarea" v-model="form.content" :autosize="{ minRows: 4, maxRows: 6 }" />
</el-form-item> </el-form-item>
<el-row justify="center"> <el-row justify="center">
<el-button round auto-insert-space @click="$emit('update:modelValue', false)">取消</el-button> <el-button round auto-insert-space @click="$emit('update:modelValue', false)">取消</el-button>
......
<script setup lang="ts"> <script setup lang="ts">
import type { ExperimentDiscussType } from '../types' import type { ExperimentDiscussType } from '../types'
import { ChatLineRound } from '@element-plus/icons-vue'
const DiscussCommentAddDialog = defineAsyncComponent(() => import('./DiscussCommentAddDialog.vue')) const DiscussCommentAddDialog = defineAsyncComponent(() => import('./DiscussCommentAddDialog.vue'))
...@@ -8,35 +9,117 @@ interface Props { ...@@ -8,35 +9,117 @@ interface Props {
} }
defineProps<Props>() defineProps<Props>()
defineEmits<{
(e: 'update'): void
}>()
const commentDialogVisible = $ref(false) const commentDialogVisible = $ref(false)
const commentVisible = $ref(false)
const commentButtonText = $computed(() => (commentVisible ? '收起' : '展开'))
</script> </script>
<template> <template>
<div class="discuss-item"> <div class="discuss-item">
<div class="discuss-item-user"> <div class="discuss-box">
<img src="" /> <div class="discuss-box-user">
<p></p> <img :src="data.sso_user.avatar" />
<p>{{ data.sso_user.real_name || data.sso_user.nickname || data.sso_user.username }}</p>
</div>
<div class="discuss-box-main">
<div class="discuss-box-header">
<p class="discuss-box-time">{{ data.created_time }}</p>
<div class="tools">
<el-button size="small" type="primary" plain round @click="commentVisible = !commentVisible">
{{ commentButtonText }}
</el-button>
<el-icon><ChatLineRound></ChatLineRound></el-icon>{{ data.reply_count }}
</div>
</div>
<h3>{{ data.title }}</h3>
<div class="discuss-box-content" v-html="data.content"></div>
</div>
</div> </div>
<div class="discuss-item-main"></div> <template v-if="commentVisible">
<div class="discuss-box discuss-comment" v-for="item in data.replies" :key="item.id">
<div class="discuss-box-user">
<img :src="item.sso_user.avatar" />
<p>{{ item.sso_user.real_name || item.sso_user.nickname || item.sso_user.username }}</p>
</div>
<div class="discuss-box-main">
<p class="discuss-box-time">{{ item.created_time }}</p>
<div class="discuss-box-content" v-html="item.content"></div>
</div>
</div>
</template>
<el-row justify="end" style="margin-top: 10px">
<el-button round type="primary" size="small" @click="commentDialogVisible = true">我要评论</el-button>
</el-row>
</div> </div>
<el-row justify="end">
<el-button round type="primary" @click="commentDialogVisible = true">我要评论</el-button>
</el-row>
<!-- 我要评论 --> <!-- 我要评论 -->
<DiscussCommentAddDialog v-model="commentDialogVisible" v-if="commentDialogVisible"></DiscussCommentAddDialog> <DiscussCommentAddDialog
:data="data"
v-model="commentDialogVisible"
@update="$emit('update')"
v-if="commentDialogVisible"
></DiscussCommentAddDialog>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.video-item { .discuss-item {
h2 { margin-top: 10px;
font-size: 16px; padding: 10px 0;
color: #333; border-top: 1px dashed #ccc;
margin-bottom: 10px; }
text-align: center; .discuss-box {
display: flex;
margin: 10px 0;
padding: 10px;
font-size: 12px;
color: var(--main-color);
border-radius: 10px;
border: 1px solid var(--main-color);
&.discuss-comment {
margin-left: 40px;
color: #016fa0;
border: 1px solid #016fa0;
} }
}
.discuss-box-user {
img { img {
width: 100%; width: 50px;
height: 200px; height: 50px;
border-radius: 50%;
overflow: hidden;
object-fit: cover; object-fit: cover;
} }
p {
text-align: center;
}
}
.discuss-box-main {
flex: 1;
padding-left: 10px;
h3 {
font-size: 14px;
font-weight: 500;
}
}
.discuss-box-content {
padding: 5px 0;
color: #555;
}
.discuss-box-header {
display: flex;
align-items: center;
justify-content: space-between;
.tools {
display: flex;
align-items: center;
.el-icon {
font-size: 16px;
margin-left: 10px;
margin-right: 5px;
color: #333333;
}
}
} }
</style> </style>
...@@ -137,8 +137,10 @@ onUnmounted(() => { ...@@ -137,8 +137,10 @@ onUnmounted(() => {
padding: 20px; padding: 20px;
background-color: rgba(45, 48, 55, 1); background-color: rgba(45, 48, 55, 1);
border-radius: 6px; border-radius: 6px;
box-sizing: border-box;
.el-tabs { .el-tabs {
flex: 1; flex: 1;
overflow: hidden;
} }
:deep(.el-tabs__content) { :deep(.el-tabs__content) {
height: calc(100% - 40px); height: calc(100% - 40px);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论