You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
407 lines
18 KiB
407 lines
18 KiB
import React, { useEffect, useState } from 'react';
|
|
import { connect } from 'react-redux';
|
|
import { Spin, Table, Popconfirm, Button, Input, Row, Col } from 'antd';
|
|
import { ButtonGroup } from '$components';
|
|
import moment from 'moment';
|
|
import FileSaver from 'file-saver';
|
|
import MetadataFileModal from '../components/metadataFileModal';
|
|
import MetadataTagModal from '../components/metadataTagModal';
|
|
import MetadataResourceModal from '../components/metadataResourceModal';
|
|
import { RouteRequest } from '@peace/utils';
|
|
import { RouteTable } from '$utils'
|
|
|
|
const FilesTable = (props) => {
|
|
const { user, dispatch, actions, clientHeight, resourceCatalogId, resourceCatalogKey,
|
|
isRequesting, metadataModels, tagList, metadataResourceApplications, params } = props;
|
|
const { metadataManagement } = actions;
|
|
const SortValues = { 'ascend': 'asc', 'descend': 'desc' };
|
|
const [tableData, setTableData] = useState([]);
|
|
const [tableDataCount, setTableDataCount] = useState(0);//Table数据
|
|
const [updateAtSort, setUpdateAtSort] = useState('descend');
|
|
const [keywords, setKeywords] = useState('');
|
|
const [limit, setLimit] = useState(10);
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
|
|
const [selectedRows, setSelectedRows] = useState([]);
|
|
const [modalVisible, setModalVisible] = useState(false);
|
|
const [editData, setEditData] = useState({});
|
|
const [tagModalVisible, setTagModalVisible] = useState(false);
|
|
const [editTagData, setEditTagData] = useState({});
|
|
const [resourceModalVisible, setResourceModalVisible] = useState(false);
|
|
const [editResourceData, setEditResourceData] = useState({});
|
|
|
|
useEffect(() => {
|
|
dispatch(metadataManagement.getTagList());
|
|
setUpdateAtSort('descend');
|
|
initData({ limit, offset: currentPage - 1, orderDirection: SortValues[updateAtSort] });
|
|
}, []);
|
|
|
|
const initData = (query = {}) => {
|
|
dispatch(metadataManagement.getMetadataFiles({ resourceId: params?.type == 'files' ? params?.resourceId : null, catalog: resourceCatalogId, keywords, orderBy: 'updateAt', ...query })).then(res => {
|
|
if (res.success) {
|
|
setTableData(res.payload.data.rows);
|
|
setTableDataCount(res.payload.data.count);
|
|
let resourceNames = [];
|
|
res.payload.data.rows.map(r => {
|
|
resourceNames.push(r.name);
|
|
})
|
|
if (resourceNames.length)
|
|
dispatch(metadataManagement.getMetadataResourceApplications({ resourceNames: resourceNames.join(','), type: '文件' }))
|
|
}
|
|
|
|
})
|
|
}
|
|
const onEdit = (record) => {
|
|
dispatch(metadataManagement.getMetadataModels({ modelTypes: '文件' })).then(res => {
|
|
if (res.success) {
|
|
setEditData({
|
|
title: '修改文件元数据', record: {
|
|
...record, ...record.attributesParam,
|
|
files: record.fileName ? [{
|
|
url: "\\assets\\files\\common\\" + record.fileName, name: record.fileName.split('_').pop()
|
|
}] : []
|
|
}
|
|
});
|
|
setModalVisible(true);
|
|
}
|
|
})
|
|
}
|
|
const confirmDelete = (record) => {
|
|
dispatch(metadataManagement.delMetadataFiles(record.id)).then(res => {
|
|
if (res.success) {
|
|
onSearch(); setModalVisible(false);
|
|
deleteFile({ url: "\\assets\\files\\common\\" + record.fileName })
|
|
}
|
|
});
|
|
}
|
|
//删除文件
|
|
const deleteFile = (file) => {
|
|
if (file.url) {
|
|
RouteRequest.delete(RouteTable.cleanUpUploadTrash, { url: file.url });
|
|
};
|
|
}
|
|
const marking = (id) => {
|
|
dispatch(metadataManagement.getTagMetadata(id, 'file')).then(res => {
|
|
if (res.success) {
|
|
const obj = { tagSet: [], tags: [], id: id };
|
|
if (res.payload.data.length) {
|
|
const tagSetIds = res.payload.data.map(d => d.tagSet)
|
|
obj.tagSet = [...new Set(tagSetIds)];
|
|
obj.tags = res.payload.data.map(d => d.id);
|
|
}
|
|
setEditTagData({ record: obj });
|
|
setTagModalVisible(true);
|
|
}
|
|
})
|
|
}
|
|
const onConfirmTag = (values) => {
|
|
dispatch(metadataManagement.postTagMetadata({ file: editTagData.record.id, ...values })).then(res => {
|
|
if (res.success) {
|
|
onSearch(); setTagModalVisible(false);
|
|
}
|
|
});
|
|
}
|
|
const applyResources = (record) => {
|
|
setEditResourceData({ record: { resourceId: record.id, resourceName: record.name, applyBy: user.id, applyByName: user.name, resourceType: '文件' } });
|
|
setResourceModalVisible(true);
|
|
}
|
|
|
|
const onConfirmResource = (values) => {
|
|
dispatch(metadataManagement.postMetadataResourceApplications(values)).then(res => {
|
|
if (res.success) {
|
|
onSearch(); setResourceModalVisible(false);
|
|
}
|
|
});
|
|
}
|
|
const onTableChange = (pagination, filters, sorter) => {
|
|
let limit = Number.parseInt(pagination.pageSize);
|
|
let offset = Number.parseInt(pagination.current) - 1;
|
|
setCurrentPage(pagination.current);
|
|
setLimit(limit);
|
|
let query = { offset, limit, orderDirection: SortValues[updateAtSort] };
|
|
if (sorter.columnKey === 'updateAt') {
|
|
query.orderDirection = SortValues[sorter.order];
|
|
setUpdateAtSort(sorter.order);
|
|
}
|
|
setSelectedRowKeys([]);
|
|
setSelectedRows([]);
|
|
initData(query);
|
|
}
|
|
|
|
const getfilesize = (size) => {
|
|
if (!size)
|
|
return "0K";
|
|
var num = 1024.00; //byte
|
|
if (size < num)
|
|
return size + "B";
|
|
if (size < Math.pow(num, 2))
|
|
return (size / num).toFixed(2) + "KB"; //kb
|
|
if (size < Math.pow(num, 3))
|
|
return (size / Math.pow(num, 2)).toFixed(2) + "M"; //M
|
|
if (size < Math.pow(num, 4))
|
|
return (size / Math.pow(num, 3)).toFixed(2) + "G"; //G
|
|
return (size / Math.pow(num, 4)).toFixed(2) + "T"; //T
|
|
}
|
|
|
|
const columns = [
|
|
{
|
|
title: '文件名称',
|
|
dataIndex: 'name',
|
|
key: 'name',
|
|
width: '16%',
|
|
ellipsis: true
|
|
}, {
|
|
title: '文件描述',
|
|
dataIndex: 'description',
|
|
key: 'description',
|
|
width: '29%',
|
|
ellipsis: true
|
|
}, {
|
|
title: '文件类型',
|
|
dataIndex: 'type',
|
|
key: 'type',
|
|
width: '10%',
|
|
render: (text, record) => {
|
|
if (record.fileName)
|
|
return <span>{text}</span>
|
|
else
|
|
return ''
|
|
}
|
|
}, {
|
|
title: '标签',
|
|
dataIndex: 'tags',
|
|
key: 'tags',
|
|
width: '18%',
|
|
ellipsis: true,
|
|
render: (text, record, index) => {
|
|
let tagName = record.tagFiles.map(tagSet => tagSet.tag.name);
|
|
return tagName.join(',');
|
|
}
|
|
}, {
|
|
title: '大小',
|
|
dataIndex: 'size',
|
|
key: 'size',
|
|
width: '10%',
|
|
render: (text, record) => {
|
|
if (record.fileName)
|
|
return <span>{getfilesize(text)}</span>
|
|
else
|
|
return ''
|
|
}
|
|
}, {
|
|
title: '修改时间',
|
|
dataIndex: 'updateAt',
|
|
key: 'updateAt',
|
|
width: '18%',
|
|
sortOrder: updateAtSort,
|
|
sorter: (a, b) => moment(a.updateAt).valueOf() - moment(b.updateAt).valueOf(),
|
|
sortDirections: ['descend', 'ascend', 'descend'],
|
|
render: (text, record, index) => {
|
|
return text && moment(text).format('YYYY-MM-DD HH:mm:ss') || ''
|
|
}
|
|
}, {
|
|
title: '操作',
|
|
dataIndex: 'action',
|
|
width: '8%',
|
|
render: (text, record) => {
|
|
let resourceApplicationsRecords = metadataResourceApplications.filter(ra =>
|
|
ra.applyBy == user.id && ra.resourceName === record.name && ra.resourceId == record.id && !!record.token);
|
|
return <ButtonGroup>
|
|
{user.role == '数据消费者' ? null :
|
|
<>
|
|
<a style={{ marginLeft: 10 }} onClick={() => onEdit(record)}>编辑</a>
|
|
<Popconfirm
|
|
title="是否确认删除该元数据?"
|
|
onConfirm={() => confirmDelete(record)}
|
|
><a style={{ marginLeft: 10 }}>删除</a></Popconfirm>
|
|
<a style={{ marginLeft: 10 }} onClick={() => marking(record.id)}>打标</a>
|
|
</>
|
|
}
|
|
|
|
{user.role == '系统管理员' ? '' : resourceApplicationsRecords.length === 0 ?
|
|
<a style={{ marginLeft: 10 }} onClick={() => applyResources(record)}>申请资源</a> :
|
|
<span style={{ marginLeft: 10, color: "#c0c0c0" }} title='已存在资源申请'>申请资源</span>}
|
|
</ButtonGroup>
|
|
}
|
|
}];
|
|
|
|
const onSearch = () => {
|
|
setSelectedRowKeys([]);
|
|
setSelectedRows([]);
|
|
setCurrentPage(1);
|
|
initData({ limit, offset: 0, orderDirection: SortValues[updateAtSort] });
|
|
}
|
|
const handleExport = (isAll = false) => {
|
|
let tableHeader = `<tr>`;
|
|
columns.filter(c => c.dataIndex != 'action').map(c => { tableHeader += `<th><div>${c.title}</div></th>`; });
|
|
tableHeader += '</tr>';
|
|
if (isAll) {
|
|
dispatch(metadataManagement.getMetadataFiles({ catalog: resourceCatalogId })).then(res => {
|
|
if (res.success) {
|
|
handleExportTable(tableHeader, res.payload.data.rows);
|
|
}
|
|
})
|
|
} else {
|
|
let data = []
|
|
if (updateAtSort === 'descend') {
|
|
data = selectedRows.sort((a, b) => moment(b.updateAt).valueOf() - moment(a.updateAt).valueOf());
|
|
} else {
|
|
data = selectedRows.sort((a, b) => moment(a.updateAt).valueOf() - moment(b.updateAt).valueOf());
|
|
}
|
|
handleExportTable(tableHeader, data);
|
|
}
|
|
}
|
|
const handleExportTable = (tableHeader, contentData) => {
|
|
let tableContent = '';
|
|
contentData.map(cd => {
|
|
tableContent += `<tr>`;
|
|
tableContent += `<th style="font-weight:600"><div>${cd.name}</div></th>`;
|
|
tableContent += `<th style="font-weight:600"><div>${cd.description || ''}</div></th>`;
|
|
tableContent += `<th style="font-weight:600"><div>${cd.fileName ? cd.type : ''}</div></th>`;
|
|
let tagName = cd.tagFiles.map(tagSet => tagSet.tag.name);
|
|
tableContent += `<th style="font-weight:600"><div>${tagName.join(',')}</div></th>`;
|
|
tableContent += `<th style="font-weight:600"><div>${cd.fileName && cd.size ? getfilesize(cd.size) : ''}</div></th>`;
|
|
tableContent += `<th style="font-weight:600"><div>${moment(cd.updateAt).format('YYYY-MM-DD HH:mm:ss')}</div></th>`;
|
|
tableContent += `</tr>`;
|
|
})
|
|
let exportTable = `\uFEFF<table border="1">
|
|
${tableHeader}
|
|
${tableContent}
|
|
</table>`;
|
|
let tempStr = new Blob([exportTable], { type: 'text/plain;charset=utf-8' });
|
|
FileSaver.saveAs(tempStr, `文件元数据导出.xls`);
|
|
}
|
|
//新建、修改
|
|
const onConfirm = (values) => {
|
|
let obj = {}
|
|
if (editData.add) {
|
|
obj = { createBy: user.id, catalog: resourceCatalogId, catalogKey: resourceCatalogKey, ...values }
|
|
if (values.files && values.files.length) {
|
|
obj.type = values.files[0].name.split('.').pop();
|
|
obj.size = values.files[0].size;
|
|
obj.fileName = values.files[0].realName;
|
|
}
|
|
dispatch(metadataManagement.postMetadataFiles(obj)).then(res => {
|
|
if (res.success) {
|
|
onSearch(); setModalVisible(false);
|
|
}
|
|
});
|
|
} else {
|
|
obj = { catalog: resourceCatalogId, catalogKey: resourceCatalogKey, ...values }
|
|
if (values.files && values.files.length) {
|
|
obj.type = values.files[0].name.split('.').pop();
|
|
if (values.files[0].size) {
|
|
obj.size = values.files[0].size;
|
|
}
|
|
obj.fileName = values.files[0].realName;
|
|
}
|
|
dispatch(metadataManagement.putMetadataFiles(editData.record.id, obj)).then(res => {
|
|
if (res.success) {
|
|
onSearch(); setModalVisible(false);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
return <Spin spinning={isRequesting}>
|
|
<Row style={{ marginBottom: 16 }}>
|
|
<Col span={12}>
|
|
{user.role == '数据消费者' ? null : <>
|
|
<Button type='primary' onClick={() => {
|
|
dispatch(metadataManagement.getMetadataModels({ modelTypes: '文件' })).then(res => {
|
|
if (res.success) {
|
|
setEditData({ add: true, title: '新建文件元数据', record: {} });
|
|
setModalVisible(true);
|
|
}
|
|
})
|
|
}}>新建</Button>
|
|
{
|
|
tableDataCount == 0 ? <Button disabled={tableDataCount == 0} style={{ marginLeft: 16 }} onClick={() => handleExport()}>导出</Button> :
|
|
selectedRowKeys && selectedRowKeys.length ?
|
|
<Button disabled={tableDataCount == 0} style={{ marginLeft: 16 }} onClick={() => handleExport()}>导出</Button>
|
|
: <Popconfirm title={'是否导出全部?'} onConfirm={() => handleExport(true)} okText="确定" cancelText="取消">
|
|
<Button disabled={tableDataCount == 0} style={{ marginLeft: 16 }}> 导出</Button>
|
|
</Popconfirm>
|
|
}</>}
|
|
</Col>
|
|
<Col span={12} style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
|
<Input style={{ width: 220 }} placeholder="名称/类型"
|
|
allowClear onPressEnter={onSearch} onChange={e => setKeywords(e.target.value || '')} />
|
|
<Button type='primary' style={{ marginLeft: 16 }} onClick={onSearch}>查询</Button>
|
|
</Col>
|
|
</Row>
|
|
|
|
|
|
<Table
|
|
scroll={{ y: clientHeight - 320 }}
|
|
rowKey='id'
|
|
columns={columns}
|
|
dataSource={tableData}
|
|
onChange={onTableChange}
|
|
pagination={{
|
|
current: currentPage,
|
|
pageSize: limit,
|
|
total: tableDataCount,
|
|
showSizeChanger: true,
|
|
// showQuickJumper: true,
|
|
showTotal: (total) => { return <span style={{ fontSize: 15 }}>{`共${Math.ceil(total / limit)}页,${total}项`}</span> },
|
|
|
|
}}
|
|
rowSelection={{
|
|
onChange: (selectedRowKeys, selectedRows) => {
|
|
setSelectedRowKeys(selectedRowKeys)
|
|
setSelectedRows(selectedRows);
|
|
},
|
|
selectedRowKeys: selectedRowKeys
|
|
}}
|
|
>
|
|
</Table>
|
|
{
|
|
modalVisible ?
|
|
<MetadataFileModal
|
|
metadataModels={metadataModels.filter(m => m.modelType === '文件')}
|
|
editData={editData}
|
|
onCancel={(file, updateId) => {
|
|
setModalVisible(false)
|
|
if (file)
|
|
deleteFile(file);
|
|
if (updateId) {
|
|
dispatch(metadataManagement.putMetadataFiles(updateId, {}, true)).then(res => {
|
|
if (res.success) {
|
|
onSearch(); setModalVisible(false);
|
|
}
|
|
});
|
|
}
|
|
}}
|
|
onConfirm={onConfirm} /> : ''
|
|
}
|
|
{
|
|
tagModalVisible ?
|
|
<MetadataTagModal
|
|
tagList={tagList}
|
|
editData={editTagData}
|
|
onCancel={() => setTagModalVisible(false)}
|
|
onConfirm={onConfirmTag} /> : ''
|
|
}
|
|
{
|
|
resourceModalVisible ?
|
|
<MetadataResourceModal
|
|
editData={editResourceData}
|
|
onCancel={() => setResourceModalVisible(false)}
|
|
onConfirm={onConfirmResource} /> : ''
|
|
}
|
|
</Spin >
|
|
}
|
|
function mapStateToProps(state) {
|
|
const { global, auth, metadataFiles, metadataModels, tagList, tagMetadata, metadataResourceApplications } = state;
|
|
return {
|
|
user: auth.user,
|
|
actions: global.actions,
|
|
clientHeight: global.clientHeight,
|
|
isRequesting: metadataFiles.isRequesting || metadataModels.isRequesting || tagList.isRequesting
|
|
|| tagMetadata.isRequesting || metadataResourceApplications.isRequesting,
|
|
metadataModels: metadataModels.data,
|
|
tagList: tagList.data || [],
|
|
metadataResourceApplications: metadataResourceApplications.data || []
|
|
};
|
|
}
|
|
export default connect(mapStateToProps)(FilesTable)
|