- 修复无法查看原生会话录屏的bug
- 优化列表显示的时间 - 优化获取开发环境的方式
This commit is contained in:
parent
b977b85cdf
commit
11d3dc167b
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ web/build
|
|||||||
*.db
|
*.db
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.eslintcache
|
.eslintcache
|
||||||
|
.env
|
@ -53,9 +53,10 @@ func AssetPagingEndpoint(c echo.Context) error {
|
|||||||
owner := c.QueryParam("owner")
|
owner := c.QueryParam("owner")
|
||||||
sharer := c.QueryParam("sharer")
|
sharer := c.QueryParam("sharer")
|
||||||
userGroupId := c.QueryParam("userGroupId")
|
userGroupId := c.QueryParam("userGroupId")
|
||||||
|
ip := c.QueryParam("ip")
|
||||||
|
|
||||||
account, _ := GetCurrentAccount(c)
|
account, _ := GetCurrentAccount(c)
|
||||||
items, total, err := model.FindPageAsset(pageIndex, pageSize, name, protocol, tags, account, owner, sharer, userGroupId)
|
items, total, err := model.FindPageAsset(pageIndex, pageSize, name, protocol, tags, account, owner, sharer, userGroupId, ip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ func ErrorHandler(next echo.HandlerFunc) echo.HandlerFunc {
|
|||||||
|
|
||||||
func Auth(next echo.HandlerFunc) echo.HandlerFunc {
|
func Auth(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
|
|
||||||
urls := []string{"download", "recording", "login", "static", "favicon", "logo"}
|
urls := []string{"download", "recording", "login", "static", "favicon", "logo", "asciinema"}
|
||||||
|
|
||||||
return func(c echo.Context) error {
|
return func(c echo.Context) error {
|
||||||
// 路由拦截 - 登录身份、资源权限判断等
|
// 路由拦截 - 登录身份、资源权限判断等
|
||||||
|
@ -22,12 +22,12 @@ func OverviewCounterEndPoint(c echo.Context) error {
|
|||||||
asset int64
|
asset int64
|
||||||
)
|
)
|
||||||
if model.TypeUser == account.Type {
|
if model.TypeUser == account.Type {
|
||||||
countUser, _ = model.CountUser()
|
countUser, _ = model.CountOnlineUser()
|
||||||
countOnlineSession, _ = model.CountOnlineSession()
|
countOnlineSession, _ = model.CountOnlineSession()
|
||||||
credential, _ = model.CountCredentialByUserId(account.ID)
|
credential, _ = model.CountCredentialByUserId(account.ID)
|
||||||
asset, _ = model.CountAssetByUserId(account.ID)
|
asset, _ = model.CountAssetByUserId(account.ID)
|
||||||
} else {
|
} else {
|
||||||
countUser, _ = model.CountUser()
|
countUser, _ = model.CountOnlineUser()
|
||||||
countOnlineSession, _ = model.CountOnlineSession()
|
countOnlineSession, _ = model.CountOnlineSession()
|
||||||
credential, _ = model.CountCredential()
|
credential, _ = model.CountCredential()
|
||||||
asset, _ = model.CountAsset()
|
asset, _ = model.CountAsset()
|
||||||
|
@ -63,8 +63,8 @@ func FindAssetByConditions(protocol string, account User) (o []Asset, err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func FindPageAsset(pageIndex, pageSize int, name, protocol, tags string, account User, owner, sharer, userGroupId string) (o []AssetVo, total int64, err error) {
|
func FindPageAsset(pageIndex, pageSize int, name, protocol, tags string, account User, owner, sharer, userGroupId, ip string) (o []AssetVo, total int64, err error) {
|
||||||
db := global.DB.Table("assets").Select("assets.id,assets.name,assets.ip,assets.port,assets.protocol,assets.active,assets.owner,assets.created, users.nickname as owner_name,COUNT(resource_sharers.user_id) as sharer_count").Joins("left join users on assets.owner = users.id").Joins("left join resource_sharers on assets.id = resource_sharers.resource_id").Group("assets.id")
|
db := global.DB.Table("assets").Select("assets.id,assets.name,assets.ip,assets.port,assets.protocol,assets.active,assets.owner,assets.created,assets.tags, users.nickname as owner_name,COUNT(resource_sharers.user_id) as sharer_count").Joins("left join users on assets.owner = users.id").Joins("left join resource_sharers on assets.id = resource_sharers.resource_id").Group("assets.id")
|
||||||
dbCounter := global.DB.Table("assets").Select("DISTINCT assets.id").Joins("left join resource_sharers on assets.id = resource_sharers.resource_id").Group("assets.id")
|
dbCounter := global.DB.Table("assets").Select("DISTINCT assets.id").Joins("left join resource_sharers on assets.id = resource_sharers.resource_id").Group("assets.id")
|
||||||
|
|
||||||
if TypeUser == account.Type {
|
if TypeUser == account.Type {
|
||||||
@ -103,6 +103,11 @@ func FindPageAsset(pageIndex, pageSize int, name, protocol, tags string, account
|
|||||||
dbCounter = dbCounter.Where("assets.name like ?", "%"+name+"%")
|
dbCounter = dbCounter.Where("assets.name like ?", "%"+name+"%")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(ip) > 0 {
|
||||||
|
db = db.Where("assets.ip like ?", "%"+ip+"%")
|
||||||
|
dbCounter = dbCounter.Where("assets.ip like ?", "%"+ip+"%")
|
||||||
|
}
|
||||||
|
|
||||||
if len(protocol) > 0 {
|
if len(protocol) > 0 {
|
||||||
db = db.Where("assets.protocol = ?", protocol)
|
db = db.Where("assets.protocol = ?", protocol)
|
||||||
dbCounter = dbCounter.Where("assets.protocol = ?", protocol)
|
dbCounter = dbCounter.Where("assets.protocol = ?", protocol)
|
||||||
|
@ -107,7 +107,7 @@ func DeleteUserById(id string) {
|
|||||||
global.DB.Where("user_id = ?", id).Delete(&ResourceSharer{})
|
global.DB.Where("user_id = ?", id).Delete(&ResourceSharer{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func CountUser() (total int64, err error) {
|
func CountOnlineUser() (total int64, err error) {
|
||||||
err = global.DB.Find(&User{}).Count(&total).Error
|
err = global.DB.Where("online = ?", true).Find(&User{}).Count(&total).Error
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
8
web/package-lock.json
generated
8
web/package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "next-terminal",
|
"name": "next-terminal",
|
||||||
"version": "0.1.1",
|
"version": "0.2.4",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -5363,9 +5363,9 @@
|
|||||||
"integrity": "sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ=="
|
"integrity": "sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ=="
|
||||||
},
|
},
|
||||||
"dayjs": {
|
"dayjs": {
|
||||||
"version": "1.9.6",
|
"version": "1.10.4",
|
||||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.9.6.tgz",
|
"resolved": "https://registry.npm.taobao.org/dayjs/download/dayjs-1.10.4.tgz?cache=0&sync_timestamp=1611309982734&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdayjs%2Fdownload%2Fdayjs-1.10.4.tgz",
|
||||||
"integrity": "sha512-HngNLtPEBWRo8EFVmHFmSXAjtCX8rGNqeXQI0Gh7wCTSqwaKgPIDqu9m07wABVopNwzvOeCb+2711vQhDlcIXw=="
|
"integrity": "sha1-jlRKm4aD9heD9XCYCoqA6vVKseI="
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
"@ant-design/icons": "^4.3.0",
|
"@ant-design/icons": "^4.3.0",
|
||||||
"antd": "^4.8.4",
|
"antd": "^4.8.4",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
|
"dayjs": "^1.10.4",
|
||||||
"guacamole-common-js": "^1.2.0",
|
"guacamole-common-js": "^1.2.0",
|
||||||
"qs": "^6.9.4",
|
"qs": "^6.9.4",
|
||||||
"react": "^16.14.0",
|
"react": "^16.14.0",
|
||||||
|
@ -1,22 +1,5 @@
|
|||||||
// prod
|
|
||||||
let wsPrefix;
|
|
||||||
if (window.location.protocol === 'https:') {
|
|
||||||
wsPrefix = 'wss:'
|
|
||||||
} else {
|
|
||||||
wsPrefix = 'ws:'
|
|
||||||
}
|
|
||||||
|
|
||||||
export const server = '';
|
|
||||||
export const wsServer = wsPrefix + window.location.host;
|
|
||||||
export const prefix = window.location.protocol + '//' + window.location.host;
|
|
||||||
|
|
||||||
// dev
|
|
||||||
// export const server = '//127.0.0.1:8088';
|
|
||||||
// export const wsServer = 'ws://127.0.0.1:8088';
|
|
||||||
// export const prefix = '';
|
|
||||||
|
|
||||||
export const PROTOCOL_COLORS = {
|
export const PROTOCOL_COLORS = {
|
||||||
'rdp': 'red',
|
'rdp': 'cyan',
|
||||||
'ssh': 'blue',
|
'ssh': 'blue',
|
||||||
'telnet': 'geekblue',
|
'telnet': 'geekblue',
|
||||||
'vnc': 'purple'
|
'vnc': 'purple'
|
||||||
|
28
web/src/common/env.js
Normal file
28
web/src/common/env.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
function env() {
|
||||||
|
if (process.env.REACT_APP_ENV === 'development') {
|
||||||
|
// 本地开发环境
|
||||||
|
return {
|
||||||
|
server: '//127.0.0.1:8088',
|
||||||
|
wsServer: 'ws://127.0.0.1:8088',
|
||||||
|
prefix: '',
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 生产环境
|
||||||
|
let wsPrefix;
|
||||||
|
if (window.location.protocol === 'https:') {
|
||||||
|
wsPrefix = 'wss:'
|
||||||
|
} else {
|
||||||
|
wsPrefix = 'ws:'
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
server: '',
|
||||||
|
wsServer: wsPrefix + window.location.host,
|
||||||
|
prefix: window.location.protocol + '//' + window.location.host,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default env();
|
||||||
|
|
||||||
|
export const server = env().server;
|
||||||
|
export const wsServer = env().wsServer;
|
||||||
|
export const prefix = env().prefix;
|
@ -1,5 +1,5 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import {server} from "./constants";
|
import {server} from "./env";
|
||||||
import {message} from 'antd';
|
import {message} from 'antd';
|
||||||
import {getHeaders} from "../utils/utils";
|
import {getHeaders} from "../utils/utils";
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import Guacamole from 'guacamole-common-js';
|
|||||||
import {Affix, Button, Col, Drawer, Dropdown, Form, Input, Menu, message, Modal, Row} from 'antd'
|
import {Affix, Button, Col, Drawer, Dropdown, Form, Input, Menu, message, Modal, Row} from 'antd'
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import request from "../../common/request";
|
import request from "../../common/request";
|
||||||
import {wsServer} from "../../common/constants";
|
import {wsServer} from "../../common/env";
|
||||||
import {
|
import {
|
||||||
AppstoreTwoTone,
|
AppstoreTwoTone,
|
||||||
CopyTwoTone,
|
CopyTwoTone,
|
||||||
|
@ -2,7 +2,7 @@ import React, {Component} from 'react';
|
|||||||
import "xterm/css/xterm.css"
|
import "xterm/css/xterm.css"
|
||||||
import {Terminal} from "xterm";
|
import {Terminal} from "xterm";
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import {wsServer} from "../../common/constants";
|
import {wsServer} from "../../common/env";
|
||||||
import "./Console.css"
|
import "./Console.css"
|
||||||
import {getToken, isEmpty} from "../../utils/utils";
|
import {getToken, isEmpty} from "../../utils/utils";
|
||||||
import {FitAddon} from 'xterm-addon-fit'
|
import {FitAddon} from 'xterm-addon-fit'
|
||||||
|
@ -22,7 +22,7 @@ import {
|
|||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import request from "../../common/request";
|
import request from "../../common/request";
|
||||||
import {server} from "../../common/constants";
|
import {server} from "../../common/env";
|
||||||
import Upload from "antd/es/upload";
|
import Upload from "antd/es/upload";
|
||||||
import {download, getFileName, getToken, isEmpty, renderSize} from "../../utils/utils";
|
import {download, getFileName, getToken, isEmpty, renderSize} from "../../utils/utils";
|
||||||
import './FileSystem.css'
|
import './FileSystem.css'
|
||||||
@ -107,7 +107,7 @@ class FileSystem extends Component {
|
|||||||
if (isEmpty(key)) {
|
if (isEmpty(key)) {
|
||||||
key = '/';
|
key = '/';
|
||||||
}
|
}
|
||||||
let result = await request.get(`${server}/sessions/${this.state.sessionId}/ls?dir=${key}`);
|
let result = await request.get(`/sessions/${this.state.sessionId}/ls?dir=${key}`);
|
||||||
if (result['code'] !== 1) {
|
if (result['code'] !== 1) {
|
||||||
message.error(result['message']);
|
message.error(result['message']);
|
||||||
return;
|
return;
|
||||||
|
@ -2,7 +2,7 @@ import React, {Component} from 'react';
|
|||||||
import Guacamole from 'guacamole-common-js';
|
import Guacamole from 'guacamole-common-js';
|
||||||
import {Modal, Result, Spin} from 'antd'
|
import {Modal, Result, Spin} from 'antd'
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import {wsServer} from "../../common/constants";
|
import {wsServer} from "../../common/env";
|
||||||
import {getToken} from "../../utils/utils";
|
import {getToken} from "../../utils/utils";
|
||||||
import './Access.css'
|
import './Access.css'
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import React, {Component} from 'react';
|
|||||||
import "xterm/css/xterm.css"
|
import "xterm/css/xterm.css"
|
||||||
import {Terminal} from "xterm";
|
import {Terminal} from "xterm";
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import {wsServer} from "../../common/constants";
|
import {wsServer} from "../../common/env";
|
||||||
import {getToken, isEmpty} from "../../utils/utils";
|
import {getToken, isEmpty} from "../../utils/utils";
|
||||||
import {FitAddon} from 'xterm-addon-fit';
|
import {FitAddon} from 'xterm-addon-fit';
|
||||||
import "./Access.css"
|
import "./Access.css"
|
||||||
|
@ -26,9 +26,8 @@ import qs from "qs";
|
|||||||
import AssetModal from "./AssetModal";
|
import AssetModal from "./AssetModal";
|
||||||
import request from "../../common/request";
|
import request from "../../common/request";
|
||||||
import {message} from "antd/es";
|
import {message} from "antd/es";
|
||||||
import {itemRender} from "../../utils/utils";
|
import {isEmpty, itemRender} from "../../utils/utils";
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeleteOutlined,
|
DeleteOutlined,
|
||||||
DownOutlined,
|
DownOutlined,
|
||||||
@ -41,6 +40,7 @@ import {PROTOCOL_COLORS} from "../../common/constants";
|
|||||||
import Logout from "../user/Logout";
|
import Logout from "../user/Logout";
|
||||||
import {hasPermission, isAdmin} from "../../service/permission";
|
import {hasPermission, isAdmin} from "../../service/permission";
|
||||||
|
|
||||||
|
|
||||||
const confirm = Modal.confirm;
|
const confirm = Modal.confirm;
|
||||||
const {Search} = Input;
|
const {Search} = Input;
|
||||||
const {Content} = Layout;
|
const {Content} = Layout;
|
||||||
@ -59,6 +59,7 @@ const routes = [
|
|||||||
class Asset extends Component {
|
class Asset extends Component {
|
||||||
|
|
||||||
inputRefOfName = React.createRef();
|
inputRefOfName = React.createRef();
|
||||||
|
inputRefOfIp = React.createRef();
|
||||||
changeOwnerFormRef = React.createRef();
|
changeOwnerFormRef = React.createRef();
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -172,6 +173,17 @@ class Asset extends Component {
|
|||||||
this.loadTableData(query);
|
this.loadTableData(query);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleSearchByIp = ip => {
|
||||||
|
let query = {
|
||||||
|
...this.state.queryParams,
|
||||||
|
'pageIndex': 1,
|
||||||
|
'pageSize': this.state.queryParams.pageSize,
|
||||||
|
'ip': ip,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loadTableData(query);
|
||||||
|
};
|
||||||
|
|
||||||
handleTagsChange = tags => {
|
handleTagsChange = tags => {
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedTags: tags
|
selectedTags: tags
|
||||||
@ -459,18 +471,48 @@ class Asset extends Component {
|
|||||||
dataIndex: 'protocol',
|
dataIndex: 'protocol',
|
||||||
key: 'protocol',
|
key: 'protocol',
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
|
const title = `${record['ip'] + ':' + record['port']}`
|
||||||
return (<Tag color={PROTOCOL_COLORS[text]}>{text}</Tag>);
|
return (
|
||||||
|
<Tooltip title={title}>
|
||||||
|
<Tag color={PROTOCOL_COLORS[text]}>{text}</Tag>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
title: '标签',
|
||||||
|
dataIndex: 'tags',
|
||||||
|
key: 'tags',
|
||||||
|
render: tags => {
|
||||||
|
if (!isEmpty(tags)) {
|
||||||
|
let tagDocuments = []
|
||||||
|
let tagArr = tags.split(',');
|
||||||
|
for (let i = 0; i < tagArr.length; i++) {
|
||||||
|
if (tags[i] === '-') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tagDocuments.push(<Tag>{tagArr[i]}</Tag>)
|
||||||
|
}
|
||||||
|
return tagDocuments;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
title: '状态',
|
title: '状态',
|
||||||
dataIndex: 'active',
|
dataIndex: 'active',
|
||||||
key: 'active',
|
key: 'active',
|
||||||
render: text => {
|
render: text => {
|
||||||
|
|
||||||
if (text) {
|
if (text) {
|
||||||
return (<Badge status="processing" text="运行中"/>);
|
return (
|
||||||
|
<Tooltip title='运行中'>
|
||||||
|
<Badge status="processing"/>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
return (<Badge status="error" text="不可用"/>);
|
return (
|
||||||
|
<Tooltip title='不可用'>
|
||||||
|
<Badge status="error"/>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@ -480,7 +522,14 @@ class Asset extends Component {
|
|||||||
}, {
|
}, {
|
||||||
title: '创建日期',
|
title: '创建日期',
|
||||||
dataIndex: 'created',
|
dataIndex: 'created',
|
||||||
key: 'created'
|
key: 'created',
|
||||||
|
render: (text, record) => {
|
||||||
|
return (
|
||||||
|
<Tooltip title={text}>
|
||||||
|
{dayjs(text).fromNow()}
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
@ -598,10 +647,10 @@ class Asset extends Component {
|
|||||||
<Content key='page-content' className="site-layout-background page-content">
|
<Content key='page-content' className="site-layout-background page-content">
|
||||||
<div style={{marginBottom: 20}}>
|
<div style={{marginBottom: 20}}>
|
||||||
<Row justify="space-around" align="middle" gutter={24}>
|
<Row justify="space-around" align="middle" gutter={24}>
|
||||||
<Col span={8} key={1}>
|
<Col span={4} key={1}>
|
||||||
<Title level={3}>资产列表</Title>
|
<Title level={3}>资产列表</Title>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={16} key={2} style={{textAlign: 'right'}}>
|
<Col span={20} key={2} style={{textAlign: 'right'}}>
|
||||||
<Space>
|
<Space>
|
||||||
|
|
||||||
<Search
|
<Search
|
||||||
@ -609,6 +658,15 @@ class Asset extends Component {
|
|||||||
placeholder="资产名称"
|
placeholder="资产名称"
|
||||||
allowClear
|
allowClear
|
||||||
onSearch={this.handleSearchByName}
|
onSearch={this.handleSearchByName}
|
||||||
|
style={{width: 200}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Search
|
||||||
|
ref={this.inputRefOfIp}
|
||||||
|
placeholder="资产IP"
|
||||||
|
allowClear
|
||||||
|
onSearch={this.handleSearchByIp}
|
||||||
|
style={{width: 200}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Select mode="multiple"
|
<Select mode="multiple"
|
||||||
@ -638,6 +696,7 @@ class Asset extends Component {
|
|||||||
|
|
||||||
<Button icon={<UndoOutlined/>} onClick={() => {
|
<Button icon={<UndoOutlined/>} onClick={() => {
|
||||||
this.inputRefOfName.current.setValue('');
|
this.inputRefOfName.current.setValue('');
|
||||||
|
this.inputRefOfIp.current.setValue('');
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedTags: []
|
selectedTags: []
|
||||||
})
|
})
|
||||||
|
@ -36,6 +36,7 @@ import {
|
|||||||
import {compare, itemRender} from "../../utils/utils";
|
import {compare, itemRender} from "../../utils/utils";
|
||||||
import Logout from "../user/Logout";
|
import Logout from "../user/Logout";
|
||||||
import {hasPermission, isAdmin} from "../../service/permission";
|
import {hasPermission, isAdmin} from "../../service/permission";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
const confirm = Modal.confirm;
|
const confirm = Modal.confirm;
|
||||||
const {Content} = Layout;
|
const {Content} = Layout;
|
||||||
@ -403,7 +404,14 @@ class DynamicCommand extends Component {
|
|||||||
}, {
|
}, {
|
||||||
title: '创建日期',
|
title: '创建日期',
|
||||||
dataIndex: 'created',
|
dataIndex: 'created',
|
||||||
key: 'created'
|
key: 'created',
|
||||||
|
render: (text, record) => {
|
||||||
|
return (
|
||||||
|
<Tooltip title={text}>
|
||||||
|
{dayjs(text).fromNow()}
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
title: '操作',
|
title: '操作',
|
||||||
key: 'action',
|
key: 'action',
|
||||||
|
@ -35,6 +35,7 @@ import {
|
|||||||
import {itemRender} from "../../utils/utils";
|
import {itemRender} from "../../utils/utils";
|
||||||
import Logout from "../user/Logout";
|
import Logout from "../user/Logout";
|
||||||
import {hasPermission, isAdmin} from "../../service/permission";
|
import {hasPermission, isAdmin} from "../../service/permission";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
const confirm = Modal.confirm;
|
const confirm = Modal.confirm;
|
||||||
const {Search} = Input;
|
const {Search} = Input;
|
||||||
@ -375,6 +376,13 @@ class Credential extends Component {
|
|||||||
title: '创建时间',
|
title: '创建时间',
|
||||||
dataIndex: 'created',
|
dataIndex: 'created',
|
||||||
key: 'created',
|
key: 'created',
|
||||||
|
render: (text, record) => {
|
||||||
|
return (
|
||||||
|
<Tooltip title={text}>
|
||||||
|
{dayjs(text).fromNow()}
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
|
@ -18,12 +18,13 @@ import {
|
|||||||
} from "antd";
|
} from "antd";
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import request from "../../common/request";
|
import request from "../../common/request";
|
||||||
import {differTime, formatDate, itemRender} from "../../utils/utils";
|
import {differTime, itemRender} from "../../utils/utils";
|
||||||
import Playback from "./Playback";
|
import Playback from "./Playback";
|
||||||
import {message} from "antd/es";
|
import {message} from "antd/es";
|
||||||
import {DeleteOutlined, ExclamationCircleOutlined, SyncOutlined, UndoOutlined} from "@ant-design/icons";
|
import {DeleteOutlined, ExclamationCircleOutlined, SyncOutlined, UndoOutlined} from "@ant-design/icons";
|
||||||
import {PROTOCOL_COLORS} from "../../common/constants";
|
import {PROTOCOL_COLORS} from "../../common/constants";
|
||||||
import Logout from "../user/Logout";
|
import Logout from "../user/Logout";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
const confirm = Modal.confirm;
|
const confirm = Modal.confirm;
|
||||||
const {Content} = Layout;
|
const {Content} = Layout;
|
||||||
@ -244,29 +245,28 @@ class OfflineSession extends Component {
|
|||||||
title: '资产名称',
|
title: '资产名称',
|
||||||
dataIndex: 'assetName',
|
dataIndex: 'assetName',
|
||||||
key: 'assetName'
|
key: 'assetName'
|
||||||
}, {
|
|
||||||
title: '远程连接',
|
|
||||||
dataIndex: 'access',
|
|
||||||
key: 'access',
|
|
||||||
render: (text, record) => {
|
|
||||||
|
|
||||||
return `${record.username}@${record.ip}:${record.port}`;
|
|
||||||
}
|
|
||||||
}, {
|
}, {
|
||||||
title: '连接协议',
|
title: '连接协议',
|
||||||
dataIndex: 'protocol',
|
dataIndex: 'protocol',
|
||||||
key: 'protocol',
|
key: 'protocol',
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
|
const title = `${record.username}@${record.ip}:${record.port}`;
|
||||||
return (<Tag color={PROTOCOL_COLORS[text]}>{text}</Tag>);
|
return (
|
||||||
|
<Tooltip title={title}>
|
||||||
|
<Tag color={PROTOCOL_COLORS[text]}>{text}</Tag>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
title: '接入时间',
|
title: '接入时间',
|
||||||
dataIndex: 'connectedTime',
|
dataIndex: 'connectedTime',
|
||||||
key: 'connectedTime',
|
key: 'connectedTime',
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
|
return (
|
||||||
return formatDate(text, 'yyyy-MM-dd hh:mm:ss');
|
<Tooltip title={text}>
|
||||||
|
{dayjs(text).fromNow()}
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
title: '接入时长',
|
title: '接入时长',
|
||||||
|
@ -19,12 +19,13 @@ import {
|
|||||||
} from "antd";
|
} from "antd";
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import request from "../../common/request";
|
import request from "../../common/request";
|
||||||
import {differTime, formatDate, itemRender} from "../../utils/utils";
|
import {differTime, itemRender} from "../../utils/utils";
|
||||||
import {message} from "antd/es";
|
import {message} from "antd/es";
|
||||||
import {PROTOCOL_COLORS} from "../../common/constants";
|
import {PROTOCOL_COLORS} from "../../common/constants";
|
||||||
import {DisconnectOutlined, ExclamationCircleOutlined, SyncOutlined, UndoOutlined} from "@ant-design/icons";
|
import {DisconnectOutlined, ExclamationCircleOutlined, SyncOutlined, UndoOutlined} from "@ant-design/icons";
|
||||||
import Monitor from "../access/Monitor";
|
import Monitor from "../access/Monitor";
|
||||||
import Logout from "../user/Logout";
|
import Logout from "../user/Logout";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
const confirm = Modal.confirm;
|
const confirm = Modal.confirm;
|
||||||
const {Content} = Layout;
|
const {Content} = Layout;
|
||||||
@ -241,29 +242,28 @@ class OnlineSession extends Component {
|
|||||||
title: '资产名称',
|
title: '资产名称',
|
||||||
dataIndex: 'assetName',
|
dataIndex: 'assetName',
|
||||||
key: 'assetName'
|
key: 'assetName'
|
||||||
}, {
|
|
||||||
title: '远程连接',
|
|
||||||
dataIndex: 'access',
|
|
||||||
key: 'access',
|
|
||||||
render: (text, record) => {
|
|
||||||
|
|
||||||
return `${record.username}@${record.ip}:${record.port}`;
|
|
||||||
}
|
|
||||||
}, {
|
}, {
|
||||||
title: '连接协议',
|
title: '连接协议',
|
||||||
dataIndex: 'protocol',
|
dataIndex: 'protocol',
|
||||||
key: 'protocol',
|
key: 'protocol',
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
|
const title = `${record.username}@${record.ip}:${record.port}`;
|
||||||
return (<Tag color={PROTOCOL_COLORS[text]}>{text}</Tag>);
|
return (
|
||||||
|
<Tooltip title={title}>
|
||||||
|
<Tag color={PROTOCOL_COLORS[text]}>{text}</Tag>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
title: '接入时间',
|
title: '接入时间',
|
||||||
dataIndex: 'connectedTime',
|
dataIndex: 'connectedTime',
|
||||||
key: 'connectedTime',
|
key: 'connectedTime',
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
|
return (
|
||||||
return formatDate(text, 'yyyy-MM-dd hh:mm:ss');
|
<Tooltip title={text}>
|
||||||
|
{dayjs(text).fromNow()}
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
title: '接入时长',
|
title: '接入时长',
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import Guacamole from "guacamole-common-js";
|
import Guacamole from "guacamole-common-js";
|
||||||
import {server} from "../../common/constants";
|
import server from "../../common/env";
|
||||||
import {Button, Col, Row, Slider, Typography} from "antd";
|
import {Button, Col, Row, Slider, Typography} from "antd";
|
||||||
import {PauseCircleOutlined, PlayCircleOutlined} from '@ant-design/icons';
|
import {PauseCircleOutlined, PlayCircleOutlined} from '@ant-design/icons';
|
||||||
import {Tooltip} from "antd/lib/index";
|
import {Tooltip} from "antd/lib/index";
|
||||||
|
@ -36,6 +36,7 @@ import {
|
|||||||
import Logout from "./Logout";
|
import Logout from "./Logout";
|
||||||
import UserShareAsset from "./UserShareAsset";
|
import UserShareAsset from "./UserShareAsset";
|
||||||
import {hasPermission} from "../../service/permission";
|
import {hasPermission} from "../../service/permission";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
const confirm = Modal.confirm;
|
const confirm = Modal.confirm;
|
||||||
const {Search} = Input;
|
const {Search} = Input;
|
||||||
@ -342,7 +343,14 @@ class User extends Component {
|
|||||||
}, {
|
}, {
|
||||||
title: '创建日期',
|
title: '创建日期',
|
||||||
dataIndex: 'created',
|
dataIndex: 'created',
|
||||||
key: 'created'
|
key: 'created',
|
||||||
|
render: (text, record) => {
|
||||||
|
return (
|
||||||
|
<Tooltip title={text}>
|
||||||
|
{dayjs(text).fromNow()}
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
|
@ -9,6 +9,7 @@ import {DeleteOutlined, ExclamationCircleOutlined, PlusOutlined, SyncOutlined, U
|
|||||||
import Logout from "./Logout";
|
import Logout from "./Logout";
|
||||||
import UserGroupModal from "./UserGroupModal";
|
import UserGroupModal from "./UserGroupModal";
|
||||||
import UserShareAsset from "./UserShareAsset";
|
import UserShareAsset from "./UserShareAsset";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
const confirm = Modal.confirm;
|
const confirm = Modal.confirm;
|
||||||
const {Search} = Input;
|
const {Search} = Input;
|
||||||
@ -285,7 +286,14 @@ class UserGroup extends Component {
|
|||||||
}, {
|
}, {
|
||||||
title: '创建日期',
|
title: '创建日期',
|
||||||
dataIndex: 'created',
|
dataIndex: 'created',
|
||||||
key: 'created'
|
key: 'created',
|
||||||
|
render: (text, record) => {
|
||||||
|
return (
|
||||||
|
<Tooltip title={text}>
|
||||||
|
{dayjs(text).fromNow()}
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
|
@ -6,6 +6,12 @@ import * as serviceWorker from './serviceWorker';
|
|||||||
import zhCN from 'antd/es/locale-provider/zh_CN';
|
import zhCN from 'antd/es/locale-provider/zh_CN';
|
||||||
import {ConfigProvider} from 'antd';
|
import {ConfigProvider} from 'antd';
|
||||||
import {HashRouter as Router} from "react-router-dom";
|
import {HashRouter as Router} from "react-router-dom";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import relativeTime from "dayjs/plugin/relativeTime";
|
||||||
|
import 'dayjs/locale/zh-cn'
|
||||||
|
|
||||||
|
dayjs.extend(relativeTime);
|
||||||
|
dayjs.locale('zh-cn');
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<ConfigProvider locale={zhCN}>
|
<ConfigProvider locale={zhCN}>
|
||||||
|
Loading…
Reference in New Issue
Block a user