feature: dataMask logs dialog

This commit is contained in:
ningyv
2024-11-29 18:39:13 +08:00
parent eb4fb872a3
commit e031f80b2e
7 changed files with 679 additions and 127 deletions
@@ -66,6 +66,22 @@ export type DataMaskStrategyItem = {
updater:EntityItem
updateTime:string
}
export type DataMaskLogItem = {
id:string
service: {
id:string
name:string
}
method:string
url:string
remote_ip:string
consumer: {
id:string
name:string
}
authorization:string
record_time:string
}
export type FilterFormField= {
@@ -13,6 +13,7 @@ import { ProtectedRoute } from "@core/components/aoplatform/RenderRoutes";
import Login from "@core/pages/Login";
import { useLocaleContext } from "./LocaleContext";
import Root from "@core/pages/Root"
import DataMaskingCompare from "@core/pages/policy/dataMasking/DataMaskingCompare";
interface GlobalState {
isAuthenticated: boolean;
userData: UserData | null;
@@ -286,6 +287,7 @@ const globalReducer = (state: GlobalState, action: GlobalAction): GlobalState =>
export const DefaultRouteConfig = [
{ path: '/', pathMatch: 'full', component: <Root /> ,key:'root',},
{ path: '/login', component: <Login /> ,key:'login'},
{ path: '/dataMaskCompare/:logId/:serviceId?/:teamId?', component: <DataMaskingCompare /> ,key:'dataMaskCompare'},
{ path: '/', pathMatch:'prefix',component:<ProtectedRoute /> ,key:'basciLayout',children:[
{ path: '*', component: <ErrorBoundary><NotFound/></ErrorBoundary>, key: 'errorBoundary' }
]}
+2 -2
View File
@@ -975,7 +975,7 @@ p{
.ant-drawer-content-wrapper{
min-width: 820px !important;
.ant-table:not(.ant-table-bordered){
border:1px solid var(--border-color) !important;
/* border:1px solid var(--border-color) !important; */
border-top:0px !important;
}
.ant-table:not(.ant-table-borderer){
@@ -1001,7 +1001,7 @@ p{
.ant-modal-wrap:not(.height-fixed-modal){
.ant-modal-body{
.ant-table:not(.ant-table-bordered){
border:1px solid var(--border-color) !important;
/* border:1px solid var(--border-color) !important; */
border-top:0px !important;
}
.ant-table:not(.ant-table-borderer){
@@ -1,6 +1,6 @@
import { ActionType } from "@ant-design/pro-components";
import { useEffect, useMemo, useRef, useState } from "react";
import { App, Button, message, Switch } from 'antd'
import { App, Button, message, Switch, Modal } from 'antd'
import PageList, { PageProColumns } from "@common/components/aoplatform/PageList";
import { $t } from "@common/locales";
import { useGlobalContext } from "@common/contexts/GlobalStateContext";
@@ -8,14 +8,14 @@ import { BasicResponse, DELETE_TIPS, RESPONSE_TIPS, STATUS_CODE } from "@common/
import { useFetch } from "@common/hooks/http";
import WithPermission from "@common/components/aoplatform/WithPermission.tsx";
import TableBtnWithPermission from "@common/components/aoplatform/TableBtnWithPermission";
import { DATA_MASSKING_TABLE_COLUMNS } from "./DataMaskingColumn";
import { DATA_MASKING_TABLE_COLUMNS } from "./DataMaskingColumn";
import { useNavigate, useParams } from "react-router-dom";
import { PolicyPublishInfoType, PolicyPublishModalHandle, RouterParams } from "@common/const/type";
import { DrawerWithFooter } from "@common/components/aoplatform/DrawerWithFooter";
import { DataMaskStrategyItem } from "@common/const/policy/type";
import {PolicyPublishModalContent} from '@common/components/aoplatform/PolicyPublishModalContent'
import { PolicyPublishModalContent } from '@common/components/aoplatform/PolicyPublishModalContent'
import { checkAccess } from "@common/utils/permission";
import DataMaskingLogModal from "./DataMaskingLogModal.tsx";
const DataMasking = (props: any) => {
const {
@@ -25,19 +25,21 @@ const DataMasking = (props: any) => {
rowOperation = []
} = props;
const { serviceId, teamId } = useParams<RouterParams>()
const { state,accessData } = useGlobalContext()
const { state, accessData } = useGlobalContext()
const navigator = useNavigate()
const [drawerVisible, setDrawerVisible] = useState<boolean>(false)
const [drawerData, setDrawerData] = useState<PolicyPublishInfoType >()
const [modalVisible, setModalVisible] = useState<boolean>(false);
const [drawerData, setDrawerData] = useState<PolicyPublishInfoType>()
const [isOkToPublish, setIsOkToPublish] = useState<boolean>(false)
const drawerRef = useRef<PolicyPublishModalHandle>(null)
const { modal } = App.useApp()
/**
* 列表ref
*/
/**
* 列表ref
*/
const pageListRef = useRef<ActionType>(null);
/**
* 请求数据
*/
@@ -47,27 +49,28 @@ const DataMasking = (props: any) => {
* 搜索关键字
*/
const [searchWord, setSearchWord] = useState<string>('')
const [strategy, setStrategy] = useState<string>('')
/**
* 获取列数据,国际化变化时重新获取
*/
const columns = useMemo(() => {
const res = DATA_MASSKING_TABLE_COLUMNS.map(x => {
const res = DATA_MASKING_TABLE_COLUMNS.map(x => {
// 启动列渲染
if (x.dataIndex === 'isStop') {
x.render = (text: any, record: any) => <WithPermission access={`${ serviceId === undefined ? 'system.devops':'team.service'}.policy.edit`} ><Switch checked={!record.isStop} onChange={(e) => { changeOpenApiStatus(e, record) }} /></WithPermission>
x.render = (text: any, record: any) => <WithPermission access={`${serviceId === undefined ? 'system.devops' : 'team.service'}.policy.edit`} ><Switch checked={!record.isStop} onChange={(e) => { changeOpenApiStatus(e, record) }} /></WithPermission>
}
// 处理数列渲染
if (x.dataIndex === 'treatmentNumber') {
x.render = (text: any, record: any) => <span className="w-full block cursor-pointer [&>.ant-typography]:text-theme" onClick={(e) => { openLogsModal(record) }} >{ text }</span>
x.render = (text: any, record: any) => <span className="w-full block cursor-pointer [&>.ant-typography]:text-theme" onClick={(e) => { openLogsModal(record) }} >{text}</span>
}
return {
...x,
title: typeof x.title === 'string' ? $t(x.title as string) : x.title
title: <span title={$t(x.title as string)}>{$t(x.title as string)}</span>
}
})
return res
}, [ state.language])
}, [state.language])
/**
* 操作列
@@ -80,16 +83,21 @@ const DataMasking = (props: any) => {
fixed: 'right',
valueType: 'option',
render: (_: React.ReactNode, entity: any) => [
...(rowOperation.length && rowOperation.find((item: string) => item === 'edit') ? [<TableBtnWithPermission access={`${ serviceId === undefined ? 'system.devops':'team.service'}.policy.edit`} key="edit" btnType="edit" onClick={() => { openEditModal(entity) }} btnTitle="编辑" />] : []),
// ...(rowOperation.length && rowOperation.find((item: string) => item === 'logs') ? [<TableBtnWithPermission access={`${ serviceId === undefined ? 'system.devops':'team.service'}.policy.view`} key="logs" btnType="logs" onClick={() => { openLogsModal(entity) }} btnTitle="详情" />] : []),
...(rowOperation.length && rowOperation.find((item: string) => item === 'edit') ? [<TableBtnWithPermission access={`${serviceId === undefined ? 'system.devops' : 'team.service'}.policy.edit`} key="edit" btnType="edit" onClick={() => { openEditModal(entity) }} btnTitle="编辑" />] : []),
...(rowOperation.length && rowOperation.find((item: string) => item === 'logs') ? [<TableBtnWithPermission access={`${serviceId === undefined ? 'system.devops' : 'team.service'}.policy.view`} key="logs" btnType="logs" onClick={() => { openLogsModal(entity) }} btnTitle="日志" />] : []),
...(rowOperation.length && rowOperation.find((item: string) => item === 'delete') ? [
entity.isDelete ? <TableBtnWithPermission access={`${ serviceId === undefined ? 'system.devops':'team.service'}.policy.edit`} key="refresh" btnType="refresh" onClick={() => { restorePolicy(entity) }} btnTitle="恢复" /> :
<TableBtnWithPermission access={`${ serviceId === undefined ? 'system.devops':'team.service'}.policy.delete`} key="delete" btnType="delete" onClick={() => { openModal('delete',entity) }} btnTitle="删除" />
] : []),
entity.isDelete ? <TableBtnWithPermission access={`${serviceId === undefined ? 'system.devops' : 'team.service'}.policy.edit`} key="refresh" btnType="refresh" onClick={() => { restorePolicy(entity) }} btnTitle="恢复" /> :
<TableBtnWithPermission access={`${serviceId === undefined ? 'system.devops' : 'team.service'}.policy.delete`} key="delete" btnType="delete" onClick={() => { openModal('delete', entity) }} btnTitle="删除" />
] : []),
],
}
] : []
const handleCloseModal = () => {
setModalVisible(false);
// setDetailInvokeError(false)
// setDetailInvokeStatic(undefined)
// setCompareTotal(false)
};
/**
* 手动刷新表格数据
*/
@@ -104,12 +112,12 @@ const DataMasking = (props: any) => {
*/
const changeOpenApiStatus = (enabled: boolean, entity: any) => {
fetchData<BasicResponse<null>>(
`strategy/${serviceId === undefined? 'global':'service'}/data-masking/${enabled ? 'enable' :'disable' }`,
`strategy/${serviceId === undefined ? 'global' : 'service'}/data-masking/${enabled ? 'enable' : 'disable'}`,
{
method: 'PATCH',
eoParams: {
service:serviceId,
team:teamId,
service: serviceId,
team: teamId,
strategy: entity.id
}
}
@@ -133,44 +141,45 @@ const DataMasking = (props: any) => {
pageSize: number;
current: number;
},
sort:Record<string, string>,
filter:Record<string, string>) => {
sort: Record<string, string>,
filter: Record<string, string>) => {
let filters
if(filter){
if (filter) {
filters = []
if(filter.isStop){
if(filter.isStop.indexOf('true')!== -1){
filters.push('enable')
}
if(filter.isStop.indexOf('false')!== -1){
filters.push('disable')
}
if(filter.publishStatus?.length > 0){
filters = [...filters, ...filter.publishStatus]
}
if (filter.isStop) {
if (filter.isStop.indexOf('true') !== -1) {
filters.push('enable')
}
if (filter.isStop.indexOf('false') !== -1) {
filters.push('disable')
}
if (filter.publishStatus?.length > 0) {
filters = [...filters, ...filter.publishStatus]
}
}
}
return fetchData<BasicResponse<{list:DataMaskStrategyItem[], total:number}>>(
`strategy/${serviceId === undefined? 'global':'service'}/data-masking/list`,
return fetchData<BasicResponse<{ list: DataMaskStrategyItem[], total: number }>>(
`strategy/${serviceId === undefined ? 'global' : 'service'}/data-masking/list`,
{
method: 'GET',
eoParams: {
order:Object.keys(sort)?.[0],
sort:Object.keys(sort)?.length > 0 ? Object.values(sort)?.[0] === 'descend' ? 'desc' : 'asc' : undefined,
filters:JSON.stringify(filters),
eoParams: {
order: Object.keys(sort)?.[0],
sort: Object.keys(sort)?.length > 0 ? Object.values(sort)?.[0] === 'descend' ? 'desc' : 'asc' : undefined,
filters: JSON.stringify(filters),
keyword: searchWord,
service:serviceId,
team:teamId,},
eoTransformKeys: ['is_stop', 'is_delete', 'update_time','publish_status','processed_total']
service: serviceId,
team: teamId,
},
eoTransformKeys: ['is_stop', 'is_delete', 'update_time', 'publish_status', 'processed_total']
}
).then(response => {
const { code,data, msg } = response
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
// 保存数据
return {
data:data.list,
total:data.total,
data: data.list,
total: data.total,
success: true
}
} else {
@@ -181,7 +190,7 @@ const DataMasking = (props: any) => {
return { data: [], success: false }
})
}
/**
@@ -198,17 +207,17 @@ const DataMasking = (props: any) => {
const publish = async () => {
message.loading($t(RESPONSE_TIPS.loading));
const { code, data, msg } = await fetchData<BasicResponse<PolicyPublishInfoType>>(
'strategy/global/data-masking/to-publishs',
{ method: 'GET',eoTransformKeys:['opt_time','is_publish','version_name','unpublish_msg'] }
'strategy/global/data-masking/to-publishs',
{ method: 'GET', eoTransformKeys: ['opt_time', 'is_publish', 'version_name', 'unpublish_msg'] }
);
message.destroy();
if (code === STATUS_CODE.SUCCESS) {
setDrawerVisible(true)
setDrawerData(data)
setIsOkToPublish(data.isPublish??true)
setDrawerVisible(true)
setDrawerData(data)
setIsOkToPublish(data.isPublish ?? true)
} else {
message.error(msg || $t(RESPONSE_TIPS.error));
return
message.error(msg || $t(RESPONSE_TIPS.error));
return
}
}
@@ -225,42 +234,44 @@ const DataMasking = (props: any) => {
*/
const openLogsModal = (entity: any) => {
console.log('日志', entity);
setStrategy(entity.id)
setModalVisible(true)
}
const openModal =async (type:'delete',entity?:DataMaskStrategyItem)=>{
if(entity?.publishStatus === 'online'){
return deletePolicy(entity!).then((res)=>{if(res === true) manualReloadTable()})
const openModal = async (type: 'delete', entity?: DataMaskStrategyItem) => {
if (entity?.publishStatus === 'online') {
return deletePolicy(entity!).then((res) => { if (res === true) manualReloadTable() })
}
let title:string = ''
let content:string|React.ReactNode = ''
switch (type){
case 'delete':
title=$t('删除')
content=$t(DELETE_TIPS.default)
break;
let title: string = ''
let content: string | React.ReactNode = ''
switch (type) {
case 'delete':
title = $t('删除')
content = $t(DELETE_TIPS.default)
break;
}
modal.confirm({
title,
content,
onOk:()=>{
switch (type){
case 'delete':
return deletePolicy(entity!).then((res)=>{if(res === true) manualReloadTable()})
}
},
width:600,
okText:$t('确认'),
okButtonProps:{
disabled : !checkAccess( `${ serviceId === undefined ? 'system.devops':'team.service'}.policy.edit`, accessData)
},
cancelText:$t('取消'),
closable:true,
icon:<></>,
title,
content,
onOk: () => {
switch (type) {
case 'delete':
return deletePolicy(entity!).then((res) => { if (res === true) manualReloadTable() })
}
},
width: 600,
okText: $t('确认'),
okButtonProps: {
disabled: !checkAccess(`${serviceId === undefined ? 'system.devops' : 'team.service'}.policy.edit`, accessData)
},
cancelText: $t('取消'),
closable: true,
icon: <></>,
})
}
}
/**
* 删除
@@ -268,13 +279,14 @@ const DataMasking = (props: any) => {
*/
const deletePolicy = (entity: DataMaskStrategyItem) => {
return fetchData<BasicResponse<null>>(
`strategy/${serviceId === undefined? 'global':'service'}/data-masking`,
`strategy/${serviceId === undefined ? 'global' : 'service'}/data-masking`,
{
method: 'DELETE',
eoParams: {
service:serviceId,
team:teamId,
strategy:entity.id},
eoParams: {
service: serviceId,
team: teamId,
strategy: entity.id
},
}
).then(response => {
const { code, msg } = response
@@ -285,7 +297,7 @@ const DataMasking = (props: any) => {
message.error(msg || $t(RESPONSE_TIPS.error))
return Promise.reject(msg || $t(RESPONSE_TIPS.error))
}
}).catch((errorInfo)=> Promise.reject(errorInfo))
}).catch((errorInfo) => Promise.reject(errorInfo))
}
/**
@@ -294,13 +306,14 @@ const DataMasking = (props: any) => {
*/
const restorePolicy = (entity: any) => {
fetchData<BasicResponse<null>>(
`strategy/${serviceId === undefined? 'global':'service'}/data-masking/restore`,
`strategy/${serviceId === undefined ? 'global' : 'service'}/data-masking/restore`,
{
method: 'PATCH',
eoParams: {
service:serviceId,
team:teamId,
strategy:entity.id},
eoParams: {
service: serviceId,
team: teamId,
strategy: entity.id
},
}
).then(response => {
const { code, msg } = response
@@ -313,13 +326,13 @@ const DataMasking = (props: any) => {
})
}
const onSubmit = () => {
return drawerRef.current?.publish()?.then((res) => {
manualReloadTable();
return res;
});
}
return drawerRef.current?.publish()?.then((res) => {
manualReloadTable();
return res;
});
}
return (
<>
@@ -331,38 +344,51 @@ const DataMasking = (props: any) => {
pageSize: number;
current: number;
},
sort:Record<string, string>,
filter:Record<string, string>) => getPolicyList(params,sort, filter)}
sort: Record<string, string>,
filter: Record<string, string>) => getPolicyList(params, sort, filter)}
addNewBtnTitle={$t("添加策略")}
addNewBtnAccess={`${ serviceId === undefined ? 'system.devops':'team.service'}.policy.edit`}
addNewBtnAccess={`${serviceId === undefined ? 'system.devops' : 'team.service'}.policy.edit`}
onAddNewBtnClick={() => { addPolicy() }}
searchPlaceholder={$t("输入名称、筛选条件查找")}
afterNewBtn={
publishBtn && [<WithPermission key="removeFromDepPermission" access={`${ serviceId === undefined ? 'system.devops':'team.service'}.policy.publish`} >
publishBtn && [<WithPermission key="removeFromDepPermission" access={`${serviceId === undefined ? 'system.devops' : 'team.service'}.policy.publish`} >
<Button className="mr-btnbase" key="removeFromDep" onClick={() => publish()}>{$t('发布')}</Button>
</WithPermission>]
</WithPermission>]
}
onSearchWordChange={(e) => {
setSearchWord(e.target.value)
}}
manualReloadTable={manualReloadTable}
/>
<DrawerWithFooter
destroyOnClose={true}
title={$t('申请发布')}
width={'60%'}
onClose={()=>{setDrawerVisible(false)}}
okBtnTitle={$t('发布')}
open={drawerVisible}
submitDisabled={!isOkToPublish}
submitAccess={`${ serviceId === undefined ? 'system.devops':'team.service'}.policy.publish`}
onSubmit={onSubmit}
>
<PolicyPublishModalContent
ref={drawerRef}
data={drawerData! }
/>
</DrawerWithFooter>
<DrawerWithFooter
destroyOnClose={true}
title={$t('申请发布')}
width={'60%'}
onClose={() => { setDrawerVisible(false) }}
okBtnTitle={$t('发布')}
open={drawerVisible}
submitDisabled={!isOkToPublish}
submitAccess={`${serviceId === undefined ? 'system.devops' : 'team.service'}.policy.publish`}
onSubmit={onSubmit}
>
<PolicyPublishModalContent
ref={drawerRef}
data={drawerData!}
/>
</DrawerWithFooter>
<Modal
title={$t('处理日志')}
visible={modalVisible}
onCancel={handleCloseModal}
footer={null}
wrapClassName="modal-without-footer"
width={1000}
maskClosable={true}
>
<div className="pb-btnybase flex flex-nowrap flex-col h-full w-full items-center justify-between">
<DataMaskingLogModal strategy={strategy}></DataMaskingLogModal>
</div>
</Modal>
</>
)
}
@@ -5,7 +5,7 @@ import { $t } from "@common/locales";
import { StrategyStatusEnum, StrategyStatusColorClass } from "@common/const/policy/consts";
export const DATA_MASSKING_TABLE_COLUMNS: PageProColumns<any>[] = [
export const DATA_MASKING_TABLE_COLUMNS: PageProColumns<any>[] = [
{
title: ('策略名称'),
dataIndex: 'name',
@@ -67,3 +67,41 @@ export const DATA_MASSKING_TABLE_COLUMNS: PageProColumns<any>[] = [
sorter: (a, b) => frontendTimeSorter(a, b, 'updateTime')
},
];
export const DATA_MASKING_TABLE_LOG_COLUMNS: PageProColumns<any>[] = [
{
title: ('服务'),
dataIndex: ['service', 'name'],
ellipsis: true,
width: 80
},
{
title: ('调用地址'),
dataIndex: 'url',
ellipsis: true,
width: 200
},
{
title: ('消费者IP'),
dataIndex: 'remote_ip',
ellipsis: true,
width: 150
},
{
title: ('消费者'),
dataIndex: ['consumer', 'name'],
ellipsis: true,
width: 80
},
{
title: ('鉴权名称'),
dataIndex: 'authorization',
ellipsis: true,
width: 100
},
{
title: ('时间'),
dataIndex: 'record_time',
width: 150,
ellipsis: true
},
]
@@ -0,0 +1,97 @@
import { Codebox } from "@common/components/postcat/api/Codebox";
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const";
import { RouterParams } from "@common/const/type";
import { $t } from "@common/locales";
import { App, Button, message, Switch, Modal, Spin } from 'antd'
import { useFetch } from "@common/hooks/http";
import { useEffect, useState } from "react";
import { LoadingOutlined } from "@ant-design/icons";
import { useParams } from "react-router-dom";
type LogItems = {
id: string;
origin: string;
target: string;
}
const DataMaskingCompare = () => {
const { logId, serviceId, teamId } = useParams();
const { fetchData } = useFetch()
const [loading, setLoading] = useState(false)
const [originValue, setOriginValue] = useState('')
const [targetValue, settTargetValue] = useState('')
const getLogData = () => {
setLoading(true)
return fetchData<BasicResponse<{ log: LogItems }>>(`strategy/${serviceId === undefined ? 'global' : 'service'}/data-masking/log`,
{
method: 'GET',
eoParams: {
log: logId,
service: serviceId,
team: teamId,
}
}).then(response => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
const { log } = data
setOriginValue(log.origin || '')
settTargetValue(log.target || '')
setLoading(false)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
}
}).catch(() => {
return { data: [], success: false }
}).finally(() => {
const aa = `{
"code": {
"gg": "gg",
"gg1": "gg",
"gg2": "gg",
"gg3": "gg",
"gg4": "gg"
}
}`
setOriginValue(JSON.stringify(JSON.parse(aa), null, 2))
settTargetValue(JSON.stringify(JSON.parse(aa), null, 2))
setLoading(false)
})
}
useEffect(() => {
getLogData()
}, []);
return (
<Spin wrapperClassName=" h-full flex-1" indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} spinning={loading}>
<div className="flex h-full overflow-hidden">
<div className="w-1/2 p-2 h-full">
<div className="h-[30px] bg-gray-200 mb-2 flex items-center justify-center">
</div>
<div style={{ height: 'calc(100vh - 50px)' }}>
<Codebox
language='json'
height="100%"
width="100%"
value={originValue}
/>
</div>
</div>
<div className="w-1/2 p-2 h-full">
<div className="h-[30px] bg-green-100 mb-2 flex items-center justify-center">
</div>
<div style={{ height: 'calc(100vh - 50px)' }}>
<Codebox
language='json'
width="100%"
height="100%"
value={targetValue}
sx={{ whiteSpace: 'nowrap' }}
readOnly
/>
</div>
</div>
</div>
</Spin>
);
}
export default DataMaskingCompare;
@@ -0,0 +1,373 @@
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { DataMaskLogItem } from "@common/const/policy/type";
import PageList, { PageProColumns } from "@common/components/aoplatform/PageList";
import { $t } from "@common/locales";
import { App, Button, message, DatePicker, Modal } from 'antd'
import { DATA_MASKING_TABLE_LOG_COLUMNS, DATA_MASKING_TABLE_COLUMNS } from './DataMaskingColumn';
import { useGlobalContext } from '@common/contexts/GlobalStateContext';
import { ActionType } from '@ant-design/pro-components';
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const';
import { useParams } from 'react-router-dom';
import { RouterParams } from '@common/const/type';
import { useFetch } from '@common/hooks/http';
import WithPermission from '@common/components/aoplatform/WithPermission';
import TimeRangeSelector, { TimeRange } from '@common/components/aoplatform/TimeRangeSelector';
import { SearchBody } from '@dashboard/const/type';
import TableBtnWithPermission from '@common/components/aoplatform/TableBtnWithPermission';
const { RangePicker } = DatePicker;
const DataMaskingLogModal = (props: any) => {
const { strategy } = props;
const { state, accessData } = useGlobalContext()
const { serviceId, teamId } = useParams<RouterParams>()
const [datePickerValue, setDatePickerValue] = useState<any>();
const [queryData, setQueryData] = useState<SearchBody>({})
/**
* 请求数据
*/
const { fetchData } = useFetch()
/**
* 列表ref
*/
const pageListRef = useRef<ActionType>(null);
/**
* 搜索关键字
*/
const [searchWord, setSearchWord] = useState<string>('')
/**
* 操作列
*/
const operation: PageProColumns<any>[] = [
{
title: '操作',
key: 'option',
btnNums: 1,
fixed: 'right',
valueType: 'option',
render: (_: React.ReactNode, entity: any) => {
let url = `/dataMaskCompare/${entity.id}`
if (serviceId) {
url += `/${serviceId}`
}
if (teamId) {
url += `/${teamId}`
}
return [
<TableBtnWithPermission access={`${serviceId === undefined ? 'system.devops' : 'team.service'}.policy.view`} key="view" btnType="view" onClick={() => { window.open(url,'_blank') }} btnTitle="查看" />
]
}
}
]
/**
* 手动刷新表格数据
*/
const manualReloadTable = () => {
pageListRef.current?.reload()
};
const columns = useMemo(() => {
const res = DATA_MASKING_TABLE_LOG_COLUMNS.map(x => {
if (x.dataIndex === 'url') {
x.render = (text: any, record: any) => <><span className='text-green-500'>{record.method}</span>&nbsp;<span>{text}</span></>
}
return {
...x,
title: typeof x.title === 'string' ? $t(x.title as string) : x.title
}
})
return res
}, [state.language])
/**
* 获取列表数据
* @param dataType
* @returns
*/
const getPolicyList = (params: DataMaskLogItem & {
pageSize: number;
current: number;
}) => {
return fetchData<BasicResponse<{ logs: DataMaskLogItem[], total: number }>>(
`strategy/${serviceId === undefined ? 'global' : 'service'}/data-masking/list`,
{
method: 'GET',
eoParams: {
keyword: searchWord,
begin: queryData?.start,
end: queryData?.end,
page: params.current,
page_size: params.pageSize,
strategy: strategy,
service: serviceId,
team: teamId,
},
eoTransformKeys: ['is_stop', 'is_delete', 'update_time', 'publish_status', 'processed_total']
}
).then(response => {
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
const mockData: any = [
{
id: '12334',
service: {
id: 'xxx',
name: 'xxx'
},
url: 'url',
remote_ip: '9234923',
consumer: {
id: 'yyy',
name: 'yyy'
},
method: 'GET',
authorization: 'authorization',
record_time: '2021-09-09 12:12:12',
},
{
id: 'fff1',
service: {
id: 'xxx',
name: 'xxx'
},
url: 'url',
remote_ip: '9234923',
consumer: {
id: 'yyy',
name: 'yyy'
},
method: 'GET',
authorization: 'authorization',
record_time: '2021-09-09 12:12:12',
},
{
id: 'fff2',
service: {
id: 'xxx',
name: 'xxx'
},
url: 'url',
remote_ip: '9234923',
consumer: {
id: 'yyy',
name: 'yyy'
},
method: 'GET',
authorization: 'authorization',
record_time: '2021-09-09 12:12:12',
},
{
id: 'fff3',
service: {
id: 'xxx',
name: 'xxx'
},
url: 'url',
remote_ip: '9234923',
consumer: {
id: 'yyy',
name: 'yyy'
},
method: 'GET',
authorization: 'authorization',
record_time: '2021-09-09 12:12:12',
},
{
id: 'fff4',
service: {
id: 'xxx',
name: 'xxx'
},
url: 'url',
remote_ip: '9234923',
consumer: {
id: 'yyy',
name: 'yyy'
},
method: 'GET',
authorization: 'authorization',
record_time: '2021-09-09 12:12:12',
},
{
id: 'fff5',
service: {
id: 'xxx',
name: 'xxx'
},
url: 'url',
remote_ip: '9234923',
consumer: {
id: 'yyy',
name: 'yyy'
},
method: 'GET',
authorization: 'authorization',
record_time: '2021-09-09 12:12:12',
},
{
id: 'fff6',
service: {
id: 'xxx',
name: 'xxx'
},
url: 'url',
remote_ip: '9234923',
consumer: {
id: 'yyy',
name: 'yyy'
},
method: 'GET',
authorization: 'authorization',
record_time: '2021-09-09 12:12:12',
},
{
id: 'fff7',
service: {
id: 'xxx',
name: 'xxx'
},
url: 'url',
remote_ip: '9234923',
consumer: {
id: 'yyy',
name: 'yyy'
},
method: 'GET',
authorization: 'authorization',
record_time: '2021-09-09 12:12:12',
},
{
id: 'fff8',
service: {
id: 'xxx',
name: 'xxx'
},
url: 'url',
remote_ip: '9234923',
consumer: {
id: 'yyy',
name: 'yyy'
},
method: 'GET',
authorization: 'authorization',
record_time: '2021-09-09 12:12:12',
},
{
id: 'fff9',
service: {
id: 'xxx',
name: 'xxx'
},
url: 'url',
remote_ip: '9234923',
consumer: {
id: 'yyy',
name: 'yyy'
},
method: 'GET',
authorization: 'authorization',
record_time: '2021-09-09 12:12:12',
},
{
id: 'fff11',
service: {
id: 'xxx',
name: 'xxx'
},
url: 'url',
remote_ip: '9234923',
consumer: {
id: 'yyy',
name: 'yyy'
},
method: 'GET',
authorization: 'authorization',
record_time: '2021-09-09 12:12:12',
},
{
id: 'fff22',
service: {
id: 'xxx',
name: 'xxx'
},
url: 'url',
remote_ip: '9234923',
consumer: {
id: 'yyy',
name: 'yyy'
},
method: 'GET',
authorization: 'authorization',
record_time: '2021-09-09 12:12:11',
}
]
// 保存数据
return {
data: mockData,
total: data.total,
success: true
}
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
return { data: [], success: false }
}
}).catch(() => {
return { data: [], success: false }
})
}
const handleTimeRangeChange = (timeRange: TimeRange) => {
setQueryData(pre => ({ ...pre, ...timeRange } as SearchBody))
manualReloadTable()
};
const handleDatePickerChange = (dates: any) => {
if (dates && Array.isArray(dates) && dates.length === 2) {
const [startDate, endDate] = dates;
const start = startDate!.startOf('day').unix(); // 开始日期的00:00:00
const end = endDate!.endOf('day').unix(); // 结束日期的23:59:59
handleTimeRangeChange({ start, end });
} else {
handleTimeRangeChange({ start: null, end: null})
}
}
const resetQuery = () => {
setDatePickerValue(null)
handleTimeRangeChange({ start: null, end: null})
};
return (
<>
<div className="w-full h-full p-[20px]">
<PageList<DataMaskLogItem>
id="data_masking_log_list"
ref={pageListRef}
minVirtualHeight={400}
columns={[...columns, ...operation]}
afterNewBtn={
[<div className="flex items-center flex-wrap p-[10px] px-btnbase content-before bg-MAIN_BG ">
<RangePicker
onChange={handleDatePickerChange}
value={datePickerValue} />
<div className="flex [&>.reset-btn]:!h-auto flex-nowrap items-center ml-[10px]">
<Button className="reset-btn" onClick={resetQuery}>{$t('重置')}</Button>
</div>
</div>]
}
request={async (params: DataMaskLogItem & {
pageSize: number;
current: number;
}) => getPolicyList(params)}
searchPlaceholder={$t("输入调用地址、消费者IP和消费者条件查找")}
onSearchWordChange={(e) => {
setSearchWord(e.target.value)
}}
manualReloadTable={manualReloadTable}
></PageList>
</div>
</>
)
};
export default DataMaskingLogModal;