This commit is contained in:
Li1304553726 2025-04-27 19:30:42 +08:00
parent 8772be5e7a
commit 8293f6389d
6 changed files with 94 additions and 10 deletions

View File

@ -9,6 +9,7 @@ import {
ObjectType, ObjectType,
PostType, PostType,
PostState, PostState,
PostMeta,
} from '@nice/common'; } from '@nice/common';
import { MessageService } from '../message/message.service'; import { MessageService } from '../message/message.service';
import { BaseService } from '../base/base.service'; import { BaseService } from '../base/base.service';
@ -52,6 +53,15 @@ export class PostService extends BaseService<Prisma.PostDelegate> {
return result; return result;
} }
async update(args: Prisma.PostUpdateArgs, staff?: UserProfile) { async update(args: Prisma.PostUpdateArgs, staff?: UserProfile) {
// 确保 meta 字段是一个对象
if (args.data.reTime) {
// 处理不同类型的 reTime 输入
if (typeof args.data.reTime === 'string' || args.data.reTime instanceof Date) {
args.data.reTime = {
set: new Date(args.data.reTime)
};
}
}
args.data.authorId = staff?.id; args.data.authorId = staff?.id;
args.data.updatedAt = new Date(); args.data.updatedAt = new Date();
const result = await super.update(args); const result = await super.update(args);

View File

@ -50,8 +50,9 @@ export function useNavItem() {
icon: <InboxOutlined className="text-base" />, icon: <InboxOutlined className="text-base" />,
}, },
help: { help: {
to: env.LIB_URL || "27.57.72.38", // to: env.LIB_URL || "27.57.72.38",
label: "意见建议", to: "/help",
label: "心理锦囊",
icon: <CommentOutlined className="text-base" />, icon: <CommentOutlined className="text-base" />,
}, },
}; };

View File

@ -1,4 +1,4 @@
import { useContext } from "react"; import { useContext, useEffect } from "react";
import { PostDetailContext } from "../context/PostDetailContext"; import { PostDetailContext } from "../context/PostDetailContext";
import { Space, Typography } from "antd"; import { Space, Typography } from "antd";
import { PostBadge } from "../badge/PostBadge"; import { PostBadge } from "../badge/PostBadge";
@ -15,7 +15,13 @@ import dayjs from "dayjs";
import { LetterBadge } from "../../LetterBadge"; import { LetterBadge } from "../../LetterBadge";
const { Title, Paragraph, Text } = Typography; const { Title, Paragraph, Text } = Typography;
export default function Header() { export default function Header() {
const { post, user } = useContext(PostDetailContext); const { post, user, staff } = useContext(PostDetailContext);
// 添加更详细的日志
console.log('Post Data:', {
post,
reTime: post?.reTime,
reTimeType: post?.reTime ? typeof post.reTime : 'undefined'
});
return ( return (
<header className="rounded-t-xl bg-gradient-to-r from-primary to-primary-400 text-white p-6 relative"> <header className="rounded-t-xl bg-gradient-to-r from-primary to-primary-400 text-white p-6 relative">
<div className="flex flex-col space-b-1"> <div className="flex flex-col space-b-1">
@ -73,7 +79,25 @@ export default function Header() {
{post?.isPublic ? "公开" : "保密"} {post?.isPublic ? "公开" : "保密"}
</Text> </Text>
</Space> </Space>
<Space className="mr-4">
<span className="text-white"></span>
<Text className="text-white">
{staff?.phoneNumber || "暂无联系方式"}
</Text>
</Space>
<Space className="mr-4">
<span className="text-white"></span>
<Text className="text-white">
{post?.reTime ? (
<>
{/* <CalendarOutlined className="mr-1" /> */}
{dayjs(post.reTime).format("YYYY-MM-DD HH:mm")}
</>
) : (
"暂无预约"
)}
</Text>
</Space>
{/* First Row - Basic Info */} {/* First Row - Basic Info */}
<div className="flex flex-wrap items-center gap-1"> <div className="flex flex-wrap items-center gap-1">
{/* Author Info Badge */} {/* Author Info Badge */}
@ -82,7 +106,6 @@ export default function Header() {
{post?.meta?.tags?.length > 0 && ( {post?.meta?.tags?.length > 0 && (
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
{/* Tags Badges */} {/* Tags Badges */}
<LetterBadge type="state" value={post?.state} /> <LetterBadge type="state" value={post?.state} />
{(post?.terms || [])?.map((term, index) => { {(post?.terms || [])?.map((term, index) => {
return ( return (

View File

@ -4,6 +4,7 @@ import {
postDetailSelect, postDetailSelect,
PostDto, PostDto,
RolePerms, RolePerms,
StaffDto,
UserProfile, UserProfile,
} from "@nice/common"; } from "@nice/common";
import { useAuth } from "@web/src/providers/auth-provider"; import { useAuth } from "@web/src/providers/auth-provider";
@ -23,6 +24,7 @@ interface PostDetailContextType {
user?: UserProfile; user?: UserProfile;
setKeyCode?: React.Dispatch<React.SetStateAction<string>>; setKeyCode?: React.Dispatch<React.SetStateAction<string>>;
canSee?: boolean; canSee?: boolean;
staff?: StaffDto;
} }
interface PostFormProviderProps { interface PostFormProviderProps {
children: ReactNode; children: ReactNode;
@ -36,27 +38,53 @@ export function PostDetailProvider({
editId, editId,
}: PostFormProviderProps) { }: PostFormProviderProps) {
const { user, hasSomePermissions } = useAuth(); const { user, hasSomePermissions } = useAuth();
const postParams = PostParams.getInstance(); const postParams = PostParams.getInstance();
const queryParams = { const queryParams = {
where: { id: editId }, where: { id: editId },
select: postDetailSelect, select: {
...postDetailSelect,
meta: true, // 确保包含 meta 字段
createdAt: true,
updatedAt: true,
title: true,
reTime: true,
isPublic: true,
author: {
select: {
id: true,
showname: true,
phoneNumber: true
}
},
receivers: {
select: {
id: true,
showname: true,
meta: true
}
}
}
}; };
const [keyCode, setKeyCode] = useState<string>(""); const [keyCode, setKeyCode] = useState<string>("");
useEffect(() => { useEffect(() => {
if (editId) { if (editId) {
postParams.addDetailItem(queryParams); postParams.addDetailItem(queryParams);
} }
return () => { return () => {
if (editId) { if (editId) {
postParams.removeDetailItem(queryParams); postParams.removeDetailItem(queryParams);
} }
}; };
}, [editId]); }, [editId]);
const { data: post, isLoading }: { data: PostDto; isLoading: boolean } = ( const { data: post, isLoading }: { data: PostDto; isLoading: boolean } = (
api.post.findFirst as any api.post.findFirst as any
).useQuery(queryParams, { enabled: Boolean(editId) }); ).useQuery(queryParams, { enabled: Boolean(editId) });
const { data: staff } : { data: StaffDto}= api.staff.findFirst.useQuery(
{ where: { id: post?.authorId } },
{ enabled: !!post?.authorId }
);
const canSee = useMemo(() => { const canSee = useMemo(() => {
if (hasSomePermissions(RolePerms.READ_ANY_POST)) { if (hasSomePermissions(RolePerms.READ_ANY_POST)) {
return true; return true;
@ -83,6 +111,7 @@ export function PostDetailProvider({
isLoading, isLoading,
canSee, canSee,
setKeyCode, setKeyCode,
staff,
}}> }}>
{children} {children}
</PostDetailContext.Provider> </PostDetailContext.Provider>

View File

@ -1,4 +1,4 @@
import { Form, Input, Button, Checkbox, Select, Tabs } from "antd"; import { Form, Input, Button, Checkbox, Select, Tabs, DatePicker } from "antd";
import { useLetterEditor } from "../context/LetterEditorContext"; import { useLetterEditor } from "../context/LetterEditorContext";
import { SendOutlined } from "@ant-design/icons"; import { SendOutlined } from "@ant-design/icons";
import QuillEditor from "@web/src/components/common/editor/quill/QuillEditor"; import QuillEditor from "@web/src/components/common/editor/quill/QuillEditor";
@ -98,6 +98,25 @@ export function LetterBasicForm() {
<PublicOrNotSelector /> <PublicOrNotSelector />
</Form.Item> </Form.Item>
</div> </div>
<div className="flex gap-2">
{/* 添加预约时间字段 */}
<Form.Item
name={["reTime"]}
label="预约时间"
rules={[{ required: false, message: "请选择预约时间" }]}
>
<DatePicker className="w-full"
showTime
format="YYYY-MM-DD HH:mm"
placeholder="选择预约时间"
style={{ width: "200px" }}
disabledDate={(current) => {
// 禁用过去的日期
return current && current.valueOf() < Date.now();
}}
/>
</Form.Item>
</div>
{/* Tags Input */} {/* Tags Input */}
{/* <Form.Item name={["meta", "tags"]} className="mb-6"> {/* <Form.Item name={["meta", "tags"]} className="mb-6">
<Select <Select

View File

@ -213,6 +213,7 @@ model Post {
resources Resource[] // 附件列表 resources Resource[] // 附件列表
isPublic Boolean? @default(true) @map("is_public") isPublic Boolean? @default(true) @map("is_public")
meta Json? // 签名 和 IP 和 tags meta Json? // 签名 和 IP 和 tags
reTime DateTime? // 添加预约时间字段
// 复合索引 // 复合索引
@@index([type, domainId]) // 类型和域组合查询 @@index([type, domainId]) // 类型和域组合查询
@ -221,6 +222,7 @@ model Post {
// 时间相关索引 // 时间相关索引
@@index([createdAt]) // 按创建时间倒序索引 @@index([createdAt]) // 按创建时间倒序索引
@@index([updatedAt]) // 按更新时间倒序索引 @@index([updatedAt]) // 按更新时间倒序索引
@@index([reTime]) // 按预约时间倒序索引
} }
model Message { model Message {