Commit f94d2407 by zhaochengxiang

增加管理信息

parent 4a1a9224
...@@ -11,7 +11,7 @@ import { Action, CatalogId, ModelerId, Hints, ModelerData, PermitCheckOut, Edita ...@@ -11,7 +11,7 @@ import { Action, CatalogId, ModelerId, Hints, ModelerData, PermitCheckOut, Edita
import HistoryAndVersionDrawer from './HistoryAndVersionDrawer'; import HistoryAndVersionDrawer from './HistoryAndVersionDrawer';
import { EditModelContext } from './ContextManage'; import { EditModelContext } from './ContextManage';
import EditInherited from './EditInherited'; import EditInherited from './EditInherited';
import { ImportActionHeaderSubject } from './ImportActionHeader'; import { ImportActionHeaderSubject } from './ImportActionManage';
import PermissionButton from '../../../../util/Component/PermissionButton'; import PermissionButton from '../../../../util/Component/PermissionButton';
import './EditModel.less'; import './EditModel.less';
......
...@@ -6,6 +6,7 @@ import ImportActionHeader from './ImportActionHeader'; ...@@ -6,6 +6,7 @@ import ImportActionHeader from './ImportActionHeader';
import ImportActionInherited from './ImportActionInherited'; import ImportActionInherited from './ImportActionInherited';
import { ImportActionTable } from './ImportActionTable'; import { ImportActionTable } from './ImportActionTable';
import ImportActionIndex from './ImportActionIndex'; import ImportActionIndex from './ImportActionIndex';
import ImportActionManage from './ImportActionManage';
import { getInternalCurrentAnchor, getQueryParam } from '../../../../util'; import { getInternalCurrentAnchor, getQueryParam } from '../../../../util';
import { Action } from '../../../../util/constant'; import { Action } from '../../../../util/constant';
import { dispatch } from '../../../../model'; import { dispatch } from '../../../../model';
...@@ -131,6 +132,7 @@ const ImportAction = React.forwardRef((props, ref) => { ...@@ -131,6 +132,7 @@ const ImportAction = React.forwardRef((props, ref) => {
'model-import-action-technical', 'model-import-action-technical',
'model-import-action-table', 'model-import-action-table',
'model-import-action-index', 'model-import-action-index',
'model-import-action-manage',
], ],
0, 0,
5, 5,
...@@ -588,6 +590,7 @@ const ImportAction = React.forwardRef((props, ref) => { ...@@ -588,6 +590,7 @@ const ImportAction = React.forwardRef((props, ref) => {
<Tabs.TabPane tab='技术信息' key="model-import-action-technical" /> <Tabs.TabPane tab='技术信息' key="model-import-action-technical" />
<Tabs.TabPane tab='数据表结构' key="model-import-action-table" /> <Tabs.TabPane tab='数据表结构' key="model-import-action-table" />
<Tabs.TabPane tab='数据表索引' key="model-import-action-index" /> <Tabs.TabPane tab='数据表索引' key="model-import-action-index" />
<Tabs.TabPane tab='管理信息' key="model-import-action-manage" />
</Tabs> </Tabs>
</div> </div>
<div ref={setContainer} style={{ height: action==='edit-inherite-modal'?'60vh':'calc(100vh - 44px - 64px - 82px)', overflow: 'auto', padding: '0 20px' }}> <div ref={setContainer} style={{ height: action==='edit-inherite-modal'?'60vh':'calc(100vh - 44px - 64px - 82px)', overflow: 'auto', padding: '0 20px' }}>
...@@ -627,6 +630,11 @@ const ImportAction = React.forwardRef((props, ref) => { ...@@ -627,6 +630,11 @@ const ImportAction = React.forwardRef((props, ref) => {
editable={action!=='detail'&&action!=='flow'&&action!=='detail-version'&&action!=='edit-inherited'} editable={action!=='detail'&&action!=='flow'&&action!=='detail-version'&&action!=='edit-inherited'}
terms={terms} terms={terms}
/> />
<ImportActionManage
form={form}
modelerData={modelerData||{}}
editable={action!=='detail'&&action!=='flow'&&action!=='detail-version'&&action!=='edit-inherited'}
/>
</div> </div>
</div> </div>
} }
......
...@@ -46,31 +46,17 @@ const updateOptions = [ ...@@ -46,31 +46,17 @@ const updateOptions = [
const dataTypeRemark = '描述ETL框架中目标表的数据类型'; const dataTypeRemark = '描述ETL框架中目标表的数据类型';
const bindingLoadRemark = '描述ETL框架绑定加载列表,如chain、daily、current等'; const bindingLoadRemark = '描述ETL框架绑定加载列表,如chain、daily、current等';
export const ImportActionHeaderSubject = new Subject();
const ImportActionHeader = (props) => { const ImportActionHeader = (props) => {
const { editable, form, modelerData, constraints, templates, onConstraintChange, onTemplateChange, validateReports, onChange, terms, supportedPartitionTypes } = props; const { editable, form, modelerData, constraints, templates, onConstraintChange, onTemplateChange, validateReports, onChange, terms, supportedPartitionTypes } = props;
const [ options, setOptions ] = useState([]); const [ options, setOptions ] = useState([]);
const [ autoTranslate, setAutoTranslate ] = useState(false); const [ autoTranslate, setAutoTranslate ] = useState(false);
const [ maintenanceRecords, setMaintenanceRecords ] = useState(null);
const [ dataTypeList, setDataTypeList ] = useState(null); const [ dataTypeList, setDataTypeList ] = useState(null);
const [ bindingLoadRangeList, setBindingLoadRangeList ] = useState(null); const [ bindingLoadRangeList, setBindingLoadRangeList ] = useState(null);
const [isCollapse, setCollapse] = useState(true) const [isCollapse, setCollapse] = useState(true)
useEffect(() => { useEffect(() => {
const $$header = ImportActionHeaderSubject.subscribe((act) => {
if (act?.type === 'refreshMaintenanceRecords') {
getMaintenanceRecords();
}
})
return () => {
$$header.unsubscribe()
}
}, [modelerData])
useEffect(() => {
getDataTypeList(); getDataTypeList();
}, []) }, [])
...@@ -87,30 +73,11 @@ const ImportActionHeader = (props) => { ...@@ -87,30 +73,11 @@ const ImportActionHeader = (props) => {
setAutoTranslate((modelerData.name||'')===''); setAutoTranslate((modelerData.name||'')==='');
if (modelerData) { if (modelerData) {
form?.setFieldsValue(modelerData); form?.setFieldsValue(modelerData);
if ((modelerData.id||'')!=='' && maintenanceRecords===null) {
getMaintenanceRecords();
}
} }
//eslint-disable-next-line react-hooks/exhaustive-deps //eslint-disable-next-line react-hooks/exhaustive-deps
}, [modelerData]) }, [modelerData])
useEffect(() => {
if ((maintenanceRecords||[]).length>0) {
let maintenanceDescription = '';
maintenanceRecords.forEach((record, index) => {
if (index !== 0) {
maintenanceDescription += '/';
}
maintenanceDescription += record;
})
form?.setFieldsValue({ maintenanceRecords: maintenanceDescription });
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [maintenanceRecords, editable])
//分布 //分布
const distributionDescription = useMemo(() => { const distributionDescription = useMemo(() => {
let newDistributionDescription = '' let newDistributionDescription = ''
...@@ -194,20 +161,6 @@ const ImportActionHeader = (props) => { ...@@ -194,20 +161,6 @@ const ImportActionHeader = (props) => {
}, },
}; };
const getMaintenanceRecords = () => {
dispatch({
type: 'datamodel.getMaintenanceRecords',
payload: {
params: {
id: modelerData.id
}
},
callback: data => {
setMaintenanceRecords(data);
}
})
}
const getDataTypeList = () => { const getDataTypeList = () => {
dispatch({ dispatch({
type: 'datamodel.dataTypeList', type: 'datamodel.dataTypeList',
...@@ -318,14 +271,14 @@ const ImportActionHeader = (props) => { ...@@ -318,14 +271,14 @@ const ImportActionHeader = (props) => {
> >
<Row gutter={10}> <Row gutter={10}>
<Col xs={24} sm={24} lg={12} xl={8}> <Col xs={24} sm={24} lg={12} xl={8}>
<Form.Item <Form.Item
label={<ItemTitle name='cnName' cnName='中文名称' validateReports={validateReports} />} label={<ItemTitle name='cnName' cnName='中文名称' validateReports={validateReports} />}
name="cnName" name="cnName"
rules={[{ required: true, message: '请输入中文名称!' }]} rules={[{ required: true, message: '请输入中文名称!' }]}
style={{ marginBottom }} style={{ marginBottom }}
> >
<InputDebounce /> <InputDebounce />
</Form.Item> </Form.Item>
</Col> </Col>
<Col xs={24} sm={24} lg={12} xl={8}> <Col xs={24} sm={24} lg={12} xl={8}>
<Form.Item <Form.Item
......
import React from 'react'
import { Button, Form, Descriptions, Input, Row, Col } from 'antd'
import { DownOutlined, UpOutlined } from '@ant-design/icons'
import { Subject } from 'rxjs';
import { dispatch } from '../../../../model'
export const ImportActionHeaderSubject = new Subject();
const FC = (props) => {
const { editable, form, modelerData } = props
const [isCollapse, setCollapse] = React.useState(true)
const [maintenanceRecords, setMaintenanceRecords] = React.useState()
React.useEffect(() => {
if (modelerData?.id) {
getMaintenanceRecords()
}
const $$header = ImportActionHeaderSubject.subscribe((act) => {
if (act?.type === 'refreshMaintenanceRecords') {
getMaintenanceRecords();
}
})
return () => {
$$header.unsubscribe()
}
}, [modelerData])
const maintenanceDescription = React.useMemo(() => {
if ((maintenanceRecords??[]).length>0) {
let newDescription = ''
for (const [index, record] of maintenanceRecords.entries()) {
if (index !== 0) {
newDescription += '/'
}
newDescription += record
}
return newDescription
}
return ''
}, [maintenanceRecords])
const getMaintenanceRecords = () => {
dispatch({
type: 'datamodel.getMaintenanceRecords',
payload: {
params: {
id: modelerData?.id
}
},
callback: data => {
setMaintenanceRecords(data);
}
})
}
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 18 },
},
};
return (
<div className='model-import-action-header'>
<div className='model-import-action-manage mb-3' style={{
display: 'flex',
alignItems: 'center',
}}
>
<h2 className='mr-3' style={{ marginBottom: 0 }}>管理信息</h2>
{
isCollapse ? <Button type='primary' size='small' onClick={() => {
setCollapse(!isCollapse)
}}>展开<DownOutlined /></Button> : <Button type='primary' size='small' onClick={() => {
setCollapse(!isCollapse)
}}>收起<UpOutlined /></Button>
}
</div>
{
!isCollapse && <React.Fragment>
{
editable ? (
<Form form={form} {...formItemLayout}>
<Row gutter={10}>
<Col xs={24} sm={24} lg={12} xl={8}>
<Form.Item
label="维护历史"
>
<Input.TextArea rows={3} disabled={true} value={maintenanceDescription} />
</Form.Item>
</Col>
</Row>
</Form>
) : (
<Descriptions column={3}>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }} >维护历史</div>} >
<div style={{ maxHeight: 70, overflow: 'auto' }}>
{
(maintenanceRecords||[]).map((record, index) => {
return <div key={index}>{record||''}</div>;
})
}
</div>
</Descriptions.Item>
</Descriptions>
)
}
</React.Fragment>
}
</div>
)
}
export default FC
\ No newline at end of file
import React, { useState, useEffect, useMemo, useRef } from 'react';
import { Form, Input, Row, Col, Descriptions, Select, AutoComplete, Button, Divider, Tooltip, Checkbox, Space } from 'antd';
import { DownOutlined, UpOutlined, ExclamationCircleFilled, WarningFilled } from '@ant-design/icons';
import { Subject } from 'rxjs';
import { highlightSearchContentByTerms, generateUUID, IsArr } from '../../../../util';
import { dispatch, dispatchLatest } from '../../../../model';
import DebounceInput from './DebounceInput';
import './ImportActionHeader.less';
const { TextArea } = Input;
const { Option } = Select;
const InputDebounce = DebounceInput(300)(Input);
const loadOptions = ['append', 'refresh', 'insert', 'update', 'full', 'chain', 'delete', '手工导入'];
const updateOptions = [
'每个交易日早间交易前加载上一交易日数据,历史资料入历史表',
'每个交易日早间交易前清空该表,交易期间实时加载,下午收市后入历史表',
'每个交易日7:30加载',
'每个交易日8:30加载',
'每个交易日15:00加载',
'每个交易日18:00加载',
'每个交易日19:00加载',
'每个交易日19:30加载',
'每个交易日20:00加载',
'每个交易日22:00加载',
'每个交易日23:00加载',
'每个交易日20:00加载T-2的数据',
'每日中午12:00加载T-3日数据',
'实时更新',
'收盘后加载',
'收市后加载',
'下午收市后加载',
'下午收市后入历史表',
'下午收市后入实时和历史表',
'晚间结算后加载',
'实时从mysql同步',
'手工维护',
'用户提交',
'作业提交',
'脚本加载',
];
const dataTypeRemark = '描述ETL框架中目标表的数据类型';
const bindingLoadRemark = '描述ETL框架绑定加载列表,如chain、daily、current等';
export const ImportActionHeaderSubject = new Subject();
const ImportActionHeader = (props) => {
const { editable, form, modelerData, constraints, templates, onConstraintChange, onTemplateChange, validateReports, onChange, terms, supportedPartitionTypes } = props;
const [ options, setOptions ] = useState([]);
const [ autoTranslate, setAutoTranslate ] = useState(false);
const [ onlyShowRequireChange, setOnlyShowRequireChange ] = useState(true);
const [ maintenanceRecords, setMaintenanceRecords ] = useState(null);
const [ dataTypeList, setDataTypeList ] = useState(null);
const [ bindingLoadRangeList, setBindingLoadRangeList ] = useState(null);
useEffect(() => {
const $$header = ImportActionHeaderSubject.subscribe((act) => {
if (act?.type === 'refreshMaintenanceRecords') {
getMaintenanceRecords();
}
})
return () => {
$$header.unsubscribe()
}
}, [modelerData])
useEffect(() => {
getDataTypeList();
}, [])
useEffect(() => {
if (modelerData?.dataType) {
getBindingLoadRangeList(modelerData?.dataType);
} else {
setBindingLoadRangeList([]);
}
}, [modelerData?.dataType])
useEffect(() => {
setAutoTranslate((modelerData.name||'')==='');
if (modelerData) {
form?.setFieldsValue(modelerData);
if ((modelerData.id||'')!=='' && maintenanceRecords===null) {
getMaintenanceRecords();
}
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [modelerData])
useEffect(() => {
if ((maintenanceRecords||[]).length>0) {
let maintenanceDescription = '';
maintenanceRecords.forEach((record, index) => {
if (index !== 0) {
maintenanceDescription += '/';
}
maintenanceDescription += record;
})
form?.setFieldsValue({ maintenanceRecords: maintenanceDescription });
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [maintenanceRecords, editable])
//分布
const distributionDescription = useMemo(() => {
let newDistributionDescription = ''
if (!editable && modelerData) {
if (modelerData?.easyDataModelerDistributionKey) {
(modelerData?.easyDataModelerDistributionKey||[]).forEach((item, index) => {
if (index > 0) {
newDistributionDescription += ',';
}
newDistributionDescription += item.name||'';
});
}
}
return newDistributionDescription;
}, [editable, modelerData])
//主键
const primaryDescription = useMemo(() => {
let newPrimaryDescription = ''
if (modelerData?.easyDataModelerPrimaryKey) {
(modelerData?.easyDataModelerPrimaryKey||[]).forEach((item, index) => {
if (index > 0) {
newPrimaryDescription += ',';
}
newPrimaryDescription += item.name||'';
})
}
return newPrimaryDescription;
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [editable, modelerData])
//分区
const partitionsDescription = useMemo(() => {
let newPartitionsDescription = ''
if (modelerData?.partition?.keys) {
(modelerData?.partition?.keys||[]).forEach((item, index) => {
if (index > 0) {
newPartitionsDescription += ',';
}
newPartitionsDescription += item.name||'';
})
}
if (modelerData?.partition?.partitionType?.cnName) {
newPartitionsDescription += '/' + modelerData?.partition?.partitionType?.cnName||'';
}
return newPartitionsDescription;
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [editable, modelerData])
//类主键
const semiPrimaryDescription = useMemo(() => {
let newSemiPrimaryDescription = ''
if (modelerData?.easyDataModelerSemiPrimaryKey) {
(modelerData?.easyDataModelerSemiPrimaryKey||[]).forEach((item, index) => {
if (index > 0) {
newSemiPrimaryDescription += ',';
}
newSemiPrimaryDescription += item.name||'';
})
}
return newSemiPrimaryDescription;
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [editable, modelerData])
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 18 },
},
};
const getMaintenanceRecords = () => {
dispatch({
type: 'datamodel.getMaintenanceRecords',
payload: {
params: {
id: modelerData.id
}
},
callback: data => {
setMaintenanceRecords(data);
}
})
}
const getDataTypeList = () => {
dispatch({
type: 'datamodel.dataTypeList',
callback: data => {
setDataTypeList(data);
}
})
}
const getBindingLoadRangeList = (dataTypeName) => {
dispatch({
type: 'datamodel.bindingLoadRangeList',
payload: {
dataTypeName
},
callback: data => {
setBindingLoadRangeList(data);
}
})
}
const onSearch = (searchText) => {
const _searchText = searchText.replace(/ /g,'');
if (_searchText !== '') {
dispatchLatest({
type: 'datamodel.autocomplete',
payload: {
params: {
word: _searchText,
isEasyDataModelerDataModelAttribute: false,
}
},
callback: data => {
const _options = [];
(data||[]).forEach(item => {
_options.push({ value: item });
})
setOptions(_options);
}
})
} else {
dispatchLatest({
type: 'datamodel.recommandEnglishWords',
payload: {
params: {
chineseWord: modelerData.cnName,
}
},
callback: data => {
const _options = [];
(data||[]).forEach(item => {
_options.push({ value: item });
})
setOptions(_options);
}
})
}
}
const onValuesChange = (changedValues, allValues) => {
if (changedValues.hasOwnProperty('tableType')) return;
onChange && onChange(changedValues, allValues);
//有手动编辑过英文名称并且有内容的情况下, 不能通过编辑中文名称自动翻译
if (changedValues.hasOwnProperty('name')) {
setAutoTranslate(changedValues.name==='');
} else if (changedValues.hasOwnProperty('cnName')) {
if (autoTranslate) {
dispatchLatest({
type: 'datamodel.translatePhase',
payload: {
params: {
phaseInChinese: changedValues.cnName,
}
},
callback: data => {
if ((data?.translated||'') !== '') {
form?.setFieldsValue({ name: data?.translated||'' });
onChange && onChange({...changedValues, ...{name: data?.translated||''}}, {...allValues, ...{name: data?.translated||''}});
}
}
})
}
} else if (changedValues.hasOwnProperty('dataType')) {
if (changedValues.dataType) {
onChange?.({...changedValues, bindingLoadRange: ''}, {...allValues, bindingLoadRange: ''});
} else {
onChange?.({...changedValues, bindingLoadRange: ''}, {...allValues, bindingLoadRange: ''});
}
}
}
const onOnlyShowRequireChange = () => {
setOnlyShowRequireChange(!onlyShowRequireChange);
}
return (
<div className='model-import-action-header' id='model-import-action-header'>
<div
className='mb-3'
style={{
display: 'flex',
alignItems: 'center',
}}
>
<h2 className='mr-3' style={{ marginBottom: 0 }}>基本信息</h2>
{
(onlyShowRequireChange ? <Button type='primary' size='small' onClick={onOnlyShowRequireChange}>展开<DownOutlined /></Button> : <Button type='primary' size='small' onClick={onOnlyShowRequireChange}>收起<UpOutlined /></Button>)
}
</div>
{
editable ? (
<Form
form={form}
{...formItemLayout}
onValuesChange={onValuesChange}
>
<Row gutter={10}>
<Col xs={24} sm={24} lg={12} xl={8}>
<Form.Item
label={<ItemTitle name='cnName' cnName='中文名称' validateReports={validateReports} />}
name="cnName"
rules={[{ required: true, message: '请输入中文名称!' }]}
>
<InputDebounce />
</Form.Item>
</Col>
<Col xs={24} sm={24} lg={12} xl={8}>
<Form.Item
label={<ItemTitle name='name' cnName='英文名称' validateReports={validateReports} />}
name="name"
rules={[{ required: true, message: '请输入英文名称!' }]}
>
<AutoComplete
options={options}
onSearch={onSearch}
/>
</Form.Item>
</Col>
<Col xs={24} sm={24} lg={12} xl={8}>
<Form.Item
label="规范"
name="easyDataModelerModelingConstraint"
rules={[{ required: true, message: '请选择规范!' }]}
>
<ConstraintSelect
constraints={constraints}
onChange={onConstraintChange}
/>
</Form.Item>
</Col>
<Col xs={24} sm={24} lg={12} xl={8}>
<Form.Item
label={<ItemTitle name='remark' cnName='数据内容' validateReports={validateReports} />}
name="remark"
rules={[{ required: true, message: '请输入数据内容!' }]}
style={{ marginBottom: 15 }}
>
<TextArea rows={4} placeholder='描述数据表包含的业务数据,包括数据内容业务描述、表的适用范围、数据粒度、数据统计口径、数据来源等。对于原始数据表,可以说明加载的源接口信息。' />
</Form.Item>
</Col>
<Col xs={24} sm={24} lg={12} xl={8}>
<Form.Item
label="数据表类型"
name="tableType"
rules={[{ required: true, message: '请选择数据表类型!' }]}
>
<TemplateSelect
modelerData={modelerData}
templates={templates}
onChange={onTemplateChange}
/>
</Form.Item>
</Col>
</Row>
{
!onlyShowRequireChange && <React.Fragment>
<Divider style={{ margin: '0 0 15px' }} />
<Row gutter={10}>
<Col xs={24} sm={24} lg={12} xl={8}>
<Row>
<Col span={24}>
<Form.Item
label="技术主键"
name="easyDataModelerPrimaryKey"
>
<AttributesSelect modelerData={modelerData} mode='tags' />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="分布键"
name="easyDataModelerDistributionKey"
>
<AttributesSelect modelerData={modelerData} />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="分区键"
name="partition"
>
<PartitionSelect modelerData={modelerData} partitionTypes={supportedPartitionTypes} />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="类主键"
name="easyDataModelerSemiPrimaryKey"
>
<AttributesSelect modelerData={modelerData} mode='tags' />
</Form.Item>
</Col>
</Row>
</Col>
<Col xs={24} sm={24} lg={12} xl={8}>
<Row>
<Col span={24}>
<Form.Item
label="数据平台"
name="dataResidence"
>
<Input placeholder='描述数据表落地的数据平台及数据库' />
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="数据类型"
name="dataType"
tooltip={dataTypeRemark}
>
<Select allowClear placeholder='请选择数据类型'>
{
dataTypeList?.map((item, index) => <Option key={index} value={item}>
{item}
</Option>)
}
</Select>
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="绑定加载范围"
name="bindingLoadRange"
tooltip={bindingLoadRemark}
>
<Select allowClear placeholder='请选择绑定加载范围'>
{
bindingLoadRangeList?.map((item, index) => <Option key={index} value={item}>
{item}
</Option>)
}
</Select>
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="加载方式"
name="dataLoadingStrategy"
>
<LoadSelect />
</Form.Item>
</Col>
</Row>
</Col>
<Col xs={24} sm={24} lg={24} xl={8}>
<Row>
<Col xs={24} sm={24} lg={12} xl={24}>
<Form.Item
label="数据情况"
name="dataCircumstances"
>
<Input placeholder='描述数据表中数据的更新频率、每日增量情况、数据量级和历史数据' />
</Form.Item>
</Col>
<Col xs={24} sm={24} lg={12} xl={24}>
<Form.Item
label="更新时间"
name="dataUpdatingTiming"
>
<UpdateSelect placeholder='描述数据表的更新时间点'/>
</Form.Item>
</Col>
<Col xs={24} sm={24} lg={12} xl={24}>
<Form.Item
label="维护历史"
name="maintenanceRecords"
>
<TextArea rows={3} disabled={true} />
</Form.Item>
</Col>
</Row>
</Col>
</Row>
</React.Fragment>
}
</Form>
) : (
<React.Fragment>
<Descriptions column={3}>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}><ItemTitle name='cnName' cnName='中文名称' validateReports={validateReports} /></div>} >{highlightSearchContentByTerms(modelerData.cnName||'', terms)}</Descriptions.Item>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}><ItemTitle name='name' cnName='英文名称' validateReports={validateReports} /></div>}>{highlightSearchContentByTerms(modelerData.name||'', terms)}</Descriptions.Item>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}>规范</div>} >{modelerData.easyDataModelerModelingConstraint?(modelerData.easyDataModelerModelingConstraint.cnName||''):''}</Descriptions.Item>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}><ItemTitle name='remark' cnName='数据内容' validateReports={validateReports} /></div>}>{highlightSearchContentByTerms(modelerData.remark||'', terms)}</Descriptions.Item>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}>数据表类型</div>} >{modelerData.tableType}</Descriptions.Item>
</Descriptions>
{
!onlyShowRequireChange && <Divider style={{ margin: '0 0 15px' }} />
}
{
!onlyShowRequireChange && <React.Fragment>
<Descriptions column={3}>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}>技术主键</div>} >{highlightSearchContentByTerms(primaryDescription||'', terms)}</Descriptions.Item>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}>数据平台</div>} >{highlightSearchContentByTerms(modelerData.dataResidence||'', terms)}</Descriptions.Item>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}>数据情况</div>} >{highlightSearchContentByTerms(modelerData.dataCircumstances||'', terms)}</Descriptions.Item>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}>分布键</div>} >{highlightSearchContentByTerms(distributionDescription||'', terms)}</Descriptions.Item>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}>数据类型</div>} >{highlightSearchContentByTerms(modelerData.dataType||'', terms)}</Descriptions.Item>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}>更新时间</div>} >{highlightSearchContentByTerms(modelerData.dataUpdatingTiming||'', terms)}</Descriptions.Item>
</Descriptions>
<Row>
<Col span={16}>
<Descriptions column={2}>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}>分区键</div>} >{highlightSearchContentByTerms(partitionsDescription||'', terms)}</Descriptions.Item>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}>绑定加载范围</div>} >{highlightSearchContentByTerms(modelerData.bindingLoadRange||'', terms)}</Descriptions.Item>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}>类主键</div>} >{highlightSearchContentByTerms(semiPrimaryDescription||'', terms)}</Descriptions.Item>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }}>加载方式</div>} >{highlightSearchContentByTerms(modelerData.dataLoadingStrategy||'', terms)}</Descriptions.Item>
</Descriptions>
</Col>
<Col span={8}>
<Descriptions column={1}>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }} >维护历史</div>} >
<div style={{ maxHeight: 70, overflow: 'auto' }}>
{
(maintenanceRecords||[]).map((record, index) => {
return <div key={index}>{record||''}</div>;
})
}
</div>
</Descriptions.Item>
</Descriptions>
</Col>
</Row>
</React.Fragment>
}
</React.Fragment>
)
}
</div>
)
}
export default ImportActionHeader;
const ConstraintSelect = ({ value = {}, constraints = [], onChange, ...restProps }) => {
return (
<Select
onChange={onChange}
value={value?.id}
placeholder='请选择规范'
{...restProps}
>
{
(constraints||[]) && constraints.map((constraint, index) => {
return (
<Option key={index} value={constraint.id} >{constraint.cnName||''}</Option>
);
})
}
</Select>
)
}
const TemplateSelect = ({ value = '', modelerData = undefined, templates = [], onChange, ...restProps }) => {
const mountRef = useRef(true);
const [isCustom, setIsCustom] = useState(false);
useEffect(() => {
if (mountRef.current && modelerData && Object.keys(modelerData).length > 0) {
if (modelerData?.tableType && !modelerData?.easyDataModelerModelingTemplate?.name) {
setIsCustom(true);
} else {
setIsCustom(false);
}
mountRef.current = false;
}
}, [modelerData])
return (
<span style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
{
isCustom ? <InputDebounce
placeholder='请输入数据表类型'
allowClear
value={modelerData?.tableType}
onChange={(val) => {
onChange?.(val, true);
}}
style={{ flex: 1 }}
/> : <Select
onChange={(val) => {
onChange?.(val);
}}
value={value || undefined}
placeholder='请选择数据表类型'
allowClear
style={{ flex: 1 }}
{...restProps}
>
{
(templates||[]) && templates.map((template, index) => {
return (
<Option key={index} value={template.cnName||''} >
<Tooltip title={template.remark}>
{template.cnName}
</Tooltip>
</Option>
);
})
}
</Select>
}
<Checkbox className='ml-3' checked={isCustom} onChange={(e) => {
setIsCustom(e.target.checked);
onChange?.('');
}}>自定义</Checkbox>
</span>
)
}
const AttributesSelect = ({ value = [], modelerData, onChange, mode = 'multiple', ...restProps }) => {
const onAttributeChange = (value) => {
let currentAttributes = [];
if (mode === 'multiple') {
currentAttributes = (modelerData?.easyDataModelerDataModelAttributes||[]).filter(attribute => (value||[]).indexOf(attribute.iid)!==-1);
} else {
(value||[]).forEach(item => {
const filterAttributes = (newAttributes||[]).filter(attribute => item ===attribute.iid);
if (filterAttributes.length !== 0) {
currentAttributes = [...currentAttributes, ...filterAttributes];
} else {
currentAttributes = [...currentAttributes, { name: item, iid: generateUUID() }];
}
})
}
triggerChange(currentAttributes);
}
const triggerChange = (changedValue) => {
onChange?.(changedValue);
};
//value有可能为空
value = value ? value: [];
let attributeIds = [];
let newAttributes = [...(modelerData?.easyDataModelerDataModelAttributes||[])];
value.forEach(attribute => {
attributeIds.push(attribute.iid);
if (mode === 'tags') {
const filterAttributes = (modelerData?.easyDataModelerDataModelAttributes||[]).filter(_attribute => attribute.iid ===_attribute.iid);
if (filterAttributes.length === 0) {
newAttributes = [...newAttributes, attribute];
}
}
})
return (
<Select
onChange={(value) => { onAttributeChange && onAttributeChange(value) }}
value={attributeIds}
placeholder='请选择字段名称'
mode={mode}
allowClear={true}
>
{
(newAttributes||[]).map((attribute, index) => {
return (
<Option key={index} value={attribute.iid?attribute.iid:(attribute.name||'')}>{attribute.name||''}</Option>
);
})
}
</Select>
);
}
const PartitionSelect = ({ value = {}, modelerData, partitionTypes = [], onChange, ...restProps }) => {
const onPartitionTypeChange = (value) => {
let currentPartitionType = {};
(partitionTypes||[]).forEach((partitionType, index) => {
if (value === partitionType.name) {
currentPartitionType = partitionType;
}
})
triggerChange({ partitionType: currentPartitionType });
}
const onAttributeChange = (value) => {
const currentAttributes = (modelerData?.easyDataModelerDataModelAttributes||[]).filter(attribute => (value||[]).indexOf(attribute.iid)!==-1);
triggerChange({ keys: currentAttributes });
}
const triggerChange = (changedValue) => {
onChange?.({
...value,
...changedValue,
});
};
//value有可能为空
value = value ? value: {};
let attributeIds = [];
(value?.keys||[]).forEach(attribute => {
attributeIds.push(attribute.iid);
})
return (
<Row gutter={10}>
<Col span={10}>
<Select
onChange={onPartitionTypeChange}
value={value?.partitionType?.name}
placeholder='请选择分区类型'
allowClear={true}
>
{
(partitionTypes||[]).map((partitionType, index) => {
return (
<Option key={partitionType.name||''}>{partitionType.cnName||''}</Option>
);
})
}
</Select>
</Col>
<Col span={14}>
<Select
onChange={(value) => { onAttributeChange && onAttributeChange(value) }}
value={attributeIds}
placeholder='请选择字段名称'
mode='multiple'
allowClear={true}
>
{
(modelerData?.easyDataModelerDataModelAttributes||[]).map((attribute, index) => {
return (
<Option key={index} value={attribute.iid||''}>{attribute.name||''}</Option>
);
})
}
</Select>
</Col>
</Row>
);
}
const LoadSelect = ({ value = '', onChange, ...restProps }) => {
const onLoadChange = (value) => {
triggerChange(value.join('/'));
}
const triggerChange = (changedValue) => {
onChange?.(changedValue);
};
//value有可能为空
value = value ? value: '';
let loadNames = [];
if (value !== '') {
value.split('/').forEach(item => {
loadNames.push(item);
})
}
return (
<Select
mode="tags"
tokenSeparators={['/', ' ']}
onChange={(value) => { onLoadChange && onLoadChange(value) }}
value={loadNames}
placeholder='请选择或者手动输入加载方式'
allowClear={true}
>
{
loadOptions.map((item, index) => {
return (
<Option key={index} value={item}>{item}</Option>
);
})
}
</Select>
);
}
const UpdateSelect = ({ value = '', onChange, ...restProps }) => {
const onUpdateChange = (value) => {
triggerChange(value.join('/'));
}
const triggerChange = (changedValue) => {
onChange?.(changedValue);
};
//value有可能为空
value = value ? value: '';
let updateNames = [];
if (value !== '') {
value.split('/').forEach(item => {
updateNames.push(item);
})
}
return (
<Select
mode="tags"
tokenSeparators={['/', ' ']}
onChange={(value) => { onUpdateChange && onUpdateChange(value) }}
value={updateNames}
allowClear={true}
{...restProps}
>
{
updateOptions.map((item, index) => {
return (
<Option key={index} value={item}>{item}</Option>
);
})
}
</Select>
);
}
const ItemTitle = ({ name, cnName, validateReports }) => {
return (
<Space size={2}>
{cnName}
<ValidateTip validateReports={validateReports} type='DataModel' propertyName={name} />
</Space>
)
}
export const ValidateTip = ({ validateReports, type, propertyName, iid }) => {
const reports = useMemo(() => {
const index = (validateReports??[]).findIndex(item => (
(item.type === type) && (!iid || item.iid === iid)
))
if (index !== -1) {
const items = (validateReports[index].reportItems??[]).filter(item => item.checkRule?.ruleTemplate?.checkProperty?.originalPropertyEnName === propertyName)
return items.map(item => {
const [preCheckProperty, checkProperty] = [item.checkRule?.ruleTemplate?.preCheckProperty, item.checkRule?.ruleTemplate?.checkProperty]
let tip = ''
if (preCheckProperty) {
tip = `${preCheckProperty?.propertyCnName??''} ${preCheckProperty.expressionTypeCnName??''} ${preCheckProperty.verifyExpression?.cnName??''}`
if (IsArr(preCheckProperty?.verifyExpression?.value)) {
tip = `${tip} ${preCheckProperty?.verifyExpression?.value.join(';')}`
} else {
tip = `${tip} ${preCheckProperty?.verifyExpression?.value}`
}
}
if (checkProperty) {
tip = tip?`${tip} `:''
tip = `${tip}${checkProperty?.propertyCnName??''} ${checkProperty.expressionTypeCnName??''} ${checkProperty.verifyExpression?.cnName??''}`
if (IsArr(checkProperty?.verifyExpression?.value)) {
tip = `${tip} ${checkProperty?.verifyExpression?.value.join(';')}`
} else {
tip = `${tip} ${checkProperty?.verifyExpression?.value}`
}
}
return ({
alertTypeName: item.checkRule?.alertTypeName,
alertTypeId: item.checkRule?.alertTypeId,
tip
})
})
}
return []
}, [validateReports, type, propertyName])
return (
<React.Fragment>
{
(reports??[]).length === 0 ? null : <Tooltip title={
<div>
{
(reports??[]).map((item, index) => (
<Row key={index}>
<Space>
{ (item.alertTypeId === 'enforced') ? <WarningFilled style={{ color: '#E94848' }} /> : <ExclamationCircleFilled style={{ color: '#F7AB00' }} /> }
<span>{item.tip}</span>
</Space>
</Row>
))
}
</div>
}>
{
(reports??[]).findIndex(item => item.alertTypeId === 'enforced') !== -1 ? <WarningFilled style={{ color: '#E94848' }} /> : <ExclamationCircleFilled style={{ color: '#F7AB00' }} />
}
</Tooltip>
}
</React.Fragment>
)
}
\ 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