11 changed files with 220 additions and 85 deletions
@ -1,80 +1,35 @@ |
|||||||
<template> |
<template> |
||||||
<div :class="prefixCls"> |
<div> |
||||||
<Popover title="" trigger="click" :overlayClassName="`${prefixCls}__overlay`"> |
<Tooltip :title="tips"> |
||||||
<Badge :count="count" dot :numberStyle="numberStyle"> |
<Badge :count="unreadCount" :offset="[0, 15]" size="small" @click="go({ path: PageEnum.MESSAGE_PAGE })"> |
||||||
<BellOutlined /> |
<BellOutlined /> |
||||||
</Badge> |
</Badge> |
||||||
<template #content> |
</Tooltip> |
||||||
<Tabs> |
|
||||||
<template v-for="item in listData" :key="item.key"> |
|
||||||
<TabPane> |
|
||||||
<template #tab> |
|
||||||
{{ item.name }} |
|
||||||
<span v-if="item.list.length !== 0">({{ item.list.length }})</span> |
|
||||||
</template> |
|
||||||
<!-- 绑定title-click事件的通知列表中标题是“可点击”的--> |
|
||||||
<NoticeList :list="item.list" v-if="item.key === '1'" @title-click="onNoticeClick" /> |
|
||||||
<NoticeList :list="item.list" v-else /> |
|
||||||
</TabPane> |
|
||||||
</template> |
|
||||||
</Tabs> |
|
||||||
</template> |
|
||||||
</Popover> |
|
||||||
</div> |
</div> |
||||||
</template> |
</template> |
||||||
<script lang="ts" setup> |
<script lang="ts" setup> |
||||||
import { computed, ref } from 'vue' |
import { onMounted, computed } from 'vue' |
||||||
import { Popover, Tabs, Badge } from 'ant-design-vue' |
import { Badge, Tooltip } from 'ant-design-vue' |
||||||
import { BellOutlined } from '@ant-design/icons-vue' |
import { BellOutlined } from '@ant-design/icons-vue' |
||||||
import { tabListData, ListItem } from './data' |
import { useGo } from '@/hooks/web/usePage' |
||||||
import NoticeList from './NoticeList.vue' |
import { PageEnum } from '@/enums/pageEnum' |
||||||
import { useDesign } from '@/hooks/web/useDesign' |
import { useUserMessageStore } from '@/store/modules/userMessage' |
||||||
import { useMessage } from '@/hooks/web/useMessage' |
import { storeToRefs } from 'pinia' |
||||||
|
|
||||||
const TabPane = Tabs.TabPane |
const go = useGo() |
||||||
const numberStyle = ref({}) |
|
||||||
const { prefixCls } = useDesign('header-notify') |
|
||||||
const { createMessage } = useMessage() |
|
||||||
const listData = ref(tabListData) |
|
||||||
|
|
||||||
const count = computed(() => { |
const store = useUserMessageStore() |
||||||
let count = 0 |
const { unreadCount } = storeToRefs(store) |
||||||
for (let i = 0; i < tabListData.length; i++) { |
const tips = computed<string>(() => { |
||||||
count += tabListData[i].list.length |
if (unreadCount.value === 0) { |
||||||
|
return '查看站内信' |
||||||
} |
} |
||||||
return count |
return `查看站内信: 未读 ${unreadCount.value} 条` |
||||||
}) |
}) |
||||||
|
|
||||||
function onNoticeClick(record: ListItem) { |
onMounted(async () => { |
||||||
createMessage.success('你点击了通知,ID=' + record.id) |
// 通过store进行更新 |
||||||
// 可以直接将其标记为已读(为标题添加删除线),此处演示的代码会切换删除线状态 |
store.updateUnreadCount() |
||||||
record.titleDelete = !record.titleDelete |
}) |
||||||
} |
|
||||||
</script> |
</script> |
||||||
<style lang="less"> |
<style lang="less"></style> |
||||||
@prefix-cls: ~'@{namespace}-header-notify'; |
|
||||||
|
|
||||||
.@{prefix-cls} { |
|
||||||
padding-top: 2px; |
|
||||||
|
|
||||||
&__overlay { |
|
||||||
max-width: 360px; |
|
||||||
} |
|
||||||
|
|
||||||
.ant-tabs-content { |
|
||||||
width: 300px; |
|
||||||
} |
|
||||||
|
|
||||||
.ant-badge { |
|
||||||
font-size: 18px; |
|
||||||
|
|
||||||
.ant-badge-multiple-words { |
|
||||||
padding: 0 4px; |
|
||||||
} |
|
||||||
|
|
||||||
svg { |
|
||||||
width: 0.9em; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
</style> |
|
||||||
|
@ -0,0 +1,24 @@ |
|||||||
|
import { defineStore } from 'pinia' |
||||||
|
import { getUnreadNotifyMessageCount } from '@/api/system/notify/message' |
||||||
|
|
||||||
|
type MessageState = { |
||||||
|
unreadCount: number // 未读消息数量
|
||||||
|
} |
||||||
|
|
||||||
|
export const useUserMessageStore = defineStore('userMessage', { |
||||||
|
state: (): MessageState => ({ |
||||||
|
unreadCount: 0 |
||||||
|
}), |
||||||
|
getters: { |
||||||
|
getUnreadCount(state) { |
||||||
|
return state.unreadCount |
||||||
|
} |
||||||
|
}, |
||||||
|
actions: { |
||||||
|
// 更新未读消息的数量
|
||||||
|
async updateUnreadCount() { |
||||||
|
const count = await getUnreadNotifyMessageCount() |
||||||
|
this.unreadCount = count |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
@ -1,5 +1,5 @@ |
|||||||
<template> |
<template> |
||||||
<BasicModal title="详情" @register="innerRegister"> |
<BasicModal title="站内信详情" @register="innerRegister"> |
||||||
<Description @register="descriptionRegister" /> |
<Description @register="descriptionRegister" /> |
||||||
</BasicModal> |
</BasicModal> |
||||||
</template> |
</template> |
@ -0,0 +1,97 @@ |
|||||||
|
import { useRender } from '@/components/Table' |
||||||
|
import { DICT_TYPE } from '@/utils/dict' |
||||||
|
import { JsonPreview } from '@/components/CodeEditor' |
||||||
|
import { DescItem } from '@/components/Description/index' |
||||||
|
import { h } from 'vue' |
||||||
|
|
||||||
|
// 站内信详情modal
|
||||||
|
export const infoSchema: DescItem[] = [ |
||||||
|
{ |
||||||
|
field: 'id', |
||||||
|
label: '编号', |
||||||
|
labelMinWidth: 50 |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'readStatus', |
||||||
|
label: '是否已读', |
||||||
|
render: (value) => { |
||||||
|
return useRender.renderDict(value, DICT_TYPE.INFRA_BOOLEAN_STRING) |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'userType', |
||||||
|
label: '用户类型', |
||||||
|
render: (value) => { |
||||||
|
console.log(value) |
||||||
|
return useRender.renderDict(value, DICT_TYPE.USER_TYPE) |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'userType', |
||||||
|
label: '用户编号' |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'templateId', |
||||||
|
label: '模板编号' |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'templateCode', |
||||||
|
label: '模板编码' |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'templateNickname', |
||||||
|
label: '发送人名称' |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'templateContent', |
||||||
|
label: '模板内容' |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'templateParams', |
||||||
|
label: '模板参数', |
||||||
|
render: (value) => { |
||||||
|
return h(JsonPreview, { data: value }) |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'templateType', |
||||||
|
label: '模板类型', |
||||||
|
render: (value) => { |
||||||
|
return useRender.renderDict(value, DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE) |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'readTime', |
||||||
|
label: '阅读时间', |
||||||
|
render: (value) => { |
||||||
|
if (!value) { |
||||||
|
return useRender.renderTag('未阅读') |
||||||
|
} |
||||||
|
return useRender.renderDate(value) |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'createTime', |
||||||
|
label: '创建时间', |
||||||
|
render: (value) => { |
||||||
|
return useRender.renderDate(value) |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
|
||||||
|
// 站内信详情
|
||||||
|
export interface MessageInfo { |
||||||
|
userId: number |
||||||
|
userType: number |
||||||
|
templateId: number |
||||||
|
templateCode: string |
||||||
|
templateNickname: string |
||||||
|
templateContent: string |
||||||
|
templateType: number |
||||||
|
templateParams: { [key: string]: string } |
||||||
|
readStatus: boolean |
||||||
|
readTime?: any |
||||||
|
id: number |
||||||
|
createTime: number |
||||||
|
key: string |
||||||
|
} |
Reference in new issue