|
|
@@ -0,0 +1,258 @@ |
|
|
|
import React, { useState, useEffect, useRef } from 'react'; |
|
|
|
import { useSetState } from 'ahooks'; |
|
|
|
import { Space, Table, Input, Divider, Tag, Card } from 'antd'; |
|
|
|
import type { TableColumnsType, InputRef } from 'antd'; |
|
|
|
import type { ColumnType, TableProps } from 'antd/es/table'; |
|
|
|
import { t } from '@/utils/i18n'; |
|
|
|
import { SearchOutlined, ExclamationCircleFilled } from '@ant-design/icons'; |
|
|
|
import { antdUtils } from '@/utils/antd'; |
|
|
|
import { useRequest } from '@/hooks/use-request'; |
|
|
|
import { formatDate } from '@/utils/formatTime' |
|
|
|
import oauth2Service from '@/request/service/oauth2'; |
|
|
|
import { |
|
|
|
OAuth2TokenVO, |
|
|
|
OAuth2TokenPageReqVO |
|
|
|
} from '@/models'; |
|
|
|
|
|
|
|
|
|
|
|
type DataIndex = keyof OAuth2TokenVO; |
|
|
|
|
|
|
|
const mapOperation = (operation: number) => { |
|
|
|
if (operation === 1) { |
|
|
|
return (<Tag color="purple">通知</Tag>) |
|
|
|
} else if (operation === 2) { |
|
|
|
return (<Tag color="purple">新增</Tag>) |
|
|
|
} else if (operation === 3) { |
|
|
|
return (<Tag color="yellow">修改</Tag>) |
|
|
|
} else if (operation === 4) { |
|
|
|
return (<Tag color="red">删除</Tag>) |
|
|
|
} else if (operation === 5) { |
|
|
|
return (<Tag color="blue">导出</Tag>) |
|
|
|
} else { |
|
|
|
return (<Tag color="red">未知({operation})</Tag>) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
export default () => { |
|
|
|
const [dataSource, setDataSource] = useState<OAuth2TokenVO[]>([]); |
|
|
|
|
|
|
|
const { runAsync: getPageData } = useRequest(oauth2Service.getAccessTokenPageApi, { manual: true }); |
|
|
|
const { runAsync: deleteAccessToken } = useRequest(oauth2Service.deleteAccessTokenApi, { manual: true }); |
|
|
|
|
|
|
|
const [searchState, setSearchState] = useSetState<OAuth2TokenPageReqVO>({ |
|
|
|
pageNo: 1, |
|
|
|
pageSize: 10 |
|
|
|
}); |
|
|
|
const [total, setTotal] = useState(0) |
|
|
|
const searchInput = useRef<InputRef>(null); |
|
|
|
const [onSearching, setOnSearching] = useState(false); |
|
|
|
|
|
|
|
const load = async () => { |
|
|
|
console.log(searchState) |
|
|
|
const [error, { code, msg, data }] = await getPageData(searchState); |
|
|
|
setOnSearching(false); |
|
|
|
if (error || code !== 0) { |
|
|
|
antdUtils.message?.open({ type: 'error', content: msg ?? '操作失败' }); |
|
|
|
return |
|
|
|
} |
|
|
|
setTotal(data.total); |
|
|
|
setDataSource(data.list); |
|
|
|
}; |
|
|
|
|
|
|
|
const getColumnSearchProps = (dataIndex: DataIndex, placeholder: string): ColumnType<OAuth2TokenVO> => ({ |
|
|
|
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters, close }) => ( |
|
|
|
<div style={{ padding: 8 }} onKeyDown={(e) => e.stopPropagation()}> |
|
|
|
<Input.Search |
|
|
|
ref={searchInput} |
|
|
|
placeholder={placeholder} |
|
|
|
value={selectedKeys[0]} |
|
|
|
onChange={(e) => { |
|
|
|
setSelectedKeys(e.target.value && e.target.value !== '' ? [e.target.value] : []) |
|
|
|
}} |
|
|
|
onSearch={(value) => { |
|
|
|
if (value === '' && clearFilters) { |
|
|
|
clearFilters!!() |
|
|
|
} |
|
|
|
confirm(); |
|
|
|
}} |
|
|
|
onPressEnter={() => confirm()} |
|
|
|
allowClear |
|
|
|
style={{ marginBottom: 8, display: 'block' }} |
|
|
|
enterButton="搜索" |
|
|
|
size="middle" |
|
|
|
loading={onSearching} |
|
|
|
/> |
|
|
|
</div> |
|
|
|
), |
|
|
|
filterIcon: (filtered: boolean) => ( |
|
|
|
<SearchOutlined style={{ color: filtered ? 'primaryColor' : undefined }} /> |
|
|
|
), |
|
|
|
onFilterDropdownOpenChange: (visible) => { |
|
|
|
if (visible) { |
|
|
|
setTimeout(() => searchInput.current?.select(), 100); |
|
|
|
} |
|
|
|
}, |
|
|
|
}); |
|
|
|
|
|
|
|
const forceQuite = async (params: OAuth2TokenVO) => { |
|
|
|
antdUtils.modal?.confirm({ |
|
|
|
title: '系统提示', |
|
|
|
icon: <ExclamationCircleFilled />, |
|
|
|
content: '是否要强制退出用户', |
|
|
|
okText: '确定', |
|
|
|
okType: 'danger', |
|
|
|
cancelText: '取消', |
|
|
|
onOk() { |
|
|
|
return new Promise(async (resolve) => { |
|
|
|
const [error, { code, msg }] = await deleteAccessToken(params.accessToken); |
|
|
|
if (error || code !== 0) { |
|
|
|
antdUtils.message?.open({ type: 'error', content: msg ?? '操作失败' }) |
|
|
|
} else { |
|
|
|
antdUtils.message?.open({ type: 'success', content: '操作成功' }) |
|
|
|
} |
|
|
|
resolve(''); |
|
|
|
await load(); |
|
|
|
}).catch(() => antdUtils.message?.open({ |
|
|
|
type: 'error', |
|
|
|
content: '操作失败', |
|
|
|
})); |
|
|
|
}, |
|
|
|
onCancel() { |
|
|
|
}, |
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
const columns: TableColumnsType<OAuth2TokenVO> = [ |
|
|
|
{ |
|
|
|
title: '用户编号', |
|
|
|
dataIndex: 'userId', |
|
|
|
key: 'userId', |
|
|
|
align: 'center', |
|
|
|
width: 100, |
|
|
|
...getColumnSearchProps('userId', "请输入用户编号") |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '访问令牌', |
|
|
|
dataIndex: 'accessToken', |
|
|
|
key: 'accessToken', |
|
|
|
align: 'center', |
|
|
|
width: 120, |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '刷新令牌', |
|
|
|
dataIndex: 'refreshToken', |
|
|
|
key: 'refreshToken', |
|
|
|
align: 'center', |
|
|
|
width: 100, |
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
title: '客户端编号', |
|
|
|
dataIndex: 'clientId', |
|
|
|
key: 'clientId', |
|
|
|
align: 'center', |
|
|
|
width: 150, |
|
|
|
...getColumnSearchProps('clientId', "客户端编号") |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '用户类型', |
|
|
|
dataIndex: 'userType', |
|
|
|
key: 'userType', |
|
|
|
fixed: 'left', |
|
|
|
align: 'center', |
|
|
|
width: 100, |
|
|
|
filters: [ |
|
|
|
{ text: '会员', value: 1 }, |
|
|
|
{ text: '管理员', value: 2 }, |
|
|
|
], |
|
|
|
filterMultiple: false, |
|
|
|
filterSearch: false, |
|
|
|
render: (value: number) => { |
|
|
|
if (value === 1) { |
|
|
|
return <Tag color="purple">会员</Tag> |
|
|
|
} else if (value === 2) { |
|
|
|
return <Tag color="blue">管理员</Tag> |
|
|
|
} else { |
|
|
|
return <Tag color="red">未知</Tag> |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '创建时间', |
|
|
|
dataIndex: 'createTime', |
|
|
|
key: 'createTime', |
|
|
|
align: 'center', |
|
|
|
width: 150, |
|
|
|
render: (value: number) => { |
|
|
|
return formatDate(new Date(value), "YYYY-mm-dd HH:MM:SS") |
|
|
|
} |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '过期时间', |
|
|
|
dataIndex: 'expiresTime', |
|
|
|
key: 'expiresTime', |
|
|
|
align: 'center', |
|
|
|
width: 150, |
|
|
|
render: (value: number) => { |
|
|
|
return formatDate(new Date(value), "YYYY-mm-dd HH:MM:SS") |
|
|
|
} |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: t("QkOmYwne" /* 操作 */), |
|
|
|
key: 'action', |
|
|
|
fixed: 'right', |
|
|
|
align: 'center', |
|
|
|
width: 250, |
|
|
|
render: (value: OAuth2TokenVO, record) => ( |
|
|
|
<Space size="small" split={(<Divider type='vertical' />)}> |
|
|
|
<a onClick={() => { |
|
|
|
|
|
|
|
}}> 详情 </a> |
|
|
|
|
|
|
|
<a onClick={() => { |
|
|
|
forceQuite(value) |
|
|
|
}}> 强制退出 </a> |
|
|
|
</Space> |
|
|
|
), |
|
|
|
}, |
|
|
|
]; |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
load(); |
|
|
|
}, [searchState]); |
|
|
|
|
|
|
|
const onChange: TableProps<OAuth2TokenVO>['onChange'] = (pagination, filters, sorter, extra) => { |
|
|
|
const state: OAuth2TokenPageReqVO = { |
|
|
|
clientId: filters.clientId ? filters.clientId[0] as string : undefined, |
|
|
|
userId: filters.userId ? parseInt(filters.userId[0] as string) : undefined, |
|
|
|
userType: filters.userType ? filters.userType[0] as number : undefined, |
|
|
|
pageNo: pagination.current, |
|
|
|
pageSize: pagination.pageSize |
|
|
|
} |
|
|
|
setOnSearching(true); |
|
|
|
setSearchState(state); |
|
|
|
}; |
|
|
|
|
|
|
|
return ( |
|
|
|
<> |
|
|
|
<div> |
|
|
|
<Card className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]'> |
|
|
|
<Table rowKey="id" |
|
|
|
scroll={{ x: true }} |
|
|
|
columns={columns} |
|
|
|
dataSource={dataSource} |
|
|
|
onChange={onChange} |
|
|
|
className='bg-transparent' |
|
|
|
pagination={{ |
|
|
|
position: ['bottomRight'], |
|
|
|
current: searchState.pageNo, |
|
|
|
pageSize: searchState.pageSize, |
|
|
|
total |
|
|
|
}} |
|
|
|
/> |
|
|
|
</Card> |
|
|
|
</div> |
|
|
|
</> |
|
|
|
); |
|
|
|
}; |