11 changed files with 220 additions and 85 deletions
			
			
		@ -1,80 +1,35 @@
					 | 
				
			||||
<template> | 
				
			||||
  <div :class="prefixCls"> | 
				
			||||
    <Popover title="" trigger="click" :overlayClassName="`${prefixCls}__overlay`"> | 
				
			||||
      <Badge :count="count" dot :numberStyle="numberStyle"> | 
				
			||||
  <div> | 
				
			||||
    <Tooltip :title="tips"> | 
				
			||||
      <Badge :count="unreadCount" :offset="[0, 15]" size="small" @click="go({ path: PageEnum.MESSAGE_PAGE })"> | 
				
			||||
        <BellOutlined /> | 
				
			||||
      </Badge> | 
				
			||||
      <template #content> | 
				
			||||
        <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> | 
				
			||||
    </Tooltip> | 
				
			||||
  </div> | 
				
			||||
</template> | 
				
			||||
<script lang="ts" setup> | 
				
			||||
import { computed, ref } from 'vue' | 
				
			||||
import { Popover, Tabs, Badge } from 'ant-design-vue' | 
				
			||||
import { onMounted, computed } from 'vue' | 
				
			||||
import { Badge, Tooltip } from 'ant-design-vue' | 
				
			||||
import { BellOutlined } from '@ant-design/icons-vue' | 
				
			||||
import { tabListData, ListItem } from './data' | 
				
			||||
import NoticeList from './NoticeList.vue' | 
				
			||||
import { useDesign } from '@/hooks/web/useDesign' | 
				
			||||
import { useMessage } from '@/hooks/web/useMessage' | 
				
			||||
 | 
				
			||||
const TabPane = Tabs.TabPane | 
				
			||||
const numberStyle = ref({}) | 
				
			||||
const { prefixCls } = useDesign('header-notify') | 
				
			||||
const { createMessage } = useMessage() | 
				
			||||
const listData = ref(tabListData) | 
				
			||||
 | 
				
			||||
const count = computed(() => { | 
				
			||||
  let count = 0 | 
				
			||||
  for (let i = 0; i < tabListData.length; i++) { | 
				
			||||
    count += tabListData[i].list.length | 
				
			||||
import { useGo } from '@/hooks/web/usePage' | 
				
			||||
import { PageEnum } from '@/enums/pageEnum' | 
				
			||||
import { useUserMessageStore } from '@/store/modules/userMessage' | 
				
			||||
import { storeToRefs } from 'pinia' | 
				
			||||
 | 
				
			||||
const go = useGo() | 
				
			||||
 | 
				
			||||
const store = useUserMessageStore() | 
				
			||||
const { unreadCount } = storeToRefs(store) | 
				
			||||
const tips = computed<string>(() => { | 
				
			||||
  if (unreadCount.value === 0) { | 
				
			||||
    return '查看站内信' | 
				
			||||
  } | 
				
			||||
  return count | 
				
			||||
  return `查看站内信: 未读 ${unreadCount.value} 条` | 
				
			||||
}) | 
				
			||||
 | 
				
			||||
function onNoticeClick(record: ListItem) { | 
				
			||||
  createMessage.success('你点击了通知,ID=' + record.id) | 
				
			||||
  // 可以直接将其标记为已读(为标题添加删除线),此处演示的代码会切换删除线状态 | 
				
			||||
  record.titleDelete = !record.titleDelete | 
				
			||||
} | 
				
			||||
onMounted(async () => { | 
				
			||||
  // 通过store进行更新 | 
				
			||||
  store.updateUnreadCount() | 
				
			||||
}) | 
				
			||||
</script> | 
				
			||||
<style lang="less"> | 
				
			||||
@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> | 
				
			||||
<style lang="less"></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> | 
				
			||||
  <BasicModal title="详情" @register="innerRegister"> | 
				
			||||
  <BasicModal title="站内信详情" @register="innerRegister"> | 
				
			||||
    <Description @register="descriptionRegister" /> | 
				
			||||
  </BasicModal> | 
				
			||||
</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