feat: 增加DEFAULT_USER_PASSWORD,作为创建用户时的默认密码,添加p-limit库,添加DB_PARALLEL_LIMIT = 32环境变量作为“数据库批次操作默认并发数” 限制只有超级管理员才能创建超级管理员用户 删除用户时可以级联删除SelectionLog 添加zustand全局状态管理 一对多的院系管理功能 ,支持增删改查院系管理员信息、用户可以在header中切换管理的院系
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
'use client'
|
||||
|
||||
import React, { useState } from 'react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { z } from 'zod'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { trpc } from '@/lib/trpc'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Dialog, DialogTrigger } from '@/components/ui/dialog'
|
||||
import { Plus } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import { FormDialog, FormActionBar, FormGridContent, FormCancelAction, FormSubmitAction, type FormFieldConfig } from '@/components/common/form-dialog'
|
||||
import {
|
||||
AdvancedSelect,
|
||||
SelectPopover,
|
||||
SelectTrigger,
|
||||
SelectContent,
|
||||
SelectInput,
|
||||
SelectItemList,
|
||||
SelectedName
|
||||
} from '@/components/common/advanced-select'
|
||||
import { useSmartSelectOptions } from '@/hooks/use-smart-select-options'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
|
||||
// 创建院系管理员的 schema
|
||||
const createDeptAdminSchema = z.object({
|
||||
uid: z.string().min(1, '用户ID不能为空'),
|
||||
deptCode: z.string().min(1, '院系代码不能为空'),
|
||||
adminEmail: z.string().email('邮箱格式不正确').optional().or(z.literal('')),
|
||||
adminLinePhone: z.string().optional(),
|
||||
adminMobilePhone: z.string().optional(),
|
||||
note: z.string().optional(),
|
||||
})
|
||||
|
||||
type CreateDeptAdminInput = z.input<typeof createDeptAdminSchema>
|
||||
|
||||
const createDeptAdminDefaultValues: CreateDeptAdminInput = {
|
||||
uid: '',
|
||||
deptCode: '',
|
||||
adminEmail: '',
|
||||
adminLinePhone: '',
|
||||
adminMobilePhone: '',
|
||||
note: '',
|
||||
}
|
||||
|
||||
interface DeptAdminCreateDialogProps {
|
||||
onDeptAdminCreated: () => void
|
||||
}
|
||||
|
||||
export function DeptAdminCreateDialog({ onDeptAdminCreated }: DeptAdminCreateDialogProps) {
|
||||
// 表单 dialog 控制
|
||||
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false)
|
||||
|
||||
// react-hook-form 管理创建表单
|
||||
const createForm = useForm<CreateDeptAdminInput>({
|
||||
resolver: zodResolver(createDeptAdminSchema),
|
||||
defaultValues: createDeptAdminDefaultValues,
|
||||
})
|
||||
|
||||
// 获取院系列表
|
||||
const { data: depts } = trpc.common.getDepts.useQuery()
|
||||
|
||||
const deptOptions = depts?.map(dept => ({ id: dept.code, name: dept.fullName, shortName: dept.name })) || []
|
||||
const { sortedOptions: sortedDeptOptions, logSelection: logDeptSelection } = useSmartSelectOptions({
|
||||
options: deptOptions,
|
||||
context: 'deptAdmin.create.dept',
|
||||
scope: 'personal',
|
||||
})
|
||||
|
||||
// 创建院系管理员 mutation
|
||||
const createDeptAdminMutation = trpc.deptAdmin.create.useMutation({
|
||||
onSuccess: () => {
|
||||
setIsCreateDialogOpen(false)
|
||||
createForm.reset(createDeptAdminDefaultValues)
|
||||
toast.success('院系管理员创建成功')
|
||||
onDeptAdminCreated()
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(error.message || '创建院系管理员失败')
|
||||
},
|
||||
})
|
||||
|
||||
// 定义字段配置
|
||||
const formFields: FormFieldConfig[] = React.useMemo(() => [
|
||||
{
|
||||
name: 'uid',
|
||||
label: '用户ID',
|
||||
required: true,
|
||||
render: ({ field }) => (
|
||||
<Input {...field} placeholder="请输入用户ID(职工号)" />
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'deptCode',
|
||||
label: '院系',
|
||||
required: true,
|
||||
render: ({ field }) => (
|
||||
<AdvancedSelect
|
||||
{...field}
|
||||
options={sortedDeptOptions}
|
||||
onChange={(value) => { logDeptSelection(value); field.onChange(value) }}
|
||||
filterFunction={(option, searchValue) => {
|
||||
const search = searchValue.toLowerCase()
|
||||
return option.id.includes(search) || option.name.toLowerCase().includes(search) ||
|
||||
(option.shortName && option.shortName.toLowerCase().includes(search))
|
||||
}}
|
||||
>
|
||||
<SelectPopover>
|
||||
<SelectTrigger placeholder="请选择院系">
|
||||
<SelectedName />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectInput placeholder="搜索院系名称/代码" />
|
||||
<SelectItemList />
|
||||
</SelectContent>
|
||||
</SelectPopover>
|
||||
</AdvancedSelect>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'adminEmail',
|
||||
label: '邮箱',
|
||||
render: ({ field }) => (
|
||||
<Input {...field} type="email" placeholder="请输入邮箱" />
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'adminLinePhone',
|
||||
label: '座机',
|
||||
render: ({ field }) => (
|
||||
<Input {...field} placeholder="请输入座机号码" />
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'adminMobilePhone',
|
||||
label: '手机',
|
||||
render: ({ field }) => (
|
||||
<Input {...field} placeholder="请输入手机号码" />
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'note',
|
||||
label: '备注',
|
||||
render: ({ field }) => (
|
||||
<Textarea {...field} placeholder="请输入备注信息" className="min-h-[80px]" />
|
||||
),
|
||||
},
|
||||
], [sortedDeptOptions, logDeptSelection])
|
||||
|
||||
const handleSubmit = async (data: CreateDeptAdminInput) => {
|
||||
createDeptAdminMutation.mutate(data)
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
setIsCreateDialogOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dialog open={isCreateDialogOpen} onOpenChange={setIsCreateDialogOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button className="flex items-center gap-2">
|
||||
<Plus className="h-4 w-4" />
|
||||
创建院系管理员
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
</Dialog>
|
||||
|
||||
<FormDialog
|
||||
isOpen={isCreateDialogOpen}
|
||||
title="创建院系管理员"
|
||||
description="请填写院系管理员信息"
|
||||
form={createForm}
|
||||
fields={formFields}
|
||||
onClose={handleClose}
|
||||
>
|
||||
<FormGridContent />
|
||||
<FormActionBar>
|
||||
<FormCancelAction />
|
||||
<FormSubmitAction onSubmit={handleSubmit} isSubmitting={createDeptAdminMutation.isPending}>创建</FormSubmitAction>
|
||||
</FormActionBar>
|
||||
</FormDialog>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user