import {Avatar, Button, Form, Input, message, Modal, Tag, Tooltip, Typography} from 'antd'; import React, {useEffect, useMemo, useState} from 'react'; import XinTable from '@/components/XinTable'; import type {XinTableColumn, XinTableProps} from "@/components/XinTable/typings.ts"; import type ISysUser from "@/domain/iSysUser.ts"; import AuthButton from "@/components/AuthButton"; import type {DeptFieldType, ResetPasswordType, RoleFieldType} from "@/api/system/sys_user"; import {deptField, resetPassword, roleField} from "@/api/system/sys_user"; import {RedoOutlined} from "@ant-design/icons"; import {useTranslation} from "react-i18next"; import dayjs from "dayjs"; import relativeTime from "dayjs/plugin/relativeTime"; import useAuth from "@/hooks/useAuth.ts"; const { Title, Text } = Typography; dayjs.extend(relativeTime); const Table: React.FC = () => { const {t} = useTranslation(); const { auth } = useAuth(); /** 角色选项数据 */ const [roles, setRoles] = useState([]); /** 部门选项数据 */ const [departments, setDepartments] = useState([]); /** 部门选项数据映射 */ const departmentMap: Map = useMemo(() => { const map: Map = new Map(); const buildMap = (dept: DeptFieldType[]) => { dept.forEach(item => { map.set(item.dept_id, item.name); if (item.children && item.children.length > 0) { buildMap(item.children); } }) } buildMap(departments); return map; }, [departments]); /** 高级表格列配置 */ const columns: XinTableColumn[] = [ { title: t("system.user.id"), dataIndex: 'id', hideInForm: true, sorter: true, align: 'center', }, { title: t("system.user.username"), dataIndex: 'username', valueType: 'text', align: 'center', required: true, rules: [{required: true, message: t("system.user.username.required")}], }, { title: t("system.user.nickname"), dataIndex: 'nickname', valueType: 'text', align: 'center', required: true, rules: [{required: true, message: t("system.user.nickname.required")}], }, { title: t("system.user.sex"), dataIndex: 'sex', valueType: 'radio', filters: [ { text: t("system.user.sex.0"), value: 0 }, { text: t("system.user.sex.1"), value: 1 }, ], align: 'center', hideInSearch: true, fieldProps: { options: [ { value: 0, label: t("system.user.sex.0") }, { value: 1, label: t("system.user.sex.1") }, ] }, render: (value: number) => { return value === 0 ? t("system.user.sex.0") : t("system.user.sex.1"); } }, { title: t("system.user.email"), dataIndex: 'email', valueType: 'text', align: 'center', required: true, rules: [{required: true, message: t("system.user.email.required")}], }, { title: t("system.user.role"), dataIndex: 'role_id', valueType: 'select', align: 'center', hideInSearch: true, required: true, rules: [{required: true, message: t("system.user.role.required")}], render: (value: number[]) => ( <> {value.map(item => ( {roles.find(r => r.role_id === item)?.name || '-'} ))} ), fieldProps: { mode: 'multiple', options: roles.map(r => ({ label: r.name, value: r.role_id })), }, }, { title: t("system.user.dept"), dataIndex: 'dept_id', valueType: 'treeSelect', align: 'center', required: true, rules: [{required: true, message: t("system.user.dept.required")}], render: (value) => ( // 嵌套寻找部门名称 {departmentMap.get(value) || '-'} ), fieldProps: { treeData: departments, fieldNames: {label: 'name', value: 'dept_id'} } }, { title: t("system.user.status"), dataIndex: 'status', valueType: 'radioButton', fieldProps: { options: [ { value: 0, label: t("system.user.status.0") }, { value: 1, label: t("system.user.status.1") }, ] }, render: (value: number) => { return value === 1 ? {t("system.user.status.1")} : {t("system.user.status.0")}; }, required: true, rules: [{required: true, message: t("system.user.status.required")}], filters: [ { text: t("system.user.status.0"), value: 0 }, { text: t("system.user.status.1"), value: 1 }, ], hideInSearch: true, align: 'center', }, { title: t("system.user.mobile"), dataIndex: 'mobile', valueType: 'text', required: true, rules: [{required: true, message: t("system.user.mobile.required")}], align: 'center', }, { title: t("system.user.avatar"), dataIndex: 'avatar_url', hideInSearch: true, hideInForm: true, render: (_, entity: ISysUser) => , align: 'center', }, { title: t("system.user.password"), dataIndex: 'password', valueType: 'password', hideInTable: true, hideInSearch: true, hideInUpdate: true, rules: [{required: true, message: t("system.user.password.required")}], fieldProps: {autoComplete: 'new-password'}, }, { title: t("system.user.rePassword"), dataIndex: 'rePassword', valueType: 'password', hideInTable: true, hideInSearch: true, hideInUpdate: true, rules: [{required: true, message: t("system.user.rePassword.required")}], fieldProps: {autoComplete: 'new-password'}, }, { title: t("system.user.created_at"), hideInForm: true, hideInSearch: true, dataIndex: 'created_at', align: 'center', render: (value: string) => value ? dayjs(value).fromNow() : '-', }, { title: t("system.user.updated_at"), hideInForm: true, hideInSearch: true, dataIndex: 'updated_at', align: 'center', render: (value: string) => value ? dayjs(value).fromNow() : '-', }, ]; /** 修改密码相关状态 */ const [isModalOpen, setIsModalOpen] = useState(false); const [resetUserId, setResetUserId] = useState(); const [buttonLoading, setButtonLoading] = useState(false); /** 打开重置密码框 */ const showRedoModal = (id: number) => { setIsModalOpen(true); setResetUserId(id); }; /** 提交重置密码 */ const handleRedoSubmit = async (values: ResetPasswordType) => { try { setButtonLoading(true); await resetPassword({...values, id: resetUserId!}); setIsModalOpen(false); message.success(t("system.user.resetSuccess")); } finally { setButtonLoading(false); } }; useEffect(() => { if(auth('system.user.dept')) { deptField().then(res => setDepartments(res.data.data!)); } if(auth('system.user.role')) { roleField().then(res => setRoles(res.data.data!)); } }, []); /** 操作栏之后渲染 */ const operateRender: XinTableProps['operateRender'] = (record, dom) => ([ <> {record.id !== 1 && ); }; export default Table;