Compare commits

...

15 Commits

Author SHA1 Message Date
liys f297b0abdc Merge branch 'feature/业务线管理' into release/2.19.1.2503.01-业务线个税
# Conflicts:
#	src/pages/calcTable/customTableTitle.tsx
2026-01-04 10:51:34 +08:00
lys 0e65d086dc feature/业务线管理 2025-12-04 15:30:21 +08:00
lys ca12e057b9 Merge branch 'master' into feature/业务线管理 2025-12-04 15:21:18 +08:00
lys fd0a3f2cb2 feature/业务线管理 2025-10-22 16:45:22 +08:00
lys 23c659f04b feature/业务线管理 2025-10-20 10:45:39 +08:00
lys 88a419491a feature/业务线管理 2025-10-15 17:45:04 +08:00
lys 62708e104a feature/业务线管理 2025-07-04 14:59:32 +08:00
lys b200c940e1 Merge branch 'master' into feature/业务线管理 2025-07-03 13:44:20 +08:00
lys b361ad6ce5 Merge branch 'master' into feature/业务线管理 2025-06-19 10:09:21 +08:00
lys d4e797ecd1 Merge branch 'master' into feature/业务线管理 2025-06-19 10:06:14 +08:00
lys 2892f4c6ee feature/业务线管理 2025-06-19 10:04:34 +08:00
lys c3013e2586 Merge branch 'master' into feature/业务线管理 2025-06-19 09:19:51 +08:00
lys e2eb2f97a9 feature/业务线管理 2025-06-19 09:10:07 +08:00
lys 0f9d4e833c Merge branch 'master' into feature/业务线管理
# Conflicts:
#	src/pages/unitTable/renderColsOpts.tsx
2025-06-12 13:51:32 +08:00
lys ed3e74621a feature/业务线管理 2025-04-25 09:04:51 +08:00
4 changed files with 80 additions and 266 deletions

View File

@ -1,136 +0,0 @@
.pbmc_body {
height: calc(100% - 50px);
background: #f6f6f6;
overflow: auto;
font-size: 12px;
.weapp-salary-payroll-mobile-preview {
width: 100%;
height: 100%;
overflow-y: auto;
.bill-container {
background: #f6f6f6;
.space {
width: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
margin-bottom: 16px;
.ant-btn {
margin-right: 16px;
}
}
.bill-info-header {
padding-top: 16px;
.title {
padding: 0 16px;
font-size: 19px;
font-weight: 700;
margin-bottom: 12px;
text-align: center;
}
.time {
padding: 0 16px;
font-size: 12px;
color: #999;
}
.img {
margin-top: 20px;
width: 100%;
img {
width: 100%;
}
}
}
.top {
padding-bottom: 0;
}
.footer {
padding-top: 8px;
}
.corporate-culture-text {
text-align: left;
color: #111;
padding: 8px 16px;
white-space: pre-wrap;
word-break: break-all;
}
.salary-detail-table-container {
padding-top: 8px;
.salary-group {
border-top: 1px solid #f2f2f2;
margin-bottom: 16px;
.group-title {
background: #fff;
display: flex;
align-items: center;
min-height: 45px;
padding: 0 16px;
border-bottom: 1px solid #f2f2f2;
font-weight: bolder;
font-size: 14px;
}
.group-list {
.list-item {
display: flex;
min-height: 45px;
border-bottom: 1px solid #f2f2f2;
width: 100%;
background: #fff;
.item-name {
padding: 8px 16px;
width: 50%;
display: flex;
align-items: center;
background: #fbfbfb;
border-right: 1px solid #f2f2f2;
flex-shrink: 0;
}
.item-count {
display: flex;
align-items: center;
padding: 16px;
white-space: pre-wrap;
word-break: break-all;
}
}
}
}
}
}
}
}
.pbmc_footer {
position: relative;
height: 50px;
.pbmcf_indicator {
position: absolute;
bottom: 16px;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
width: 110px;
height: 4px;
background-color: #ebebeb;
border-radius: 2px;
}
}

View File

@ -1,119 +0,0 @@
import React, { useCallback, useEffect, useMemo, useState } from "react";
import styles from "./index.less";
import { Util } from "@/utils";
import cs from "classnames";
import API from "@/api";
interface OwnProps {}
type Props = OwnProps;
const MPayroll: React.FC<Props> = (props) => {
const [mySalaryBillData, setMySalaryBillData] = useState<any>({});
useEffect(() => {
getMySalaryBill();
return () => {};
}, []);
const getMySalaryBill = useCallback(() => {
API.CalculateService.getMySalaryBill(Util.getUrlData("salaryInfoId")).then(({ data: res }) => {
const { data, status } = res || {};
if (status) setMySalaryBillData(data);
});
}, []);
const dealTemplate = (itemTypeList: any, type: string) => {
let cloneItemTypeList = _.cloneDeep(itemTypeList);
let showData: any = [],
onlyOneGrup = false;
cloneItemTypeList.forEach((group: any) => {
const { items, groupName, groupId } = group;
if (items.length !== 0) {
items.forEach((item: any) => {
item.salaryItemValue = !_.isNil(item.salaryItemValue) ? item.salaryItemValue : "";
});
if (items.length % 2 && type === "pc") items.push({});
showData.push({ groupId, groupName, items });
}
});
if (cloneItemTypeList.length === 1) {
onlyOneGrup = true;
cloneItemTypeList[0].name = "";
}
return { onlyOneGrup, showData };
};
const salaryTemplate = useMemo(() => {
return !_.isEmpty(mySalaryBillData) ? mySalaryBillData?.salaryTemplate : {};
}, [mySalaryBillData]);
const itemTypeList = useMemo(() => {
return !_.isEmpty(mySalaryBillData) ? [mySalaryBillData?.employeeInformation, ...mySalaryBillData?.salaryGroups] : [];
}, [mySalaryBillData]);
const payrollData: any = useMemo(() => {
return !_.isEmpty(itemTypeList)
? dealTemplate(
_.filter(itemTypeList, (o) => !!o),
"mobile"
)
: {};
}, [mySalaryBillData, itemTypeList]);
console.log(payrollData);
return (
<>
<div className={styles.pbmc_body}>
<div className={styles["weapp-salary-payroll-mobile-preview"]}>
<div className={styles["bill-container"]}>
<div className={styles["bill-info-header"]}>
<div className={styles["title"]}>{salaryTemplate?.theme || ""}</div>
</div>
{!payrollData?.onlyOneGrup && salaryTemplate?.textContentPosition == 1 && salaryTemplate.textContent && (
<div className={cs(styles["corporate-culture-text"], styles["top"])} title={salaryTemplate.textContent} dangerouslySetInnerHTML={{ __html: salaryTemplate.textContent }} />
)}
<div className={styles["salary-detail-table-container"]}>
{!_.isEmpty(payrollData?.showData) &&
payrollData?.showData.map((groupItem: any, index: number) => {
if (!groupItem) return null;
const { groupId, groupName, items = [] } = groupItem;
return (
<div className={styles["salary-group"]} key={groupId || index}>
{groupName ? <div className={styles["group-title"]}>{groupName}</div> : null}
<div className={styles["group-list"]}>
{payrollData?.onlyOneGrup && salaryTemplate?.textContentPosition == "1" && salaryTemplate.textContent && (
<div className={cs(styles["list-item"], styles["top"])}>
<div></div>
<div>{salaryTemplate.textContent}</div>
</div>
)}
{items.map((templatItem: any, index: number) => {
const { salaryItemValue, name, salaryItemShowName } = templatItem || {};
return (
<div className={styles["list-item"]} key={index}>
<div className={styles["item-name"]} title={salaryItemShowName || name}>
<span>{salaryItemShowName || name || ""}</span>
</div>
<div className={styles["item-count"]}>{salaryItemValue}</div>
</div>
);
})}
{payrollData?.onlyOneGrup && salaryTemplate?.textContentPosition == "2" && salaryTemplate.textContent && (
<div className={styles["list-item"]}>
<div></div>
<div>{salaryTemplate.textContent}</div>
</div>
)}
</div>
</div>
);
})}
</div>
{!payrollData?.onlyOneGrup && salaryTemplate?.textContentPosition == 2 && salaryTemplate.textContent && (
<div className={cs(styles["corporate-culture-text"], styles["footer"])} title={salaryTemplate.textContent} dangerouslySetInnerHTML={{ __html: salaryTemplate.textContent }} />
)}
</div>
</div>
</div>
<div className={styles.pbmc_footer}>
<div className={styles.pbmcf_indicator}></div>
</div>
</>
);
};
export default MPayroll;

View File

@ -17,13 +17,14 @@ interface OwnProps {
i18n?: any;
pattern?: number;
calcDetail?: boolean; //查看详情页面
mzgOptPermission?: boolean; //二开美之高操作权限
children?: any;
}
type Props = OwnProps;
const customTableTitle: FunctionComponent<Props> = (props) => {
const { dataIndex, title, onHandleFormulatd, i18n = {}, pattern, dataType, calcDetail, children } = props;
const { dataIndex, title, onHandleFormulatd, i18n = {}, pattern, dataType, calcDetail, children, mzgOptPermission } = props;
const handleToggleSalaryItemVal = (salaryItemId: string, type: string, updateParams: any = {}) => {
window.parent.postMessage({ type: "turn", payload: { id: "LOCKING", params: { lockType: type, salaryItemId, ...updateParams } } }, "*");
};
@ -38,11 +39,13 @@ const customTableTitle: FunctionComponent<Props> = (props) => {
<Icon type="icon-piliangsuoding" title={i18n["点击锁定所有解锁的项目值"]} onClick={() => handleToggleSalaryItemVal(dataIndex as string, "LOCK")} />
<Icon type="icon-piliangjiesuo" title={i18n["点击解锁所有锁定的项目值"]} onClick={() => handleToggleSalaryItemVal(dataIndex as string, "UNLOCK")} />
<Icon type="icon-piliangfenpei" title={i18n["查看拓扑图"]} onClick={() => handleToggleSalaryItemVal(dataIndex as string, "DIAGRAM")} />
<Icon type="icon-pilianggengxin" title={i18n["批量更新"]} onClick={() => handleToggleSalaryItemVal(dataIndex as string, "BATCHUPDATE", { pattern, salaryItemName: title, dataType })} />
{!mzgOptPermission && (
<Icon type="icon-pilianggengxin" title={i18n["批量更新"]} onClick={() => handleToggleSalaryItemVal(dataIndex as string, "BATCHUPDATE", { pattern, salaryItemName: title, dataType })} />
)}
</div>
)}
</div>
);
};
export default customTableTitle;
export default customTableTitle;

View File

@ -5,8 +5,7 @@
* 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 { Button, Checkbox, Dropdown, MenuProps, Space, Table, Tooltip, Typography } from "antd";
import { DeleteOutlined, LockOutlined, QuestionCircleOutlined, SettingOutlined, UnlockOutlined } from "@ant-design/icons";
import CustomTableTitle from "@/pages/calcTable/customTableTitle";
import CalcExplainFooter from "@/pages/calcTable/calcExplainFooter";
@ -38,6 +37,7 @@ const index: FunctionComponent<Props> = (props) => {
const [payload, setPayload] = useState<string>("");
const [fixed, setFixed] = useState<fixedProps>(true);
const [sumRow, setSumRow] = useState<Partial<{}>>({}); //总计行数据
const [mzgOptPermission, setMzgOptPermission] = useState<boolean>(false); //美之高操作权限 false 默认可以编辑,true不可编辑
useEffect(() => {
window.parent.postMessage({ type: "init" }, "*");
@ -63,7 +63,8 @@ const index: FunctionComponent<Props> = (props) => {
fixed = true,
tableScrollHeight,
sumRow,
optWidth
optWidth,
mzgOptPermission = false
} = data;
setSumRowlistUrl(sumRowlistUrl);
setShowTotalCell(showTotalCell);
@ -77,6 +78,7 @@ const index: FunctionComponent<Props> = (props) => {
setDataSource(dataSource);
setSelectedRowKeys([...selectedRowKeys, ...rowKeys]);
setTableScrollHeight(tableScrollHeight);
setMzgOptPermission(mzgOptPermission);
setColumns([
...convertColumns(_.map(columns, (o) => ({ ...o, i18n: i18nRes }))),
{
@ -125,7 +127,17 @@ const index: FunctionComponent<Props> = (props) => {
const convertColumns: any = (cols: any[]) => {
return _.map(cols, (item) => {
if (_.isNaN(parseInt(item.dataIndex))) {
return { ...item };
// 医博肛肠二开
if (item.dataIndex === "ybgc-custom") {
return {
...item,
render: (text: string, record: any) => {
return <Checkbox checked={record?.calculateStatus === "1"} onChange={(e) => handlePassed(record, e.target.checked)} />;
}
};
} else {
return { ...item };
}
} else {
return {
...item,
@ -196,6 +208,38 @@ const index: FunctionComponent<Props> = (props) => {
})
}
]);
item.rightClickType &&
item.rightClickType.includes("MARK") &&
(items = [
...items,
{
label: item.i18n["标记"],
key: "MARK",
icon: <Icon type="icon-biaoji" />,
onClick: () =>
handleSetMark({
lockStatus: "LOCK",
acctEmpId: record?.id,
salaryItemId: item?.dataIndex
})
}
]);
item.rightClickType &&
item.rightClickType.includes("UNMARK") &&
(items = [
...items,
{
label: item.i18n["取消标记"],
key: "UNMARK",
icon: <Icon type="icon-quxiaobiaoji" />,
onClick: () =>
handleSetUnMark({
lockStatus: "UNLOCK",
acctEmpId: record?.id,
salaryItemId: item?.dataIndex
})
}
]);
return (
<Dropdown menu={{ items: !item.calcDetail || item.rightClickType ? items : [] }} trigger={["contextMenu"]} overlayClassName={styles.contextMenu} destroyPopupOnHide>
<span className={styles.contentSpan}>
@ -204,6 +248,7 @@ const index: FunctionComponent<Props> = (props) => {
</span>
<Icon type="icon-piliangfenpei" title={i18n["查看拓扑图"]} className={styles.diagramIcon} onClick={() => handleDiagramTd(item?.dataIndex, record?.id)} />
{record.lockItems && record.lockItems.includes(item.dataIndex) ? <LockOutlined title={item.i18n["锁定的项目值"]} /> : null}
{record.markItems && record.markItems.includes(item.dataIndex) ? <Icon type="icon-biaoji-copy" title={item.i18n["标记的项目值"]} style={{ marginLeft: 4 }} /> : null}
{!_.isEmpty(record[`${item.dataIndex}_feedback`]) ? (
<Tooltip title={record[`${item.dataIndex}_feedback`]}>
<QuestionCircleOutlined />
@ -236,6 +281,26 @@ const index: FunctionComponent<Props> = (props) => {
const handleSetFeedback = (params: any) => {
window.parent.postMessage({ type: "turn", payload: { id: "SETFEEDBACK", params } }, "*");
};
// 安徽国元信托有限责任公司薪酬二开-薪资核算项添加右击添加标记和取消标记的操作
const handleSetMark = (params: any) => {
window.parent.postMessage({ type: "turn", payload: { id: "MARK", params } }, "*");
};
const handleSetUnMark = (params: any) => {
window.parent.postMessage({ type: "turn", payload: { id: "UNMARK", params } }, "*");
};
// 医博二开
const handlePassed = (params: any, calculateStatus: boolean) => {
setDataSource((pre) => {
pre = _.map(pre, (o) => {
if (o.id === params.id) {
return { ...o, calculateStatus: calculateStatus ? "1" : "0" };
}
return o;
});
return pre;
});
window.parent.postMessage({ type: "turn", payload: { id: "CUSTPASSED", params: { ...params, calculateStatus: calculateStatus ? "1" : "0" } } }, "*");
};
const sizeChange = (pageobj: IPage) => {};
const onChange = (pageobj: IPage) => {
setPageInfo(() => {
@ -245,8 +310,9 @@ const index: FunctionComponent<Props> = (props) => {
};
const rowSelection = {
columnWidth: 50,
columnTitle: isDetailTable && _.isNil(showSee) ? "序号" : "",
renderCell: (value: boolean, record: any, index: number, originNode: React.ReactNode) => (isDetailTable && _.isNil(showSee) ? <span>{index + 1}</span> : originNode),
columnTitle: isDetailTable && !showSee ? "序号" : "",
renderCell: (value: boolean, record: any, index: number, originNode: React.ReactNode) =>
isDetailTable && !showSee ? <span>{!_.isEmpty(pageInfo) ? ((pageInfo.current as number) - 1) * (pageInfo.pageSize as number) + index + 1 : index + 1}</span> : originNode,
selectedRowKeys,
preserveSelectedRowKeys: true,
onChange: (rowKeys: React.Key[]) => {
@ -272,7 +338,7 @@ const index: FunctionComponent<Props> = (props) => {
x: 1200,
y: `calc(100vh - ${tableScrollHeight || (!showTotalCell ? 165 : 200)}px)`
}}
columns={!isDetailTable || showSee ? columns : _.filter(columns, (o) => o.dataIndex !== "operate")}
columns={(!isDetailTable || showSee) && !mzgOptPermission ? columns : _.filter(columns, (o) => o.dataIndex !== "operate")}
footer={() => (!isDetailTable ? <CalcExplainFooter i18n={i18n} /> : null)}
pagination={
!_.isNil(pageInfo)
@ -300,4 +366,4 @@ const index: FunctionComponent<Props> = (props) => {
);
};
export default index;
export default index;