泛微薪资核算iframe表格

feature/低版本火狐浏览器
黎永顺 2 years ago
parent c219b1a5fb
commit f7237c2db6

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Binary file not shown.

@ -16,7 +16,7 @@ class CalculateService extends BasicService {
departmentIds: departmentIds ? departmentIds.split(",") : undefined,
positionIds: positionIds ? positionIds.split(",") : undefined,
subcompanyIds: subcompanyIds ? subcompanyIds.split(",") : undefined,
statuses: statuses ? statuses.split(",") : [],
statuses: statuses ? statuses.split(",") : []
};
for (let key in queryParams) {
if (queryParams[key] === "" || queryParams[key] === "0") {
@ -72,6 +72,10 @@ class CalculateService extends BasicService {
}
return this.post(`/api/bs/hrmsalary/salaryacct/acctresult/sum`, queryParams);
};
//合计行
getAcctResultsum = async (params: any) => {
return this.post(`/api/bs/hrmsalary/salaryacct/acctresult/sum`, params);
};
}
const calculateService = new CalculateService();

@ -22,7 +22,8 @@ export default ({ children, style = {} }: any) => {
background: (
window.location.hash.indexOf("atdTable") !== -1 ||
window.location.hash.indexOf("standingbookTable") !== -1 ||
window.location.hash.indexOf("previewTable") !== -1
window.location.hash.indexOf("previewTable") !== -1 ||
window.location.hash.indexOf("calcTable") !== -1
) ? "#f6f6f6" : "#FFF",
...style
}}

@ -12,6 +12,7 @@ module.exports = {
"/rankMapTable.*": "blank",
"/reportTable.*": "blank",
"/commonTable.*": "blank",
"/calcTable.*": "blank",
"/payrollFilesTable.*": "blank",
"/employeeDeclareTable.*": "blank",
"/manage.*": "manage",

@ -4,17 +4,17 @@
*
*/
import * as React from 'react';
import { createFromIconfontCN } from '@ant-design/icons';
import { Util } from '@/utils';
import * as React from "react";
import { createFromIconfontCN } from "@ant-design/icons";
import { Util } from "@/utils";
export declare type IconType = React.ReactNode | string;
const hrmSalaryUrl = "/spa/hrmSalary/hrmSalaryCalculateDetail/";
const Icon = createFromIconfontCN({
scriptUrl: [
// @ts-ignore
`${Util.getPublicPath()}css/iconfont/iconfont.js`,
],
`${process.env.NODE_ENV === "dev" ? Util.getPublicPath() : hrmSalaryUrl}css/iconfont/iconfont.js`
]
});
/**
@ -25,18 +25,18 @@ export const buildIcon: (
type: string,
icon: IconType,
style?: React.CSSProperties,
className?: string,
className?: string
) => React.ReactNode | null = function (
type,
icon,
style = {},
className = '',
) {
className = ""
) {
let comp;
switch (type) {
case 'IMAGE':
case "IMAGE":
comp =
typeof icon === 'string' ? (
typeof icon === "string" ? (
<img
src={icon}
className={className}
@ -48,13 +48,13 @@ export const buildIcon: (
break;
default:
comp =
typeof icon === 'string' ? (
<Icon type={icon} style={style} className={className} />
typeof icon === "string" ? (
<Icon type={icon} style={style} className={className}/>
) : (
icon
);
}
return comp;
};
};
export default Icon;

@ -84,6 +84,75 @@
color: rgb(217, 0, 27)
}
.expand-th:hover {
.toogle-lock-tool {
width: 30%;
}
}
th.td_odd {
background: #fffaf0 !important;
}
.expand-th {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
.title-text {
width: 90%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1 1;
cursor: pointer;
}
.toogle-lock-tool {
display: flex;
width: 0;
overflow: hidden;
height: 100%;
justify-content: center;
align-items: center;
& > :first-child {
margin-right: 4px;
}
:global {
.anticon {
color: #5d9cec;
cursor: pointer;
font-size: 14px;
}
}
}
}
.explain-icon-area {
display: flex;
justify-content: flex-start;
align-items: center;
.icon-item {
display: flex;
align-items: center;
margin-right: 12px;
color: #5d9cec;
font-size: 12px;
:global {
.anticon {
font-size: 12px;
margin-right: 4px;
}
}
}
}
:global {
.ant-btn-link, .ant-dropdown-trigger {
padding: 0;

@ -0,0 +1,36 @@
import React, { FunctionComponent } from "react";
import Icon from "@/lib/CustomIcon";
import { LockOutlined, UnlockOutlined } from "@ant-design/icons";
import styles from "@/pages/atdTable/components/index.less";
interface OwnProps {
i18n: any;
}
type Props = OwnProps;
const CalcExplainFooter: FunctionComponent<Props> = (props) => {
const { i18n } = props;
return (
<div className={styles["explain-icon-area"]}>
<div className={styles["icon-item"]}>
<Icon type="icon-piliangsuoding"/>
<span>{i18n["批量锁定"]}</span>
</div>
<div className={styles["icon-item"]}>
<Icon type="icon-piliangjiesuo"/>
<span>{i18n["批量解锁"]}</span>
</div>
<div className={styles["icon-item"]}>
<LockOutlined/>
<span>{i18n["当前状态锁定,点击解锁"]}</span>
</div>
<div className={styles["icon-item"]}>
<UnlockOutlined/>
<span>{i18n["当前状态未锁定,点击锁定"]}</span>
</div>
</div>
);
};
export default CalcExplainFooter;

@ -0,0 +1,63 @@
/*
* Author:
* name: -
* Description:
* Date: 2023/9/18
*/
import React, { FunctionComponent, useCallback, useEffect, useMemo, useState } from "react";
import { Spin, Table, Typography } from "antd";
import { ColumnType } from "antd/lib/table";
import API from "@/api";
const { Text } = Typography;
interface OwnProps {
columns: ColumnType<any>[];
dataSourceUrl: string;
payload: any;
}
type Props = OwnProps;
const calcFixedTotal: FunctionComponent<Props> = (props) => {
const [sumRow, setSumRow] = useState<Partial<{}>>({});//薪资核算总计行数据
const [loading, setLoading] = useState<boolean>(false);
const flattenFn = (source: ColumnType<any>[]) => {
let res: ColumnType<any>[] = [];
source.forEach((el: any) => {
_.isEmpty(el.children) && res.push(el);
el.children && res.push(...flattenFn(el.children));
});
return res;
};
const columns = useMemo(() => {
return !_.isEmpty(props.columns) ? flattenFn(props.columns) : [];
}, [props.columns]);
const dataSourceUrl = useCallback((payload) => {
return API.CalculateService.getAcctResultsum(payload);
}, [props.dataSourceUrl]);
useEffect(() => {
if (!_.isEmpty(props.payload)) {
setLoading(true);
dataSourceUrl(props.payload).then(({ data }) => {
setLoading(false);
const { data: result, status } = data;
if (status) setSumRow(result.sumRow || {});
});
}
}, [props.payload]);
return (<>
{
_.map(columns, (item: any, index) => {
return <Table.Summary.Cell index={index + 1} key={index + 1}>
{
loading ? <Spin spinning={loading} size="small"></Spin> :
<Text type="danger">{sumRow[item.dataIndex] || "-"}</Text>
}
</Table.Summary.Cell>;
})
}
</>);
};
export default calcFixedTotal;

@ -0,0 +1,51 @@
/*
* Author:
* name:
* Description:
* Date: 2023/9/15
*/
import React, { FunctionComponent } from "react";
import classnames from "classnames";
import Icon from "@/lib/CustomIcon";
import styles from "@/pages/atdTable/components/index.less";
interface OwnProps {
dataIndex?: string;
title?: string;
lockStatus?: string;
onHandleFormulatd?: any;
i18n?: any;
}
type Props = OwnProps;
const customTableTitle: FunctionComponent<Props> = (props) => {
const { dataIndex, title, lockStatus, onHandleFormulatd, i18n = {} } = props;
const handleToggleSalaryItemVal = (salaryItemId: string, type: string) => {
window.parent.postMessage(
{
type: "turn",
payload: { id: "LOCKING", params: { lockType: type, salaryItemId } }
},
"*"
);
};
return (
// th-width-lock
<div className={classnames(styles["expand-th"])}>
<div className={styles["title-text"]} title={title} onClick={() => onHandleFormulatd(dataIndex)}>{title}</div>
{
!!lockStatus &&
<div className={styles["toogle-lock-tool"]}>
<Icon type="icon-piliangsuoding" title={i18n["点击锁定所有解锁的项目值"]}
onClick={() => handleToggleSalaryItemVal(dataIndex as string, "LOCK")}/>
<Icon type="icon-piliangjiesuo" title={i18n["点击解锁所有锁定的项目值"]}
onClick={() => handleToggleSalaryItemVal(dataIndex as string, "UNLOCK")}/>
</div>
}
</div>
);
};
export default customTableTitle;

@ -0,0 +1,150 @@
/*
* Author:
* name: -
* Description:
* Date: 2023/9/14
*/
import React, { FunctionComponent, useEffect, useState } from "react";
import { Button, Table, Typography } from "antd";
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 { IPage } from "@/common/types";
import styles from "@/pages/atdTable/components/index.less";
interface OwnProps {
}
type Props = OwnProps;
const { Text } = Typography;
const index: FunctionComponent<Props> = (props) => {
const [columns, setColumns] = useState<ColumnType<any>[]>([]);
const [dataSource, setDataSource] = useState<any[]>([]);
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const [pageInfo, setPageInfo] = useState<Partial<PaginationData>>({});
const [i18n, setI18n] = useState<any>({});
const [showTotalCell, setShowTotalCell] = useState<boolean>(false);
const [sumRowlistUrl, setSumRowlistUrl] = useState<string>("");
const [payload, setPayload] = useState<string>("");
useEffect(() => {
window.parent.postMessage({ type: "init" }, "*");
window.addEventListener("message", receiveMessageFromIndex, false);
return () => {
window.removeEventListener("message", receiveMessageFromIndex, false);
};
}, []);
const receiveMessageFromIndex = (event: any) => {
const data: any = exceptStr(event.data);
if (!_.isEmpty(data)) {
const {
columns, dataSource, pageInfo, selectedRowKeys, i18n: i18nRes = {},
showTotalCell = false, sumRowlistUrl = "", payload = {}
} = data;
setSumRowlistUrl(sumRowlistUrl);
setShowTotalCell(showTotalCell);
setI18n(i18nRes);
setPayload(payload);
setPageInfo(pageInfo);
setDataSource(dataSource);
setSelectedRowKeys(selectedRowKeys);
setColumns([...convertColumns(_.map(columns, o => ({ ...o, i18n: i18nRes }))), {
title: i18nRes["操作"], dataIndex: "operate", fixed: "right", width: 120,
render: (__, record) => (<Button type="link" onClick={() => handleEdit(record?.id)}>{i18nRes["编辑"]}</Button>)
}]);
}
};
const convertColumns: any = (cols: any[]) => {
return _.map(cols, item => {
if (_.isNaN(parseInt(item.dataIndex))) {
return { ...item };
} 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,
render: (text: string) => (
<span className={styles.contentSpan}>
<span title={text} className={styles.contentTitle}>{text}</span>
{
item.lockStatus === "LOCK" ? <LockOutlined title="锁定的项目值"/> : null
}
</span>
)
};
}
});
};
const handleFormulaTd = (dataIndex: string) => {
window.parent.postMessage(
{
type: "turn",
payload: { id: "FORMULA", params: { dataIndex } }
},
"*"
);
};
const handleEdit = (id: string) => {
window.parent.postMessage(
{
type: "turn",
payload: { id: "EDIT", params: { id } }
},
"*"
);
};
const sizeChange = (pageobj: IPage) => {
};
const onChange = (pageobj: IPage) => {
setPageInfo(() => {
window.parent.postMessage(
{
type: "turn",
payload: { id: "PAGEINFO", params: { ...pageInfo, ...pageobj } }
},
"*"
);
return { ...pageInfo, ...pageobj };
});
};
const rowSelection = {
columnWidth: 60,
selectedRowKeys: selectedRowKeys,
onChange: (selectedRowKeys: React.Key[]) => {
setSelectedRowKeys(selectedRowKeys);
window.parent.postMessage(
{
type: "turn",
payload: { id: "CHECKBOX", params: { selectedRowKeys } }
},
"*"
);
}
};
return (<Table
rowKey="id" size="small" bordered className={styles.tableWrapper}
columns={columns} dataSource={dataSource} rowSelection={rowSelection}
scroll={{ x: 1200, y: `calc(100vh - ${!showTotalCell ? 165 : 200}px)` }}
footer={() => <CalcExplainFooter i18n={i18n}/>}
pagination={{
...paginationFun(pageInfo, sizeChange, onChange, i18n),
size: "default"
}}
summary={() => (
!showTotalCell ? <></> :
<Table.Summary 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}/>
</Table.Summary.Row>
</Table.Summary>
)}
/>);
};
export default index;
Loading…
Cancel
Save