add
This commit is contained in:
parent
8772be5e7a
commit
8293f6389d
|
@ -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);
|
||||||
|
|
|
@ -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" />,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue