Commit 3ea3e720 by zhaochengxiang

资产管理调整

parent 597eb9fd
...@@ -98,5 +98,9 @@ div[id^='__qiankun_microapp_wrapper_'] { ...@@ -98,5 +98,9 @@ div[id^='__qiankun_microapp_wrapper_'] {
word-break: break-all; word-break: break-all;
} }
.yy-popover-content {
pointer-events: auto !important;
}
import React from "react" import React, { useEffect, useState } from "react"
import {Modal,Descriptions} from "antd" import { Modal, Typography } from "antd"
import AssetItem from './AssetItem';
const AssetDetail = (props)=>{
const { onCancel,visible, item } = props
const [ assetName, setAssetName ] = useState('');
useEffect(() => {
if (item) {
const index = (item.elements||[]).findIndex(element => element.name==='中文名称');
if (index !== -1) {
setAssetName(item.elements[index].value||'');
}
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ item ])
const AssetDetail = (props)=>{
const {handleCancle,visible,boxDetail} = props
return( return(
<Modal <Modal
title={`资产Id:${boxDetail.id}`} title={
<Typography.Paragraph
className='mr-5'
title={`资产: ${assetName||''}`}
ellipsis
>
{`资产: ${assetName||''}`}
</Typography.Paragraph>}
visible={visible} visible={visible}
width={800} width={800}
onCancel={()=>{handleCancle()}} onCancel={()=>{ onCancel && onCancel()}}
// style={{ top: 30}}
footer={null} footer={null}
> >
<Descriptions size="small" column={2} bordered> <AssetItem data={item} />
{boxDetail.elements&&boxDetail.elements.map((element, index)=>{
return(
<Descriptions.Item key={index} label={element.name}>{element.value}</Descriptions.Item>
)
})
}
</Descriptions>
</Modal> </Modal>
) )
} }
......
import React, { useEffect, useState } from 'react';
import { Avatar, Row, Col, Typography, Divider } from 'antd';
import './AssetItem.less';
const colors = [
'#BDD2FD',
'#C2C8D5',
'#FBE5A2',
'#F6C3B7',
'#B6E3F5',
'#D3C6EA',
'#FFD8B8',
'#AAD8D8',
'#FFD6E7',
];
const AssetItem = (props) => {
const { data } = props;
const [ typesOfElements, setTypesOfElements ] = useState([]);
useEffect(() => {
if (data) {
convertData();
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ data ]);
const convertData = () => {
const _typesOfElements = [];
const _types = [];
data && (data.elements||[]).forEach(element => {
if (_types.indexOf(element.type||'') === -1) {
_types.push(element.type||'');
}
})
_types.forEach(type => {
const _elements = (data.elements||[]).filter(element => (element.type||'') === type);
_typesOfElements.push({ type, elements: _elements||[] });
})
setTypesOfElements(_typesOfElements);
}
return (
<div className='asset-item'>
{
(typesOfElements||[]).map((typeOfElements, index) => {
const _type = typeOfElements.type||'';
return (
<div key={index} className='d-flex' style={{ alignItems: 'center' }}>
<Avatar className='mr-3' style={{ backgroundColor: colors[index%colors.length] }}>{ _type==='' ? '无' : _type.slice(0, 1) }</Avatar>
<div className='textOverflow' style={{ flex: 1 }}>
<Row className='mb-3' style={{ width: '100%' }}>
{
typeOfElements && typeOfElements.elements && typeOfElements.elements.map((element, _index) => {
return (
<Col className='mt-3' key={_index} md={8}>
<Typography.Paragraph title={ `${element.name||''}: ${element.value||''}` } ellipsis>
{ `${element.name||''}: ${element.value||''}` }
</Typography.Paragraph>
</Col>
);
})
}
</Row>
{ index !== ((typesOfElements||[]).length-1) && <Divider /> }
</div>
</div>
)
})
}
</div>
);
}
export default AssetItem;
\ No newline at end of file
.asset-item {
.yy-divider-horizontal {
margin: 0 !important;
}
.yy-typography, .yy-typography p {
margin-bottom: 0 !important;
}
}
\ No newline at end of file
import React,{useState, useEffect} from "react" import React,{ useState, useEffect } from "react";
import {Card,Checkbox,Button,List,Skeleton,Row,Col,Typography,Pagination ,Space,Modal,Switch} from "antd" import { Card, Checkbox, Button, List, Skeleton, Pagination, Space, Modal, Switch, Divider, Tooltip, Popover } from "antd";
import "./AssetTable.less" import { EditOutlined, ReconciliationOutlined, DeleteOutlined } from '@ant-design/icons';
import {dispatch } from '../../../../model';
import { dispatch } from '../../../../model';
import AssetModal from "./AssetModal" import AssetModal from "./AssetModal"
import AssetDetail from "./AssetDetail" import AssetDetail from "./AssetDetail"
import ImportAsset from './ImportAsset'; import ImportAsset from './ImportAsset';
import AssetItem from './AssetItem';
import ImportElement from './ImportElement';
import { showMessage } from '../../../../util'; import { showMessage } from '../../../../util';
const { Text } = Typography; import "./AssetTable.less";
const AssetTable = (props) =>{ const AssetTable = (props) =>{
const {nodeId, node} = props const {nodeId, node} = props
const [tableLoad,setTableLoad] = useState(false) const [tableLoad,setTableLoad] = useState(false)
const [attrBox,setAttrBox] = useState([]) const [attrBox,setAttrBox] = useState([])
const [attrBox2,setAttrBox2] = useState({})
const [editBox,setEditBox] = useState({}) const [editBox,setEditBox] = useState({})
const [keyWord,setKeyWord] = useState('')
const [keyMessage,setKeyMessage] = useState('')
const [tableBox,setTableBox] = useState({dataList:[],total:0,}) const [tableBox,setTableBox] = useState({dataList:[],total:0,})
const [pageNumber,setPageNumber] = useState({page:1,size:20,rebuild:0}) const [pageNumber,setPageNumber] = useState({page:1,size:20,rebuild:0})
const {dataList,total} = tableBox const {dataList,total} = tableBox
...@@ -33,30 +29,30 @@ const AssetTable = (props) =>{ ...@@ -33,30 +29,30 @@ const AssetTable = (props) =>{
const [checkValue,setCheckValue] = useState(false) const [checkValue,setCheckValue] = useState(false)
const [ assetNames, setAssetNames ] = useState([]); const [ assetNames, setAssetNames ] = useState([]);
const [ importAssetVisible, setImportAssetVisible ] = useState(false); const [ importAssetVisible, setImportAssetVisible ] = useState(false);
const [ importElementVisible, setImportElementVisible ] = useState(false);
useEffect(()=>{ useEffect(()=>{
getListBasicAttrs() getListBasicAttrs();
//eslint-disable-next-line react-hooks/exhaustive-deps //eslint-disable-next-line react-hooks/exhaustive-deps
},[]) },[])
useEffect(()=>{ useEffect(()=>{
if(nodeId) if(nodeId) {
setPageNumber({...pageNumber,page:1,rebuild:new Date().getTime()}) setPageNumber({...pageNumber,page:1,rebuild:new Date().getTime()});
}
//eslint-disable-next-line react-hooks/exhaustive-deps //eslint-disable-next-line react-hooks/exhaustive-deps
},[nodeId]) },[nodeId])
useEffect(()=>{ useEffect(()=>{
if(nodeId&&rebuild!==0) if(nodeId&&rebuild!==0) {
getTable() getTable();
}
//eslint-disable-next-line react-hooks/exhaustive-deps //eslint-disable-next-line react-hooks/exhaustive-deps
},[rebuild]) },[rebuild])
const changeCurrent=(page,size)=>{ const changeCurrent=(page,size)=>{
setPageNumber({page,size,rebuild:new Date().getTime()}) setPageNumber({page,size,rebuild:new Date().getTime()});
} }
const getListBasicAttrs=()=>{ const getListBasicAttrs=()=>{
...@@ -64,15 +60,7 @@ const AssetTable = (props) =>{ ...@@ -64,15 +60,7 @@ const AssetTable = (props) =>{
type: 'assetmanage.listBasicAttrs', type: 'assetmanage.listBasicAttrs',
payload: null, payload: null,
callback: dataBox => { callback: dataBox => {
// let box = {} setAttrBox(dataBox);
// for(let item of dataBox){
// box[item.key] = item.value
// }
// setAttrBox2(dataBox)
setAttrBox(dataBox)
},
error: () => {
} }
}) })
} }
...@@ -81,7 +69,12 @@ const AssetTable = (props) =>{ ...@@ -81,7 +69,12 @@ const AssetTable = (props) =>{
setTableLoad(true) setTableLoad(true)
dispatch({ dispatch({
type: 'assetmanage.listDataAssetsByPage', type: 'assetmanage.listDataAssetsByPage',
payload: {dirId:nodeId,pageNum:page,pageSize:size,keyword:keyMessage!==''?keyMessage:undefined}, payload: {
dirId: nodeId,
pageNum: page,
pageSize: size,
keyword: ''
},
callback: dataBox => { callback: dataBox => {
const _assetNames = []; const _assetNames = [];
(dataBox.data||[]).forEach((table) => { (dataBox.data||[]).forEach((table) => {
...@@ -101,7 +94,6 @@ const AssetTable = (props) =>{ ...@@ -101,7 +94,6 @@ const AssetTable = (props) =>{
}, },
error: () => { error: () => {
setTableLoad(false) setTableLoad(false)
} }
}) })
} }
...@@ -141,31 +133,20 @@ const AssetTable = (props) =>{ ...@@ -141,31 +133,20 @@ const AssetTable = (props) =>{
error: () => { error: () => {
} }
}) })
} }
}) })
} }
const importAssets = () => { const exportAsset = () => {
setImportAssetVisible(true);
}
const exportAssets = () => {
window.open(`/api/dataassetmanager/dataAssetApi/export?parentPath=${node.path||''}`); window.open(`/api/dataassetmanager/dataAssetApi/export?parentPath=${node.path||''}`);
} }
const more=(data)=>{ const more=(data)=>{
setVisible2({box:data,visible:true}) setVisible2({box:data,visible:true})
} }
const handleCancle2=()=>{ const handleCancle2=()=>{
setVisible2({...visible2,visible:false}) setVisible2({...visible2,visible:false})
}
const fetchTableList=()=>{
setKeyMessage(keyWord)
setPageNumber({...pageNumber,page:1,rebuild:new Date().getTime()})
} }
const onCheck =(checked)=>{ const onCheck =(checked)=>{
...@@ -192,6 +173,7 @@ const AssetTable = (props) =>{ ...@@ -192,6 +173,7 @@ const AssetTable = (props) =>{
} }
setSelectBox(checkedValue) setSelectBox(checkedValue)
} }
const dels=()=>{ const dels=()=>{
if(selectBox&&selectBox[0]!==undefined){ if(selectBox&&selectBox[0]!==undefined){
modal.confirm({ modal.confirm({
...@@ -213,50 +195,81 @@ const AssetTable = (props) =>{ ...@@ -213,50 +195,81 @@ const AssetTable = (props) =>{
}) })
}else{ }else{
showMessage("warn","请选择删除项") showMessage("warn","请选择删除项")
} }
} }
const onImportAssetCancel = (refresh = false) => { const onImportAssetVisibleChange = (visible = false, refresh = false ) => {
setImportAssetVisible(false); setImportAssetVisible(visible);
refresh && getTable(); refresh && getTable();
} }
const onImportElementVisibleChange = (visible = false) => {
setImportElementVisible(visible);
}
const onExportElementBtnClick = () => {
window.open('/api/dataassetmanager/elementApi/export');
}
return( return(
<Card <Card
bordered={false} bordered={false}
className={"asset-list"} className="asset-list"
bodyStyle={{padding:'0 10px'}} bodyStyle={{padding:'0 10px'}}
headStyle={{padding:10}} headStyle={{padding:10}}
title={ title={
<div style={{display:'flex',justifyContent:'space-between',height:32}}> <div style={{display:'flex',justifyContent:'space-between',height:32}}>
<div style={{fontSize:18,fontWeight:800,color:'#767676',lineHeight:'32px'}}>资产管理</div> <div style={{fontSize:18,fontWeight:800,color:'#767676',lineHeight:'32px'}}>资产管理</div>
<Space> <Space>
{/* <Input.Search style={{width:180,float:'right'}}
onChange={e=>{ setKeyWord(e.target.value)}}
value={keyWord}
placeholder={"请输入关键字"}
enterButton
onSearch={()=>{fetchTableList()}}
/> */}
{/* <Button type="primary" >回收站</Button> */} {/* <Button type="primary" >回收站</Button> */}
</Space> </Space>
</div> </div>
} }
> >
<div style={{display:'flex',justifyContent:'space-between',height:52,padding:'10px 0',borderBottom:'1px solid #f0f0f0',lineHeight:'32px'}}> <div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
height: 52,
padding: '10px 0',
borderBottom:'1px solid #f0f0f0'
}} >
<Switch checkedChildren="全选" unCheckedChildren="全选" checked={checkValue} onChange={onCheck} defaultChecked={false} style={{marginTop:4}}/> <Switch checkedChildren="全选" unCheckedChildren="全选" checked={checkValue} onChange={onCheck} defaultChecked={false} style={{marginTop:4}}/>
<div>
<Space> <Space>
<span>资产要素:</span>
<Popover
placement="bottom"
content={<ImportElement onCancel={onImportElementVisibleChange} />}
title='资产要素导入'
visible={importElementVisible}
onVisibleChange={onImportElementVisibleChange}
trigger="click">
<Button type="primary">导入</Button>
</Popover>
<Button type="primary" onClick={onExportElementBtnClick}>导出</Button>
</Space>
<Space className='ml-5'>
<span>资产:</span>
<Button type="primary" onClick={add}>新增</Button> <Button type="primary" onClick={add}>新增</Button>
<Button type="primary" danger onClick={dels} >删除</Button> <Button type="primary" danger onClick={dels} >删除</Button>
<Button type="primary" onClick={importAssets} >导入</Button> <Popover
<Button type="primary" onClick={exportAssets} >导出</Button> placement="bottomRight"
content={<ImportAsset node={node} onCancel={onImportAssetVisibleChange} />}
title='资产导入'
visible={importAssetVisible}
onVisibleChange={onImportAssetVisibleChange}
trigger="click">
<Button type="primary">
导入
</Button>
</Popover>
<Button type="primary" onClick={exportAsset} >导出</Button>
</Space> </Space>
</div> </div>
</div>
<Checkbox.Group style={{width:'100%'}} onChange={onChange} value={selectBox}> <Checkbox.Group style={{width:'100%'}} onChange={onChange} value={selectBox}>
<List <List
loading={tableLoad} loading={tableLoad}
...@@ -264,33 +277,32 @@ const AssetTable = (props) =>{ ...@@ -264,33 +277,32 @@ const AssetTable = (props) =>{
dataSource={dataList || []} dataSource={dataList || []}
footer={null} footer={null}
renderItem={(item, index) => ( renderItem={(item, index) => (
<List.Item <List.Item>
actions={[
<Button type="link" key="edit" onClick={()=>edit(item)}>修改</Button>,
<Button type="link"key="delete" onClick={()=>del(item)}>删除</Button>,
<Button type="link"key="detail" onClick={()=>more(item)}>详情</Button>,
]}
>
<Skeleton title={false} loading={tableLoad} active> <Skeleton title={false} loading={tableLoad} active>
<List.Item.Meta <List.Item.Meta
title={ title={
<div> <>
<div className='d-flex mt-3 mb-1' style={{ alignItems: 'center' }}>
<div className='textOverflow' style={{ flex: 1 }}>
<Checkbox value={item.id}></Checkbox> <Checkbox value={item.id}></Checkbox>
<span style={{marginLeft:8}}>{assetNames[index]||''}</span> <span title={assetNames[index]||''} style={{ marginLeft:8 }}>{assetNames[index]||''}</span>
</div> </div>
<Space className='m-3' style={{ marginLeft: 'auto' }} size='small'>
<Tooltip placement='bottom' title={'修改'}>
<Button icon={<EditOutlined />} size='small' onClick={() => { edit(item); }} />
</Tooltip>
<Tooltip placement='bottom' title={'详情'}>
<Button icon={<ReconciliationOutlined />} size='small' onClick={() => { more(item); }} />
</Tooltip>
<Tooltip placement='bottom' title={'删除'}>
<Button icon={<DeleteOutlined />} size='small' onClick={() => { del(item); }} />
</Tooltip>
</Space>
</div>
<Divider />
</>
} }
description={ description={ <AssetItem data={item} /> }
<Row>
{item.elements&&item.elements.map(element=>{
return(
<Col md={6} key={element.id||''}>
<Text>{element.name}</Text>
<Text>{element.value}</Text>
</Col>
)
})
}
</Row>}
/> />
</Skeleton> </Skeleton>
</List.Item> </List.Item>
...@@ -310,12 +322,11 @@ const AssetTable = (props) =>{ ...@@ -310,12 +322,11 @@ const AssetTable = (props) =>{
showTotal={total => `共 ${total} 条`} showTotal={total => `共 ${total} 条`}
/> />
</Checkbox.Group> </Checkbox.Group>
<AssetModal visible={visible.visible} attrBox={attrBox} editBox={editBox} addType={visible.addtype} handleCancle={handleCancle} attrBox={attrBox} nodeId={nodeId} setPageNumber={setPageNumber} pageNumber={pageNumber}/> <AssetModal visible={visible.visible} attrBox={attrBox} editBox={editBox} addType={visible.addtype} handleCancle={handleCancle} nodeId={nodeId} setPageNumber={setPageNumber} pageNumber={pageNumber}/>
<AssetDetail visible={visible2.visible} boxDetail={visible2.box} handleCancle={handleCancle2}/> <AssetDetail
<ImportAsset visible={visible2.visible}
visible={importAssetVisible} item={visible2.box}
onCancel={onImportAssetCancel} onCancel={handleCancle2}
node = {node}
/> />
{contextHolder} {contextHolder}
</Card> </Card>
......
...@@ -12,4 +12,15 @@ ...@@ -12,4 +12,15 @@
height: calc(100vh - 64px - 30px - 53px - 53px - 5px) !important; height: calc(100vh - 64px - 30px - 53px - 53px - 5px) !important;
overflow: auto !important; overflow: auto !important;
} }
.yy-divider-horizontal {
margin: 0 !important;
}
.yy-list-vertical {
.yy-list-item-meta, .yy-list-item-meta-title {
margin-bottom: 0 !important;
}
}
.yy-list-item {
padding: 0 !important;
}
} }
\ No newline at end of file
import React from 'react'; import React from 'react';
import { Modal, Button, Upload } from 'antd'; import { Button, Upload, Space } from 'antd';
import { DownloadOutlined, UploadOutlined } from '@ant-design/icons'; import { DownloadOutlined, UploadOutlined } from '@ant-design/icons';
import {dispatch } from '../../../../model'; import { dispatch } from '../../../../model';
import { showMessage } from '../../../../util';
class ImportAsset extends React.Component { class ImportAsset extends React.Component {
...@@ -25,13 +26,19 @@ class ImportAsset extends React.Component { ...@@ -25,13 +26,19 @@ class ImportAsset extends React.Component {
onOk = () => { onOk = () => {
const { node, onCancel } = this.props; const { node, onCancel } = this.props;
const { fileList } = this.state; const { fileList } = this.state;
if ((fileList||[]).length === 0) {
showMessage('info', '请先选择模版上传');
return;
}
this.setState({ confirmLoading: true }, () => { this.setState({ confirmLoading: true }, () => {
dispatch({ dispatch({
type: 'assetmanage.assetImport', type: 'assetmanage.assetImport',
payload: { fileList: fileList[0], params: { parentPath: node.path||'' } }, payload: { fileList: fileList[0], params: { parentPath: node.path||'' } },
callback: () => { callback: () => {
this.setState({ confirmLoading: false }, () => { this.setState({ confirmLoading: false }, () => {
onCancel && onCancel(true); onCancel && onCancel(false, true);
}); });
}, },
error: () => { error: () => {
...@@ -43,8 +50,8 @@ class ImportAsset extends React.Component { ...@@ -43,8 +50,8 @@ class ImportAsset extends React.Component {
render() { render() {
const { visible, onCancel } = this.props; const { onCancel } = this.props;
const { fileList } = this.state; const { fileList, confirmLoading } = this.state;
const uploadProps = { const uploadProps = {
onRemove: file => { onRemove: file => {
...@@ -64,18 +71,7 @@ class ImportAsset extends React.Component { ...@@ -64,18 +71,7 @@ class ImportAsset extends React.Component {
}; };
return ( return (
<Modal <div style={{ width: 300 }}>
forceRender
visible={visible}
title={'导入资产'}
width={520}
onOk={this.onOk}
onCancel={() => {
this.reset();
onCancel && onCancel();
}}
>
<>
<div> <div>
<Button icon={<DownloadOutlined />} onClick={ this.downloadTemplate }> <Button icon={<DownloadOutlined />} onClick={ this.downloadTemplate }>
模版下载 模版下载
...@@ -88,8 +84,16 @@ class ImportAsset extends React.Component { ...@@ -88,8 +84,16 @@ class ImportAsset extends React.Component {
</Button> </Button>
</Upload> </Upload>
</div> </div>
</> <div className='mt-3 d-flex pt-3' style={{ borderTop: '1px solid rgba(0, 0, 0, 0.06)' }} >
</Modal> <Space style={{ marginLeft: 'auto' }}>
<Button onClick={() => {
this.reset();
onCancel && onCancel();
}}>取消</Button>
<Button type='primary' onClick={this.onOk} loading={confirmLoading} >确定</Button>
</Space>
</div>
</div>
) )
} }
} }
......
import React, { useState } from 'react';
import { Button, Upload, Space } from 'antd';
import { DownloadOutlined, UploadOutlined } from '@ant-design/icons';
import { dispatchLatest } from '../../../../model';
import { showMessage } from '../../../../util';
const ImportElement = (props) => {
const { onCancel } = props;
const [ fileList, setFileList ] = useState([]);
const [ confirmLoading, setConfirmLoading ] = useState(false);
const downloadTemplate = () => {
window.open("/data-govern/docs/ElementModel.xlsx");
}
const uploadProps = {
onRemove: file => {
const index = fileList.indexOf(file);
const newFileList = fileList.slice();
newFileList.splice(index, 1);
setFileList(newFileList);
},
beforeUpload: file => {
setFileList([file]);
return false;
},
fileList: fileList||[],
accept:".xlsx",
};
const handleOk = () => {
if ((fileList||[]).length === 0) {
showMessage('info', '请先选择模版上传');
return;
}
setConfirmLoading(true);
dispatchLatest({
type: 'dataassetelement.importElement',
payload: { fileList },
callback: data => {
setConfirmLoading(false);
reset();
onCancel && onCancel();
},
error: () => {
setConfirmLoading(false);
}
})
}
const reset = () => {
setFileList([]);
}
return (
<div style={{ width: 300 }}>
<div>
<Button icon={<DownloadOutlined />} onClick={ downloadTemplate }>
模版下载
</Button>
</div>
<div className='mt-3'>
<Upload {...uploadProps}>
<Button icon={<UploadOutlined />}>
选择文件上传
</Button>
</Upload>
</div>
<div className='mt-3 d-flex pt-3' style={{ borderTop: '1px solid rgba(0, 0, 0, 0.06)' }} >
<Space style={{ marginLeft: 'auto' }}>
<Button onClick={() => {
reset();
onCancel && onCancel();
}}>取消</Button>
<Button type='primary' onClick={handleOk} loading={confirmLoading} >确定</Button>
</Space>
</div>
</div>
)
}
export default ImportElement;
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment