1、薪资核算新增环比上月数据

2、核算归档后依旧可查看上月环比数据界面
3、个税申报表批量多选申报【现阶段仅能选择一个个税扣缴义务人来生成申报表】
4、个税申报表增加一个 批量撤回按钮 【跳出一个界面选择 与申报界面一致,可批量选择个税扣缴义务人与薪资所属月来进行批量撤回】
5、薪资核算界面内增加搜索个税扣缴义务人。以及搜索归档与未归档的核算。(按状态筛选)
6、薪资核算时,二级部门需与员工的一级部门进行对应【现阶段员工二级部门由导入与sql自动带出两个方式,若为员工手动导入,则需审核】图2为对应表
This commit is contained in:
鱼不吐泡泡 2026-02-11 11:16:02 +08:00
parent 11ac14d440
commit 1c4633a1c0
16 changed files with 370 additions and 484 deletions

View File

@ -291,4 +291,8 @@ export const updateSobConfig = params => {
return WeaTools.callApi("/api/bs/hrmsalary/salaryacct/updateSobConfig", "GET", params);
};
// 2025-12-11 核算人员--环比上月实发工资差额列表
export const getGzceList = params => {
return postFetch("/api/bs/hrmsalary/salaryacct/getGzceList/list", params);
};

View File

@ -39,3 +39,8 @@ export const withDrawTaxDeclaration = (params) => {
};
//个税申报表-批量撤回申报
export const batchDeleteTaxDeclaration = (params) => {
return postFetch("/api/bs/hrmsalary/taxdeclaration/batchDeleteTaxDeclaration", params);
};

View File

@ -6,10 +6,11 @@
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaLocaleProvider, WeaTop } from "ecCom";
import { Dropdown, Menu, message } from "antd";
import { WeaLocaleProvider, WeaTop, WeaReqTop } from "ecCom";
import {Button, Dropdown, Menu, message} from "antd";
import Layout from "../doCalc/layout";
import SalaryEditCalc from "../doCalc/components/salaryEditCalc";
import SalaryCalcPersonConfirm from "../doCalc/components/salaryCalcPersonConfirm";
import AdvanceInputBtn from "../doCalc/components/advanceInputBtn";
import { convertToUrlString } from "../../../util/url";
import { getExportField } from "../../../apis/calculate";
@ -24,6 +25,7 @@ class Index extends Component {
constructor(props) {
super(props);
this.state = {
selectedKey: "person",
showChildren: false,
customExpDialog: { visible: false, salaryAcctRecordId: "", checkItems: [], itemsByGroup: [] }
};
@ -67,9 +69,50 @@ class Index extends Component {
break;
}
};
renderReqBtns = () => {
const { selectedKey} = this.state;
let reqBtns = [];
switch (selectedKey) {
case "calc":
reqBtns = [
<Dropdown.Button type="primary" style={{ marginRight: "10px" }}
onClick={() => this.handleMenuClick({ key: "exportAll" })}
overlay={<Menu onClick={(e) => this.handleMenuClick(e)}>
<Menu.Item key="export_selected">{getLabel(543715, "导出所选")}</Menu.Item>
<Menu.Item key="export_custom">{getLabel(544270, "自定义导出")}</Menu.Item>
</Menu>}>{getLabel(81272, "")}</Dropdown.Button>,
<AdvanceInputBtn onOpenAdvanceSearch={() => this.calc.openAdvanceSearch()}
onAdvanceSearch={() => this.calc.onAdSearch(false)}
/>
];
break;
default:
break;
}
return reqBtns;
};
renderContent = () => {
const { selectedKey } = this.state;
let dom = null;
switch (selectedKey) {
case "person":
dom = <SalaryCalcPersonConfirm calcDetail={false} readOnly={true} {...this.props}/>;
break;
case "calc":
dom = <SalaryEditCalc {...this.props} calcDetail={false} ref={dom => this.calc = dom}/>;
break;
default:
break;
}
return dom;
};
render() {
const { showChildren, customExpDialog } = this.state;
const tabs = [
{ key: "person", title: getLabel(543547, "人员确认") },
{ key: "calc", title: getLabel(538011, "薪资核算") }
];
const { calculateStore: { setOtherConditions } } = this.props;
const { showChildren, customExpDialog,selectedKey} = this.state;
const btns = [
<Dropdown.Button type="primary" style={{ marginRight: "10px" }}
onClick={() => this.handleMenuClick({ key: "exportAll" })}
@ -83,11 +126,14 @@ class Index extends Component {
];
return (
<Layout {...this.props} init={this.init}>
<WeaTop title={getLabel(111, "薪资核算详情")} icon={<i className="icon-coms-fa"/>} iconBgcolor="#F14A2D"
showDropIcon={false} buttons={btns}
>
<div className="salary-calculate-view">
{showChildren && <SalaryEditCalc {...this.props} calcDetail ref={dom => this.calc = dom}/>}
<div className="salary-calculate-do-calc">
<WeaReqTop
title={getLabel(111, "薪资核算详情")} tabDatas={tabs} selectedKey={selectedKey}
buttonSpace={10} icon={<i className="icon-coms-fa"/>} iconBgcolor="#F14A2D"
onChange={key => this.setState({ selectedKey: key }, () => setOtherConditions([]))}
buttons={this.renderReqBtns()}
>
<div className="salary-calculate-view">{this.renderContent()}</div>
{/* 薪资核算-自定义导出*/}
<CustomCalcExportDialog
{...customExpDialog}
@ -97,8 +143,8 @@ class Index extends Component {
});
}}
/>
</div>
</WeaTop>
</WeaReqTop>
</div>
</Layout>
);
}

View File

@ -1,8 +1,28 @@
.salary-calculate-view {
.salary-calculate-do-calc {
min-width: 1000px;
overflow: auto;
width: 100%;
height: 100%;
background-color: #f1f1f1;
position: relative;
z-index: 0;
padding: 8px 16px;
background: #f6f6f6;
.icon-jinggao {
color: red;
font-size: 20px;
margin-right: 10px;
cursor: pointer;
}
.wea-new-top-req {
z-index: 0 !important;
}
.wea-new-top-req-wapper .wea-new-top-req-title > div:last-child {
right: 16px;
}
.salary-calculate-view {
padding: 8px 16px;
height: 100%;
}
}

View File

@ -6,8 +6,7 @@
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaLocaleProvider, WeaTools, WeaTop } from "ecCom";
import { WeaForm } from "comsMobx";
import { WeaLocaleProvider, WeaTop } from "ecCom";
import { Button, message, Modal } from "antd";
import moment from "moment";
import CalculateQuery from "./components/calculateQuery";
@ -16,15 +15,9 @@ import CalculateDialog from "./components/calculateDialog";
import ProgressModal from "../../components/progressModal";
import LogDialog from "../../components/logViewModal";
import { backCalculate, deleteSalaryacct, fileSalaryAcct, reAccounting } from "../../apis/calculate";
import FormInfo from "../../components/FormInfo";
import { queryConditions } from "./config";
import { postFetch } from "../../util/request";
import cs from "classnames";
import "./index.less";
const getKey = WeaTools.getKey;
const getLabel = WeaLocaleProvider.getLabel;
const form = new WeaForm();
@inject("calculateStore", "taxAgentStore")
@observer
@ -37,33 +30,19 @@ class Calculate extends Component {
dateRange: [
moment(new Date()).subtract(1, "year").startOf("year").format("YYYY-MM"),
moment(new Date()).endOf("year").format("YYYY-MM")
]
}, isRefresh: false, logDialogVisible: false, conditions: [],
],
status:"",
}, isRefresh: false, logDialogVisible: false,
progressModule: { visible: false, progress: 0, title: getLabel(111, "正在归档中请稍后") },
calcDaialog: { visible: false, title: "" }, showAdvance: false
calcDaialog: { visible: false, title: "" }
};
this.timer = null;
this.handleDebounce = null;
}
async componentDidMount() {
const { data } = await postFetch("/api/bs/hrmsalary/taxAgent/listAuth", { filterType: "QUERY_DATA" });
this.setState({
conditions: _.map(queryConditions, item => ({
...item, items: _.map(item.items, o => {
o = { ...o, label: getLabel(o.lanId, o.label) };
if (getKey(o) === "taxAgentIds") {
return { ...o, options: _.map(data, k => ({ key: k.id + "", showname: k.name })) };
}
return { ...o };
})
}))
}, () => form.initFormFields(this.state.conditions));
}
renderCalculateOpts = () => {
const { taxAgentStore: { PageAndOptAuth } } = this.props;
const { queryParams, isRefresh, showAdvance } = this.state;
const { queryParams, isRefresh } = this.state;
const admin = PageAndOptAuth.opts.includes("admin");
let calculateOpts = [
<Button type="primary" onClick={() => this.setState({
@ -72,11 +51,10 @@ class Calculate extends Component {
title: getLabel(538780, "核算")
}
})}>{getLabel(538780, "核算")}</Button>,
<CalculateQuery queryParams={queryParams} onAdvance={() => this.setState({ showAdvance: !showAdvance })}
onChange={v => this.setState({
isRefresh: _.keys(v)[0] === "name" ? isRefresh : !isRefresh,
queryParams: { ...queryParams, ...v }
})} onSearch={() => this.setState({ isRefresh: !isRefresh })}/>
<CalculateQuery queryParams={queryParams} onChange={v => this.setState({
isRefresh: _.keys(v)[0] === "name" ? isRefresh : !isRefresh,
queryParams: { ...queryParams, ...v }
})} onSearch={() => this.setState({ isRefresh: !isRefresh })}/>
];
return !admin ? calculateOpts.slice(1) : calculateOpts;
};
@ -212,9 +190,7 @@ class Calculate extends Component {
};
render() {
const {
queryParams, isRefresh, calcDaialog, progressModule, logDialogVisible, filterConditions, conditions, showAdvance
} = this.state;
const { queryParams, isRefresh, calcDaialog, progressModule, logDialogVisible, filterConditions } = this.state;
return (
<WeaTop title={getLabel(538011, "薪资核算")} icon={<i className="icon-coms-fa"/>} iconBgcolor="#F14A2D"
buttons={this.renderCalculateOpts()} className="calculate-main-layout" showDropIcon
@ -226,18 +202,7 @@ class Calculate extends Component {
}
]}>
<div className="calculate-body">
<div className={cs("advance-calc", { "show-advance-calc": showAdvance })}>
<FormInfo center={false} itemRender={{}} form={form} formFields={conditions} colCount={2}/>
<div className="advance-calc-btns">
<Button type="primary"
onClick={() => this.setState({ isRefresh: !isRefresh })}>{getLabel(111, "搜索")}</Button>
<Button type="ghost" onClick={() => form.resetForm()}>{getLabel(111, "重置")}</Button>
<Button type="ghost"
onClick={() => this.setState({ showAdvance: !showAdvance })}>{getLabel(111, "取消")}</Button>
</div>
</div>
<CalculateTablelist form={form} queryParams={queryParams} isRefresh={isRefresh}
onCalcOpts={this.handleCalcOpts}/>
<CalculateTablelist queryParams={queryParams} isRefresh={isRefresh} onCalcOpts={this.handleCalcOpts}/>
<CalculateDialog {...calcDaialog}
onCancel={(bool, id) => this.setState({
calcDaialog: { ...calcDaialog, visible: false },

View File

@ -5,7 +5,7 @@
* Date: 2023/10/9
*/
import React, { Component } from "react";
import { WeaInputSearch, WeaLocaleProvider } from "ecCom";
import {WeaInputSearch, WeaLocaleProvider, WeaSelect} from "ecCom";
import { MonthRangePicker } from "../../../reportView/components/statisticalMicroSettingsSlide";
const getLabel = WeaLocaleProvider.getLabel;
@ -13,7 +13,7 @@ const getLabel = WeaLocaleProvider.getLabel;
class Index extends Component {
render() {
const { queryParams } = this.props;
const { dateRange, name } = queryParams;
const { dateRange, name, status } = queryParams;
return (
<div className="salary-btn-flex">
<div className="mounth-range">
@ -21,14 +21,21 @@ class Index extends Component {
<MonthRangePicker dateRange={dateRange} viewAttr={2}
onChange={v => this.props.onChange({ dateRange: v })}/>
</div>
<div className="advance-custom">
<WeaInputSearch value={name}
placeholder={getLabel(543431, "请输入薪资账套名称")}
onChange={v => this.props.onChange({ name: v })}
onSearch={this.props.onSearch}
/>
<a href="javascript:void(0);" onClick={this.props.onAdvance}>{getLabel(111, "高级搜索")}</a>
<div>
<span>状态</span>
<WeaSelect
className='status'
style={{ width: 100,marginRight: 10}}
onChange={v => this.props.onChange({ status: v })}
viewAttr={2}
value={status}
options={[{"key": "0","selected": true,"showname": ""}, {"key": "1","selected": false,"showname": "未归档"}, {"key": "2","selected": false,"showname": "已归档"}, {"key": "3","selected": false,"showname": "已申报"}]} />
</div>
<WeaInputSearch value={name}
placeholder={getLabel(543431, "请输入薪资账套名称")}
onChange={v => this.props.onChange({ name: v })}
onSearch={this.props.onSearch}
/>
</div>
);
}

View File

@ -29,14 +29,12 @@ class Index extends Component {
}
getSalaryAcctList = (props) => {
const { pageInfo } = this.state, { queryParams, form } = props;
const { taxAgentIds } = form.getFormParams();
const { dateRange, ...extra } = queryParams;
const { pageInfo } = this.state;
const { queryParams } = props;
const { dateRange,status, ...extra } = queryParams;
const [startMonthStr, endMonthStr] = dateRange || [];
const params = { startMonthStr, endMonthStr, ...extra };
const payload = {
...pageInfo, ...params, taxAgentIds: taxAgentIds ? taxAgentIds.split(",") : []
};
const params = { startMonthStr, endMonthStr, status, ...extra };
const payload = { ...pageInfo, ...params };
this.setState({ loading: true });
getSalaryAcctList(payload).then(({ status, data }) => {
this.setState({ loading: false });

View File

@ -15,7 +15,8 @@ import {
deleteAcctemployee,
reducedemployeeList,
refreshAcctemployee,
saveAcctemployee
saveAcctemployee,
getGzceList
} from "../../../../../apis/calculate";
import { personConfirmSearchConditions } from "./condition";
import { getSearchs } from "../../../../../util";
@ -26,7 +27,8 @@ const getLabel = WeaLocaleProvider.getLabel;
const api = {
range: acctemployeeList,
sub: reducedemployeeList,
add: addedemployeeList
add: addedemployeeList,
gzce: getGzceList
};
@inject("calculateStore")
@ -45,9 +47,11 @@ class Index extends Component {
componentDidMount() {
if ($) {
const domTabInnerList = $(".salary-calculate-do-calc-content .ant-tabs-tab-inner");
domTabInnerList[0].setAttribute("title", "");
domTabInnerList[1].setAttribute("title", "");
domTabInnerList[2].setAttribute("title", "");
if (domTabInnerList && domTabInnerList.length > 0){
domTabInnerList[0].setAttribute("title", "");
domTabInnerList[1].setAttribute("title", "");
domTabInnerList[2].setAttribute("title", "");
}
}
this.setState({
searchConditions: _.map(personConfirmSearchConditions, item => {
@ -79,24 +83,34 @@ class Index extends Component {
renderTabBtns = () => {
const { selectedKey, selectedRowKeys } = this.state;
const { calcDetail } = this.props;
const { calcDetail,readOnly } = this.props;
let tabBtns = [];
switch (selectedKey) {
case "range":
tabBtns = [
<WeaButtonIcon buttonType="del" type="primary" title={getLabel(111, "批量删除")}
disabled={_.isEmpty(selectedRowKeys)}
onClick={() => this.handleDeletePCitem()}/>,
<WeaBrowser type={17} title={getLabel(383694, "添加人员")} isSingle={false} customized
onChange={ids => ids && this.handleUserBrowserChange(ids.split(","))}
>
<WeaButtonIcon buttonType="add" type="primary" title={getLabel(1421, "新增")}/>
</WeaBrowser>,
<span className="icon-refresh" onClick={this.handleRefresh}><i
className="icon-coms-Refresh"/></span>,
<Button type="primary" onClick={this.handleExport}>{getLabel(17416, "导出")}</Button>
];
calcDetail && tabBtns.splice(0, 2);
if (readOnly) {
tabBtns = [
<Button type="primary" onClick={this.handleExport}>{getLabel(17416, "导出")}</Button>
];
}
break;
case "gzce":
tabBtns = [
<WeaButtonIcon buttonType="del" type="primary" title={getLabel(111, "批量删除")}
disabled={_.isEmpty(selectedRowKeys)}
onClick={() => this.handleDeletePCitem()}/>,
<WeaBrowser type={17} title={getLabel(383694, "添加人员")} isSingle={false} customized
onChange={ids => ids && this.handleUserBrowserChange(ids.split(","))}
>
<WeaButtonIcon buttonType="add" type="primary" title={getLabel(1421, "新增")}/>
</WeaBrowser>,
<span className="icon-refresh" onClick={this.handleRefresh}><i
className="icon-coms-Refresh"/></span>,
<Button type="primary" onClick={this.handleExport}>{getLabel(17416, "导出")}</Button>
];
calcDetail && tabBtns.splice(0, 2);
break;
case "add":
case "sub":
@ -163,6 +177,9 @@ class Index extends Component {
url = `${window.location.origin}/api/bs/hrmsalary/salaryacct/acctemployee/export?salaryAcctRecordId=${salaryAcctRecordId}&${convertToUrlString(PCSearchForm.getFormParams())}`;
} else if (this.state.selectedKey === "sub") {
url = `${window.location.origin}/api/bs/hrmsalary/salaryacct/reducedemployee/export?salaryAcctRecordId=${salaryAcctRecordId}&${convertToUrlString(PCSearchForm.getFormParams())}`;
// 2025-12-11 by ydh 新增环比上月实发工资差额页签
} else if (this.state.selectedKey === "gzce") {
url = `${window.location.origin}/api/bs/hrmsalary/salaryacct/gzceList/export?salaryAcctRecordId=${salaryAcctRecordId}&${convertToUrlString(PCSearchForm.getFormParams())}`;
} else {
url = `${window.location.origin}/api/bs/hrmsalary/salaryacct/addedemployee/export?salaryAcctRecordId=${salaryAcctRecordId}&${convertToUrlString(PCSearchForm.getFormParams())}`;
}
@ -239,6 +256,11 @@ class Index extends Component {
style={{ marginLeft: 8 }}
/>
</React.Fragment>, viewcondition: "add"
},
{
title: <React.Fragment>
<span>环比上月实发工资差额</span>
</React.Fragment>, viewcondition: "gzce"
}
];
const pagination = {
@ -281,6 +303,27 @@ class Index extends Component {
searchsBaseValue={PCSearchForm.getFormParams().employeeName}
onAdReset={() => PCSearchForm.resetForm()} autoCalculateWidth
/>
{selectedKey === "gzce" && <WeaTable
dataSource={dataSource} loading={loading} rowSelection={calcDetail ? null : rowSelection}
pagination={pagination} scroll={{y: `calc(100vh - 365px)`}} rowKey="id"
columns={[..._.map(columns, item => {
let width = "";
const {dataIndex} = item;
switch (dataIndex) {
case "taxAgentName":
case "departmentName":
width = "15%";
break;
default:
width = "45%";
break;
}
return {...item, width};
})
]}
/>
}
{selectedKey !== "gzce" &&
<WeaTable
dataSource={dataSource} loading={loading} rowSelection={calcDetail ? null : rowSelection}
pagination={pagination} scroll={{ y: `calc(100vh - 365px)` }} rowKey="id"
@ -310,6 +353,7 @@ class Index extends Component {
}
]}
/>
}
</div>
);
}

View File

@ -1,176 +0,0 @@
export const editCalcSearchConditions = [
{
items: [
{
colSpan: 2,
conditionType: "INPUT",
domkey: ["employeeName"],
fieldcol: 12,
label: "姓名",
lanId: 25034,
labelcol: 6,
value: "",
viewAttr: 2
},
{
colSpan: 2,
conditionType: "INPUT",
domkey: ["workcode"],
fieldcol: 12,
label: "工号",
lanId: 1933,
labelcol: 6,
value: "",
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: "164",
viewAttr: 2
},
colSpan: 1,
conditionType: "BROWSER",
domkey: ["subcompanyIds"],
fieldcol: 12,
label: "分部",
lanId: 33553,
labelcol: 6,
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: "57",
viewAttr: 2
},
colSpan: 2,
conditionType: "BROWSER",
domkey: ["departmentIds"],
fieldcol: 12,
label: "部门",
lanId: 27511,
labelcol: 6,
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: "24",
viewAttr: 2
},
colSpan: 2,
conditionType: "BROWSER",
domkey: ["positionIds"],
fieldcol: 12,
label: "岗位",
lanId: 6086,
labelcol: 6,
viewAttr: 2
},
{
colSpan: 2,
conditionType: "SELECT",
domkey: ["statuses"],
fieldcol: 12,
multiple: true,
label: "状态",
lanId: 535101,
labelcol: 6,
options: [],
viewAttr: 2
},
{
colSpan: 2,
conditionType: "CHECKBOX",
domkey: ["consolidatedTaxation"],
fieldcol: 12,
isQuickSearch: false,
label: "合并计税",
labelcol: 6,
viewAttr: 2
}
],
defaultshow: true,
title: "常用条件"
}
];
export const batchUpdateConditions = [
{
items: [
{
colSpan: 1,
conditionType: "INPUT",
domkey: ["salaryItemName"],
fieldcol: 14,
label: "批量编辑项目",
lanId: 111,
labelcol: 6,
value: "",
viewAttr: 1
},
{
colSpan: 1,
conditionType: "INPUTNUMBER",
domkey: ["value"],
fieldcol: 14,
label: "批量编辑为",
lanId: 111,
labelcol: 6,
value: "",
rules: "required",
viewAttr: 3
}
],
defaultshow: true,
title: ""
}
];

View File

@ -1,206 +0,0 @@
/*
* Author: 黎永顺
* name: 薪资核算-高级搜索面板
* Description:
* Date: 2023/9/14
*/
import React, { Component } from "react";
import { WeaFormItem, WeaInput, WeaLocaleProvider, WeaSearchGroup, WeaSelect, WeaTools } from "ecCom";
import { Button, Col, Row } from "antd";
import { inject, observer } from "mobx-react";
import uuidV4 from "uuid/v4";
import { editCalcSearchConditions } from "./condition";
import { getExportField } from "../../../../../apis/calculate";
import { commonEnumList } from "../../../../../apis/ruleconfig";
import { getSearchs } from "../../../../../util";
const getKey = WeaTools.getKey;
const getLabel = WeaLocaleProvider.getLabel;
@inject("calculateStore")
@observer
class EditCalcAdvanceSearchPannel extends Component {
constructor(props) {
super(props);
this.state = {
searchConditions: [], salaryItems: [],
customSearchConditions: [], filterEnum: []
};
}
componentDidMount() {
this.getExportField();
this.getFilterEnumList();
this.setState({
searchConditions: _.map(editCalcSearchConditions, item => {
return {
...item,
items: _.map(item.items, o => {
if (getKey(o) === "statuses") {
return {
...o,
options: [
{ key: "0", showname: getLabel(18883, "试用") }, { key: "1", showname: getLabel(15711, "正式") },
{ key: "2", showname: getLabel(480, "临时") }, { key: "3", showname: getLabel(15844, "试用延期") },
{ key: "4", showname: getLabel(542707, "解雇") }, { key: "5", showname: getLabel(6091, "离职") },
{ key: "6", showname: getLabel(6092, "退休") }
]
};
}
return { ...o };
}),
title: getLabel(32905, "常用条件")
};
})
}, () => {
const { calculateStore: { ECSearchForm } } = this.props;
ECSearchForm.initFormFields(this.state.searchConditions);
});
}
getFilterEnumList = () => {
commonEnumList({ enumClass: "com.engine.salary.enums.common.FilterEnum" })
.then(({ status, data }) => {
if (status) {
this.setState({
filterEnum: _.map(data, item => ({
key: item.value,
showname: item.defaultLabel
}))
});
}
});
};
getExportField = () => {
getExportField({ salaryAcctRecordId: this.props.salaryAcctRecordId })
.then(({ status, data }) => {
if (status) {
const { itemsByGroup } = data;
this.setState({
salaryItems: _.map(itemsByGroup, item => ({
key: item.salarySobItemGroupId.toString(),
label: item.salarySobItemGroupName,
options: _.map(item.salaryItems, o => ({
key: o.salaryItemId.toString(), showname: o.salaryItemName
}))
}))
});
}
});
};
handleAddCustomSearchForm = () => {
const { calculateStore: { setOtherConditions } } = this.props;
const { customSearchConditions, salaryItems, filterEnum } = this.state;
const uuid = uuidV4();
this.setState({
customSearchConditions: [
...customSearchConditions,
{
com: CustomFormFields({
uuid, salaryItems, filterEnum, onDelete: this.handleDelete, onChange: this.handleChange
}),
uuid, itemId: "", filter: "", params: ""
}
]
}, () => {
setOtherConditions(_.map(this.state.customSearchConditions, o => ({
itemId: o.itemId, filter: o.filter, params: o.params
})));
});
};
handleChange = (uuid, params) => {
const { calculateStore: { setOtherConditions } } = this.props;
const { customSearchConditions } = this.state;
this.setState({
customSearchConditions: _.map(customSearchConditions, o => {
if (o.uuid === uuid) {
return { ...o, ...params };
}
return { ...o };
})
}, () => {
setOtherConditions(_.map(this.state.customSearchConditions, o => ({
itemId: o.itemId, filter: o.filter, params: o.params
})));
});
};
handleDelete = (uuid) => {
const { calculateStore: { setOtherConditions } } = this.props;
const { customSearchConditions } = this.state;
this.setState({
customSearchConditions: _.filter(customSearchConditions, o => o.uuid !== uuid)
}, () => {
setOtherConditions(_.map(this.state.customSearchConditions, o => ({
itemId: o.itemId, filter: o.filter, params: o.params
})));
});
};
render() {
const { searchConditions, customSearchConditions } = this.state;
const { calculateStore: { ECSearchForm, setOtherConditions } } = this.props;
return (
<React.Fragment>
<div className="wea-advanced-searchsAd">
{getSearchs(ECSearchForm, searchConditions, 2, false)}
<WeaSearchGroup needTigger showGroup title={getLabel(32843, "其他条件")} items={customSearchConditions}
col={2}/>
<div className="custom-advance-largeSpacing">
<Button className="link" icon="plus"
onClick={this.handleAddCustomSearchForm}>{getLabel(111, "添加搜索条件")}</Button>
</div>
<div className="searchAdvanced-commonSelect">
{/*<Button type="ghost">{getLabel(111, "保存常用筛选")}</Button>*/}
</div>
</div>
<div className="wea-search-buttons">
<div style={{ textAlign: "center" }}>
<span style={{ marginLeft: 15 }}><Button type="primary"
onClick={this.props.onAdSearch}>{getLabel(388113, "搜索")}</Button></span>
<span style={{ marginLeft: 15 }}><Button type="ghost"
onClick={() => {
this.setState({
customSearchConditions: []
}, () => {
ECSearchForm.resetForm();
setOtherConditions([]);
});
}}>{getLabel(2022, "重置")}</Button></span>
<span style={{ marginLeft: 15 }}><Button type="ghost"
onClick={this.props.onToggleSwitch}>{getLabel(31129, "取消")}</Button></span>
</div>
</div>
</React.Fragment>
);
}
}
export default EditCalcAdvanceSearchPannel;
const CustomFormFields = (props) => {
const { uuid, onDelete, salaryItems, filterEnum, onChange } = props;
return <WeaFormItem labelCol={{ span: 0 }} wrapperCol={{ span: 18 }}>
<Row>
<Col span={6} style={{ paddingRight: 10 }}>
<WeaSelect
options={salaryItems} detailtype={5} showSearch optionFilterProp="children"
onChange={v => onChange(uuid, { itemId: v })}
/>
</Col>
<Col span={18}>
<Row>
<Col span={12} style={{ paddingRight: 10 }}>
<WeaSelect options={filterEnum} onChange={v => onChange(uuid, { filter: v })}/>
</Col>
<Col span={12} style={{ position: "relative" }}>
<WeaInput onChange={v => onChange(uuid, { params: v })}/>
<Button
type="ghost" icon="cross" className="formItem-delete" shape="circle"
onClick={() => onDelete(uuid)}
/>
</Col>
</Row>
</Col>
</Row>
</WeaFormItem>;
};

View File

@ -1,7 +1,7 @@
import React from "react";
import { inject, observer } from "mobx-react";
import { Button, DatePicker, Dropdown, Menu, message, Modal, Tag } from "antd";
import { WeaInputSearch, WeaLocaleProvider, WeaNewScroll, WeaTop } from "ecCom";
import {WeaInputSearch, WeaLocaleProvider, WeaNewScroll, WeaSelect, WeaTop} from "ecCom";
import { renderNoright } from "../../util";
import CustomTab from "../../components/customTab";
import moment from "moment";
@ -26,7 +26,7 @@ export default class Calculate extends React.Component {
searchValue: "",
startDate: moment(new Date()).startOf("year").format("YYYY-MM"),
endDate: moment(new Date()).startOf("month").format("YYYY-MM"),
current: 1
current: 1,
};
this.pageInfo = { current: 1, pageSize: 10 };
}
@ -37,7 +37,7 @@ export default class Calculate extends React.Component {
getSalaryAcctList({
name: "",
startMonthStr: this.state.startDate,
endMonthStr: this.state.endDate
endMonthStr: this.state.endDate,
});
}
@ -63,7 +63,7 @@ export default class Calculate extends React.Component {
getSalaryAcctList({
name: this.state.searchValue,
startMonthStr,
endMonthStr
endMonthStr,
});
});
}
@ -263,7 +263,7 @@ export default class Calculate extends React.Component {
name: this.state.searchValue,
startMonthStr: this.state.startDate,
endMonthStr: this.state.endDate,
current: value
current: value,
});
}

View File

@ -24,6 +24,8 @@ export const declareConditions = [
options: [],
rules: "required|string",
viewAttr: 3,
multiple:true,
showSearch:true,
},
{
colSpan: 1,

View File

@ -0,0 +1,45 @@
export const declareConditions = [
{
items: [
{
colSpan: 1,
conditionType: "MONTHPICKER",
domkey: ["salaryMonthStr"],
fieldcol: 14,
label: "薪资所属月",
lanId: 542604,
labelcol: 6,
value: "",
rules: "required|string",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "SELECT",
domkey: ["taxAgentId"],
fieldcol: 14,
label: "个税扣缴义务人",
lanId: 537996,
labelcol: 6,
options: [],
rules: "required|string",
viewAttr: 3,
multiple: true,
showSearch:true,
},
{
colSpan: 1,
conditionType: "INPUT",
domkey: ["description"],
fieldcol: 14,
label: "备注",
lanId: 536726,
labelcol: 6,
value: "",
viewAttr: 2
}
],
defaultshow: true,
title: ""
}
];

View File

@ -0,0 +1,99 @@
/*
* Author: ydh
* name: 个税申报重构- 撤回申报
* Description:
* Date: 2026/01/21
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaDialog, WeaLocaleProvider, WeaTools } from "ecCom";
import { Button, message } from "antd";
import { getSearchs } from "../../../../util";
import {batchDeleteTaxDeclaration, saveDeclare, withDrawTaxDeclaration} from "../../../../apis/declare";
import { declareConditions } from "./condition";
import { postFetch } from "../../../../util/request";
import * as API from "../../../../apis/ruleconfig";
const getKey = WeaTools.getKey;
const getLabel = WeaLocaleProvider.getLabel;
@inject("declareStore")
@observer
class Index extends Component {
constructor(props) {
super(props);
this.state = {
conditions: [], loading: false
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) this.getTaxAgentSelectListAsAdmin(nextProps);
if (nextProps.visible !== this.props.visible && !nextProps.visible) this.props.declareStore.initDeclareForm();
}
getTaxAgentSelectListAsAdmin = async (props) => {
const { data: sysinfo } = await API.sysinfo();
const { declareStore: { declareForm } } = props;
postFetch("/api/bs/hrmsalary/taxAgent/listAuth", { filterType: "ADMIN_DATA" })
.then(({ status, data }) => {
if (status) {
this.setState({
conditions: _.map(declareConditions, item => ({
...item,
items: _.map(item.items, o => {
if (getKey(o) === "taxAgentId") {
return {
...o, label: getLabel(o.lanId, o.label),
options: _.map(data, g => ({ key: String(g.id), showname: g.name }))
};
} else if (getKey(o) === "salaryMonthStr") {
return {
...o,
label: sysinfo["TAX_DECLARATION_DATE_TYPE"] === "1" ? getLabel(111, "税款所属期") : getLabel(111, "薪资所属月")
};
}
return { ...o, label: getLabel(o.lanId, o.label) };
})
}))
}, () => declareForm.initFormFields(this.state.conditions));
}
});
};
// 撤回申报
taxdeclarationDelete = () => {
const { declareStore: { declareForm } } = this.props;
declareForm.validateForm().then(f => {
if (f.isValid) {
const payload = declareForm.getFormParams();
this.setState({ loading: true });
batchDeleteTaxDeclaration({...payload}).then(({ status, errormsg }) => {
if (status) {
message.success(getLabel(505793, "撤回成功"));
this.props.onCancel("refresh");
} else {
message.error(errormsg);
}
});
} else {
f.showErrors();
}
});
};
render() {
const { conditions, loading } = this.state;
const { declareStore: { declareForm } } = this.props;
return (
<WeaDialog
{...this.props} style={{ width: 500, height: 174 }} initLoadCss
buttons={[
<Button type="primary" onClick={this.taxdeclarationDelete} loading={loading}>撤回申报</Button>
]}
>
<div className="declare-dialog-layout">{getSearchs(declareForm, conditions, 1, false)}</div>
</WeaDialog>
);
}
}
export default Index;

View File

@ -12,6 +12,7 @@ import moment from "moment";
import DeclareQuery from "./components/declareQuery";
import DeclareTablelist from "./components/declareTablelist";
import DeclareDialog from "./components/declareDialog";
import DeclareWithDrawDialog from "./components/declareWithDrawDaialog";
import LogDialog from "../../components/logViewModal";
import "./index.less";
@ -31,6 +32,7 @@ class Calculate extends Component {
]
}, isRefresh: false,
declareDaialog: { visible: false, title: "" },
declareWithDrawDaialog: { visible: false, title: "" }, // 撤回申报弹窗
logDialogVisible: false, filterConditions: "[]"
};
this.handleDebounce = null;
@ -53,6 +55,14 @@ class Calculate extends Component {
</div>
}
})}>{getLabel(543618, "生成申报表")}</Button>,
<Button type="primary" onClick={() => this.setState({
declareWithDrawDaialog: {
visible: true,
title: <div style={{ display: "flex", alignItems: "center" }}>
<span style={{ marginRight: 10 }}>撤回申报</span>
</div>
}
})}>批量撤回申报表</Button>,
<DeclareQuery queryParams={queryParams} onChange={v => this.setState({
isRefresh: _.keys(v)[0] === "taxAgentName" ? isRefresh : !isRefresh,
queryParams: { ...queryParams, ...v }
@ -74,7 +84,7 @@ class Calculate extends Component {
};
render() {
const { queryParams, isRefresh, declareDaialog, logDialogVisible, filterConditions } = this.state;
const { queryParams, isRefresh, declareDaialog, declareWithDrawDaialog, logDialogVisible, filterConditions } = this.state;
return (
<WeaTop title={getLabel(543353, "个税申报")} icon={<i className="icon-coms-fa"/>} iconBgcolor="#F14A2D"
buttons={this.renderCalculateOpts()} className="declare-main-layout" showDropIcon
@ -92,6 +102,12 @@ class Calculate extends Component {
isRefresh: bool === "refresh" ? !isRefresh : isRefresh
})}
/>
<DeclareWithDrawDialog {...declareWithDrawDaialog}
onCancel={(bool) => this.setState({
declareWithDrawDaialog: { ...declareWithDrawDaialog, visible: false },
isRefresh: bool === "refresh" ? !isRefresh : isRefresh
})}
/>
{/*操作日志*/}
<LogDialog visible={logDialogVisible} logFunction="taxdecla" filterConditions={filterConditions}
onCancel={() => this.setState({ logDialogVisible: false })}/>

View File

@ -75,6 +75,23 @@
border-radius: 0;
}
.wea-select-input{
height: 30px;
white-space: nowrap;
min-width: 100px;
width: 100%;
display: inline-block;
padding: 4px 17px 4px 4px;
position: relative;
min-height: 30px;
border: 1px solid #d9d9d9;
}
.arrow {
position: absolute;
right: 4px;
top: 8px;
color: #666;
}
.wea-content {
padding: 0;