feat(notify): 添加消息记录管理功能

- 新增 NotifyMessageRecordList 组件实现消息记录列表功能
- 在 NotificationMessage 组件中更新路由跳转至新的消息记录页面
- 添加消息记录相关国际化配置项
- 创建独立的消息记录页面组件
- 更新 BoxProductList 组件中的 actionRef 引用管理
- 优化消息记录列表的搜索和筛选功能
- 实现消息点击自动标记已读功能
- 添加消息记录的详细信息查看功能
This commit is contained in:
shenyifei 2026-01-16 11:06:42 +08:00
parent f183da70ee
commit 33b46abc27
8 changed files with 208 additions and 8 deletions

View File

@ -210,6 +210,7 @@ export default function BoxProductList(props: IBoxProductListProps) {
>[];
const actionRef = useRef<ActionType>();
const actionBrandRef = useRef<ActionType>();
return (
<BizContainer<
@ -263,6 +264,7 @@ export default function BoxProductList(props: IBoxProductListProps) {
status
drag={{
fieldProps: {
actionRef: actionRef,
tableRender: (_, defaultDom) => (
<RouteContext.Consumer>
{(value: RouteContextType) => {
@ -296,12 +298,12 @@ export default function BoxProductList(props: IBoxProductListProps) {
ghost={true}
search={false}
onValueChange={() => {
actionRef.current?.reload();
actionBrandRef.current?.reload();
}}
/>,
],
}}
actionRef={actionRef}
actionRef={actionBrandRef}
ghost={true}
params={boxBrandParams}
grid={{ column: 1 }}
@ -378,7 +380,7 @@ export default function BoxProductList(props: IBoxProductListProps) {
);
}
actionRef.current?.reload();
actionBrandRef.current?.reload();
}}
checkedChildren={intl.formatMessage({
id:
@ -402,6 +404,10 @@ export default function BoxProductList(props: IBoxProductListProps) {
ghost={true}
search={false}
brandId={item.brandId}
onValueChange={() => {
actionBrandRef.current?.reload();
actionRef.current?.reload();
}}
trigger={() => {
return <Button type="link"></Button>;
}}
@ -412,6 +418,10 @@ export default function BoxProductList(props: IBoxProductListProps) {
ghost={true}
search={false}
brandId={item.brandId}
onValueChange={() => {
actionBrandRef.current?.reload();
actionRef.current?.reload();
}}
trigger={() => {
return <Button type="link"></Button>;
}}
@ -442,6 +452,9 @@ export default function BoxProductList(props: IBoxProductListProps) {
mode={'create'}
ghost={true}
search={false}
onValueChange={() => {
actionBrandRef.current?.reload();
}}
/>
</div>
</ProCard>

View File

@ -80,13 +80,13 @@ const NotificationMessage: React.FC<NotificationMessageProps> = ({
markAsRead(item.messageReceiverId);
}
// 可以跳转到消息详情页面
// history.push(`/message/detail/${item.messageReceiverId}`);
// history.push(`/operation/settings/notify/message-record`);
};
// 查看更多消息
const handleViewMore = () => {
setDropdownOpen(false);
history.push('/message');
history.push('/operation/settings/notify/message-record');
};
// 下拉菜单内容

View File

@ -0,0 +1,163 @@
import { BizContainer, BizValueType, ModeType } from '@/components';
import { business } from '@/services';
import { useIntl } from '@@/exports';
import { ActionType, ProColumns } from '@ant-design/pro-components';
import { ProDescriptionsItemProps } from '@ant-design/pro-descriptions';
import { Tag } from 'antd';
import React, { useRef } from 'react';
interface INotifyMessageRecordListProps {
ghost?: boolean;
search?: boolean;
onValueChange?: () => void;
mode?: ModeType;
trigger?: () => React.ReactNode;
}
export default function NotifyMessageRecordList(
props: INotifyMessageRecordListProps,
) {
const {
ghost = false,
search = true,
mode = 'page',
trigger,
onValueChange,
} = props;
const intl = useIntl();
const intlPrefix = 'notifyMessageRecord';
const actionRef = useRef<ActionType>();
// 是否已读状态映射
const isReadMap: Record<string, { text: string; color: string }> = {
false: {
text: intl.formatMessage({ id: intlPrefix + '.status.unread' }),
color: 'red',
},
true: {
text: intl.formatMessage({ id: intlPrefix + '.status.read' }),
color: 'default',
},
};
const columns: ProColumns<BusinessAPI.MessageReceiverVO, BizValueType>[] = [
{
title: intl.formatMessage({ id: intlPrefix + '.column.title' }),
dataIndex: ['messageVO', 'title'],
key: 'messageId',
ellipsis: true,
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.content' }),
dataIndex: ['messageVO', 'content'],
key: 'content',
ellipsis: true,
hideInTable: true, // 内容较长,在表格中隐藏,只在详情中显示
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.isRead' }),
dataIndex: 'isRead',
key: 'isRead',
valueType: 'select',
valueEnum: {
true: {
text: isReadMap.true.text,
status: 'Default',
},
false: {
text: isReadMap.false.text,
status: 'Error',
},
},
render: (_, record) => {
const isRead = record.isRead ? 'true' : 'false';
const isReadInfo = isReadMap[isRead];
return <Tag color={isReadInfo.color}>{isReadInfo.text}</Tag>;
},
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.readAt' }),
dataIndex: 'readAt',
key: 'readAt',
valueType: 'dateTime',
search: false,
hideInTable: true, // 已读时间通常不显示在列表中
},
{
title: intl.formatMessage({ id: intlPrefix + '.column.createdAt' }),
dataIndex: 'createdAt',
key: 'createdAt',
valueType: 'dateTime',
search: false,
sorter: true,
},
];
const detailColumns: ProDescriptionsItemProps<
BusinessAPI.MessageReceiverVO,
BizValueType
>[] = columns as ProDescriptionsItemProps<
BusinessAPI.MessageReceiverVO,
BizValueType
>[];
return (
<BizContainer<
typeof business.messageReceiver,
BusinessAPI.MessageReceiverVO,
BusinessAPI.MessageReceiverPageQry
>
rowKey={'messageReceiverId'}
permission={'operation-notify-message-record'}
func={business.messageReceiver}
method={'messageReceiver'}
methodUpper={'MessageReceiver'}
intlPrefix={intlPrefix}
modeType={mode}
onValueChange={onValueChange}
container={{ ghost }}
actionRef={actionRef}
status={false}
page={{
fieldProps: {
bordered: true,
ghost,
// @ts-ignore
search,
pagination: {
defaultPageSize: 20,
showSizeChanger: true,
showQuickJumper: true,
},
},
columns,
options: () => [],
// 自定义行点击事件,点击消息自动标记已读
onRow: (record: any) => ({
onClick: async () => {
// 如果未读,标记为已读
if (!record.isRead) {
try {
await business.messageReceiver.markReadMessageReceiver({
messageReceiverId: record.messageReceiverId,
});
actionRef.current?.reload();
onValueChange?.();
} catch (error) {
console.error('标记已读失败:', error);
}
}
},
}),
}}
create={false}
update={false}
destroy={false}
detail={{
formType: 'drawer',
columns: detailColumns,
trigger,
}}
/>
);
}

View File

@ -27,9 +27,6 @@ const variables = [
'车次号',
'车牌号',
'目的地',
'利润金额',
'瓜农姓名',
'瓜农货款',
'录入员姓名',
'录入员提审时间',
// 采购单审核

View File

@ -1,2 +1,3 @@
export { default as NotificationMessage } from './NotificationMessage';
export { default as NotifyMessageRecordList } from './NotifyMessageRecordList';
export { default as NotifyMessageTemplateList } from './NotifyMessageTemplateList';

View File

@ -3435,4 +3435,24 @@ export default {
markReadSuccess: '标记已读成功',
markReadFailed: '标记已读失败',
},
notifyMessageRecord: {
column: {
title: '消息标题',
content: '消息内容',
isRead: '阅读状态',
readAt: '已读时间',
createdAt: '接收时间',
option: '操作',
},
status: {
read: '已读',
unread: '未读',
},
modal: {
view: {
title: '查看消息详情',
button: '详情',
},
},
},
};

View File

@ -0,0 +1,5 @@
import { NotifyMessageRecordList } from '@/components';
export default function Page() {
return <NotifyMessageRecordList />;
}

View File

@ -259,6 +259,7 @@ declare namespace BusinessAPI {
status?: boolean;
/** 纸箱品牌ID */
brandId?: string;
title?: string;
/** 品牌类型1_我方纸箱2_瓜农纸箱3_第三方纸箱4_礼盒 */
type?: 'OUR_BOX' | 'FARMER_BOX' | 'THIRD_PARTY_BOX' | 'GIFT_BOX';
offset?: number;