peng.peng
2 years ago
17 changed files with 1604 additions and 143 deletions
@ -0,0 +1,339 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
import React, { Component } from 'react'; |
||||
|
import { connect } from 'react-redux'; |
||||
|
import { Spin, Upload, message, Modal, Card, Button } from 'antd'; |
||||
|
import moment from 'moment'; |
||||
|
import { PlusOutlined, UploadOutlined, CloseOutlined } from '@ant-design/icons'; |
||||
|
import { RouteRequest } from '@peace/utils'; |
||||
|
import { RouteTable } from '$utils' |
||||
|
const { confirm } = Modal; |
||||
|
class Uploads extends Component { |
||||
|
constructor(props) { |
||||
|
super(props); |
||||
|
this.state = { |
||||
|
fileUploading: false, |
||||
|
fileList: [], |
||||
|
curPreviewPic: '', |
||||
|
delPicIng: false, |
||||
|
removeFilesList: [] |
||||
|
}; |
||||
|
} |
||||
|
dealName = (uploaded) => { |
||||
|
let realName = uploaded.split('/')[2] |
||||
|
let x1 = realName.split('.') |
||||
|
let x2 = x1[0].split('_') |
||||
|
let showName = `${x2[0]}.${x1[1]}` |
||||
|
return showName |
||||
|
} |
||||
|
|
||||
|
// setFileList = (value) => {
|
||||
|
// let defaultFileList = [];
|
||||
|
// defaultFileList = value.map((u, index) => {
|
||||
|
// let fileUrl = `${this.ApiRoot}/${u.url}`;
|
||||
|
// return {
|
||||
|
// uid: -index - 1,
|
||||
|
// name: this.dealName(u.url),
|
||||
|
// status: 'done',
|
||||
|
// storageUrl: u.url,
|
||||
|
// url: fileUrl
|
||||
|
// };
|
||||
|
// });
|
||||
|
// onChange(defaultFileList)
|
||||
|
// this.setState({
|
||||
|
// fileList: defaultFileList
|
||||
|
// });
|
||||
|
// };
|
||||
|
|
||||
|
componentDidMount() { |
||||
|
const { value } = this.props; |
||||
|
if (value) { |
||||
|
// this.setState(value);
|
||||
|
this.setState({ fileList: value }) |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
componentWillReceiveProps(np) { |
||||
|
const { dispatch, value: thisEditData, onChange } = this.props; |
||||
|
const { value: nextEditData } = np; |
||||
|
|
||||
|
const setFileList = () => { |
||||
|
let defaultFileList = []; |
||||
|
defaultFileList = nextEditData.map((u, index) => { |
||||
|
let fileUrl = u.filename; |
||||
|
return { |
||||
|
uid: -index - 1, |
||||
|
name: u.name, |
||||
|
status: 'done', |
||||
|
storageUrl: u.filename, |
||||
|
url: fileUrl, |
||||
|
size: u.size || -1 |
||||
|
}; |
||||
|
}); |
||||
|
this.setState({ |
||||
|
fileList: defaultFileList |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
if (nextEditData && nextEditData.length) { |
||||
|
if (!thisEditData || !this.state.fileList.length) { |
||||
|
setFileList(); |
||||
|
} else if (nextEditData.length != thisEditData.length) { |
||||
|
setFileList(); |
||||
|
} else { |
||||
|
let repeat = true; |
||||
|
for (let i = 0; i < thisEditData.length; i++) { |
||||
|
if (thisEditData[i] != nextEditData[i]) { |
||||
|
repeat = false; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
if (!repeat) { |
||||
|
setFileList(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
// else{
|
||||
|
// this.setState({
|
||||
|
// fileList:[],
|
||||
|
// })
|
||||
|
// }
|
||||
|
} |
||||
|
//删除文件
|
||||
|
deleteFile(file) { |
||||
|
if (file.url) { |
||||
|
RouteRequest.delete(RouteTable.cleanUpUploadTrash, { url: file.url }); |
||||
|
}; |
||||
|
} |
||||
|
handleOk = (that, file, fileList, curPreviewPic, removeFilesList) => { |
||||
|
let nextFileList = []; |
||||
|
fileList.map((f, i) => { |
||||
|
if (f.uid != file.uid) { |
||||
|
nextFileList.push(f); |
||||
|
} |
||||
|
}); |
||||
|
that.deleteFile(file); |
||||
|
let nextRemoveFiles = removeFilesList.concat([file.storageUrl]); |
||||
|
if (curPreviewPic == file.url) { |
||||
|
that.setState({ |
||||
|
curPreviewPic: '' |
||||
|
}); |
||||
|
} |
||||
|
that.props.onChange(nextFileList); |
||||
|
that.setState({ |
||||
|
fileList: nextFileList, |
||||
|
removeFilesList: nextRemoveFiles |
||||
|
}); |
||||
|
} |
||||
|
render() { |
||||
|
const UploadPath = { |
||||
|
project: ['txt', 'dwg', 'doc', 'docx', 'xls', 'xlsx', 'pdf', 'png', 'jpg', 'rar', 'zip'], |
||||
|
report: ['doc', 'docx', 'xls', 'xlsx', 'pdf'], |
||||
|
data: ['txt', 'xls', 'xlsx'], |
||||
|
image: ['png', 'jpg', 'svg', 'jpeg'], |
||||
|
three: ['js'], |
||||
|
video: ['mp4'] |
||||
|
}; |
||||
|
/** |
||||
|
* uploadType 【string】 主要区别文件上传路径 以及类型 以 web/routes/attachment/index.js 中 UploadPath 的 key 值为准;默认 project; |
||||
|
* disabled 【boolean】 上传是否可用 |
||||
|
* maxFilesNum 【number】 最大上传数量 |
||||
|
* fileTypes 【array[string]】 可允许上传的文件类型; |
||||
|
* maxFileSize 【number】 单个文件最大大小 M |
||||
|
* listType 【antd】 upload 组件的属性 |
||||
|
* onChange 【function】 文件数量变化时候回调 返回文件 |
||||
|
* value 【array[obj]】 编辑数据 [{url:'xxx', [size:999]}] |
||||
|
* onStateChange 【function】 文件状态改变回调函数 上传中 return { uploading:true/false } |
||||
|
*/ |
||||
|
const { |
||||
|
uploadType, |
||||
|
disabled, |
||||
|
maxFilesNum, |
||||
|
fileTypes, |
||||
|
maxFileSize, |
||||
|
listType, |
||||
|
onChange, |
||||
|
value, |
||||
|
showUploadList, |
||||
|
onStateChange, |
||||
|
addNew |
||||
|
} = this.props; |
||||
|
const { fileList, curPreviewPic, delPicIng, removeFilesList } = this.state; |
||||
|
const that = this; |
||||
|
let uploadType_ = uploadType || 'project'; |
||||
|
let maxFilesNum_ = maxFilesNum || 1; |
||||
|
let defaultFileTypes = fileTypes || UploadPath[uploadType_]; |
||||
|
const uploadProps = { |
||||
|
name: 'checkFile_', |
||||
|
multiple: false, |
||||
|
showUploadList: showUploadList || true, |
||||
|
action: "/_upload/new?type=project", |
||||
|
listType: listType || 'text', |
||||
|
disabled: disabled, |
||||
|
beforeUpload: (file) => { |
||||
|
if (fileList.length >= maxFilesNum_) { |
||||
|
message.warning(`最多选择${maxFilesNum_}个文件上传`); |
||||
|
return false; |
||||
|
} |
||||
|
if (file.name.length > 60) { |
||||
|
message.warning(`文件名过长(大于60字符),请修改后上传`); |
||||
|
return false; |
||||
|
} |
||||
|
const extNames = file.name.split('.'); |
||||
|
var reg = /^[\.\s\u4e00-\u9fa5a-zA-Z0-9_-]{0,}$/; |
||||
|
// if (!reg.exec(file.name)) {
|
||||
|
// message.warning(`文件名包含除字母、汉字、数字、中划线、下划线之外的字符,请修改后上传`);
|
||||
|
// return false;
|
||||
|
// }
|
||||
|
let isDAE = false; |
||||
|
if (extNames.length > 0) { |
||||
|
let fileType = extNames[extNames.length - 1].toLowerCase(); |
||||
|
isDAE = defaultFileTypes.some((f) => f == fileType); |
||||
|
} |
||||
|
if (!isDAE) { |
||||
|
message.error(`只能上传 ${defaultFileTypes.join()} 格式的文件!`); |
||||
|
return false; |
||||
|
} |
||||
|
const isLt = file.size / 1024 / 1024 < (maxFileSize || 3); |
||||
|
if (!isLt) { |
||||
|
message.error(`文件必须小于${maxFileSize || 3}MB!`); |
||||
|
return false; |
||||
|
} |
||||
|
this.setState({ |
||||
|
fileUploading: true |
||||
|
}); |
||||
|
if (onStateChange) { |
||||
|
onStateChange({ uploading: true }); |
||||
|
} |
||||
|
}, |
||||
|
onChange(info) { |
||||
|
const status = info.file.status; |
||||
|
if (status === 'uploading') { |
||||
|
that.setState({ |
||||
|
fileList: info.fileList |
||||
|
}); |
||||
|
} |
||||
|
if (status === 'done') { |
||||
|
let { filename } = info.file.response; |
||||
|
let size = info.file.size; |
||||
|
let nextFileList = fileList; |
||||
|
nextFileList[nextFileList.length - 1] = { |
||||
|
uid: -moment().unix(), |
||||
|
name: info.file.name, |
||||
|
status: 'done', |
||||
|
storageUrl: filename, |
||||
|
url: filename, |
||||
|
size: size |
||||
|
}; |
||||
|
onChange(nextFileList); |
||||
|
that.setState({ |
||||
|
fileUploading: false, |
||||
|
fileList: nextFileList |
||||
|
}); |
||||
|
if (onStateChange) { |
||||
|
onStateChange({ uploading: false }); |
||||
|
} |
||||
|
} else if (status === 'error') { |
||||
|
that.setState({ |
||||
|
fileUploading: false |
||||
|
}); |
||||
|
message.error(`${info.file.name} 上传失败,请重试`); |
||||
|
if (onStateChange) { |
||||
|
onStateChange({ uploading: false }); |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
onRemove(file) { |
||||
|
// if (confirm('请确认是否删除此文件?删除后将不可恢复!') === true) {
|
||||
|
if (addNew) { |
||||
|
that.handleOk(that, file, fileList, curPreviewPic, removeFilesList); |
||||
|
} else { |
||||
|
confirm({ |
||||
|
title: '请确认是否删除此文件?删除后将不可恢复!', |
||||
|
onOk() { |
||||
|
that.handleOk(that, file, fileList, curPreviewPic, removeFilesList); |
||||
|
}, |
||||
|
onCancel() { }, |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
onPreview(file) { |
||||
|
let filePostfix = file.url.split('.').pop(); |
||||
|
filePostfix = filePostfix.toLowerCase(); |
||||
|
if (UploadPath.image.some((img) => img == filePostfix)) { |
||||
|
that.setState({ |
||||
|
curPreviewPic: file.url |
||||
|
}); |
||||
|
} else { |
||||
|
message.warn('仅支持图片预览'); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
let fileList_ = fileList |
||||
|
// .map(f => {
|
||||
|
// if (f.storageUrl) {
|
||||
|
// let realName = f.storageUrl.split('/').pop()
|
||||
|
// if (f.name != realName) {
|
||||
|
// f.name = realName
|
||||
|
// }
|
||||
|
// }
|
||||
|
// return f
|
||||
|
// })
|
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
<Spin spinning={delPicIng}> |
||||
|
<Upload {...uploadProps} fileList={fileList_}> |
||||
|
{ |
||||
|
disabled ? ( |
||||
|
'' |
||||
|
) : |
||||
|
listType == 'picture-card' ? |
||||
|
( |
||||
|
fileList.length >= maxFilesNum_ ? null : ( |
||||
|
<div style={{}}> |
||||
|
<PlusOutlined /> |
||||
|
<div>上传图片</div> |
||||
|
</div> |
||||
|
) |
||||
|
) : ( |
||||
|
<Button disabled={fileList.length >= maxFilesNum_} icon={<UploadOutlined />}> 文件上传 </Button> |
||||
|
) |
||||
|
} |
||||
|
</Upload> |
||||
|
{ |
||||
|
curPreviewPic ? ( |
||||
|
<Card |
||||
|
bodyStyle={{ |
||||
|
padding: 8 |
||||
|
}} |
||||
|
> |
||||
|
<div style={{ marginBottom: 8 }} > |
||||
|
<span>文件预览</span> |
||||
|
<span |
||||
|
style={{ float: 'right' }} |
||||
|
onClick={() => { this.setState({ curPreviewPic: '' }); }} |
||||
|
> |
||||
|
<CloseOutlined style={{ fontSize: 20 }} /> |
||||
|
</span> |
||||
|
</div> |
||||
|
<img style={{ width: '100%' }} src={curPreviewPic}></img> |
||||
|
</Card> |
||||
|
) : '' |
||||
|
} |
||||
|
</Spin> |
||||
|
</div> |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function mapStateToProps(state) { |
||||
|
const { auth } = state |
||||
|
return { |
||||
|
user: auth.user |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export default connect(mapStateToProps)(Uploads); |
@ -0,0 +1,174 @@ |
|||||
|
import React, { useEffect, useState } from 'react'; |
||||
|
import { Modal, Input, Form, Select, InputNumber, Tooltip, Tag, message } from 'antd'; |
||||
|
import { UploadLocal } from '$components'; |
||||
|
const { TextArea } = Input; |
||||
|
const MetadataFileModal = (props) => { |
||||
|
const { onConfirm, onCancel, editData, metadataModels } = props; |
||||
|
const [form] = Form.useForm(); |
||||
|
const [editUrl, setEditUrl] = useState([]); |
||||
|
useEffect(() => { |
||||
|
}, []); |
||||
|
const handleOk = () => { |
||||
|
form.validateFields().then(values => { |
||||
|
if (onConfirm) { |
||||
|
let dataSave = JSON.parse(JSON.stringify(values)); |
||||
|
dataSave.attributesParam = {}; |
||||
|
metadataModels.map(m => { |
||||
|
dataSave.attributesParam[m.attributeCode] = values[m.attributeCode]; |
||||
|
delete dataSave[m.attributeCode]; |
||||
|
}) |
||||
|
onConfirm(dataSave); |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
const validatorNull = (rule, value, getFieldValue, validateFields, label) => { |
||||
|
if (!value || !value.trim().length) { |
||||
|
return Promise.reject(new Error(`${label}不可空字符串`)); |
||||
|
} |
||||
|
return Promise.resolve(); |
||||
|
} |
||||
|
const renderModelItems = () => { |
||||
|
const items = metadataModels.filter(mm => mm.modelType === '文件').map(m => { |
||||
|
if (m.control === '文本框') { |
||||
|
const rules = [{ required: !m.nullable, message: '' }] |
||||
|
if (!m.nullable) { |
||||
|
rules.push(({ getFieldValue, validateFields }) => ({ |
||||
|
validator(_, value) { return validatorNull(_, value, getFieldValue, validateFields, m.attributeName) } |
||||
|
})) |
||||
|
rules.push({ max: m.length, message: `${m.attributeName}不超过${m.length}个字符` }) |
||||
|
} |
||||
|
return <Form.Item |
||||
|
label={m.attributeName.length > 10 ? <Tooltip title={m.attributeName}> |
||||
|
{m.attributeName.substring(0, 10) + '...'} |
||||
|
</Tooltip> : m.attributeName} |
||||
|
name={m.attributeCode} |
||||
|
rules={rules}> |
||||
|
<Input style={{ width: '90%' }} placeholder={`请输入${m.attributeName}`} /> |
||||
|
</Form.Item> |
||||
|
} else if (m.control === '数字输入框') { |
||||
|
const rules = [{ required: !m.nullable, message: `${m.attributeName}不可空` }] |
||||
|
let maxValue = ''; |
||||
|
let length = m.length; |
||||
|
if (length) { |
||||
|
while (length > 0) { |
||||
|
maxValue += '9' |
||||
|
length--; |
||||
|
} |
||||
|
} |
||||
|
return <Form.Item |
||||
|
label={m.attributeName.length > 10 ? <Tooltip title={m.attributeName}> |
||||
|
{m.attributeName.substring(0, 10) + '...'} |
||||
|
</Tooltip> : m.attributeName} |
||||
|
name={m.attributeCode} |
||||
|
rules={rules}> |
||||
|
<InputNumber min={0} max={maxValue ? parseInt(maxValue) : 0} precision={0} style={{ width: '90%' }} placeholder={`请输入${m.attributeName}`} /> |
||||
|
</Form.Item> |
||||
|
} else { |
||||
|
return <Form.Item |
||||
|
label={m.attributeName.length > 10 ? <Tooltip title={m.attributeName}> |
||||
|
{m.attributeName.substring(0, 10) + '...'} |
||||
|
</Tooltip> : m.attributeName} |
||||
|
name={m.attributeCode} |
||||
|
rules={[{ required: !m.nullable, message: `${m.attributeName}不可空` }]}> |
||||
|
<Select |
||||
|
placeholder={`请选择${m.attributeName}`} |
||||
|
style={{ width: '90%' }} |
||||
|
showSearch |
||||
|
optionFilterProp='children' |
||||
|
getPopupContainer={triggerNode => triggerNode.parentNode} |
||||
|
filterOption={(input, option) => option.props.children |
||||
|
.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
||||
|
> |
||||
|
<Select.Option value={'是'} key={'是'}>是</Select.Option> |
||||
|
<Select.Option value={'否'} key={'否'}>否</Select.Option> |
||||
|
</Select> |
||||
|
</Form.Item > |
||||
|
} |
||||
|
}) |
||||
|
return items; |
||||
|
} |
||||
|
|
||||
|
const vsjunct = (params) => { |
||||
|
if (params.length) { |
||||
|
let appendix = [] |
||||
|
for (let p of params) { |
||||
|
appendix.push({ |
||||
|
fName: p.name, |
||||
|
size: p.size, |
||||
|
fileSize: p.size, |
||||
|
storageUrl: p.storageUrl,//必须有storageUrl
|
||||
|
}) |
||||
|
} |
||||
|
setEditUrl(appendix) |
||||
|
} else { |
||||
|
setEditUrl([]) |
||||
|
} |
||||
|
} |
||||
|
const handleCancel = () => { |
||||
|
if (editData.add) { |
||||
|
if (form.getFieldValue('files') && form.getFieldValue('files').length) { |
||||
|
onCancel(form.getFieldValue('files')[0]); |
||||
|
} else { |
||||
|
onCancel(null); |
||||
|
} |
||||
|
} else { |
||||
|
if (!(form.getFieldValue('files') && form.getFieldValue('files').length)) { |
||||
|
message.warning('文件已被删除,可重新编辑上传'); |
||||
|
onCancel(null, editData.record.id); |
||||
|
} else { |
||||
|
if (!editData.record.files.length) { |
||||
|
message.warning('文件需确定提交,才进行入库存储'); |
||||
|
onCancel(form.getFieldValue('files')[0]); |
||||
|
} else { |
||||
|
onCancel(null); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return ( |
||||
|
<Modal title={editData.title} open={true} destroyOnClose |
||||
|
okText='确定' width={800} |
||||
|
onOk={() => handleOk(null)} |
||||
|
onCancel={() => handleCancel()}> |
||||
|
<Form form={form} labelCol={{ span: 6 }} wrapperCol={{ span: 18 }} initialValues={editData.record || {}}> |
||||
|
<Form.Item |
||||
|
label='文件名称' |
||||
|
name='name' |
||||
|
rules={[{ required: true, message: '' }, { max: 50, message: `文件名称不超过50个字符` }, |
||||
|
({ getFieldValue, validateFields }) => ({ |
||||
|
validator(_, value) { return validatorNull(_, value, getFieldValue, validateFields, '文件名称') } |
||||
|
})]}> |
||||
|
<Input style={{ width: '90%' }} placeholder={`请输入文件名称`} /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
label='文件描述' |
||||
|
name='description' |
||||
|
rules={[{ max: 255, message: `文件描述不超过255个字符` }]}> |
||||
|
<TextArea rows={4} style={{ width: '90%' }} placeholder={`请输入文件描述`} /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
label='文件' |
||||
|
name='files' |
||||
|
rules={[{ required: true, message: '文件不可为空' }]}> |
||||
|
<UploadLocal |
||||
|
addNew={editData.add || !editData.record.files.length} |
||||
|
isLocal={true} |
||||
|
maxFilesNum={1} |
||||
|
maxFileSize={40} |
||||
|
onChange={vsjunct} |
||||
|
fileTypes={["jpg", "png", "gif", "txt", "doc", "docx", "pdf", "xls", "xlsx", "zip", "rar"]} |
||||
|
value={editUrl} |
||||
|
defaultValue={editUrl} |
||||
|
fileList={editData.record.files || []} |
||||
|
/> |
||||
|
</Form.Item> |
||||
|
<Form.Item style={{ paddingLeft: 190 }}> |
||||
|
<Tag color="orange">文件大小不超过40MB,开放资源包含多个文件,建议将文件进行压缩,形成压缩包再上传</Tag> |
||||
|
<Tag color="orange">支持的文件格式:jpg,png,gif,txt,doc,docx,pdf,xsl,xlsx,zip,rar</Tag> |
||||
|
</Form.Item> |
||||
|
{renderModelItems()} |
||||
|
</Form> |
||||
|
</Modal > |
||||
|
) |
||||
|
} |
||||
|
export default MetadataFileModal; |
@ -0,0 +1,53 @@ |
|||||
|
import React, { useEffect, useState } from 'react'; |
||||
|
import { Modal, Input, Form } from 'antd'; |
||||
|
const { TextArea } = Input; |
||||
|
const MetadataResourceModal = (props) => { |
||||
|
const { onConfirm, onCancel, editData } = props; |
||||
|
const [form] = Form.useForm(); |
||||
|
useEffect(() => { |
||||
|
}, []); |
||||
|
const handleOk = () => { |
||||
|
form.validateFields().then(values => { |
||||
|
if (onConfirm) { |
||||
|
onConfirm({ ...editData.record, ...values }); |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
const validatorNull = (rule, value, getFieldValue, validateFields, label) => { |
||||
|
if (!value || !value.trim().length) { |
||||
|
return Promise.reject(new Error(`${label}不可空字符串`)); |
||||
|
} |
||||
|
return Promise.resolve(); |
||||
|
} |
||||
|
return ( |
||||
|
<Modal title={'申请资源'} open={true} destroyOnClose |
||||
|
okText='确定' width={800} |
||||
|
onOk={() => handleOk(null)} |
||||
|
onCancel={onCancel}> |
||||
|
<Form form={form} labelCol={{ span: 6 }} wrapperCol={{ span: 18 }} initialValues={editData.record || {}}> |
||||
|
<Form.Item |
||||
|
label='资源名称' |
||||
|
name='resourceName' |
||||
|
rules={[{ required: true, message: '资源名称不可空' }]}> |
||||
|
<Input disabled style={{ width: '90%' }} /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
label='申请人' |
||||
|
name='applyByName' |
||||
|
rules={[{ required: true, message: '申请人不可空' }]}> |
||||
|
<Input disabled style={{ width: '90%' }} /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
label='需求描述' |
||||
|
name='requirements' |
||||
|
rules={[{ required: true, message: '' }, { max: 255, message: `需求描述不超过255个字符` }, |
||||
|
({ getFieldValue, validateFields }) => ({ |
||||
|
validator(_, value) { return validatorNull(_, value, getFieldValue, validateFields, '需求描述') } |
||||
|
})]}> |
||||
|
<TextArea rows={4} style={{ width: '90%' }} placeholder={`请输入需求描述`} /> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
</Modal > |
||||
|
) |
||||
|
} |
||||
|
export default MetadataResourceModal; |
@ -0,0 +1,79 @@ |
|||||
|
import React, { useEffect, useState } from 'react'; |
||||
|
import { Modal, Form, Select, } from 'antd'; |
||||
|
const MetadataDatabaseTagModal = (props) => { |
||||
|
const { onConfirm, onCancel, editData, tagList } = props; |
||||
|
const [form] = Form.useForm(); |
||||
|
const [tagSet, setTagSet] = useState(editData.record.tagSet || []); |
||||
|
useEffect(() => { |
||||
|
}, []); |
||||
|
const handleOk = () => { |
||||
|
form.validateFields().then(values => { |
||||
|
if (onConfirm) { |
||||
|
onConfirm({ ...values }); |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
const renderTagItems = () => { |
||||
|
let tags = []; |
||||
|
if (tagSet.length) { |
||||
|
tagList.map(t => { |
||||
|
if (tagSet.includes(t.tagSetId)) { |
||||
|
t.tags.map(t => { |
||||
|
tags.push(<Select.Option value={t.id} key={`tag-${t.id}`}>{t.name}</Select.Option>) |
||||
|
}) |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
return tags; |
||||
|
} |
||||
|
return ( |
||||
|
<Modal title={'打标'} open={true} destroyOnClose |
||||
|
okText='确定' width={800} |
||||
|
onOk={() => handleOk(null)} |
||||
|
onCancel={onCancel}> |
||||
|
<Form form={form} labelCol={{ span: 6 }} wrapperCol={{ span: 18 }} initialValues={editData.record}> |
||||
|
<Form.Item |
||||
|
label="标签集" |
||||
|
name='tagSet' |
||||
|
rules={[{ required: true, message: '请选择标签集' }]}> |
||||
|
<Select |
||||
|
maxTagCount={5} |
||||
|
placeholder='请选择标签集' |
||||
|
style={{ width: '90%' }} |
||||
|
showSearch |
||||
|
optionFilterProp='children' |
||||
|
getPopupContainer={triggerNode => triggerNode.parentNode} |
||||
|
filterOption={(input, option) => option.props.children |
||||
|
.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
||||
|
onChange={value => { |
||||
|
setTagSet(value) |
||||
|
form.setFieldValue('tags', []); |
||||
|
}} |
||||
|
mode="multiple" |
||||
|
> |
||||
|
{tagList.map(t => <Select.Option value={t.tagSetId} key={`tagSet-${t.tagSetId}`}>{t.tagSetName}</Select.Option>)} |
||||
|
</Select> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
label="标签" |
||||
|
name='tags' |
||||
|
rules={[{ required: true, message: '请选择标签' }]}> |
||||
|
<Select |
||||
|
maxTagCount={5} |
||||
|
placeholder='请选择标签' |
||||
|
style={{ width: '90%' }} |
||||
|
showSearch |
||||
|
optionFilterProp='children' |
||||
|
getPopupContainer={triggerNode => triggerNode.parentNode} |
||||
|
filterOption={(input, option) => option.props.children |
||||
|
.toLowerCase().indexOf(input.toLowerCase()) >= 0} |
||||
|
mode="multiple" |
||||
|
> |
||||
|
{renderTagItems()} |
||||
|
</Select> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
</Modal > |
||||
|
) |
||||
|
} |
||||
|
export default MetadataDatabaseTagModal; |
@ -1,105 +1,410 @@ |
|||||
import React, { useEffect, useState } from 'react'; |
import React, { useEffect, useState } from 'react'; |
||||
import { connect } from 'react-redux'; |
import { connect } from 'react-redux'; |
||||
import { Spin, Table, Popconfirm } from 'antd'; |
import { Spin, Table, Popconfirm, Button, Input } from 'antd'; |
||||
|
import { ButtonGroup } from '$components'; |
||||
import moment from 'moment'; |
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 FilesTable = (props) => { |
||||
const { user, dispatch, actions, clientHeight, resourceCatalogId, isRequesting } = props; |
const { user, dispatch, actions, clientHeight, resourceCatalogId, resourceCatalogKey, |
||||
|
isRequesting, metadataModels, tagList, metadataResourceApplications } = props; |
||||
const { metadataManagement } = actions; |
const { metadataManagement } = actions; |
||||
const [resourceCatalogData, setResourceCatalogData] = useState([]); |
const SortValues = { 'ascend': 'asc', 'descend': 'desc' }; |
||||
const [limit, setLimit] = useState(10) |
const [tableData, setTableData] = useState([]); |
||||
const [offset, setOffset] = useState(0) |
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(() => { |
useEffect(() => { |
||||
initData(resourceCatalogId); |
dispatch(metadataManagement.getTagList()); |
||||
}, []); |
setUpdateAtSort('descend'); |
||||
|
initData({ limit, offset: currentPage - 1, orderDirection: SortValues[updateAtSort] }); |
||||
|
}, [resourceCatalogId]); |
||||
|
|
||||
const initData = (resourceCatalogId) => { |
const initData = (query = {}) => { |
||||
dispatch(metadataManagement.getMetadataFiles({ catalog: resourceCatalogId, limit, offset })).then(res => { |
dispatch(metadataManagement.getMetadataFiles({ catalog: resourceCatalogId, keywords, orderBy: 'updateAt', ...query })).then(res => { |
||||
const { data } = res.payload; |
|
||||
if (res.success) { |
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) { |
||||
|
obj.tagSet = res.payload.data.map(d => d.tagSet); |
||||
|
obj.tags = res.payload.data.map(d => d.id); |
||||
|
} |
||||
|
setEditTagData({ record: obj }); |
||||
|
setTagModalVisible(true); |
||||
} |
} |
||||
}) |
}) |
||||
} |
} |
||||
const onEdit = (record) => { } |
const onConfirmTag = (values) => { |
||||
const confirmDelete = (id) => { } |
dispatch(metadataManagement.postTagMetadata({ file: editTagData.record.id, ...values })).then(res => { |
||||
const marking = (id) => { } |
if (res.success) { |
||||
const applyResources = (id) => { } |
onSearch(); setTagModalVisible(false); |
||||
const columns = [{ |
} |
||||
|
}); |
||||
|
} |
||||
|
const applyResources = (record) => { |
||||
|
setEditResourceData({ record: { 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: '文件名称', |
title: '文件名称', |
||||
dataIndex: 'name', |
dataIndex: 'name', |
||||
key: 'name', |
key: 'name', |
||||
width: '20%' |
width: '16%', |
||||
|
ellipsis: true |
||||
}, { |
}, { |
||||
title: '文件描述', |
title: '文件描述', |
||||
dataIndex: 'description', |
dataIndex: 'description', |
||||
key: 'description', |
key: 'description', |
||||
width: '20%' |
width: '29%', |
||||
|
ellipsis: true |
||||
}, { |
}, { |
||||
title: '文件类型', |
title: '文件类型', |
||||
dataIndex: 'type', |
dataIndex: 'type', |
||||
key: 'type', |
key: 'type', |
||||
width: '20%' |
width: '10%', |
||||
|
render: (text, record) => { |
||||
|
if (record.fileName) |
||||
|
return <span>{text}</span> |
||||
|
else |
||||
|
return '' |
||||
|
} |
||||
}, { |
}, { |
||||
title: '标签', |
title: '标签', |
||||
dataIndex: 'tags', |
dataIndex: 'tags', |
||||
key: 'tags', |
key: 'tags', |
||||
width: '20%' |
width: '18%', |
||||
|
ellipsis: true, |
||||
|
render: (text, record, index) => { |
||||
|
let tagName = record.tagFiles.map(tagSet => tagSet.tag.name); |
||||
|
return tagName.join(','); |
||||
|
} |
||||
}, { |
}, { |
||||
title: '大小', |
title: '大小', |
||||
dataIndex: 'size', |
dataIndex: 'size', |
||||
key: 'size', |
key: 'size', |
||||
width: '20%' |
|
||||
}, { |
|
||||
title: '创建者', |
|
||||
dataIndex: 'createBy', |
|
||||
key: 'createBy', |
|
||||
width: '10%', |
width: '10%', |
||||
|
render: (text, record) => { |
||||
|
if (record.fileName) |
||||
|
return <span>{getfilesize(text)}</span> |
||||
|
else |
||||
|
return '' |
||||
|
} |
||||
}, { |
}, { |
||||
title: '修改时间', |
title: '修改时间', |
||||
dataIndex: 'updateAt', |
dataIndex: 'updateAt', |
||||
key: 'updateAt', |
key: 'updateAt', |
||||
width: '20%', |
width: '18%', |
||||
|
sortOrder: updateAtSort, |
||||
|
sorter: (a, b) => moment(a.updateAt).valueOf() - moment(b.updateAt).valueOf(), |
||||
|
sortDirections: ['descend', 'ascend', 'descend'], |
||||
render: (text, record, index) => { |
render: (text, record, index) => { |
||||
return text ? moment(text).format('YYYY-MM-DD HH:mm') : '' |
return text && moment(text).format('YYYY-MM-DD HH:mm:ss') || '' |
||||
} |
} |
||||
}, { |
}, { |
||||
title: '操作', |
title: '操作', |
||||
dataIndex: 'action', |
dataIndex: 'action', |
||||
width: '20%', |
width: '8%', |
||||
render: (text, record) => { |
render: (text, record) => { |
||||
return <div> |
let resourceApplicationsRecords = metadataResourceApplications.filter(ra => |
||||
<a onClick={() => onEdit(record)}>编辑</a> |
ra.applyBy == user.id && ra.resourceName === record.name); |
||||
|
return <ButtonGroup> |
||||
|
<a style={{ marginLeft: 10 }} onClick={() => onEdit(record)}>编辑</a> |
||||
<Popconfirm |
<Popconfirm |
||||
title="是否确认删除该元数据?若确认删除则关联的数据将一并删除!" |
title="是否确认删除该元数据?" |
||||
onConfirm={() => confirmDelete(record.id)} |
onConfirm={() => confirmDelete(record)} |
||||
> <a>删除</a></Popconfirm> |
> <a style={{ marginLeft: 10 }}>删除</a></Popconfirm> |
||||
|
<a style={{ marginLeft: 10 }} onClick={() => marking(record.id)}>打标</a> |
||||
<a onClick={() => marking(record.id)}>打标</a> |
{resourceApplicationsRecords.length === 0 ? |
||||
|
<a style={{ marginLeft: 10 }} onClick={() => applyResources(record)}>申请资源</a> : |
||||
<a onClick={() => applyResources(record.id)}>申请资源</a> |
<span style={{ marginLeft: 10, color: "#c0c0c0" }} title='已存在资源申请'>申请资源</span>} |
||||
</div> |
</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, isAll); |
||||
|
} |
||||
|
}) |
||||
|
} 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, isAll = false) => { |
||||
|
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.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.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].url.split('\\').pop(); |
||||
|
} |
||||
|
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].url.split('\\').pop(); |
||||
|
} |
||||
|
dispatch(metadataManagement.putMetadataFiles(editData.record.id, obj)).then(res => { |
||||
|
if (res.success) { |
||||
|
onSearch(); setModalVisible(false); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
return <Spin spinning={isRequesting}> |
return <Spin spinning={isRequesting}> |
||||
<Table scroll={{ y: clientHeight - 320 }} |
<div style={{ marginBottom: 16 }}> |
||||
rowKey='filesId' |
<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> |
||||
|
} |
||||
|
<Button type='primary' style={{ marginLeft: 16, float: 'right' }} onClick={onSearch}>查询</Button> |
||||
|
<Input style={{ width: 220, float: 'right' }} placeholder="输入名称/类型" |
||||
|
allowClear onPressEnter={onSearch} onChange={e => setKeywords(e.target.value || '')} /> |
||||
|
</div > |
||||
|
<Table |
||||
|
scroll={{ y: clientHeight - 320 }} |
||||
|
rowKey='id' |
||||
columns={columns} |
columns={columns} |
||||
dataSource={[]}> |
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> }, |
||||
|
onShowSizeChange: (currentPage, pageSize) => { |
||||
|
setCurrentPage(currentPage); |
||||
|
setLimit(pageSize); |
||||
|
}, |
||||
|
onChange: (page, pageSize) => { |
||||
|
setSelectedRowKeys([]); |
||||
|
setSelectedRows([]); |
||||
|
setCurrentPage(page); |
||||
|
setLimit(pageSize); |
||||
|
let queryParams = { |
||||
|
orderDirection: SortValues[updateAtSort], |
||||
|
page: page - 1, |
||||
|
size: pageSize |
||||
|
}; |
||||
|
initData(queryParams); |
||||
|
} |
||||
|
}} |
||||
|
rowSelection={{ |
||||
|
onChange: (selectedRowKeys, selectedRows) => { |
||||
|
setSelectedRowKeys(selectedRowKeys) |
||||
|
setSelectedRows(selectedRows); |
||||
|
}, |
||||
|
selectedRowKeys: selectedRowKeys |
||||
|
}} |
||||
|
> |
||||
</Table> |
</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 > |
</Spin > |
||||
|
|
||||
} |
} |
||||
function mapStateToProps(state) { |
function mapStateToProps(state) { |
||||
const { global, auth, metadataFiles } = state; |
const { global, auth, metadataDatabases, metadataModels, tagList, tagMetadata, metadataResourceApplications } = state; |
||||
return { |
return { |
||||
user: auth.user, |
user: auth.user, |
||||
actions: global.actions, |
actions: global.actions, |
||||
clientHeight: global.clientHeight, |
clientHeight: global.clientHeight, |
||||
isRequesting: metadataFiles.isRequesting |
isRequesting: metadataDatabases.isRequesting || metadataModels.isRequesting || tagList.isRequesting |
||||
|
|| tagMetadata.isRequesting || metadataResourceApplications.isRequesting, |
||||
|
metadataModels: metadataModels.data, |
||||
|
tagList: tagList.data || [], |
||||
|
tagMetadata: tagMetadata.data || [], |
||||
|
metadataResourceApplications: metadataResourceApplications.data || [] |
||||
}; |
}; |
||||
} |
} |
||||
export default connect(mapStateToProps)(FilesTable) |
export default connect(mapStateToProps)(FilesTable) |
Loading…
Reference in new issue