Commit 5e42e69d by zhaochengxiang

Merge branch 'model-compare-v2' into 'master'

Model compare v2

See merge request !14
parents 80e8725c 749e6a25
......@@ -24,6 +24,4 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json
yarn.lock
/center-home
\ No newline at end of file
......@@ -224,6 +224,11 @@ export class App extends React.Component {
<Route path={'/center-home/data-model-action'} component={EditModel} exact />
<Route path={'/center-home/asset-detail'} component={AssetDetailPage} exact />
<Route path={'/center-home/model-review-detail'} component={ModelReviewDetail} />
<Route path={'/data-model-product/physics-model'} component={Model} exact />
<Route path={'/data-model-product/physics-model-branch'} component={Model} exact />
<Route path={'/data-model-product/admin/model-specification'} component={ModelConfig} exact />
</Switch>
</Router>
</AppContext.Provider>
......
......@@ -210,6 +210,10 @@ export function* dataModelRollback(payload) {
return yield call(datamodelerService.dataModelRollback, payload);
}
export function* compareOtherModel(payload) {
return yield call(datamodelerService.compareOtherModel, payload);
}
export function* getDataModelLocation(payload) {
return yield call(datamodelerService.getDataModelLocation, payload);
}
......@@ -250,6 +254,18 @@ export function* heartbeat() {
return yield call(datamodelerService.heartbeat);
}
export function* exportTableDDLAbstractList(payload) {
return yield call(datamodelerService.exportTableDDLAbstractList, payload);
}
export function* getExportTableDDL(payload) {
return yield call(datamodelerService.getExportTableDDL, payload);
}
export function* downloadExportTableDDLListZip(payload) {
return yield call(datamodelerService.downloadExportTableDDLListZip, payload);
}
export function* validateDataModel(payload) {
return yield call(datamodelerService.validateDataModel, payload);
}
......@@ -346,6 +362,10 @@ export function* getPrivilegeAdmin() {
return yield call(datamodelerService.getPrivilegeAdmin);
}
export function* getCatalogAdmin() {
return yield call(datamodelerService.getCatalogAdmin);
}
export function* getPrivilegeBranchAdmin() {
return yield call(datamodelerService.getPrivilegeBranchAdmin);
}
......@@ -592,6 +612,50 @@ export function* getCompareJobResultDeployModels(payload) {
return yield call(datamodelerService.getCompareJobResultDeployModels, payload)
}
export function* getCompareJobResultMetadataNotMatchCatalog(payload) {
return yield call(datamodelerService.getCompareJobResultMetadataNotMatchCatalog, payload)
}
export function* getCompareJobResultMetadataPartialMatchCatalog(payload) {
return yield call(datamodelerService.getCompareJobResultMetadataPartialMatchCatalog, payload)
}
export function* getCompareJobResultMetadataPerfectMatchCatalog(payload) {
return yield call(datamodelerService.getCompareJobResultMetadataPerfectMatchCatalog, payload)
}
export function* getCompareJobResultModelNotMatchCatalog(payload) {
return yield call(datamodelerService.getCompareJobResultModelNotMatchCatalog, payload)
}
export function* getCompareJobResultModelPartialMatchCatalog(payload) {
return yield call(datamodelerService.getCompareJobResultModelPartialMatchCatalog, payload)
}
export function* getCompareJobResultModelPerfectMatchCatalog(payload) {
return yield call(datamodelerService.getCompareJobResultModelPerfectMatchCatalog, payload)
}
export function* getCompareJobResultModelCount(payload) {
const deployWaitingCount = yield call(datamodelerService.getCompareJobResultDeployWaitingTotalCount, payload)
const deployedCount = yield call(datamodelerService.getCompareJobResultDeployedTotalCount, payload)
const offlineCount = yield call(datamodelerService.getCompareJobResultOfflineTotalCount, payload)
return { totalCount: (deployWaitingCount+deployedCount+offlineCount), deployWaitingCount, deployedCount, offlineCount }
}
export function* getCompareJobResultDeployWaitingModelPage(payload) {
return yield call(datamodelerService.getCompareJobResultDeployWaitingModelPage, payload)
}
export function* getCompareJobResultDeployedModelPage(payload) {
return yield call(datamodelerService.getCompareJobResultDeployedModelPage, payload)
}
export function* getCompareJobResultOfflineModelPage(payload) {
return yield call(datamodelerService.getCompareJobResultOfflineModelPage, payload)
}
export function* addDataTypeConfig(payload) {
return yield call(datamodelerService.addDataTypeConfig, payload)
}
......@@ -710,4 +774,8 @@ export function* getOwner(payload) {
export function* setOwner(payload) {
return yield call(datamodelerService.setOwner, payload)
}
export function* findAssociationMetadataByModelId(payload) {
return yield call(datamodelerService.findAssociationMetadataByModelId, payload)
}
\ No newline at end of file
import { PostFile, GetJSON, PostJSON, Post, Get, Delete, Delete1, Delete2 } from "../util/axios"
import { PostFile, GetJSON, PostJSON, Post, Get, Delete, Delete1, Delete2, callFetchRaw } from "../util/axios"
export function loadDataModelCatalog() {
return GetJSON("/datamodeler/easyDataModelerCURD/loadDataModelCatalog");
......@@ -201,6 +201,10 @@ export function dataModelRollback(payload) {
return PostJSON("/datamodeler/easyDataModelerCURD/reset", payload);
}
export function compareOtherModel(payload) {
return PostJSON("/datamodeler/easyDataModelerCURD/compareOtherModel", payload);
}
export function ddlGenerators() {
return GetJSON("/datamodeler/easyDataModelerExport/ddlGenerators");
}
......@@ -237,6 +241,18 @@ export function heartbeat() {
return Get("/datamodeler/easyDataModelerExport/heartbeat");
}
export function exportTableDDLAbstractList(payload) {
return PostJSON("/datamodeler/easyDataModelerExport/exportTableDDLAbstractList", payload);
}
export function getExportTableDDL(payload) {
return Post("/datamodeler/easyDataModelerExport/getExportTableDDL", payload);
}
export function downloadExportTableDDLListZip(payload) {
return callFetchRaw("post","/datamodeler/easyDataModelerExport/downloadExportTableDDLListZip", payload);
}
export function validateDataModel(payload) {
return PostJSON("/datamodeler/easyDataModelerConstraint/validateDataModel", payload);
}
......@@ -297,6 +313,10 @@ export function getPrivilegeAdmin() {
return Get("/datamodeler/easyDataModelerPrivilegeProvider/getAdmin");
}
export function getCatalogAdmin() {
return Get("/datamodeler/easyDataModelerPrivilegeProvider/getCatalogAdmin");
}
export function getPrivilegeBranchAdmin() {
return Get("/datamodeler/easyDataModelerPrivilegeProvider/getBranchCreation");
}
......@@ -537,6 +557,55 @@ export function getCompareJobResultDeployModels(payload) {
return PostJSON("/datamodeler/easyDataModelModelCompareJobResult/deployModelByResultItemIds", payload)
}
export function getCompareJobResultMetadataNotMatchCatalog(payload) {
return GetJSON("/datamodeler/easyDataModelModelCompareJobResult/getMetadataNotMatchCatalog", payload)
}
export function getCompareJobResultMetadataPartialMatchCatalog(payload) {
return GetJSON("/datamodeler/easyDataModelModelCompareJobResult/getMetadataPartialMatchCatalog", payload)
}
export function getCompareJobResultMetadataPerfectMatchCatalog(payload) {
return GetJSON("/datamodeler/easyDataModelModelCompareJobResult/getMetadataPerfectMatchCatalog", payload)
}
export function getCompareJobResultModelNotMatchCatalog(payload) {
return GetJSON("/datamodeler/easyDataModelModelCompareJobResult/getModelNotMatchCatalog", payload)
}
export function getCompareJobResultModelPartialMatchCatalog(payload) {
return GetJSON("/datamodeler/easyDataModelModelCompareJobResult/getModelPartialMatchCatalog", payload)
}
export function getCompareJobResultModelPerfectMatchCatalog(payload) {
return GetJSON("/datamodeler/easyDataModelModelCompareJobResult/getModelPerfectMatchCatalog", payload)
}
export function getCompareJobResultDeployWaitingTotalCount(payload) {
return GetJSON("/datamodeler/easyDataModelModelCompareJobResult/getDeployWaitingTotalCount", payload)
}
export function getCompareJobResultDeployWaitingModelPage(payload) {
return GetJSON("/datamodeler/easyDataModelModelCompareJobResult/getDeployWaitingModelPage", payload)
}
export function getCompareJobResultDeployedTotalCount(payload) {
return GetJSON("/datamodeler/easyDataModelModelCompareJobResult/getDeployedTotalCount", payload)
}
export function getCompareJobResultDeployedModelPage(payload) {
return GetJSON("/datamodeler/easyDataModelModelCompareJobResult/getDeployedModelPage", payload)
}
export function getCompareJobResultOfflineTotalCount(payload) {
return GetJSON("/datamodeler/easyDataModelModelCompareJobResult/getOfflineTotalCount", payload)
}
export function getCompareJobResultOfflineModelPage(payload) {
return GetJSON("/datamodeler/easyDataModelModelCompareJobResult/getOfflineModelPage", payload)
}
/*type config*/
export function addDataTypeConfig(payload) {
return PostJSON("/datamodeler/easyDataModelerColumnDataType/addDataTypeConfig", payload)
......@@ -660,4 +729,9 @@ export function getOwner(payload) {
export function setOwner(payload) {
return PostJSON("/datamodeler/easyDataModelerCooperation/setDataModelOwner", payload)
}
//模型和元数据关联
export function findAssociationMetadataByModelId(payload) {
return GetJSON("/datamodeler/easyDataModelerMetadataAssociation/findAssociationByModelId", payload)
}
\ No newline at end of file
......@@ -66,10 +66,11 @@ function FC<RowType extends object = any>({ width, maxHeight, pageSize, pageNum,
useEffect(() => {
if (!!columns && tableWidth > 0) {
const contentWidth = getWidth(width ?? tableWidth,extraColWidth)
setDefaultWidth(columns, contentWidth)
paddingCol.current.width = 0
const cols = columns
const newCols = columns
.map((col, index) => {
const render = getRender(col);
const colWidth = col.width ?? 100;
......@@ -83,7 +84,7 @@ function FC<RowType extends object = any>({ width, maxHeight, pageSize, pageNum,
}),
};
})
setCols(cols)
setCols(newCols)
}
}, [columns, tableWidth, width, extraColWidth])
......
import { AxiosResponse } from "axios"
export default function (res: AxiosResponse<any>) {
const blob = res.data
const headers = res.headers
let tempName = headers["content-disposition"]
?.split(";")?.[1]
?.split("filename=")?.[1]?.split(".")?.[0].replace(/"/g, "");
tempName = decodeURI(tempName);
// const blob = new Blob([content], { type: 'application/octet-stream' })
var url = (window.URL && window.URL.createObjectURL) ? window.URL.createObjectURL(blob) : window.webkitURL.createObjectURL(blob);
const link = document.createElement('a');
link.style.display = 'none';
link.href = url;
link.setAttribute('download', tempName); //or any other extension
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href) // 释放URL 对象
document.body.removeChild(link)
}
\ No newline at end of file
......@@ -16,7 +16,6 @@ export const PermitCheckOut = 'permitCheckOut';
export const StateId = 'sid';
export const VersionId = 'vid';
export const TemplateId = 'tid';
export const Holder = 'holder';
export const ReadOnly = 'readOnly';
export const ApprovalId = 'approvalId';
export const ApprovalType = 'approvalType';
......
......@@ -562,4 +562,12 @@ export function isChromeVersionLessThan80() {
}
return false;
}
export function openMetadataDetail(id) {
window.open(`/center-home/metadetail?mid=${encodeURIComponent(id)}&action=metadetail&type=detail&manager=false&activekey=1`);
}
export function openModelDetail(id) {
window.open(`/data-govern/data-model-action?action=detail&mid=${id}`);
}
\ No newline at end of file
......@@ -116,10 +116,8 @@ const FC = (props) => {
<div className='edit-header'>
<span style={{ fontSize: 16, fontWeight: 'bold', color: '#fff' }}>{title}</span>
</div>
<div className='edit-container'>
<div className='edit-container-card' style={{ padding: '20px 20px 0' }}>
<EditAssets ref={editAssetsRef} action={action} type={type} ids={ids} elementIds={elementIds} />
</div>
<div className='edit-container' style={{ padding: '10px 10px 0' }}>
<EditAssets ref={editAssetsRef} action={action} type={type} ids={ids} elementIds={elementIds} />
</div>
<div className='edit-footer'>
{
......@@ -459,7 +457,7 @@ export const EditAssets = React.forwardRef(function ({ action, type, ids, elemen
<div ref={tableRef}>
<Form form={form} component={false}>
<Table
maxHeight='calc(100vh - 245px)'
maxHeight='calc(100vh - 213px)'
loading={loading}
columns={columns}
dataSource={tableData}
......
.edit-model {
display: flex;
flex-direction: column;
overflow: hidden;
height: 100vh;
.edit-header {
display: flex;
flex: none;
width: 100%;
height: 44px;
padding: 0 15px;
background-color: #464d6e;
align-items: center;
// position: fixed;
justify-content: space-between;
border-bottom: 1px solid #EFEFEF;
// z-index: 100;
}
.edit-container {
flex: 1;
background: #F2F2F2;
height: calc(100vh - 44px - 64px);
overflow: hidden;
}
.edit-container-card {
margin: 10px;
height: calc(100vh - 44px - 64px - 20px);
// background: #fff;
overflow: hidden;
}
.edit-footer {
display: flex;
bottom: 0;
flex: none;
width: 100%;
height: 64px;
position: fixed;
min-height: 64px;
max-height: 500px;
justify-content: flex-end;
opacity: 0.9;
background: #fff;
box-shadow: 0 -1px 4px 0 #e5e9ea;
padding: 0 20px;
padding: 10px 20px;
}
}
\ No newline at end of file
import React, { useState } from 'react';
import { Modal, Button, Form, Radio } from 'antd';
const exportModes = [
{ name: '导出DDL', key: 'ddl' },
{ name: '导出Erwin', key: 'erwin' },
{ name: '导出Excel', key: 'excel' },
{ name: '导出Word', key: 'word' },
{ name: '导出模型信息', key: 'basicExcel' },
]
const ExportOtherModal = (props) => {
const { visible, onCancel } = props;
const [ modeKey, setModeKey ] = useState('');
const [ form ] = Form.useForm();
const onModeChange = (e) => {
setModeKey(e.target?.value);
}
const onOk = async() => {
try {
await form.validateFields();
reset();
onCancel && onCancel(modeKey);
} catch (errInfo) {
console.log('Validate Failed:', errInfo);
}
}
const cancel = () => {
reset();
onCancel && onCancel();
}
const reset = () => {
form.resetFields();
setModeKey('');
}
const footer = [
<Button
key="0"
onClick={cancel}
>
取消
</Button>,
<Button
key="1"
type="primary"
onClick={onOk}
>
确定
</Button>,
];
return (
<Modal
forceRender
visible={visible}
title='模型导出'
width={700}
onCancel={cancel}
footer={footer}
>
<Form form={form}>
<Form.Item
name='mode'
label='导出方式'
rules={[
{
required: true,
message: '请选择导出方式',
},
]}
>
<Radio.Group onChange={onModeChange} value={modeKey}>
{
exportModes.map((item, index) => {
return (
<Radio
value={item.key}
key={index}
>
{item.name}
</Radio>
);
})
}
</Radio.Group>
</Form.Item>
</Form>
</Modal>
)
}
export default ExportOtherModal;
\ No newline at end of file
......@@ -19,7 +19,7 @@ import './ImportAction.less'
export const importActionSubject = new Subject()
const ImportAction = React.forwardRef((props, ref) => {
const { action, hints, onChange, form, modelerId, terms, ddl, roughModelerData, versionId, permitCheckOut, catalogId, branchId, approvalModelId, approvalId, reference = '' } = props;
const { action, hints, onChange, form, modelerId, terms, ddl, roughModelerData, versionId, permitCheckOut, catalogId, branchId, approvalModelId, approvalId, reference = '', height } = props;
const [ constraints, setConstraints ] = useState([]);
const [ constraint, setConstraint ] = useState({});
......@@ -47,13 +47,9 @@ const ImportAction = React.forwardRef((props, ref) => {
useEffect(() =>{
if ((action||'')==='') return;
if ((!mountRef.current && action === 'edit' && !permitCheckOut) || action === 'edit-inherited') {
return;
}
//流程打开模型详情的情况下,id由-1变成-2,会再次触发获取模型详情.这里直接return掉
if (approvalId || (!mountRef.current&&action === 'flow')) {
if ((!mountRef.current&&action === 'edit'&&!permitCheckOut)
|| action==='edit-inherited'
|| approvalId) {
return;
}
......@@ -110,38 +106,22 @@ const ImportAction = React.forwardRef((props, ref) => {
useEffect(() => {
if (approvalModelId) {
//把数据表结构中的数据清空,解决性能问题
const newModelerData = { ...modelerData, easyDataModelerDataModelAttributes: [] };
onChange && onChange(newModelerData);
setModelerData(newModelerData);
modelerDataRef.current = newModelerData;
if (action==='edit') {
form?.resetFields();
}
if (action === 'detail'|| action ==='flow') {
//把数据表结构中的数据清空,解决性能问题
const newModelerData = { ...modelerData, easyDataModelerDataModelAttributes: [] };
onChange && onChange(newModelerData);
setModelerData(newModelerData);
modelerDataRef.current = newModelerData;
}
setLoading(true);
dispatch({
type: 'datamodel.getAllConstraints',
callback: data => {
setConstraints(data);
dispatch({
type: 'datamodel.getDataModelWithRecommendedDefinitionAndTermDiscovery',
payload: {
id: approvalModelId,
},
callback: data => {
setLoading(false);
getExtraData(data);
},
error: () => {
setLoading(false);
}
})
},
error: () => {
setLoading(false);
}
})
getCurrentDataModel()
}
}, [approvalModelId])
}, [approvalModelId, action])
useEffect(() => {
if (constraint?.name) {
......@@ -274,7 +254,8 @@ const ImportAction = React.forwardRef((props, ref) => {
}
const getCurrentDataModel = () => {
if ((modelerId||'') === '') {
if ((action!=='flow'&&!modelerId)
|| (action === 'flow'&&!approvalModelId)) {
setLoading(false);
return;
}
......@@ -289,6 +270,9 @@ const ImportAction = React.forwardRef((props, ref) => {
type = 'datamodel.modelCopy';
} else if (action === 'flow') {
type = 'datamodel.getDataModelWithRecommendedDefinitionAndTermDiscovery';
params = {
id: approvalModelId,
}
} else if (action === 'detail-version') {
type = 'datamodel.getDataModelByVersionId';
params = {
......@@ -647,7 +631,7 @@ const ImportAction = React.forwardRef((props, ref) => {
}
</Tabs>
}
<div ref={setContainer} style={{ height: action==='edit-inherite-modal'?'60vh':(reference!=='full-search'?'calc(100vh - 44px - 64px - 66px)': '100%'), overflow: 'auto' }}>
<div ref={setContainer} style={{ height: action==='edit-inherite-modal'?'60vh':(reference==='full-search'?'100%':(height-66)), overflow: 'auto' }}>
<ImportActionHeader
form={form}
editable={action!=='detail'&&action!=='flow'&&action!=='detail-version'&&action!=='edit-inherited'}
......
......@@ -109,7 +109,7 @@ const FC = (props) => {
</Form>
) : (
<Descriptions column={3}>
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 85 }} >维护历史</div>} >
<Descriptions.Item label={<div style={{ textAlign: 'right', width: 106 }} >维护历史</div>} >
<div style={{ maxHeight: 70, overflow: 'auto' }}>
{
(maintenanceRecords||[]).map((record, index) => {
......
......@@ -2,10 +2,12 @@ import React from "react"
import { Button, Descriptions, Space, Popover } from "antd"
import { DownOutlined, UpOutlined, QuestionCircleOutlined } from '@ant-design/icons'
import { Action, ModelerId, PermitCheckOut, Editable, StateId, Holder, ReadOnly } from '../../../../util/constant'
import { Action, ModelerId, PermitCheckOut, Editable, StateId, ReadOnly } from '../../../../util/constant'
import { importActionSubject } from "./ImportAction"
import { dispatch } from '../../../../model';
import './ImportActionHeader.less'
import { openMetadataDetail } from "../../../../util"
export const inheritanceHistoricalType = 'historical'
export const inheritanceZipperType = 'zipper'
......@@ -14,6 +16,7 @@ const FC = (props) => {
const { modelerData, action } = props
const [isCollapse, setCollapse] = React.useState(true)
const [relationModelerDatas, setRelationModelerDatas] = React.useState([])
const [associationMetadata, setMetadata] = React.useState()
React.useEffect(() => {
const $importActionSubject = importActionSubject.subscribe((props) => {
......@@ -54,6 +57,24 @@ const FC = (props) => {
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [modelerData])
React.useEffect(() => {
if (modelerData?.id) {
getAssociationMetadata()
}
}, [modelerData?.id])
const getAssociationMetadata = () => {
dispatch({
type: 'datamodel.findAssociationMetadataByModelId',
payload: {
easyDataModelerDataModelId: modelerData?.id,
},
callback: data => {
setMetadata(data)
}
})
}
return (
<div className='model-import-action-relation'>
<Space>
......@@ -77,7 +98,23 @@ const FC = (props) => {
!isCollapse && <Descriptions className='mt-3' column={3}>
<Descriptions.Item
label={
<div style={{ textAlign: 'right', width: 100 }}>
<div style={{ textAlign: 'right', width: 106 }}>
元数据
</div>}
>
<span>
{
!associationMetadata?.metadataPath ? '暂无信息' : <a className='mr-3' onClick={() => {
openMetadataDetail(associationMetadata?.metadataId)
}}>
{associationMetadata?.metadataPath}
</a>
}
</span>
</Descriptions.Item>
<Descriptions.Item
label={
<div style={{ textAlign: 'right', width: 106 }}>
历史存储形式
</div>}
>
......@@ -86,7 +123,7 @@ const FC = (props) => {
relationModelerDatas?.length===0 ? '暂无信息' :
relationModelerDatas?.map((item, index) => (
<a className='mr-3' key={index} onClick={() => {
window.open(`/data-govern/data-model-action?${Action}=detail&${ModelerId}=${item.id}&${PermitCheckOut}=${item.permitCheckOut||false}&${Editable}=${item.editable||false}&${StateId}=${item.state?.id||''}&${Holder}=${item.holder||''}&${ReadOnly}=false`);
window.open(`/data-govern/data-model-action?${Action}=detail&${ModelerId}=${item.id}&${PermitCheckOut}=${item.permitCheckOut||false}&${Editable}=${item.editable||false}&${StateId}=${item.state?.id||''}&${ReadOnly}=false`);
}}>
{item.cnName}
</a>
......
import React, { useState, useCallback, useRef, useEffect, useContext, useMemo } from 'react';
import { Input, Form, Typography, Button, Select, Row, Col, Popover, Checkbox, Tooltip, Table, Pagination, Space } from 'antd';
import { Input, Form, Typography, Button, Select, Row, Col, Popover, Checkbox, Tooltip, Pagination, Space } from 'antd';
import { CheckOutlined, PlusOutlined, QuestionCircleOutlined, DeleteOutlined } from '@ant-design/icons';
import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
......@@ -18,6 +18,7 @@ import Suggest from './suggest';
import { AttentionSvg, UnAttentionSvg } from './ModelSvg';
import { EditModelContext } from './ContextManage';
import { ValidateTip } from './ImportActionHeader';
import Table from '../../ResizeableTable';
import './ImportActionHeader.less';
import './ImportActionTable.less';
......@@ -32,36 +33,6 @@ const MENU_ID = 'model-attribute-menu';
export const InputDebounce = DebounceInput(300)(Input);
const ResizeableHeaderCell = props => {
const { onResize, width, onClick, ...restProps } = props;
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>
);
};
export const DatatypeInput = ({ value = {}, datatypes, onChange }) => {
const onNameChange = (value) => {
......@@ -453,7 +424,6 @@ export const ImportActionTable = (props) => {
dataIndex: 'definition',
editable: true,
ellipsis: true,
width: 200,
render: (text, record, __) => {
return (
<React.Fragment>
......@@ -1029,30 +999,6 @@ export const ImportActionTable = (props) => {
}
}
const handleResize = index => (e, { size }) => {
const nextColumns = [...columns];
nextColumns[index] = {
...nextColumns[index],
width: size.width,
};
setColumns(nextColumns);
};
const resizeColumns = () => {
return (
columns.map((column, index) => {
return {
...column,
onHeaderCell: column => ({
width: column.width,
onResize: handleResize(index),
}),
};
})
);
}
return (
<div className='model-import-action-table' id='model-import-action-table'>
<div className='d-flex mb-3' style={{ justifyContent: 'space-between', alignItems: 'center' }}>
......@@ -1101,9 +1047,6 @@ export const ImportActionTable = (props) => {
<Form form={form} component={false} onValuesChange={onValuesChange}>
<Table
components={{
header: {
cell: ResizeableHeaderCell,
},
body: {
cell: EditableCell,
//编辑或者搜索状态下不允许拖动
......@@ -1167,16 +1110,10 @@ export const ImportActionTable = (props) => {
return rowParams;
}}
dataSource={filterPageData||[]}
columns={resizeColumns()}
columns={columns??[]}
size='small'
rowKey='iid'
pagination={false}
sticky
scroll={{
x: 1500,
//解决屏幕尺寸窄时,字段不好横向拖动的问题
y: tableWidth>1500?'100%':630,
}}
/>
</Form>
</DndProvider>
......
......@@ -12,6 +12,7 @@ import { useContextMenu, Menu as RcMenu, Item as RcItem } from "react-contexify"
import PermissionRcItem from '../../../../util/Component/PermissionRcItem';
import TagCell from './tag-help';
import BranchModelSync from './branch-model-sync';
import ModelCompareSelectModel from './model-compare-select-model';
import './ModelTable.less';
import 'react-contexify/dist/ReactContexify.css';
......@@ -19,6 +20,14 @@ import produce from "immer";
const { Paragraph, Text } = Typography;
export const stateColorDic = {
草稿: '#DE7777',
评审中: '#779BDE',
评审通过: '#7CDEBF',
已上线: '#4C7813',
已下线: '#AAAAAA',
}
const ModelNameColumn = (props) => {
const { text, record, detailItem } = props;
const [ data, setData ] = useState(record);
......@@ -149,6 +158,10 @@ const ModelTable = (props) => {
visible: false,
item: undefined,
});
const [modelCompareSelectModelParams, setModelCompareSelectModelParams] = useState({
visible: false,
item: undefined,
})
const expandedDataMapRef = useRef(new Map());
const shouldScrollRef = useRef(false);
......@@ -235,18 +248,9 @@ const ModelTable = (props) => {
sortable: true,
resizable: true,
formatter(props) {
let color = '';
if (props.row.state?.id === '1') {
color = '#DE7777';
} else if (props.row.state?.id === '2') {
color = '#779BDE';
} else if (props.row.state?.id === '4') {
color = '#77DEBF';
}
return (
<span>
<span style={{ display: 'inline-block', width: 10, height: 10, borderRadius: 5, marginRight: 5, backgroundColor: color }}></span>
<span style={{ display: 'inline-block', width: 10, height: 10, borderRadius: 5, marginRight: 5, backgroundColor: stateColorDic[props.row.state?.cnName]??'#77DEBF' }}></span>
<span>{props.row.state?.cnName||''}</span>
</span>
);
......@@ -668,6 +672,11 @@ const ModelTable = (props) => {
detailItem(data)
}
})
} else if (key === 'model-compare') {
setModelCompareSelectModelParams({
visible: true,
item: currentItem,
})
}
}
......@@ -680,10 +689,6 @@ const ModelTable = (props) => {
} else {
if (!currentItem?.editable && currentItem?.state?.id!=='4') {
disableEdit = true;
if (currentItem?.state?.id === '2') {
editTip = '待发布的模型不允许编辑';
}
}
if (!currentItem?.permitCheckOut && currentItem?.state?.id==='4') {
......@@ -705,23 +710,9 @@ const ModelTable = (props) => {
return (
<div>
<div className='flex' style={{ height: 20, alignItems: 'center', marginBottom: 12 }}>
<Paragraph style={{ overflow: 'hidden' }}>
<Text className='title-color' ellipsis={true}>
总数:
<Text className='text-color'>{(tableData||[]).length}</Text>
</Text>
</Paragraph>
<Paragraph style={{ overflow: 'hidden', marginLeft: 20 }}>
<Text className='title-color' ellipsis={true}>
已选数:
<Text className='text-color'>{summarySelectedCount}</Text>
</Text>
</Paragraph>
</div>
<DataGrid
gridRef={gridRef}
style={{ blockSize: 'calc(100vh - 94px - 37px - 57px - 24px - 32px)' }}
style={{ blockSize: 'calc(100vh - 121px - 152px )' }}
checkable
columns={columns}
// rows={Array.from({ length: 10000 }).map((_, i) => ({
......@@ -779,6 +770,13 @@ const ModelTable = (props) => {
>
复制模型
</PermissionRcItem>
{/* <PermissionRcItem
id='model-compare'
defaultPermission={true}
onClick={handleItemClick}
>
模型对比
</PermissionRcItem> */}
{
view !== 'branch' && <PermissionRcItem
id='auth-transfer'
......@@ -857,6 +855,15 @@ const ModelTable = (props) => {
}
}}
/>
<ModelCompareSelectModel
{...modelCompareSelectModelParams}
onCancel={() => {
setModelCompareSelectModelParams({
visible: false,
item: undefined,
})
}}
/>
{ contextHolder }
</div>
);
......
......@@ -40,7 +40,7 @@ const ModelTree = (props) => {
id: MENU_ID,
});
const { onSelect, onViewChange, refrence='', importStockModel, keyword, searchProperties, setRootNode, onDirRefresh } = props;
const { onSelect, onViewChange, refrence='', importStockModel, keyword, searchProperties, setRootNode, setNode, onDirRefresh } = props;
const { user } = useContext(AppContext);
const [ loading, setLoading ] = useState(false);
......@@ -62,6 +62,7 @@ const ModelTree = (props) => {
const [ dataList, setDataList ] = useState([]);
const [options, setOptions] = useState([]);
const [isAdmin, setAdmin] = useState(false);
const [isCatalogAdmin, setCatalogAdmin] = useState(false);
const [isBranchAdmin, setBranchAdmin] = useState(false);
const [loadingRoot, setLoadingRoot] = useState(false);
......@@ -74,6 +75,7 @@ const ModelTree = (props) => {
useEffect(() => {
getShowSyncAndDomains();
getPrivilegeAdmin();
getCatalogAdmin();
getPrivilegeBranchAdmin();
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
......@@ -117,6 +119,10 @@ const ModelTree = (props) => {
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ keyword, searchProperties, viewSelectedKey, item, prevItem])
useEffect(() => {
setNode?.(item)
}, [item])
const haveStockImportPermission = useMemo(() => {
return (item?.optionList||[]).findIndex(option => option.name==='存量模型导入'&&option.enabled) !== -1
}, [item])
......@@ -149,6 +155,15 @@ const ModelTree = (props) => {
});
}
const getCatalogAdmin = () => {
dispatch({
type: 'datamodel.getCatalogAdmin',
callback: data => {
setCatalogAdmin(data==='true'?true:false);
}
});
}
const getPrivilegeBranchAdmin = () => {
dispatch({
type: 'datamodel.getPrivilegeBranchAdmin',
......@@ -646,7 +661,7 @@ const ModelTree = (props) => {
</Dropdown>
{
((viewSelectedKey==='dir'&&isAdmin) || (viewSelectedKey==='branch'&&(isAdmin||isBranchAdmin))) && (
((viewSelectedKey==='dir'&&(isAdmin||isCatalogAdmin)) || (viewSelectedKey==='branch'&&(isAdmin||isBranchAdmin))) && (
<Tooltip title={(viewSelectedKey==='dir')?"新增目录":'新增项目'}>
<PlusOutlined className='default' onClick={add} style={{ fontSize:16,cursor:'pointer' }} />
</Tooltip>
......@@ -665,7 +680,7 @@ const ModelTree = (props) => {
</Tooltip>
{
(viewSelectedKey==='dir' && isAdmin) && !isSetRootId && (
(viewSelectedKey==='dir'&&(isAdmin||isCatalogAdmin)) && !isSetRootId && (
<Dropdown overlay={syncMenu} placement="bottomLeft">
<Tooltip title="同步目录">
<SyncOutlined className='default' style={{ fontSize:16,cursor:'pointer' }} />
......@@ -675,7 +690,7 @@ const ModelTree = (props) => {
}
{
(viewSelectedKey==='dir' && isAdmin) && isSetRootId && (
(viewSelectedKey==='dir'&&(isAdmin||isCatalogAdmin)) && isSetRootId && (
<Tooltip title="同步目录" className='ml-2'>
<SyncOutlined className='default' style={{ fontSize:16,cursor:'pointer' }} onClick={sync} />
</Tooltip>
......@@ -683,7 +698,7 @@ const ModelTree = (props) => {
}
{
(viewSelectedKey==='dir' && !isAdmin) && <React.Fragment>
(viewSelectedKey==='dir'&&!isAdmin&&!isCatalogAdmin) && <React.Fragment>
<div style={{ width: 16 }}></div>
<div style={{ width: 16 }}></div>
</React.Fragment>
......@@ -735,7 +750,7 @@ const ModelTree = (props) => {
return <span title={nodeData?.remark||''}>{nodeData?.name||''}</span>;
}}
onRightClick={({event, node}) => {
if ((viewSelectedKey==='dir'&&isAdmin) || (viewSelectedKey === 'branch'&&(node?.deletable||node?.editable))) {
if ((viewSelectedKey==='dir'&&(isAdmin||isCatalogAdmin)) || (viewSelectedKey === 'branch'&&(node?.deletable||node?.editable))) {
setCurrentRightClickDir(node);
displayMenu(event);
}
......
......@@ -6,14 +6,12 @@ import { formatVersionDate, showMessage } from '../../../../util';
import VersionCompareHeader from './VersionCompareHeader';
import VersionCompareTable from './VersionCompareTable';
import VersionCompareIndex from './VersionCompareIndex';
import FilterColumnAction from './FilterColumnAction';
import VersionDdlAlter from './version-ddl-alter';
import './VersionCompare.less';
const { Text, Paragraph } = Typography;
const { Option } = Select;
export const defaultColumnTitles = ['序号', '中文名称', '英文名称', '类型', '业务含义'];
const VersionCompare = (props) => {
......@@ -27,8 +25,6 @@ const VersionCompare = (props) => {
const [ compareData, setCompareData ] = useState(null);
const [ loadingCompare, setLoadingCompare ] = useState(false);
const [ onlyShowChange, setOnlyShowChange ] = useState(true);
const [ attrFilterColumns, setAttrFilterColumns ] = useState([]);
const [ attrSelectedTitles, setAttrSelectedTitles ] = useState(defaultColumnTitles);
const [ddlAlterParams, setAlterParams] = useState({
visible: false,
id: undefined,
......@@ -36,8 +32,6 @@ const VersionCompare = (props) => {
basicVersion: undefined,
incVersion: undefined,
})
const attrColumnsRef = useRef([]);
useEffect(() => {
if ((id||'') !== '') {
......@@ -132,51 +126,6 @@ const VersionCompare = (props) => {
callback: data => {
setLoadingCompare(false);
setCompareData(data);
const newAttrOptionColumns = [];
(data?.heads?.columnHead||[]).forEach((item, index) => {
newAttrOptionColumns.push({
title: item||'',
dataIndex: `column${index}`,
render: (attrValue, record, index) => {
let stateClassName = '';
if (attrValue?.state==='ADD' || attrValue?.state==='UPDATE') {
stateClassName = 'add';
} else if (attrValue?.state === 'DELETE') {
stateClassName = 'delete';
}
return (
<Paragraph>
<Tooltip title={attrValue?.value||''}>
<Text className={stateClassName} ellipsis={true}>{attrValue?.value||''}</Text>
</Tooltip>
</Paragraph>
);
},
width: (item==='序号')?60: 150,
ellipsis: true,
option: true,
});
})
const newAttrColumns = [...newAttrOptionColumns, {
title: <FilterColumnAction columns={newAttrOptionColumns} defaultSelectedKeys={defaultColumnTitles} onChange={onFilterChange} />,
dataIndex: 'columnFilter',
render: (_, record, index) => {
return '';
},
width: 40,
ellipsis: true,
option: false
}];
attrColumnsRef.current = newAttrColumns;
const newFilterColumns = newAttrColumns.filter(column => column.option===false || attrSelectedTitles.indexOf(column.title) !== -1);
setAttrFilterColumns(newFilterColumns);
},
error: () => {
setLoadingCompare(false);
......@@ -184,13 +133,6 @@ const VersionCompare = (props) => {
})
}
const onFilterChange = (values) => {
const newFilterColumns = attrColumnsRef.current.filter(column => column.option===false || values.indexOf(column.title) !== -1);
setAttrSelectedTitles(values);
setAttrFilterColumns(newFilterColumns);
}
const onAlterClick = () => {
setAlterParams({
visible: true,
......@@ -257,20 +199,7 @@ const VersionCompare = (props) => {
<div className='py-5'>
<Spin spinning={loadingCompare} >
{
compareData && <div className='flex'>
<div style={{ flex: 1, borderRight: '1px solid #EFEFEF', paddingRight: 10, overflow: 'hidden'}}>
<VersionCompareHeader data={compareData} />
<VersionCompareTable data={compareData} columns={attrFilterColumns} />
<VersionCompareIndex data={compareData} />
</div>
<div style={{ flex: 1, paddingLeft: 10, overflow: 'hidden'}}>
<VersionCompareHeader data={compareData} direction='right' />
<VersionCompareTable data={compareData} columns={attrFilterColumns} direction='right' />
<VersionCompareIndex data={compareData} direction='right'/>
</div>
</div>
}
<CompareDetail data={compareData} />
</Spin>
</div>
<VersionDdlAlter
......@@ -289,4 +218,36 @@ const VersionCompare = (props) => {
);
}
export default VersionCompare;
\ No newline at end of file
export default VersionCompare;
export const CompareDetail = ({ data }) => {
const [selectedColumnTitles, setSelectedColumnTitles] = React.useState()
return (
<>
{
data && <div className='flex'>
<div style={{ flex: 1, borderRight: '1px solid #EFEFEF', paddingRight: 10, overflow: 'hidden'}}>
<VersionCompareHeader data={data} />
<VersionCompareTable
data={data}
selectedColumnTitles={selectedColumnTitles}
onFilterChange={(val) => setSelectedColumnTitles(val)}
/>
<VersionCompareIndex data={data} />
</div>
<div style={{ flex: 1, paddingLeft: 10, overflow: 'hidden'}}>
<VersionCompareHeader data={data} direction='right' />
<VersionCompareTable
data={data}
selectedColumnTitles={selectedColumnTitles}
onFilterChange={(val) => setSelectedColumnTitles(val)}
direction='right'
/>
<VersionCompareIndex data={data} direction='right'/>
</div>
</div>
}
</>
)
}
\ No newline at end of file
import { useEffect, useState } from 'react';
import { Typography, Table } from 'antd';
import React from 'react';
import { Typography, Table, Tooltip } from 'antd';
import FilterColumnAction from './FilterColumnAction';
const { Title } = Typography;
export const defaultColumnTitles = ['序号', '中文名称', '英文名称', '类型', '业务含义'];
const VersionCompareTable = (props) => {
const { data, direction = 'left', selectedColumnTitles = defaultColumnTitles, onFilterChange } = props;
const [columns, setColumns] = React.useState()
const { data, direction = 'left', columns } = props;
const [ tableData, setTableData ] = useState([]);
useEffect(() => {
const newTableData = [];
let columnValue = [];
if (direction==='left') {
columnValue = data?.left?.columnValue||[];
} else if (direction==='right') {
columnValue = data?.right?.columnValue||[];
React.useEffect(() => {
const newColumns = [];
for (const [index, item] of (data?.heads?.columnHead||[]).entries()) {
newColumns.push({
title: item||'',
dataIndex: `column${index}`,
render: (attrValue, record, index) => {
let stateClassName = '';
if (attrValue?.state==='ADD' || attrValue?.state==='UPDATE') {
stateClassName = 'add';
} else if (attrValue?.state === 'DELETE') {
stateClassName = 'delete';
}
return (
<Typography.Paragraph>
<Tooltip title={attrValue?.value||''}>
<Typography.Text className={stateClassName} ellipsis={true}>{attrValue?.value||''}</Typography.Text>
</Tooltip>
</Typography.Paragraph>
);
},
width: (item==='序号')?60: 150,
ellipsis: true,
option: true,
});
}
(columnValue||[]).forEach((attrItem) => {
let newAttrItem = {};
(attrItem||[]).forEach((item, index) => {
newAttrItem[`column${index}`] = item;
})
newTableData.push(newAttrItem);
})
setColumns([...newColumns, {
title: <FilterColumnAction columns={newColumns} defaultSelectedKeys={defaultColumnTitles} onChange={(val) => onFilterChange?.(val)} />,
dataIndex: 'columnFilter',
render: (_, record, index) => {
return '';
},
width: 40,
ellipsis: true,
option: false
}])
}, [data])
setTableData(newTableData);
const _columns = React.useMemo(() => {
return (columns??[]).filter(column => column.option===false || (selectedColumnTitles??[]).indexOf(column.title) !== -1)
}, [selectedColumnTitles, columns])
const tableData = React.useMemo(() => {
const newTableData = [];
let columnValue = (direction==='left') ? data?.left?.columnValue : data?.right?.columnValue;
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ data ])
for (const item of columnValue??[]) {
let newItem = {};
for (const [index, _item] of item.entries()) {
newItem[`column${index}`] = _item;
}
newTableData.push(newItem);
}
return newTableData
}, [direction, data])
return (
<div>
......@@ -38,7 +79,7 @@ const VersionCompareTable = (props) => {
</Typography>
</div>
<Table
columns={columns||[]}
columns={_columns||[]}
dataSource={tableData}
pagination={false}
/>
......
import React from "react"
import { Modal, Button } from 'antd'
import Draggable from 'react-draggable'
import { QuestionCircleFilled } from '@ant-design/icons'
import { dispatch } from '../../../../model'
const FC = (props) => {
const { type } = props
const [tip, setTip] = React.useState()
const [visible, setVisible] = React.useState(false)
const [disabled, setDisabled] = React.useState(true)
const [bounds, setBounds] = React.useState({ left: 0, top: 0, bottom: 0, right: 0 })
const draggleRef = React.useRef()
React.useEffect(() => {
getTip()
}, [])
const title = React.useMemo(() => {
return type==='design' ? '设计评审提示' : '规范评审提示'
}, [type])
const getTip = () => {
dispatch({
type: 'datamodel.getPhysicalModelApprovalTip',
payload: {
type
},
callback: data => {
setTip(data?.tip)
}
})
}
const handleCancel = (e) => {
setVisible(false)
}
const onStart = (_event, uiData) => {
const { clientWidth, clientHeight } = window.document.documentElement;
const targetRect = draggleRef.current?.getBoundingClientRect();
if (!targetRect) {
return;
}
setBounds({
left: -targetRect.left + uiData.x,
right: clientWidth - (targetRect.right - uiData.x),
top: -targetRect.top + uiData.y,
bottom: clientHeight - (targetRect.bottom - uiData.y),
});
}
return (
<>
{
tip && <Button icon={<QuestionCircleFilled style={{ fontSize: 18, color: '#3B80D6' }} />} onClick={() => {
setVisible(true)
}} />
}
<Modal
title={
<div
style={{
width: '100%',
cursor: 'move',
}}
onMouseOver={() => {
if (disabled) {
setDisabled(false);
}
}}
onMouseOut={() => {
setDisabled(true);
}}
// fix eslintjsx-a11y/mouse-events-have-key-events
// https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/mouse-events-have-key-events.md
onFocus={() => {}}
onBlur={() => {}}
// end
>
{ title }
</div>
}
visible={visible}
onCancel={handleCancel}
footer={null}
bodyStyle={{ padding: '15px', overflowX: 'auto', maxHeight: '80vh' }}
modalRender={modal => (
<Draggable
disabled={disabled}
bounds={bounds}
onStart={(event, uiData) => onStart(event, uiData)}
>
<div ref={draggleRef}>{modal}</div>
</Draggable>
)}
>
<div>
{ (tip??'').split('\n').map((item, index) => (<div key={index}>{item}</div>)) }
</div>
</Modal>
</>
)
}
export default FC
\ No newline at end of file
......@@ -2,11 +2,7 @@ import React from 'react'
import { Modal, Button, Spin, Form, Checkbox, Typography, Tooltip, Row, Col, Tree, } from 'antd'
import { dispatch } from '../../../../model'
import VersionCompareHeader from './VersionCompareHeader'
import VersionCompareTable from './VersionCompareTable'
import VersionCompareIndex from './VersionCompareIndex'
import { defaultColumnTitles } from './VersionCompare'
import FilterColumnAction from './FilterColumnAction'
import { CompareDetail } from './VersionCompare'
import './VersionCompare.less'
import { formatDate } from '../../../../util'
......@@ -61,7 +57,7 @@ const FC = (props) => {
onCancel={() => { close() }}
>
<Spin spinning={waiting}>
<Diff item={item} />
<Basic item={item} />
</Spin>
</Modal>
)
......@@ -69,12 +65,10 @@ const FC = (props) => {
export default FC
const Diff = ({ item }) => {
const Basic = ({ item }) => {
const [loading, setLoading] = React.useState(false)
const [data, setData] = React.useState()
const [onlyShowChange, setOnlyShowChange] = React.useState(true)
const [attrSelectedTitles, setAttrSelectedTitles] = React.useState(defaultColumnTitles)
const [attrColumns, setAttrColumns] = React.useState()
React.useEffect(() => {
if (item) {
......@@ -82,59 +76,6 @@ const Diff = ({ item }) => {
}
}, [item, onlyShowChange])
React.useEffect(() => {
if (data) {
const newAttrOptionColumns = [];
(data?.heads?.columnHead||[]).forEach((item, index) => {
newAttrOptionColumns.push({
title: item||'',
dataIndex: `column${index}`,
render: (attrValue, record, index) => {
let stateClassName = '';
if (attrValue?.state==='ADD' || attrValue?.state==='UPDATE') {
stateClassName = 'add';
} else if (attrValue?.state === 'DELETE') {
stateClassName = 'delete';
}
return (
<Typography.Paragraph>
<Tooltip title={attrValue?.value||''}>
<Typography.Text className={stateClassName} ellipsis={true}>{attrValue?.value||''}</Typography.Text>
</Tooltip>
</Typography.Paragraph>
);
},
width: (item==='序号')?60: 150,
ellipsis: true,
option: true,
});
});
const newAttrColumns = [...newAttrOptionColumns, {
title: <FilterColumnAction columns={newAttrOptionColumns} defaultSelectedKeys={defaultColumnTitles} onChange={onFilterChange} />,
dataIndex: 'columnFilter',
render: (_, record, index) => {
return '';
},
width: 40,
ellipsis: true,
option: false
}];
setAttrColumns(newAttrColumns)
}
}, [data])
const attrFilterColumns = React.useMemo(() => {
return (attrColumns??[]).filter(column => column.option===false || (attrSelectedTitles??[]).indexOf(column.title) !== -1)
}, [attrSelectedTitles, attrColumns])
const onFilterChange = (values) => {
setAttrSelectedTitles(values)
}
const onOnlyShowChange = (e) => {
setOnlyShowChange(e.target.checked)
}
......@@ -176,20 +117,7 @@ const Diff = ({ item }) => {
<div className='py-5'>
<Spin spinning={loading} >
{
data && <div className='flex'>
<div style={{ flex: 1, borderRight: '1px solid #EFEFEF', paddingRight: 10, overflow: 'hidden'}}>
<VersionCompareHeader data={data} />
<VersionCompareTable data={data} columns={attrFilterColumns} />
<VersionCompareIndex data={data} />
</div>
<div style={{ flex: 1, paddingLeft: 10, overflow: 'hidden'}}>
<VersionCompareHeader data={data} direction='right' />
<VersionCompareTable data={data} columns={attrFilterColumns} direction='right' />
<VersionCompareIndex data={data} direction='right'/>
</div>
</div>
}
<CompareDetail data={data} />
</Spin>
</div>
</div>
......
......@@ -203,22 +203,7 @@ const Basic = React.forwardRef(function ({ type, items }, ref) {
setLoadingTreeData(false)
setRootNode(data)
const newTreeData = produce(data?.subCatalogs??[], draft => {
const setNode = (g) => {
g.key = g.id;
g.title = g.name;
g.children = [];
(g.subCatalogs??[]).forEach((child) => {
setNode(child)
g.children.push(child)
});
}
draft.forEach((child) => {
setNode(child)
})
})
const newTreeData = data?.subCatalogs??[]
setTreeData(newTreeData)
if ((newTreeData??[]).length > 0) {
setNode(newTreeData[0])
......
import React from 'react';
import { Modal, Button, Form, Radio } from 'antd';
import copy from "copy-to-clipboard"
import { dispatch } from '../../../../model'
import { showNotifaction } from '../../../../util'
import ExportDDL from './export-ddl'
const exportModes = [
{ name: '导出DDL', key: 'ddl' },
{ name: '导出Erwin', key: 'erwin' },
{ name: '导出Excel', key: 'excel' },
{ name: '导出Word', key: 'word' },
]
const FC = (props) => {
const { ids, visible, onCancel } = props
const [exportDDLParams, setExportDDLParams] = React.useState({
visible: false
})
const basicRef = React.useRef()
const [form] = Form.useForm()
const save = async() => {
try {
await basicRef.current.validate()
const modeKey = basicRef.current.modeKey
if (modeKey === 'ddl') {
setExportDDLParams({ visible: true })
} if (modeKey === 'erwin') {
dispatch({
type: 'datamodel.exportERWinString',
payload: {
ids: (ids??[]).toString(),
},
callback: data => {
copy(JSON.stringify(data))
showNotifaction('提示', 'Erwin信息已成功复制到剪贴板', 5)
}
})
} else if (modeKey === 'excel') {
window.open(`/api/datamodeler/easyDataModelerExport/excel?ids=${(ids??[]).toString()}`)
} else if (modeKey === 'word') {
window.open(`/api/datamodeler/easyDataModelerExport/word/template?ids=${(ids??[]).toString()}`)
}
} catch (errInfo) {
console.log('Validate Failed:', errInfo);
}
}
const close = () => {
onCancel?.()
}
const footer = React.useMemo(() => {
return [
<Button key='cancel'
onClick={() => close()}
>取消</Button>,
<Button key='save' type='primary'
onClick={() => save()}
>保存</Button>
]
}, [close, save])
return (
<>
<Modal
visible={visible}
title='模型导出'
width={540}
footer={footer}
destroyOnClose
onCancel={() => { close() }}
>
<Basic ref={basicRef} />
</Modal>
<ExportDDL
{...exportDDLParams}
ids={ids}
onCancel={() => {
setExportDDLParams({ visible: false })
}}
/>
</>
)
}
export default FC
const Basic = React.forwardRef(function ({}, ref) {
const [modeKey, setModeKey] = React.useState()
const [form] = Form.useForm()
React.useImperativeHandle(ref, () => ({
validate: async () => {
return await form.validateFields()
},
modeKey
}), [form, modeKey])
const onModeChange = (e) => {
setModeKey(e.target?.value)
}
return (
<Form form={form}>
<Form.Item name='mode' label='导出方式'
rules={[{ required: true, message: '请选择导出方式' }]}
>
<Radio.Group onChange={onModeChange} value={modeKey}>
{
exportModes.map((item) => (
<Radio value={item.key} key={item.key}>
{item.name}
</Radio>
))
}
</Radio.Group>
</Form.Item>
</Form>
)
})
\ No newline at end of file
......@@ -2,11 +2,7 @@ import React from 'react'
import { Modal, Button, Spin, Form, Checkbox, Typography, Tooltip, Row, Col, Tree, } from 'antd'
import { dispatch } from '../../../../model'
import VersionCompareHeader from './VersionCompareHeader'
import VersionCompareTable from './VersionCompareTable'
import VersionCompareIndex from './VersionCompareIndex'
import { defaultColumnTitles } from './VersionCompare'
import FilterColumnAction from './FilterColumnAction'
import { CompareDetail } from './VersionCompare'
import './merge-to-master.less'
import './VersionCompare.less'
......@@ -119,8 +115,6 @@ export const Diff = ({ item }) => {
const [loading, setLoading] = React.useState(false)
const [data, setData] = React.useState()
const [onlyShowChange, setOnlyShowChange] = React.useState(true)
const [attrSelectedTitles, setAttrSelectedTitles] = React.useState(defaultColumnTitles)
const [attrColumns, setAttrColumns] = React.useState()
React.useEffect(() => {
if (item) {
......@@ -128,59 +122,6 @@ export const Diff = ({ item }) => {
}
}, [item, onlyShowChange])
React.useEffect(() => {
if (data) {
const newAttrOptionColumns = [];
(data?.heads?.columnHead||[]).forEach((item, index) => {
newAttrOptionColumns.push({
title: item||'',
dataIndex: `column${index}`,
render: (attrValue, record, index) => {
let stateClassName = '';
if (attrValue?.state==='ADD' || attrValue?.state==='UPDATE') {
stateClassName = 'add';
} else if (attrValue?.state === 'DELETE') {
stateClassName = 'delete';
}
return (
<Typography.Paragraph>
<Tooltip title={attrValue?.value||''}>
<Typography.Text className={stateClassName} ellipsis={true}>{attrValue?.value||''}</Typography.Text>
</Tooltip>
</Typography.Paragraph>
);
},
width: (item==='序号')?60: 150,
ellipsis: true,
option: true,
});
});
const newAttrColumns = [...newAttrOptionColumns, {
title: <FilterColumnAction columns={newAttrOptionColumns} defaultSelectedKeys={defaultColumnTitles} onChange={onFilterChange} />,
dataIndex: 'columnFilter',
render: (_, record, index) => {
return '';
},
width: 40,
ellipsis: true,
option: false
}];
setAttrColumns(newAttrColumns)
}
}, [data])
const attrFilterColumns = React.useMemo(() => {
return (attrColumns??[]).filter(column => column.option===false || (attrSelectedTitles??[]).indexOf(column.title) !== -1)
}, [attrSelectedTitles, attrColumns])
const onFilterChange = (values) => {
setAttrSelectedTitles(values)
}
const onOnlyShowChange = (e) => {
setOnlyShowChange(e.target.checked)
}
......@@ -221,20 +162,7 @@ export const Diff = ({ item }) => {
<div className='py-5'>
<Spin spinning={loading} >
{
data && <div className='flex'>
<div style={{ flex: 1, borderRight: '1px solid #EFEFEF', paddingRight: 10, overflow: 'hidden'}}>
<VersionCompareHeader data={data} />
<VersionCompareTable data={data} columns={attrFilterColumns} />
<VersionCompareIndex data={data} />
</div>
<div style={{ flex: 1, paddingLeft: 10, overflow: 'hidden'}}>
<VersionCompareHeader data={data} direction='right' />
<VersionCompareTable data={data} columns={attrFilterColumns} direction='right' />
<VersionCompareIndex data={data} direction='right'/>
</div>
</div>
}
<CompareDetail data={data} />
</Spin>
</div>
</div>
......
import React from 'react'
import { Modal, Button, Row, Col, Spin, Tree, Input, Pagination, Tooltip, Typography, Space, Select, } from 'antd'
import { useDebounceEffect } from "ahooks"
import { dispatch } from '../../../../model'
import Table from '../../ResizeableTable'
import produce from 'immer'
import { paginate, showMessage } from '../../../../util'
import ModelCompare from './model-compare'
import './branch-select-model.less'
const FC = ({ visible, item, onCancel }) => {
const [animated, setAnimated] = React.useState(true)
const [modelCompareParams, setModelCompareParams] = React.useState({
visible: false,
leftItem: undefined,
rightItem: undefined
})
const basicRef = React.useRef()
React.useEffect(() => {
if (visible) {
setTimeout(() => {
setAnimated(false)
}, 300)
}
}, [visible])
const close = () => {
setAnimated(true)
onCancel?.()
}
const save = () => {
const selectedRows = basicRef.current.selectedRows??[]
if ((selectedRows??[]).length === 0) {
showMessage('warn', '请选选择模型')
return
}
setModelCompareParams({
visible: true,
leftItem: item,
rightItem: selectedRows[0]
})
}
const footer = React.useMemo(() => {
return [
<Button key='cancel'
onClick={() => close()}
>取消</Button>,
<Button key='save' type='primary'
onClick={() => save()}
>确定</Button>
]
}, [close, save])
return (
<>
<Modal
title='模型对比设置'
visible={visible}
footer={footer}
width='80%'
bodyStyle={{ padding: '15px', overflowX: 'auto', height: '80vh' }}
centered destroyOnClose
onCancel={() => { close() }}
>
{ !animated && <Basic ref={basicRef} /> }
</Modal>
<ModelCompare
{...modelCompareParams}
onCancel={() => {
setModelCompareParams({
visible: false,
leftItem: undefined,
rightItem: undefined,
})
}}
/>
</>
)
}
export default FC
const Basic = React.forwardRef(function ({}, ref) {
const [args, setArgs] = React.useState({
keyword: undefined,
})
const [pagination, setPagination] = React.useState({
page: 1,
size: 20,
})
const [loadingTreeData, setLoadingTreeData] = React.useState(false)
const [treeData, setTreeData] = React.useState()
const [node, setNode] = React.useState()
const [loading, setLoading] = React.useState(false)
const [data, setData] = React.useState()
const [selectedRows, setSelectedRows] = React.useState()
const [expandedKeys, setExpandedKeys] = React.useState([])
const [autoExpandParent, setAutoExpandParent] = React.useState(false)
React.useImperativeHandle(ref, () => ({
selectedRows
}), [selectedRows])
React.useEffect(() => {
getTreeData()
}, [])
React.useEffect(() => {
setPagination({...pagination, page: 1})
}, [node])
useDebounceEffect(() => {
if (node) {
getDataModels()
}
}, [node, args], { wait: 300 })
const treeData1 = React.useMemo(() => {
if (treeData) {
const newTreeData = produce(treeData, draft => {
const setNode = (g) => {
g.key = g.id;
g.title = g.name;
g.children = [];
(g.subCatalogs??[]).forEach((child) => {
setNode(child)
g.children.push(child)
});
}
draft.forEach((child) => {
setNode(child)
})
})
return newTreeData
}
return undefined
}, [treeData])
const setArgsByParams = React.useCallback((params) => {
setArgs((prev) => {
return {...prev, ...params}
})
}, [])
const [tableData, total] = React.useMemo(() => {
const newData= [...data??[]]
return [paginate(newData, pagination.page, pagination.size), (newData??[]).length]
}, [data, pagination])
const columns = [
{
title: '模型名称',
dataIndex: 'name',
render: (text, record) => {
return <Tooltip title={text}>
<Typography.Text ellipsis={true}>{text}</Typography.Text>
</Tooltip>
}
},
{
title: '中文名称',
dataIndex: 'cnName',
render: (text, record) => {
return <Tooltip title={text}>
<Typography.Text ellipsis={true}>{text}</Typography.Text>
</Tooltip>
}
},
{
title: '描述',
dataIndex: 'remark',
render: (text, record) => {
return <Tooltip title={text}>
<Typography.Text ellipsis={true}>{text}</Typography.Text>
</Tooltip>
}
},
{
title: '创建人',
dataIndex: 'editor',
render: (text, record) => {
return <Tooltip title={text}>
<Typography.Text ellipsis={true}>{text}</Typography.Text>
</Tooltip>
}
},
]
const getTreeData = () => {
setLoadingTreeData(true)
dispatch({
type: 'datamodel.refreshDataModelCatalog',
callback: (data) => {
setLoadingTreeData(false)
const newTreeData = data?.subCatalogs??[]
setTreeData(newTreeData)
if ((newTreeData??[]).length > 0) {
setNode(newTreeData[0])
}
},
error: () => {
setLoadingTreeData(false)
}
})
}
const getDataModels = () => {
setLoading(true)
if (args.keyword) {
} else {
dispatch({
type: 'datamodel.getCurrentDataModelCatalog',
payload: {
easyDataModelerCatalogId: node?.id,
},
callback: (data) => {
setLoading(false)
setData(data?.easyDataModelerDataModels)
},
error: () => {
setLoading(false)
}
})
}
}
const onTreeExpand = (expandedKeys) => {
setExpandedKeys(expandedKeys)
setAutoExpandParent(false)
}
const onTreeSelect = (selectedKeys, { selectedNodes }) => {
if (selectedKeys.length === 0 || selectedNodes.length === 0) {
return
}
setNode(selectedNodes[0])
}
const onChange = (val) => {
setSelectedRows(val)
}
return (
<div className='branch-select-model'>
<Row>
<Col span={4}>
<Spin spinning={loadingTreeData}>
<Tree
className='tree'
showLine
showIcon={false}
autoExpandParent={autoExpandParent}
treeData={treeData1}
selectedKeys={node?[node.id]:[]}
expandedKeys={expandedKeys}
onSelect={onTreeSelect}
onExpand={onTreeExpand}
/>
</Spin>
</Col>
<Col span={20}>
<div
style={{
display: 'flex',
padding: '0px 0px 15px',
alignItems: 'center',
justifyContent: 'flex-end',
}}>
<Input size="middle"
placeholder="请输入关键字搜索"
value={args.keyword}
bordered={true} allowClear
onChange={(e) => {
setArgsByParams({ keyword: e.target.value })
setPagination({ ...pagination, page: 1 })
}}
style={{ width: 200 }}
/>
</div>
<Table
size='small'
extraColWidth={32}
rowKey='id'
loading={loading}
columns={columns}
dataSource={tableData??[]}
pagination={false}
rowSelection={{
type: 'radio',
selectedRowKeys: (selectedRows??[]).map(item => item.id),
onChange: (selectedRowKeys, selectedRows) => {
setSelectedRows(selectedRows)
},
}}
scroll={{ y: 'calc(80vh - 170px)' }}
/>
{
total!==0 && <Pagination
style={{
textAlign: 'center',
marginTop: 15,
}}
showSizeChanger
onChange={(page,size) => {
setPagination({page, size})
}}
current={pagination.page}
pageSize={pagination.size}
defaultCurrent={1}
total={total}
showTotal={(total) => `共${total??0}项`}
/>
}
</Col>
</Row>
</div>
)
})
\ No newline at end of file
import React from 'react'
import { Modal, Checkbox, Spin } from 'antd'
import { CompareDetail } from './VersionCompare'
import { dispatch } from '../../../../model'
const FC = ({ visible, leftItem, rightItem, onCancel }) => {
const close = () => {
onCancel?.()
}
return (
<Modal
title='模型对比'
visible={visible}
footer={null}
width='70%'
bodyStyle={{ padding: '15px', overflowX: 'auto', height: '80vh' }}
centered destroyOnClose
onCancel={() => { close() }}
>
<Basic leftItem={leftItem} rightItem={rightItem} />
</Modal>
)
}
export default FC
const Basic = ({ leftItem, rightItem }) => {
const [loading, setLoading] = React.useState(false)
const [data, setData] = React.useState()
const [onlyShowChange, setOnlyShowChange] = React.useState(true)
React.useEffect(() => {
if (leftItem && rightItem) {
compareOtherModel()
}
}, [leftItem, rightItem, onlyShowChange])
const onOnlyShowChange = (e) => {
setOnlyShowChange(e.target.checked)
}
const compareOtherModel = () => {
setLoading(true)
dispatch({
type: 'datamodel.compareOtherModel',
payload: {
params: {
leftEasyDataModelerDataModelId: leftItem?.id,
rightEasyDataModelerDataModelId: rightItem?.id,
includeSame: !onlyShowChange,
}
},
callback: data => {
setLoading(false)
setData(data)
},
error: () => {
setLoading(false)
}
})
}
return (
<div className='model-version-compare'>
<div className='flex'>
<div style={{ flex: 1, paddingRight: 10, overflow: 'hidden'}}>
{`模型:${leftItem?.path}/${leftItem?.name}`}
</div>
<div style={{ flex: 1, paddingLeft: 10, overflow: 'hidden'}}>
<div className='flex' style={{ justifyContent: 'space-between', alignItems: 'center' }}>
<span>{`模型:${rightItem?.path}/${rightItem?.name}`}</span>
<Checkbox onChange={onOnlyShowChange} checked={onlyShowChange}>
仅显示差异
</Checkbox>
</div>
</div>
</div>
<div className='py-5'>
<Spin spinning={loading} >
<CompareDetail data={data} />
</Spin>
</div>
</div>
)
}
\ No newline at end of file
import React from 'react'
import { Descriptions, Row, Col, Typography, Tooltip, Space } from 'antd'
import { stateColorDic } from './ModelTable'
const FC = (props) => {
const { data, node } = props
const [deployedCount, deployWaitingCount, releaseWaitingCount, offlineCount] = React.useMemo(() => {
return [
(data??[]).filter(item => item.state?.cnName === '已上线').length,
(data??[]).filter(item => item.state?.cnName === '评审通过').length,
(data??[]).filter(item => item.state?.cnName === '评审中').length,
(data??[]).filter(item => item.state?.cnName === '已下线').length,
]
}, [data])
return (
<div style={{ height: 80, padding: '10px 20px' }}>
<Row gutter={10}>
<Col flex='1' style={{ overflow: 'hidden' }}>
<Tooltip title={node?.title}>
<Typography.Text ellipsis={true} style={{ fontWeight: 500, fontSize: 16 }}>
{node?.title}
</Typography.Text>
</Tooltip>
</Col>
<Col flex='0 0 auto'>
<Space size={50}>
<StateItem title='已上线' count={deployedCount} />
<StateItem title='评审通过' count={deployWaitingCount} />
<StateItem title='评审中' count={releaseWaitingCount} />
<StateItem title='已下线' count={offlineCount} />
</Space>
</Col>
</Row>
<div style={{ marginTop: 10 }}>
<Tooltip title={node?.remark}>
<Typography.Text ellipsis={true}>
{node?.remark}
</Typography.Text>
</Tooltip>
</div>
</div>
)
}
export default FC
const StateItem = ({ title, count }) => {
return (
<Space size={10}>
<div style={{ width: 10, height: 10, borderRadius: 5, backgroundColor: stateColorDic[title]??'#77DEBF' }}></div>
<span>{title}</span>
<span style={{ color: stateColorDic[title]??'#77DEBF' }}>{count}</span>
</Space>
)
}
\ No newline at end of file
......@@ -6,7 +6,7 @@ import { useDebounceEffect } from 'ahooks'
import { isSzseEnv, showMessage, showNotifaction } from '../../../../util'
import Table from '../../../../util/Component/Table'
import produce from 'immer'
import { Action, CatalogId, Editable, Holder, ModelerId, PermitCheckOut, ReadOnly, StateId } from '../../../../util/constant'
import { Action, CatalogId, Editable, ModelerId, PermitCheckOut, ReadOnly, StateId } from '../../../../util/constant'
import { dispatch } from '../../../../model'
const FC = (props) => {
......@@ -75,7 +75,7 @@ const FC = (props) => {
visible={visible}
footer={footer}
width='80%'
bodyStyle={{ padding: '15px', overflowX: 'auto', maxHeight: '80vh' }}
bodyStyle={{ padding: '15px', overflowX: 'auto', height: '80vh' }}
title='模型送审'
centered destroyOnClose
onCancel={() => { close() }}
......@@ -327,7 +327,7 @@ const List = React.forwardRef(function ({ items }, ref) {
<Typography.Paragraph ellipsis={{
rows: 3,
}}><a onClick={() => {
window.open(`/data-govern/data-model-action?${Action}=detail&${ModelerId}=${record.id}&${PermitCheckOut}=${record.permitCheckOut||false}&${Editable}=${record.editable||false}&${StateId}=${record.state?.id||''}&${Holder}=${record.holder||''}&${ReadOnly}=false`);
window.open(`/data-govern/data-model-action?${Action}=detail&${ModelerId}=${record.id}&${PermitCheckOut}=${record.permitCheckOut||false}&${Editable}=${record.editable||false}&${StateId}=${record.state?.id||''}&${ReadOnly}=false`);
}}>{text}</a></Typography.Paragraph>
</Tooltip>
)
......
......@@ -4,7 +4,7 @@ import { ArrowsAltOutlined, ShrinkOutlined } from '@ant-design/icons';
import { dispatch } from '../../../../model'
import Table from '../../../../util/Component/Table'
import { checkMenuAdmit, inputWidth, isSzseEnv, showMessage } from '../../../../util'
import { checkMenuAdmit, inputWidth, isSzseEnv, openMetadataDetail, showMessage } from '../../../../util'
import { useDebounceEffect } from 'ahooks'
const topN = 20
......@@ -138,7 +138,7 @@ const FC = (props) => {
useDebounceEffect(()=>{
setColumns(isCompact?[...cols].slice(0, 4):[...cols])
}, [cols, isCompact], { wait: 100 })
}, [isCompact], { wait: 100 })
const onSourceClick = (id, name) => {
const timestamp = new Date().getTime();
......@@ -150,7 +150,7 @@ const FC = (props) => {
id
},
callback: data => {
window.open(`/center-home/metadetail?mid=${encodeURIComponent(data?._id)}&action=metadetail&type=detail&manager=false&activekey=1&name=${encodeURIComponent(name||'')}`);
openMetadataDetail(data?._id)
}
})
} else {
......
......@@ -10,29 +10,6 @@
overflow: hidden;
}
.tree-toggle-wrap {
position: relative;
width: 20px;
height: 100%;
.tree-toggle {
display: flex;
justify-content: center;
align-items: center;
left: 0;
right: 0;
background: #f2f5fc;
position: absolute;
top: calc(50% - 40px);
width: 12px;
height: 80px;
border-radius: 0 12px 12px 0;
-ms-transform: translateY(-50%);
transform: translateY(-50%);
cursor: pointer;
}
}
.right {
flex: 1;
overflow: hidden;
......@@ -43,4 +20,28 @@
.left {
width: 0 !important;
}
}
.tree-toggle-wrap {
position: relative;
width: 15px;
height: 100%;
background: #f0f2f5;
.tree-toggle {
display: flex;
justify-content: center;
align-items: center;
left: 0;
right: 0;
background: #f2f5fc;
position: absolute;
top: 50%;
width: 12px;
height: 80px;
border-radius: 0 12px 12px 0;
-ms-transform: translateY(-50%);
transform: translateY(-50%);
cursor: pointer;
}
}
\ No newline at end of file
......@@ -5,7 +5,7 @@ import { defaultPage } from '../../../util/hooks/page'
import Table from '../../../util/Component/Table'
import { dispatch } from '../../../model'
import { generateUUID, paginate, showMessage, showNotifaction } from '../../../util'
import UpdateTask from './update-task'
import UpdateTask, { Range } from './update-task'
import ColConfig from './col-config'
import '../AssetTask/index.less'
......@@ -108,21 +108,12 @@ const FC = (props) => {
dataIndex: 'jobCatalogItems',
render: (_, record) => {
return (
<Tooltip title={
<div>
{
(record.jobCatalogItems??[]).map(item => (
<Row key={generateUUID()}>
{`【模型】${(item.modelCatalogNameList??[]).join('/')} -【元数据】${(item.metadataCatalogNameList??[]).join('/')}`}
</Row>
))
}
</div>
}>
<Tooltip title={<Range task={record} type='detail' />}>
<Typography.Text ellipsis={true}>
{
(record.jobCatalogItems??[]).map(item => `【模型】${(item.modelCatalogNameList??[]).join('/')} -【元数据】${(item.metadataCatalogNameList??[]).join('/')}`).toString()
}
{ (record?.jobModelCatalogItems??[]).length > 0 && '【模型范围】' }
{ record?.jobModelCatalogItems?.map((item, index) => `${(item.modelCatalogNameList??[]).join('/')}`).toString() }
{ (record?.jobMetadataCatalogItems??[]).length > 0 && '【元数据范围】' }
{ record?.jobMetadataCatalogItems?.map((item, index) => `${(item.metadataCatalogNameList??[]).join('/')}`).toString() }
</Typography.Text>
</Tooltip>
)
......
......@@ -422,6 +422,9 @@ const FC = (props) => {
setSelectedRows(selectedRows)
},
}}
scroll={{
y: readonly?'calc(80vh - 230px)':null
}}
/>
</div>
<AddRule
......
......@@ -36,7 +36,7 @@ const ResizeableHeaderCell = props => {
};
const ResizeableTable = (props) => {
const { columns, extraColWidth = 0, ...restProps } = props
const { columns, extraColWidth = 0, components, ...restProps } = props
const [tableWidth, setTableWidth] = useState(0)
......@@ -62,10 +62,18 @@ const ResizeableTable = (props) => {
useEffect(() => {
if (!!columns && tableWidth > 0) {
const contentWidth = getWidth(tableWidth, extraColWidth)
for (const item of columns??[]) {
const index = (cols??[]).findIndex(_item => item.dataIndex === _item.dataIndex && item.title === _item.title)
if (index !== -1) {
item.width = cols[index].width
}
}
setDefaultWidth(columns, contentWidth)
paddingCol.current.width = 0
const cols = columns
const newCols = columns
.map((col, index) => {
const colWidth = col.width ?? 100;
return {
......@@ -78,7 +86,7 @@ const ResizeableTable = (props) => {
}),
};
})
setCols(cols)
setCols(newCols)
}
}, [columns, tableWidth])
......@@ -94,7 +102,8 @@ const ResizeableTable = (props) => {
components={{
header: {
cell: ResizeableHeaderCell,
}
},
...components,
}}
columns={cols1}
{ ...restProps }
......
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