feat 搭建架构骨架
This commit is contained in:
211
src/views/message/detail.vue
Normal file
211
src/views/message/detail.vue
Normal file
@@ -0,0 +1,211 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { AppButton } from '@/components'
|
||||
// 页面容器:数据只经 store,不直接 import api
|
||||
import { useMessageStore } from '@/stores/modules/message'
|
||||
import { formatFileSize } from '@/utils/format'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const messageStore = useMessageStore()
|
||||
|
||||
const item = computed(() => messageStore.current)
|
||||
const messageId = computed(() => String(route.params.id))
|
||||
|
||||
function load(): void {
|
||||
void messageStore.fetchDetail(messageId.value)
|
||||
}
|
||||
|
||||
function onBack(): void {
|
||||
void router.push('/message')
|
||||
}
|
||||
|
||||
function onPreview(): void {
|
||||
ElMessage.info('附件待接口接入')
|
||||
}
|
||||
|
||||
function onDownload(): void {
|
||||
ElMessage.info('附件待接口接入')
|
||||
}
|
||||
|
||||
watch(messageId, load)
|
||||
|
||||
onMounted(load)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="message-detail">
|
||||
<nav class="message-detail__breadcrumb text-secondary">
|
||||
<RouterLink to="/message" class="link">
|
||||
消息中心
|
||||
</RouterLink>
|
||||
<span> > </span>
|
||||
<span>{{ item ? `${item.type}详情` : '消息详情' }}</span>
|
||||
</nav>
|
||||
|
||||
<template v-if="item">
|
||||
<article class="message-detail__card">
|
||||
<h1 class="message-detail__title">
|
||||
{{ item.title }}
|
||||
</h1>
|
||||
<p class="message-detail__time text-secondary">
|
||||
发布时间:{{ item.publishTime }}
|
||||
</p>
|
||||
<div class="message-detail__content">
|
||||
{{ item.content }}
|
||||
</div>
|
||||
|
||||
<section v-if="item.attachments.length > 0" class="message-detail__attachments">
|
||||
<h2 class="message-detail__attachments-title">
|
||||
附件({{ item.attachments.length }})
|
||||
</h2>
|
||||
<ul class="message-detail__file-list">
|
||||
<li
|
||||
v-for="(file, index) in item.attachments"
|
||||
:key="`${file.name}-${index}`"
|
||||
class="message-detail__file"
|
||||
>
|
||||
<div class="message-detail__file-info">
|
||||
<span class="message-detail__file-name" :title="file.name">{{ file.name }}</span>
|
||||
<span class="message-detail__file-meta text-secondary">
|
||||
{{ formatFileSize(file.size) }} · 上传于{{ file.uploadTime }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="message-detail__file-actions">
|
||||
<button class="message-detail__file-btn" @click="onPreview">
|
||||
预览
|
||||
</button>
|
||||
<button class="message-detail__file-btn" @click="onDownload">
|
||||
下载
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<div class="message-detail__actions">
|
||||
<AppButton type="primary" @click="onBack">
|
||||
返回
|
||||
</AppButton>
|
||||
</div>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<p v-else class="message-detail__empty text-secondary">
|
||||
消息不存在
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.message-detail {
|
||||
padding-top: @spacing-lg;
|
||||
padding-bottom: @spacing-xxl;
|
||||
|
||||
&__breadcrumb {
|
||||
margin-bottom: @spacing-base;
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
|
||||
&__card {
|
||||
padding: @spacing-xl;
|
||||
border-radius: @radius-lg;
|
||||
background: @white;
|
||||
box-shadow: @shadow-base;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: @font-size-xl;
|
||||
font-weight: 600;
|
||||
color: @heading-color;
|
||||
}
|
||||
|
||||
&__time {
|
||||
margin-top: @spacing-sm;
|
||||
font-size: @font-size-sm;
|
||||
}
|
||||
|
||||
&__content {
|
||||
margin-top: @spacing-lg;
|
||||
padding: @spacing-base;
|
||||
border-radius: @radius-base;
|
||||
background: @bg-color-light;
|
||||
color: @text-color;
|
||||
font-size: @font-size-base;
|
||||
line-height: 1.8;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
&__attachments {
|
||||
margin-top: @spacing-lg;
|
||||
|
||||
&-title {
|
||||
margin-bottom: @spacing-sm;
|
||||
font-size: @font-size-lg;
|
||||
font-weight: 600;
|
||||
color: @heading-color;
|
||||
}
|
||||
}
|
||||
|
||||
&__file-list {
|
||||
.flex(column, flex-start);
|
||||
gap: @spacing-sm;
|
||||
}
|
||||
|
||||
&__file {
|
||||
.flex(row, space-between);
|
||||
gap: @spacing-base;
|
||||
padding: @spacing-sm @spacing-base;
|
||||
border: 1px solid @border-color;
|
||||
border-radius: @radius-base;
|
||||
background: @bg-color-light;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
&__file-info {
|
||||
.flex(column, flex-start);
|
||||
gap: 2px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
&__file-name {
|
||||
font-size: @font-size-base;
|
||||
color: @heading-color;
|
||||
.ellipsis();
|
||||
}
|
||||
|
||||
&__file-meta {
|
||||
font-size: @font-size-sm;
|
||||
}
|
||||
|
||||
&__file-actions {
|
||||
.flex(row, center);
|
||||
gap: @spacing-sm;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&__file-btn {
|
||||
font-size: @font-size-sm;
|
||||
color: @primary-color;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
|
||||
&__actions {
|
||||
.flex(row, flex-start);
|
||||
margin-top: @spacing-lg;
|
||||
}
|
||||
|
||||
&__empty {
|
||||
padding: @spacing-xxl 0;
|
||||
text-align: center;
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user