From 6214ac308cab6093dc63b8660a88d7bb677bbd3f Mon Sep 17 00:00:00 2001 From: longdayi <13477510+longdayilongdayi@user.noreply.gitee.com> Date: Sat, 25 Jan 2025 02:27:40 +0800 Subject: [PATCH] 01250227 --- apps/server/src/models/base/base.service.ts | 3 +- apps/web/package.json | 1 + apps/web/src/app/main/letter/editor/page.tsx | 25 +- apps/web/src/app/main/letter/list/page.tsx | 11 +- .../src/app/main/letter/write/SendCard.tsx | 80 +++--- .../write/{header.tsx => WriteHeader.tsx} | 4 +- apps/web/src/app/main/letter/write/mock.ts | 31 --- apps/web/src/app/main/letter/write/page.tsx | 35 +-- apps/web/src/app/main/letter/write/types.ts | 12 - .../src/components/layout/main/useNavItem.ts | 2 +- .../post/editor/form/LetterBasicForm.tsx | 210 ++++++--------- .../post/editor/layout/LetterEditorLayout.tsx | 101 ------- .../models/post/list/LetterList.tsx | 121 ++++++++- .../components/models/staff/staff-select.tsx | 4 + .../components/models/term/term-select.tsx | 12 +- apps/web/src/index.css | 250 ------------------ apps/web/src/routes/index.tsx | 4 +- packages/utils/src/index.ts | 4 +- packages/utils/src/types.ts | 1 + pnpm-lock.yaml | 3 + 20 files changed, 295 insertions(+), 619 deletions(-) rename apps/web/src/app/main/letter/write/{header.tsx => WriteHeader.tsx} (93%) delete mode 100644 apps/web/src/app/main/letter/write/mock.ts delete mode 100644 apps/web/src/app/main/letter/write/types.ts delete mode 100644 apps/web/src/components/models/post/editor/layout/LetterEditorLayout.tsx create mode 100644 packages/utils/src/types.ts diff --git a/apps/server/src/models/base/base.service.ts b/apps/server/src/models/base/base.service.ts index 346c314..19fa918 100644 --- a/apps/server/src/models/base/base.service.ts +++ b/apps/server/src/models/base/base.service.ts @@ -451,7 +451,7 @@ export class BaseService< pageSize?: number; where?: WhereArgs; select?: SelectArgs; - }): Promise<{ items: R['findMany']; totalPages: number }> { + }): Promise<{ items: R['findMany']; totalPages: number, totalCount: number }> { const { page = 1, pageSize = 10, where, select } = args; try { @@ -470,6 +470,7 @@ export class BaseService< return { items, totalPages, + totalCount: total }; } catch (error) { this.handleError(error, 'read'); diff --git a/apps/web/package.json b/apps/web/package.json index efe8d7d..379260d 100755 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -34,6 +34,7 @@ "@nice/common": "workspace:^", "@nice/iconer": "workspace:^", "@nice/theme": "workspace:^", + "@nice/utils": "workspace:^", "@nice/ui": "workspace:^", "@tanstack/query-async-storage-persister": "^5.51.9", "@tanstack/react-query": "^5.51.21", diff --git a/apps/web/src/app/main/letter/editor/page.tsx b/apps/web/src/app/main/letter/editor/page.tsx index e2ff2f9..61bd7bc 100644 --- a/apps/web/src/app/main/letter/editor/page.tsx +++ b/apps/web/src/app/main/letter/editor/page.tsx @@ -1,16 +1,19 @@ -import { motion } from "framer-motion"; -import LetterEditorLayout from "@web/src/components/models/post/editor/layout/LetterEditorLayout"; +import { LetterFormProvider } from "@web/src/components/models/post/editor/context/LetterEditorContext"; +import { LetterBasicForm } from "@web/src/components/models/post/editor/form/LetterBasicForm"; +import WriteHeader from "../write/WriteHeader"; +import { useSearchParams } from "react-router-dom"; + +export default function LetterEditorPage() { + const [searchParams] = useSearchParams(); + const receiverId = searchParams.get("receiverId"); + const termId = searchParams.get("termId"); -export default function EditorLetterPage() { return ( -
- - - +
+ + + +
); } diff --git a/apps/web/src/app/main/letter/list/page.tsx b/apps/web/src/app/main/letter/list/page.tsx index e494780..6d9fe18 100644 --- a/apps/web/src/app/main/letter/list/page.tsx +++ b/apps/web/src/app/main/letter/list/page.tsx @@ -1,14 +1,19 @@ +import LetterList from "@web/src/components/models/post/list/LetterList"; import { Header } from "./Header"; export default function LetterListPage() { return ( // 添加 flex flex-col 使其成为弹性布局容器 -
+
{/* 添加 flex-grow 使内容区域自动填充剩余空间 */} - - + +
); } diff --git a/apps/web/src/app/main/letter/write/SendCard.tsx b/apps/web/src/app/main/letter/write/SendCard.tsx index 7483167..3c67a97 100644 --- a/apps/web/src/app/main/letter/write/SendCard.tsx +++ b/apps/web/src/app/main/letter/write/SendCard.tsx @@ -1,37 +1,42 @@ import { motion } from 'framer-motion'; -import { PaperAirplaneIcon } from '@heroicons/react/24/outline'; import { StaffDto } from "@nice/common"; -import { Button } from 'antd'; +import { Button, Tooltip, Badge } from 'antd'; +import { SendOutlined } from '@ant-design/icons'; +import { useNavigate } from 'react-router-dom'; export interface SendCardProps { staff: StaffDto; + termId?: string; } -export function SendCard({ staff }: SendCardProps) { +export function SendCard({ staff, termId }: SendCardProps) { + const navigate = useNavigate(); + + const handleSendLetter = () => { + navigate(`/editor?termId=${termId || ''}&receiverId=${staff.id}`); + }; return (
{/* Image Container */} -
+
{staff.meta?.photoUrl ? ( {staff.showname} ) : (
{/* Content Container */} -
+
-
-

- {staff.showname} -

- - {staff.meta?.rank || '未设置职级'} - +
+
+
+

+ {staff.showname} +

+ +
+

{staff.department?.name || '未设置部门'}

+
+ + + {staff.meta?.rank || '未设置职级'} + +
-

{staff.department?.name || '未设置部门'}

{/* Contact Information */} -
-

- +

+
+ - {staff.meta?.email || '未设置邮箱'} -

-

- + {staff.meta?.email || '未设置邮箱'} +

+
+ - {staff.phoneNumber || '未设置电话'} -

-

- + {staff.phoneNumber || '未设置电话'} +

+
+ - {staff.meta?.office || '未设置办公室'} -

+ {staff.meta?.office || '未设置办公室'} +
diff --git a/apps/web/src/app/main/letter/write/header.tsx b/apps/web/src/app/main/letter/write/WriteHeader.tsx similarity index 93% rename from apps/web/src/app/main/letter/write/header.tsx rename to apps/web/src/app/main/letter/write/WriteHeader.tsx index f072d2b..8d84c6b 100644 --- a/apps/web/src/app/main/letter/write/header.tsx +++ b/apps/web/src/app/main/letter/write/WriteHeader.tsx @@ -1,5 +1,5 @@ -export default function Header() { - return
+export default function WriteHeader() { + return
{/* 主标题 */}
diff --git a/apps/web/src/app/main/letter/write/mock.ts b/apps/web/src/app/main/letter/write/mock.ts deleted file mode 100644 index 1a7ff1d..0000000 --- a/apps/web/src/app/main/letter/write/mock.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Leader } from "./types"; - -export const leaders: Leader[] = [ - { - id: "1", - name: "John Mitchell", - rank: "General", - division: "Air Combat Command", - imageUrl: - "https://th.bing.com/th/id/OIP.ea0spF2OAgI4I1KzgZFtTgHaHX?rs=1&pid=ImgDetMain", - email: "j.mitchell@af.mil", - phone: "(555) 123-4567", - office: "Pentagon, Wing A-123", - }, - { - id: "2", - name: "Sarah Williams", - rank: "Colonel", - division: "Air Force Space Command", - imageUrl: - "https://th.bing.com/th/id/OIP.ea0spF2OAgI4I1KzgZFtTgHaHX?rs=1&pid=ImgDetMain", - }, - { - id: "3", - name: "Michael Roberts", - rank: "Major General", - division: "Air Mobility Command", - imageUrl: - "https://th.bing.com/th/id/OIP.ea0spF2OAgI4I1KzgZFtTgHaHX?rs=1&pid=ImgDetMain", - }, -]; diff --git a/apps/web/src/app/main/letter/write/page.tsx b/apps/web/src/app/main/letter/write/page.tsx index 1ed0640..f4d8c8a 100644 --- a/apps/web/src/app/main/letter/write/page.tsx +++ b/apps/web/src/app/main/letter/write/page.tsx @@ -1,14 +1,18 @@ -import { useState, useMemo, useCallback, useEffect } from 'react'; +import { useState, useCallback, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; -import Header from './header'; +import { useSearchParams } from 'react-router-dom'; + import { SendCard } from './SendCard'; -import { Spin, Empty, Input, Alert, message, Pagination } from 'antd'; +import { Spin, Empty, Input, Alert, Pagination } from 'antd'; import { api } from '@nice/client'; import DepartmentSelect from '@web/src/components/models/department/department-select'; import debounce from 'lodash/debounce'; import { SearchOutlined } from '@ant-design/icons'; +import WriteHeader from './WriteHeader'; export default function WriteLetterPage() { + const [searchParams] = useSearchParams(); + const termId = searchParams.get('termId'); const [searchQuery, setSearchQuery] = useState(''); const [selectedDept, setSelectedDept] = useState(); const [currentPage, setCurrentPage] = useState(1); @@ -30,19 +34,19 @@ export default function WriteLetterPage() { }] } }); - useEffect(() => { - console.log(selectedDept) - console.log(data) - console.log(searchQuery) - }, [selectedDept, data, searchQuery]) - // Reset to first page when search query or department changes - useCallback(() => { + + const resetPage = useCallback(() => { setCurrentPage(1); - }, [searchQuery, selectedDept]); + }, []); + + // Reset page when search or department changes + useEffect(() => { + resetPage(); + }, [searchQuery, selectedDept, resetPage]); return ( -
-
+
+
{/* Search and Filter Section */} @@ -86,10 +90,11 @@ export default function WriteLetterPage() { animate={{ opacity: 1 }} exit={{ opacity: 0 }} > - {data?.items.map((item) => ( + {data?.items.map((item: any) => ( ))} diff --git a/apps/web/src/app/main/letter/write/types.ts b/apps/web/src/app/main/letter/write/types.ts deleted file mode 100644 index 4d0af62..0000000 --- a/apps/web/src/app/main/letter/write/types.ts +++ /dev/null @@ -1,12 +0,0 @@ -export interface Leader { - id: string; - name: string; - rank: string; - division: string; - imageUrl: string; - email: string; // Added - phone: string; // Added - office: string; // Added -} - - diff --git a/apps/web/src/components/layout/main/useNavItem.ts b/apps/web/src/components/layout/main/useNavItem.ts index d90d947..665c034 100644 --- a/apps/web/src/components/layout/main/useNavItem.ts +++ b/apps/web/src/components/layout/main/useNavItem.ts @@ -23,7 +23,7 @@ export function useNavItem() { // 构建分类导航项 const categoryItems = data.map(term => ({ - to: `/write-letter?category=${term.id}`, + to: `/write-letter?termId=${term.id}`, label: term.name })); diff --git a/apps/web/src/components/models/post/editor/form/LetterBasicForm.tsx b/apps/web/src/components/models/post/editor/form/LetterBasicForm.tsx index f5327b7..dadb265 100644 --- a/apps/web/src/components/models/post/editor/form/LetterBasicForm.tsx +++ b/apps/web/src/components/models/post/editor/form/LetterBasicForm.tsx @@ -1,164 +1,106 @@ import { Form, Input, Button, Checkbox, Select } from "antd"; -import { useState } from "react"; import { useLetterEditor } from "../context/LetterEditorContext"; -import { api } from "@nice/client"; -import { - UserOutlined, - FolderOutlined, - TagOutlined, - FileTextOutlined, -} from "@ant-design/icons"; - +import { SendOutlined } from "@ant-design/icons"; import QuillEditor from "@web/src/components/common/editor/quill/QuillEditor"; -import { PostBadge } from "../../detail/badge/PostBadge"; +import StaffSelect from "../../../staff/staff-select"; +import TermSelect from "../../../term/term-select"; export function LetterBasicForm() { const { onSubmit, receiverId, termId, form } = useLetterEditor(); - const { data: receiver } = api.staff.findFirst.useQuery( - { - where: { - id: receiverId, - }, - }, - { - enabled: !!receiverId, - } - ); - const { data: term } = api.term.findFirst.useQuery( - { - where: { id: termId }, - }, - { enabled: !!termId } - ); - const handleFinish = async (values: any) => { await onSubmit(values); }; - return ( -
+
- {/* 收件人和板块信息行 */} -
-
- -
收件人:{receiver?.showname}
-
- + initialValues={{ meta: { tags: [] }, receiverId, termId, isPublic: true }} + > +
+ + + + + +
+ + - - - 标题 - - (必选) + + /> + + + {/* Tags Input */} + + - -
+ )} + /> + + + {/* Content Editor */} + +
+ form.setFieldValue("content", content)} - {/* 标签输入 */} -
- - - 标签 - - } - name={["meta", "tags"]} - labelCol={{ span: 24 }} - wrapperCol={{ span: 24 }}> - handleSearch(e.target.value)} + prefix={} + /> +
+
+ + {/* Content Area */} +
+ {isLoading ? ( +
+ {[...Array(6)].map((_, index) => ( +
+ ))} +
+ ) : data?.items.length ? ( + <> +
+ {data.items.map((letter: any) => ( + + ))} +
+
+ +
+ + ) : ( +
+ + {searchText ? "未找到相关信件" : "暂无信件"} + + } + + className="flex flex-col items-center" + /> +
+ )} +
+ + +
+ ); +} diff --git a/apps/web/src/components/models/staff/staff-select.tsx b/apps/web/src/components/models/staff/staff-select.tsx index d6721b1..5fa44d6 100644 --- a/apps/web/src/components/models/staff/staff-select.tsx +++ b/apps/web/src/components/models/staff/staff-select.tsx @@ -3,6 +3,7 @@ import { Button, Select, Spin } from "antd"; import type { SelectProps } from "antd"; import { api } from "@nice/client"; import React from "react"; +import { SizeType } from "antd/es/config-provider/SizeContext"; interface StaffSelectProps { value?: string | string[]; onChange?: (value: string | string[]) => void; @@ -10,6 +11,7 @@ interface StaffSelectProps { multiple?: boolean; domainId?: string; placeholder?: string; + size?: SizeType } export default function StaffSelect({ @@ -19,6 +21,7 @@ export default function StaffSelect({ style, multiple, domainId, + size }: StaffSelectProps) { const [keyword, setQuery] = useState(""); @@ -67,6 +70,7 @@ export default function StaffSelect({ return ( <>