feat(notice): 新增公告阅读记录管理功能
- 重构公告阅读状态接口为公告阅读记录列表接口 - 新增公告阅读记录模块,包含完整的CRUD操作 - 在公告列表页面集成阅读记录查看功能 - 实现公告阅读状态的表格展示和筛选功能 - 新增公告阅读记录详情页面和回复功能 - 添加公告阅读记录相关的命名空间定义master
parent
363edfed2c
commit
dbce939fc7
|
|
@ -24,7 +24,7 @@ export const noticeInfo = declareRequest(
|
||||||
"noticeLoading",
|
"noticeLoading",
|
||||||
"Get > /appmenu/notice/{id}",
|
"Get > /appmenu/notice/{id}",
|
||||||
);
|
);
|
||||||
export const noticeReadStatus = declareRequest(
|
export const noticeReadRecordList = declareRequest(
|
||||||
"noticeLoading",
|
"noticeLoading",
|
||||||
"Post > @/appmenu/notice/noticeReadStatus",
|
"Post > @/appmenu/notice/noticeReadRecordList",
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { declareRequest } from "@cqsjjb/jjb-dva-runtime";
|
||||||
|
|
||||||
|
export const noticeReadRecordList = declareRequest(
|
||||||
|
"noticeReadRecordLoading",
|
||||||
|
"Post > @/appmenu/noticeReadRecord/list",
|
||||||
|
);
|
||||||
|
export const noticeReadRecordAdd = declareRequest(
|
||||||
|
"noticeReadRecordLoading",
|
||||||
|
"Post > @/appmenu/noticeReadRecord/save",
|
||||||
|
);
|
||||||
|
export const noticeReadRecordEdit = declareRequest(
|
||||||
|
"noticeReadRecordLoading",
|
||||||
|
"Put > @/appmenu/noticeReadRecord/edit",
|
||||||
|
);
|
||||||
|
export const noticeReadRecordDelete = declareRequest(
|
||||||
|
"noticeReadRecordLoading",
|
||||||
|
"Delete > @/appmenu/noticeReadRecord/{id}",
|
||||||
|
);
|
||||||
|
export const noticeReadRecordBatchDelete = declareRequest(
|
||||||
|
"noticeReadRecordLoading",
|
||||||
|
"Delete > @/appmenu/noticeReadRecord/ids/{ids}",
|
||||||
|
);
|
||||||
|
export const noticeReadRecordInfo = declareRequest(
|
||||||
|
"noticeReadRecordLoading",
|
||||||
|
"Get > /appmenu/noticeReadRecord/{id}",
|
||||||
|
);
|
||||||
|
export const noticeInfo = declareRequest(
|
||||||
|
"noticeReadRecordLoading",
|
||||||
|
"Get > /appmenu/notice/noticeContentInfo/{id}",
|
||||||
|
);
|
||||||
|
|
||||||
|
export const noticeReadRecordReply = declareRequest(
|
||||||
|
"noticeReadRecordLoading",
|
||||||
|
"Put > @/appmenu/noticeReadRecord/reply",
|
||||||
|
);
|
||||||
|
|
@ -7,4 +7,5 @@ import { defineNamespace } from "@cqsjjb/jjb-dva-runtime";
|
||||||
export const NS_GLOBAL = defineNamespace("global");
|
export const NS_GLOBAL = defineNamespace("global");
|
||||||
export const NS_APP_MENU = defineNamespace("appMenu");
|
export const NS_APP_MENU = defineNamespace("appMenu");
|
||||||
export const NS_NOTICE = defineNamespace("Notice");
|
export const NS_NOTICE = defineNamespace("Notice");
|
||||||
|
export const NS_NoticeReadRecord = defineNamespace("NoticeReadRecord");
|
||||||
export const NS_CORPINFO = defineNamespace("corpInfo");
|
export const NS_CORPINFO = defineNamespace("corpInfo");
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ function List(props) {
|
||||||
<span
|
<span
|
||||||
style={{ color: "#00BCD4", cursor: "pointer" }}
|
style={{ color: "#00BCD4", cursor: "pointer" }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCurrentId(record.id);
|
setCurrentId(record.noticeId);
|
||||||
setViewModalVisible(true);
|
setViewModalVisible(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -145,7 +145,7 @@ function List(props) {
|
||||||
loading={props.noticeLoading}
|
loading={props.noticeLoading}
|
||||||
getData={getData}
|
getData={getData}
|
||||||
currentId={currentId}
|
currentId={currentId}
|
||||||
noticeReadStatus={props["noticeReadStatus"]}
|
noticeReadRecordList={props["noticeReadRecordList"]}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
setViewModalVisible(false);
|
setViewModalVisible(false);
|
||||||
setCurrentId("");
|
setCurrentId("");
|
||||||
|
|
@ -157,8 +157,12 @@ function List(props) {
|
||||||
}
|
}
|
||||||
function ViewModalComponent(props) {
|
function ViewModalComponent(props) {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const { tableProps, getData } = useTable(props["noticeReadStatus"], {
|
const { tableProps, getData } = useTable(props["noticeReadRecordList"], {
|
||||||
form,
|
form,
|
||||||
|
params: {
|
||||||
|
noticeId: props.currentId,
|
||||||
|
pageSize: 10,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
|
|
@ -170,26 +174,40 @@ function ViewModalComponent(props) {
|
||||||
maskClosable={false}
|
maskClosable={false}
|
||||||
open={props.open}
|
open={props.open}
|
||||||
title="查看"
|
title="查看"
|
||||||
width={800}
|
width={1000}
|
||||||
onOk={form.submit}
|
footer={null}
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
loading={props.loading}
|
loading={props.loading}
|
||||||
|
|
||||||
>
|
>
|
||||||
<Search
|
<Search
|
||||||
labelCol={{ span: 2 }}
|
labelCol={{ span: 8 }}
|
||||||
form={form}
|
form={form}
|
||||||
onFinish={getData}
|
onFinish={getData}
|
||||||
options={[
|
options={[
|
||||||
{ name: "companyName", label: "企业名称" },
|
{ name: "corpinfoName", label: "企业名称" },
|
||||||
{ name: "deptId", label: "是否阅读" },
|
{
|
||||||
|
name: "readStatus",
|
||||||
|
label: "是否阅读",
|
||||||
|
render: FORM_ITEM_RENDER_ENUM.SELECT,
|
||||||
|
items: [{ bianma: "0", name: "未读" }, { bianma: "1", name: "已读" }],
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<Table
|
<Table
|
||||||
|
rowKey="userId"
|
||||||
columns={[
|
columns={[
|
||||||
{ dataIndex: "companyName", title: "企业名称" },
|
{ dataIndex: "corpinfoName", title: "企业名称" },
|
||||||
{ dataIndex: "userName", title: "姓名" },
|
{ dataIndex: "userName", title: "姓名" },
|
||||||
{ dataIndex: "readStatus", title: "阅读状态" },
|
{
|
||||||
|
dataIndex: "readStatus",
|
||||||
|
title: "阅读状态",
|
||||||
|
render: (_, record) => {
|
||||||
|
if (!record.readStatus)
|
||||||
|
return "";
|
||||||
|
const scopeMap = { 0: "未读", 1: "已读" };
|
||||||
|
return scopeMap[record.readStatus];
|
||||||
|
},
|
||||||
|
},
|
||||||
{ dataIndex: "readTime", title: "阅读时间" },
|
{ dataIndex: "readTime", title: "阅读时间" },
|
||||||
{ dataIndex: "replyContent", title: "回复内容" },
|
{ dataIndex: "replyContent", title: "回复内容" },
|
||||||
]}
|
]}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||||
|
import { Button, Form, Space } from "antd";
|
||||||
|
import Page from "zy-react-library/components/Page";
|
||||||
|
import Search from "zy-react-library/components/Search/index";
|
||||||
|
import Table from "zy-react-library/components/Table/index";
|
||||||
|
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
|
||||||
|
import useTable from "zy-react-library/hooks/useTable";
|
||||||
|
import { NS_NoticeReadRecord } from "~/enumerate/namespace";
|
||||||
|
|
||||||
|
function NoticeReadRecord(props) {
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const { tableProps, getData } = useTable(props["noticeReadRecordList"], {
|
||||||
|
form,
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<Page isShowAllAction={false}>
|
||||||
|
<Search
|
||||||
|
labelCol={{ span: 6 }}
|
||||||
|
form={form}
|
||||||
|
onFinish={getData}
|
||||||
|
options={[
|
||||||
|
{ name: "title", label: "公告名称" },
|
||||||
|
{
|
||||||
|
name: "readStatus",
|
||||||
|
label: "是否阅读",
|
||||||
|
render: FORM_ITEM_RENDER_ENUM.SELECT,
|
||||||
|
items: [{ bianma: "0", name: "未读" }, { bianma: "1", name: "已读" }],
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Table
|
||||||
|
rowKey="noticeId"
|
||||||
|
columns={[
|
||||||
|
{ dataIndex: "title", title: "公告名称" },
|
||||||
|
{ dataIndex: "publishTime", title: "发布时间" },
|
||||||
|
{ title: "是否阅读", dataIndex: "readStatus", render: (_, record) => (
|
||||||
|
<div>{record.readStatus === "1" ? <span style={{ color: "green" }}>是</span> : record.readStatus === "0" ? <span style={{ color: "red" }}>否</span> : <span style={{ color: "red" }}>否</span>}</div>
|
||||||
|
) },
|
||||||
|
{
|
||||||
|
title: "操作",
|
||||||
|
align: "center",
|
||||||
|
width: 200,
|
||||||
|
render: (_, record) => (
|
||||||
|
<Space>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
onClick={() => props.history.push(`./View?id=${record.noticeId}`)}
|
||||||
|
>
|
||||||
|
查看
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
{...tableProps}
|
||||||
|
/>
|
||||||
|
</Page>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Connect([NS_NoticeReadRecord], true)(NoticeReadRecord);
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
import { Connect } from "@cqsjjb/jjb-dva-runtime";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Form,
|
||||||
|
message,
|
||||||
|
Modal,
|
||||||
|
Typography,
|
||||||
|
} from "antd";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import FormBuilder from "zy-react-library/components/FormBuilder";
|
||||||
|
import Page from "zy-react-library/components/Page";
|
||||||
|
import { FORM_ITEM_RENDER_ENUM } from "zy-react-library/enum/formItemRender";
|
||||||
|
import useGetUrlQuery from "zy-react-library/hooks/useGetUrlQuery";
|
||||||
|
import { NS_NoticeReadRecord } from "~/enumerate/namespace";
|
||||||
|
|
||||||
|
function NoticeReadRecordView(props) {
|
||||||
|
const { Title, Text } = Typography;
|
||||||
|
const queryParams = useGetUrlQuery();
|
||||||
|
const [noticeReadRecordInfo, setNoticeReadRecordInfo] = useState({});
|
||||||
|
const [replyModalVisible, setReplyModalVisible] = useState(false);
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const getData = async () => {
|
||||||
|
const { data } = await props["noticeInfo"]({ id: queryParams.id });
|
||||||
|
setNoticeReadRecordInfo(data);
|
||||||
|
// 如果未查看,则插入查看记录
|
||||||
|
if (data.readStatus !== "1") {
|
||||||
|
const res = await props["noticeReadRecordAdd"]({ noticeId: queryParams.id });
|
||||||
|
if (!res.success) {
|
||||||
|
message.error("记录阅读状态失败,请重新阅读");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setNoticeReadRecordInfo(prev => ({
|
||||||
|
...prev,
|
||||||
|
noticeReadId: res.data,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleReply = () => {
|
||||||
|
setReplyModalVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReplySubmit = async (values) => {
|
||||||
|
const { success } = await props["noticeReadRecordReply"]({
|
||||||
|
noticeReadId: noticeReadRecordInfo.noticeReadId,
|
||||||
|
replyContent: values.replyContent,
|
||||||
|
});
|
||||||
|
if (success) {
|
||||||
|
message.success("回复成功");
|
||||||
|
setReplyModalVisible(false);
|
||||||
|
form.resetFields();
|
||||||
|
window.history.back();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page
|
||||||
|
headerTitle="查看"
|
||||||
|
extraActionButtons={
|
||||||
|
noticeReadRecordInfo.requireReply && !noticeReadRecordInfo.replyContent && (
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={handleReply}
|
||||||
|
>
|
||||||
|
回复
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div style={{ maxWidth: 1200, margin: "0 auto", padding: "20px" }}>
|
||||||
|
<Title level={2} style={{ textAlign: "center", marginBottom: "24px" }}>
|
||||||
|
{noticeReadRecordInfo.title}
|
||||||
|
</Title>
|
||||||
|
|
||||||
|
<div style={{ textAlign: "center", marginBottom: "24px" }}>
|
||||||
|
<Text type="secondary">
|
||||||
|
发布时间:
|
||||||
|
{noticeReadRecordInfo.publishTime}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
minHeight: "200px",
|
||||||
|
padding: "20px",
|
||||||
|
marginBottom: "24px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div dangerouslySetInnerHTML={{ __html: noticeReadRecordInfo.content }} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
title="回复公告"
|
||||||
|
width={600}
|
||||||
|
open={replyModalVisible}
|
||||||
|
maskClosable={false}
|
||||||
|
onCancel={() => {
|
||||||
|
setReplyModalVisible(false);
|
||||||
|
form.resetFields();
|
||||||
|
}}
|
||||||
|
onOk={() => form.submit()}
|
||||||
|
confirmLoading={props.noticeReadRecordReplyLoading}
|
||||||
|
>
|
||||||
|
<FormBuilder
|
||||||
|
form={form}
|
||||||
|
span={24}
|
||||||
|
labelCol={{ span: 10 }}
|
||||||
|
showActionButtons={false}
|
||||||
|
onFinish={handleReplySubmit}
|
||||||
|
loading={props.noticeReadRecordReplyLoading}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
name: "replyContent",
|
||||||
|
label: "回复内容",
|
||||||
|
required: true,
|
||||||
|
render: FORM_ITEM_RENDER_ENUM.TEXTAREA,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
</Page>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Connect([NS_NoticeReadRecord], true)(NoticeReadRecordView);
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
function AppMenu(props) {
|
||||||
|
return props.children;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AppMenu;
|
||||||
Loading…
Reference in New Issue