From 28d17accd2de0511761fa0a2de497b7d4791651a Mon Sep 17 00:00:00 2001 From: dushixiang Date: Sun, 17 Jan 2021 23:54:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E8=B5=84=E4=BA=A7=E9=9A=94?= =?UTF-8?q?=E7=A6=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/api/asset.go | 4 +- pkg/api/resource.go | 32 ++ pkg/api/routes.go | 6 +- pkg/api/user-group.go | 23 +- pkg/model/asset.go | 11 +- pkg/model/resource.go | 26 ++ pkg/model/user-group-member.go | 7 + pkg/model/user-group.go | 25 +- pkg/model/user.go | 32 +- web/src/components/asset/Asset.js | 1 + web/src/components/user/User.js | 76 +++- web/src/components/user/UserGroup.js | 74 ++-- web/src/components/user/UserGroupModal.js | 4 +- web/src/components/user/UserShareAsset.js | 392 +++++++++++++++++ .../components/user/UserShareSelectAsset.js | 416 ++++++++++++++++++ web/src/utils/utils.js | 6 + 16 files changed, 1072 insertions(+), 63 deletions(-) create mode 100644 web/src/components/user/UserShareAsset.js create mode 100644 web/src/components/user/UserShareSelectAsset.js diff --git a/pkg/api/asset.go b/pkg/api/asset.go index 8a9b139..e56e9e9 100644 --- a/pkg/api/asset.go +++ b/pkg/api/asset.go @@ -33,9 +33,11 @@ func AssetPagingEndpoint(c echo.Context) error { name := c.QueryParam("name") protocol := c.QueryParam("protocol") tags := c.QueryParam("tags") + owner := c.QueryParam("owner") + sharer := c.QueryParam("sharer") account, _ := GetCurrentAccount(c) - items, total, _ := model.FindPageAsset(pageIndex, pageSize, name, protocol, tags, account) + items, total, _ := model.FindPageAsset(pageIndex, pageSize, name, protocol, tags, account, owner, sharer) return Success(c, H{ "total": total, diff --git a/pkg/api/resource.go b/pkg/api/resource.go index e4d523a..e06415e 100644 --- a/pkg/api/resource.go +++ b/pkg/api/resource.go @@ -6,6 +6,12 @@ import ( "strings" ) +type RU struct { + UserId string `json:"userId"` + ResourceType string `json:"resourceType"` + ResourceIds []string `json:"resourceIds"` +} + func ResourceGetAssignEndPoint(c echo.Context) error { resourceId := c.Param("id") userIds, err := model.FindUserIdsByResourceId(resourceId) @@ -25,3 +31,29 @@ func ResourceOverwriteAssignEndPoint(c echo.Context) error { return Success(c, "") } + +func ResourceRemoveByUserIdAssignEndPoint(c echo.Context) error { + var ru RU + if err := c.Bind(&ru); err != nil { + return err + } + + if err := model.DeleteByUserIdAndResourceTypeAndResourceIdIn(ru.UserId, ru.ResourceType, ru.ResourceIds); err != nil { + return err + } + + return Success(c, "") +} + +func ResourceAddByUserIdAssignEndPoint(c echo.Context) error { + var ru RU + if err := c.Bind(&ru); err != nil { + return err + } + + if err := model.AddSharerResources(ru.UserId, ru.ResourceType, ru.ResourceIds); err != nil { + return err + } + + return Success(c, "") +} diff --git a/pkg/api/routes.go b/pkg/api/routes.go index b8fd34d..dfc8a35 100644 --- a/pkg/api/routes.go +++ b/pkg/api/routes.go @@ -58,8 +58,8 @@ func SetupRoutes() *echo.Echo { userGroups.PUT("/:id", UserGroupUpdateEndpoint) userGroups.DELETE("/:id", UserGroupDeleteEndpoint) userGroups.GET("/:id", UserGroupGetEndpoint) - userGroups.POST("/:id/members", UserGroupAddMembersEndpoint) - userGroups.DELETE("/:id/members/:memberId", UserGroupDelMembersEndpoint) + //userGroups.POST("/:id/members", UserGroupAddMembersEndpoint) + //userGroups.DELETE("/:id/members/:memberId", UserGroupDelMembersEndpoint) } assets := e.Group("/assets", Auth) @@ -119,6 +119,8 @@ func SetupRoutes() *echo.Echo { { resources.GET("/:id/assign", ResourceGetAssignEndPoint) resources.POST("/:id/assign", ResourceOverwriteAssignEndPoint) + resources.POST("/remove", ResourceRemoveByUserIdAssignEndPoint) + resources.POST("/add", ResourceAddByUserIdAssignEndPoint) } e.GET("/properties", PropertyGetEndpoint) diff --git a/pkg/api/user-group.go b/pkg/api/user-group.go index 24831af..4d3686c 100644 --- a/pkg/api/user-group.go +++ b/pkg/api/user-group.go @@ -10,6 +10,7 @@ import ( ) type UserGroup struct { + Id string `json:"id"` Name string `json:"name"` Members []string `json:"members"` } @@ -52,12 +53,17 @@ func UserGroupPagingEndpoint(c echo.Context) error { func UserGroupUpdateEndpoint(c echo.Context) error { id := c.Param("id") - var item model.UserGroup + var item UserGroup if err := c.Bind(&item); err != nil { return err } + userGroup := model.UserGroup{ + Name: item.Name, + } - model.UpdateUserGroupById(&item, id) + if err := model.UpdateUserGroupById(&userGroup, item.Members, id); err != nil { + return err + } return Success(c, nil) } @@ -81,7 +87,18 @@ func UserGroupGetEndpoint(c echo.Context) error { return err } - return Success(c, item) + members, err := model.FindUserGroupMembersByUserGroupId(id) + if err != nil { + return err + } + + userGroup := UserGroup{ + Id: item.ID, + Name: item.Name, + Members: members, + } + + return Success(c, userGroup) } func UserGroupAddMembersEndpoint(c echo.Context) error { diff --git a/pkg/model/asset.go b/pkg/model/asset.go index 7eaeafc..5be697d 100644 --- a/pkg/model/asset.go +++ b/pkg/model/asset.go @@ -58,7 +58,7 @@ func FindAssetByConditions(protocol string, account User) (o []Asset, err error) return } -func FindPageAsset(pageIndex, pageSize int, name, protocol, tags string, account User) (o []AssetVo, total int64, err error) { +func FindPageAsset(pageIndex, pageSize int, name, protocol, tags string, account User, owner, sharer 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(resources.user_id) as sharer_count").Joins("left join users on assets.owner = users.id").Joins("left join resources on assets.id = resources.resource_id").Group("assets.id") dbCounter := global.DB.Table("assets").Select("DISTINCT assets.id").Joins("left join resources on assets.id = resources.resource_id") @@ -66,6 +66,15 @@ func FindPageAsset(pageIndex, pageSize int, name, protocol, tags string, account owner := account.ID db = db.Where("assets.owner = ? or resources.user_id = ?", owner, owner) dbCounter = dbCounter.Where("assets.owner = ? or resources.user_id = ?", owner, owner) + } else { + if len(owner) > 0 { + db = db.Where("assets.owner = ?", owner) + dbCounter = dbCounter.Where("assets.owner = ?", owner) + } + if len(sharer) > 0 { + db = db.Where("resources.user_id = ?", sharer) + dbCounter = dbCounter.Where("resources.user_id = ?", sharer) + } } if len(name) > 0 { diff --git a/pkg/model/resource.go b/pkg/model/resource.go index 4dc596b..a3fa9dc 100644 --- a/pkg/model/resource.go +++ b/pkg/model/resource.go @@ -1,6 +1,7 @@ package model import ( + "gorm.io/gorm" "next-terminal/pkg/global" "next-terminal/pkg/utils" ) @@ -45,3 +46,28 @@ func OverwriteUserIdsByResourceId(resourceId, resourceType string, userIds []str } db.Commit() } + +func DeleteByUserIdAndResourceTypeAndResourceIdIn(userId, resourceType string, resourceIds []string) error { + return global.DB.Where("user_id = ? and resource_type = ? and resource_id in ?", userId, resourceType, resourceIds).Delete(&Resource{}).Error +} + +func AddSharerResources(userId, resourceType string, resourceIds []string) error { + return global.DB.Transaction(func(tx *gorm.DB) (err error) { + + for i := range resourceIds { + resourceId := resourceIds[i] + id := utils.Sign([]string{resourceId, resourceType, userId}) + resource := &Resource{ + ID: id, + ResourceId: resourceId, + ResourceType: resourceType, + UserId: userId, + } + err = tx.Create(resource).Error + if err != nil { + return err + } + } + return nil + }) +} diff --git a/pkg/model/user-group-member.go b/pkg/model/user-group-member.go index 2d2f4d2..ca05e08 100644 --- a/pkg/model/user-group-member.go +++ b/pkg/model/user-group-member.go @@ -1,5 +1,7 @@ package model +import "next-terminal/pkg/global" + type UserGroupMember struct { ID string `gorm:"primary_key" json:"name"` UserId string `json:"userId"` @@ -9,3 +11,8 @@ type UserGroupMember struct { func (r *UserGroupMember) TableName() string { return "user_group_members" } + +func FindUserGroupMembersByUserGroupId(id string) (o []string, err error) { + err = global.DB.Table("user_group_members").Select("user_id").Where("user_group_id = ?", id).Find(&o).Error + return +} diff --git a/pkg/model/user-group.go b/pkg/model/user-group.go index be55e90..21a77fa 100644 --- a/pkg/model/user-group.go +++ b/pkg/model/user-group.go @@ -86,9 +86,28 @@ func FindUserGroupById(id string) (o UserGroup, err error) { return } -func UpdateUserGroupById(o *UserGroup, id string) { - o.ID = id - global.DB.Updates(o) +func UpdateUserGroupById(o *UserGroup, members []string, id string) error { + return global.DB.Transaction(func(tx *gorm.DB) error { + o.ID = id + err := tx.Updates(o).Error + if err != nil { + return err + } + + err = tx.Where("user_group_id = ?", id).Delete(&UserGroupMember{}).Error + if err != nil { + return err + } + if members != nil { + userGroupId := o.ID + err = AddUserGroupMembers(tx, members, userGroupId) + if err != nil { + return err + } + } + return err + }) + } func DeleteUserGroupById(id string) { diff --git a/pkg/model/user.go b/pkg/model/user.go index a1c338f..51caec7 100644 --- a/pkg/model/user.go +++ b/pkg/model/user.go @@ -23,6 +23,18 @@ type User struct { Type string `json:"type"` } +type UserVo struct { + ID string `gorm:"primary_key" json:"id"` + Username string `json:"username"` + Nickname string `json:"nickname"` + Online bool `json:"online"` + Enabled bool `json:"enabled"` + Created utils.JsonTime `json:"created"` + Type string `json:"type"` + //OwnerAssetCount int64 `json:"ownerAssetCount"` + SharerAssetCount int64 `json:"sharerAssetCount"` +} + func (r *User) TableName() string { return "users" } @@ -38,19 +50,27 @@ func FindAllUser() (o []User) { return } -func FindPageUser(pageIndex, pageSize int, username, nickname string) (o []User, total int64, err error) { - db := global.DB +func FindPageUser(pageIndex, pageSize int, username, nickname string) (o []UserVo, total int64, err error) { + db := global.DB.Table("users").Select("users.id,users.username,users.nickname,users.online,users.enabled,users.created,users.type, count(resources.user_id) as sharer_asset_count").Joins("left join resources on users.id = resources.user_id and resources.resource_type = 'asset'").Group("users.id") + dbCounter := global.DB.Table("users") if len(username) > 0 { - db = db.Where("username like ?", "%"+username+"%") + db = db.Where("users.username like ?", "%"+username+"%") + dbCounter = dbCounter.Where("username like ?", "%"+username+"%") } if len(nickname) > 0 { - db = db.Where("nickname like ?", "%"+nickname+"%") + db = db.Where("users.nickname like ?", "%"+nickname+"%") + dbCounter = dbCounter.Where("nickname like ?", "%"+nickname+"%") } - err = db.Order("created desc").Find(&o).Offset((pageIndex - 1) * pageSize).Limit(pageSize).Count(&total).Error + err = dbCounter.Count(&total).Error + if err != nil { + return nil, 0, err + } + + err = db.Order("users.created desc").Find(&o).Offset((pageIndex - 1) * pageSize).Limit(pageSize).Error if o == nil { - o = make([]User, 0) + o = make([]UserVo, 0) } return } diff --git a/web/src/components/asset/Asset.js b/web/src/components/asset/Asset.js index 5eb8395..113aa64 100644 --- a/web/src/components/asset/Asset.js +++ b/web/src/components/asset/Asset.js @@ -88,6 +88,7 @@ class Asset extends Component { }; async componentDidMount() { + this.loadTableData(); let result = await request.get('/tags'); diff --git a/web/src/components/user/User.js b/web/src/components/user/User.js index 1c05470..6848e68 100644 --- a/web/src/components/user/User.js +++ b/web/src/components/user/User.js @@ -21,17 +21,9 @@ import qs from "qs"; import UserModal from "./UserModal"; import request from "../../common/request"; import {message} from "antd/es"; -import { - DeleteOutlined, - DownOutlined, - ExclamationCircleOutlined, - IssuesCloseOutlined, - PlusOutlined, - StopOutlined, - SyncOutlined, - UndoOutlined -} from '@ant-design/icons'; +import {DeleteOutlined, ExclamationCircleOutlined, PlusOutlined, SyncOutlined, UndoOutlined} from '@ant-design/icons'; import Logout from "./Logout"; +import UserShareAsset from "./UserShareAsset"; const confirm = Modal.confirm; const {Search} = Input; @@ -68,6 +60,7 @@ class User extends Component { model: null, selectedRowKeys: [], delBtnLoading: false, + assetVisible: false }; componentDidMount() { @@ -230,14 +223,14 @@ class User extends Component { }) try { let result = await request.delete('/users/' + this.state.selectedRowKeys.join(',')); - if (result.code === 1) { + if (result['code'] === 1) { message.success('操作成功', 3); this.setState({ selectedRowKeys: [] }) await this.loadTableData(this.state.queryParams); } else { - message.error('删除失败 :( ' + result.message, 10); + message.error(result['message'], 10); } } finally { this.setState({ @@ -246,6 +239,13 @@ class User extends Component { } } + handleAssetCancel = () => { + this.loadTableData() + this.setState({ + assetVisible: false + }) + } + render() { const columns = [{ @@ -293,6 +293,18 @@ class User extends Component { return (); } } + }, { + title: '共享资产', + dataIndex: 'sharerAssetCount', + key: 'sharerAssetCount', + render: (text, record, index) => { + return + } }, { title: '创建日期', dataIndex: 'created', @@ -483,15 +495,39 @@ class User extends Component { loading={this.state.loading} /> - + : undefined + } + + { + + }} + onCancel={this.handleAssetCancel} + okText='确定' + cancelText='取消' + footer={null} > - + + ); diff --git a/web/src/components/user/UserGroup.js b/web/src/components/user/UserGroup.js index e8358b0..d6e8a79 100644 --- a/web/src/components/user/UserGroup.js +++ b/web/src/components/user/UserGroup.js @@ -40,11 +40,10 @@ class UserGroup extends Component { modalVisible: false, modalTitle: '', modalConfirmLoading: false, - model: null, + model: undefined, selectedRowKeys: [], delBtnLoading: false, users: [], - members: [] }; componentDidMount() { @@ -125,11 +124,35 @@ class UserGroup extends Component { }); }; - showModal(title, user = {}) { + showModal = async (title, id, index) => { - this.handleSearchByNickname(''); + let items = this.state.items; + + let model = {} + if (id) { + items[index].updateBtnLoading = true; + this.setState({ + items: items + }); + + let result = await request.get('/user-groups/' + id); + if (result['code'] !== 1) { + message.error(result['message']); + items[index].updateBtnLoading = false; + this.setState({ + items: items + }); + return; + } + + items[index].updateBtnLoading = false; + model = result['data'] + } + + await this.handleSearchByNickname(''); + console.log(model) this.setState({ - model: user, + model: model, modalVisible: true, modalTitle: title }); @@ -138,7 +161,8 @@ class UserGroup extends Component { handleCancelModal = e => { this.setState({ modalVisible: false, - modalTitle: '' + modalTitle: '', + model: undefined }); }; @@ -243,9 +267,7 @@ class UserGroup extends Component { dataIndex: 'memberCount', key: 'memberCount', render: (text, record, index) => { - return + return } }, { title: '创建日期', @@ -255,13 +277,12 @@ class UserGroup extends Component { { title: '操作', key: 'action', - render: (text, record) => { - - + render: (text, record, index) => { return (
+ loading={this.state.items[index].updateBtnLoading} + onClick={() => this.showModal('更新用户组', record['id'], index)}>编辑
@@ -325,7 +346,7 @@ class UserGroup extends Component { @@ -382,17 +403,20 @@ class UserGroup extends Component { loading={this.state.loading} /> - - + {/* 为了屏蔽ant modal 关闭后数据仍然遗留的问题*/} + {this.state.modalVisible ? + + : undefined + } + diff --git a/web/src/components/user/UserGroupModal.js b/web/src/components/user/UserGroupModal.js index f22cdbd..008d79e 100644 --- a/web/src/components/user/UserGroupModal.js +++ b/web/src/components/user/UserGroupModal.js @@ -1,4 +1,4 @@ -import React, {useState} from 'react'; +import React from 'react'; import {Form, Input, Modal, Select} from "antd/lib/index"; const UserGroupModal = ({ @@ -9,7 +9,6 @@ const UserGroupModal = ({ confirmLoading, model, users, - members, }) => { const [form] = Form.useForm(); @@ -24,6 +23,7 @@ const UserGroupModal = ({ title={title} visible={visible} maskClosable={false} + destroyOnClose={true} onOk={() => { form .validateFields() diff --git a/web/src/components/user/UserShareAsset.js b/web/src/components/user/UserShareAsset.js new file mode 100644 index 0000000..a61bc1f --- /dev/null +++ b/web/src/components/user/UserShareAsset.js @@ -0,0 +1,392 @@ +import React, {Component} from 'react'; + +import { + Badge, + Button, + Col, + Divider, + Drawer, + Input, + Layout, + Modal, + Row, + Select, + Space, + Table, + Tag, + Tooltip, + Typography +} from "antd"; +import qs from "qs"; +import request from "../../common/request"; +import {message} from "antd/es"; + + +import {DeleteOutlined, ExclamationCircleOutlined, PlusOutlined, SyncOutlined, UndoOutlined} from '@ant-design/icons'; +import {PROTOCOL_COLORS} from "../../common/constants"; +import UserShareChooseAsset from "./UserShareSelectAsset"; + +const confirm = Modal.confirm; +const {Search} = Input; +const {Content} = Layout; +const {Title, Text} = Typography; + +class UserShareAsset extends Component { + + inputRefOfName = React.createRef(); + changeOwnerFormRef = React.createRef(); + + state = { + items: [], + total: 0, + queryParams: { + pageIndex: 1, + pageSize: 10, + protocol: '' + }, + loading: false, + tags: [], + model: {}, + selectedRowKeys: [], + delBtnLoading: false, + changeOwnerModalVisible: false, + changeSharerModalVisible: false, + changeOwnerConfirmLoading: false, + changeSharerConfirmLoading: false, + users: [], + selected: {}, + selectedSharers: [], + chooseAssetVisible: false + }; + + async componentDidMount() { + let sharer = this.props.sharer; + this.loadTableData({sharer: sharer}); + + let result = await request.get('/tags'); + if (result['code'] === 1) { + this.setState({ + tags: result['data'] + }) + } + } + + async loadTableData(queryParams) { + this.setState({ + loading: true + }); + + queryParams = queryParams || this.state.queryParams; + + // queryParams + let paramsStr = qs.stringify(queryParams); + + let data = { + items: [], + total: 0 + }; + + try { + let result = await request.get('/assets/paging?' + paramsStr); + if (result['code'] === 1) { + data = result['data']; + } else { + message.error(result['message']); + } + } catch (e) { + + } finally { + const items = data.items.map(item => { + return {'key': item['id'], ...item} + }) + this.setState({ + items: items, + total: data.total, + queryParams: queryParams, + loading: false + }); + } + } + + handleChangPage = async (pageIndex, pageSize) => { + let queryParams = this.state.queryParams; + queryParams.pageIndex = pageIndex; + queryParams.pageSize = pageSize; + + this.setState({ + queryParams: queryParams + }); + + await this.loadTableData(queryParams) + }; + + handleSearchByName = name => { + let query = { + ...this.state.queryParams, + 'pageIndex': 1, + 'pageSize': this.state.queryParams.pageSize, + 'name': name, + } + + this.loadTableData(query); + }; + + handleTagsChange = tags => { + console.log(tags) + // this.setState({ + // tags: tags + // }) + let query = { + ...this.state.queryParams, + 'pageIndex': 1, + 'pageSize': this.state.queryParams.pageSize, + 'tags': tags.join(','), + } + + this.loadTableData(query); + } + + handleSearchByProtocol = protocol => { + let query = { + ...this.state.queryParams, + 'pageIndex': 1, + 'pageSize': this.state.queryParams.pageSize, + 'protocol': protocol, + } + this.loadTableData(query); + } + + render() { + + const columns = [{ + title: '序号', + dataIndex: 'id', + key: 'id', + render: (id, record, index) => { + return index + 1; + } + }, { + title: '资产名称', + dataIndex: 'name', + key: 'name', + render: (name, record) => { + let short = name; + if (short && short.length > 20) { + short = short.substring(0, 20) + " ..."; + } + return ( + + {short} + + ); + } + }, { + title: '网络', + dataIndex: 'ip', + key: 'ip', + render: (text, record) => { + + return record['ip'] + ':' + record['port']; + } + }, { + title: '连接协议', + dataIndex: 'protocol', + key: 'protocol', + render: (text, record) => { + + return ({text}); + } + }, { + title: '状态', + dataIndex: 'active', + key: 'active', + render: text => { + if (text) { + return (); + } else { + return (); + } + } + }, { + title: '所有者', + dataIndex: 'ownerName', + key: 'ownerName' + }, { + title: '创建日期', + dataIndex: 'created', + key: 'created' + } + ]; + + const selectedRowKeys = this.state.selectedRowKeys; + const rowSelection = { + selectedRowKeys: this.state.selectedRowKeys, + onChange: (selectedRowKeys, selectedRows) => { + this.setState({selectedRowKeys}); + }, + }; + const hasSelected = selectedRowKeys.length > 0; + + return ( + <> + +
+ + + 共享资产列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + `总计 ${total} 条` + }} + loading={this.state.loading} + /> + + {this.state.chooseAssetVisible ? + { + this.loadTableData() + this.setState({ + chooseAssetVisible: false + }) + }} + visible={this.state.chooseAssetVisible} + width={window.innerWidth * 0.8} + > + + + + : undefined + } + + + + ); + } +} + +export default UserShareAsset; diff --git a/web/src/components/user/UserShareSelectAsset.js b/web/src/components/user/UserShareSelectAsset.js new file mode 100644 index 0000000..36d2130 --- /dev/null +++ b/web/src/components/user/UserShareSelectAsset.js @@ -0,0 +1,416 @@ +import React, {Component} from 'react'; + +import { + Badge, + Button, + Col, + Divider, + Input, + Layout, + Modal, + Row, + Select, + Space, + Table, + Tag, + Tooltip, + Typography +} from "antd"; +import qs from "qs"; +import request from "../../common/request"; +import {message} from "antd/es"; + + +import {PlusOutlined, SyncOutlined, UndoOutlined} from '@ant-design/icons'; +import {PROTOCOL_COLORS} from "../../common/constants"; + +const confirm = Modal.confirm; +const {Search} = Input; +const {Content} = Layout; +const {Title, Text} = Typography; + +class UserShareAsset extends Component { + + inputRefOfName = React.createRef(); + changeOwnerFormRef = React.createRef(); + + state = { + items: [], + total: 0, + queryParams: { + pageIndex: 1, + pageSize: 10, + protocol: '' + }, + loading: false, + tags: [], + model: {}, + selectedRowKeys: [], + selectedRows: [], + delBtnLoading: false, + changeOwnerModalVisible: false, + changeSharerModalVisible: false, + changeOwnerConfirmLoading: false, + changeSharerConfirmLoading: false, + users: [], + selected: {}, + totalSelectedRows: [], + sharer: '' + }; + + async componentDidMount() { + + this.setState({ + sharer: this.props.sharer + }) + let r2 = await request.get('/assets/paging?pageIndex=1&pageSize=1000&sharer=' + this.props.sharer); + if (r2['code'] === 1) { + let items = r2['data']['items']; + + this.setState({ + totalSelectedRows: items + }) + } + + this.loadTableData(); + + let result = await request.get('/tags'); + if (result['code'] === 1) { + this.setState({ + tags: result['data'] + }) + } + } + + async loadTableData(queryParams) { + this.setState({ + loading: true + }); + + queryParams = queryParams || this.state.queryParams; + + // queryParams + let paramsStr = qs.stringify(queryParams); + + let data = { + items: [], + total: 0 + }; + + try { + let result = await request.get('/assets/paging?' + paramsStr); + if (result['code'] === 1) { + data = result['data']; + } else { + message.error(result['message']); + } + } catch (e) { + + } finally { + const items = data.items.map(item => { + return {'key': item['id'], ...item} + }) + let totalSelectedRows = this.state.totalSelectedRows; + let selectedRowKeys = totalSelectedRows.map(item => item['id']); + this.setState({ + items: items, + total: data.total, + queryParams: queryParams, + loading: false, + selectedRowKeys: selectedRowKeys + }); + } + } + + handleChangPage = async (pageIndex, pageSize) => { + let queryParams = this.state.queryParams; + queryParams.pageIndex = pageIndex; + queryParams.pageSize = pageSize; + + this.setState({ + queryParams: queryParams + }); + + await this.loadTableData(queryParams) + }; + + handleSearchByName = name => { + let query = { + ...this.state.queryParams, + 'pageIndex': 1, + 'pageSize': this.state.queryParams.pageSize, + 'name': name, + } + + this.loadTableData(query); + }; + + handleTagsChange = tags => { + console.log(tags) + // this.setState({ + // tags: tags + // }) + let query = { + ...this.state.queryParams, + 'pageIndex': 1, + 'pageSize': this.state.queryParams.pageSize, + 'tags': tags.join(','), + } + + this.loadTableData(query); + } + + handleSearchByProtocol = protocol => { + let query = { + ...this.state.queryParams, + 'pageIndex': 1, + 'pageSize': this.state.queryParams.pageSize, + 'protocol': protocol, + } + this.loadTableData(query); + } + + unSelectRow = async (assetId) => { + let userId = this.state.sharer; + let result = await request.post(`/resources/remove`, { + userId: userId, + resourceType: 'asset', + resourceIds: [assetId] + }); + if (result['code'] === 1) { + message.success('操作成功', 3); + } else { + message.error(result['message'], 10); + } + + const selectedRowKeys = this.state.selectedRowKeys.filter(key => key !== assetId); + const totalSelectedRows = this.state.totalSelectedRows.filter(item => item['id'] !== assetId); + this.setState({ + selectedRowKeys: selectedRowKeys, + totalSelectedRows: totalSelectedRows + }) + } + + render() { + + const columns = [{ + title: '序号', + dataIndex: 'id', + key: 'id', + render: (id, record, index) => { + return index + 1; + } + }, { + title: '资产名称', + dataIndex: 'name', + key: 'name', + render: (name, record) => { + let short = name; + if (short && short.length > 20) { + short = short.substring(0, 20) + " ..."; + } + return ( + + {short} + + ); + } + }, { + title: '网络', + dataIndex: 'ip', + key: 'ip', + render: (text, record) => { + + return record['ip'] + ':' + record['port']; + } + }, { + title: '连接协议', + dataIndex: 'protocol', + key: 'protocol', + render: (text, record) => { + + return ({text}); + } + }, { + title: '状态', + dataIndex: 'active', + key: 'active', + render: text => { + if (text) { + return (); + } else { + return (); + } + } + }, { + title: '所有者', + dataIndex: 'ownerName', + key: 'ownerName' + }, { + title: '创建日期', + dataIndex: 'created', + key: 'created' + } + ]; + + const selectedRowKeys = this.state.selectedRowKeys; + const rowSelection = { + selectedRowKeys: this.state.selectedRowKeys, + onChange: (selectedRowKeys, selectedRows) => { + this.setState({selectedRowKeys, selectedRows}); + }, + }; + let hasSelected = false; + if (selectedRowKeys.length > 0) { + let totalSelectedRows = this.state.totalSelectedRows; + let allSelectedRowKeys = totalSelectedRows.map(item => item['id']); + for (let i = 0; i < selectedRowKeys.length; i++) { + let selectedRowKey = selectedRowKeys[i]; + if (!allSelectedRowKeys.includes(selectedRowKey)) { + hasSelected = true; + break; + } + } + } + + return ( + <> + 共享资产列表 +
+ { + this.state.totalSelectedRows.map(item => { + return this.unSelectRow(item['id'])} + key={item['id']}>{item['name']} + }) + } +
+ + + +
+ +
+ 全部资产列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
`总计 ${total} 条` + }} + loading={this.state.loading} + /> + + + ); + } +} + +export default UserShareAsset; diff --git a/web/src/utils/utils.js b/web/src/utils/utils.js index 4a650f9..f56f8d4 100644 --- a/web/src/utils/utils.js +++ b/web/src/utils/utils.js @@ -170,4 +170,10 @@ export function compare(p) { } return 0; } +} + +export function difference(a, b) { + let aSet = new Set(a) + let bSet = new Set(b) + return Array.from(new Set(a.concat(b).filter(v => !aSet.has(v) || !bSet.has(v)))) } \ No newline at end of file