update 操作日志完善
This commit is contained in:
@@ -298,7 +298,7 @@ export default class QueryTable extends Component {
|
||||
columns: (() => {
|
||||
const c = []
|
||||
if (type !== 'tree' && rowNumber & !expandable & !expandedRowRender) {
|
||||
c.push(rowNoColumn)
|
||||
//c.push(rowNoColumn)
|
||||
}
|
||||
c.push(...(columns || []))
|
||||
return c.filter(p => !p.hidden)
|
||||
|
||||
@@ -1,23 +1,42 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Alert, Button, Card, Descriptions, Form, Popconfirm, Input, message as Message, Select, DatePicker } from 'antd'
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
Card,
|
||||
Descriptions,
|
||||
Form,
|
||||
Popconfirm,
|
||||
Input,
|
||||
message as Message,
|
||||
Select,
|
||||
DatePicker,
|
||||
Tag,
|
||||
} from 'antd'
|
||||
import { Auth, Container, QueryTable } from 'components'
|
||||
import { api } from 'common/api'
|
||||
import { toCamelCase } from 'util/format'
|
||||
import { isEqual } from 'lodash'
|
||||
import getDictData from 'util/dic'
|
||||
import moment from 'moment'
|
||||
import ReactJson from 'react-json-view'
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
const { RangePicker } = DatePicker
|
||||
|
||||
const apiAction = {
|
||||
page: api.sysOpLogPage,
|
||||
delete: api.sysOpLogDelete
|
||||
delete: api.sysOpLogDelete,
|
||||
}
|
||||
|
||||
const methodColor = {
|
||||
POST: 'orange',
|
||||
GET: 'green',
|
||||
}
|
||||
|
||||
export default class index extends Component {
|
||||
state = {
|
||||
codes: {
|
||||
opType: []
|
||||
}
|
||||
opType: [],
|
||||
},
|
||||
}
|
||||
// 表格实例
|
||||
table = React.createRef()
|
||||
@@ -26,37 +45,54 @@ export default class index extends Component {
|
||||
{
|
||||
title: '日志名称',
|
||||
dataIndex: 'name',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '操作类型',
|
||||
dataIndex: 'opType',
|
||||
render: text => (<>{this.bindCodeValue(text, 'op_type')}</>),
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '是否成功',
|
||||
dataIndex: 'success',
|
||||
render: text => (<> {text ? '是' : '否'}</>),
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: 'ip',
|
||||
dataIndex: 'ip',
|
||||
width: 200,
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '请求地址',
|
||||
dataIndex: 'url',
|
||||
width: 300,
|
||||
sorter: true,
|
||||
render: (text, record) => (
|
||||
<>
|
||||
<Tag color={methodColor[record.reqMethod.toUpperCase()]}>
|
||||
{record.reqMethod}
|
||||
</Tag>{' '}
|
||||
{text}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '是否成功',
|
||||
dataIndex: 'success',
|
||||
width: 100,
|
||||
render: text => (
|
||||
<>
|
||||
{text ? (
|
||||
<span className="text-success">是</span>
|
||||
) : (
|
||||
<span className="text-error">否</span>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: 'ip',
|
||||
dataIndex: 'ip',
|
||||
width: 120,
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '操作时间',
|
||||
dataIndex: 'opTime',
|
||||
width: 140,
|
||||
sorter: true,
|
||||
defaultSortOrder: 'descend',
|
||||
},
|
||||
{
|
||||
title: '操作人',
|
||||
width: 140,
|
||||
dataIndex: 'account',
|
||||
sorter: true,
|
||||
},
|
||||
@@ -66,9 +102,9 @@ export default class index extends Component {
|
||||
* 阻止外部组件引发的渲染,提升性能
|
||||
* 可自行添加渲染条件
|
||||
* [必要]
|
||||
* @param {*} props
|
||||
* @param {*} state
|
||||
* @returns
|
||||
* @param {*} props
|
||||
* @param {*} state
|
||||
* @returns
|
||||
*/
|
||||
shouldComponentUpdate(props, state) {
|
||||
return !isEqual(this.state, state)
|
||||
@@ -78,29 +114,20 @@ export default class index extends Component {
|
||||
* 加载字典数据,之后开始加载表格数据
|
||||
* 如果必须要加载字典数据,可直接对表格设置autoLoad=true
|
||||
*/
|
||||
componentDidMount() {
|
||||
this.table.current.onLoading()
|
||||
getDictData('op_type').then(res => {
|
||||
this.setState({
|
||||
codes: res
|
||||
}, () => {
|
||||
this.table.current.onLoadData()
|
||||
})
|
||||
})
|
||||
}
|
||||
componentDidMount() {}
|
||||
|
||||
/**
|
||||
* 调用加载数据接口,可在调用前对query进行处理
|
||||
* [异步,必要]
|
||||
* @param {*} params
|
||||
* @param {*} query
|
||||
* @returns
|
||||
* @param {*} params
|
||||
* @param {*} query
|
||||
* @returns
|
||||
*/
|
||||
loadData = async (params, query) => {
|
||||
if (query.dates && query.dates.length) {
|
||||
query.searchBeginTime = moment(query.dates[0]).format('YYYY-MM-DD HH:mm:ss');
|
||||
query.searchEndTime = moment(query.dates[1]).format('YYYY-MM-DD HH:mm:ss');
|
||||
delete query.dates;
|
||||
query.searchBeginTime = moment(query.dates[0]).format('YYYY-MM-DD HH:mm:ss')
|
||||
query.searchEndTime = moment(query.dates[1]).format('YYYY-MM-DD HH:mm:ss')
|
||||
delete query.dates
|
||||
}
|
||||
const { data } = await apiAction.page({
|
||||
...params,
|
||||
@@ -109,16 +136,16 @@ export default class index extends Component {
|
||||
return data
|
||||
}
|
||||
/**
|
||||
* 绑定字典数据
|
||||
* @param {*} code
|
||||
* @param {*} name
|
||||
* @returns
|
||||
*/
|
||||
* 绑定字典数据
|
||||
* @param {*} code
|
||||
* @param {*} name
|
||||
* @returns
|
||||
*/
|
||||
bindCodeValue(code, name) {
|
||||
name = toCamelCase(name)
|
||||
const codes = this.state.codes[name]
|
||||
if (codes) {
|
||||
const c = codes.find((p) => +p.code === code)
|
||||
const c = codes.find(p => +p.code === code)
|
||||
if (c) {
|
||||
return c.value
|
||||
}
|
||||
@@ -129,8 +156,8 @@ export default class index extends Component {
|
||||
/**
|
||||
* 对表格上的操作进行统一处理
|
||||
* [异步]
|
||||
* @param {*} action
|
||||
* @param {*} successMessage
|
||||
* @param {*} action
|
||||
* @param {*} successMessage
|
||||
*/
|
||||
async onAction(action, successMessage) {
|
||||
this.table.current.onLoading()
|
||||
@@ -144,27 +171,27 @@ export default class index extends Component {
|
||||
}
|
||||
|
||||
onOpLogClear() {
|
||||
this.onAction(
|
||||
apiAction.delete(),
|
||||
'清空成功'
|
||||
)
|
||||
this.onAction(apiAction.delete(), '清空成功')
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Container mode="fluid">
|
||||
<br />
|
||||
<Alert closable type="error" message={
|
||||
<>
|
||||
<div>后端bug:任何操作的操作类型都是增加</div>
|
||||
<div>没有记录请求参数.返回结果等信息</div>
|
||||
</>
|
||||
} />
|
||||
<Alert
|
||||
closable
|
||||
type="error"
|
||||
message={
|
||||
<>
|
||||
<div>后端bug:任何操作的操作类型都是增加</div>
|
||||
<div>没有记录请求参数.返回结果等信息</div>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<br />
|
||||
<Card bordered={false}>
|
||||
<QueryTable
|
||||
ref={this.table}
|
||||
autoLoad={false}
|
||||
loadData={this.loadData}
|
||||
columns={this.columns}
|
||||
query={
|
||||
@@ -172,41 +199,23 @@ export default class index extends Component {
|
||||
<Form.Item label="日志名称" name="name">
|
||||
<Input autoComplete="off" placeholder="请输入日志名称" />
|
||||
</Form.Item>
|
||||
<Form.Item label="操作类型" name="opType">
|
||||
<Select placeholder="请选择操作类型">
|
||||
{
|
||||
this.state.codes.opType.map(item => {
|
||||
return <Select.Option
|
||||
key={item.code}
|
||||
value={+item.code}
|
||||
>{item.value}</Select.Option>
|
||||
})
|
||||
}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item label="是否成功" name="success">
|
||||
<Select placeholder="请选择是否成功" style={{ width: '170px' }}>
|
||||
<Select.Option
|
||||
key='true'
|
||||
>
|
||||
是</Select.Option>
|
||||
<Select.Option
|
||||
key='false'
|
||||
>
|
||||
否</Select.Option>
|
||||
<Select.Option key="true">是</Select.Option>
|
||||
<Select.Option key="false">否</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item label="操作时间" name="dates">
|
||||
<RangePicker
|
||||
showTime={
|
||||
{
|
||||
hideDisabledOptions: true,
|
||||
defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')]
|
||||
}
|
||||
}
|
||||
showTime={{
|
||||
hideDisabledOptions: true,
|
||||
defaultValue: [
|
||||
moment('00:00:00', 'HH:mm:ss'),
|
||||
moment('23:59:59', 'HH:mm:ss'),
|
||||
],
|
||||
}}
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
>
|
||||
</RangePicker>
|
||||
></RangePicker>
|
||||
</Form.Item>
|
||||
</Auth>
|
||||
}
|
||||
@@ -222,8 +231,14 @@ export default class index extends Component {
|
||||
</Auth>
|
||||
}
|
||||
expandable={{
|
||||
expandedRowRender: record =>
|
||||
<Descriptions bordered size="small">
|
||||
expandedRowRender: record => (
|
||||
<Descriptions
|
||||
bordered
|
||||
size="small"
|
||||
style={{ maxWidth: '100%' }}
|
||||
labelStyle={{ width: '150px' }}
|
||||
contentStyle={{ wordBreak: 'break-all' }}
|
||||
>
|
||||
<Descriptions.Item span="1" label="方法名称">
|
||||
{record.methodName}
|
||||
</Descriptions.Item>
|
||||
@@ -240,20 +255,26 @@ export default class index extends Component {
|
||||
{record.className}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item span="3" label="返回结果">
|
||||
{record.result}
|
||||
<ReactJson
|
||||
src={JSON.parse(record.result || '{}')}
|
||||
collapsed
|
||||
/>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item span="3" label="请求参数">
|
||||
{record.param}
|
||||
<ReactJson
|
||||
src={JSON.parse(record.param || '{}')}
|
||||
collapsed
|
||||
/>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item span="3" label="具体消息">
|
||||
{record.message}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
),
|
||||
}}
|
||||
|
||||
/>
|
||||
</Card>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import getDictData from 'util/dic'
|
||||
import FormBody from './form'
|
||||
import RoleForm from './role'
|
||||
import DataForm from './data'
|
||||
import auth from 'components/authorized/handler'
|
||||
|
||||
// 配置页面所需接口函数
|
||||
const apiAction = {
|
||||
@@ -209,25 +210,25 @@ export default class index extends Component {
|
||||
<Auth aut="sysUser:resetPwd">
|
||||
<a onClick={() => this.onResetPassword(record)}>重置密码</a>
|
||||
</Auth>,
|
||||
<Auth auth={{ sysRole: [['grantRole'], ['grantData']] }}>
|
||||
<Auth auth={{ sysUser: [['grantRole'], ['grantData']] }}>
|
||||
<Dropdown
|
||||
placement="bottomRight"
|
||||
overlay={
|
||||
<Menu>
|
||||
<Auth auth="sysRole:grantRole">
|
||||
<Menu.Item>
|
||||
{auth('sysUser:grantRole') && (
|
||||
<Menu.Item key="1">
|
||||
<a onClick={() => this.onOpen(this.roleForm, record)}>
|
||||
授权角色
|
||||
</a>
|
||||
</Menu.Item>
|
||||
</Auth>
|
||||
<Auth auth="sysRole:grantData">
|
||||
<Menu.Item>
|
||||
)}
|
||||
{auth('sysUser:grantData') && (
|
||||
<Menu.Item key="2">
|
||||
<a onClick={() => this.onOpen(this.dataForm, record)}>
|
||||
授权额外数据
|
||||
</a>
|
||||
</Menu.Item>
|
||||
</Auth>
|
||||
)}
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -7,7 +7,7 @@ const defaultState = {
|
||||
}
|
||||
|
||||
const localStorageState = () => {
|
||||
return JSON.parse(window.localStorage.getItem(SETTING_KEY))
|
||||
return JSON.parse(window.localStorage.getItem(SETTING_KEY)) || {}
|
||||
}
|
||||
|
||||
const mergeState = {
|
||||
|
||||
@@ -6,9 +6,8 @@ import store from 'store'
|
||||
const { getState, subscribe } = store
|
||||
|
||||
export default class index extends Component {
|
||||
|
||||
state = {
|
||||
...getState('nav')
|
||||
...getState('nav'),
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
@@ -23,21 +22,25 @@ export default class index extends Component {
|
||||
this.unsubscribe()
|
||||
}
|
||||
|
||||
renderMenu = (menu) => {
|
||||
return menu.map((p) => {
|
||||
renderMenu = menu => {
|
||||
return menu.map(p => {
|
||||
return p.children ? this.renderSubMenu(p) : this.renderMenuItem(p)
|
||||
})
|
||||
}
|
||||
|
||||
renderSubMenu = (menu) => {
|
||||
renderSubMenu = menu => {
|
||||
return (
|
||||
<Menu.SubMenu key={menu.id} title={menu.meta.title} icon={menu.meta.icon && <AntIcon type={menu.meta.icon} />}>
|
||||
<Menu.SubMenu
|
||||
key={menu.id}
|
||||
title={menu.meta.title}
|
||||
icon={menu.meta.icon && <AntIcon type={menu.meta.icon} />}
|
||||
>
|
||||
{this.renderMenu(menu.children)}
|
||||
</Menu.SubMenu>
|
||||
)
|
||||
}
|
||||
|
||||
renderMenuItem = (menu) => {
|
||||
renderMenuItem = menu => {
|
||||
return (
|
||||
<Menu.Item key={menu.id} onClick={() => this.onOpenContentWindow(menu)}>
|
||||
{menu.meta.icon && <AntIcon type={menu.meta.icon} />}
|
||||
@@ -46,12 +49,12 @@ export default class index extends Component {
|
||||
)
|
||||
}
|
||||
|
||||
onOpenContentWindow = (menu) => {
|
||||
onOpenContentWindow = menu => {
|
||||
window.openContentWindow({
|
||||
key: menu.id,
|
||||
title: menu.meta.title,
|
||||
icon: menu.meta.icon,
|
||||
path: menu.component
|
||||
path: menu.component,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -60,12 +63,11 @@ export default class index extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const props = {
|
||||
mode: 'inline',
|
||||
selectable: false,
|
||||
style: this.props.menuStyle,
|
||||
theme: 'light'
|
||||
theme: 'light',
|
||||
}
|
||||
|
||||
const on = {
|
||||
@@ -74,16 +76,20 @@ export default class index extends Component {
|
||||
|
||||
return (
|
||||
<>
|
||||
{
|
||||
this.state.nav.map((item, i) => {
|
||||
{this.state.nav.map((item, i) => {
|
||||
if (item.menu.length) {
|
||||
return (
|
||||
<section key={i}>
|
||||
<div className="yo-sider-nav--app">{item.app.name}</div>
|
||||
<Menu {...props} {...on}>{this.renderMenu(item.menu)}</Menu>
|
||||
<Menu {...props} {...on}>
|
||||
{this.renderMenu(item.menu)}
|
||||
</Menu>
|
||||
</section>
|
||||
)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user