Commit 82c5dcfe by zhaochengxiang

推荐优化

parent 2799b217
......@@ -14,7 +14,7 @@ import { dispatch, dispatchLatest } from '../../../../model';
import { addEventListenerForSidebar, removeEventListenerForSidebar } from './Help';
import { AppContext } from '../../../../App';
import DebounceInput from './DebounceInput';
import SuggestTable from './SuggestTable';
import Suggest from './suggest';
import { AttentionSvg, UnAttentionSvg } from './ModelSvg';
import { EditModelContext } from './ContextManage';
import { ValidateTip } from './ImportActionHeader';
......@@ -152,12 +152,13 @@ export const EditableCell = ({
index,
datatypes,
require,
onPressEnter,
children,
...restProps
}) => {
let editingComponent = null;
if (editing) {
let inputNode = <InputDebounce />;
let inputNode = <InputDebounce onPressEnter={() => { onPressEnter?.() }} />;
if (inputType === 'check') {
inputNode = <Checkbox />;
......@@ -256,11 +257,6 @@ export const ImportActionTable = (props) => {
const [ form ] = Form.useForm();
const [ editingKey, setEditingKey ] = useState('');
const [ loadingSuggest, setLoadingSuggest ] = useState(false);
const [ suggests, setSuggests ] = useState([]);
const [ suggestHaveMore, setSuggestHaveMore ] = useState(false);
const [ suggestOffset, setSuggestOffset ] = useState(1);
const [ currentChangedValues, setCurrentChangedValues] = useState({});
const [ englishSuggests, setEnglishSuggests ] = useState([]);
const [ keywordCondition, setKeywordCondition ] = useState({ keyword: '', needFilter: true });
const { keyword, needFilter } = keywordCondition;
......@@ -271,6 +267,12 @@ export const ImportActionTable = (props) => {
const { pageNum, pageSize, filterData } = filterPageCondition;
const [ insertIndex, setInsertIndex ] = useState(0);
const [ currentItem, setCurrentItem ] = useState(null);
const [suggestParams, setSuggestParams] = useState({
visible: false,
name: undefined,
cnName: undefined,
triggerType: undefined,
})
const { attrIsEditingFunction } = useContext(EditModelContext);
......@@ -837,7 +839,6 @@ export const ImportActionTable = (props) => {
}
setEditingKey('');
setSuggests([]);
setEnglishSuggests([]);
}
......@@ -858,70 +859,6 @@ export const ImportActionTable = (props) => {
ownPrimaryKey = (modelerData.easyDataModelerPrimaryKey.filter(item => item.name===allValues.name).length>0);
}
if (changedValues.hasOwnProperty('cnName') || changedValues.hasOwnProperty('name')) {
if (offset === 1) {
setSuggests([]);
}
const newData = [...data];
const index = newData.findIndex((item) => iid === item.iid);
if (index === -1) {
newData.splice(0, 0, { iid, ...allValues});
} else if (index !== -1) {
const item = newData[index];
newData.splice(index, 1, { ...item, ...allValues });
}
setSuggestHaveMore(false);
setCurrentChangedValues(changedValues);
function getSuggest() {
setLoadingSuggest(true);
dispatchLatest({
type: 'datamodel.suggest',
payload: {
params: {
name: allValues.name||'',
cnName: allValues.cnName||'',
topN: (offset+perSuggestCount-1),
offset
}
},
callback: data => {
setLoadingSuggest(false);
if (changedValues.hasOwnProperty('cnName')) {
const moreSuggests = (data||[]).length>0?(data[0].suggestions||[]):[];
const newSuggests = (offset===1 ? moreSuggests : [...suggests, ...moreSuggests]);
if (moreSuggests.length === perSuggestCount) {
setSuggestHaveMore(true);
}
setSuggestOffset(newSuggests.length+1);
setSuggests(newSuggests);
} else if (changedValues.hasOwnProperty('name')) {
const moreSuggests = (data||[]).length>1?(data[1].suggestions||[]):[];
const newSuggests = (offset===1 ? moreSuggests : [...suggests, ...moreSuggests]);
if (moreSuggests.length === perSuggestCount) {
setSuggestHaveMore(true);
}
setSuggestOffset(newSuggests.length+1);
setSuggests(newSuggests);
}
},
error: () => {
setLoadingSuggest(false);
}
})
}
if (changedValues.hasOwnProperty('cnName')) {
if (autoTranslateRef.current) {
dispatchLatest({
......@@ -935,17 +872,11 @@ export const ImportActionTable = (props) => {
if ((data?.translated||'') !== '') {
form.setFieldsValue({ name: data?.translated||'' });
}
getSuggest();
}
})
} else {
getSuggest();
}
} else if (changedValues.hasOwnProperty('name')) {
autoTranslateRef.current(changedValues.name==='');
getSuggest();
}
} else if(changedValues.hasOwnProperty('notNull') ) {
if (!changedValues.notNull && ownPrimaryKey) {
showMessage('info', '主键不允许为空');
......@@ -965,10 +896,26 @@ export const ImportActionTable = (props) => {
form.setFieldsValue({
...restRecord
});
setSuggests([]);
};
const onColumnPressEnter = (title) => {
if (title === '中文名称') {
setSuggestParams({
visible: true,
name: form?.getFieldValue('name'),
cnName: form?.getFieldValue('cnName'),
triggerType: 'cnName',
})
} else if (title === '英文名称') {
setSuggestParams({
visible: true,
name: form?.getFieldValue('name'),
cnName: form?.getFieldValue('cnName'),
triggerType: 'name',
})
}
}
const mergedColumns = () => {
if (editable) {
const _columns = cols.map((col) => {
......@@ -1004,7 +951,10 @@ export const ImportActionTable = (props) => {
colTitle: col.title,
editing: isEditing(record),
datatypes: supportedDatatypes,
require: col.require
require: col.require,
onPressEnter: () => {
onColumnPressEnter(col.title)
}
}),
};
});
......@@ -1049,20 +999,6 @@ export const ImportActionTable = (props) => {
setKeywordCondition({ keyword: value||'', needFilter: true });
}
const loadMoreSuggests = (event) => {
event.stopPropagation();
onValuesChange(currentChangedValues, form.getFieldsValue(), suggestOffset);
}
const closeSuggests = (event) => {
event.stopPropagation();
setSuggestHaveMore(false);
setSuggests([]);
setSuggestOffset(1);
}
const displayMenu = (e) => {
show(e);
}
......@@ -1232,34 +1168,6 @@ export const ImportActionTable = (props) => {
//解决屏幕尺寸窄时,字段不好横向拖动的问题
y: tableWidth>1500?'100%':630,
}}
expandable={{
columnWidth: 0,
expandedRowRender: record => (
<React.Fragment>
{
editingKey!=='' && <React.Fragment>
{
suggests && suggests.length>0 && (
<SuggestTable suggests={suggests} onSelect={onSuggestChange} />
)
}
</React.Fragment>
}
<div className='flex pt-3' style={{ justifyContent: 'center' }}>
<Tooltip title={!suggestHaveMore?'没有更多推荐字段': ''}>
<Button onClick={loadMoreSuggests} disabled={!suggestHaveMore} loading={loadingSuggest}>加载更多</Button>
</Tooltip>
<Button className='ml-3' onClick={closeSuggests}>收起推荐</Button>
</div>
</React.Fragment>
),
expandIcon: ({ expanded, onExpand, record }) => {
return null;
},
rowExpandable: record => (editingKey!==''&&((suggests||[]).length>0 || (englishSuggests||[]).length>0)),
expandedRowKeys: [editingKey]
}}
/>
</Form>
</DndProvider>
......@@ -1284,6 +1192,21 @@ export const ImportActionTable = (props) => {
/>
}
<div onClick={(e) => { e.stopPropagation() }}>
<Suggest
{...suggestParams}
onCancel={() => {
setSuggestParams({
visible: false,
name: undefined,
cnName: undefined,
triggerType: undefined,
})
}}
onOk={onSuggestChange}
/>
</div>
<RcMenu id={MENU_ID} >
{
(menuData??[]).map(item => (
......
.suggest-table {
.yy-table {
margin: 0 !important;
max-height: 300px !important;
overflow: auto !important;
}
}
\ No newline at end of file
import React, { useState } from 'react';
import { Table, Tooltip, Typography } from 'antd';
import { Resizable } from 'react-resizable';
import ResizeObserver from 'rc-resize-observer';
import React from 'react'
import { Modal, Button, Spin, Tooltip, Typography } from "antd"
import { checkMenuAdmit, isSzseEnv } from '../../../../util';
import { dispatch } from '../../../../model';
import { dispatch } from '../../../../model'
import Table from '../../../../util/Component/Table'
import { checkMenuAdmit, isSzseEnv, showMessage } from '../../../../util'
import './SuggestTable.less';
const topN = 20
const ResizeableHeaderCell = props => {
const { onResize, width, onClick, ...restProps } = props;
const FC = (props) => {
const { visible, name, cnName, onCancel, onOk, triggerType = 'cnName' } = props
const [loading, setLoading] = React.useState(false)
const [suggests, setSuggests] = React.useState()
const [selectedRows, setSelectedRows] = React.useState()
const [havaMore, setMore] = React.useState(false)
const [offset, setOffset] = React.useState(1)
if (!width) {
return <th {...restProps} />;
}
return (
<Resizable
width={width}
height={0}
handle={
<span
className="react-resizable-handle"
onClick={(e) => {
e.stopPropagation();
}}
/>
}
onResize={onResize}
draggableOpts={{ enableUserSelectHack: false }}
>
<th
onClick={onClick}
{...restProps}
/>
</Resizable>
);
};
React.useEffect(() => {
getSuggests()
}, [visible])
const SourceComponent = (props) => {
const { data, onClick, name } = props;
const onSourceClick = (id, name) => {
const timestamp = new Date().getTime();
const tempArray = id.split('=');
if (tempArray.length>=3) {
const moreSourceComponent = <div style={{ maxWidth: 400 }}>
{
(data||[]).map((source, index) => {
return (
<div
className='pointer'
key={index}
style={{
textDecoration: 'underline',
}}
onClick={(e) => {
e.stopPropagation();
onClick && onClick(source.sourceId, name);
}}
>
{source.sourcePath||''}
</div>
);
dispatch({
type: 'datamodel.getParent',
payload: {
id
},
callback: data => {
window.open(`/center-home/metadetail?mid=${encodeURIComponent(data._id)}&action=metadetail&type=detail&manager=false&activekey=1&name=${encodeURIComponent(name||'')}`);
}
})
} else {
if (checkMenuAdmit('datastandard')) {
window.open(`/center-home/menu/datastandard?id=${id}&timestamp=${timestamp}`);
}
}
</div>;
return (
<Tooltip
title={moreSourceComponent}
overlayClassName='tooltip-common'
>
<a
href='#'
onClick={(e) => {
e.stopPropagation();
onClick && onClick(data[0].sourceId, name);
}}
>
{
(data||[]).length>0 && <span>{data[0].sourcePath||''}</span>
}
</a>
</Tooltip>
);
}
const SuggestTable = (props) => {
const { suggests, onSelect } = props;
const [ tableWidth, setTableWidth ] = useState(0);
const cols = [
const cols = React.useMemo(() => {
return [
{
title: '中文名称',
dataIndex: 'cnName',
......@@ -158,121 +111,166 @@ const SuggestTable = (props) => {
ellipsis: true,
render: (_, record) => {
return (
<SourceComponent data={record.recommendedStats?.sourceInfos||[]} name={record.name||''} onClick={sourceOnClick} />
<SourceComponent data={record.recommendedStats?.sourceInfos||[]} name={record.name||''} onClick={onSourceClick} />
);
}
},
];
const [ columns, setColumns ] = useState(cols);
const sourceOnClick = (id, name) => {
const timestamp = new Date().getTime();
const tempArray = id.split('=');
if (tempArray.length>=3) {
]
}, [onSourceClick])
const getSuggests = () => {
setLoading(true)
dispatch({
type: 'datamodel.getParent',
type: 'datamodel.suggest',
payload: {
id
params: {
name,
cnName,
offset,
topN,
}
},
callback: data => {
window.open(`/center-home/metadetail?mid=${encodeURIComponent(data._id)}&action=metadetail&type=detail&manager=false&activekey=1&name=${encodeURIComponent(name||'')}`);
}
setLoading(false)
if (triggerType === 'cnName') {
setSuggests(prevSuggests => {
const newSuggests = [...prevSuggests??[], ...data?.[0]?.suggestions??[]]
setOffset((data?.[0]?.suggestions??[]).length + offset)
setMore((data?.[0]?.suggestions??[]).length === topN)
return newSuggests
})
} else if (triggerType === 'name') {
setSuggests(prevSuggests => {
const newSuggests = [...prevSuggests??[], ...data?.[1]?.suggestions??[]]
setOffset((data?.[1]?.suggestions??[]).length + offset)
setMore((data?.[1]?.suggestions??[]).length === topN)
return newSuggests
})
} else {
if (checkMenuAdmit('datastandard')) {
window.open(`/center-home/menu/datastandard?id=${id}&timestamp=${timestamp}`);
}
},
error: () => {
setLoading(false)
}
})
}
const onTableSelect = (record, selected, selectedRows, nativeEvent) => {
onSelect && onSelect(record);
const close = () => {
setLoading(false)
setSuggests()
setOffset(1)
setMore(false)
onCancel?.()
}
const handleResize = index => (e, { size }) => {
const nextColumns = [...columns];
nextColumns[index] = {
...nextColumns[index],
width: size.width,
};
setColumns(nextColumns);
};
const save = () => {
if ((selectedRows??[]).length === 0) {
showMessage('warn', '请先选择推荐项')
return
}
const mergedColumns = () => {
return (
columns.map((column, index) => {
return {
...column,
onHeaderCell: column => ({
width: column.width,
onResize: handleResize(index),
}),
};
})
);
onOk?.(selectedRows?.[0])
close()
}
const rowSelection = {
type: 'radio',
onSelect: onTableSelect,
};
const footer = React.useMemo(() => {
return [
<Button key='cancel'
onClick={() => close()}
>取消</Button>,
<Button key='save' type='primary'
onClick={() => save()}
>确定</Button>
]
}, [close, save])
return (
<div className='suggest-table'>
<ResizeObserver
onResize={({ width }) => {
if (tableWidth !== width) {
setTableWidth(width);
let newColumns = [...cols];
newColumns.forEach((column, index) => {
if (!column.width) {
const rowWidth = (cols.reduce((preVal, col) => (col.width?col.width:0) + preVal, 0)) + 50;
if (width > rowWidth) {
column.width = (width-rowWidth)>200?(width-rowWidth):200;
} else {
column.width = 200;
}
}
});
setColumns(newColumns);
}
}}
<Modal
visible={visible}
footer={footer}
width='80%'
bodyStyle={{ padding: '15px', overflowX: 'auto', maxHeight: '80vh' }}
title='匹配推荐'
centered destroyOnClose
onCancel={() => { close() }}
>
<Spin spinning={loading}>
<Table
rowSelection={rowSelection}
extraColWidth='32px'
size='small'
rowKey='iid'
dataSource={suggests||[]}
columns={cols}
pagination={false}
loading={false}
rowKey='iid'
rowClassName={(record, index) => {
return 'pointer';
}}
components={{
header: {
cell: ResizeableHeaderCell,
}
onRowClick={(event, record) => {
setSelectedRows([record])
}}
columns={mergedColumns()}
onRow={(record, index) => {
return {
onClick: (e) => {
onSelect && onSelect(record);
}
}
rowSelection={{
type: 'radio',
selectedRowKeys: (selectedRows??[]).map(item => item.iid),
onChange: (selectedRowKeys, selectedRows) => {
setSelectedRows(selectedRows)
},
}}
/>
</ResizeObserver>
<div className='flex pt-3' style={{ justifyContent: 'center' }}>
<Tooltip title={!havaMore?'没有更多推荐字段':''}>
<Button onClick={getSuggests} disabled={!havaMore} >加载更多</Button>
</Tooltip>
</div>
);
</Spin>
</Modal>
)
}
export default SuggestTable;
\ No newline at end of file
export default FC
const SourceComponent = (props) => {
const { data, onClick, name } = props;
const moreSourceComponent = <div style={{ maxWidth: 400 }}>
{
(data||[]).map((source, index) => {
return (
<div
className='pointer'
key={index}
style={{
textDecoration: 'underline',
}}
onClick={(e) => {
e.stopPropagation();
onClick && onClick(source.sourceId, name);
}}
>
{source.sourcePath||''}
</div>
);
})
}
</div>;
return (
<Tooltip
title={moreSourceComponent}
overlayClassName='tooltip-common'
>
<a
href='#'
onClick={(e) => {
e.stopPropagation();
onClick && onClick(data[0].sourceId, name);
}}
>
{
(data||[]).length>0 && <span>{data[0].sourcePath||''}</span>
}
</a>
</Tooltip>
);
}
\ 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