From d7f9a8de0edc3f97212c6733134f8d9947a14215 Mon Sep 17 00:00:00 2001 From: zzyangh <799463087@qq.com> Date: Tue, 20 Jan 2026 15:03:22 +0800 Subject: [PATCH 1/5] [feature](OperationRecord): Migrate api serives to dms --- .../base/src/__snapshots__/App.test.tsx.snap | 4 +- packages/base/src/locale/zh-CN/dmsHome.ts | 2 +- packages/base/src/locale/zh-CN/dmsMenu.ts | 2 +- .../__snapshots__/index.ce.test.tsx.snap | 2 +- .../__snapshots__/index.test.tsx.snap | 2 +- .../__snapshots__/index.test.tsx.snap | 2 +- .../StepItems/__tests__/index.test.tsx | 2 +- .../__snapshots__/index.ce.test.tsx.snap | 2 +- .../__snapshots__/index.test.tsx.snap | 2 +- .../__snapshots__/common.test.tsx.snap | 2 +- packages/shared/lib/api/base/index.ts | 1 + .../base/service/OperationRecord/index.d.ts | 44 + .../api/base/service/OperationRecord/index.ts | 55 ++ .../shared/lib/api/base/service/common.d.ts | 71 +- .../lib/api/base/service/common.enum.ts | 6 + .../mockApi/sqle/operationRecord/data.ts | 16 +- .../mockApi/sqle/operationRecord/index.ts | 5 +- packages/sqle/src/locale/zh-CN/menu.ts | 2 +- .../List/__snapshots__/index.test.tsx.snap | 776 ++++++++++-------- .../src/page/OperationRecord/List/column.tsx | 64 +- .../page/OperationRecord/List/index.test.tsx | 21 +- .../src/page/OperationRecord/List/index.tsx | 81 +- .../__snapshots__/index.test.tsx.snap | 49 +- .../components/OperationStatus.tsx | 10 +- .../components/test/OperationStatus.test.tsx | 6 +- 25 files changed, 767 insertions(+), 462 deletions(-) create mode 100644 packages/shared/lib/api/base/service/OperationRecord/index.d.ts create mode 100644 packages/shared/lib/api/base/service/OperationRecord/index.ts diff --git a/packages/base/src/__snapshots__/App.test.tsx.snap b/packages/base/src/__snapshots__/App.test.tsx.snap index bd549bfd1..2bfc72951 100644 --- a/packages/base/src/__snapshots__/App.test.tsx.snap +++ b/packages/base/src/__snapshots__/App.test.tsx.snap @@ -1054,7 +1054,7 @@ exports[`App render App when "checkPageAction" is false 1`] = `
- SQLE操作记录 + 操作记录
@@ -2231,7 +2231,7 @@ exports[`App render App when token is existed 1`] = `
- SQLE操作记录 + 操作记录
diff --git a/packages/base/src/locale/zh-CN/dmsHome.ts b/packages/base/src/locale/zh-CN/dmsHome.ts index 69eece452..ddf771fce 100644 --- a/packages/base/src/locale/zh-CN/dmsHome.ts +++ b/packages/base/src/locale/zh-CN/dmsHome.ts @@ -69,7 +69,7 @@ export default { action_1_0: '授权审计', action_1_1: '权限模板审计', action_1_2: '数据源操作审计', - action_1_3: 'SQLE操作记录' + action_1_3: '操作记录' } } } diff --git a/packages/base/src/locale/zh-CN/dmsMenu.ts b/packages/base/src/locale/zh-CN/dmsMenu.ts index 682f23e37..1e8b73a71 100644 --- a/packages/base/src/locale/zh-CN/dmsMenu.ts +++ b/packages/base/src/locale/zh-CN/dmsMenu.ts @@ -8,7 +8,7 @@ export default { authAudit: '授权审计', templateAudit: '权限模板审计', instanceAudit: '数据源操作审计', - SQLEOperateRecord: 'SQLE操作记录', + SQLEOperateRecord: '操作记录', inspectionAndDiagnosis: '巡检与诊断', SQLWorkbench: 'SQL工作台', ruleTemplate: '审核规则模板', diff --git a/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.ce.test.tsx.snap b/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.ce.test.tsx.snap index 221d09608..34e9a6522 100644 --- a/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.ce.test.tsx.snap +++ b/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.ce.test.tsx.snap @@ -689,7 +689,7 @@ exports[`test base/home/CEDefaultScene should match snapshot when role is admin
- SQLE操作记录 + 操作记录
diff --git a/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.test.tsx.snap index d1feb901f..a6661062c 100644 --- a/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/base/src/page/Home/DefaultScene/__tests__/__snapshots__/index.test.tsx.snap @@ -708,7 +708,7 @@ exports[`test base/home/DefaultScene should match snapshot when role is admin 1`
- SQLE操作记录 + 操作记录
diff --git a/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/__snapshots__/index.test.tsx.snap index cb9819629..0307c2b45 100644 --- a/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/__snapshots__/index.test.tsx.snap @@ -700,7 +700,7 @@ exports[`test base/Home/StepItems should match snapshot 1`] = `
- SQLE操作记录 + 操作记录
diff --git a/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/index.test.tsx b/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/index.test.tsx index a8d289aee..27f41cce0 100644 --- a/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/index.test.tsx +++ b/packages/base/src/page/Home/DefaultScene/components/StepItems/__tests__/index.test.tsx @@ -117,7 +117,7 @@ describe('test base/Home/StepItems', () => { `/sqle/project/${projectID}/exec-workflow/create` ); - fireEvent.click(screen.getByText('SQLE操作记录')); + fireEvent.click(screen.getByText('操作记录')); expect(navigateSpy).toHaveBeenCalledTimes(13); expect(navigateSpy).toHaveBeenNthCalledWith( 13, diff --git a/packages/base/src/page/Home/__tests__/__snapshots__/index.ce.test.tsx.snap b/packages/base/src/page/Home/__tests__/__snapshots__/index.ce.test.tsx.snap index d49bc881e..ee30eb452 100644 --- a/packages/base/src/page/Home/__tests__/__snapshots__/index.ce.test.tsx.snap +++ b/packages/base/src/page/Home/__tests__/__snapshots__/index.ce.test.tsx.snap @@ -702,7 +702,7 @@ exports[`test base/page/Home should match snapshot 1`] = `
- SQLE操作记录 + 操作记录
diff --git a/packages/base/src/page/Home/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/Home/__tests__/__snapshots__/index.test.tsx.snap index 6b8b42b0c..c4064919e 100644 --- a/packages/base/src/page/Home/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/base/src/page/Home/__tests__/__snapshots__/index.test.tsx.snap @@ -721,7 +721,7 @@ exports[`test base/page/Home should match snapshot 1`] = `
- SQLE操作记录 + 操作记录
diff --git a/packages/base/src/page/Nav/SideMenu/MenuList/menus/__tests__/__snapshots__/common.test.tsx.snap b/packages/base/src/page/Nav/SideMenu/MenuList/menus/__tests__/__snapshots__/common.test.tsx.snap index e25d67106..a3a89b884 100644 --- a/packages/base/src/page/Nav/SideMenu/MenuList/menus/__tests__/__snapshots__/common.test.tsx.snap +++ b/packages/base/src/page/Nav/SideMenu/MenuList/menus/__tests__/__snapshots__/common.test.tsx.snap @@ -434,7 +434,7 @@ exports[`test genMenuItemsWithMenuStructTree should match snapshot 4`] = ` "label": - SQLE操作记录 + 操作记录 , "permission": "page:operation_record", "structKey": "sqle-log", diff --git a/packages/shared/lib/api/base/index.ts b/packages/shared/lib/api/base/index.ts index c924de868..220befc3e 100644 --- a/packages/shared/lib/api/base/index.ts +++ b/packages/shared/lib/api/base/index.ts @@ -16,6 +16,7 @@ export { default as MemberGroupService } from './service/MemberGroup'; export { default as NotificationService } from './service/Notification'; export { default as OAuth2Service } from './service/OAuth2'; export { default as OpPermissionService } from './service/OpPermission'; +export { default as OperationRecordService } from './service/OperationRecord'; export { default as ProjectService } from './service/Project'; export { default as ResourceOverviewService } from './service/ResourceOverview'; export { default as RoleService } from './service/Role'; diff --git a/packages/shared/lib/api/base/service/OperationRecord/index.d.ts b/packages/shared/lib/api/base/service/OperationRecord/index.d.ts new file mode 100644 index 000000000..2a9cb1a23 --- /dev/null +++ b/packages/shared/lib/api/base/service/OperationRecord/index.d.ts @@ -0,0 +1,44 @@ +import { + IGetOperationRecordListReply, + IAddOperationRecordReq, + IAddOperationRecordReply +} from '../common.d'; + +export interface IGetOperationRecordListParams { + filter_operate_time_from?: string; + + filter_operate_time_to?: string; + + filter_operate_project_name?: string; + + fuzzy_search_operate_user_name?: string; + + filter_operate_type_name?: string; + + filter_operate_action?: string; + + page_index: number; + + page_size: number; +} + +export interface IGetOperationRecordListReturn + extends IGetOperationRecordListReply {} + +export interface IAddOperationRecordParams extends IAddOperationRecordReq {} + +export interface IAddOperationRecordReturn extends IAddOperationRecordReply {} + +export interface IExportOperationRecordListParams { + filter_operate_time_from?: string; + + filter_operate_time_to?: string; + + filter_operate_project_name?: string; + + fuzzy_search_operate_user_name?: string; + + filter_operate_type_name?: string; + + filter_operate_action?: string; +} diff --git a/packages/shared/lib/api/base/service/OperationRecord/index.ts b/packages/shared/lib/api/base/service/OperationRecord/index.ts new file mode 100644 index 000000000..d73a17c0d --- /dev/null +++ b/packages/shared/lib/api/base/service/OperationRecord/index.ts @@ -0,0 +1,55 @@ +/* tslint:disable no-identical-functions */ +/* tslint:disable no-useless-cast */ +/* tslint:disable no-unnecessary-type-assertion */ +/* tslint:disable no-big-function */ +/* tslint:disable no-duplicate-string */ +import ServiceBase from '../Service.base'; +import { AxiosRequestConfig } from 'axios'; + +import { + IGetOperationRecordListParams, + IGetOperationRecordListReturn, + IAddOperationRecordParams, + IAddOperationRecordReturn, + IExportOperationRecordListParams +} from './index.d'; + +class OperationRecordService extends ServiceBase { + public GetOperationRecordList( + params: IGetOperationRecordListParams, + options?: AxiosRequestConfig + ) { + const paramsData = this.cloneDeep(params); + return this.get( + '/v1/dms/operation_records', + paramsData, + options + ); + } + + public AddOperationRecord( + params: IAddOperationRecordParams, + options?: AxiosRequestConfig + ) { + const paramsData = this.cloneDeep(params); + return this.post( + '/v1/dms/operation_records', + paramsData, + options + ); + } + + public ExportOperationRecordList( + params: IExportOperationRecordListParams, + options?: AxiosRequestConfig + ) { + const paramsData = this.cloneDeep(params); + return this.get( + '/v1/dms/operation_records/exports', + paramsData, + options + ); + } +} + +export default new OperationRecordService(); diff --git a/packages/shared/lib/api/base/service/common.d.ts b/packages/shared/lib/api/base/service/common.d.ts index 137f05549..5a2a9a019 100644 --- a/packages/shared/lib/api/base/service/common.d.ts +++ b/packages/shared/lib/api/base/service/common.d.ts @@ -25,6 +25,7 @@ import { OpPermissionItemOpPermissionTypeEnum, OpPermissionItemRangeTypeEnum, OperationOperationTypeEnum, + OperationRecordListItemStatusEnum, ProjectInfoProjectPriorityEnum, ProjectV1ProjectPriorityEnum, ProjectV2ProjectPriorityEnum, @@ -144,6 +145,16 @@ export interface IAddMemberReq { member?: IMember; } +export interface IAddOperationRecordReply { + code?: number; + + message?: string; +} + +export interface IAddOperationRecordReq { + operation_record?: IOperationRecord; +} + export interface IAddProjectReply { code?: number; @@ -992,6 +1003,16 @@ export interface IGetOauth2TipsResData { login_tip?: string; } +export interface IGetOperationRecordListReply { + code?: number; + + data?: IOperationRecordListItem[]; + + message?: string; + + total_nums?: number; +} + export interface IGetProjectTipsReply { code?: number; @@ -1837,10 +1858,6 @@ export interface IListMemberReply { } export interface IListMemberRoleWithOpRange { - member_group?: IProjectMemberGroup; - - op_permissions?: IUidWithName[]; - op_range_type?: ListMemberRoleWithOpRangeOpRangeTypeEnum; range_uids?: IUidWithName[]; @@ -2182,6 +2199,52 @@ export interface IOperation { operation_type?: OperationOperationTypeEnum; } +export interface IOperationRecord { + operation_action?: string; + + operation_i18n_content?: II18nStr; + + operation_project_name?: string; + + operation_req_ip?: string; + + operation_status?: string; + + operation_time?: string; + + operation_type_name?: string; + + operation_user_agent?: string; + + operation_user_name?: string; +} + +export interface IOperationRecordListItem { + id?: number; + + operation_action?: string; + + operation_content?: string; + + operation_time?: string; + + operation_type_name?: string; + + operation_user?: IOperationUser; + + operation_user_agent?: string; + + project_name?: string; + + status?: OperationRecordListItemStatusEnum; +} + +export interface IOperationUser { + ip?: string; + + user_name?: string; +} + export interface IParam { desc?: string; diff --git a/packages/shared/lib/api/base/service/common.enum.ts b/packages/shared/lib/api/base/service/common.enum.ts index 2074d5bea..51abaeff8 100644 --- a/packages/shared/lib/api/base/service/common.enum.ts +++ b/packages/shared/lib/api/base/service/common.enum.ts @@ -312,6 +312,12 @@ export enum OperationOperationTypeEnum { 'SQL' = 'SQL' } +export enum OperationRecordListItemStatusEnum { + 'succeeded' = 'succeeded', + + 'failed' = 'failed' +} + export enum ProjectInfoProjectPriorityEnum { 'high' = 'high', diff --git a/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/data.ts b/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/data.ts index 1fdd564f7..cce92f635 100644 --- a/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/data.ts +++ b/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/data.ts @@ -1,11 +1,11 @@ import { - IOperationRecordList, IOperationTypeNameList, IOperationActionList } from '../../../../api/sqle/service/common'; -import { OperationRecordListStatusEnum } from '../../../../api/sqle/service/common.enum'; +import { IOperationRecordListItem } from '../../../../api/base/service/common'; +import { OperationRecordListItemStatusEnum } from '../../../../api/base/service/common.enum'; -export const operationRecordListMockData: IOperationRecordList[] = [ +export const operationRecordListMockData: IOperationRecordListItem[] = [ { id: 54, operation_time: '2024-01-03T11:28:34+08:00', @@ -17,7 +17,9 @@ export const operationRecordListMockData: IOperationRecordList[] = [ operation_action: '编辑流程模板', operation_content: '编辑流程模板', project_name: 'default', - status: OperationRecordListStatusEnum.succeeded + status: OperationRecordListItemStatusEnum.succeeded, + operation_user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36' }, { id: 53, @@ -29,8 +31,10 @@ export const operationRecordListMockData: IOperationRecordList[] = [ operation_type_name: '流程模板', operation_action: '编辑流程模板', operation_content: '编辑流程模板', - project_name: 'default', - status: OperationRecordListStatusEnum.failed + project_name: '', + status: OperationRecordListItemStatusEnum.failed, + operation_user_agent: + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36' } ]; diff --git a/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/index.ts b/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/index.ts index 950dba0e0..6e4e1c07e 100644 --- a/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/index.ts +++ b/packages/shared/lib/testUtil/mockApi/sqle/operationRecord/index.ts @@ -1,4 +1,5 @@ import operationRecord from '../../../../api/sqle/service/OperationRecord'; +import baseOperationRecord from '../../../../api/base/service/OperationRecord'; import { MockSpyApy, createSpySuccessResponse } from '../../common'; import { operationRecordListMockData, @@ -15,7 +16,7 @@ class MockOperationRecordApi implements MockSpyApy { } public getOperationRecordList() { - const spy = jest.spyOn(operationRecord, 'getOperationRecordListV1'); + const spy = jest.spyOn(baseOperationRecord, 'GetOperationRecordList'); spy.mockImplementation(() => createSpySuccessResponse({ data: operationRecordListMockData, @@ -26,7 +27,7 @@ class MockOperationRecordApi implements MockSpyApy { } public exportOperationRecordList() { - const spy = jest.spyOn(operationRecord, 'getExportOperationRecordListV1'); + const spy = jest.spyOn(baseOperationRecord, 'ExportOperationRecordList'); spy.mockImplementation(() => createSpySuccessResponse({})); return spy; } diff --git a/packages/sqle/src/locale/zh-CN/menu.ts b/packages/sqle/src/locale/zh-CN/menu.ts index d3ba37278..55860fc3f 100644 --- a/packages/sqle/src/locale/zh-CN/menu.ts +++ b/packages/sqle/src/locale/zh-CN/menu.ts @@ -28,7 +28,7 @@ export default { projectOverview: '项目概览', allInstanceType: '所有数据库类型', syncDataSource: '外部数据源同步', - operationRecord: 'SQLE操作记录', + operationRecord: '操作记录', sqlManagement: 'SQL管控', sqlAudit: 'SQL审核', pluginAudit: 'IDE审核' diff --git a/packages/sqle/src/page/OperationRecord/List/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/OperationRecord/List/__snapshots__/index.test.tsx.snap index 292d6edf1..a9f80beae 100644 --- a/packages/sqle/src/page/OperationRecord/List/__snapshots__/index.test.tsx.snap +++ b/packages/sqle/src/page/OperationRecord/List/__snapshots__/index.test.tsx.snap @@ -10,7 +10,7 @@ exports[`sqle/OperationRecord/List render action when filter item show 1`] = `
- SQLE操作记录 + 操作记录
-
-
-
- - - - - - - 操作类型 - - - 请选择{{name}} - - - -
-
-
- 操作内容 + 项目 - - - + + + - 操作内容 + + UserAgent + + + 项目 + + +
+   +
+ + +
+   +
+ 编辑流程模板 + +
+ Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 +
+ + + +
+ + +
+ + + default + @@ -577,6 +625,91 @@ exports[`sqle/OperationRecord/List render action when filter item show 1`] = ` > 编辑流程模板 + +
+ Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 +
+ + + +
+ + +
+ + + - + @@ -775,7 +908,7 @@ exports[`sqle/OperationRecord/List render operation record table when request re
- SQLE操作记录 + 操作记录
- - - + + + - 操作内容 + + UserAgent + + + 项目 + + +
+   +
+ + +
+   +
+ 编辑流程模板 + +
+ Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 +
+ + + +
+ + +
+ + + default + @@ -1155,6 +1394,91 @@ exports[`sqle/OperationRecord/List render operation record table when request re > 编辑流程模板 + +
+ Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 +
+ + + +
+ + +
+ + + - + @@ -1353,7 +1677,7 @@ exports[`sqle/OperationRecord/List render table when request return error 1`] =
- SQLE操作记录 + 操作记录
- - - + + + - 操作内容 + + UserAgent + + + 项目 + - - - - 2024-01-03 11:28:34 - - - admin 192.168.22.31 - - 流程模板 - - - 编辑流程模板 +
+   +
- - - - - - 成功 - +  
- 2024-01-03 11:27:27 - - - admin 192.168.22.33 - - - 流程模板 - - - 编辑流程模板 - -
- - - - - 失败 - -
+ class="ant-table-expanded-row-fixed" + style="width: 0px; position: sticky; left: 0px; overflow: hidden;" + /> @@ -1763,156 +2017,6 @@ exports[`sqle/OperationRecord/List render table when request return error 1`] =
-
    -
  • - - 共 2 条数据 - -
  • -
  • - -
  • -
  • - - 1 - -
  • -
  • - -
  • -
  • - -
  • -
diff --git a/packages/sqle/src/page/OperationRecord/List/column.tsx b/packages/sqle/src/page/OperationRecord/List/column.tsx index deecb6e44..beaab71d1 100644 --- a/packages/sqle/src/page/OperationRecord/List/column.tsx +++ b/packages/sqle/src/page/OperationRecord/List/column.tsx @@ -1,20 +1,20 @@ -import { formatTime } from '@actiontech/dms-kit'; -import { IOperationRecordList } from '@actiontech/shared/lib/api/sqle/service/common'; +import { formatTime, BasicTypographyEllipsis } from '@actiontech/dms-kit'; +import { IOperationRecordListItem } from '@actiontech/shared/lib/api/base/service/common'; import { ActiontechTableColumn, PageInfoWithoutIndexAndSize } from '@actiontech/dms-kit/es/components/ActiontechTable'; -import { IGetOperationRecordListV1Params } from '@actiontech/shared/lib/api/sqle/service/OperationRecord/index.d'; +import { IGetOperationRecordListParams } from '@actiontech/shared/lib/api/base/service/OperationRecord/index.d'; import { t } from '../../../locale'; import OperationStatus from '../components/OperationStatus'; export type OperationRecordListFilterParamType = PageInfoWithoutIndexAndSize< - IGetOperationRecordListV1Params, - 'filter_operate_project_name' | 'fuzzy_search_operate_user_name' + IGetOperationRecordListParams, + 'fuzzy_search_operate_user_name' >; export const OperationRecordListColumn: ActiontechTableColumn< - IOperationRecordList, + IOperationRecordListItem, OperationRecordListFilterParamType > = [ { @@ -24,8 +24,7 @@ export const OperationRecordListColumn: ActiontechTableColumn< return formatTime(time); }, filterCustomType: 'date-range', - filterKey: ['filter_operate_time_from', 'filter_operate_time_to'], - width: 300 + filterKey: ['filter_operate_time_from', 'filter_operate_time_to'] }, { dataIndex: 'operation_user', @@ -36,34 +35,42 @@ export const OperationRecordListColumn: ActiontechTableColumn< return '-'; } return `${userInfo.user_name ?? ''} ${userInfo.ip ?? ''}`; - }, - width: 300 + } }, { dataIndex: 'operation_type_name', - title: () => t('operationRecord.list.column.operationType'), - filterCustomType: 'select', - filterKey: 'filter_operate_type_name', - width: 300 + title: () => t('operationRecord.list.column.operationType') + // filterCustomType: 'select', + // filterKey: 'filter_operate_type_name', }, { dataIndex: 'operation_content', title: () => t('operationRecord.list.column.operationAction'), - filterCustomType: 'select', - filterKey: 'filter_operate_action', + // filterCustomType: 'select', + // filterKey: 'filter_operate_action', width: 600 }, - // todo: 后期可能会迁移,目前在sqle里先隐藏 - // { - // dataIndex: 'project_name', - // title: () => t('operationRecord.list.column.projectName'), - // render(name?: string) { - // if (!name) { - // return '--'; - // } - // return name; - // } - // }, + + { + dataIndex: 'operation_user_agent', + title: () => 'UserAgent', + className: 'ellipsis-column-width', + render: (userAgent?: string) => { + return ; + } + }, + { + dataIndex: 'project_name', + title: () => t('operationRecord.list.column.projectName'), + render(name?: string) { + if (!name) { + return '-'; + } + return name; + }, + filterCustomType: 'select', + filterKey: 'filter_operate_project_name' + }, { dataIndex: 'status', title: () => t('operationRecord.list.column.status'), @@ -72,7 +79,6 @@ export const OperationRecordListColumn: ActiontechTableColumn< return '-'; } return ; - }, - width: 180 + } } ]; diff --git a/packages/sqle/src/page/OperationRecord/List/index.test.tsx b/packages/sqle/src/page/OperationRecord/List/index.test.tsx index 505ac4969..8d1873193 100644 --- a/packages/sqle/src/page/OperationRecord/List/index.test.tsx +++ b/packages/sqle/src/page/OperationRecord/List/index.test.tsx @@ -4,7 +4,6 @@ import OperationRecordList from '.'; import operationRecord from '@actiontech/shared/lib/testUtil/mockApi/sqle/operationRecord'; import { operationRecordListMockData } from '@actiontech/shared/lib/testUtil/mockApi/sqle/operationRecord/data'; import { mockUseCurrentProject } from '@actiontech/shared/lib/testUtil/mockHook/mockUseCurrentProject'; -import { mockProjectInfo } from '@actiontech/shared/lib/testUtil/mockHook/data'; import { createSpyErrorResponse } from '@actiontech/shared/lib/testUtil/mockApi'; import { getAllBySelector, @@ -24,28 +23,28 @@ describe('sqle/OperationRecord/List', () => { }); it('render operation record table when request return data', async () => { - const operationRecordListSpy = operationRecord.getOperationActionList(); - const actionSpy = operationRecord.getOperationActionList(); - const typeNameSpy = operationRecord.getOperationTypeNameList(); + const operationRecordListSpy = operationRecord.getOperationRecordList(); + // const actionSpy = operationRecord.getOperationActionList(); + // const typeNameSpy = operationRecord.getOperationTypeNameList(); const { baseElement } = superRender(); await act(async () => jest.advanceTimersByTime(3000)); expect(baseElement).toMatchSnapshot(); expect(operationRecordListSpy).toHaveBeenCalledTimes(1); - expect(actionSpy).toHaveBeenCalledTimes(1); - expect(typeNameSpy).toHaveBeenCalledTimes(1); + // expect(actionSpy).toHaveBeenCalledTimes(1); + // expect(typeNameSpy).toHaveBeenCalledTimes(1); expect( screen.getByText(`共 ${operationRecordListMockData.length} 条数据`) ).toBeInTheDocument(); }); it('render table when request return error', async () => { - const operationRecordListSpy = operationRecord.getOperationActionList(); + const operationRecordListSpy = operationRecord.getOperationRecordList(); operationRecordListSpy.mockImplementationOnce(() => createSpyErrorResponse({ message: 'error info' }) ); const { baseElement } = superRender(); await act(async () => jest.advanceTimersByTime(3000)); - expect(screen.getByText('SQLE操作记录')).toBeInTheDocument(); + expect(screen.getByText('操作记录')).toBeInTheDocument(); expect(baseElement).toMatchSnapshot(); }); @@ -75,7 +74,6 @@ describe('sqle/OperationRecord/List', () => { await act(async () => jest.advanceTimersByTime(3000)); expect(operationRecordListSpy).toHaveBeenCalled(); expect(operationRecordListSpy).toHaveBeenCalledWith({ - filter_operate_project_name: mockProjectInfo.projectName, fuzzy_search_operate_user_name: 'test', page_index: 1, page_size: 20 @@ -83,7 +81,7 @@ describe('sqle/OperationRecord/List', () => { }); it('render action when filter item show', async () => { - const operationRecordListSpy = operationRecord.getOperationActionList(); + const operationRecordListSpy = operationRecord.getOperationRecordList(); const { baseElement } = superRender(); await act(async () => jest.advanceTimersByTime(3000)); expect(operationRecordListSpy).toHaveBeenCalledTimes(1); @@ -94,7 +92,7 @@ describe('sqle/OperationRecord/List', () => { '.actiontech-table-filter-container-namespace .ant-space-item', baseElement ); - expect(filterItems.length).toBe(3); + expect(filterItems.length).toBe(2); expect(baseElement).toMatchSnapshot(); }); @@ -108,7 +106,6 @@ describe('sqle/OperationRecord/List', () => { expect(exportListSpy).toHaveBeenCalledTimes(1); expect(exportListSpy).toHaveBeenCalledWith( { - filter_operate_project_name: mockProjectInfo.projectName, fuzzy_search_operate_user_name: '' }, { diff --git a/packages/sqle/src/page/OperationRecord/List/index.tsx b/packages/sqle/src/page/OperationRecord/List/index.tsx index 6dc87a811..c5f2b12f3 100644 --- a/packages/sqle/src/page/OperationRecord/List/index.tsx +++ b/packages/sqle/src/page/OperationRecord/List/index.tsx @@ -1,14 +1,14 @@ -import { useMemo, useState, useEffect } from 'react'; +import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { Space, message } from 'antd'; import { useRequest, useBoolean } from 'ahooks'; import { BasicButton, PageHeader } from '@actiontech/dms-kit'; -import operationRecord from '@actiontech/shared/lib/api/sqle/service/OperationRecord'; +import operationRecord from '@actiontech/shared/lib/api/base/service/OperationRecord'; import { IGetOperationRecordListV1Params, IGetExportOperationRecordListV1Params } from '@actiontech/shared/lib/api/sqle/service/OperationRecord/index.d'; -import { IOperationRecordList } from '@actiontech/shared/lib/api/sqle/service/common'; +import { IOperationRecordListItem } from '@actiontech/shared/lib/api/base/service/common'; import { ActiontechTable, useTableRequestParams, @@ -18,29 +18,29 @@ import { FilterCustomProps, TableToolbar } from '@actiontech/dms-kit/es/components/ActiontechTable'; -import { useCurrentProject } from '@actiontech/shared/lib/features'; +import { useCurrentUser } from '@actiontech/shared/lib/features'; import { OperationRecordListColumn, OperationRecordListFilterParamType } from './column'; -import useOperationTypeName from '../../../hooks/useOperationTypeName'; -import useOperationActions from '../../../hooks/useOperationActions'; +// import useOperationTypeName from '../../../hooks/useOperationTypeName'; +// import useOperationActions from '../../../hooks/useOperationActions'; import { ResponseCode } from '../../../data/common'; import { DownArrowLineOutlined } from '@actiontech/icons'; const OperationRecordList: React.FC = () => { const { t } = useTranslation(); const [messageApi, contextHolder] = message.useMessage(); - const { projectName } = useCurrentProject(); - const [currentOperationTypeName, setCurrentOperationTypeName] = - useState(); + const { bindProjects } = useCurrentUser(); + // const [currentOperationTypeName, setCurrentOperationTypeName] = + // useState(); const [ exportButtonEnableStatus, { setFalse: finishExport, setTrue: startExport } ] = useBoolean(false); - const { updateOperationTypeNameList, operationTypeNameOptions } = - useOperationTypeName(); - const { updateOperationActions, operationActionOptions } = - useOperationActions(); + // const { updateOperationTypeNameList, operationTypeNameOptions } = + // useOperationTypeName(); + // const { updateOperationActions, operationActionOptions } = + // useOperationActions(); const { tableFilterInfo, updateTableFilterInfo, @@ -50,7 +50,7 @@ const OperationRecordList: React.FC = () => { setSearchKeyword, refreshBySearchKeyword } = useTableRequestParams< - IOperationRecordList, + IOperationRecordListItem, OperationRecordListFilterParamType >(); const { requestErrorMessage, handleTableRequestError } = @@ -64,11 +64,10 @@ const OperationRecordList: React.FC = () => { const params: IGetOperationRecordListV1Params = { ...pagination, ...tableFilterInfo, - filter_operate_project_name: projectName, fuzzy_search_operate_user_name: searchKeyword }; return handleTableRequestError( - operationRecord.getOperationRecordListV1(params) + operationRecord.GetOperationRecordList(params) ); }, { @@ -76,7 +75,7 @@ const OperationRecordList: React.FC = () => { } ); const filterCustomProps = useMemo(() => { - return new Map([ + return new Map([ [ 'operation_time', { @@ -84,32 +83,37 @@ const OperationRecordList: React.FC = () => { } ], [ - 'operation_type_name', + 'project_name', { - options: operationTypeNameOptions, - onChange: (value: unknown) => { - setCurrentOperationTypeName(value as string); - } - } - ], - [ - 'operation_content', - { - options: operationActionOptions(currentOperationTypeName) + options: bindProjects.map((v) => ({ + label: v.project_name, + value: v.project_name + })) } ] + // [ + // 'operation_type_name', + // { + // options: operationTypeNameOptions, + // onChange: (value: unknown) => { + // setCurrentOperationTypeName(value as string); + // } + // } + // ], + // [ + // 'operation_content', + // { + // options: operationActionOptions(currentOperationTypeName) + // } + // ] ]); - }, [ - operationTypeNameOptions, - operationActionOptions, - currentOperationTypeName - ]); + }, [bindProjects]); const { filterButtonMeta, filterContainerMeta, updateAllSelectedFilterItem } = useTableFilterContainer(OperationRecordListColumn, updateTableFilterInfo); - useEffect(() => { - updateOperationTypeNameList(); - updateOperationActions(); - }, [updateOperationActions, updateOperationTypeNameList]); + // useEffect(() => { + // updateOperationTypeNameList(); + // updateOperationActions(); + // }, [updateOperationActions, updateOperationTypeNameList]); const onExport = () => { startExport(); const hideLoading = messageApi.loading( @@ -118,11 +122,10 @@ const OperationRecordList: React.FC = () => { ); const param: IGetExportOperationRecordListV1Params = { ...tableFilterInfo, - filter_operate_project_name: projectName, fuzzy_search_operate_user_name: searchKeyword }; operationRecord - .getExportOperationRecordListV1(param, { + .ExportOperationRecordList(param, { responseType: 'blob' }) .then((res) => { diff --git a/packages/sqle/src/page/OperationRecord/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/OperationRecord/__snapshots__/index.test.tsx.snap index 539475fec..134cfe0ac 100644 --- a/packages/sqle/src/page/OperationRecord/__snapshots__/index.test.tsx.snap +++ b/packages/sqle/src/page/OperationRecord/__snapshots__/index.test.tsx.snap @@ -10,7 +10,7 @@ exports[`slqe/OperationRecord should render operation record list 1`] = `
- SQLE操作记录 + 操作记录
- - - + + + - 操作内容 + + UserAgent + + + 项目 + + +
+   +
+ + +
+   +
+
= ({ - status -}) => { +const OperationStatus: React.FC<{ + status: OperationRecordListItemStatusEnum; +}> = ({ status }) => { const { t } = useTranslation(); return ( - {status === OperationRecordListStatusEnum.succeeded ? ( + {status === OperationRecordListItemStatusEnum.succeeded ? ( <> {t('common.success')} diff --git a/packages/sqle/src/page/OperationRecord/components/test/OperationStatus.test.tsx b/packages/sqle/src/page/OperationRecord/components/test/OperationStatus.test.tsx index dd752ea96..96136ec0e 100644 --- a/packages/sqle/src/page/OperationRecord/components/test/OperationStatus.test.tsx +++ b/packages/sqle/src/page/OperationRecord/components/test/OperationStatus.test.tsx @@ -1,14 +1,14 @@ import OperationStatus from '../OperationStatus'; import { superRender } from '@actiontech/shared/lib/testUtil/superRender'; -import { OperationRecordListStatusEnum } from '@actiontech/shared/lib/api/sqle/service/common.enum'; +import { OperationRecordListItemStatusEnum } from '@actiontech/shared/lib/api/base/service/common.enum'; describe('sqle/OperationRecord/OperationStatus', () => { it('should match snap shot', () => { const { baseElement } = superRender( - + ); const { baseElement: baseElement2 } = superRender( - + ); expect(baseElement).toMatchSnapshot(); expect(baseElement2).toMatchSnapshot(); From 6f56213f1f15ee024cf89a9a6ed42de09d81e721 Mon Sep 17 00:00:00 2001 From: zzyangh <799463087@qq.com> Date: Tue, 20 Jan 2026 17:30:24 +0800 Subject: [PATCH 2/5] [feature]: Add global operation record page --- packages/base/src/locale/zh-CN/dmsMenu.ts | 1 + .../UserMenu/components/GlobalSetting.tsx | 22 +- .../__tests__/GlobalSetting.test.tsx | 5 +- .../__snapshots__/GlobalSetting.test.tsx.snap | 24 + .../__snapshots__/router.base.test.tsx.snap | 7 + .../router.ce.base.test.tsx.snap | 7 + .../router.ce.sqle.test.tsx.snap | 10 + .../__snapshots__/router.sqle.test.tsx.snap | 14 + .../src/router/test/router.ce.sqle.test.tsx | 7 + .../base/src/router/test/router.sqle.test.tsx | 7 + packages/dms-kit/docs/CHANGELOG.md | 6 +- packages/dms-kit/package.json | 2 +- packages/dms-kit/src/data/routePaths.ts | 3 + .../sqle/src/locale/zh-CN/operationRecord.ts | 3 +- .../List/__snapshots__/index.test.tsx.snap | 824 ++++++++++++++++-- .../src/page/OperationRecord/List/column.tsx | 3 +- .../page/OperationRecord/List/index.test.tsx | 53 +- .../src/page/OperationRecord/List/index.tsx | 32 +- .../__snapshots__/index.ce.test.tsx.snap | 4 +- .../__snapshots__/index.test.tsx.snap | 26 +- .../page/OperationRecord/index.ce.test.tsx | 13 + .../sqle/src/page/OperationRecord/index.tsx | 13 +- packages/sqle/src/router/config.tsx | 6 + 23 files changed, 994 insertions(+), 98 deletions(-) diff --git a/packages/base/src/locale/zh-CN/dmsMenu.ts b/packages/base/src/locale/zh-CN/dmsMenu.ts index 1e8b73a71..232d307dd 100644 --- a/packages/base/src/locale/zh-CN/dmsMenu.ts +++ b/packages/base/src/locale/zh-CN/dmsMenu.ts @@ -68,6 +68,7 @@ export default { viewRule: '查看规则', ruleManage: '规则管理', system: '系统设置', + globalOperationRecord: '全局操作记录', changeTheme: '模式切换', instanceManager: '数据源管理', knowledge: '知识库' diff --git a/packages/base/src/page/Nav/SideMenu/UserMenu/components/GlobalSetting.tsx b/packages/base/src/page/Nav/SideMenu/UserMenu/components/GlobalSetting.tsx index 859533ddb..3051050d8 100644 --- a/packages/base/src/page/Nav/SideMenu/UserMenu/components/GlobalSetting.tsx +++ b/packages/base/src/page/Nav/SideMenu/UserMenu/components/GlobalSetting.tsx @@ -6,7 +6,8 @@ import { UserShieldFilled, CenterCircleHexagonFilled, DatabaseFilled, - ProfileEditFilled + ProfileEditFilled, + OperateAuditFilled } from '@actiontech/icons'; import { ContextMenuItem } from './ContextMenu/index.type'; import ContextMenu from './ContextMenu'; @@ -16,6 +17,7 @@ import { usePermission } from '@actiontech/shared/lib/features'; import { useTypedNavigate } from '@actiontech/shared'; +import { ROUTE_PATHS } from '@actiontech/dms-kit'; const GlobalSetting: React.FC = () => { const { t } = useTranslation(); @@ -37,14 +39,15 @@ const GlobalSetting: React.FC = () => { key: 'user-center', icon: , text: t('menu.userCenter'), - onClick: () => handleClickItem('/user-center'), + onClick: () => handleClickItem(ROUTE_PATHS.BASE.USER_CENTER), permission: PERMISSIONS.PAGES.BASE.USER_CENTER }, { key: 'data-source-management', icon: , text: t('dmsMenu.globalSettings.instanceManager'), - onClick: () => handleClickItem(`/data-source-management`), + onClick: () => + handleClickItem(ROUTE_PATHS.BASE.DATA_SOURCE_MANAGEMENT.index.path), permission: PERMISSIONS.PAGES.BASE.DATA_SOURCE_MANAGEMENT }, // #if [sqle] @@ -52,15 +55,24 @@ const GlobalSetting: React.FC = () => { key: 'rule-manager', icon: , text: t('dmsMenu.globalSettings.ruleManage'), - onClick: () => handleClickItem('/sqle/rule-manager'), + onClick: () => + handleClickItem(ROUTE_PATHS.SQLE.RULE_MANAGEMENT.index.path), permission: PERMISSIONS.PAGES.SQLE.RULE_MANAGEMENT }, // #endif + { + key: 'operationRecord', + icon: , + text: t('dmsMenu.globalSettings.globalOperationRecord'), + onClick: () => + handleClickItem(ROUTE_PATHS.SQLE.GLOBAL_OPERATION_LOG.index), + permission: PERMISSIONS.PAGES.SQLE.OPERATION_RECORD + }, { key: 'system', icon: , text: t('dmsMenu.globalSettings.system'), - onClick: () => handleClickItem('/system'), + onClick: () => handleClickItem(ROUTE_PATHS.BASE.SYSTEM.index.path), permission: PERMISSIONS.PAGES.BASE.SYSTEM_SETTING } ]; diff --git a/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/GlobalSetting.test.tsx b/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/GlobalSetting.test.tsx index 76b084861..4e72f74d1 100644 --- a/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/GlobalSetting.test.tsx +++ b/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/GlobalSetting.test.tsx @@ -55,7 +55,7 @@ describe('base/page/Nav/SideMenu/GlobalSetting', () => { await act(async () => jest.advanceTimersByTime(500)); expect(baseElement).toMatchSnapshot(); - expect(getAllBySelector('.content-item-text').length).toBe(4); + expect(getAllBySelector('.content-item-text').length).toBe(5); fireEvent.click(screen.getByText('用户中心')); expect(navigateSpy).toHaveBeenNthCalledWith(1, '/user-center'); @@ -68,5 +68,8 @@ describe('base/page/Nav/SideMenu/GlobalSetting', () => { fireEvent.click(screen.getByText('系统设置')); expect(navigateSpy).toHaveBeenNthCalledWith(4, '/system'); + + fireEvent.click(screen.getByText('全局操作记录')); + expect(navigateSpy).toHaveBeenNthCalledWith(5, '/operation-record'); }); }); diff --git a/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/__snapshots__/GlobalSetting.test.tsx.snap b/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/__snapshots__/GlobalSetting.test.tsx.snap index 22d094c80..020203ef2 100644 --- a/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/__snapshots__/GlobalSetting.test.tsx.snap +++ b/packages/base/src/page/Nav/SideMenu/UserMenu/components/__tests__/__snapshots__/GlobalSetting.test.tsx.snap @@ -153,6 +153,30 @@ exports[`base/page/Nav/SideMenu/GlobalSetting render snap when is "checkPagePerm 规则管理
+
+ + + + +
+ 全局操作记录 +
+
diff --git a/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap index d755c2c7d..55b10f5d4 100644 --- a/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap +++ b/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap @@ -343,6 +343,13 @@ exports[`base/router-base-ee render base route data snap 1`] = ` "key": "globalDashboard", "path": "/sqle/global-dashboard", }, + { + "element":
+ operationRecord +
, + "key": "operationRecord", + "path": "/operation-record", + }, { "children": [ { diff --git a/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap index 85d49cecb..8d8c1d157 100644 --- a/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap +++ b/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap @@ -207,6 +207,13 @@ exports[`base/router-base-ce render base route data snap 1`] = ` "key": "globalDashboard", "path": "/sqle/global-dashboard", }, + { + "element":
+ operationRecord +
, + "key": "operationRecord", + "path": "/operation-record", + }, { "children": [ { diff --git a/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap index e50c80294..e0efcbf37 100644 --- a/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap +++ b/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap @@ -156,6 +156,16 @@ exports[`base/router-sqle-ce render sqle project detail router render sqle proje `; +exports[`base/router-sqle-ce render sqle project detail router render sqle project detail router when version is ce render operationRecord 2`] = ` + +
+
+ operationRecord +
+
+ +`; + exports[`base/router-sqle-ce render sqle project detail router render sqle project detail router when version is ce render route dashboard 1`] = `
diff --git a/packages/base/src/router/test/__snapshots__/router.sqle.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.sqle.test.tsx.snap index 51ecb6569..c9586f126 100644 --- a/packages/base/src/router/test/__snapshots__/router.sqle.test.tsx.snap +++ b/packages/base/src/router/test/__snapshots__/router.sqle.test.tsx.snap @@ -228,6 +228,20 @@ exports[`base/router-sqle-ee render sqle project detail router render sqle proje `; +exports[`base/router-sqle-ee render sqle project detail router render sqle project detail router when version is ce render global operationRecord 1`] = ` + +
+
+
+ operationRecord +
+
+
+ +`; + exports[`base/router-sqle-ee render sqle project detail router render sqle project detail router when version is ce render operationRecord 1`] = `
diff --git a/packages/base/src/router/test/router.ce.sqle.test.tsx b/packages/base/src/router/test/router.ce.sqle.test.tsx index 981fecd69..d662fd3e6 100644 --- a/packages/base/src/router/test/router.ce.sqle.test.tsx +++ b/packages/base/src/router/test/router.ce.sqle.test.tsx @@ -382,6 +382,13 @@ describe('base/router-sqle-ce', () => { expect(screen.getByText('operationRecord')).toBeInTheDocument(); }); + it('render operationRecord', () => { + const { baseElement } = customRender([`/operation-record`]); + + expect(baseElement).toMatchSnapshot(); + expect(screen.getByText('operationRecord')).toBeInTheDocument(); + }); + describe('render route sqlManagement', () => { it('render sqlManagement', async () => { const { baseElement } = customRender([ diff --git a/packages/base/src/router/test/router.sqle.test.tsx b/packages/base/src/router/test/router.sqle.test.tsx index baffe5a13..14e8eec6d 100644 --- a/packages/base/src/router/test/router.sqle.test.tsx +++ b/packages/base/src/router/test/router.sqle.test.tsx @@ -448,6 +448,13 @@ describe('base/router-sqle-ee', () => { expect(screen.getByText('operationRecord')).toBeInTheDocument(); }); + it('render global operationRecord', () => { + const { baseElement } = customRender([`/operation-record`]); + + expect(baseElement).toMatchSnapshot(); + expect(screen.getByText('operationRecord')).toBeInTheDocument(); + }); + describe('render route sqlManagement', () => { it('render sqlManagement', async () => { const { baseElement } = customRender([ diff --git a/packages/dms-kit/docs/CHANGELOG.md b/packages/dms-kit/docs/CHANGELOG.md index 263865039..d832c357d 100644 --- a/packages/dms-kit/docs/CHANGELOG.md +++ b/packages/dms-kit/docs/CHANGELOG.md @@ -40,4 +40,8 @@ nav: ## 1.0.5 -- 修复BasicButton样式 \ No newline at end of file +- 修复BasicButton样式 + +## 1.0.6 + +- 添加全局操作记录path \ No newline at end of file diff --git a/packages/dms-kit/package.json b/packages/dms-kit/package.json index f19c1faf0..709542ec3 100644 --- a/packages/dms-kit/package.json +++ b/packages/dms-kit/package.json @@ -1,6 +1,6 @@ { "name": "@actiontech/dms-kit", - "version": "1.0.5", + "version": "1.0.6", "description": "DMS Kit - React UI Components Library", "main": "lib/index.js", "module": "es/index.js", diff --git a/packages/dms-kit/src/data/routePaths.ts b/packages/dms-kit/src/data/routePaths.ts index 34ee411c1..0ce753932 100644 --- a/packages/dms-kit/src/data/routePaths.ts +++ b/packages/dms-kit/src/data/routePaths.ts @@ -335,6 +335,9 @@ export const ROUTE_PATHS = { path: ':projectID/operation-record' } }, + GLOBAL_OPERATION_LOG: { + index: '/operation-record' + }, PLUGIN_AUDIT: { index: { prefix: '/sqle/project', diff --git a/packages/sqle/src/locale/zh-CN/operationRecord.ts b/packages/sqle/src/locale/zh-CN/operationRecord.ts index d042f26e5..293712f0b 100644 --- a/packages/sqle/src/locale/zh-CN/operationRecord.ts +++ b/packages/sqle/src/locale/zh-CN/operationRecord.ts @@ -1,6 +1,7 @@ // eslint-disable-next-line import/no-anonymous-default-export export default { - pageTitle: '操作记录列表', + pageTitle: '操作记录', + globalPageTitle: '全局操作记录', ceTips: '当出现问题或错误时,您可以通过分析操作记录,查看导致问题产生的步骤或操作,以便更好地解决和预防类似问题,保证操作的安全与合规性。', list: { diff --git a/packages/sqle/src/page/OperationRecord/List/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/OperationRecord/List/__snapshots__/index.test.tsx.snap index a9f80beae..fc64dcc06 100644 --- a/packages/sqle/src/page/OperationRecord/List/__snapshots__/index.test.tsx.snap +++ b/packages/sqle/src/page/OperationRecord/List/__snapshots__/index.test.tsx.snap @@ -10,7 +10,7 @@ exports[`sqle/OperationRecord/List render action when filter item show 1`] = `
- 操作记录 + 全局操作记录
- - - - - - + @@ -898,7 +891,7 @@ exports[`sqle/OperationRecord/List render action when filter item show 1`] = ` `; -exports[`sqle/OperationRecord/List render operation record table when request return data 1`] = ` +exports[`sqle/OperationRecord/List render operation record table when project name is exited 1`] = `
@@ -1102,14 +1095,7 @@ exports[`sqle/OperationRecord/List render operation record table when request re - - - - - - + @@ -1144,12 +1130,6 @@ exports[`sqle/OperationRecord/List render operation record table when request re > UserAgent - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- 项目 - - -
-   -
-
- default - @@ -1474,11 +1440,6 @@ exports[`sqle/OperationRecord/List render operation record table when request re - - - @@ -1667,7 +1628,7 @@ exports[`sqle/OperationRecord/List render operation record table when request re `; -exports[`sqle/OperationRecord/List render table when request return error 1`] = ` +exports[`sqle/OperationRecord/List render operation record table when request return data 1`] = `
@@ -1677,7 +1638,7 @@ exports[`sqle/OperationRecord/List render table when request return error 1`] =
- 操作记录 + 全局操作记录
-
+ 操作时间 + + 操作人 + + 操作类型 + + 操作内容 + + UserAgent + + 项目 + + 状态 +
+ 2024-01-03 11:28:34 + + admin 192.168.22.31 + + 流程模板 + + 编辑流程模板 + +
+ Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 +
+ + + +
+ + +
+
+ default + +
+ + + + + + 成功 + +
+
+ 2024-01-03 11:27:27 + + admin 192.168.22.33 + + 流程模板 + + 编辑流程模板 + +
+ Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 +
+ + + +
+ + +
+
+ - + +
+ + + + + 失败 + +
+
+
+
+
+
    +
  • + + 共 2 条数据 + +
  • +
  • + +
  • +
  • + + 1 + +
  • +
  • + +
  • +
  • + +
  • +
+
+
+ + + + +`; + +exports[`sqle/OperationRecord/List render table when request return error 1`] = ` + +
+
+
+
+ 全局操作记录 +
+
+
+
+ +
+
+
+
+
+
+
+
+ + + + + + + + + + + + + +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+ + diff --git a/packages/sqle/src/page/OperationRecord/List/column.tsx b/packages/sqle/src/page/OperationRecord/List/column.tsx index beaab71d1..388a08406 100644 --- a/packages/sqle/src/page/OperationRecord/List/column.tsx +++ b/packages/sqle/src/page/OperationRecord/List/column.tsx @@ -45,10 +45,9 @@ export const OperationRecordListColumn: ActiontechTableColumn< }, { dataIndex: 'operation_content', - title: () => t('operationRecord.list.column.operationAction'), + title: () => t('operationRecord.list.column.operationAction') // filterCustomType: 'select', // filterKey: 'filter_operate_action', - width: 600 }, { diff --git a/packages/sqle/src/page/OperationRecord/List/index.test.tsx b/packages/sqle/src/page/OperationRecord/List/index.test.tsx index 8d1873193..a9de81de3 100644 --- a/packages/sqle/src/page/OperationRecord/List/index.test.tsx +++ b/packages/sqle/src/page/OperationRecord/List/index.test.tsx @@ -9,12 +9,15 @@ import { getAllBySelector, getBySelector } from '@actiontech/shared/lib/testUtil/customQuery'; +import { mockProjectInfo } from '@actiontech/shared/lib/testUtil/mockHook/data'; describe('sqle/OperationRecord/List', () => { beforeEach(() => { jest.useFakeTimers(); operationRecord.mockAllApi(); - mockUseCurrentProject(); + mockUseCurrentProject({ + projectName: undefined + }); }); beforeAll(() => { @@ -30,6 +33,11 @@ describe('sqle/OperationRecord/List', () => { await act(async () => jest.advanceTimersByTime(3000)); expect(baseElement).toMatchSnapshot(); expect(operationRecordListSpy).toHaveBeenCalledTimes(1); + expect(operationRecordListSpy).toHaveBeenNthCalledWith(1, { + page_index: 1, + page_size: 20, + fuzzy_search_operate_user_name: '' + }); // expect(actionSpy).toHaveBeenCalledTimes(1); // expect(typeNameSpy).toHaveBeenCalledTimes(1); expect( @@ -37,6 +45,23 @@ describe('sqle/OperationRecord/List', () => { ).toBeInTheDocument(); }); + it('render operation record table when project name is exited', async () => { + mockUseCurrentProject({ + projectName: mockProjectInfo.projectName + }); + const operationRecordListSpy = operationRecord.getOperationRecordList(); + const { baseElement } = superRender(); + await act(async () => jest.advanceTimersByTime(3000)); + expect(baseElement).toMatchSnapshot(); + expect(operationRecordListSpy).toHaveBeenCalledTimes(1); + expect(operationRecordListSpy).toHaveBeenNthCalledWith(1, { + page_index: 1, + page_size: 20, + filter_operate_project_name: mockProjectInfo.projectName, + fuzzy_search_operate_user_name: '' + }); + }); + it('render table when request return error', async () => { const operationRecordListSpy = operationRecord.getOperationRecordList(); operationRecordListSpy.mockImplementationOnce(() => @@ -44,7 +69,7 @@ describe('sqle/OperationRecord/List', () => { ); const { baseElement } = superRender(); await act(async () => jest.advanceTimersByTime(3000)); - expect(screen.getByText('操作记录')).toBeInTheDocument(); + expect(screen.getByText('全局操作记录')).toBeInTheDocument(); expect(baseElement).toMatchSnapshot(); }); @@ -115,4 +140,28 @@ describe('sqle/OperationRecord/List', () => { await act(async () => jest.advanceTimersByTime(3300)); expect(screen.getByText('操作记录列表导出成功')).toBeInTheDocument(); }); + + it('should export data file when click export button and project name is exited', async () => { + mockUseCurrentProject({ + projectName: mockProjectInfo.projectName + }); + const exportListSpy = operationRecord.exportOperationRecordList(); + superRender(); + await act(async () => jest.advanceTimersByTime(3000)); + fireEvent.click(screen.getByText('导出')); + await act(async () => jest.advanceTimersByTime(300)); + expect(screen.getByText('正在导出操作记录列表...')).toBeInTheDocument(); + expect(exportListSpy).toHaveBeenCalledTimes(1); + expect(exportListSpy).toHaveBeenCalledWith( + { + fuzzy_search_operate_user_name: '', + filter_operate_project_name: mockProjectInfo.projectName + }, + { + responseType: 'blob' + } + ); + await act(async () => jest.advanceTimersByTime(3300)); + expect(screen.getByText('操作记录列表导出成功')).toBeInTheDocument(); + }); }); diff --git a/packages/sqle/src/page/OperationRecord/List/index.tsx b/packages/sqle/src/page/OperationRecord/List/index.tsx index c5f2b12f3..95a3701ba 100644 --- a/packages/sqle/src/page/OperationRecord/List/index.tsx +++ b/packages/sqle/src/page/OperationRecord/List/index.tsx @@ -18,7 +18,10 @@ import { FilterCustomProps, TableToolbar } from '@actiontech/dms-kit/es/components/ActiontechTable'; -import { useCurrentUser } from '@actiontech/shared/lib/features'; +import { + useCurrentProject, + useCurrentUser +} from '@actiontech/shared/lib/features'; import { OperationRecordListColumn, OperationRecordListFilterParamType @@ -30,6 +33,7 @@ import { DownArrowLineOutlined } from '@actiontech/icons'; const OperationRecordList: React.FC = () => { const { t } = useTranslation(); const [messageApi, contextHolder] = message.useMessage(); + const { projectName } = useCurrentProject(); const { bindProjects } = useCurrentUser(); // const [currentOperationTypeName, setCurrentOperationTypeName] = // useState(); @@ -66,6 +70,9 @@ const OperationRecordList: React.FC = () => { ...tableFilterInfo, fuzzy_search_operate_user_name: searchKeyword }; + if (!!projectName) { + params.filter_operate_project_name = projectName; + } return handleTableRequestError( operationRecord.GetOperationRecordList(params) ); @@ -108,8 +115,18 @@ const OperationRecordList: React.FC = () => { // ] ]); }, [bindProjects]); + + const columns = useMemo(() => { + if (!!projectName) { + return OperationRecordListColumn.filter( + (column) => column.dataIndex !== 'project_name' + ); + } + return OperationRecordListColumn; + }, [projectName]); + const { filterButtonMeta, filterContainerMeta, updateAllSelectedFilterItem } = - useTableFilterContainer(OperationRecordListColumn, updateTableFilterInfo); + useTableFilterContainer(columns, updateTableFilterInfo); // useEffect(() => { // updateOperationTypeNameList(); // updateOperationActions(); @@ -124,6 +141,9 @@ const OperationRecordList: React.FC = () => { ...tableFilterInfo, fuzzy_search_operate_user_name: searchKeyword }; + if (!!projectName) { + param.filter_operate_project_name = projectName; + } operationRecord .ExportOperationRecordList(param, { responseType: 'blob' @@ -142,7 +162,11 @@ const OperationRecordList: React.FC = () => {
{contextHolder} { current: pagination.page_index }} loading={loading} - columns={OperationRecordListColumn} + columns={columns} onChange={tableChange} errorMessage={requestErrorMessage} /> diff --git a/packages/sqle/src/page/OperationRecord/__snapshots__/index.ce.test.tsx.snap b/packages/sqle/src/page/OperationRecord/__snapshots__/index.ce.test.tsx.snap index d9e6cb9bf..d795051e8 100644 --- a/packages/sqle/src/page/OperationRecord/__snapshots__/index.ce.test.tsx.snap +++ b/packages/sqle/src/page/OperationRecord/__snapshots__/index.ce.test.tsx.snap @@ -9,7 +9,7 @@ exports[`slqe/OperationRecord CE should match snap shot 1`] = `
- 操作记录列表 + 全局操作记录
- 操作记录列表为企业版功能。如您想使用该功能,可以通过以下链接联系我们。 + 操作记录为企业版功能。如您想使用该功能,可以通过以下链接联系我们。

-
- - - - - + @@ -271,12 +264,6 @@ exports[`slqe/OperationRecord should render operation record list 1`] = ` > UserAgent -
- 项目 - - -
-   -
-
{ test('should match snap shot', async () => { + mockUseCurrentProject({ + projectName: undefined + }); const { baseElement } = superRender(); expect(baseElement).toMatchSnapshot(); expect(screen.queryByText('导出')).not.toBeInTheDocument(); + expect(screen.getByText('全局操作记录')).toBeInTheDocument(); + }); + + test('should match snap shot when project name is exited', async () => { + mockUseCurrentProject({ + projectName: 'test' + }); + superRender(); + expect(screen.getByText('操作记录')).toBeInTheDocument(); }); }); diff --git a/packages/sqle/src/page/OperationRecord/index.tsx b/packages/sqle/src/page/OperationRecord/index.tsx index 949953316..d496f0ffc 100644 --- a/packages/sqle/src/page/OperationRecord/index.tsx +++ b/packages/sqle/src/page/OperationRecord/index.tsx @@ -3,12 +3,23 @@ import { PageHeader } from '@actiontech/dms-kit'; import { EnterpriseFeatureDisplay } from '@actiontech/shared'; import { Typography } from 'antd'; import OperationRecordList from './List'; +import { useCurrentProject } from '@actiontech/shared/lib/features'; + const OperationRecord = () => { const { t } = useTranslation(); + + const { projectName } = useCurrentProject(); + return ( <> {/* #if [ce] */} - + {/* #endif */} + }, + { + path: ROUTE_PATHS.SQLE.GLOBAL_OPERATION_LOG.index, + key: 'operationRecord', + element: , + permission: PERMISSIONS.PAGES.SQLE.OPERATION_RECORD } ]; From b7b8a48ff2f15f6bd46fdf1eb5d0589a250bf93f Mon Sep 17 00:00:00 2001 From: zzyangh <799463087@qq.com> Date: Tue, 20 Jan 2026 17:54:58 +0800 Subject: [PATCH 3/5] [feature]: Add global operation option --- .../sqle/src/locale/zh-CN/operationRecord.ts | 3 ++- .../sqle/src/page/OperationRecord/List/index.tsx | 16 +++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/sqle/src/locale/zh-CN/operationRecord.ts b/packages/sqle/src/locale/zh-CN/operationRecord.ts index 293712f0b..034ac19ac 100644 --- a/packages/sqle/src/locale/zh-CN/operationRecord.ts +++ b/packages/sqle/src/locale/zh-CN/operationRecord.ts @@ -14,7 +14,8 @@ export default { operator: '操作人', operationType: '操作类型', operationAction: '操作内容', - platformOperation: '-- (平台操作)' + platformOperation: '-- (平台操作)', + globalOperation: '全局操作' }, column: { operatingTime: '操作时间', diff --git a/packages/sqle/src/page/OperationRecord/List/index.tsx b/packages/sqle/src/page/OperationRecord/List/index.tsx index 95a3701ba..1a46c2996 100644 --- a/packages/sqle/src/page/OperationRecord/List/index.tsx +++ b/packages/sqle/src/page/OperationRecord/List/index.tsx @@ -92,10 +92,16 @@ const OperationRecordList: React.FC = () => { [ 'project_name', { - options: bindProjects.map((v) => ({ - label: v.project_name, - value: v.project_name - })) + options: [ + { + label: t('operationRecord.list.filterForm.globalOperation'), + value: '' + }, + ...bindProjects.map((v) => ({ + label: v.project_name, + value: v.project_name + })) + ] } ] // [ @@ -114,7 +120,7 @@ const OperationRecordList: React.FC = () => { // } // ] ]); - }, [bindProjects]); + }, [bindProjects, t]); const columns = useMemo(() => { if (!!projectName) { From 6bbf7cf118dad0b2ebcd0cef15a564eca1a0dae4 Mon Sep 17 00:00:00 2001 From: zzyangh <799463087@qq.com> Date: Thu, 22 Jan 2026 14:48:31 +0800 Subject: [PATCH 4/5] [feature]: Modify permission for operation log page --- .../SideMenu/UserMenu/components/GlobalSetting.tsx | 2 +- .../test/__snapshots__/router.base.test.tsx.snap | 4 ++-- .../test/__snapshots__/router.ce.base.test.tsx.snap | 4 ++-- .../test/__snapshots__/router.ce.sqle.test.tsx.snap | 2 +- .../test/__snapshots__/router.sqle.test.tsx.snap | 2 +- .../base/src/router/test/router.ce.sqle.test.tsx | 2 +- packages/base/src/router/test/router.sqle.test.tsx | 2 +- .../__tests__/__snapshots__/index.test.ts.snap | 12 ++++++++++++ .../lib/features/usePermission/permissionManifest.ts | 11 +++++++++++ .../shared/lib/features/usePermission/permissions.ts | 1 + packages/sqle/src/router/config.tsx | 4 ++-- 11 files changed, 35 insertions(+), 11 deletions(-) diff --git a/packages/base/src/page/Nav/SideMenu/UserMenu/components/GlobalSetting.tsx b/packages/base/src/page/Nav/SideMenu/UserMenu/components/GlobalSetting.tsx index 3051050d8..a8346481a 100644 --- a/packages/base/src/page/Nav/SideMenu/UserMenu/components/GlobalSetting.tsx +++ b/packages/base/src/page/Nav/SideMenu/UserMenu/components/GlobalSetting.tsx @@ -66,7 +66,7 @@ const GlobalSetting: React.FC = () => { text: t('dmsMenu.globalSettings.globalOperationRecord'), onClick: () => handleClickItem(ROUTE_PATHS.SQLE.GLOBAL_OPERATION_LOG.index), - permission: PERMISSIONS.PAGES.SQLE.OPERATION_RECORD + permission: PERMISSIONS.PAGES.SQLE.GLOBAL_OPERATION_RECORD }, { key: 'system', diff --git a/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap index 55b10f5d4..12380435e 100644 --- a/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap +++ b/packages/base/src/router/test/__snapshots__/router.base.test.tsx.snap @@ -345,9 +345,9 @@ exports[`base/router-base-ee render base route data snap 1`] = ` }, { "element":
- operationRecord + globalOperationRecord
, - "key": "operationRecord", + "key": "globalOperationRecord", "path": "/operation-record", }, { diff --git a/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap index 8d8c1d157..0e00d46ee 100644 --- a/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap +++ b/packages/base/src/router/test/__snapshots__/router.ce.base.test.tsx.snap @@ -209,9 +209,9 @@ exports[`base/router-base-ce render base route data snap 1`] = ` }, { "element":
- operationRecord + globalOperationRecord
, - "key": "operationRecord", + "key": "globalOperationRecord", "path": "/operation-record", }, { diff --git a/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap index e0efcbf37..f1084a170 100644 --- a/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap +++ b/packages/base/src/router/test/__snapshots__/router.ce.sqle.test.tsx.snap @@ -160,7 +160,7 @@ exports[`base/router-sqle-ce render sqle project detail router render sqle proje
- operationRecord + globalOperationRecord
diff --git a/packages/base/src/router/test/__snapshots__/router.sqle.test.tsx.snap b/packages/base/src/router/test/__snapshots__/router.sqle.test.tsx.snap index c9586f126..aa6ced2bb 100644 --- a/packages/base/src/router/test/__snapshots__/router.sqle.test.tsx.snap +++ b/packages/base/src/router/test/__snapshots__/router.sqle.test.tsx.snap @@ -235,7 +235,7 @@ exports[`base/router-sqle-ee render sqle project detail router render sqle proje data-test-parent-id="availabilityZoneWrapper" >
- operationRecord + globalOperationRecord
diff --git a/packages/base/src/router/test/router.ce.sqle.test.tsx b/packages/base/src/router/test/router.ce.sqle.test.tsx index d662fd3e6..e1063b394 100644 --- a/packages/base/src/router/test/router.ce.sqle.test.tsx +++ b/packages/base/src/router/test/router.ce.sqle.test.tsx @@ -386,7 +386,7 @@ describe('base/router-sqle-ce', () => { const { baseElement } = customRender([`/operation-record`]); expect(baseElement).toMatchSnapshot(); - expect(screen.getByText('operationRecord')).toBeInTheDocument(); + expect(screen.getByText('globalOperationRecord')).toBeInTheDocument(); }); describe('render route sqlManagement', () => { diff --git a/packages/base/src/router/test/router.sqle.test.tsx b/packages/base/src/router/test/router.sqle.test.tsx index 14e8eec6d..914183510 100644 --- a/packages/base/src/router/test/router.sqle.test.tsx +++ b/packages/base/src/router/test/router.sqle.test.tsx @@ -452,7 +452,7 @@ describe('base/router-sqle-ee', () => { const { baseElement } = customRender([`/operation-record`]); expect(baseElement).toMatchSnapshot(); - expect(screen.getByText('operationRecord')).toBeInTheDocument(); + expect(screen.getByText('globalOperationRecord')).toBeInTheDocument(); }); describe('render route sqlManagement', () => { diff --git a/packages/shared/lib/features/usePermission/__tests__/__snapshots__/index.test.ts.snap b/packages/shared/lib/features/usePermission/__tests__/__snapshots__/index.test.ts.snap index 7f822d835..6839c6301 100644 --- a/packages/shared/lib/features/usePermission/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/shared/lib/features/usePermission/__tests__/__snapshots__/index.test.ts.snap @@ -250,6 +250,7 @@ exports[`usePermission should match snapshot 1`] = ` "USER_CENTER": "page:user_center", }, "SQLE": { + "GLOBAL_OPERATION_RECORD": "page:global_operation_record", "KNOWLEDGE": "page:knowledge", "OPERATION_RECORD": "page:operation_record", "PROJECT_RULE_TEMPLATE": "page:project_rule_template", @@ -1714,6 +1715,16 @@ exports[`usePermission should match snapshot 2`] = ` ], "type": "page", }, + "page:global_operation_record": { + "id": "page:global_operation_record", + "role": [ + "admin", + "systemAdministrator", + "auditAdministrator", + "certainProjectManager", + ], + "type": "page", + }, "page:knowledge": { "id": "page:knowledge", "moduleSupport": [ @@ -1733,6 +1744,7 @@ exports[`usePermission should match snapshot 2`] = ` }, "page:operation_record": { "id": "page:operation_record", + "projectPermission": "project_admin", "role": [ "admin", "systemAdministrator", diff --git a/packages/shared/lib/features/usePermission/permissionManifest.ts b/packages/shared/lib/features/usePermission/permissionManifest.ts index 49dd88dd2..6c1575530 100644 --- a/packages/shared/lib/features/usePermission/permissionManifest.ts +++ b/packages/shared/lib/features/usePermission/permissionManifest.ts @@ -114,6 +114,17 @@ export const PERMISSION_MANIFEST: Record< SystemRole.admin, SystemRole.systemAdministrator, SystemRole.auditAdministrator + ], + projectPermission: OpPermissionItemOpPermissionTypeEnum.project_admin + }, + [PERMISSIONS.PAGES.SQLE.GLOBAL_OPERATION_RECORD]: { + id: PERMISSIONS.PAGES.SQLE.GLOBAL_OPERATION_RECORD, + type: 'page', + role: [ + SystemRole.admin, + SystemRole.systemAdministrator, + SystemRole.auditAdministrator, + SystemRole.certainProjectManager ] }, [PERMISSIONS.PAGES.SQLE.SQL_OPTIMIZATION]: { diff --git a/packages/shared/lib/features/usePermission/permissions.ts b/packages/shared/lib/features/usePermission/permissions.ts index 90eadafcd..befae38d3 100644 --- a/packages/shared/lib/features/usePermission/permissions.ts +++ b/packages/shared/lib/features/usePermission/permissions.ts @@ -12,6 +12,7 @@ export const PERMISSIONS = { }, SQLE: { OPERATION_RECORD: 'page:operation_record', + GLOBAL_OPERATION_RECORD: 'page:global_operation_record', SQL_OPTIMIZATION: 'page:sql_optimization', REPORT_STATISTICS: 'page:report_statistics', RULE_MANAGEMENT: 'page:rule_management', diff --git a/packages/sqle/src/router/config.tsx b/packages/sqle/src/router/config.tsx index f42c38633..be355a570 100644 --- a/packages/sqle/src/router/config.tsx +++ b/packages/sqle/src/router/config.tsx @@ -586,8 +586,8 @@ export const globalRouterConfig: RouterConfigItem[] = [ }, { path: ROUTE_PATHS.SQLE.GLOBAL_OPERATION_LOG.index, - key: 'operationRecord', + key: 'globalOperationRecord', element: , - permission: PERMISSIONS.PAGES.SQLE.OPERATION_RECORD + permission: PERMISSIONS.PAGES.SQLE.GLOBAL_OPERATION_RECORD } ]; From cdc3680e913957069af3463843b7706652270b85 Mon Sep 17 00:00:00 2001 From: zzyangh <799463087@qq.com> Date: Thu, 22 Jan 2026 15:53:06 +0800 Subject: [PATCH 5/5] [feature]: Add permission for operation log filter --- .../page/OperationRecord/List/index.test.tsx | 52 ++++++++++++++++++- .../src/page/OperationRecord/List/index.tsx | 39 +++++++++----- 2 files changed, 78 insertions(+), 13 deletions(-) diff --git a/packages/sqle/src/page/OperationRecord/List/index.test.tsx b/packages/sqle/src/page/OperationRecord/List/index.test.tsx index a9de81de3..8e40a033e 100644 --- a/packages/sqle/src/page/OperationRecord/List/index.test.tsx +++ b/packages/sqle/src/page/OperationRecord/List/index.test.tsx @@ -10,6 +10,7 @@ import { getBySelector } from '@actiontech/shared/lib/testUtil/customQuery'; import { mockProjectInfo } from '@actiontech/shared/lib/testUtil/mockHook/data'; +import { mockUseCurrentUser } from '@actiontech/shared/lib/testUtil'; describe('sqle/OperationRecord/List', () => { beforeEach(() => { @@ -18,6 +19,7 @@ describe('sqle/OperationRecord/List', () => { mockUseCurrentProject({ projectName: undefined }); + mockUseCurrentUser(); }); beforeAll(() => { @@ -112,13 +114,61 @@ describe('sqle/OperationRecord/List', () => { expect(operationRecordListSpy).toHaveBeenCalledTimes(1); fireEvent.click(screen.getByText('筛选')); - await act(async () => jest.advanceTimersByTime(300)); + await act(async () => jest.advanceTimersByTime(0)); const filterItems = getAllBySelector( '.actiontech-table-filter-container-namespace .ant-space-item', baseElement ); expect(filterItems.length).toBe(2); expect(baseElement).toMatchSnapshot(); + + fireEvent.mouseDown(getBySelector('.ant-select-selector', filterItems[1])); + await act(async () => jest.advanceTimersByTime(0)); + expect( + getAllBySelector('.ant-select-item-option', baseElement).length + ).toBe(3); + }); + + it('render project filter options when user is project manager', async () => { + mockUseCurrentUser({ + bindProjects: [ + { + is_manager: true, + project_name: 'default', + project_id: '1', + archived: false + }, + { + is_manager: false, + project_name: 'test', + project_id: '2', + archived: false + } + ], + userRoles: { + admin: false, + certainProjectManager: true, + systemAdministrator: false, + auditAdministrator: false, + projectDirector: false + } + }); + const operationRecordListSpy = operationRecord.getOperationRecordList(); + const { baseElement } = superRender(); + await act(async () => jest.advanceTimersByTime(3000)); + expect(operationRecordListSpy).toHaveBeenCalledTimes(1); + + fireEvent.click(screen.getByText('筛选')); + await act(async () => jest.advanceTimersByTime(0)); + const filterItems = getAllBySelector( + '.actiontech-table-filter-container-namespace .ant-space-item', + baseElement + ); + fireEvent.mouseDown(getBySelector('.ant-select-selector', filterItems[1])); + await act(async () => jest.advanceTimersByTime(0)); + expect( + getAllBySelector('.ant-select-item-option', baseElement).length + ).toBe(1); }); it('should export data file when click export button', async () => { diff --git a/packages/sqle/src/page/OperationRecord/List/index.tsx b/packages/sqle/src/page/OperationRecord/List/index.tsx index 1a46c2996..06ddec731 100644 --- a/packages/sqle/src/page/OperationRecord/List/index.tsx +++ b/packages/sqle/src/page/OperationRecord/List/index.tsx @@ -34,7 +34,7 @@ const OperationRecordList: React.FC = () => { const { t } = useTranslation(); const [messageApi, contextHolder] = message.useMessage(); const { projectName } = useCurrentProject(); - const { bindProjects } = useCurrentUser(); + const { bindProjects, userRoles } = useCurrentUser(); // const [currentOperationTypeName, setCurrentOperationTypeName] = // useState(); const [ @@ -82,6 +82,30 @@ const OperationRecordList: React.FC = () => { } ); const filterCustomProps = useMemo(() => { + let operationOptions; + if ( + userRoles.admin || + userRoles.auditAdministrator || + userRoles.systemAdministrator + ) { + operationOptions = [ + { + label: t('operationRecord.list.filterForm.globalOperation'), + value: '' + }, + ...bindProjects.map((v) => ({ + label: v.project_name, + value: v.project_name + })) + ]; + } else { + operationOptions = bindProjects + .filter((i) => i.is_manager) + .map((v) => ({ + label: v.project_name, + value: v.project_name + })); + } return new Map([ [ 'operation_time', @@ -92,16 +116,7 @@ const OperationRecordList: React.FC = () => { [ 'project_name', { - options: [ - { - label: t('operationRecord.list.filterForm.globalOperation'), - value: '' - }, - ...bindProjects.map((v) => ({ - label: v.project_name, - value: v.project_name - })) - ] + options: operationOptions } ] // [ @@ -120,7 +135,7 @@ const OperationRecordList: React.FC = () => { // } // ] ]); - }, [bindProjects, t]); + }, [bindProjects, t, userRoles]); const columns = useMemo(() => { if (!!projectName) {