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

chore: update

上级 cdcb443e
......@@ -10,6 +10,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",
......@@ -371,9 +372,9 @@
"dev": true
},
"node_modules/@types/web-bluetooth": {
"version": "0.0.14",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz",
"integrity": "sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A=="
"version": "0.0.15",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.15.tgz",
"integrity": "sha512-w7hEHXnPMEZ+4nGKl/KDRVpxkwYxYExuHOYXyzIzCDzEZ9ZCGMAewulr9IqJu2LR4N37fcnb1XVeuZ09qgOxhA=="
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.33.0",
......@@ -747,52 +748,55 @@
}
},
"node_modules/@vueuse/core": {
"version": "8.9.4",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-8.9.4.tgz",
"integrity": "sha512-B/Mdj9TK1peFyWaPof+Zf/mP9XuGAngaJZBwPaXBvU3aCTZlx3ltlrFFFyMV4iGBwsjSCeUCgZrtkEj9dS2Y3Q==",
"version": "9.1.0",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.1.0.tgz",
"integrity": "sha512-BIroqvXEqt826aE9r3K5cox1zobuPuAzdYJ36kouC2TVhlXvFKIILgFVWrpp9HZPwB3aLzasmG3K87q7TSyXZg==",
"dependencies": {
"@types/web-bluetooth": "^0.0.14",
"@vueuse/metadata": "8.9.4",
"@vueuse/shared": "8.9.4",
"@types/web-bluetooth": "^0.0.15",
"@vueuse/metadata": "9.1.0",
"@vueuse/shared": "9.1.0",
"vue-demi": "*"
}
},
"node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.13.8",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.8.tgz",
"integrity": "sha512-Vy1zbZhCOdsmvGR6tJhAvO5vhP7eiS8xkbYQSoVa7o6KlIy3W8Rc53ED4qI4qpeRDjv3mLfXSEpYU6Yq4pgXRg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"peerDependencies": {
"@vue/composition-api": "^1.1.0",
"vue": "^2.6.0 || ^3.2.0"
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
},
"vue": {
"optional": true
}
}
},
"node_modules/@vueuse/core/node_modules/@vueuse/shared": {
"version": "8.9.4",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-8.9.4.tgz",
"integrity": "sha512-wt+T30c4K6dGRMVqPddexEVLa28YwxW5OFIPmzUHICjphfAuBFTTdDoyqREZNDOFJZ44ARH1WWQNCUK8koJ+Ag==",
"node_modules/@vueuse/metadata": {
"version": "9.1.0",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.1.0.tgz",
"integrity": "sha512-8OEhlog1iaAGTD3LICZ8oBGQdYeMwByvXetOtAOZCJOzyCRSwqwdggTsmVZZ1rkgYIEqgUBk942AsAPwM21s6A=="
},
"node_modules/@vueuse/shared": {
"version": "9.1.0",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.1.0.tgz",
"integrity": "sha512-pB/3njQu4tfJJ78ajELNda0yMG6lKfpToQW7Soe09CprF1k3QuyoNi1tBNvo75wBDJWD+LOnr+c4B5HZ39jY/Q==",
"dependencies": {
"vue-demi": "*"
},
"peerDependencies": {
"@vue/composition-api": "^1.1.0",
"vue": "^2.6.0 || ^3.2.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
},
"vue": {
"optional": true
}
}
},
"node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.13.6",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.6.tgz",
"integrity": "sha512-02NYpxgyGE2kKGegRPYlNQSL1UWfA/+JqvzhGCOYjhfbLWXU5QQX0+9pAm/R2sCOPKr5NBxVIab7fvFU0B1RxQ==",
"node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.13.8",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.8.tgz",
"integrity": "sha512-Vy1zbZhCOdsmvGR6tJhAvO5vhP7eiS8xkbYQSoVa7o6KlIy3W8Rc53ED4qI4qpeRDjv3mLfXSEpYU6Yq4pgXRg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
......@@ -811,11 +815,6 @@
}
}
},
"node_modules/@vueuse/metadata": {
"version": "8.9.4",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-8.9.4.tgz",
"integrity": "sha512-IwSfzH80bnJMzqhaapqJl9JRIiyQU0zsRGEgnxN6jhq7992cPUJIRfV+JHRIZXjYqbwt07E1gTEp0R0zPJ1aqw=="
},
"node_modules/acorn": {
"version": "8.8.0",
"resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.8.0.tgz",
......@@ -1458,6 +1457,81 @@
"vue": "^3.2.0"
}
},
"node_modules/element-plus/node_modules/@types/web-bluetooth": {
"version": "0.0.14",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz",
"integrity": "sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A=="
},
"node_modules/element-plus/node_modules/@vueuse/core": {
"version": "8.9.4",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-8.9.4.tgz",
"integrity": "sha512-B/Mdj9TK1peFyWaPof+Zf/mP9XuGAngaJZBwPaXBvU3aCTZlx3ltlrFFFyMV4iGBwsjSCeUCgZrtkEj9dS2Y3Q==",
"dependencies": {
"@types/web-bluetooth": "^0.0.14",
"@vueuse/metadata": "8.9.4",
"@vueuse/shared": "8.9.4",
"vue-demi": "*"
},
"peerDependencies": {
"@vue/composition-api": "^1.1.0",
"vue": "^2.6.0 || ^3.2.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
},
"vue": {
"optional": true
}
}
},
"node_modules/element-plus/node_modules/@vueuse/core/node_modules/@vueuse/shared": {
"version": "8.9.4",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-8.9.4.tgz",
"integrity": "sha512-wt+T30c4K6dGRMVqPddexEVLa28YwxW5OFIPmzUHICjphfAuBFTTdDoyqREZNDOFJZ44ARH1WWQNCUK8koJ+Ag==",
"dependencies": {
"vue-demi": "*"
},
"peerDependencies": {
"@vue/composition-api": "^1.1.0",
"vue": "^2.6.0 || ^3.2.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
},
"vue": {
"optional": true
}
}
},
"node_modules/element-plus/node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.13.8",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.8.tgz",
"integrity": "sha512-Vy1zbZhCOdsmvGR6tJhAvO5vhP7eiS8xkbYQSoVa7o6KlIy3W8Rc53ED4qI4qpeRDjv3mLfXSEpYU6Yq4pgXRg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/element-plus/node_modules/@vueuse/metadata": {
"version": "8.9.4",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-8.9.4.tgz",
"integrity": "sha512-IwSfzH80bnJMzqhaapqJl9JRIiyQU0zsRGEgnxN6jhq7992cPUJIRfV+JHRIZXjYqbwt07E1gTEp0R0zPJ1aqw=="
},
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.4.tgz",
......@@ -4936,9 +5010,9 @@
"dev": true
},
"@types/web-bluetooth": {
"version": "0.0.14",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz",
"integrity": "sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A=="
"version": "0.0.15",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.15.tgz",
"integrity": "sha512-w7hEHXnPMEZ+4nGKl/KDRVpxkwYxYExuHOYXyzIzCDzEZ9ZCGMAewulr9IqJu2LR4N37fcnb1XVeuZ09qgOxhA=="
},
"@typescript-eslint/eslint-plugin": {
"version": "5.33.0",
......@@ -5226,36 +5300,44 @@
"requires": {}
},
"@vueuse/core": {
"version": "8.9.4",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-8.9.4.tgz",
"integrity": "sha512-B/Mdj9TK1peFyWaPof+Zf/mP9XuGAngaJZBwPaXBvU3aCTZlx3ltlrFFFyMV4iGBwsjSCeUCgZrtkEj9dS2Y3Q==",
"version": "9.1.0",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.1.0.tgz",
"integrity": "sha512-BIroqvXEqt826aE9r3K5cox1zobuPuAzdYJ36kouC2TVhlXvFKIILgFVWrpp9HZPwB3aLzasmG3K87q7TSyXZg==",
"requires": {
"@types/web-bluetooth": "^0.0.14",
"@vueuse/metadata": "8.9.4",
"@vueuse/shared": "8.9.4",
"@types/web-bluetooth": "^0.0.15",
"@vueuse/metadata": "9.1.0",
"@vueuse/shared": "9.1.0",
"vue-demi": "*"
},
"dependencies": {
"@vueuse/shared": {
"version": "8.9.4",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-8.9.4.tgz",
"integrity": "sha512-wt+T30c4K6dGRMVqPddexEVLa28YwxW5OFIPmzUHICjphfAuBFTTdDoyqREZNDOFJZ44ARH1WWQNCUK8koJ+Ag==",
"requires": {
"vue-demi": "*"
}
},
"vue-demi": {
"version": "0.13.6",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.6.tgz",
"integrity": "sha512-02NYpxgyGE2kKGegRPYlNQSL1UWfA/+JqvzhGCOYjhfbLWXU5QQX0+9pAm/R2sCOPKr5NBxVIab7fvFU0B1RxQ==",
"version": "0.13.8",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.8.tgz",
"integrity": "sha512-Vy1zbZhCOdsmvGR6tJhAvO5vhP7eiS8xkbYQSoVa7o6KlIy3W8Rc53ED4qI4qpeRDjv3mLfXSEpYU6Yq4pgXRg==",
"requires": {}
}
}
},
"@vueuse/metadata": {
"version": "8.9.4",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-8.9.4.tgz",
"integrity": "sha512-IwSfzH80bnJMzqhaapqJl9JRIiyQU0zsRGEgnxN6jhq7992cPUJIRfV+JHRIZXjYqbwt07E1gTEp0R0zPJ1aqw=="
"version": "9.1.0",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.1.0.tgz",
"integrity": "sha512-8OEhlog1iaAGTD3LICZ8oBGQdYeMwByvXetOtAOZCJOzyCRSwqwdggTsmVZZ1rkgYIEqgUBk942AsAPwM21s6A=="
},
"@vueuse/shared": {
"version": "9.1.0",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.1.0.tgz",
"integrity": "sha512-pB/3njQu4tfJJ78ajELNda0yMG6lKfpToQW7Soe09CprF1k3QuyoNi1tBNvo75wBDJWD+LOnr+c4B5HZ39jY/Q==",
"requires": {
"vue-demi": "*"
},
"dependencies": {
"vue-demi": {
"version": "0.13.8",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.8.tgz",
"integrity": "sha512-Vy1zbZhCOdsmvGR6tJhAvO5vhP7eiS8xkbYQSoVa7o6KlIy3W8Rc53ED4qI4qpeRDjv3mLfXSEpYU6Yq4pgXRg==",
"requires": {}
}
}
},
"acorn": {
"version": "8.8.0",
......@@ -5774,6 +5856,45 @@
"lodash-unified": "^1.0.2",
"memoize-one": "^6.0.0",
"normalize-wheel-es": "^1.2.0"
},
"dependencies": {
"@types/web-bluetooth": {
"version": "0.0.14",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz",
"integrity": "sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A=="
},
"@vueuse/core": {
"version": "8.9.4",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-8.9.4.tgz",
"integrity": "sha512-B/Mdj9TK1peFyWaPof+Zf/mP9XuGAngaJZBwPaXBvU3aCTZlx3ltlrFFFyMV4iGBwsjSCeUCgZrtkEj9dS2Y3Q==",
"requires": {
"@types/web-bluetooth": "^0.0.14",
"@vueuse/metadata": "8.9.4",
"@vueuse/shared": "8.9.4",
"vue-demi": "*"
},
"dependencies": {
"@vueuse/shared": {
"version": "8.9.4",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-8.9.4.tgz",
"integrity": "sha512-wt+T30c4K6dGRMVqPddexEVLa28YwxW5OFIPmzUHICjphfAuBFTTdDoyqREZNDOFJZ44ARH1WWQNCUK8koJ+Ag==",
"requires": {
"vue-demi": "*"
}
},
"vue-demi": {
"version": "0.13.8",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.8.tgz",
"integrity": "sha512-Vy1zbZhCOdsmvGR6tJhAvO5vhP7eiS8xkbYQSoVa7o6KlIy3W8Rc53ED4qI4qpeRDjv3mLfXSEpYU6Yq4pgXRg==",
"requires": {}
}
}
},
"@vueuse/metadata": {
"version": "8.9.4",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-8.9.4.tgz",
"integrity": "sha512-IwSfzH80bnJMzqhaapqJl9JRIiyQU0zsRGEgnxN6jhq7992cPUJIRfV+JHRIZXjYqbwt07E1gTEp0R0zPJ1aqw=="
}
}
},
"end-of-stream": {
......
......@@ -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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论