Files
school-developer/src/views/stuwork/classsafeedu/detail.vue
2026-01-22 13:38:10 +08:00

276 lines
6.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-dialog
title="查看详情"
v-model="visible"
:close-on-click-modal="false"
draggable
width="1000px">
<div v-loading="loading" class="article-container" v-if="detailData">
<!-- 报纸文章样式 -->
<div class="article-header">
<h1 class="article-title">{{ detailData.themeName || '-' }}</h1>
<div class="article-meta">
<div class="meta-left">
<span class="meta-item">学年{{ detailData.schoolYear || '-' }}</span>
<span class="meta-item">学期{{ formatSchoolTerm(detailData.schoolTerm) }}</span>
<span class="meta-item">班号{{ detailData.classNo || '-' }}</span>
</div>
<div class="meta-right">
<span class="meta-item">主持人{{ detailData.author || '-' }}</span>
<span class="meta-item">活动地点{{ detailData.address || '-' }}</span>
<span class="meta-item">活动时间{{ detailData.recordDate || '-' }}</span>
<span class="meta-item">参加人数{{ detailData.attendNum || '-' }}</span>
</div>
</div>
</div>
<!-- 活动内容 -->
<div class="article-content" v-html="detailData.content || '-'"></div>
<!-- 活动图片1 -->
<div v-if="imageList1.length > 0" class="article-images">
<h3 class="images-title">活动照片</h3>
<div class="images-grid">
<el-image
v-for="(url, index) in imageList1"
:key="index"
:src="url"
:preview-src-list="imageList1"
:initial-index="index"
fit="cover"
class="article-image" />
</div>
</div>
<!-- 活动图片2 -->
<div v-if="imageList2.length > 0" class="article-images">
<h3 class="images-title">活动照片2</h3>
<div class="images-grid">
<el-image
v-for="(url, index) in imageList2"
:key="index"
:src="url"
:preview-src-list="imageList2"
:initial-index="index"
fit="cover"
class="article-image" />
</div>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false"> </el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts" name="ClassSafeEduDetailDialog">
import { ref, computed, onMounted } from 'vue'
import { getDetail } from '/@/api/stuwork/classsafeedu'
import { getDicts } from '/@/api/admin/dict'
import { useMessage } from '/@/hooks/message'
// 定义变量内容
const visible = ref(false)
const loading = ref(false)
const detailData = ref<any>({})
const schoolTermList = ref<any[]>([])
// 图片列表
const imageList1 = computed(() => {
if (!detailData.value.attachment) return []
const urls = typeof detailData.value.attachment === 'string'
? detailData.value.attachment.split(',').filter((url: string) => url.trim())
: []
return urls
})
const imageList2 = computed(() => {
if (!detailData.value.attachment2) return []
const urls = typeof detailData.value.attachment2 === 'string'
? detailData.value.attachment2.split(',').filter((url: string) => url.trim())
: []
return urls
})
// 格式化学期
const formatSchoolTerm = (value: string | number) => {
if (value === null || value === undefined || value === '') {
return '-'
}
const dictItem = schoolTermList.value.find(item => item.value == value)
return dictItem ? dictItem.label : value
}
// 打开弹窗
const openDialog = async (row: any) => {
visible.value = true
detailData.value = {}
if (!row.id) {
useMessage().warning('数据异常')
return
}
loading.value = true
try {
const res = await getDetail(row.id)
if (res.data) {
detailData.value = res.data
} else {
useMessage().error('获取详情失败')
}
} catch (err: any) {
useMessage().error(err.msg || '获取详情失败')
} finally {
loading.value = false
}
}
// 获取学期字典
const getSchoolTermDict = async () => {
try {
const res = await getDicts('school_term')
if (res.data && Array.isArray(res.data)) {
schoolTermList.value = res.data.map((item: any) => ({
label: item.label || item.dictLabel || item.name,
value: item.value || item.dictValue || item.code
}))
}
} catch (err) {
}
}
// 初始化
onMounted(() => {
getSchoolTermDict()
})
// 暴露方法
defineExpose({
openDialog
})
</script>
<style scoped>
.article-container {
padding: 20px;
max-width: 100%;
}
.article-header {
border-bottom: 2px solid #e4e7ed;
padding-bottom: 20px;
margin-bottom: 30px;
}
.article-title {
font-size: 28px;
font-weight: bold;
color: #303133;
margin: 0 0 15px 0;
line-height: 1.5;
text-align: center;
}
.article-meta {
display: flex;
justify-content: space-between;
align-items: flex-start;
font-size: 14px;
color: #909399;
padding-top: 10px;
flex-wrap: wrap;
gap: 10px;
}
.meta-left,
.meta-right {
display: flex;
flex-direction: column;
gap: 8px;
}
.meta-item {
font-weight: 500;
}
.article-content {
font-size: 16px;
line-height: 1.8;
color: #606266;
text-align: justify;
word-wrap: break-word;
min-height: 200px;
margin-bottom: 30px;
}
.article-content :deep(p) {
margin: 0 0 15px 0;
}
.article-content :deep(img) {
max-width: 100%;
height: auto;
display: block;
margin: 20px auto;
}
.article-content :deep(h1),
.article-content :deep(h2),
.article-content :deep(h3),
.article-content :deep(h4),
.article-content :deep(h5),
.article-content :deep(h6) {
margin: 20px 0 15px 0;
font-weight: bold;
}
.article-content :deep(ul),
.article-content :deep(ol) {
margin: 15px 0;
padding-left: 30px;
}
.article-content :deep(blockquote) {
border-left: 4px solid #409eff;
padding-left: 15px;
margin: 15px 0;
color: #909399;
font-style: italic;
}
.article-images {
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid #e4e7ed;
}
.images-title {
font-size: 18px;
font-weight: bold;
color: #303133;
margin: 0 0 15px 0;
}
.images-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 15px;
}
.article-image {
width: 100%;
height: 200px;
border-radius: 4px;
cursor: pointer;
transition: transform 0.3s;
}
.article-image:hover {
transform: scale(1.05);
}
</style>