This commit is contained in:
ditiqi 2025-01-26 10:49:19 +08:00
parent f121322bbd
commit 9039d1832a
4 changed files with 101 additions and 75 deletions

View File

@ -1,4 +1,4 @@
import { VisitType } from 'packages/common/dist'; import { VisitType } from '@nice/common';
export enum QueueJobType { export enum QueueJobType {
UPDATE_STATS = 'update_stats', UPDATE_STATS = 'update_stats',
FILE_PROCESS = 'file_process', FILE_PROCESS = 'file_process',

View File

@ -120,7 +120,7 @@ export function UserMenu() {
</div> </div>
{/* 用户信息,显示在 Avatar 右侧 */} {/* 用户信息,显示在 Avatar 右侧 */}
<div className="flex flex-col space-y-0.5 ml-3"> <div className="flex flex-col space-y-0.5 ml-3 items-start">
<span className="text-sm font-semibold text-white"> <span className="text-sm font-semibold text-white">
{user?.showname || user?.username} {user?.showname || user?.username}
</span> </span>

View File

@ -7,28 +7,24 @@ import { UserOutlined } from "@ant-design/icons";
import { UserMenu } from "../element/usermenu"; import { UserMenu } from "../element/usermenu";
import SineWavesCanvas from "../../animation/sine-wave"; import SineWavesCanvas from "../../animation/sine-wave";
interface HeaderProps { interface HeaderProps {
onSearch?: (query: string) => void; onSearch?: (query: string) => void;
} }
export const Header = memo(function Header({ onSearch }: HeaderProps) { export const Header = memo(function Header({ onSearch }: HeaderProps) {
const { isAuthenticated } = useAuth() const { isAuthenticated } = useAuth();
return ( return (
<header className="sticky top-0 z-50 bg-gradient-to-br from-primary-500 to-primary-800 text-white shadow-lg"> <header className="sticky top-0 z-50 bg-gradient-to-br from-primary-500 to-primary-800 text-white shadow-lg">
<div className="container mx-auto px-4"> <div className="container mx-auto px-4">
<div className="py-3"> <div className="py-3">
<div className="flex items-center justify-between gap-4"> <div className="flex items-center justify-between gap-4">
<div className=" text-xl font-bold"> <div className=" text-xl font-bold"></div>
<div className="flex-grow max-w-2xl">
<SearchBar onSearch={onSearch} />
</div> </div>
<div className="flex-grow max-w-2xl"> <div className="flex items-center gap-6">
<SearchBar onSearch={onSearch} /> {!isAuthenticated ? (
</div> <Link
<div className="flex items-center gap-6"> to="/auth"
className="group flex items-center gap-2 rounded-lg
{
!isAuthenticated ? <Link
to="/auth"
className="group flex items-center gap-2 rounded-lg
bg-[#00539B]/90 px-5 py-2.5 font-medium bg-[#00539B]/90 px-5 py-2.5 font-medium
shadow-lg transition-all duration-300 shadow-lg transition-all duration-300
hover:-translate-y-0.5 hover:bg-[#0063B8] hover:-translate-y-0.5 hover:bg-[#0063B8]
@ -36,21 +32,21 @@ hover:shadow-xl hover:shadow-[#00539B]/30
focus:outline-none focus:ring-2 focus:outline-none focus:ring-2
focus:ring-[#8EADD4] focus:ring-offset-2 focus:ring-[#8EADD4] focus:ring-offset-2
focus:ring-offset-[#13294B]" focus:ring-offset-[#13294B]"
aria-label="Login" aria-label="Login">
> <UserOutlined
<UserOutlined className="h-5 w-5 transition-transform className="h-5 w-5 transition-transform
group-hover:scale-110 group-hover:rotate-12"></UserOutlined> group-hover:scale-110 group-hover:rotate-12"></UserOutlined>
<span></span> <span></span>
</Link> : <UserMenu /> </Link>
) : (
<UserMenu />
} )}
</div> </div>
</div> </div>
</div> </div>
<Navigation /> <Navigation />
</div> </div>
</header> </header>
); );
}); });

View File

@ -6,6 +6,7 @@ import { api } from "@nice/client";
import { StaffEditorContext } from "./staff-editor"; import { StaffEditorContext } from "./staff-editor";
import { useAuth } from "@web/src/providers/auth-provider"; import { useAuth } from "@web/src/providers/auth-provider";
import AvatarUploader from "../../common/uploader/AvatarUploader"; import AvatarUploader from "../../common/uploader/AvatarUploader";
import { StaffDto } from "@nice/common";
export default function StaffForm() { export default function StaffForm() {
const { create, update } = useStaff(); // Ensure you have these methods in your hooks const { create, update } = useStaff(); // Ensure you have these methods in your hooks
const { const {
@ -18,7 +19,13 @@ export default function StaffForm() {
canManageAnyStaff, canManageAnyStaff,
setEditId, setEditId,
} = useContext(StaffEditorContext); } = useContext(StaffEditorContext);
const { data, isLoading } = api.staff.findFirst.useQuery( const {
data,
isLoading,
}: {
data: StaffDto;
isLoading: boolean;
} = api.staff.findFirst.useQuery(
{ where: { id: editId } }, { where: { id: editId } },
{ enabled: !!editId } { enabled: !!editId }
); );
@ -33,6 +40,7 @@ export default function StaffForm() {
phoneNumber, phoneNumber,
officerId, officerId,
enabled, enabled,
photoUrl,
} = values; } = values;
setFormLoading(true); setFormLoading(true);
try { try {
@ -48,6 +56,9 @@ export default function StaffForm() {
phoneNumber, phoneNumber,
officerId, officerId,
enabled, enabled,
meta: {
photoUrl,
},
}, },
}); });
} else { } else {
@ -60,6 +71,9 @@ export default function StaffForm() {
password, password,
officerId, officerId,
phoneNumber, phoneNumber,
meta: {
photoUrl,
},
}, },
}); });
form.resetFields(); form.resetFields();
@ -85,6 +99,7 @@ export default function StaffForm() {
form.setFieldValue("officerId", data.officerId); form.setFieldValue("officerId", data.officerId);
form.setFieldValue("phoneNumber", data.phoneNumber); form.setFieldValue("phoneNumber", data.phoneNumber);
form.setFieldValue("enabled", data.enabled); form.setFieldValue("enabled", data.enabled);
form.setFieldValue("photoUrl", data?.meta?.photoUrl);
} }
}, [data]); }, [data]);
useEffect(() => { useEffect(() => {
@ -107,53 +122,68 @@ export default function StaffForm() {
requiredMark="optional" requiredMark="optional"
autoComplete="off" autoComplete="off"
onFinish={handleFinish}> onFinish={handleFinish}>
<Form.Item <div className=" flex items-center gap-4 mb-2">
name={"meta.photoUrl"} <div>
label="头像" <Form.Item
rules={[{ required: true }]}> name={"photoUrl"}
<AvatarUploader label="头像"
style={{ noStyle
width: "150px", rules={[{ required: true }]}>
height: "200px", <AvatarUploader
}}></AvatarUploader> style={{
</Form.Item> width: "100px",
height: "120px",
}}></AvatarUploader>
</Form.Item>
</div>
<div className="grid grid-cols-1 gap-2 flex-1">
<Form.Item
noStyle
rules={[{ required: true }]}
name={"username"}
label="帐号">
<Input
placeholder="请输入用户名"
allowClear
autoComplete="new-username" // 使用非标准的自动完成值
spellCheck={false}
/>
</Form.Item>
<Form.Item
noStyle
rules={[{ required: true }]}
name={"showname"}
label="姓名">
<Input
placeholder="请输入姓名"
allowClear
autoComplete="new-name" // 使用非标准的自动完成值
spellCheck={false}
/>
</Form.Item>
<Form.Item
noStyle
name={"deptId"}
label="所属单位"
rules={[{ required: true }]}>
<DepartmentSelect
rootId={isRoot ? undefined : domainId}
/>
</Form.Item>
</div>
</div>
{canManageAnyStaff && ( {canManageAnyStaff && (
<Form.Item <Form.Item
name={"domainId"} name={"domainId"}
label="所属域" label="所属域"
rules={[{ required: true }]}> rules={[{ required: true }]}>
<DepartmentSelect <DepartmentSelect
placeholder="选择域"
rootId={isRoot ? undefined : domainId} rootId={isRoot ? undefined : domainId}
domain={true} domain={true}
/> />
</Form.Item> </Form.Item>
)} )}
<Form.Item
name={"deptId"}
label="所属单位"
rules={[{ required: true }]}>
<DepartmentSelect rootId={isRoot ? undefined : domainId} />
</Form.Item>
<Form.Item
rules={[{ required: true }]}
name={"username"}
label="帐号">
<Input
allowClear
autoComplete="new-username" // 使用非标准的自动完成值
spellCheck={false}
/>
</Form.Item>
<Form.Item
rules={[{ required: true }]}
name={"showname"}
label="姓名">
<Input
allowClear
autoComplete="new-name" // 使用非标准的自动完成值
spellCheck={false}
/>
</Form.Item>
<Form.Item <Form.Item
rules={[ rules={[
{ {