feat: integrate global policy API and implement data log page

This commit is contained in:
ningyv
2024-12-06 11:50:32 +08:00
parent 84decf1310
commit a38ee5e16c
14 changed files with 235 additions and 72 deletions
@@ -146,8 +146,20 @@ export const PublishApprovalModalContent = forwardRef<PublishApprovalModalHandle
...x,
title: typeof x.title === 'string' ? $t(x.title) : x.title,
...(x.dataIndex === 'status' ? {
render:(_,entity)=>(
entity.status === 0 ? $t('正常') : $t('无效'))
render:(_,entity)=> {
switch(entity.change){
case 'none':
return '-'
case 'new':
return $t('新建')
case 'update':
return $t('更新')
case 'delete':
return $t('删除')
default:
return '-'
}
}
}:{})
}
}),[state.language])
@@ -181,6 +181,10 @@ export const TranslateWord = ()=>{
{$t('请输入IP地址或CIDR范围,每条以换行分割')}
{$t('待更新')}
{$t('待删除')}
{$t('内容')}
{$t('调用地址')}
{$t('消费者 IP')}
{$t('鉴权名称')}
</>
)
}
@@ -749,5 +749,19 @@
"K67f4e9bb": "The domain name for obtaining API market documentation information when integrating with external platforms",
"K1da86266": "Invalid",
"K3a34d49b": "Pending Update",
"Kd2850420": "Pending Deletion"
"Kd2850420": "Pending Deletion",
"K9ada4366": "Operation successful, the page will refresh shortly",
"K9b332ab1": "Request prefix",
"K3d78d483": "HTTP headers",
"K17dc3a62": "Data logs",
"Ke429194e": "Processing logs",
"K84ffb1dd": "Enter the invocation address, consumer IP, and consumer condition to search",
"Kb147fabc": "Create",
"K40ca4f2": "Update",
"K3e7aa0ad": "Content",
"K2f5fdf5e": "Call Address",
"K1bc5e0a3": "Consumer IP",
"K6f39ea21": "Authentication Name",
"K8c34c02f": "Before Masking",
"K8e3d388d": "After Masking"
}
@@ -771,6 +771,19 @@
"K67f4e9bb": "外部プラットフォームと統合する際に、API市場のドキュメント情報を取得するためのドメイン名",
"K1da86266": "無効",
"K3a34d49b": "更新待ち",
"Kd2850420": "削除待ち"
"Kd2850420": "削除待ち",
"K9ada4366": "操作成功、ページを更新します",
"K9b332ab1": "リクエストプレフィックス",
"K3d78d483": "HTTPヘッダー",
"K17dc3a62": "データログ",
"Ke429194e": "ログの処理",
"K84ffb1dd": "呼び出しアドレス、コンシューマーIP、条件を入力して検索",
"Kb147fabc": "新規作成",
"K40ca4f2": "更新",
"K3e7aa0ad": "内容",
"K2f5fdf5e": "呼び出しアドレス",
"K1bc5e0a3": "コンシューマー IP",
"K6f39ea21": "認証名",
"K8c34c02f": "マスキング前",
"K8e3d388d": "マスキング後"
}
@@ -702,5 +702,19 @@
"K31faa2a1": "优先级",
"Kbdec9fa": "筛选条件",
"Kbcbb7391": "处理数",
"Kad207008": "编辑"
"Kad207008": "编辑",
"K9ada4366": "操作成功,即将刷新页面",
"K9b332ab1": "请求前缀",
"K3d78d483": "HTTP 头部",
"K17dc3a62": "数据日志",
"Ke429194e": "处理日志",
"K84ffb1dd": "输入调用地址、消费者IP和消费者条件查找",
"Kb147fabc": "新建",
"K40ca4f2": "更新",
"K3e7aa0ad": "内容",
"K2f5fdf5e": "调用地址",
"K1bc5e0a3": "消费者 IP",
"K6f39ea21": "鉴权名称",
"K8c34c02f": "脱敏前",
"K8e3d388d": "脱敏后"
}
@@ -771,5 +771,19 @@
"K67f4e9bb": "與外部平台集成時,用於獲取 API 市場文檔信息的域名",
"K1da86266": "無效",
"K3a34d49b": "待更新",
"Kd2850420": "待刪除"
"Kd2850420": "待刪除",
"K9ada4366": "操作成功,即將刷新頁面",
"K9b332ab1": "請求前綴",
"K3d78d483": "HTTP 標頭",
"K17dc3a62": "數據日誌",
"Ke429194e": "處理日誌",
"K84ffb1dd": "輸入調用地址、消費者 IP 和消費者條件進行查找",
"Kb147fabc": "新建",
"K40ca4f2": "更新",
"K3e7aa0ad": "內容",
"K2f5fdf5e": "調用地址",
"K1bc5e0a3": "消費者 IP",
"K6f39ea21": "鑑權名稱",
"K8c34c02f": "脫敏前",
"K8e3d388d": "脫敏後"
}
@@ -1,4 +1,6 @@
import { PageProColumns } from "@common/components/aoplatform/PageList";
import { COLUMNS_TITLE } from "@common/const/const";
import { EntityItem } from "@common/const/type";
export type PartitionConfigFieldType = {
@@ -113,22 +115,43 @@ export type PartitionDashboardConfigFieldType = {
addr: string
}
}
export type PartitionDataLogHeaderListFieldType = {
key: string
value: string
}
export type PartitionDataLogConfigFieldType = {
create_time: string
id: string
update_time: string
updater: {
id: string
name: string
}
creator: {
id: string
name: string
}
config: {
headers: {
[k: string]: string
headers: PartitionDataLogHeaderListFieldType[]
url: string
}
export const PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS: PageProColumns<PartitionDataLogConfigFieldType & { _id: string }>[] = [
{
title: ('标签'),
dataIndex: 'key',
formItemProps: {
className: 'p-0 bg-transparent border-none',
rootClassName: 'test',
rules: [
{
required: true,
whitespace: true
},
],
},
ellipsis: true
},
{
title: ('内容'),
dataIndex: 'value',
formItemProps: {
className: 'p-0 bg-transparent border-none'
}
url: string
}
}
},
{
title: COLUMNS_TITLE.operate,
valueType: 'option',
btnNums: 2,
render: () => null
},
];
@@ -3,7 +3,7 @@ import { useEffect } from "react";
import { PartitionDashboardConfigFieldType } from "../../const/partitions/types";
import { DASHBOARD_SETTING_DRIVER_OPTION_LIST } from "../../const/partitions/const";
import WithPermission from "@common/components/aoplatform/WithPermission";
import { BasicResponse, PLACEHOLDER, STATUS_CODE, VALIDATE_MESSAGE } from "@common/const/const";
import { BasicResponse, PLACEHOLDER, STATUS_CODE } from "@common/const/const";
import { useFetch } from "@common/hooks/http";
import { $t } from "@common/locales";
@@ -29,10 +29,10 @@ export type DashboardSettingEditProps = {
fetchData<BasicResponse<{info: PartitionDashboardConfigFieldType}>>('monitor/config',{method: 'POST',body:JSON.stringify(value),eoParams:{}}).then(response=>{
const {code,msg} = response
if(code === STATUS_CODE.SUCCESS){
message.success(msg || '操作成功,即将刷新页面')
message.success(msg || $t('操作成功,即将刷新页面'))
refreshData?.()
}else{
message.error(msg || '操作失败')
message.error(msg || $t('操作失败'))
}
})
})
@@ -1,18 +1,90 @@
import { PartitionDataLogConfigFieldType } from "@core/const/partitions/types"
import EditableTable from "@common/components/aoplatform/EditableTable"
import WithPermission from "@common/components/aoplatform/WithPermission"
import { BasicResponse, PLACEHOLDER, STATUS_CODE } from "@common/const/const"
import { useFetch } from "@common/hooks/http"
import { $t } from "@common/locales"
import { PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS, PartitionDataLogConfigFieldType, PartitionDataLogHeaderListFieldType } from "@core/const/partitions/types"
import { Button, Form, Input, message } from "antd"
import { useEffect } from "react"
export type DashboardPageShowStatus = 'view'|'edit'
export type DashboardPageShowStatus = 'view' | 'edit'
export type DashboardSettingEditProps = {
changeStatus:(status:DashboardPageShowStatus)=>void
refreshData:()=>void
data?:PartitionDataLogConfigFieldType
changeStatus: (status: DashboardPageShowStatus) => void
refreshData: () => void
data?: PartitionDataLogConfigFieldType
}
const DataLogSettingEdit = (props:DashboardSettingEditProps) => {
const {changeStatus,refreshData,data} = props
return (
<div>
222
</div>
);
const DataLogSettingEdit = (props: DashboardSettingEditProps) => {
const { changeStatus, refreshData, data } = props
const [form] = Form.useForm();
const { fetchData } = useFetch()
const onFinish = () => {
form.validateFields().then((value) => {
const formData = {
config: {
url: value.url,
headers: value.headers.filter((item: PartitionDataLogHeaderListFieldType) => item.key).map((item: PartitionDataLogHeaderListFieldType) => ({key:item.key, value:item.value || ''}))
}
}
fetchData<BasicResponse<{ info: PartitionDataLogConfigFieldType }>>('log/loki', { method: 'POST', body: JSON.stringify(formData), eoParams: {} }).then(response => {
const { code, msg } = response
if (code === STATUS_CODE.SUCCESS) {
message.success(msg || $t('操作成功,即将刷新页面'))
refreshData?.()
} else {
message.error(msg || $t('操作失败'))
}
})
})
}
useEffect(() => { form.setFieldsValue(data) }, [data])
useEffect(() => {
return (form.setFieldsValue({}))
}, []);
return (
<>
<div className="overflow-auto h-full">
<WithPermission access={''} >
<Form
form={form}
className="mx-auto flex flex-col justify-between h-full"
layout="vertical"
onFinish={onFinish}
autoComplete="off"
>
<Form.Item<PartitionDataLogConfigFieldType>
label={$t("请求前缀")}
name="url"
rules={[{ required: true }]}
>
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} />
</Form.Item>
<Form.Item<PartitionDataLogConfigFieldType>
label={$t("HTTP 头部")}
name="headers"
>
<EditableTable<PartitionDataLogConfigFieldType & { _id: string }>
configFields={PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS}
/>
</Form.Item>
<div className="flex gap-btnbase">
<WithPermission access='system.devops.data_source.edit'>
<Button type="primary" htmlType="submit">
{$t('保存')}
</Button>
</WithPermission>
<Button type="default" onClick={() => changeStatus('view')}>
{$t('取消')}
</Button>
</div>
</Form>
</WithPermission>
</div>
</>
);
}
export default DataLogSettingEdit;
@@ -8,7 +8,7 @@ import { LoadingOutlined } from "@ant-design/icons";
import InsidePage from "@common/components/aoplatform/InsidePage.tsx";
import { $t } from "@common/locales/index.ts";
import DashboardSettingEdit, { DashboardPageShowStatus } from "./DashboardSettingEdit.tsx";
import { PartitionDashboardConfigFieldType, PartitionDataLogConfigFieldType } from "@core/const/partitions/types.ts";
import { PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS, PartitionDashboardConfigFieldType, PartitionDataLogConfigFieldType } from "@core/const/partitions/types.ts";
import PageList from "@common/components/aoplatform/PageList.tsx";
import DataLogSettingEdit from "./DataLogSettingEdit.tsx";
@@ -43,10 +43,11 @@ const PartitionInsideDashboardSetting: FC = () => {
setDataLogLoading(true)
return fetchData<BasicResponse<{ nodes: PartitionDataLogConfigFieldType[] }>>('log/loki', { method: 'GET', eoTransformKeys: [] }).then(response => {
const { code, data, msg } = response
console.log('data====', data);
if (code === STATUS_CODE.SUCCESS) {
data?.info && setDataLogData(data.info)
data?.info && setDataLogData({
url: data.info?.config?.url || '',
headers: data.info?.config?.headers || []
})
setShowDataLogStatus('view')
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
@@ -66,10 +67,17 @@ const PartitionInsideDashboardSetting: FC = () => {
getDataLogSettingInfo()
}, []);
const setDashboardSettingBtn = (type: string) => {
const setDashboardSettingBtn = () => {
return (<>
{showGraphStatus === 'view' && <WithPermission access="system.devops.data_source.edit" key="changeClusterConfig">
<Button type="primary" onClick={() => type === 'graph' ? setShowGraphStatus('edit') : setShowDataLogStatus('edit')}>{$t('修改配置')}</Button>
<Button type="primary" onClick={() => setShowGraphStatus('edit')}>{$t('修改配置')}</Button>
</WithPermission>}</>
)
}
const setDataLogSettingBtn = () => {
return (<>
{showDataLogStatus === 'view' && <WithPermission access="system.devops.data_source.edit" key="changeClusterConfig">
<Button type="primary" onClick={() => setShowDataLogStatus('edit')}>{$t('修改配置')}</Button>
</WithPermission>}</>
)
}
@@ -94,7 +102,7 @@ const PartitionInsideDashboardSetting: FC = () => {
{!loading && !data?.driver && <Tag color='#f50'>{$t('未配置')}
</Tag>}</div>}
extra={setDashboardSettingBtn('graph')}>
extra={setDashboardSettingBtn()}>
{showGraphStatus === 'view' && data && data.driver && DashboardConfigPreview(data)}
{showGraphStatus !== 'view' && <DashboardSettingEdit data={data} changeStatus={setShowGraphStatus} refreshData={getDashboardSettingInfo} />}
</Card>
@@ -111,7 +119,7 @@ const PartitionInsideDashboardSetting: FC = () => {
{!dataLogLoading && !dataLogData && <Tag color='#f50'>{$t('未配置')}
</Tag>}</div>}
extra={setDashboardSettingBtn('log')}>
extra={setDataLogSettingBtn()}>
{showDataLogStatus === 'view' && dataLogData && DataLogConfigPreview(dataLogData)}
{showDataLogStatus !== 'view' && <DataLogSettingEdit data={dataLogData} changeStatus={setShowDataLogStatus} refreshData={getDataLogSettingInfo} />}
</Card>
@@ -131,39 +139,29 @@ export function DashboardConfigPreview(x: PartitionDashboardConfigFieldType) {
</div>
}
export function DataLogConfigPreview(x: PartitionDataLogConfigFieldType) {
const columns = [
{
title: '标签',
dataIndex: 'tag',
},
{
title: '内容',
dataIndex: 'content'
const columns = PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS.map(x => {
return {
...x,
title: (<span title={$t(x.title as string)}>{$t(x.title as string)}</span>)
}
]
})
const getTableList = () => {
return new Promise((resolve, reject) => {
resolve({
data: x?.config?.headers ? Object.keys(x?.config?.headers).map((key) => {
return {
tag: key,
content: x?.config?.headers[key]
}
}) : [],
data: x?.headers || [],
success: true
})
})
}
console.log(getTableList());
return <div className="flex flex-col gap-[4px] ">
<Row className=""><Col className="font-bold text-right pr-[4px]">{$t('请求前缀')}</Col><Col>{x?.config?.url}</Col></Row>
<Row className=""><Col className="font-bold text-right pr-[4px]">{$t('请求前缀')}</Col><Col>{x?.url}</Col></Row>
<Row className=""><Col className="font-bold text-right pr-[4px]">{$t('HTTP 头部')}</Col><Col className="w-full">
<div className="w-full h-full p-[20px]">
<PageList
id="global_role"
tableClass="role_table mb-btnrbase"
primaryKey="'tag'"
primaryKey="'key'"
columns={[...columns]}
request={() => getTableList()}
showPagination={false}
@@ -233,7 +233,6 @@ const DataMasking = (props: any) => {
* @param entity
*/
const openLogsModal = (entity: any) => {
console.log('日志', entity);
setStrategy(entity.id)
setModalVisible(true)
}
@@ -83,7 +83,7 @@ export const DATA_MASKING_TABLE_LOG_COLUMNS: PageProColumns<any>[] = [
width: 200
},
{
title: ('消费者IP'),
title: ('消费者 IP'),
dataIndex: 'remote_ip',
ellipsis: true,
width: 100
@@ -103,7 +103,7 @@ export const DATA_MASKING_TABLE_LOG_COLUMNS: PageProColumns<any>[] = [
{
title: ('时间'),
dataIndex: 'record_time',
width: 150,
width: 110,
ellipsis: true
},
]
@@ -62,7 +62,7 @@ const DataMaskingCompare = () => {
<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">
{$t('脱敏前')}
</div>
<div style={{ height: 'calc(100vh - 50px)' }}>
<Codebox
@@ -77,7 +77,7 @@ const DataMaskingCompare = () => {
</div>
<div className="w-1/2 p-2 h-full">
<div className="h-[30px] bg-green-100 mb-2 flex items-center justify-center">
{$t('脱敏后')}
</div>
<div style={{ height: 'calc(100vh - 50px)' }}>
<Codebox
@@ -57,7 +57,7 @@ const DataMaskingLogModal = (props: any) => {
*/
const operation: PageProColumns<any>[] = [
{
title: '操作',
title: '',
key: 'option',
btnNums: 1,
fixed: 'right',
@@ -89,7 +89,7 @@ const DataMaskingLogModal = (props: any) => {
}
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