|
|
|
@ -4,26 +4,39 @@
|
|
|
|
|
* Description:
|
|
|
|
|
* Date: 2023/9/14
|
|
|
|
|
*/
|
|
|
|
|
import React, { FunctionComponent, useEffect, useState } from "react";
|
|
|
|
|
import type { MenuProps } from "antd";
|
|
|
|
|
import { Button, Dropdown, Space, Table, Tooltip, Typography } from "antd";
|
|
|
|
|
import React, { FunctionComponent, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
|
|
|
import { Button, Dropdown, Form, Input, InputNumber, MenuProps, Space, Table, Tooltip, Typography } from "antd";
|
|
|
|
|
import { DeleteOutlined, LockOutlined, QuestionCircleOutlined, SettingOutlined, UnlockOutlined } from "@ant-design/icons";
|
|
|
|
|
import type { FormInstance } from "antd/es/form";
|
|
|
|
|
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";
|
|
|
|
|
|
|
|
|
|
interface OwnProps {}
|
|
|
|
|
|
|
|
|
|
interface EditableRowProps {}
|
|
|
|
|
|
|
|
|
|
interface EditableCellProps {
|
|
|
|
|
editCell?: any;
|
|
|
|
|
children?: React.ReactNode;
|
|
|
|
|
record?: any;
|
|
|
|
|
pattern?: number;
|
|
|
|
|
rowIndex?: number;
|
|
|
|
|
dataIndex?: any;
|
|
|
|
|
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,7 +49,10 @@ const index: FunctionComponent<Props> = (props) => {
|
|
|
|
|
const [tableScrollHeight, setTableScrollHeight] = useState<Number>(0);
|
|
|
|
|
const [payload, setPayload] = useState<string>("");
|
|
|
|
|
const [fixed, setFixed] = useState<fixedProps>(true);
|
|
|
|
|
const [optWidth, setOptWidth] = useState<number>(120); //操作列宽度
|
|
|
|
|
const [sumRow, setSumRow] = useState<Partial<{}>>({}); //总计行数据
|
|
|
|
|
const [editCell, setEditCell] = useState<any>({}); //编辑行key
|
|
|
|
|
const [form] = Form.useForm();
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
window.parent.postMessage({ type: "init" }, "*");
|
|
|
|
@ -74,51 +90,11 @@ const index: FunctionComponent<Props> = (props) => {
|
|
|
|
|
setSumRow(sumRow);
|
|
|
|
|
setPageInfo(pageInfo);
|
|
|
|
|
setDataSource(dataSource);
|
|
|
|
|
setOptWidth(optWidth);
|
|
|
|
|
setSelectedRowKeys([...selectedRowKeys, ...rowKeys]);
|
|
|
|
|
setTableScrollHeight(tableScrollHeight);
|
|
|
|
|
setColumns([
|
|
|
|
|
...convertColumns(_.map(columns, (o) => ({ ...o, i18n: i18nRes }))),
|
|
|
|
|
{
|
|
|
|
|
title: i18nRes["操作"],
|
|
|
|
|
dataIndex: "operate",
|
|
|
|
|
fixed: "right",
|
|
|
|
|
width: optWidth || 120,
|
|
|
|
|
render: (__, record) => (
|
|
|
|
|
<Space>
|
|
|
|
|
<Button type="link" onClick={() => handleEdit(record?.id, showSee)}>
|
|
|
|
|
{showSee ? i18nRes["查看"] : i18nRes["编辑"]}
|
|
|
|
|
</Button>
|
|
|
|
|
{optWidth && (
|
|
|
|
|
<>
|
|
|
|
|
<Button
|
|
|
|
|
type="link"
|
|
|
|
|
onClick={() =>
|
|
|
|
|
handleLockEmp({
|
|
|
|
|
lockStatus: "LOCK",
|
|
|
|
|
acctEmpIds: [record?.id]
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
{i18nRes["锁定"]}
|
|
|
|
|
</Button>
|
|
|
|
|
<Button
|
|
|
|
|
type="link"
|
|
|
|
|
onClick={() =>
|
|
|
|
|
handleLockEmp({
|
|
|
|
|
lockStatus: "UNLOCK",
|
|
|
|
|
acctEmpIds: [record?.id]
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
{i18nRes["解锁"]}
|
|
|
|
|
</Button>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
{record?.lockTime && <Text>{record?.lockTime}</Text>}
|
|
|
|
|
</Space>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
]);
|
|
|
|
|
setColumns(_.map(columns, (o) => ({ ...o, i18n: i18nRes })));
|
|
|
|
|
setEditCell({});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const convertColumns: any = (cols: any[]) => {
|
|
|
|
@ -132,11 +108,21 @@ const index: FunctionComponent<Props> = (props) => {
|
|
|
|
|
children: convertColumns(_.map(item.children, (o) => ({ ...o, i18n: item.i18n }))),
|
|
|
|
|
className: styles["td_odd"],
|
|
|
|
|
i18n: item.i18n,
|
|
|
|
|
onCell: (record: any) => ({
|
|
|
|
|
onCell: (record: any, rowIndex: number) => ({
|
|
|
|
|
className: !_.isEmpty(record[`${item.dataIndex}_feedback`]) && styles["feedbackBg"],
|
|
|
|
|
editCell,
|
|
|
|
|
record,
|
|
|
|
|
rowIndex,
|
|
|
|
|
pattern: item.pattern,
|
|
|
|
|
dataIndex: item.dataIndex,
|
|
|
|
|
onContextMenu: (e: any) => {
|
|
|
|
|
(!item.calcDetail || item.rightClickType) && e.preventDefault();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onDoubleClick: (e: any) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
!item.calcDetail || item.rightClickType ? setEditCell({ dataIndex: item?.dataIndex, rowIndex }) : null;
|
|
|
|
|
},
|
|
|
|
|
handleSave
|
|
|
|
|
}),
|
|
|
|
|
render: (text: string, record: any) => {
|
|
|
|
|
let items: MenuProps["items"] = !item.calcDetail
|
|
|
|
@ -215,6 +201,10 @@ const index: FunctionComponent<Props> = (props) => {
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
const handleSave = (salaryItemId: string, row: any) => {
|
|
|
|
|
const params = { salaryItemId, idList: [row?.id], value: row[salaryItemId] };
|
|
|
|
|
window.parent.postMessage({ type: "turn", payload: { id: "EDITCELL", params } }, "*");
|
|
|
|
|
};
|
|
|
|
|
const handleFormulaTd = (dataIndex: string) => {
|
|
|
|
|
window.parent.postMessage({ type: "turn", payload: { id: "FORMULA", params: { dataIndex } } }, "*");
|
|
|
|
|
};
|
|
|
|
@ -240,7 +230,7 @@ const index: FunctionComponent<Props> = (props) => {
|
|
|
|
|
};
|
|
|
|
|
const rowSelection = {
|
|
|
|
|
columnWidth: 50,
|
|
|
|
|
columnTitle: isDetailTable ? "序号" : "",
|
|
|
|
|
columnTitle: isDetailTable ? "序号" : "",
|
|
|
|
|
renderCell: (value: boolean, record: any, index: number, originNode: React.ReactNode) => (isDetailTable ? <span>{index + 1}</span> : originNode),
|
|
|
|
|
selectedRowKeys,
|
|
|
|
|
preserveSelectedRowKeys: true,
|
|
|
|
@ -255,44 +245,149 @@ const index: FunctionComponent<Props> = (props) => {
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
return (
|
|
|
|
|
<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 || showSee ? columns : _.filter(columns, (o) => o.dataIndex !== "operate")}
|
|
|
|
|
footer={() => (!isDetailTable ? <CalcExplainFooter i18n={i18n} /> : null)}
|
|
|
|
|
pagination={
|
|
|
|
|
!_.isNil(pageInfo)
|
|
|
|
|
? {
|
|
|
|
|
...paginationFun(pageInfo, sizeChange, onChange, i18n),
|
|
|
|
|
size: "default"
|
|
|
|
|
}
|
|
|
|
|
: false
|
|
|
|
|
}
|
|
|
|
|
summary={() =>
|
|
|
|
|
!showTotalCell ? (
|
|
|
|
|
<></>
|
|
|
|
|
) : (
|
|
|
|
|
<Table.Summary fixed={fixed}>
|
|
|
|
|
<Table.Summary.Row>
|
|
|
|
|
<Table.Summary.Cell index={0} align="center">
|
|
|
|
|
<Text type="danger">{i18n["总计"]}</Text>
|
|
|
|
|
</Table.Summary.Cell>
|
|
|
|
|
<CaclFixedTotal columns={columns} dataSourceUrl={sumRowlistUrl} payload={payload} sumRow={sumRow} />
|
|
|
|
|
</Table.Summary.Row>
|
|
|
|
|
</Table.Summary>
|
|
|
|
|
const cols = useMemo(() => {
|
|
|
|
|
return [
|
|
|
|
|
...convertColumns(columns),
|
|
|
|
|
{
|
|
|
|
|
title: i18n["操作"],
|
|
|
|
|
dataIndex: "operate",
|
|
|
|
|
fixed: "right",
|
|
|
|
|
width: optWidth || 120,
|
|
|
|
|
render: (__: any, record: any) => (
|
|
|
|
|
<Space>
|
|
|
|
|
<Button type="link" onClick={() => handleEdit(record?.id, showSee)}>
|
|
|
|
|
{showSee ? i18n["查看"] : i18n["编辑"]}
|
|
|
|
|
</Button>
|
|
|
|
|
{optWidth && (
|
|
|
|
|
<>
|
|
|
|
|
<Button
|
|
|
|
|
type="link"
|
|
|
|
|
onClick={() =>
|
|
|
|
|
handleLockEmp({
|
|
|
|
|
lockStatus: "LOCK",
|
|
|
|
|
acctEmpIds: [record?.id]
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
{i18n["锁定"]}
|
|
|
|
|
</Button>
|
|
|
|
|
<Button
|
|
|
|
|
type="link"
|
|
|
|
|
onClick={() =>
|
|
|
|
|
handleLockEmp({
|
|
|
|
|
lockStatus: "UNLOCK",
|
|
|
|
|
acctEmpIds: [record?.id]
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
{i18n["解锁"]}
|
|
|
|
|
</Button>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
{record?.lockTime && <Text>{record?.lockTime}</Text>}
|
|
|
|
|
</Space>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
];
|
|
|
|
|
}, [columns, editCell, i18n]);
|
|
|
|
|
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}
|
|
|
|
|
components={components}
|
|
|
|
|
scroll={{
|
|
|
|
|
x: 1200,
|
|
|
|
|
y: `calc(100vh - ${tableScrollHeight || (!showTotalCell ? 165 : 200)}px)`
|
|
|
|
|
}}
|
|
|
|
|
columns={!isDetailTable || showSee ? cols : _.filter(cols, (o) => o.dataIndex !== "operate")}
|
|
|
|
|
footer={() => (!isDetailTable ? <CalcExplainFooter i18n={i18n} /> : null)}
|
|
|
|
|
pagination={
|
|
|
|
|
!_.isNil(pageInfo)
|
|
|
|
|
? {
|
|
|
|
|
...paginationFun(pageInfo, sizeChange, onChange, i18n),
|
|
|
|
|
size: "default"
|
|
|
|
|
}
|
|
|
|
|
: false
|
|
|
|
|
}
|
|
|
|
|
summary={() =>
|
|
|
|
|
!showTotalCell ? (
|
|
|
|
|
<></>
|
|
|
|
|
) : (
|
|
|
|
|
<Table.Summary fixed={fixed}>
|
|
|
|
|
<Table.Summary.Row>
|
|
|
|
|
<Table.Summary.Cell index={0} align="center">
|
|
|
|
|
<Text type="danger">{i18n["总计"]}</Text>
|
|
|
|
|
</Table.Summary.Cell>
|
|
|
|
|
<CaclFixedTotal columns={cols} dataSourceUrl={sumRowlistUrl} payload={payload} sumRow={sumRow} />
|
|
|
|
|
</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 { children, editCell, record, dataIndex, rowIndex, handleSave, ...restProps } = props;
|
|
|
|
|
const form = useContext(EditableContext)!;
|
|
|
|
|
const inputRef = useRef<any>(null);
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (dataIndex && editCell && editCell.dataIndex === dataIndex && editCell.rowIndex === rowIndex) {
|
|
|
|
|
toggleEdit();
|
|
|
|
|
inputRef.current!.focus();
|
|
|
|
|
}
|
|
|
|
|
}, [editCell, dataIndex, rowIndex]);
|
|
|
|
|
const toggleEdit = () => {
|
|
|
|
|
form.setFieldsValue({ [dataIndex]: record[dataIndex] });
|
|
|
|
|
};
|
|
|
|
|
const onSave = _.debounce(async (e) => {
|
|
|
|
|
try {
|
|
|
|
|
let values = await form.validateFields();
|
|
|
|
|
if (record[`${_.keys(values)[0]}_type`] === "number") {
|
|
|
|
|
values = {
|
|
|
|
|
...values,
|
|
|
|
|
[_.keys(values)[0]]: !!_.get(values, _.keys(values)[0]) ? toDecimal_n(_.get(values, _.keys(values)[0]), restProps?.pattern) : ""
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
handleSave?.(_.keys(values)[0], { ...record, ...values });
|
|
|
|
|
} catch (errInfo) {
|
|
|
|
|
console.log("Save failed:", errInfo);
|
|
|
|
|
}
|
|
|
|
|
}, 200);
|
|
|
|
|
let childNode =
|
|
|
|
|
dataIndex && editCell && editCell.dataIndex === dataIndex && editCell.rowIndex === rowIndex ? (
|
|
|
|
|
<Form.Item style={{ margin: 0 }} name={dataIndex}>
|
|
|
|
|
{record[`${dataIndex}_type`] === "number" ? (
|
|
|
|
|
<InputNumber ref={inputRef} onPressEnter={onSave} onBlur={onSave} precision={restProps?.pattern} />
|
|
|
|
|
) : (
|
|
|
|
|
<Input value={record[dataIndex]} onPressEnter={onSave} onBlur={onSave} ref={inputRef} />
|
|
|
|
|
)}
|
|
|
|
|
</Form.Item>
|
|
|
|
|
) : (
|
|
|
|
|
<>{children}</>
|
|
|
|
|
);
|
|
|
|
|
return <td {...restProps}>{childNode}</td>;
|
|
|
|
|
};
|
|
|
|
|