政务数据资源中心(Government data Resource center) 03专项3期主要建设内容
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.
 
 
 
 

255 lines
9.7 KiB

import React, { useEffect, useState } from 'react'
import { Input, Tooltip, Empty, Pagination, Popover, message } from 'antd'
import { InsertRowBelowOutlined, DatabaseOutlined, FileOutlined, PullRequestOutlined, KeyOutlined } from '@ant-design/icons';
import { useFsRequest, ApiTable } from '$utils';
import { connect } from 'react-redux';
import { downloadImg, markRedKeywords } from '../utils/index'
import KeyModal from '../components/keyModal';
import xlsx from 'xlsx';
const METADTA_TYPE = {
'库': 'databases',
'表': 'databases',
'文件': 'files',
'接口': 'restapis',
}
const METADTA_TYPE_NAMES = {
'库': '库表/库(Schema)',
'表': '库表/表(Table)',
'文件': '文件(File)',
'接口': '接口(Api)',
}
import './style.less';
function Retrieval(props) {
const { user, catalogs, dispatch, actions } = props;
const [keywords, setKeywords] = useState()
const [firstInput, setFirstInput] = useState()
const [page, setPage] = useState(1)
const [currentData, setCurrentData] = useState(null)
const [searchDataId, setSearchDataId] = useState(null)
const formRef = React.createRef();
// const { data: catalogs = [] } = useFsRequest({
// url: ApiTable.getResourceCatalog,
// });
useEffect(() => {
dispatch(actions.metadataManagement.getResourceCatalog())
}, [])
//检索元数据
const { data: result = {} } = useFsRequest({
url: ApiTable.searchMetadata,
query: {
keywords: keywords
},
refreshDeps: [keywords],
ready: !!keywords
});
//用户申请资源列表
const { data: approveList = {} } = useFsRequest({
url: ApiTable.approveList,
query: {
applyById: user?.id
},
refreshDeps: [user?.id],
ready: !!(user?.id)
});
//检索元数据
const { data: tableData = {} } = useFsRequest({
url: 'meta/table/data',
query: {
id: searchDataId
},
refreshDeps: [searchDataId],
ready: !!searchDataId,
});
useEffect(() => {
if (tableData?.rslt && tableData?.metaDataChildren) handleTableExport()
}, [tableData])
const handleTableExport = () => {
const metaData = result?.rows?.find(s => s.id == searchDataId)
if (!metaData) return;
let excelTitle = tableData?.metaDataChildren.map(s => {
return { k: s, v: s }
});
let workBook = {
SheetNames: [], //sheet名称
Sheets: {} //根据SheetNames名称顺序依次添加每个sheet数据
};
if (tableData?.rslt && tableData?.rslt?.length > 0) {
let sheetName = '元数据列表';
let sheetDataMap = new Map();
let sheetData = [excelTitle];
let index = 1;
tableData?.rslt.map(data => {
const arr = []
tableData?.metaDataChildren.map(s => {
arr.push(
{ k: s, v: JSON.stringify(data[s]) },
);
});
sheetData.push(arr)
index = index + 1;
})
sheetDataMap.set(sheetName, sheetData);
sheetDataMap.forEach((values, key) => {
// 写入excel
workBook.Sheets[key] = xlsx.utils.aoa_to_sheet(values);
workBook.Sheets[key]['!cols'] = [{ wpx: 50 }, { wpx: 150 }, { wpx: 180 }, { wpx: 230 }, { wpx: 230 }, { wpx: 230 }]
})
workBook.SheetNames = [sheetName];
// 将workBook写入文件
xlsx.writeFile(workBook, `${metaData?.name}-data.xlsx`);
} else {
message.info('当前资源暂无数据!')
}
}
const renderIcon = (type) => {
switch (type) {
case '库':
return <DatabaseOutlined />
case '表':
return <InsertRowBelowOutlined />
case '文件':
return <FileOutlined />
case '接口':
return <PullRequestOutlined />
default:
break;
}
}
const renderCatalog = (catalogId, rslt = '') => {
let resource = rslt
let catalog = catalogs.find(s => s.id == catalogId)
if (catalog?.parent) {
resource += renderCatalog(catalog.parent, catalog?.name + '/')
} else {
resource += catalog?.name
}
return resource
}
const renderText = (text) => {
return text?.length > 16 ? <Tooltip placement="top" title={text}>
{text.substring(0, 16) + '...'}
</Tooltip> : text
}
const renderName = (text) => {
function createMarkup(textFilter) {
return { __html: textFilter.length == text.length ? markRedKeywords(textFilter, keywords) : markRedKeywords(textFilter, keywords) + '...' };
}
return text?.length > 16 ?
<Popover placement="topRight" title={null} content={<span dangerouslySetInnerHTML={createMarkup(text)} />}>
<span dangerouslySetInnerHTML={createMarkup(text.substring(0, 16))} />
</Popover>
: <span dangerouslySetInnerHTML={createMarkup(text)} />
}
const downloadData = (s) => {
if (s?.type == '文件') {
const suffix = s?.fileName?.substring(s?.fileName?.length - 3, s?.fileName?.length)
if (suffix == 'png' || suffix == 'jpg') {
downloadImg(s.fileName)
} else {
window.open('/assets/files/common/' + s.fileName)
}
} else {
setSearchDataId(null)
setTimeout(() => {
setSearchDataId(s.id)
}, 10);
}
}
return !result?.rows ? <div className='search-container'>
<div className='title'>数据资源检索</div>
<Input addonAfter={<div onClick={() => { setKeywords(firstInput) }} style={{ color: '#fff', cursor: 'pointer' }}>搜索一下</div>}
style={{ width: '40%', marginLeft: 10, marginBottom: 30 }}
onChange={e => { setFirstInput(e.target.value) }}
onPressEnter={e => { setKeywords(e.target.value) }}
/>
</div> :
<>
<Input.Search defaultValue={keywords} style={{ width: '30%', marginLeft: 10, marginBottom: 30 }}
onSearch={value => {
setPage(1)
setKeywords(value)
}}
/>
{result?.rows?.slice((page - 1) * 10, (page - 1) * 10 + 10).map(s => {
const catalogText = renderCatalog(s?.catalog).split('/').reverse().toString().replaceAll(',', '/')
const tagText = s?.tagDatabases?.map(x => x.tag.name).toString() || '-'
return <div className='result-row'>
<div className='column1'>
{renderIcon(s?.type)}
{s?.code && <span> 代码{renderText(s?.code)}</span>}
<span> 名称{renderName(s?.name)}</span>
<span> 类型{METADTA_TYPE_NAMES[s?.type]}</span>
<span> 路径{renderText(catalogText)}</span>
<span> 标签{renderText(tagText)}</span>
</div>
<div className='column2'>相关操作<a onClick={() => { window.open(`/metadataManagement/latestMetadata?type=${METADTA_TYPE[s.type]}&treeId=${s?.catalog}&resourceId=${s.id}&catalogKey=${s.catalogKey}`) }}>定位</a>
{s?.type == '表' || s?.type == '文件' ?
user?.username !== 'SuperAmin' ?
<a onClick={() => {
const isOrgAdmin = user?.role == '系统管理员' && user?.orgId == s?.resourceCatalog?.organization?.id
if (isOrgAdmin) {
downloadData(s)
} else {
const token = approveList?.rows?.find(x => x.resourceId == s.id)?.token
if (!token) {
message.warning('您暂未申请该数据资源,请先申请该数据资源')
} else {
setCurrentData(s)
}
}
}}>下载</a> :
<a onClick={() => { downloadData(s) }}>下载</a> : ''}
</div>
</div>
})}
{result?.rows?.length > 0 && <Pagination
key={keywords}
defaultCurrent={1} total={result?.rows?.length}
style={{ float: 'right', paddingRight: '5%' }}
showTotal={total => `${total} 条数据`}
showSizeChanger={false}
onChange={(page, pageSize) => {
setPage(page)
}}
/>}
{!result?.rows?.length > 0 && <Empty />}
{currentData && <KeyModal
resourceId={currentData?.id}
approveList={approveList}
onFinish={() => {
downloadData(currentData)
setCurrentData(null)
}}
onCancel={() => { setCurrentData(null) }}
/>}
</>
}
function mapStateToProps(state) {
const { auth, resourceCatalog, global } = state;
return {
catalogs: resourceCatalog?.data || [],
user: auth.user,
actions: global.actions,
};
}
export default connect(mapStateToProps)(Retrieval)