Browse Source

[Feature][UI Next] Add monitor statistics audit log. (#8238)

3.0.0/version-upgrade
songjianet 3 years ago committed by GitHub
parent
commit
c64c66e7cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      dolphinscheduler-ui-next/src/layouts/content/use-dataList.ts
  2. 16
      dolphinscheduler-ui-next/src/locales/modules/en_US.ts
  3. 16
      dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
  4. 9
      dolphinscheduler-ui-next/src/router/modules/monitor.ts
  5. 27
      dolphinscheduler-ui-next/src/service/modules/audit/index.ts
  6. 48
      dolphinscheduler-ui-next/src/service/modules/audit/types.ts
  7. 26
      dolphinscheduler-ui-next/src/views/monitor/statistics/audit-log/index.module.scss
  8. 161
      dolphinscheduler-ui-next/src/views/monitor/statistics/audit-log/index.tsx
  9. 105
      dolphinscheduler-ui-next/src/views/monitor/statistics/audit-log/use-table.ts
  10. 174
      dolphinscheduler-ui-next/src/views/projects/workflow/relation/index.tsx

4
dolphinscheduler-ui-next/src/layouts/content/use-dataList.ts

@ -208,6 +208,10 @@ export function useDataList() {
{ {
label: t('menu.statistics'), label: t('menu.statistics'),
key: `/monitor/statistics` key: `/monitor/statistics`
},
{
label: t('menu.audit_log'),
key: `/monitor/audit-log`
} }
] ]
} }

16
dolphinscheduler-ui-next/src/locales/modules/en_US.ts

@ -65,6 +65,7 @@ const menu = {
db: 'DB', db: 'DB',
statistical_manage: 'Statistical Manage', statistical_manage: 'Statistical Manage',
statistics: 'Statistics', statistics: 'Statistics',
audit_log: 'Audit Log',
tenant_manage: 'Tenant Manage', tenant_manage: 'Tenant Manage',
user_manage: 'User Manage', user_manage: 'User Manage',
alarm_group_manage: 'Alarm Group Manage', alarm_group_manage: 'Alarm Group Manage',
@ -149,6 +150,21 @@ const monitor = {
failure_command_number: 'Failure Command Number', failure_command_number: 'Failure Command Number',
tasks_number_of_waiting_running: 'Tasks Number Of Waiting Running', tasks_number_of_waiting_running: 'Tasks Number Of Waiting Running',
task_number_of_ready_to_kill: 'Task Number Of Ready To Kill' task_number_of_ready_to_kill: 'Task Number Of Ready To Kill'
},
audit_log: {
user_name: 'User Name',
resource_type: 'Resource Type',
project_name: 'Project Name',
operation_type: 'Operation Type',
create_time: 'Create Time',
start_time: 'Start Time',
end_time: 'End Time',
user_audit: 'User Audit',
project_audit: 'Project Audit',
create: 'Create',
update: 'Update',
delete: 'Delete',
read: 'Read'
} }
} }

16
dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts

@ -65,6 +65,7 @@ const menu = {
db: 'DB', db: 'DB',
statistical_manage: '统计管理', statistical_manage: '统计管理',
statistics: 'Statistics', statistics: 'Statistics',
audit_log: '审计日志',
tenant_manage: '租户管理', tenant_manage: '租户管理',
user_manage: '用户管理', user_manage: '用户管理',
alarm_group_manage: '告警组管理', alarm_group_manage: '告警组管理',
@ -150,6 +151,21 @@ const monitor = {
failure_command_number: '执行失败的命令数', failure_command_number: '执行失败的命令数',
tasks_number_of_waiting_running: '待运行任务数', tasks_number_of_waiting_running: '待运行任务数',
task_number_of_ready_to_kill: '待杀死任务数' task_number_of_ready_to_kill: '待杀死任务数'
},
audit_log: {
user_name: '用户名称',
resource_type: '资源类型',
project_name: '项目名称',
operation_type: '操作类型',
create_time: '创建时间',
start_time: '开始时间',
end_time: '结束时间',
user_audit: '用户管理审计',
project_audit: '项目管理审计',
create: '创建',
update: '更新',
delete: '删除',
read: '读取'
} }
} }

9
dolphinscheduler-ui-next/src/router/modules/monitor.ts

@ -64,6 +64,15 @@ export default {
title: '统计管理-Statistics', title: '统计管理-Statistics',
showSide: true showSide: true
} }
},
{
path: '/monitor/audit-log',
name: 'statistics-audit-log',
component: components['monitor-statistics-audit-log'],
meta: {
title: '审计日志-AuditLog',
showSide: true
}
} }
] ]
} }

27
dolphinscheduler-ui-next/src/service/modules/audit/index.ts

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { axios } from '@/service/service'
import type { AuditListReq } from './types'
export function queryAuditLogListPaging(params: AuditListReq): any {
return axios({
url: '/projects/audit/audit-log-list',
method: 'get',
params
})
}

48
dolphinscheduler-ui-next/src/service/modules/audit/types.ts

@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
interface AuditListReq {
pageNo: number
pageSize: number
endDate?: string
moduleType?: string
operationType?: string
processName?: string
projectName?: string
resourceType?: string
startDate?: string
userName?: string
}
interface AuditItem {
userName: string
resource: string
operation: string
time: string
resourceName: string
}
interface AuditListRes {
totalList: AuditItem[]
total: number
totalPage: number
pageSize: number
currentPage: number
start: number
}
export { AuditListReq, AuditListRes }

26
dolphinscheduler-ui-next/src/views/monitor/statistics/audit-log/index.module.scss

@ -0,0 +1,26 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.table-card {
margin-top: 8px;
.pagination {
margin-top: 20px;
display: flex;
justify-content: center;
}
}

161
dolphinscheduler-ui-next/src/views/monitor/statistics/audit-log/index.tsx

@ -0,0 +1,161 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { defineComponent, onMounted, toRefs, watch } from 'vue'
import {
NSpace,
NInput,
NSelect,
NDatePicker,
NButton,
NIcon,
NDataTable,
NPagination,
NCard
} from 'naive-ui'
import { SearchOutlined } from '@vicons/antd'
import { useTable } from './use-table'
import { useI18n } from 'vue-i18n'
import Card from '@/components/card'
import styles from './index.module.scss'
const AuditLog = defineComponent({
name: 'audit-log',
setup() {
const { t, variables, getTableData, createColumns } = useTable()
const requestTableData = () => {
getTableData({
pageSize: variables.pageSize,
pageNo: variables.page,
resourceType: variables.resourceType,
operationType: variables.operationType,
userName: variables.userName,
datePickerRange: variables.datePickerRange
})
}
const onUpdatePageSize = () => {
variables.page = 1
requestTableData()
}
const onSearch = () => {
variables.page = 1
requestTableData()
}
onMounted(() => {
createColumns(variables)
requestTableData()
})
watch(useI18n().locale, () => {
createColumns(variables)
})
return {
t,
...toRefs(variables),
requestTableData,
onUpdatePageSize,
onSearch
}
},
render() {
const { t, requestTableData, onUpdatePageSize, onSearch } = this
return (
<>
<NCard>
<NSpace justify='end'>
<NInput
v-model={[this.userName, 'value']}
size='small'
placeholder={t('monitor.audit_log.user_name')}
clearable
/>
<NSelect
v-model={[this.operationType, 'value']}
size='small'
options={[
{ value: 'CREATE', label: t('monitor.audit_log.create') },
{ value: 'UPDATE', label: t('monitor.audit_log.update') },
{ value: 'DELETE', label: t('monitor.audit_log.delete') },
{ value: 'READ', label: t('monitor.audit_log.read') }
]}
placeholder={t('monitor.audit_log.operation_type')}
style={{ width: '180px' }}
clearable
/>
<NSelect
v-model={[this.resourceType, 'value']}
size='small'
options={[
{
value: 'USER_MODULE',
label: t('monitor.audit_log.user_audit')
},
{
value: 'PROJECT_MODULE',
label: t('monitor.audit_log.project_audit')
}
]}
placeholder={t('monitor.audit_log.resource_type')}
style={{ width: '180px' }}
clearable
/>
<NDatePicker
v-model={[this.datePickerRange, 'value']}
type='datetimerange'
size='small'
start-placeholder={t('monitor.audit_log.start_time')}
end-placeholder={t('monitor.audit_log.end_time')}
clearable
/>
<NButton size='small' type='primary' onClick={onSearch}>
{{
icon: () => (
<NIcon>
<SearchOutlined />
</NIcon>
)
}}
</NButton>
</NSpace>
</NCard>
<Card class={styles['table-card']}>
<NDataTable columns={this.columns} data={this.tableData} />
<div class={styles.pagination}>
<NPagination
v-model:page={this.page}
v-model:page-size={this.pageSize}
page-count={this.totalPage}
show-size-picker
page-sizes={[10, 30, 50]}
show-quick-jumper
onUpdatePage={requestTableData}
onUpdatePageSize={onUpdatePageSize}
/>
</div>
</Card>
</>
)
}
})
export default AuditLog

105
dolphinscheduler-ui-next/src/views/monitor/statistics/audit-log/use-table.ts

@ -0,0 +1,105 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useI18n } from 'vue-i18n'
import { reactive, ref } from 'vue'
import { useAsyncState } from '@vueuse/core'
import { queryAuditLogListPaging } from '@/service/modules/audit'
import { format } from 'date-fns'
import type { AuditListRes } from '@/service/modules/audit/types'
export function useTable() {
const { t } = useI18n()
const variables = reactive({
columns: [],
tableData: [],
page: ref(1),
pageSize: ref(10),
resourceType: ref(null),
operationType: ref(null),
userName: ref(null),
datePickerRange: ref(null),
totalPage: ref(1)
})
const createColumns = (variables: any) => {
variables.columns = [
{
title: '#',
key: 'index'
},
{
title: t('monitor.audit_log.user_name'),
key: 'userName'
},
{
title: t('monitor.audit_log.resource_type'),
key: 'resource'
},
{
title: t('monitor.audit_log.project_name'),
key: 'resourceName'
},
{
title: t('monitor.audit_log.operation_type'),
key: 'operation'
},
{
title: t('monitor.audit_log.create_time'),
key: 'time'
}
]
}
const getTableData = (params: any) => {
const data = {
pageSize: params.pageSize,
pageNo: params.pageNo,
resourceType: params.resourceType,
operationType: params.operationType,
userName: params.userName,
startDate: params.datePickerRange
? format(new Date(params.datePickerRange[0]), 'yyyy-MM-dd HH:mm:ss')
: '',
endDate: params.datePickerRange
? format(new Date(params.datePickerRange[1]), 'yyyy-MM-dd HH:mm:ss')
: ''
}
const { state } = useAsyncState(
queryAuditLogListPaging(data).then((res: AuditListRes) => {
variables.tableData = res.totalList.map((item, index) => {
return {
index: index + 1,
...item
}
}) as any
}),
{}
)
return state
}
return {
t,
variables,
getTableData,
createColumns
}
}

174
dolphinscheduler-ui-next/src/views/projects/workflow/relation/index.tsx

@ -25,98 +25,98 @@ import Card from '@/components/card'
import Graph from './components/Graph' import Graph from './components/Graph'
const workflowRelation = defineComponent({ const workflowRelation = defineComponent({
name: 'workflow-relation', name: 'workflow-relation',
setup() { setup() {
const { t, locale } = useI18n() const { t, locale } = useI18n()
const route = useRoute() const route = useRoute()
const { variables, getWorkflowName, getOneWorkflow, getWorkflowList } = const { variables, getWorkflowName, getOneWorkflow, getWorkflowList } =
useRelation() useRelation()
onMounted(() => { onMounted(() => {
getWorkflowList(Number(route.params.projectCode)) getWorkflowList(Number(route.params.projectCode))
getWorkflowName(Number(route.params.projectCode)) getWorkflowName(Number(route.params.projectCode))
}) })
const handleResetDate = () => { const handleResetDate = () => {
variables.seriesData = [] variables.seriesData = []
variables.workflow && variables.workflow !== 0 variables.workflow && variables.workflow !== 0
? getOneWorkflow( ? getOneWorkflow(
Number(variables.workflow), Number(variables.workflow),
Number(route.params.projectCode) Number(route.params.projectCode)
) )
: getWorkflowList(Number(route.params.projectCode)) : getWorkflowList(Number(route.params.projectCode))
} }
watch( watch(
() => [variables.workflow, variables.labelShow, locale.value], () => [variables.workflow, variables.labelShow, locale.value],
() => { () => {
handleResetDate() handleResetDate()
} }
) )
return { t, handleResetDate, ...toRefs(variables) } return { t, handleResetDate, ...toRefs(variables) }
}, },
render() { render() {
const { t, handleResetDate } = this const { t, handleResetDate } = this
return ( return (
<Card title={t('project.workflow.workflow_relation')}> <Card title={t('project.workflow.workflow_relation')}>
{{ {{
default: () => default: () =>
Object.keys(this.seriesData).length > 0 && ( Object.keys(this.seriesData).length > 0 && (
<Graph seriesData={this.seriesData} labelShow={this.labelShow} /> <Graph seriesData={this.seriesData} labelShow={this.labelShow} />
), ),
'header-extra': () => ( 'header-extra': () => (
<NSpace> <NSpace>
<NSelect <NSelect
clearable clearable
style={{ width: '300px' }} style={{ width: '300px' }}
placeholder={t('project.workflow.workflow_name')} placeholder={t('project.workflow.workflow_name')}
options={this.workflowOptions} options={this.workflowOptions}
v-model={[this.workflow, 'value']} v-model={[this.workflow, 'value']}
/> />
<NTooltip trigger={'hover'}> <NTooltip trigger={'hover'}>
{{ {{
default: () => t('project.workflow.refresh'), default: () => t('project.workflow.refresh'),
trigger: () => ( trigger: () => (
<NButton <NButton
strong strong
secondary secondary
circle circle
type='info' type='info'
onClick={handleResetDate} onClick={handleResetDate}
> >
<NIcon> <NIcon>
<ReloadOutlined /> <ReloadOutlined />
</NIcon> </NIcon>
</NButton> </NButton>
) )
}} }}
</NTooltip> </NTooltip>
<NTooltip trigger={'hover'}> <NTooltip trigger={'hover'}>
{{ {{
default: () => t('project.workflow.show_hide_label'), default: () => t('project.workflow.show_hide_label'),
trigger: () => ( trigger: () => (
<NButton <NButton
strong strong
secondary secondary
circle circle
type='info' type='info'
onClick={() => (this.labelShow = !this.labelShow)} onClick={() => (this.labelShow = !this.labelShow)}
> >
<NIcon> <NIcon>
<EyeOutlined /> <EyeOutlined />
</NIcon> </NIcon>
</NButton> </NButton>
) )
}} }}
</NTooltip> </NTooltip>
</NSpace> </NSpace>
) )
}} }}
</Card> </Card>
) )
} }
}) })
export default workflowRelation export default workflowRelation

Loading…
Cancel
Save