| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import React from 'react'; |
| import { |
| Button, |
| Space, |
| Tag, |
| Tooltip, |
| Progress, |
| Popover, |
| Typography, |
| Dropdown, |
| } from '@douyinfe/semi-ui'; |
| import { IconMore } from '@douyinfe/semi-icons'; |
| import { renderGroup, renderNumber, renderQuota } from '../../../helpers'; |
|
|
| |
| |
| |
| const renderRole = (role, t) => { |
| switch (role) { |
| case 1: |
| return ( |
| <Tag color='blue' shape='circle'> |
| {t('普通用户')} |
| </Tag> |
| ); |
| case 10: |
| return ( |
| <Tag color='yellow' shape='circle'> |
| {t('管理员')} |
| </Tag> |
| ); |
| case 100: |
| return ( |
| <Tag color='orange' shape='circle'> |
| {t('超级管理员')} |
| </Tag> |
| ); |
| default: |
| return ( |
| <Tag color='red' shape='circle'> |
| {t('未知身份')} |
| </Tag> |
| ); |
| } |
| }; |
|
|
| |
| |
| |
| const renderUsername = (text, record) => { |
| const remark = record.remark; |
| if (!remark) { |
| return <span>{text}</span>; |
| } |
| const maxLen = 10; |
| const displayRemark = |
| remark.length > maxLen ? remark.slice(0, maxLen) + '…' : remark; |
| return ( |
| <Space spacing={2}> |
| <span>{text}</span> |
| <Tooltip content={remark} position='top' showArrow> |
| <Tag color='white' shape='circle' className='!text-xs'> |
| <div className='flex items-center gap-1'> |
| <div |
| className='w-2 h-2 flex-shrink-0 rounded-full' |
| style={{ backgroundColor: '#10b981' }} |
| /> |
| {displayRemark} |
| </div> |
| </Tag> |
| </Tooltip> |
| </Space> |
| ); |
| }; |
|
|
| |
| |
| |
| const renderStatistics = (text, record, showEnableDisableModal, t) => { |
| const isDeleted = record.DeletedAt !== null; |
|
|
| |
| let tagColor = 'grey'; |
| let tagText = t('未知状态'); |
| if (isDeleted) { |
| tagColor = 'red'; |
| tagText = t('已注销'); |
| } else if (record.status === 1) { |
| tagColor = 'green'; |
| tagText = t('已启用'); |
| } else if (record.status === 2) { |
| tagColor = 'red'; |
| tagText = t('已禁用'); |
| } |
|
|
| const content = ( |
| <Tag color={tagColor} shape='circle' size='small'> |
| {tagText} |
| </Tag> |
| ); |
|
|
| const tooltipContent = ( |
| <div className='text-xs'> |
| <div> |
| {t('调用次数')}: {renderNumber(record.request_count)} |
| </div> |
| </div> |
| ); |
|
|
| return ( |
| <Tooltip content={tooltipContent} position='top'> |
| {content} |
| </Tooltip> |
| ); |
| }; |
|
|
| |
| const renderQuotaUsage = (text, record, t) => { |
| const { Paragraph } = Typography; |
| const used = parseInt(record.used_quota) || 0; |
| const remain = parseInt(record.quota) || 0; |
| const total = used + remain; |
| const percent = total > 0 ? (remain / total) * 100 : 0; |
| const popoverContent = ( |
| <div className='text-xs p-2'> |
| <Paragraph copyable={{ content: renderQuota(used) }}> |
| {t('已用额度')}: {renderQuota(used)} |
| </Paragraph> |
| <Paragraph copyable={{ content: renderQuota(remain) }}> |
| {t('剩余额度')}: {renderQuota(remain)} ({percent.toFixed(0)}%) |
| </Paragraph> |
| <Paragraph copyable={{ content: renderQuota(total) }}> |
| {t('总额度')}: {renderQuota(total)} |
| </Paragraph> |
| </div> |
| ); |
| return ( |
| <Popover content={popoverContent} position='top'> |
| <Tag color='white' shape='circle'> |
| <div className='flex flex-col items-end'> |
| <span className='text-xs leading-none'>{`${renderQuota(remain)} / ${renderQuota(total)}`}</span> |
| <Progress |
| percent={percent} |
| aria-label='quota usage' |
| format={() => `${percent.toFixed(0)}%`} |
| style={{ width: '100%', marginTop: '1px', marginBottom: 0 }} |
| /> |
| </div> |
| </Tag> |
| </Popover> |
| ); |
| }; |
|
|
| |
| |
| |
| const renderInviteInfo = (text, record, t) => { |
| return ( |
| <div> |
| <Space spacing={1}> |
| <Tag color='white' shape='circle' className='!text-xs'> |
| {t('邀请')}: {renderNumber(record.aff_count)} |
| </Tag> |
| <Tag color='white' shape='circle' className='!text-xs'> |
| {t('收益')}: {renderQuota(record.aff_history_quota)} |
| </Tag> |
| <Tag color='white' shape='circle' className='!text-xs'> |
| {record.inviter_id === 0 |
| ? t('无邀请人') |
| : `${t('邀请人')}: ${record.inviter_id}`} |
| </Tag> |
| </Space> |
| </div> |
| ); |
| }; |
|
|
| |
| |
| |
| const renderOperations = ( |
| text, |
| record, |
| { |
| setEditingUser, |
| setShowEditUser, |
| showPromoteModal, |
| showDemoteModal, |
| showEnableDisableModal, |
| showDeleteModal, |
| showResetPasskeyModal, |
| showResetTwoFAModal, |
| t, |
| }, |
| ) => { |
| if (record.DeletedAt !== null) { |
| return <></>; |
| } |
|
|
| const moreMenu = [ |
| { |
| node: 'item', |
| name: t('重置 Passkey'), |
| onClick: () => showResetPasskeyModal(record), |
| }, |
| { |
| node: 'item', |
| name: t('重置 2FA'), |
| onClick: () => showResetTwoFAModal(record), |
| }, |
| { |
| node: 'divider', |
| }, |
| { |
| node: 'item', |
| name: t('注销'), |
| type: 'danger', |
| onClick: () => showDeleteModal(record), |
| }, |
| ]; |
|
|
| return ( |
| <Space> |
| {record.status === 1 ? ( |
| <Button |
| type='danger' |
| size='small' |
| onClick={() => showEnableDisableModal(record, 'disable')} |
| > |
| {t('禁用')} |
| </Button> |
| ) : ( |
| <Button |
| size='small' |
| onClick={() => showEnableDisableModal(record, 'enable')} |
| > |
| {t('启用')} |
| </Button> |
| )} |
| <Button |
| type='tertiary' |
| size='small' |
| onClick={() => { |
| setEditingUser(record); |
| setShowEditUser(true); |
| }} |
| > |
| {t('编辑')} |
| </Button> |
| <Button |
| type='warning' |
| size='small' |
| onClick={() => showPromoteModal(record)} |
| > |
| {t('提升')} |
| </Button> |
| <Button |
| type='secondary' |
| size='small' |
| onClick={() => showDemoteModal(record)} |
| > |
| {t('降级')} |
| </Button> |
| <Dropdown menu={moreMenu} trigger='click' position='bottomRight'> |
| <Button type='tertiary' size='small' icon={<IconMore />} /> |
| </Dropdown> |
| </Space> |
| ); |
| }; |
|
|
| |
| |
| |
| export const getUsersColumns = ({ |
| t, |
| setEditingUser, |
| setShowEditUser, |
| showPromoteModal, |
| showDemoteModal, |
| showEnableDisableModal, |
| showDeleteModal, |
| showResetPasskeyModal, |
| showResetTwoFAModal, |
| }) => { |
| return [ |
| { |
| title: 'ID', |
| dataIndex: 'id', |
| }, |
| { |
| title: t('用户名'), |
| dataIndex: 'username', |
| render: (text, record) => renderUsername(text, record), |
| }, |
| { |
| title: t('状态'), |
| dataIndex: 'info', |
| render: (text, record, index) => |
| renderStatistics(text, record, showEnableDisableModal, t), |
| }, |
| { |
| title: t('剩余额度/总额度'), |
| key: 'quota_usage', |
| render: (text, record) => renderQuotaUsage(text, record, t), |
| }, |
| { |
| title: t('分组'), |
| dataIndex: 'group', |
| render: (text, record, index) => { |
| return <div>{renderGroup(text)}</div>; |
| }, |
| }, |
| { |
| title: t('角色'), |
| dataIndex: 'role', |
| render: (text, record, index) => { |
| return <div>{renderRole(text, t)}</div>; |
| }, |
| }, |
| { |
| title: t('邀请信息'), |
| dataIndex: 'invite', |
| render: (text, record, index) => renderInviteInfo(text, record, t), |
| }, |
| { |
| title: '', |
| dataIndex: 'operate', |
| fixed: 'right', |
| width: 200, |
| render: (text, record, index) => |
| renderOperations(text, record, { |
| setEditingUser, |
| setShowEditUser, |
| showPromoteModal, |
| showDemoteModal, |
| showEnableDisableModal, |
| showDeleteModal, |
| showResetPasskeyModal, |
| showResetTwoFAModal, |
| t, |
| }), |
| }, |
| ]; |
| }; |
|
|