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

chore: update

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