修改客户认领和客户管理页面的查询和操作功能并且包含按钮权限 & 产品管理添加启动/禁用和最低价格字段
This commit is contained in:
@@ -3,10 +3,10 @@ import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { format } from "date-fns"
|
||||
import { Suspense, useCallback, useState } from "react"
|
||||
import { Controller, useForm } from "react-hook-form"
|
||||
import { toast } from "sonner"
|
||||
import { z } from "zod"
|
||||
import { bindAdmin, getPageUser } from "@/actions/user"
|
||||
import { DataTable } from "@/components/data-table"
|
||||
import { bindAdmin, getPageUserPage } from "@/actions/user"
|
||||
import { Auth } from "@/components/auth"
|
||||
import { DataTable, useDataTable } from "@/components/data-table"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import {
|
||||
@@ -16,82 +16,47 @@ import {
|
||||
FieldLabel,
|
||||
} from "@/components/ui/field"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { useFetch } from "@/hooks/data"
|
||||
import { ScopeUserWriteBind } from "@/lib/scopes"
|
||||
import type { User } from "@/models/user"
|
||||
|
||||
interface UserQueryParams {
|
||||
account?: string
|
||||
name?: string
|
||||
interface FilterValues {
|
||||
phone?: string
|
||||
}
|
||||
|
||||
const filterSchema = z.object({
|
||||
account: z.string().optional(),
|
||||
name: z.string().optional(),
|
||||
phone: z.string().optional(),
|
||||
})
|
||||
|
||||
type FormValues = z.infer<typeof filterSchema>
|
||||
|
||||
export default function UserPage() {
|
||||
const [userList, setUserList] = useState<User[]>([])
|
||||
const [filters, setFilters] = useState<FilterValues>({})
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const { control, handleSubmit, reset } = useForm<FormValues>({
|
||||
resolver: zodResolver(filterSchema),
|
||||
defaultValues: {
|
||||
account: "",
|
||||
name: "",
|
||||
phone: "",
|
||||
},
|
||||
})
|
||||
|
||||
const fetchUsers = useCallback(async (filters: UserQueryParams = {}) => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const res = await getPageUser(filters)
|
||||
if (res.success) {
|
||||
const req = [{ ...res.data }]
|
||||
setUserList(req)
|
||||
} else {
|
||||
toast.error(res.message || "获取用户失败")
|
||||
setUserList([])
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : error
|
||||
toast.error(`获取管理员失败: ${message}`)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const bind = useCallback(
|
||||
async (id: number) => {
|
||||
try {
|
||||
const res = await bindAdmin({ id })
|
||||
if (res.success) {
|
||||
toast.success("用户已认领")
|
||||
fetchUsers()
|
||||
} else {
|
||||
toast.error(res.message || "认领失败")
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : error
|
||||
toast.error(`认领请求失败: ${message}`)
|
||||
}
|
||||
},
|
||||
[fetchUsers],
|
||||
const fetchUsers = useCallback(
|
||||
(page: number, size: number) => getPageUserPage({ page, size, ...filters }),
|
||||
[filters],
|
||||
)
|
||||
|
||||
const onFilter = handleSubmit((data: FormValues) => {
|
||||
const params: UserQueryParams = {}
|
||||
const table = useDataTable<User>(fetchUsers)
|
||||
const bind = useFetch(table, (id: number) => bindAdmin({ id }), {
|
||||
done: "用户已认领",
|
||||
fail: "用户认领失败",
|
||||
})
|
||||
|
||||
if (data.account?.trim()) params.account = data.account.trim()
|
||||
if (data.name?.trim()) params.name = data.name.trim()
|
||||
const hasValidFilter = Object.keys(params).length > 0
|
||||
if (hasValidFilter) {
|
||||
fetchUsers(params)
|
||||
} else {
|
||||
setUserList([])
|
||||
setLoading(false)
|
||||
toast.info("请输入筛选条件后再查询")
|
||||
}
|
||||
const onFilter = handleSubmit(data => {
|
||||
const result: FilterValues = {}
|
||||
if (data.phone) result.phone = data.phone
|
||||
setFilters(result)
|
||||
table.pagination.onPageChange(1)
|
||||
})
|
||||
|
||||
return (
|
||||
@@ -99,30 +64,15 @@ export default function UserPage() {
|
||||
<form onSubmit={onFilter} className="bg-white p-4">
|
||||
<div className="flex flex-wrap items-end gap-4">
|
||||
<Controller
|
||||
name="account"
|
||||
control={control}
|
||||
render={({ field, fieldState }) => (
|
||||
<Field
|
||||
data-invalid={fieldState.invalid}
|
||||
className="w-80 flex-none"
|
||||
>
|
||||
<FieldLabel>账号/手机号/邮箱</FieldLabel>
|
||||
<Input {...field} placeholder="请输入账号/手机号/邮箱" />
|
||||
<FieldError>{fieldState.error?.message}</FieldError>
|
||||
</Field>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="name"
|
||||
name="phone"
|
||||
control={control}
|
||||
render={({ field, fieldState }) => (
|
||||
<Field
|
||||
data-invalid={fieldState.invalid}
|
||||
className="w-40 flex-none"
|
||||
>
|
||||
<FieldLabel>姓名</FieldLabel>
|
||||
<Input {...field} placeholder="请输入姓名" />
|
||||
<FieldLabel>手机号</FieldLabel>
|
||||
<Input {...field} placeholder="请输入手机号" />
|
||||
<FieldError>{fieldState.error?.message}</FieldError>
|
||||
</Field>
|
||||
)}
|
||||
@@ -136,7 +86,7 @@ export default function UserPage() {
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
reset()
|
||||
setUserList([])
|
||||
setFilters({})
|
||||
setLoading(false)
|
||||
}}
|
||||
>
|
||||
@@ -147,7 +97,7 @@ export default function UserPage() {
|
||||
|
||||
<Suspense>
|
||||
<DataTable<User>
|
||||
data={userList || []}
|
||||
{...table}
|
||||
status={loading ? "load" : "done"}
|
||||
columns={[
|
||||
{ header: "账号", accessorKey: "username" },
|
||||
@@ -186,14 +136,6 @@ export default function UserPage() {
|
||||
</Badge>
|
||||
),
|
||||
},
|
||||
{
|
||||
header: "身份证号",
|
||||
accessorKey: "id_no",
|
||||
cell: ({ row }) => {
|
||||
const idNo = row.original.id_no
|
||||
return idNo ? `${idNo.slice(0, 6)}****${idNo.slice(-4)}` : "-"
|
||||
},
|
||||
},
|
||||
{
|
||||
header: "客户来源",
|
||||
accessorKey: "source",
|
||||
@@ -213,10 +155,6 @@ export default function UserPage() {
|
||||
cell: ({ row }) => (row.original.status === 1 ? "正常" : "禁用"),
|
||||
},
|
||||
{ header: "联系方式", accessorKey: "contact_wechat" },
|
||||
{
|
||||
header: "客户经理",
|
||||
cell: ({ row }) => row.original.admin?.name || "-",
|
||||
},
|
||||
{
|
||||
header: "最后登录时间",
|
||||
accessorKey: "last_login",
|
||||
@@ -226,12 +164,12 @@ export default function UserPage() {
|
||||
new Date(row.original.last_login),
|
||||
"yyyy-MM-dd HH:mm",
|
||||
)
|
||||
: "-",
|
||||
: "",
|
||||
},
|
||||
{
|
||||
header: "最后登录IP",
|
||||
accessorKey: "last_login_ip",
|
||||
cell: ({ row }) => row.original.last_login_ip || "-",
|
||||
cell: ({ row }) => row.original.last_login_ip || "",
|
||||
},
|
||||
{
|
||||
header: "创建时间",
|
||||
@@ -244,13 +182,15 @@ export default function UserPage() {
|
||||
meta: { pin: "right" },
|
||||
header: "操作",
|
||||
cell: ctx => (
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => bind(ctx.row.original.id)}
|
||||
disabled={!!ctx.row.original.admin_id}
|
||||
>
|
||||
{ctx.row.original.admin_id ? "已认领" : "认领"}
|
||||
</Button>
|
||||
<Auth scope={ScopeUserWriteBind}>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => bind(ctx.row.original.id)}
|
||||
disabled={!!ctx.row.original.admin_id}
|
||||
>
|
||||
{ctx.row.original.admin_id ? "已认领" : "认领"}
|
||||
</Button>
|
||||
</Auth>
|
||||
),
|
||||
},
|
||||
]}
|
||||
|
||||
Reference in New Issue
Block a user