import { useEffect, useMemo, useState } from 'react'; import { Edit3, KeyRound, Plus, Search, Trash2, Users } from 'lucide-react'; import { clientApi, type ManagedUser, type UserPayload } from '@/api/adminApi'; import { formatDateTime } from '@/utils/dateTime'; import { readSession } from '@/api/session'; import { Button, Input, Modal, Select, Table, Tag, type TableColumn } from '@/components/ui'; import './ClientUsersPage.css'; type UserForm = { displayName: string; username: string; email: string; phone: string; status: string; password: string; }; type ConfirmAction = { type: 'status' | 'delete'; user: ManagedUser; }; const emptyForm: UserForm = { displayName: '', username: '', email: '', phone: '', status: 'active', password: '', }; function toForm(user?: ManagedUser): UserForm { return user ? { displayName: user.displayName, username: user.username, email: user.email ?? '', phone: user.phone ?? '', status: user.status, password: '', } : emptyForm; } export function ClientUsersPage() { const session = readSession('client'); const tenantId = session?.user.tenantId ?? undefined; const [users, setUsers] = useState([]); const [keyword, setKeyword] = useState(''); const [editingUser, setEditingUser] = useState(null); const [creating, setCreating] = useState(false); const [form, setForm] = useState(emptyForm); const [passwordUser, setPasswordUser] = useState(null); const [newPassword, setNewPassword] = useState(''); const [confirmAction, setConfirmAction] = useState(null); const [error, setError] = useState(''); const [saving, setSaving] = useState(false); async function load() { if (!tenantId) return; setUsers(await clientApi.listUsers(tenantId)); } useEffect(() => { void load().catch((err) => setError(err instanceof Error ? err.message : '加载用户失败')); }, [tenantId]); const filteredUsers = useMemo(() => { const value = keyword.trim().toLowerCase(); return users.filter((item) => { const target = `${item.displayName} ${item.email ?? ''} ${item.phone ?? ''}`.toLowerCase(); return !value || target.includes(value); }); }, [keyword, users]); function openEditor(user?: ManagedUser) { setForm(toForm(user)); setEditingUser(user ?? null); setCreating(!user); } function updateField(key: Key, value: UserForm[Key]) { setForm((current) => ({ ...current, [key]: value })); } async function saveUser() { if (!form.displayName.trim() || (!form.email.trim() && !form.phone.trim()) || (creating && form.password.length < 6)) { setError('请填写姓名、邮箱或手机号;新增用户密码至少 6 位'); return; } setSaving(true); const body: UserPayload = { displayName: form.displayName, username: form.username || form.email || form.phone, email: form.email, phone: form.phone, status: form.status, roleCode: 'enterprise_admin', operatorId: session?.user.id, }; try { if (creating) { await clientApi.createUser({ ...body, password: form.password }, tenantId); } else if (editingUser) { await clientApi.updateUser(editingUser.id, body, tenantId); } setCreating(false); setEditingUser(null); await load(); } catch (failure) { setError(failure instanceof Error ? failure.message : '用户保存失败'); } finally { setSaving(false); } } async function runConfirm() { if (!confirmAction) return; if (confirmAction.type === 'delete') { await clientApi.deleteUser(confirmAction.user.id, session?.user.id, tenantId); } else { await clientApi.changeUserStatus(confirmAction.user.id, confirmAction.user.status === 'active' ? 'disabled' : 'active', session?.user.id, tenantId); } setConfirmAction(null); await load(); } async function savePassword() { if (!passwordUser) return; await clientApi.changeUserPassword(passwordUser.id, newPassword, session?.user.id, tenantId); setPasswordUser(null); setNewPassword(''); } const columns = useMemo>>(() => [ { key: 'name', title: '用户名', width: '140px', render: (record) => {record.displayName} }, { key: 'email', title: '邮箱', render: (record) => {record.email ?? '-'} }, { key: 'phone', title: '手机号', width: '160px', render: (record) => {record.phone ?? '-'} }, { key: 'role', title: '角色', width: '130px', render: () => 企业管理员 }, { key: 'status', title: '状态', width: '120px', render: (record) => {record.status === 'active' ? '正常' : '禁用'} }, { key: 'lastLoginAt', title: '最后登录时间', width: '190px', render: (record) => {formatDateTime(record.lastLoginAt)} }, { key: 'actions', title: '操作', width: '290px', render: (record) => (
), }, ], []); return (

用户管理

setKeyword(event.target.value)} placeholder="搜索用户名、邮箱或手机号" prefix={} value={keyword} />
{error ?
{error}
: null}
{(creating || editingUser) ? ( } onClose={() => { setCreating(false); setEditingUser(null); }} open size="xl" title={creating ? '添加用户' : '编辑用户'} >
updateField('displayName', event.target.value)} placeholder="请输入用户名" value={form.displayName} /> updateField('email', event.target.value)} placeholder="请输入邮箱" value={form.email} /> updateField('phone', event.target.value)} placeholder="请输入手机号" value={form.phone} /> updateField('username', event.target.value)} value={form.username} /> {creating ? updateField('password', event.target.value)} type="password" value={form.password} /> : null} setNewPassword(event.target.value)} type="password" value={newPassword} />
) : null} {confirmAction ? ( } onClose={() => setConfirmAction(null)} open title={confirmAction.type === 'delete' ? '删除用户' : '变更用户状态'}>

{confirmAction.type === 'delete' ? `确认删除用户 ${confirmAction.user.displayName}?` : `确认${confirmAction.user.status === 'active' ? '禁用' : '启用'}用户 ${confirmAction.user.displayName}?`}

) : null} ); }