Merge branch 'release/2.19.1.2501.01-个税' into custom-艾志工业-合并个税

# Conflicts:
#	pc4mobx/hrmSalary/pages/calculate/doCalc/components/salaryEditCalc/editCalcTable.js
#	pc4mobx/hrmSalary/pages/employeedeclareDetail/index.js
This commit is contained in:
lys 2025-04-11 14:03:28 +08:00
commit f4726da0fc
35 changed files with 772 additions and 50 deletions

View File

@ -283,3 +283,28 @@ export const getTaxdeclarationContrastList = (params) => {
export const exportContrast = params => {
return postExportFetch("/api/bs/hrmsalary/taxdeclaration/exportContrast", params);
};
//扣除名单确认-人员列表
export const getDeductionAmountList = (params) => {
return postFetch("/api/bs/hrmsalary/deductionAmount/list", params);
};
//扣除名单确认-增加人员
export const addDeductionAmount = (params) => {
return postFetch("/api/bs/hrmsalary/deductionAmount/add", params);
};
//扣除名单确认-删除人员
export const deleteDeductionAmount = (params) => {
return postFetch("/api/bs/hrmsalary/deductionAmount/delete", params);
};
//扣除名单确认-编辑人员
export const editDeductionAmount = (params) => {
return postFetch("/api/bs/hrmsalary/deductionAmount/edit", params);
};
//扣除名单确认-确认人员
export const confirmDeductionAmount = (params) => {
return postFetch("/api/bs/hrmsalary/deductionAmount/confirm", params);
};
//扣除名单确认-反馈人员
export const feedbackDeductionAmount = (params) => {
return postFetch("/api/bs/hrmsalary/deductionAmount/feedback", params);
};

View File

@ -155,13 +155,14 @@
.item-count {
//flex-basis: 328px;
flex: 1;
padding-left: 16px;
padding: 12px 16px;
height: 100%;
line-height: 40px;
background: #fff;
font-size: 12px;
color: #5F5F5F;
word-break: break-all;
display: flex;
align-items: center;
}
}
}

View File

@ -6,7 +6,6 @@ import SalaryAdjustmentRecords from "./pages/salaryAdjustmentRecords";
import MySalaryMobile from "./pages/mySalaryMobile";
import MySalary from "./pages/mySalaryBenefits";
import Programme from "./pages/socialSecurityBenefits/welfarePlan";
// import Archivess from "./pages/socialSecurityBenefits/archives";
import Archives from "./pages/socialSecurityBenefits/welfareArchive"; //社保福利档案重构页面
import StandingBook from "./pages/socialSecurityBenefits/standingBook/standingBook"; //社保福利台账重构页面
import StandingBookDetail from "./pages/socialSecurityBenefits/standingBookDetail";
@ -19,20 +18,16 @@ import CumSituation from "./pages/dataAcquisition/cumSituation";
import Attendance from "./pages/dataAcquisition/attendance";
import SpecialAddDeduction from "./pages/dataAcquisition/specialAddDeduction";
import Ledger from "./pages/ledgerPage";
// import Calculate from "./pages/calculate";
import Calculate from "./pages/calculate/calculate"; //重构的薪资核算页面
// import Payroll from "./pages/payroll";
import Payroll from "./pages/payrollRelease"; //重构的工资单发放页面
import PayrollGrant from "./pages/payroll/payrollGrant";
import PayrollDetail from "./pages/payroll/payrollDetail/payrollDetail";
// import Declare from "./pages/declare";
import DeclareDetail from "./pages/declareDetail";
import DeclareOnlineComparison from "./pages/declareOnlineComparison";
import Employeedeclare from "./pages/employeedeclare";
import EnterprisePayCertificationDetail from "./pages/enterprisePayCertificationDetail";
import BankVoucherDetail from "./pages/bankVoucherDetail";
import EmployeedeclareDetail from "./pages/employeedeclareDetail";
// import Declare from "./pages/declare";
import Declare from "./pages/declare/declare"; //重构的个税申报表
import TaxRate from "./pages/taxRate";
import TaxAgents from "./pages/taxAgent";
@ -119,14 +114,9 @@ const Routes = (
<Route key="employeedeclare" path="employeedeclare" component={Employeedeclare}/>
<Route key="enterprisePayCertificationDetail" path="enterprisePayCertificationDetail"
component={EnterprisePayCertificationDetail}/>
<Route key="bankVoucherDetail" path="bankVoucherDetail"
component={BankVoucherDetail}/>
<Route key="bankVoucherDetail" path="bankVoucherDetail" component={BankVoucherDetail}/>
<Route key="employeedeclareDetail" path="employeedeclareDetail" component={EmployeedeclareDetail}/>
<Route
key="generateDeclarationDetail"
path="generateDeclarationDetail"
component={GenerateDeclarationDetail}
/>
<Route key="generateDeclarationDetail" path="generateDeclarationDetail" component={GenerateDeclarationDetail}/>
<Route key="taxRate" path="taxRate" component={TaxRate}/>
<Route key="taxAgent" path="taxAgent" component={TaxAgent}/>
<Route key="taxAgents" path="taxAgents" component={TaxAgents}/>

View File

@ -22,6 +22,8 @@ class Layout extends Component {
componentWillReceiveProps(nextProps, nextContext) {
if (window.e9LibsConfigCustomF && _.some(window.e9LibsConfigCustomF, o => (_.some(o, k => k === "h_hrmSalary")))) {
stores.baseFormStore.initForm();
stores.baseFormStore.initFormExtra();
if (window.location.hash.indexOf("payroll") !== -1) {
window.localStorage.removeItem("template-basedata");
window.localStorage.removeItem("salary-showset");

View File

@ -153,6 +153,36 @@ export const salaryDetailSearchConditions = [
multiple: true,
viewAttr: 2
},
{
browserConditionParam: {
completeParams: {},
conditionDataParams: {},
dataParams: {},
destDataParams: {},
hasAddBtn: false,
hasAdvanceSerach: false,
idSeparator: ",",
isAutoComplete: 1,
isDetail: 0,
isMultCheckbox: false,
isSingle: false,
icon: "icon-coms-hrm",
linkUrl: "",
pageSize: 10,
quickSearchName: "",
replaceDatas: [],
title: "",
type: "17",
viewAttr: 2
},
colSpan: 1,
conditionType: "BROWSER",
domkey: ["employeeIds"],
fieldcol: 16,
label: getLabel(111, "人员"),
labelcol: 8,
viewAttr: 2
},
{
browserConditionParam: {
completeParams: {},

View File

@ -109,12 +109,13 @@ class SalaryDetails extends Component {
getSalaryList = (props) => {
const { attendanceStore: { salaryDetailSearchForm, tableStore }, dateRange } = props || this.props;
const [startDateStr, endDateStr] = dateRange;
const { taxAgentIds, subcompanyIds, departmentIds, ...extra } = salaryDetailSearchForm.getFormParams();
const { taxAgentIds, subcompanyIds, departmentIds, employeeIds, ...extra } = salaryDetailSearchForm.getFormParams();
const { pageInfo, transferDialog, updateSum } = this.state;
const payload = {
taxAgentIds: taxAgentIds ? taxAgentIds.split(",") : [],
departmentIds: departmentIds ? departmentIds.split(",") : [],
subcompanyIds: subcompanyIds ? subcompanyIds.split(",") : [],
employeeIds: employeeIds ? employeeIds.split(",") : [],
...extra, ...pageInfo, startDateStr, endDateStr
};
this.setState({ loading: true });

View File

@ -182,7 +182,7 @@
}
.wea-advanced-searchsAd {
height: 155px;
height: 200px;
overflow: hidden auto;
.formItem-delete {

View File

@ -0,0 +1,110 @@
/*
* 核算编辑
* 数据查看锚点
* @Author: 黎永顺
* @Date: 2025/2/10
* @Wechat:
* @Email: 971387674@qq.com
* @description:
*/
import React, { Component } from "react";
import { WeaLocaleProvider } from "ecCom";
import classnames from "classnames";
const getLabel = WeaLocaleProvider.getLabel;
class CalcAnchorList extends Component {
constructor(props) {
super(props);
this.state = {
collapsed: false, currentIndex: 0
};
this.isClickRef = null;
this.timerRef = null;
}
componentDidMount() {
document.getElementById("salary_anchor_area").addEventListener("scroll", this.handlerScroll);
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && !nextProps.visible) this.setState({
collapsed: false,
currentIndex: 0
});
}
componentWillUnmount() {
document.getElementById("salary_anchor_area").removeEventListener("scroll", this.handlerScroll);
}
handlerScroll = () => {
// 点击锚点时,不执行滚动函数
if (this.isClickRef) return;
// 获取滚动容器的滚动高度(这里相对于#salary_anchor_area滚动的
const scrollTop = document.getElementById("salary_anchor_area").scrollTop;
// 获取所有wea-search-group anchor_开头的元素集合
const contentList = document.querySelectorAll("[class^='wea-search-group anchor_']");
const offsetTopArr = [];
contentList.forEach((item) => {
// 获取每个wea-search-group anchor_开头的元素的offsetTop
offsetTopArr.push(item.offsetTop);
});
for (let i = 0; i < offsetTopArr.length; i++) {
// 当滚动条高度达到对应wea-search-group anchor_开头的元素的滚动高度、则将锚点设置为高亮状态
if (scrollTop + 190 >= offsetTopArr[i]) this.setState({ currentIndex: i });
}
};
onClickAnchor = (item, index) => {
const anchorElement = document.getElementById("salary_anchor_area");
const el = document.querySelector(`.anchor_${item.salarySobItemGroupId}`);
if (el) {
anchorElement.scroll({ top: el.offsetTop, behavior: "smooth" });
}
this.setState({ currentIndex: index });
// 点击时设置为true,为了防止同时执行滚动事件
this.isClickRef = true;
// 清除定时器,防止滚动事件触发、出现走马灯闪烁问题
if (this.timerRef) clearTimeout(this.timerRef);
this.timerRef = setTimeout(() => {
this.isClickRef = false;
}, 1000);
};
render() {
const { collapsed, currentIndex } = this.state, { datas } = this.props;
return (
<div id="anchorList-contianer" style={{ position: "sticky", top: 8, zIndex: 10086 }}>
<div className={classnames("anchor-list-wrapper", { "anchor-list-collapsed": collapsed })}>
{
collapsed ?
<div className="anchor-list-collapsed-btn">
<i className="icon-coms02-Initialize-template"
onClick={() => this.setState({ collapsed: !collapsed })}/>
</div> :
<React.Fragment>
<div className="anchor-list-header">
<i className="icon-coms-right" onClick={() => this.setState({ collapsed: !collapsed })}/>
</div>
<div className="anchor-list">
<div className="anchor-list-ink">
<span className="anchor-list-ink-ball visible"
style={{ top: `${2.5 + currentIndex * 27.7}px`, height: 23 }}/>
</div>
{_.map(datas, (o, i) => (
<div className={classnames("anchor-list-link", { "anchor-list-link-active": currentIndex === i })}
onClick={() => this.onClickAnchor(o, i)}>
<span
className={classnames("anchor-list-link-title", { "anchor-list-link-title-active": currentIndex === i })}>{o.salarySobItemGroupName}</span>
</div>)
)}
</div>
</React.Fragment>
}
</div>
</div>
);
}
}
export default CalcAnchorList;

View File

@ -313,10 +313,7 @@ class EditCalcTable extends Component {
/>
<EditSalaryCalcSlide {...salaryCalcSlide}
onClose={(isFresh) => this.setState({
salaryCalcSlide: {
visible: false,
id: ""
}
salaryCalcSlide: { visible: false, id: "", viewAttr: 2 }
}, () => isFresh === "true" && this.queryCalcResultList())}/>
{
progressVisible &&

View File

@ -12,9 +12,9 @@ import PayrollItemsTable from "../../../../calculateDetail/payrollItemsTable";
import IssuedAndReissueTable from "../../../../calculateDetail/issuedAndReissueTable";
import { acctresultDetail, saveAcctResult } from "../../../../../apis/calculate";
import { toDecimal_n } from "../../../../../util";
import CalcAnchorList from "./calcAnchorList";
import "./index.less";
const getLabel = WeaLocaleProvider.getLabel;
class EditSalaryCalcSlide extends Component {
@ -29,7 +29,7 @@ class EditSalaryCalcSlide extends Component {
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) this.acctresultDetail(nextProps.id);
if (nextProps.visible !== this.props.visible && !nextProps.visible) this.setState({ selectedKey: "0" });
if (nextProps.visible !== this.props.visible && !nextProps.visible) this.setState({ selectedKey: "0" }, () => document.getElementById("salary_anchor_area").scrollTop = 0);
}
acctresultDetail = (id) => {
@ -142,7 +142,9 @@ class EditSalaryCalcSlide extends Component {
className="salary-calculate-esf-layout" {...this.props}
top={0} width={60} height={100} measure={"%"}
direction={"right"} title={this.renderTitle()}
content={<div className="salary-calculate-esf-area">
content={<div className="salary-calculate-esf-area" id="salary_anchor_area">
{/*锚点*/}
<CalcAnchorList datas={itemsByGroup} visible={this.props.visible}/>
<EditSalaryBaseInfo {...this.props} baseInfo={baseInfo}
onChange={baseInfo => this.setState({ baseInfo })}/>
<WeaTab keyParam="viewcondition" className="calc-esf-tab"

View File

@ -147,6 +147,7 @@
height: 100%;
.salary-calculate-esf-area {
position: relative;
background: #f6f6f6;
height: 100%;
overflow-y: auto;
@ -200,6 +201,109 @@
.wea-search-group {
padding: 0;
}
//锚点按钮
.anchor-list-collapsed {
padding: 0 !important;
}
.anchor-list-wrapper {
position: absolute;
right: 0;
margin: 10px 15px 20px;
padding: 8px 10px;
overflow: auto;
background-color: #fff;
box-shadow: 0 3px 12px 0 rgba(0, 0, 0, .12);
border-radius: 3px;
cursor: pointer;
.anchor-list-collapsed-btn {
opacity: .5;
background: #000;
color: #fff;
border-radius: 3px;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
}
.anchor-list-header {
display: flex;
align-items: center;
justify-content: flex-end;
min-width: 130px;
padding: 5px;
}
.anchor-list {
padding: 0 10px;
position: relative;
margin-top: 10px;
transition: margin-top .3s;
.anchor-list-ink {
position: absolute;
top: 0;
left: 5px;
height: 100%;
.anchor-list-ink-ball.visible {
display: inline-block;
}
.anchor-list-ink-ball {
position: absolute;
left: 50%;
display: none;
width: 3px;
height: 8px;
background-color: #5d9cec;
border: 1.5px solid #5d9cec;
border-radius: 8px;
transform: translateX(-50%);
transition: top .3s ease-in-out;
}
}
.anchor-list-ink:before {
position: relative;
display: block;
width: 1px;
height: 100%;
margin: 0 auto;
background-color: #f0f0f0;
content: " ";
}
.anchor-list-link {
padding: 7px 0 7px 10px;
line-height: 1.143;
.anchor-list-link-title {
position: relative;
display: block;
overflow: hidden;
color: #666;
white-space: nowrap;
text-overflow: ellipsis;
transition: all .3s;
cursor: pointer;
outline: none;
text-decoration: none;
background-color: transparent;
}
}
.anchor-list-link-active > .anchor-list-link-title {
color: #5d9cec;
}
}
}
}
}
}

View File

@ -68,7 +68,7 @@ class PayrollItemsTable extends Component {
}
];
return (
<WeaSearchGroup title={salarySobItemGroupName} showGroup needTigger>
<WeaSearchGroup title={salarySobItemGroupName} showGroup needTigger className={`anchor_${salarySobItemGroupId}`}>
<WeaTable
rowKey="salaryItemId"
dataSource={dataSource}

View File

@ -5,11 +5,13 @@
* Date: 2023/2/20
*/
import React, { Component } from "react";
import { WeaSearchGroup, WeaTable } from "ecCom";
import { WeaLocaleProvider, WeaSearchGroup, WeaTable } from "ecCom";
import { getTableRecordDate } from "../../../apis/cumDeduct";
import { DataCollectionDateRangePick, DataCollectionSelect, Input } from "../cumDeduct";
import "./index.less";
const getLabel = WeaLocaleProvider.getLabel;
class TableRecord extends Component {
constructor(props) {
super(props);
@ -167,11 +169,11 @@ class TableRecord extends Component {
};
const items = screenParams.length === 1 ? [
{
com: Input({ value: record.username })
com: Input({ label: getLabel(111, "姓名"), value: record.username })
}
] : [
{
com: Input({ value: record.username })
com: Input({ label: getLabel(111, "姓名"), value: record.username })
},
{
com: DataCollectionSelect({

View File

@ -609,8 +609,10 @@ export const DataCollectionSelect = (props) => {
};
export const Input = (props) => {
const { value } = props;
return (<WeaInput value={value} viewAttr={1}/>);
const { value, label } = props;
return (<WeaFormItem label={label} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
<WeaInput value={value} viewAttr={1}/>
</WeaFormItem>);
};
export const DataCollectionDateRangePick = (props) => {
const { range, label, onChange, format = "YYYY-MM", key } = props;

View File

@ -336,7 +336,7 @@ class Index extends Component {
const { addAllLoading, incomeTaxStatus } = this.state;
const commonBtns = [
<Button type="primary" onClick={this.handleOpenImport}>导入</Button>,
<Button type="ghost" onClick={this.handleOnlineAccess}>{getLabel(111, "在线获取")}</Button>,
// <Button type="ghost" onClick={this.handleOnlineAccess}>{getLabel(111, "在线获取")}</Button>,
<Button type="ghost" onClick={() => this.handleAddData()}>新建</Button>,
<Dropdown
overlay={

View File

@ -67,6 +67,7 @@ class Index extends Component {
return _.map(_.filter(toJS(declareTableStore.columns), (item) => (item.display === "true" && showColumns.includes(item["dataIndex"]))), o => ({
dataIndex: o.dataIndex, title: o.title, width: 150,
render: (text, record) => {
if (!record[o["dataIndex"]]) return <span/>;
return Object.prototype.toString.call(record[o["dataIndex"]]) === "[object String]" ? <span>{text}</span> :
<div className="comparison-column-item-container">
<div className="comparison-single-row">

View File

@ -94,7 +94,7 @@ class Index extends Component {
width: 260,
render: (_, record) => (<React.Fragment>
<a
href={`${window.ecologyContentPath || ""}/spa/hrmSalary/static/index.html#/main/hrmSalary/employeedeclareDetail?id=${record.id}&taxName=${record.taxAgentName}`}
href={`${window.ecologyContentPath || ""}/spa/hrmSalary/static/index.html#/main/hrmSalary/employeedeclareDetail?id=${record.id}&taxName=${encodeURIComponent(record.taxAgentName)}`}
target="_blank">{getLabel(83110, "查看详情")}</a>
<Dropdown overlay={
<Menu>

View File

@ -0,0 +1,78 @@
/*
* 扣除名单确认
* 编辑是否扣除
* @Author: 黎永顺
* @Date: 2025/3/27
* @Wechat:
* @Email: 971387674@qq.com
* @description:
*/
import React, { Component } from "react";
import { WeaDialog, WeaLocaleProvider, WeaTools } from "ecCom";
import { Button, message } from "antd";
import { WeaForm } from "comsMobx";
import FormInfo from "../../../components/FormInfo";
import { deductConditions } from "../constants";
import * as API from "../../../apis/declare";
const getKey = WeaTools.getKey;
const getLabel = WeaLocaleProvider.getLabel;
const form = new WeaForm();
class DeductionAmountEditDialog extends Component {
constructor(props) {
super(props);
this.state = {
conditions: [], loading: false
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) this.initForm(nextProps);
if (nextProps.visible !== this.props.visible && !nextProps.visible) form.resetForm();
}
initForm = (props) => {
const { record } = props;
this.setState({
conditions: _.map(deductConditions, item => ({
...item,
items: _.map(item.items, o => ({ ...o, value: record[getKey(o)] + "", label: getLabel(o.lanId, o.label) }))
}))
}, () => form.initFormFields(this.state.conditions));
};
save = () => {
form.validateForm().then(f => {
if (f.isValid) {
const { id } = this.props.record;
const paylaod = { id, deductFlag: form.getFormParams().deductFlag };
this.setState({ loading: true });
API.editDeductionAmount(paylaod).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success(getLabel(30700, "操作成功!"));
this.props.onCancel(this.props.onSuccess);
} else {
message.error(errormsg);
}
}).catch(() => this.setState({ loading: false }));
} else {
f.showErrors();
}
});
};
render() {
const { conditions, loading } = this.state;
const height = _.reduce(conditions, (pre, cur) => pre + cur.items.length, 0).length * 47;
return (<WeaDialog {...this.props} initLoadCss title={getLabel(111, "编辑")} style={{ height }}
buttons={[<Button type="primary" loading={loading}
onClick={this.save}>{getLabel(111, "确定")}</Button>,
<Button type="ghost" onClick={() => this.props.onCancel()}>{getLabel(111, "取消")}</Button>]}>
<FormInfo className="form-dialog-layout" center={false} form={form} formFields={conditions}/>
</WeaDialog>);
}
}
export default DeductionAmountEditDialog;

View File

@ -0,0 +1,173 @@
/*
* 扣除名单确认
* @Author: 黎永顺
* @Date: 2025/3/26
* @Wechat:
* @Email: 971387674@qq.com
* @description:
*/
import React, { Component } from "react";
import { WeaButtonIcon, WeaDialog, WeaLocaleProvider, WeaTable, WeaTools } from "ecCom";
import DeductionListConfirmEmployeeDialog from "./deductionListConfirmEmployeeDialog";
import DeductionAmountEditDialog from "./deductionAmountEditDialog";
import { Button, Col, message, Modal, Row } from "antd";
import * as API from "../../../apis/declare";
import { calcPageNo } from "../../../util";
const { getLabel } = WeaLocaleProvider, { getUrlParams } = WeaTools;
class DeductionListConfirmDialog extends Component {
constructor(props) {
super(props);
this.state = {
pageInfo: { current: 1, pageSize: 10, total: 0 }, loading: false, columns: [], dataSource: [], visible: false,
selectedRowKeys: [], editDialog: { visible: false, record: {} }, loadingBtn: { confirm: false, feedback: false }
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) this.getDeductionAmountList(nextProps);
if (nextProps.visible !== this.props.visible && !nextProps.visible) this.setState({
pageInfo: { current: 1, pageSize: 10, total: 0 }, loading: false, dataSource: [], selectedRowKeys: []
});
}
getDeductionAmountList = (props) => {
const { pageInfo } = this.state, { id: taxAgentId } = getUrlParams(), { year } = props || this.props;
const payload = { ...pageInfo, taxAgentId, year };
this.setState({ loading: true });
API.getDeductionAmountList(payload).then(({ status, data }) => {
this.setState({ loading: false });
if (status) {
const { columns, list: dataSource, pageNum: current, pageSize, total } = data;
this.setState({
dataSource, pageInfo: { ...pageInfo, current, pageSize, total },
columns: [..._.map(columns, o => {
if (o.dataIndex === "deductFlag") {
return { ...o, render: v => (<span>{v === 1 ? getLabel(111, "是") : getLabel(111, "否")}</span>) };
}
return { ...o };
}), {
title: getLabel(111, "操作"), dataIndex: "action",
render: (v, record) => (<a href="javascript:void(0)" onClick={() => this.setState({
editDialog: { visible: true, record }
})}>{getLabel(111, "编辑")}</a>)
}]
});
}
}).catch(() => this.setState({ loading: false }));
};
handleDelete = () => {
Modal.confirm({
title: getLabel(111, "信息确认"),
content: getLabel(111, "确认删除本条数据吗?"),
onOk: () => {
API.deleteDeductionAmount({ ids: this.state.selectedRowKeys }).then(({ status, errormsg }) => {
if (status) {
const { pageInfo } = this.state, { current, pageSize, total } = pageInfo;
message.success(getLabel(111, "操作成功"));
this.setState({
selectedRowKeys: [],
pageInfo: {
...pageInfo, current: calcPageNo(total, current, pageSize, this.state.selectedRowKeys.length)
}
}, () => this.getDeductionAmountList());
} else {
message.error(errormsg);
}
});
}
});
};
confirmDeductionAmount = () => {
const { id: taxAgentId } = getUrlParams(), { year } = this.props;
const payload = { taxAgentId, year };
this.setState({ loadingBtn: { ...this.state.loadingBtn, confirm: true } });
API.confirmDeductionAmount(payload).then(({ status, errormsg }) => {
this.setState({ loadingBtn: { ...this.state.loadingBtn, confirm: false } });
if (status) {
message.success(getLabel(111, "操作成功"));
this.getDeductionAmountList();
} else {
message.error(errormsg);
}
});
};
feedbackDeductionAmount = () => {
const { id: taxAgentId } = getUrlParams(), { year } = this.props;
const payload = { taxAgentId, year };
this.setState({ loadingBtn: { ...this.state.loadingBtn, confirm: true } });
API.feedbackDeductionAmount(payload).then(({ status, errormsg }) => {
this.setState({ loadingBtn: { ...this.state.loadingBtn, confirm: false } });
if (status) {
message.success(getLabel(111, "操作成功"));
this.getDeductionAmountList();
} else {
message.error(errormsg);
}
});
};
render() {
const { loading, columns, dataSource, pageInfo, visible, selectedRowKeys, editDialog, loadingBtn } = this.state;
const pagination = {
...pageInfo,
showTotal: total => `${getLabel(18609, "共")} ${total} ${getLabel(18256, "条")}`,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
onShowSizeChange: (current, pageSize) => {
this.setState({
pageInfo: { ...pageInfo, current, pageSize }
}, () => this.getDeductionAmountList());
},
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => this.getDeductionAmountList());
}
};
const rowSelection = {
selectedRowKeys, onChange: v => this.setState({ selectedRowKeys: v })
};
const height = this.refs.employeeRef ? this.refs.employeeRef.state.height : 400;
return (
<WeaDialog {...this.props} initLoadCss ref="confirmRef" className="confirmationDialog"
title={(<Row type="flex">
<Col span={12}>
<span className="title">{getLabel(111, "扣除名单确认")}</span>
</Col>
<Col span={12} className="title-right">
<Button type="primary" onClick={this.confirmDeductionAmount}
loading={loadingBtn.confirm}>{getLabel(111, "确认")}</Button>
<Button type="primary" onClick={this.feedbackDeductionAmount}
loading={loadingBtn.feedback}>{getLabel(111, "反馈")}</Button>
</Col>
</Row>)}
style={{
width: 1150, height: 490, minHeight: 200, minWidth: 380, maxHeight: "90%",
maxWidth: "90%", overflow: "hidden", transform: "translate(0px, 0px)"
}}>
<div className="confirmationDialogContent">
<div className="tableBtns">
<WeaButtonIcon buttonType="add" type="primary" title={getLabel(111, "添加")}
onClick={() => this.setState({ visible: true })}/>
<WeaButtonIcon buttonType="del" type="primary" title={getLabel(111, "删除")} onClick={this.handleDelete}
disabled={_.isEmpty(selectedRowKeys)}/>
</div>
<WeaTable columns={columns} dataSource={dataSource} loading={loading} pagination={pagination} rowKey="id"
rowSelection={rowSelection} scroll={{ y: `calc(${height}px - 113px)` }}/>
<DeductionAmountEditDialog {...editDialog} onSuccess={this.getDeductionAmountList}
onCancel={(callback) => this.setState({
editDialog: { visible: false, record: {} }
}, () => callback && callback())}/>
<DeductionListConfirmEmployeeDialog visible={visible} onSuccess={this.getDeductionAmountList}
year={this.props.year} payload={this.props.payload}
onCancel={(callback) => this.setState({ visible: false }, () => callback && callback())}/>
</div>
</WeaDialog>
);
}
}
export default DeductionListConfirmDialog;

View File

@ -0,0 +1,106 @@
/*
* 扣除名单确认
* 人员添加列表
* @Author: 黎永顺
* @Date: 2025/3/26
* @Wechat:
* @Email: 971387674@qq.com
* @description:
*/
import React, { Component } from "react";
import { WeaDialog, WeaLocaleProvider, WeaTable, WeaTools } from "ecCom";
import { Button, message } from "antd";
import * as API from "../../../apis/declare";
const { getLabel } = WeaLocaleProvider, { getUrlParams } = WeaTools;
const columns = [{ title: getLabel(111, "姓名"), dataIndex: "employeeName" }, {
title: getLabel(111, "分部"),
dataIndex: "subCompanyName"
}, { title: getLabel(111, "部门"), dataIndex: "departmentName" }, {
title: getLabel(111, "个税扣缴义务人"),
dataIndex: "taxAgentName"
}, { title: getLabel(111, "工号"), dataIndex: "jobNum" }, { title: getLabel(111, "手机号码"), dataIndex: "mobile" }];
class DeductionListConfirmEmployeeDialog extends Component {
constructor(props) {
super(props);
this.state = {
pageInfo: { current: 1, pageSize: 10, total: 0 }, loading: false, dataSource: [], selectedRowKeys: [],
saveloading: false
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) this.employeedeclareList(nextProps);
if (nextProps.visible !== this.props.visible && !nextProps.visible) this.setState({
pageInfo: { current: 1, pageSize: 10, total: 0 }, loading: false, dataSource: [], selectedRowKeys: []
});
}
employeedeclareList = (props) => {
const { pageInfo } = this.state, { payload } = props || this.props;
this.setState({ loading: true });
API.employeedeclareList({ ...payload, ...pageInfo }).then(({ status, data }) => {
this.setState({ loading: false });
if (status) {
const { pageInfo: result } = data;
const { list: dataSource, pageNum: current, pageSize, total } = result;
this.setState({ dataSource, pageInfo: { ...pageInfo, current, pageSize, total } });
}
}).catch(() => this.setState({ loading: false }));
};
save = () => {
const { selectedRowKeys: employeeDeclareIds } = this.state, { id: taxAgentId } = getUrlParams(), { year } = this.props;
const payload = { taxAgentId, year, employeeDeclareIds };
this.setState({ saveloading: true });
API.addDeductionAmount(payload).then(({ status, errormsg }) => {
this.setState({ saveloading: false });
if (status) {
message.success(getLabel(111, "操作成功"));
this.props.onCancel(this.props.onSuccess);
} else {
message.error(errormsg);
}
});
};
render() {
const { loading, dataSource, pageInfo, selectedRowKeys, saveloading } = this.state;
const pagination = {
...pageInfo,
showTotal: total => `${getLabel(18609, "共")} ${total} ${getLabel(18256, "条")}`,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
onShowSizeChange: (current, pageSize) => {
this.setState({
pageInfo: { ...pageInfo, current, pageSize }
}, () => this.employeedeclareList());
},
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => this.employeedeclareList());
}
};
const rowSelection = {
selectedRowKeys, onChange: v => this.setState({ selectedRowKeys: v })
};
const height = this.refs.employeeRef ? this.refs.employeeRef.state.height : 400;
return (<WeaDialog {...this.props} hasScroll initLoadCss title={getLabel(111, "选择人员")} ref="employeeRef"
buttons={[<Button type="primary" disabled={_.isEmpty(selectedRowKeys)} loading={saveloading}
onClick={this.save}>{getLabel(111, "确认")}</Button>,
<Button type="ghost" onClick={() => this.props.onCancel()}>{getLabel(111, "取消")}</Button>]}
style={{
width: 1150, height: 490, minHeight: 200, minWidth: 380, maxHeight: "90%", maxWidth: "90%",
overflow: "hidden", transform: "translate(0px, 0px)"
}}>
<div className="confirmationDialogContent">
<WeaTable columns={columns} dataSource={dataSource} loading={loading} pagination={pagination} rowKey="id"
rowSelection={rowSelection} scroll={{ y: `calc(${height}px - 113px)` }}/>
</div>
</WeaDialog>);
}
}
export default DeductionListConfirmEmployeeDialog;

View File

@ -170,7 +170,6 @@ export const advanceConditions = [
defaultshow: true
}
];
export const declareConditions = [
{
items: [
@ -491,3 +490,31 @@ export const declareConditions = [
defaultshow: true
}
];
// 扣除名单确认
export const deductConditions = [
{
items: [
{
conditionType: "INPUT",
domkey: ["employeeName"],
fieldcol: 12,
label: "姓名",
lanId: 111,
labelcol: 6,
value: "",
viewAttr: 1
},
{
conditionType: "SWITCH",
domkey: ["deductFlag"],
fieldcol: 12,
label: "是否扣除",
lanId: 111,
labelcol: 6,
value: "",
viewAttr: 2
},
],
defaultshow: true
}
];

View File

@ -12,6 +12,7 @@ import { Button, Dropdown, Menu, message, Modal, Spin } from "antd";
import BaseInfo from "./components/baseInfo";
import EmployeeDeclareDetailSchemaEditDialog from "./components/employeeDeclareDetailSchemaEditDialog";
import EmployeeDeclareDetailSchemaImportDialog from "./components/employeeDeclareDetailImportDialog";
import DeductionListConfirmDialog from "./components/deductionListConfirmDialog";
import { commonEnumList } from "../../apis/payrollFiles";
import {
employeedeclareDeclare,
@ -48,6 +49,7 @@ class Index extends Component {
taxCycle: new Date(), pageInfo: { current: 1, pageSize: 10, total: 0 },
loading: { query: false, refresh: false, feedback: false, declare: false, exportLoading: false },
declareEditDialog: { visible: false, id: "", title: "" },
confirmationDialog: { visible: false, payload: {} },
declareStatusList: [], employmentStatusList: [],
employmentTypeList: [], adConditons: [],
selectedRowKeys: [], exportPayload: {},
@ -169,7 +171,7 @@ class Index extends Component {
employeeDeclareStore: { advanceForm: form },
taxAgentStore: { showOperateBtn, isTaxDeclareAdmin }
} = this.props;
const { pageInfo, declareStatus, taxCycle, selectedKey, selectedRowKeys } = this.state;
const { pageInfo, declareStatus, taxCycle, selectedKey, selectedRowKeys, confirmationDialog } = this.state;
const { departmentIds, positionIds, ...formParams } = form.getFormParams();
//判断税款所属期是否在两月以内
const isGreaterThanLastTwoMonths = moment(taxCycle).isAfter(moment().subtract(2, "months"));
@ -190,7 +192,8 @@ class Index extends Component {
this.baseInfoRef.getEmployeeDeclareInfo();
this.setState({
azOperate: isGreaterThanLastTwoMonths,
pageInfo: { ...pageInfo, current, pageSize, total }
pageInfo: { ...pageInfo, current, pageSize, total },
confirmationDialog: { ...confirmationDialog, payload }
}, () => {
const payload = {
dataSource, selectedRowKeys, selectedKey,
@ -420,7 +423,7 @@ class Index extends Component {
});
};
handleMenuClick = ({ key }) => {
const { selectedRowKeys } = this.state;
const { selectedRowKeys, confirmationDialog } = this.state;
switch (key) {
case "1":
if (_.isEmpty(selectedRowKeys)) {
@ -429,6 +432,9 @@ class Index extends Component {
}
this.handleDeleteDeclare(selectedRowKeys);
break;
case"5":
this.setState({ confirmationDialog: { ...confirmationDialog, visible: true } });
break;
default:
break;
}
@ -463,7 +469,7 @@ class Index extends Component {
render() {
const {
selectedKey, showSearchAd, declareStatus, declareStatusList, taxCycle, declareEditDialog, loading,
pageInfo, adConditons, employmentTypeList, employmentStatusList, azOperate
pageInfo, adConditons, employmentTypeList, employmentStatusList, azOperate, confirmationDialog
} = this.state;
const {
taxAgentStore: { showOperateBtn, isTaxDeclareAdmin }, employeeDeclareStore: { advanceForm: form, declareForm }
@ -474,6 +480,7 @@ class Index extends Component {
{/*<Menu.Item key="2">{getLabel(111, "批量编辑")}</Menu.Item>*/}
{/*<Menu.Item key="3">{getLabel(81272, "导出全部")}</Menu.Item>*/}
{/*<Menu.Item key="4">{getLabel(543715, "导出所选")}</Menu.Item>*/}
<Menu.Item key="5">{getLabel(111, "扣除名单确认")}</Menu.Item>
</Menu>
);
const buttons = [
@ -492,7 +499,11 @@ class Index extends Component {
loading={loading.refresh}>{getLabel(111, "刷新数据")}</Button>,
<Dropdown overlay={menu}>
<Button type="ghost" icon="ellipsis" className="moreBtn"/>
</Dropdown>
</Dropdown>,
<DeductionListConfirmDialog {...confirmationDialog} year={moment(taxCycle).format("YYYY")}
onCancel={() => this.setState({
confirmationDialog: { ...confirmationDialog, visible: false }
})}/>
];
const topTab = [
{ title: getLabel(332, "全部"), viewcondition: "list" },

View File

@ -207,3 +207,32 @@
}
}
}
//扣除名单确认
.confirmationDialog {
.title-right {
text-align: right;
button {
margin-left: 10px;
}
}
.confirmationDialogContent {
width: 100%;
height: 100%;
background: #f6f6f6;
padding: 8px 16px;
.tableBtns {
display: grid;
grid-template-columns: auto auto;
justify-content: end;
gap: 10px;
}
.wea-new-table {
background: #FFF;
}
}
}

View File

@ -41,6 +41,10 @@
.baseSettingWrapper {
padding: 12px 12px 12px 20px;
.wea-form-item-wrapper {
display: inline-block !important;
}
.baseSettingLeft {
border: 1px solid #ebedf0;
padding: 0 !important;

View File

@ -46,7 +46,7 @@ class LedgerSalaryItemBaseInfo extends Component {
};
handleDeleteEmplist = (item) => {
const { dataSource, onChangeSortableList } = this.props;
onChangeSortableList(_.xorWith(dataSource, [item], _.isEqual));
onChangeSortableList(_.filter(dataSource, o => o.id !== item.id));
};
render() {

View File

@ -182,7 +182,7 @@ class LedgerSalaryItemNormal extends Component {
>
<LedgerSalaryItemTable
tableData={items}
dataSource={_.find(newDateSource, childItem => childItem.uuid === uuid).items}
dataSource={_.find(dataSource, childItem => childItem.uuid === uuid).items}
salarySobId={editId || saveSalarySobId}
selectedRowKeys={field.selectedRowKeys || []}
onDropCategoryItem={(data) => onDropCategoryItem(field, data)}

View File

@ -53,6 +53,10 @@ class Index extends Component {
} = payrollTempForm.getFormParams(),
{ ackFeedbackStatus, feedbackStatus, autoAckDays, ...extraFb } = payrollTempFeedbackForm.getFormParams(),
{ formData, smsSettingDialog } = this.tmpBaseSetRef.state;
if (autoSendStatus !== "1" && emailStatus !== "1" && msgStatus !== "1" && smsStatus !== 1) {
message.warning(getLabel(111, "工资单模板至少开启一个发送通道"));
return;
}
const payload = {
...toJS(tmplDataSource), ...extraFb, ...formData, ...extraBs,
ackFeedbackStatus: ackFeedbackStatus === "1",

View File

@ -20,6 +20,10 @@
}
}
.wea-new-top-req {
z-index: 0 !important;
}
.wea-new-top-req-wapper .wea-new-top-req-title > div:last-child {
right: 16px;
}

View File

@ -193,7 +193,16 @@ export const conditions = [
conditionType: "SWITCH",
domkey: ["SHOT_EMP_BTN"],
fieldcol: 10,
label: "启用组织快照",
label: "启用人事信息快照",
lanId: 111,
labelcol: 8,
viewAttr: 2
},
{
conditionType: "SWITCH",
domkey: ["SALARY_ACCT_SYNC_TYPE"],
fieldcol: 10,
label: "是否采用线程池",
lanId: 111,
labelcol: 8,
viewAttr: 2

View File

@ -25,8 +25,8 @@ export const renderRuleForm = (form, condition, onChange) => {
tipPosition="bottom">
<WeaSwitch
fieldConfig={fields} form={form} formParams={formParams}
onChange={v => getKey(fields) !== "salaryAcctFixedColumns" && onChange(v)}
onBlur={(v) => getKey(fields) === "salaryAcctFixedColumns" && onChange({ salaryAcctFixedColumns: { value: v } })}
onChange={v => !["INPUT", "INPUTNUMBER", "TEXTAREA"].includes(fields.conditionType) && onChange(v)}
onBlur={v => ["INPUT", "INPUTNUMBER", "TEXTAREA"].includes(fields.conditionType) && onChange({ [getKey(fields)]: { value: v } })}
/>
</WeaFormItem>),
colSpan: 1,

View File

@ -104,7 +104,7 @@ class RuleConfig extends Component {
form.updateFields({ [item]: { value: sysinfo[item] === "0" ? "0" : (sysinfo[item] || "0") } });
} else if (item === "taxAgentShowStatus" || item === "salaryShowStatus" || item === "adjustShowStatus") {
form.updateFields({ [item]: { value: sysinfo[item] || "1" } });
} else if (item === "OPEN_APPLICATION_ENCRYPT") {
} else if (item === "OPEN_APPLICATION_ENCRYPT" || item === "SALARY_ACCT_SYNC_TYPE") {
form.updateFields({ [item]: { value: _.isNil(sysinfo[item]) ? "1" : (sysinfo[item] || "") } });
} else if (
item === "APPROVAL_CAN_MANUAL_FILE_STATUS" || item === "APPROVAL_CAN_RE_CALC_STATUS" || item === "APPROVAL_CAN_EDIT_RESULT_STATUS"
@ -163,6 +163,7 @@ class RuleConfig extends Component {
case "ATTENDANCE_SERIAL_COLLECTION_BTN":
case "TAX_DECLARATION_DATE_TYPE":
case "SHOT_EMP_BTN":
case "SALARY_ACCT_SYNC_TYPE":
if (!this.handleDebounce) {
this.handleDebounce = _.debounce(() => {
const confTitle = {
@ -183,6 +184,7 @@ class RuleConfig extends Component {
ATTENDANCE_SERIAL_COLLECTION_BTN: getLabel(111, "考勤引用是否采集班次数据"),
TAX_DECLARATION_DATE_TYPE: getLabel(111, "申报日期类型"),
SHOT_EMP_BTN: getLabel(111, "启用组织快照"),
SALARY_ACCT_SYNC_TYPE: getLabel(111, "是否采用线程池")
};
this.unifiedSettings(key, confTitle[key]);
this.handleDebounce = null;

View File

@ -200,6 +200,7 @@
border: 1px solid #e5e5e5 !important;
padding: 4px 8px !important;
min-height: 70px !important;
word-wrap: break-word;
}
}
}

View File

@ -103,6 +103,14 @@
}
.welfare-plan-edit-layout {
.ant-table-content {
padding-left: 208px !important;
.ant-table-fixed-left {
top: 1px;
}
}
.flex-center {
display: flex;
align-items: center;

View File

@ -96,7 +96,9 @@ class Index extends Component {
<ImportDialog
{...this.props} {...importDialog}
onResetImportResult={() => this.setState({
importDialog: { ...importDialog, importResult: {}, imageId: "", link: null }
importDialog: {
...importDialog, importResult: {}, imageId: "", link: "/api/bs/hrmsalary/variableSalary/downloadTemplate"
}
})}
importParams={this.renderFormComponent()}
exportDataDom={

View File

@ -10,12 +10,9 @@ const getLabel = WeaLocaleProvider.getLabel;
export class BaseFormStore {
@observable form = new WeaForm(); // 规则渲染form
@observable logStore = new LogStore();
@observable condition = []; // 存储后台得到的form数据
@observable saveLoading = false; // 保存状态处理:保证保存的时候接口只走一次
@observable loading = true; // 页面初始化的loading状态数据加载成功前后前使用
@observable hasRight = true; // 判断用户是有权限查看当前页面: 没有权限渲染无权限页面,有权限渲染数据
@action("初始化form表单") initForm = () => this.form = new WeaForm();
@observable formExtra = new WeaForm(); // 规则渲染form
@action("初始化form表单") initFormExtra = () => this.formExtra = new WeaForm();
@observable logVisible = false; // 控制日志弹框的显影
@action // 初始化操作: 一般用来初始化获取后台数据