From 66f107058e5aa93221abe42f36479e421b689415 Mon Sep 17 00:00:00 2001 From: fanhongcai Date: Sun, 23 Aug 2026 08:55:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=8F=8D=E5=9B=AC=EE=95=BD=E9=8F=8D?= =?UTF-8?q?=E5=BF=95=E5=A2=97=E9=8F=88=EE=84=80=E5=BD=BF=20+=20=E6=90=B4?= =?UTF-8?q?=E6=97=82=E6=95=A4=E7=94=AF=E5=82=9A=E6=BA=80=E6=B6=93=E5=A9=83?= =?UTF-8?q?=E7=81=A6=E9=8F=83=E3=83=A5=E5=B7=BB=E6=90=B4=E6=97=82=E6=95=A4?= =?UTF-8?q?=E6=B6=93=E5=BA=A1=E5=9E=8E=E7=BC=81=E5=8B=AC=E5=A7=8C=E9=8D=99?= =?UTF-8?q?=3F+=20=E9=8F=83=E3=83=A7=E2=96=BC=E9=8D=90=E6=BB=83=E5=B7=BB/?= =?UTF-8?q?=E7=90=9B=E3=84=A5=E5=B4=9F=E5=A6=AF=EE=81=86=E5=A2=97=E6=B5=BC?= =?UTF-8?q?=E6=A8=BA=E5=AF=B2=20+=20=E6=B6=93=EE=81=83=E6=B1=89=E7=92=A7?= =?UTF-8?q?=E5=8B=AC=E6=9E=A1=E5=AF=AE=E5=9C=AD=E7=8D=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 7 ++ client/electron/main.cjs | 2 +- client/package-lock.json | 7 ++ client/package.json | 1 + client/src/App.tsx | 5 +- client/src/api/auth.ts | 5 + client/src/components/ProfileModal.tsx | 154 +++++++++++++++++++++++++ client/src/constants/user.ts | 19 +++ client/src/layout/KeepAliveOutlet.tsx | 4 +- client/src/layout/MainLayout.tsx | 63 +++++++++- client/src/main.tsx | 3 + client/src/pages/Apps.tsx | 135 +++++++++++++++++++--- client/src/pages/Forms.tsx | 4 +- client/src/pages/Schedule.tsx | 54 ++++++++- client/src/store/auth.ts | 10 +- client/src/types.ts | 4 + client/src/utils/lunar.ts | 47 ++++++++ client/src/vite-env.d.ts | 3 + client/vite.config.ts | 7 ++ server/src/auth/auth.controller.ts | 11 +- server/src/auth/auth.service.ts | 14 +++ 项目要求.md | 15 +++ 22 files changed, 545 insertions(+), 29 deletions(-) create mode 100644 client/src/components/ProfileModal.tsx create mode 100644 client/src/constants/user.ts create mode 100644 client/src/utils/lunar.ts diff --git a/.gitignore b/.gitignore index 3123a28..1f93c9b 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,10 @@ client/release/ # local tooling data .codebuddy/ .playwright-cli/ + +# temp debug artifacts (screenshots / UI dumps) +/apps-calendar-lite.png +/apps-group-collapse.png +/schedule-lunar.png +/forms.yaml +/forms2.yaml diff --git a/client/electron/main.cjs b/client/electron/main.cjs index c61abd2..2a023e4 100644 --- a/client/electron/main.cjs +++ b/client/electron/main.cjs @@ -9,7 +9,7 @@ function createWindow() { height: 800, minWidth: 980, minHeight: 640, - title: 'ChatOA', + title: `ChatOA v${app.getVersion()}`, autoHideMenuBar: true, webPreferences: { preload: path.join(__dirname, 'preload.cjs'), diff --git a/client/package-lock.json b/client/package-lock.json index 40c3226..b83a789 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,6 +12,7 @@ "antd": "^5.22.0", "axios": "^1.7.9", "dayjs": "^1.11.13", + "lunar-typescript": "^1.8.6", "quill": "^1.3.7", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -4956,6 +4957,12 @@ "yallist": "^3.0.2" } }, + "node_modules/lunar-typescript": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/lunar-typescript/-/lunar-typescript-1.8.6.tgz", + "integrity": "sha512-5Eo4T/cnuXfrgO4k5LCpOGHIUOuz5hCF/IfNv0T29WY2shR36Hiz+ecN9WjnUuxUKhql9gbOkPaQoqLFKtPRNA==", + "license": "MIT" + }, "node_modules/matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", diff --git a/client/package.json b/client/package.json index 6850704..d089819 100644 --- a/client/package.json +++ b/client/package.json @@ -55,6 +55,7 @@ "antd": "^5.22.0", "axios": "^1.7.9", "dayjs": "^1.11.13", + "lunar-typescript": "^1.8.6", "quill": "^1.3.7", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/client/src/App.tsx b/client/src/App.tsx index 2f37be8..52aff88 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -58,7 +58,10 @@ export default function App() { } /> } /> } /> - } /> + {/* 注意:/ai-chat 必须与 /ai-chat/:assistantId 都渲染 KeepAliveOutlet(相同类型), + 若用 会把 Outlet 位置的 KeepAliveOutlet 卸载,导致切走再切回时 + 所有 keep-alive 页面状态(如应用页打开的运行页签)被重置 */} + } /> } /> } /> diff --git a/client/src/api/auth.ts b/client/src/api/auth.ts index 94071ec..ebd91a0 100644 --- a/client/src/api/auth.ts +++ b/client/src/api/auth.ts @@ -22,3 +22,8 @@ export async function fetchMe() { const { data } = await client.get('/auth/me'); return data; } + +export async function updateMe(patch: { signature?: string; status?: string }) { + const { data } = await client.patch('/auth/me', patch); + return data; +} diff --git a/client/src/components/ProfileModal.tsx b/client/src/components/ProfileModal.tsx new file mode 100644 index 0000000..040d41d --- /dev/null +++ b/client/src/components/ProfileModal.tsx @@ -0,0 +1,154 @@ +import { useEffect, useState } from 'react'; +import { + Avatar, + Button, + Descriptions, + Input, + Modal, + Select, + Tag, + message, +} from 'antd'; +import { useAuth } from '../store/auth'; +import { USER_STATUS, userStatusMeta } from '../constants/user'; + +interface Props { + open: boolean; + onClose: () => void; +} + +/** 个人信息弹窗:展示资料 + 编辑签名 + 设置状态 */ +export default function ProfileModal({ open, onClose }: Props) { + const user = useAuth((s) => s.user); + const updateProfile = useAuth((s) => s.updateProfile); + const [signature, setSignature] = useState(''); + const [status, setStatus] = useState(undefined); + const [saving, setSaving] = useState(false); + + // 每次打开时同步当前用户数据 + useEffect(() => { + if (open) { + setSignature(user?.signature ?? ''); + setStatus(user?.status); + } + }, [open, user]); + + const save = async () => { + setSaving(true); + try { + await updateProfile({ + signature: signature.trim(), + status: status && status !== user?.status ? status : undefined, + }); + message.success('已保存'); + onClose(); + } catch { + message.error('保存失败,请重试'); + } finally { + setSaving(false); + } + }; + + const statusMeta = userStatusMeta(user?.status); + + return ( + + 取消 + , + , + ]} + > +
+ + {user?.nickname?.[0] ?? 'U'} + +
+
+ {user?.nickname} + {statusMeta && ( + + {statusMeta.label} + + )} +
+
+ @{user?.username} +
+
+
+ + + +
+
+ 个性签名 +
+ setSignature(e.target.value)} + /> +
+ +
+
+ 我的状态 +
+