Compare commits

...

10 Commits

@ -37,6 +37,7 @@
text-overflow: ellipsis;
white-space: nowrap;
word-break: keep-all;
min-height: 18px;
}
:global {

@ -4,26 +4,43 @@
* Description:
* Date: 2023/9/14
*/
import React, { FunctionComponent, useEffect, useState } from "react";
import { Button, Table, Typography } from "antd";
import React, { FunctionComponent, useContext, useEffect, useRef, useState } from "react";
import { Button, Form, Input, InputNumber, Table, Typography } from "antd";
import type { FormInstance } from "antd/es/form";
import { LockOutlined } from "@ant-design/icons";
import CustomTableTitle from "@/pages/calcTable/customTableTitle";
import CalcExplainFooter from "@/pages/calcTable/calcExplainFooter";
import CaclFixedTotal from "./calcFixedTotal";
import type { ColumnType } from "antd/lib/table";
import type { PaginationData } from "rc-pagination";
import { exceptStr, paginationFun } from "@/utils/common";
import { exceptStr, paginationFun, toDecimal_n } from "@/utils/common";
import { IPage } from "@/common/types";
import styles from "@/pages/atdTable/components/index.less";
import cs from "classnames";
interface OwnProps {
}
interface EditableRowProps {
}
interface EditableCellProps {
title?: React.ReactNode;
editable?: boolean;
children?: React.ReactNode;
dataIndex?: any;
record?: any;
pattern?: number;
rowIndex?: number;
handleSave?: (type: string, record: any) => void;
}
type Props = OwnProps;
type fixedProps = boolean | "top" | "bottom";
const { Text } = Typography;
const index: FunctionComponent<Props> = (props) => {
const EditableContext = React.createContext<FormInstance<any> | null>(null);
const Index: FunctionComponent<Props> = (props) => {
const [columns, setColumns] = useState<ColumnType<any>[]>([]);
const [dataSource, setDataSource] = useState<any[]>([]);
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
@ -36,6 +53,8 @@ const index: FunctionComponent<Props> = (props) => {
const [payload, setPayload] = useState<string>("");
const [fixed, setFixed] = useState<fixedProps>(true);
const [sumRow, setSumRow] = useState<Partial<{}>>({});//总计行数据
const [form] = Form.useForm();
const editItemList = useRef<any[]>([]);
useEffect(() => {
window.parent.postMessage({ type: "init" }, "*");
@ -62,22 +81,32 @@ const index: FunctionComponent<Props> = (props) => {
setPageInfo(pageInfo);
setDataSource(dataSource);
setSelectedRowKeys(selectedRowKeys);
editItemList.current = [];
setTableScrollHeight(tableScrollHeight);
setColumns([...convertColumns(_.map(columns, o => ({ ...o, i18n: i18nRes }))), {
setColumns([...convertColumns(_.map(columns, o => ({ ...o, i18n: i18nRes })), calcDetail), {
title: i18nRes["操作"], dataIndex: "operate", fixed: "right", width: 120,
render: (__, record) => (<Button type="link" onClick={() => handleEdit(record?.id)}>{i18nRes["编辑"]}</Button>)
}]);
}
};
const convertColumns: any = (cols: any[]) => {
const convertColumns: any = (cols: any[], editable: boolean) => {
return _.map(cols, item => {
if (_.isNaN(parseInt(item.dataIndex))) {
return { ...item };
return { ...item, editable: false };
} else {
return {
...item, title: <CustomTableTitle {...item} onHandleFormulatd={handleFormulaTd}/>,
children: convertColumns(_.map(item.children, o => ({ ...o, i18n: item.i18n }))),
className: styles["td_odd"], i18n: item.i18n,
children: convertColumns(_.map(item.children, o => ({ ...o, i18n: item.i18n })), editable),
className: styles["td_odd"], i18n: item.i18n, editable: !editable,
onCell: (record: any, rowIndex: number) => ({
record,
rowIndex,
dataIndex: item.dataIndex,
title: item.title,
editable: !editable,
pattern: item.pattern,
handleSave
}),
render: (text: string) => (
<span className={styles.contentSpan}>
<span title={text} className={styles.contentTitle}>{text}</span>
@ -90,6 +119,52 @@ const index: FunctionComponent<Props> = (props) => {
}
});
};
const handleSave = (salaryItemId: string, row: any) => {
setDataSource(prevState => {
const newData = [...prevState];
const index = newData.findIndex(item => row.id === item.id);
const item = newData[index];
if (_.map(editItemList.current, t => t.id).includes(row.id)) {
editItemList.current = _.reduce(editItemList.current, (pre: any, cur: any) => {
if (cur.id === row.id) {
return [...pre, {
id: row.id, items: _.map(cur.items, h => h.salaryItemId).includes(salaryItemId) ?
_.map(cur.items, k => {
if (k.salaryItemId === salaryItemId) {
return { ...k, salaryItemId, resultValue: row[salaryItemId] };
}
return { ...k };
})
: [...cur.items, { salaryItemId, resultValue: row[salaryItemId] }]
}];
}
return [...pre, cur];
}, []);
} else {
editItemList.current.push({
id: row.id, items: [{ salaryItemId, resultValue: row[salaryItemId] }]
});
}
window.parent.postMessage(
{
type: "turn",
payload: { id: "BEATCHUPDATE", params: { resultValueList: JSON.stringify(editItemList.current) } }
},
"*"
);
newData.splice(index, 1, { ...item, ...row });
return newData;
});
};
const handleChange = (rowIndex: any, dataIndex: any, v: any, dataSource: any[]) => {
setDataSource(() => {
return _.map([...dataSource], (item, index) => {
if (index === rowIndex) item[dataIndex] = v;
return item;
});
});
};
const handleFormulaTd = (dataIndex: string) => {
window.parent.postMessage(
{
@ -138,12 +213,19 @@ const index: FunctionComponent<Props> = (props) => {
);
}
};
return (<Table
const components = {
body: {
row: EditableRow,
cell: EditableCell
}
};
return (<Form form={form} component={false}><Table
rowKey="id" size="small" bordered className={styles.tableWrapper}
dataSource={dataSource} rowSelection={rowSelection}
scroll={{ x: 1200, y: `calc(100vh - ${tableScrollHeight || (!showTotalCell ? 165 : 200)}px)` }}
columns={!isDetailTable ? columns : _.filter(columns, o => o.dataIndex !== "operate")}
footer={() => !isDetailTable ? <CalcExplainFooter i18n={i18n}/> : null}
footer={() => !isDetailTable ? <CalcExplainFooter i18n={i18n}/> : null} components={components}
pagination={!_.isNil(pageInfo) ? {
...paginationFun(pageInfo, sizeChange, onChange, i18n),
size: "default"
@ -157,7 +239,62 @@ const index: FunctionComponent<Props> = (props) => {
</Table.Summary.Row>
</Table.Summary>
)}
/>);
/></Form>);
};
export default index;
export default Index;
const EditableRow: React.FC<EditableRowProps> = (props) => {
const [form] = Form.useForm();
return (
<Form form={form} component={false}>
<EditableContext.Provider value={form}>
<tr {...props} />
</EditableContext.Provider>
</Form>
);
};
const EditableCell: React.FC<EditableCellProps> = (props) => {
const { title, editable, children, dataIndex, record, handleSave, rowIndex, ...restProps } = props;
const [editing, setEditing] = useState(false);
const inputRef = useRef<any>(null);
const form = useContext(EditableContext)!;
useEffect(() => {
if (editing) {
inputRef.current!.focus();
}
}, [editing]);
const toggleEdit = () => {
setEditing(!editing);
form.setFieldsValue({ [dataIndex]: record[dataIndex] });
};
const save = _.debounce(async () => {
try {
let values = await form.validateFields();
if (record[`${_.keys(values)[0]}_type`] === "number") {
values = {
...values,
[_.keys(values)[0]]: !_.isNil(_.get(values, _.keys(values)[0])) ? toDecimal_n(_.get(values, _.keys(values)[0]), restProps?.pattern) : toDecimal_n(0, restProps?.pattern)
};
}
handleSave?.(_.keys(values)[0], { ...record, ...values });
} catch (errInfo) {
console.log("Save failed:", errInfo);
}
}, 200);
let childNode = children;
if (editable) {
childNode = editing ? (
<Form.Item style={{ margin: 0 }} name={dataIndex}>
{record[`${dataIndex}_type`] === "number" ?
<InputNumber ref={inputRef} precision={restProps?.pattern} onChange={save} onBlur={toggleEdit}
onPressEnter={toggleEdit}/> :
<Input ref={inputRef} onPressEnter={toggleEdit} onBlur={toggleEdit} onChange={save}/>}
</Form.Item>
) : (
// record[dataIndex]
<div className={cs({ [styles["editable-cell"]]: true })} onClick={toggleEdit}> {children} </div>
);
}
return <td {...restProps}>{childNode}</td>;
};

Loading…
Cancel
Save