修复定时任务状态筛选

This commit is contained in:
whyour 2023-03-02 23:16:18 +08:00
parent 67bc305950
commit 3b9a4f0834
7 changed files with 632 additions and 128 deletions

View File

@ -245,8 +245,11 @@ export default class CronService {
const filterKeys: any = Object.keys(filterQuery); const filterKeys: any = Object.keys(filterQuery);
for (const key of filterKeys) { for (const key of filterKeys) {
let q: any = {}; let q: any = {};
if (filterKeys[key]) { if (!filterQuery[key]) continue;
q[key] = filterKeys[key]; if (key === 'status' && filterQuery[key].includes(2)) {
q = { [Op.or]: [{ [key]: filterQuery[key] }, { isDisabled: 1 }] };
} else {
q[key] = filterQuery[key];
} }
query[Op.and].push(q); query[Op.and].push(q);
} }

404
src/components/vlist.tsx Normal file
View File

@ -0,0 +1,404 @@
import React, {
useRef,
useEffect,
useContext,
createContext,
useReducer,
useState,
useMemo,
} from 'react';
import { throttle, isNumber, debounce } from 'lodash';
const initialState = {
// 行高度
rowHeight: 0,
// 当前的scrollTop
curScrollTop: 0,
// 总行数
totalLen: 0,
};
function reducer(state, action) {
const { curScrollTop, totalLen, ifScrollTopClear, scrollTop } = action;
let stateScrollTop = state.curScrollTop;
switch (action.type) {
// 改变trs 即 改变渲染的列表trs
case 'changeTrs':
return {
...state,
curScrollTop,
};
// 更改totalLen
case 'changeTotalLen':
if (totalLen === 0) {
stateScrollTop = 0;
}
return {
...state,
totalLen,
curScrollTop: stateScrollTop,
};
case 'reset':
return {
...state,
curScrollTop: ifScrollTopClear ? 0 : scrollTop ?? state.curScrollTop,
};
default:
throw new Error();
}
}
// ==============全局常量 ================== //
const DEFAULT_VID = 'vtable';
const vidMap = new Map();
let preData = 0;
// ===============context ============== //
const ScrollContext = createContext({
dispatch: undefined,
renderLen: 1,
start: 0,
offsetStart: 0,
// =============
rowHeight: initialState.rowHeight,
totalLen: 0,
vid: DEFAULT_VID,
});
// =============组件 =================== //
function VCell(props: any): JSX.Element {
const { children, ...restProps } = props;
return (
<td {...restProps}>
<div>{children[1]}</div>
</td>
);
}
function VRow(props: any, ref: any): JSX.Element {
const { rowHeight } = useContext(ScrollContext);
const { children, style, ...restProps } = props;
const trRef = useRef<HTMLTableRowElement>(null);
return (
<tr
{...restProps}
ref={Object.prototype.hasOwnProperty.call(ref, 'current') ? ref : trRef}
style={{
...style,
height: rowHeight || 'auto',
boxSizing: 'border-box',
}}
>
{children}
</tr>
);
}
function VWrapper(props: any): JSX.Element {
const { children, ...restProps } = props;
const { renderLen, start, dispatch, vid, totalLen } =
useContext(ScrollContext);
const contents = useMemo(() => {
return children[1];
}, [children]);
const contentsLen = useMemo(() => {
return contents?.length ?? 0;
}, [contents]);
useEffect(() => {
if (totalLen !== contentsLen) {
dispatch({
type: 'changeTotalLen',
totalLen: contentsLen ?? 0,
});
}
}, [contentsLen, dispatch, vid, totalLen]);
let tempNode = null;
if (Array.isArray(contents) && contents.length) {
tempNode = [
children[0],
contents.slice(start, start + (renderLen ?? 1)).map((item) => {
if (Array.isArray(item)) {
// 兼容antd v4.3.5 --- rc-table 7.8.1及以下
return item[0];
}
// 处理antd ^v4.4.0 --- rc-table ^7.8.2
return item;
}),
];
} else {
tempNode = children;
}
return <tbody {...restProps}>{tempNode}</tbody>;
}
function VTable(props: any, otherParams): JSX.Element {
const { style, children, ...rest } = props;
const { width, ...rest_style } = style;
const { vid, scrollY, resetScrollTopWhenDataChange, rowHeight, scrollTop } =
otherParams ?? {};
const [state, dispatch] = useReducer(reducer, {
...initialState,
curScrollTop: scrollTop,
rowHeight,
});
const wrap_tableRef = useRef<HTMLDivElement>(null);
const tableRef = useRef<HTMLTableElement>(null);
const ifChangeRef = useRef(false);
// 数据的总条数
const [totalLen, setTotalLen] = useState<number>(
children[1]?.props?.data?.length ?? 0,
);
useEffect(() => {
setTotalLen(state.totalLen);
}, [state.totalLen]);
// 组件卸载的清除操作
useEffect(() => {
return () => {
vidMap.delete(vid);
};
}, [vid]);
// 数据变更
useEffect(() => {
ifChangeRef.current = true;
// console.log('数据变更')
if (isNumber(children[1]?.props?.data?.length)) {
dispatch({
type: 'changeTotalLen',
totalLen: children[1]?.props?.data?.length ?? 0,
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [children[1].props.data]);
// table总高度
const tableHeight = useMemo<string | number>(() => {
let temp: string | number = 'auto';
if (rowHeight && totalLen) {
temp = rowHeight * totalLen;
}
return temp;
}, [totalLen]);
// table的scrollY值
const [tableScrollY, setTableScrollY] = useState(0);
// tableScrollY 随scrollY / tableHeight 进行变更
useEffect(() => {
let temp = 0;
if (typeof scrollY === 'string') {
temp =
(wrap_tableRef.current?.parentNode as HTMLElement)?.offsetHeight ?? 0;
} else {
temp = scrollY;
}
// if (isNumber(tableHeight) && tableHeight < temp) {
// temp = tableHeight;
// }
// 处理tableScrollY <= 0的情况
if (temp <= 0) {
temp = 0;
}
setTableScrollY(temp);
}, [scrollY, tableHeight]);
// 渲染的条数
const renderLen = useMemo<number>(() => {
let temp = 1;
if (rowHeight && totalLen && tableScrollY) {
if (tableScrollY <= 0) {
temp = 0;
} else {
const tempRenderLen = ((tableScrollY / rowHeight) | 0) + 10;
// console.log('tempRenderLen', tempRenderLen)
// temp = tempRenderLen > totalLen ? totalLen : tempRenderLen;
temp = tempRenderLen;
}
}
return temp;
}, [totalLen, tableScrollY]);
// 渲染中的第一条
let start = rowHeight ? (state.curScrollTop / rowHeight) | 0 : 0;
start = start < 5 ? 0 : start - 5 + 1;
// 偏移量
let offsetStart = state.curScrollTop % (rowHeight * 5);
if (start > 0) {
offsetStart = offsetStart % rowHeight;
}
// console.log(offsetStart)
// offsetStart= offsetStart%rowHeight
// 用来优化向上滚动出现的空白
if (state.curScrollTop && state.curScrollTop >= rowHeight * 5) {
// start -= 1
// if (offsetStart >= rowHeight) {
// offsetStart +=
// } else {
offsetStart += rowHeight * 4;
// }
} else {
start = 0;
}
// console.log(state.curScrollTop, start, offsetStart)
// 数据变更 操作scrollTop
useEffect(() => {
const scrollNode = wrap_tableRef.current?.parentNode as HTMLElement;
if (ifChangeRef?.current) {
// console.log(scrollNode)
ifChangeRef.current = false;
if (resetScrollTopWhenDataChange) {
// 重置scrollTop
if (scrollNode) {
scrollNode.scrollTop = 0;
}
dispatch({ type: 'reset', ifScrollTopClear: true });
} else {
// console.log(preData)
// scrollNode.scrollTop = preData+53
// 不重置scrollTop 不清空curScrollTop
dispatch({ type: 'reset', ifScrollTopClear: false });
}
}
if (vidMap.has(vid)) {
vidMap.set(vid, {
...vidMap.get(vid),
scrollNode,
});
}
}, [totalLen, resetScrollTopWhenDataChange, vid, children]);
useEffect(() => {
const throttleScroll = throttle((e) => {
const scrollTop: number = e?.target?.scrollTop ?? 0;
// const scrollHeight: number = e?.target?.scrollHeight ?? 0
// const clientHeight: number = e?.target?.clientHeight ?? 0
if (scrollTop) {
preData = scrollTop;
}
// 到底了 没有滚动条就不会触发reachEnd. 建议设置scrolly高度少点或者数据量多点.
// 若renderLen大于totalLen, 置空curScrollTop. => table paddingTop会置空.
dispatch({
type: 'changeTrs',
curScrollTop: renderLen <= totalLen ? scrollTop : 0,
});
}, 60);
const ref = wrap_tableRef?.current?.parentNode as HTMLElement;
if (ref) {
ref.addEventListener('scroll', throttleScroll, { passive: true });
}
return () => {
ref.removeEventListener('scroll', throttleScroll);
};
}, [renderLen, totalLen]);
return (
<div
className="virtuallist"
ref={wrap_tableRef}
style={{
width: '100%',
position: 'relative',
height: tableHeight,
boxSizing: 'border-box',
paddingTop: state.curScrollTop,
}}
>
<ScrollContext.Provider
value={{
dispatch,
start,
offsetStart,
renderLen,
totalLen,
vid,
rowHeight,
}}
>
<table
{...rest}
ref={tableRef}
style={{
...rest_style,
width,
position: 'relative',
transform: `translateY(-${offsetStart}px)`,
}}
>
{children}
</table>
</ScrollContext.Provider>
</div>
);
}
// ================导出===================
export function VList(props: {
height: number;
// 唯一标识
vid?: string;
rowHeight: number | string;
reset?: boolean;
scrollTop?: number | string;
}): any {
const { vid = DEFAULT_VID, rowHeight, height, reset, scrollTop } = props;
const resetScrollTopWhenDataChange = reset ?? true;
if (!vidMap.has(vid)) {
vidMap.set(vid, { _id: vid });
}
return {
table: (p) =>
VTable(p, {
vid,
scrollY: height,
rowHeight,
resetScrollTopWhenDataChange,
scrollTop,
}),
body: {
wrapper: VWrapper,
row: VRow,
cell: VCell,
},
};
}

View File

@ -1,16 +1,19 @@
import { MutableRefObject, useLayoutEffect, useState } from 'react'; import { MutableRefObject, useLayoutEffect, useState } from 'react';
import useResizeObserver from '@react-hook/resize-observer' import useResizeObserver from '@react-hook/resize-observer';
import { getTableScroll } from '@/utils'; import { getTableScroll } from '@/utils';
export default <T extends HTMLElement>(target: MutableRefObject<T>, extraHeight?: number) => { export default <T extends HTMLElement>(
const [height, setHeight] = useState<number>() target: MutableRefObject<T>,
extraHeight?: number,
) => {
const [height, setHeight] = useState<number>(0);
useResizeObserver(target, (entry) => { useResizeObserver(target, (entry) => {
let _targe = entry.target as any let _target = entry.target as any;
if (!_targe.classList.contains('ant-table-wrapper')) { if (!_target.classList.contains('ant-table-wrapper')) {
_targe = entry.target.querySelector('.ant-table-wrapper') _target = entry.target.querySelector('.ant-table-wrapper');
}
setHeight(getTableScroll({ extraHeight, target: _targe as HTMLElement }))
})
return height
} }
setHeight(getTableScroll({ extraHeight, target: _target as HTMLElement }));
});
return height;
};

View File

@ -354,3 +354,26 @@ pre {
white-space: break-spaces !important; white-space: break-spaces !important;
padding: 0 !important; padding: 0 !important;
} }
.virtuallist {
.ant-table-tbody > tr > td > div {
white-space: unset !important;
}
}
.virtuallist .ant-table-tbody > tr > td > div {
box-sizing: border-box;
white-space: nowrap;
vertical-align: middle;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
}
.virtuallist .ant-table-tbody > tr > td.ant-table-row-expand-icon-cell > div {
overflow: inherit;
}
.ant-table-bordered .virtuallist > table > .ant-table-tbody > tr > td {
border-right: 1px solid #f0f0f0;
}

View File

@ -53,7 +53,7 @@ import { SharedContext } from '@/layouts';
import useTableScrollHeight from '@/hooks/useTableScrollHeight'; import useTableScrollHeight from '@/hooks/useTableScrollHeight';
import { getCommandScript, parseCrontab } from '@/utils'; import { getCommandScript, parseCrontab } from '@/utils';
import { ColumnProps } from 'antd/lib/table'; import { ColumnProps } from 'antd/lib/table';
import { VList } from 'virtuallist-antd'; import { VList } from '../../components/vlist';
const { Text, Paragraph } = Typography; const { Text, Paragraph } = Typography;
const { Search } = Input; const { Search } = Input;
@ -339,6 +339,7 @@ const Crontab = () => {
<Tooltip title={isPc ? '运行' : ''}> <Tooltip title={isPc ? '运行' : ''}>
<a <a
onClick={(e) => { onClick={(e) => {
setReset(false);
e.stopPropagation(); e.stopPropagation();
runCron(record, index); runCron(record, index);
}} }}
@ -351,6 +352,7 @@ const Crontab = () => {
<Tooltip title={isPc ? '停止' : ''}> <Tooltip title={isPc ? '停止' : ''}>
<a <a
onClick={(e) => { onClick={(e) => {
setReset(false);
e.stopPropagation(); e.stopPropagation();
stopCron(record, index); stopCron(record, index);
}} }}
@ -362,6 +364,7 @@ const Crontab = () => {
<Tooltip title={isPc ? '日志' : ''}> <Tooltip title={isPc ? '日志' : ''}>
<a <a
onClick={(e) => { onClick={(e) => {
setReset(false);
e.stopPropagation(); e.stopPropagation();
setLogCron({ ...record, timestamp: Date.now() }); setLogCron({ ...record, timestamp: Date.now() });
}} }}
@ -405,6 +408,10 @@ const Crontab = () => {
const [moreMenuActive, setMoreMenuActive] = useState(false); const [moreMenuActive, setMoreMenuActive] = useState(false);
const tableRef = useRef<any>(); const tableRef = useRef<any>();
const tableScrollHeight = useTableScrollHeight(tableRef); const tableScrollHeight = useTableScrollHeight(tableRef);
const resetRef = useRef<boolean>(true);
const setReset = (v) => {
resetRef.current = v;
};
const goToScriptManager = (record: any) => { const goToScriptManager = (record: any) => {
const result = getCommandScript(record.command); const result = getCommandScript(record.command);
@ -424,9 +431,9 @@ const Crontab = () => {
}crons?searchValue=${searchText}&page=${page}&size=${size}&filters=${JSON.stringify( }crons?searchValue=${searchText}&page=${page}&size=${size}&filters=${JSON.stringify(
filters, filters,
)}`; )}`;
if (sorter && sorter.field) { if (sorter && sorter.column && sorter.order) {
url += `&sorter=${JSON.stringify({ url += `&sorter=${JSON.stringify({
field: sorter.field, field: sorter.column.key,
type: sorter.order === 'ascend' ? 'ASC' : 'DESC', type: sorter.order === 'ascend' ? 'ASC' : 'DESC',
})}`; })}`;
} }
@ -688,6 +695,7 @@ const Crontab = () => {
items: getMenuItems(record), items: getMenuItems(record),
onClick: ({ key, domEvent }) => { onClick: ({ key, domEvent }) => {
domEvent.stopPropagation(); domEvent.stopPropagation();
setReset(false);
action(key, record, index); action(key, record, index);
}, },
}} }}
@ -723,6 +731,7 @@ const Crontab = () => {
}; };
const onSearch = (value: string) => { const onSearch = (value: string) => {
setReset(true);
setSearchText(value.trim()); setSearchText(value.trim());
}; };
@ -750,6 +759,10 @@ const Crontab = () => {
setSelectedRowIds(selectedIds); setSelectedRowIds(selectedIds);
}; };
useEffect(() => {
setReset(false);
}, [selectedRowIds]);
const rowSelection = { const rowSelection = {
selectedRowKeys: selectedRowIds, selectedRowKeys: selectedRowIds,
onChange: onSelectChange, onChange: onSelectChange,
@ -777,6 +790,7 @@ const Crontab = () => {
}; };
const operateCrons = (operationStatus: number) => { const operateCrons = (operationStatus: number) => {
setReset(false);
Modal.confirm({ Modal.confirm({
title: `确认${OperationName[operationStatus]}`, title: `确认${OperationName[operationStatus]}`,
content: <>{OperationName[operationStatus]}</>, content: <>{OperationName[operationStatus]}</>,
@ -803,6 +817,7 @@ const Crontab = () => {
sorter: SorterResult<any> | SorterResult<any>[], sorter: SorterResult<any> | SorterResult<any>[],
) => { ) => {
const { current, pageSize } = pagination; const { current, pageSize } = pagination;
setReset(true);
setPageConf({ setPageConf({
page: current as number, page: current as number,
size: pageSize as number, size: pageSize as number,
@ -917,10 +932,22 @@ const Crontab = () => {
const tabClick = (key: string) => { const tabClick = (key: string) => {
const view = enabledCronViews.find((x) => x.id == key); const view = enabledCronViews.find((x) => x.id == key);
setSelectedRowIds([]); setSelectedRowIds([]);
setReset(true);
setPageConf({ ...pageConf, page: 1 }); setPageConf({ ...pageConf, page: 1 });
setViewConf(view ? view : null); setViewConf(view ? view : null);
}; };
const vComponents = useMemo(() => {
return VList({
height: tableScrollHeight,
reset: resetRef.current,
rowHeight: 69,
scrollTop: resetRef.current
? 0
: tableRef.current?.querySelector('.ant-table-body')?.scrollTop,
});
}, [tableScrollHeight, resetRef.current]);
return ( return (
<PageContainer <PageContainer
className="ql-container-wrapper crontab-wrapper ql-container-wrapper-has-tab" className="ql-container-wrapper crontab-wrapper ql-container-wrapper-has-tab"
@ -932,6 +959,8 @@ const Crontab = () => {
enterButton enterButton
allowClear allowClear
loading={loading} loading={loading}
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
onSearch={onSearch} onSearch={onSearch}
/>, />,
<Button key="2" type="primary" onClick={() => addCron()}> <Button key="2" type="primary" onClick={() => addCron()}>
@ -1053,6 +1082,7 @@ const Crontab = () => {
rowSelection={rowSelection} rowSelection={rowSelection}
rowClassName={getRowClassName} rowClassName={getRowClassName}
onChange={onPageChange} onChange={onPageChange}
components={vComponents}
/> />
</div> </div>
<CronLogModal <CronLogModal

View File

@ -1,4 +1,10 @@
import React, { useCallback, useRef, useState, useEffect } from 'react'; import React, {
useCallback,
useRef,
useState,
useEffect,
useMemo,
} from 'react';
import { import {
Button, Button,
message, message,
@ -33,6 +39,8 @@ import { useOutletContext } from '@umijs/max';
import { SharedContext } from '@/layouts'; import { SharedContext } from '@/layouts';
import useTableScrollHeight from '@/hooks/useTableScrollHeight'; import useTableScrollHeight from '@/hooks/useTableScrollHeight';
import Copy from '../../components/copy'; import Copy from '../../components/copy';
import { VList } from '../../components/vlist';
const { Text } = Typography; const { Text } = Typography;
const { Search } = Input; const { Search } = Input;
@ -58,50 +66,6 @@ enum OperationPath {
const type = 'DragableBodyRow'; const type = 'DragableBodyRow';
const DragableBodyRow = ({
index,
moveRow,
className,
style,
...restProps
}: any) => {
const ref = useRef();
const [{ isOver, dropClassName }, drop] = useDrop({
accept: type,
collect: (monitor) => {
const { index: dragIndex } = (monitor.getItem() as any) || {};
if (dragIndex === index) {
return {};
}
return {
isOver: monitor.isOver(),
dropClassName:
dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',
};
},
drop: (item: any) => {
moveRow(item.index, index);
},
});
const [, drag] = useDrag({
type,
item: { index },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
});
drop(drag(ref));
return (
<tr
ref={ref}
className={`${className}${isOver ? dropClassName : ''}`}
style={{ cursor: 'move', ...style }}
{...restProps}
/>
);
};
const Env = () => { const Env = () => {
const { headerStyle, isPhone, theme } = useOutletContext<SharedContext>(); const { headerStyle, isPhone, theme } = useOutletContext<SharedContext>();
const columns: any = [ const columns: any = [
@ -259,6 +223,10 @@ const Env = () => {
const [importLoading, setImportLoading] = useState(false); const [importLoading, setImportLoading] = useState(false);
const tableRef = useRef<any>(); const tableRef = useRef<any>();
const tableScrollHeight = useTableScrollHeight(tableRef, 59); const tableScrollHeight = useTableScrollHeight(tableRef, 59);
const resetRef = useRef<boolean>(true);
const setReset = (v) => {
resetRef.current = v;
};
const getEnvs = () => { const getEnvs = () => {
setLoading(true); setLoading(true);
@ -273,6 +241,7 @@ const Env = () => {
}; };
const enabledOrDisabledEnv = (record: any, index: number) => { const enabledOrDisabledEnv = (record: any, index: number) => {
setReset(false);
Modal.confirm({ Modal.confirm({
title: `确认${record.status === Status. ? '启用' : '禁用'}`, title: `确认${record.status === Status. ? '启用' : '禁用'}`,
content: ( content: (
@ -318,16 +287,19 @@ const Env = () => {
}; };
const addEnv = () => { const addEnv = () => {
setReset(false);
setEditedEnv(null as any); setEditedEnv(null as any);
setIsModalVisible(true); setIsModalVisible(true);
}; };
const editEnv = (record: any, index: number) => { const editEnv = (record: any, index: number) => {
setReset(false);
setEditedEnv(record); setEditedEnv(record);
setIsModalVisible(true); setIsModalVisible(true);
}; };
const deleteEnv = (record: any, index: number) => { const deleteEnv = (record: any, index: number) => {
setReset(false);
Modal.confirm({ Modal.confirm({
title: '确认删除', title: '确认删除',
content: ( content: (
@ -367,11 +339,72 @@ const Env = () => {
getEnvs(); getEnvs();
}; };
const components = { const vComponents = useMemo(() => {
return VList({
height: tableScrollHeight!,
reset: resetRef.current,
rowHeight: 48,
scrollTop: resetRef.current
? 0
: tableRef.current?.querySelector('.ant-table-body')?.scrollTop,
});
}, [tableScrollHeight, resetRef.current]);
const DragableBodyRow = (props: any) => {
const { index, moveRow, className, style, ...restProps } = props;
const ref = useRef();
const [{ isOver, dropClassName }, drop] = useDrop({
accept: type,
collect: (monitor) => {
const { index: dragIndex } = (monitor.getItem() as any) || {};
if (dragIndex === index) {
return {};
}
return {
isOver: monitor.isOver(),
dropClassName:
dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',
};
},
drop: (item: any) => {
moveRow(item.index, index);
},
});
const [, drag] = useDrag({
type,
item: { index },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
});
useEffect(() => {
drop(drag(ref));
}, [drag, drop]);
const components = useMemo(() => vComponents.body.row, []);
const tempProps = useMemo(() => {
return {
ref: ref,
className: `${className}${isOver ? dropClassName : ''}`,
style: { cursor: 'move', ...style },
...restProps,
};
}, [className, dropClassName, restProps, style, isOver]);
return <> {components(tempProps, ref)} </>;
};
const components = useMemo(() => {
return {
...vComponents,
body: { body: {
...vComponents.body,
row: DragableBodyRow, row: DragableBodyRow,
}, },
}; };
}, [vComponents]);
const moveRow = useCallback( const moveRow = useCallback(
(dragIndex: number, hoverIndex: number) => { (dragIndex: number, hoverIndex: number) => {
@ -399,12 +432,17 @@ const Env = () => {
setSelectedRowIds(selectedIds); setSelectedRowIds(selectedIds);
}; };
useEffect(() => {
setReset(false);
}, [selectedRowIds]);
const rowSelection = { const rowSelection = {
selectedRowKeys: selectedRowIds, selectedRowKeys: selectedRowIds,
onChange: onSelectChange, onChange: onSelectChange,
}; };
const delEnvs = () => { const delEnvs = () => {
setReset(false);
Modal.confirm({ Modal.confirm({
title: '确认删除', title: '确认删除',
content: <></>, content: <></>,
@ -426,6 +464,7 @@ const Env = () => {
}; };
const operateEnvs = (operationStatus: number) => { const operateEnvs = (operationStatus: number) => {
setReset(false);
Modal.confirm({ Modal.confirm({
title: `确认${OperationName[operationStatus]}`, title: `确认${OperationName[operationStatus]}`,
content: <>{OperationName[operationStatus]}</>, content: <>{OperationName[operationStatus]}</>,
@ -458,6 +497,7 @@ const Env = () => {
}; };
const onSearch = (value: string) => { const onSearch = (value: string) => {
setReset(true);
setSearchText(value.trim()); setSearchText(value.trim());
}; };
@ -521,6 +561,7 @@ const Env = () => {
style: headerStyle, style: headerStyle,
}} }}
> >
<div ref={tableRef}>
{selectedRowIds.length > 0 && ( {selectedRowIds.length > 0 && (
<div style={{ marginBottom: 16 }}> <div style={{ marginBottom: 16 }}>
<Button <Button
@ -566,7 +607,6 @@ const Env = () => {
)} )}
<DndProvider backend={HTML5Backend}> <DndProvider backend={HTML5Backend}>
<Table <Table
ref={tableRef}
columns={columns} columns={columns}
rowSelection={rowSelection} rowSelection={rowSelection}
pagination={false} pagination={false}
@ -584,6 +624,7 @@ const Env = () => {
}} }}
/> />
</DndProvider> </DndProvider>
</div>
<EnvModal <EnvModal
visible={isModalVisible} visible={isModalVisible}
handleCancel={handleCancel} handleCancel={handleCancel}

View File

@ -183,7 +183,7 @@ export function getTableScroll({
extraHeight, extraHeight,
target, target,
}: { extraHeight?: number; target?: HTMLElement } = {}) { }: { extraHeight?: number; target?: HTMLElement } = {}) {
if (typeof extraHeight == 'undefined') { if (typeof extraHeight === 'undefined') {
// 47 + 40 + 12 // 47 + 40 + 12
extraHeight = 99; extraHeight = 99;
} }