feat(im): 继续优化频道的各种代码(v2)

im
YunaiV 2026-05-19 17:48:35 +08:00
parent bfd407d75b
commit 2442a01e48
3 changed files with 39 additions and 115 deletions

View File

@ -36,7 +36,6 @@ export const deleteManagerChannel = (id: number) => {
}
// 获得启用的频道精简列表(表单选择用)
// TODO @AI改成 simplelist 命名上?
export const getEnabledChannelList = () => {
export const getSimpleChannelList = () => {
return request.get<ImManagerChannelVO[]>({ url: '/im/manager/channel/simple-list' })
}

View File

@ -1,5 +1,4 @@
<template>
<!-- TODO @AI要不使用 model 组件弹窗用户允许手动弹窗 -->
<div class="material-card" @click="onClick">
<div class="title">{{ payload.title || '(无标题)' }}</div>
<img v-if="payload.coverUrl" class="cover" :src="payload.coverUrl" />
@ -7,37 +6,23 @@
<span class="link">{{ payload.url ? '外链' : '查看详情' }}</span>
</div>
<!-- 全屏文章详情仿微信公众号文章打开 -->
<el-dialog
<Dialog
v-model="detailVisible"
:show-close="false"
:title="payload.title || '详情'"
fullscreen
append-to-body
destroy-on-close
class="material-detail-dialog"
>
<template #header>
<div class="detail-header">
<button class="back-btn" @click="detailVisible = false">
<Icon icon="ant-design:close-outlined" :size="18" />
</button>
<span class="detail-title">{{ payload.title || '详情' }}</span>
<span class="placeholder"></span>
</div>
</template>
<div v-loading="detailLoading" class="detail-body">
<div v-loading="detailLoading" class="material-detail-body">
<div class="article-title">{{ payload.title || '' }}</div>
<div v-if="detailHtml" class="article-content" v-html="detailHtml"></div>
<div v-if="detailHtml" class="article-content" v-dompurify-html="detailHtml"></div>
<div v-else-if="!detailLoading" class="article-empty">暂无正文</div>
</div>
</el-dialog>
</Dialog>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue'
import { ElDialog } from 'element-plus'
import type { PropType } from 'vue'
import Icon from '@/components/Icon/src/Icon.vue'
import { getChannelMaterial } from '@/api/im/channel/material'
import { parseMessage, type MaterialMessage } from '@/views/im/utils/message'
@ -62,7 +47,8 @@ const detailHtml = ref('')
/** 点击行为url 非空跳外链;为空则按 materialId 拉富文本正文,全屏 dialog 渲染 */
const onClick = async () => {
if (payload.value.url) {
window.open(payload.value.url, '_blank')
// noopener,noreferrer window.opener / referrer
window.open(payload.value.url, '_blank', 'noopener,noreferrer')
return
}
if (!props.message.materialId) {
@ -137,107 +123,46 @@ const onClick = async () => {
color: var(--el-color-primary);
}
}
</style>
<style lang="scss">
/* 全屏文章详情样式(非 scopedel-dialog 全屏后 header / body 在 teleport 子树) */
.material-detail-dialog {
.el-dialog__header {
margin: 0;
padding: 0;
border-bottom: 1px solid var(--el-border-color-lighter);
.material-detail-body {
max-width: 720px;
margin: 0 auto;
padding: 24px 20px 80px;
.article-title {
font-size: 22px;
font-weight: 600;
line-height: 1.4;
color: var(--el-text-color-primary);
margin-bottom: 20px;
}
.el-dialog__body {
padding: 0;
}
.article-content {
font-size: 15px;
line-height: 1.75;
color: var(--el-text-color-primary);
.detail-header {
display: flex;
align-items: center;
height: 52px;
padding: 0 12px;
background: var(--el-bg-color);
.back-btn {
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
border: none;
border-radius: 50%;
cursor: pointer;
color: var(--el-text-color-primary);
&:hover {
background: var(--el-fill-color-light);
}
:deep(img) {
max-width: 100%;
height: auto;
}
.detail-title {
flex: 1;
text-align: center;
font-size: 15px;
font-weight: 500;
color: var(--el-text-color-primary);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
:deep(p) {
margin: 12px 0;
}
.placeholder {
width: 36px;
}
}
.detail-body {
max-width: 720px;
margin: 0 auto;
padding: 24px 20px 80px;
min-height: calc(100vh - 52px);
.article-title {
font-size: 22px;
:deep(h1),
:deep(h2),
:deep(h3) {
margin: 20px 0 12px;
font-weight: 600;
line-height: 1.4;
color: var(--el-text-color-primary);
margin-bottom: 20px;
}
}
.article-content {
font-size: 15px;
line-height: 1.75;
color: var(--el-text-color-primary);
:deep(img),
img {
max-width: 100%;
height: auto;
}
:deep(p),
p {
margin: 12px 0;
}
:deep(h1),
:deep(h2),
:deep(h3),
h1,
h2,
h3 {
margin: 20px 0 12px;
font-weight: 600;
}
}
.article-empty {
text-align: center;
color: var(--el-text-color-secondary);
margin-top: 80px;
}
.article-empty {
text-align: center;
color: var(--el-text-color-secondary);
margin-top: 80px;
}
}
</style>

View File

@ -1,6 +1,6 @@
import { defineStore, acceptHMRUpdate } from 'pinia'
import { store } from '@/store'
import { getEnabledChannelList, type ImManagerChannelVO } from '@/api/im/manager/channel'
import { getSimpleChannelList, type ImManagerChannelVO } from '@/api/im/manager/channel'
import { useConversationStore } from './conversationStore'
import { ImConversationType } from '../../utils/constants'
import { getCurrentUserId, imStorage, setQuietly, StorageKeys } from '../../utils/storage'
@ -62,7 +62,7 @@ export const useChannelStore = defineStore('imChannelStore', {
return
}
try {
this.channels = (await getEnabledChannelList()) || []
this.channels = (await getSimpleChannelList()) || []
this.loaded = true
this.syncConversationMetadata()
this.saveChannels()