mirror of
https://gitee.com/bootx/dax-pay-ui.git
synced 2025-09-04 03:16:02 +00:00
feat 消息通知查看和未读列表
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
export enum PageEnum {
|
||||
// basic login path
|
||||
// 登录
|
||||
BASE_LOGIN = '/login',
|
||||
// 个人设置
|
||||
ACCOUNT_SETTING = '/account/setting',
|
||||
// basic home path
|
||||
// 站内信界面 (后端修改了路由路径后, 这个也需要修改)
|
||||
SITE_MESSAGE = '/person/siteMessage',
|
||||
// 登陆后主页
|
||||
BASE_HOME = '/dashboard',
|
||||
// error page path
|
||||
// 异常页
|
||||
ERROR_PAGE = '/exception',
|
||||
// error log page path
|
||||
ERROR_LOG_PAGE = '/error-log/list',
|
||||
|
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<basic-modal
|
||||
v-bind="$attrs"
|
||||
:width="modalWidth"
|
||||
title="通知消息"
|
||||
:min-height="550"
|
||||
:visible="visible"
|
||||
:mask-closable="false"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<a-card class="daily-article" :loading="confirmLoading">
|
||||
<a-card-meta :title="message.title" :description="'发布人:' + message.senderName + ' 发布时间: ' + message.senderTime" />
|
||||
<a-divider />
|
||||
<span v-html="message.content" class="article-content"></span>
|
||||
</a-card>
|
||||
<template #footer>
|
||||
<a-button key="cancel" @click="handleCancel">取消</a-button>
|
||||
</template>
|
||||
</basic-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import BasicModal from '/@/components/Modal/src/BasicModal.vue'
|
||||
import { $ref } from 'vue/macros'
|
||||
|
||||
const modalWidth = $ref('60%')
|
||||
let visible = $ref(false)
|
||||
let confirmLoading = $ref(false)
|
||||
let message = $ref({})
|
||||
|
||||
// 初始化 显示信息内容
|
||||
function init(messageInfo) {
|
||||
visible = true
|
||||
message = messageInfo
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
visible = false
|
||||
}
|
||||
defineExpose({ init })
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
@@ -1,181 +0,0 @@
|
||||
<template>
|
||||
<a-list :class="prefixCls" bordered :pagination="getPagination">
|
||||
<template v-for="item in getData" :key="item.id">
|
||||
<a-list-item class="list-item">
|
||||
<a-list-item-meta>
|
||||
<template #title>
|
||||
<div class="title">
|
||||
<a-typography-paragraph
|
||||
@click="handleTitleClick(item)"
|
||||
style="width: 100%; margin-bottom: 0 !important"
|
||||
:style="{ cursor: isTitleClickable ? 'pointer' : '' }"
|
||||
:delete="!!item.titleDelete"
|
||||
:ellipsis="$props.titleRows && $props.titleRows > 0 ? { rows: $props.titleRows, tooltip: !!item.title } : false"
|
||||
:content="item.title"
|
||||
/>
|
||||
<div class="extra" v-if="item.extra">
|
||||
<a-tag class="tag" :color="item.color">
|
||||
{{ item.extra }}
|
||||
</a-tag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #avatar>
|
||||
<a-avatar v-if="item.avatar" class="avatar" :src="item.avatar" />
|
||||
<span v-else> {{ item.avatar }}</span>
|
||||
</template>
|
||||
|
||||
<template #description>
|
||||
<div>
|
||||
<div class="description" v-if="item.description">
|
||||
<a-typography-paragraph
|
||||
style="width: 100%; margin-bottom: 0 !important"
|
||||
:ellipsis="$props.descRows && $props.descRows > 0 ? { rows: $props.descRows, tooltip: !!item.description } : false"
|
||||
:content="item.description"
|
||||
/>
|
||||
</div>
|
||||
<div class="datetime">
|
||||
{{ item.datetime }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, PropType, ref, watch, unref } from 'vue'
|
||||
import { ListItem } from './data'
|
||||
import { useDesign } from '/@/hooks/web/useDesign'
|
||||
import { List, Avatar, Tag, Typography } from 'ant-design-vue'
|
||||
import { isNumber } from '/@/utils/is'
|
||||
export default defineComponent({
|
||||
components: {
|
||||
[Avatar.name]: Avatar,
|
||||
[List.name]: List,
|
||||
[List.Item.name]: List.Item,
|
||||
AListItemMeta: List.Item.Meta,
|
||||
ATypographyParagraph: Typography.Paragraph,
|
||||
[Tag.name]: Tag,
|
||||
},
|
||||
props: {
|
||||
list: {
|
||||
type: Array as PropType<ListItem[]>,
|
||||
default: () => [],
|
||||
},
|
||||
pageSize: {
|
||||
type: [Boolean, Number] as PropType<Boolean | Number>,
|
||||
default: 5,
|
||||
},
|
||||
currentPage: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
titleRows: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
descRows: {
|
||||
type: Number,
|
||||
default: 2,
|
||||
},
|
||||
onTitleClick: {
|
||||
type: Function as PropType<(Recordable) => void>,
|
||||
},
|
||||
},
|
||||
emits: ['update:currentPage'],
|
||||
setup(props, { emit }) {
|
||||
const { prefixCls } = useDesign('header-notify-list')
|
||||
const current = ref(props.currentPage || 1)
|
||||
const getData = computed(() => {
|
||||
const { pageSize, list } = props
|
||||
if (pageSize === false) return []
|
||||
let size = isNumber(pageSize) ? pageSize : 5
|
||||
return list.slice(size * (unref(current) - 1), size * unref(current))
|
||||
})
|
||||
watch(
|
||||
() => props.currentPage,
|
||||
(v) => {
|
||||
current.value = v
|
||||
},
|
||||
)
|
||||
const isTitleClickable = computed(() => !!props.onTitleClick)
|
||||
const getPagination = computed(() => {
|
||||
const { list, pageSize } = props
|
||||
if (pageSize > 0 && list && list.length > pageSize) {
|
||||
return {
|
||||
total: list.length,
|
||||
pageSize,
|
||||
//size: 'small',
|
||||
current: unref(current),
|
||||
onChange(page) {
|
||||
current.value = page
|
||||
emit('update:currentPage', page)
|
||||
},
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
function handleTitleClick(item: ListItem) {
|
||||
props.onTitleClick && props.onTitleClick(item)
|
||||
}
|
||||
|
||||
return { prefixCls, getPagination, getData, handleTitleClick, isTitleClickable }
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@prefix-cls: ~'@{namespace}-header-notify-list';
|
||||
|
||||
.@{prefix-cls} {
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
::v-deep(.ant-pagination-disabled) {
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
&-item {
|
||||
padding: 6px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
.title {
|
||||
margin-bottom: 8px;
|
||||
font-weight: normal;
|
||||
|
||||
.extra {
|
||||
float: right;
|
||||
margin-top: -1.5px;
|
||||
margin-right: 0;
|
||||
font-weight: normal;
|
||||
|
||||
.tag {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.datetime {
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -14,14 +14,14 @@
|
||||
<a-spin :spinning="loading">
|
||||
<a-list>
|
||||
<a-list-item v-for="o in notReadMsgList" :key="o.id">
|
||||
<a href="javascript:" @click="showMessage(o)">
|
||||
<a-list-item-meta :description="o.senderTime">
|
||||
<template #title>
|
||||
<a-list-item-meta :description="o.senderTime">
|
||||
<template #title>
|
||||
<a @click="showMessage(o)">
|
||||
<a-tag color="red">未读</a-tag>
|
||||
<a-typography-text :ellipsis="{ tooltip: o.title }" :content="o.title" />
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
</a>
|
||||
<a-typography-text style="width: 150px" :ellipsis="{ tooltip: o.title }" :content="o.title" />
|
||||
</a>
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
<span>{{ o.senderName }}</span>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
@@ -31,20 +31,24 @@
|
||||
</a-spin>
|
||||
</template>
|
||||
</a-popover>
|
||||
<notice-icon-reader ref="noticeIconReader" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { onMounted } from 'vue'
|
||||
import { BellOutlined } from '@ant-design/icons-vue'
|
||||
import { tabListData, ListItem } from './data'
|
||||
import { useDesign } from '/@/hooks/web/useDesign'
|
||||
import { useMessage } from '/@/hooks/web/useMessage'
|
||||
import { $ref } from 'vue/macros'
|
||||
import { countByReceiveNotRead, pageByReceive } from '/@/layouts/default/header/components/notify/SiteMessage.api'
|
||||
import { router } from '/@/router'
|
||||
import { PageEnum } from '/@/enums/pageEnum'
|
||||
import NoticeIconReader from '/@/layouts/default/header/components/notify/NoticeIconReader.vue'
|
||||
|
||||
const { prefixCls } = useDesign('header-notify')
|
||||
const { createMessage } = useMessage()
|
||||
const listData = ref(tabListData)
|
||||
|
||||
const noticeIconReader = $ref<any>()
|
||||
|
||||
let loading = $ref(false)
|
||||
let visible = $ref(false)
|
||||
@@ -83,23 +87,18 @@
|
||||
}
|
||||
|
||||
// 跳转到站内信界面
|
||||
function toSiteMessage() {}
|
||||
function toSiteMessage() {
|
||||
visible = false
|
||||
router.push(PageEnum.SITE_MESSAGE)
|
||||
}
|
||||
|
||||
// 查看我的消息
|
||||
function showMessage(message) {}
|
||||
function onNoticeClick(record: ListItem) {
|
||||
createMessage.success('你点击了通知,ID=' + record.id)
|
||||
// 可以直接将其标记为已读(为标题添加删除线),此处演示的代码会切换删除线状态
|
||||
record.titleDelete = !record.titleDelete
|
||||
function showMessage(message) {
|
||||
visible = false
|
||||
if (!message.haveRead) {
|
||||
|
||||
}
|
||||
noticeIconReader.init(message)
|
||||
}
|
||||
</script>
|
||||
<style lang="less">
|
||||
.header-notice {
|
||||
display: inline-block;
|
||||
transition: all 0.3s;
|
||||
|
||||
span {
|
||||
vertical-align: initial;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="less"></style>
|
||||
|
@@ -20,11 +20,10 @@
|
||||
<lock-modal @register="register" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
// components
|
||||
import { Dropdown, Menu } from 'ant-design-vue'
|
||||
import type { MenuInfo } from 'ant-design-vue/lib/menu/src/interface'
|
||||
|
||||
import { computed, onMounted } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { useUserStore } from '/@/store/modules/user'
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'
|
||||
@@ -36,8 +35,6 @@
|
||||
|
||||
import { router } from '/@/router'
|
||||
import { PageEnum } from '/@/enums/pageEnum'
|
||||
import { getFilePreviewUrlPrefix } from '/@/api/common/FileUpload'
|
||||
import { $ref } from 'vue/macros'
|
||||
import DropdownMenuItem from '/@/layouts/default/header/components/user-dropdown/DropMenuItem.vue'
|
||||
import LockModal from '/@/layouts/default/header/components/lock/LockModal.vue'
|
||||
|
||||
|
Reference in New Issue
Block a user