diff --git a/pc4mobx/hrmSalary/apis/welfareArchive.js b/pc4mobx/hrmSalary/apis/welfareArchive.js index a38f22ce..e86e909e 100644 --- a/pc4mobx/hrmSalary/apis/welfareArchive.js +++ b/pc4mobx/hrmSalary/apis/welfareArchive.js @@ -13,6 +13,10 @@ export const getCondition = params => { export const queryList = (params) => { return postFetch("/api/bs/hrmsalary/archives/getTable", params); }; +//社保福利档案_非系统人员列表 +export const getExtTable = (params) => { + return postFetch("/api/bs/hrmsalary/archives/getExtTable", params); +}; //社保福利档案列表 export const queryInsuranceTabTotal = (params) => { return WeaTools.callApi("/api/bs/hrmsalary/archives/queryInsuranceTabTotal", params); diff --git a/pc4mobx/hrmSalary/components/importDialog/components/impStep1.js b/pc4mobx/hrmSalary/components/importDialog/components/impStep1.js new file mode 100644 index 00000000..6ab09b3e --- /dev/null +++ b/pc4mobx/hrmSalary/components/importDialog/components/impStep1.js @@ -0,0 +1,87 @@ +/* + * Author: 黎永顺 + * name: 导入-步骤一 + * Description: + * Date: 2023/8/11 + */ +import React, { Component } from "react"; +import { WeaLocaleProvider } from "ecCom"; +import { Icon, message, Upload } from "antd"; + +const Dragger = Upload.Dragger; +const { getLabel } = WeaLocaleProvider; + +class ImpStep1 extends Component { + constructor(props) { + super(props); + this.state = { + fileList: [] + }; + } + + handleChange = (data) => { + const { fileList, file } = data; + if (file.response && typeof (file.response) != "undefined" && file.status !== "removed") message.success(getLabel(111, "上传成功")); + this.setState({ fileList: fileList.slice(-1) }); + }; + + render() { + const { fileList } = this.state; + const dragger = { + accept: ".xlsx", + name: "file", + multiple: false, + action: "/api/doc/upload/uploadFile", + fileList, + onChange: this.handleChange + }; + return ( +
+ {/* 导入选项 */} + { + this.props.importParams && +
+
{getLabel(543201, "导入选项")}
+ {this.props.importParams} +
+ } +
{getLabel(543202, "导入Excel")}
+

+ +

+

+

{getLabel(543203, "点击或将文件拖拽到此区域上传")}

+

{getLabel(543204, "支持单个或批量上传,严禁上传公司内部资料及其他违禁文件")}

+
+ +

+ +
+
{getLabel(27577, "操作步骤")}
+

+ {`1. ${getLabel(30907, "第一步")},${getLabel(543205, "请选择导出的Excel文件或")}`}   + {getLabel(543207, "点击这里下载模板")}   + {this.props.exportDataDom} +

+

{`2. ${getLabel(543211, "第二步")},${getLabel(543212, "请一定要确定Excel文档中的格式是模板中的格式")},${getLabel(543213, "没有被修改掉")};`}

+

{`3. ${getLabel(543216, "第三步")},${getLabel(543215, "选择填写好的Excel文档")},${getLabel(543214, "点击“下一步”按钮进行数据预览")};`}

+

+ {`4. ${getLabel(543217, "第四步")},${getLabel(543218, "如果以上步骤和Excel文档正确的话")},${getLabel(543219, "导入成功会有提示")},${getLabel(543220, "数据会被正确导入")}。${getLabel(543221, "如果有问题")},${getLabel(543222, "则会提示Excel文档的错误之处")}。`} +

+
+ +
+
{getLabel(543223, "Excel文件说明")}
+

{`1. ${getLabel(543224, "后缀名为xls或者xlsx")};`}

+

{`2. ${getLabel(543225, "数据请勿放在合并的单元格中")};`}

+

{`3. ${getLabel(543226, "账单月份格式必须为")}:YYYY-MM;`}

+
+ +
+ ); + } +} + +export default ImpStep1; diff --git a/pc4mobx/hrmSalary/components/importDialog/components/impStep2.js b/pc4mobx/hrmSalary/components/importDialog/components/impStep2.js new file mode 100644 index 00000000..8a7373d4 --- /dev/null +++ b/pc4mobx/hrmSalary/components/importDialog/components/impStep2.js @@ -0,0 +1,49 @@ +/* + * Author: 黎永顺 + * name: 导入-步骤二 + * Description: + * Date: 2023/9/5 + */ +import React, { Component } from "react"; +import { WeaTable } from "ecCom"; +import { postFetch } from "../../../util/request"; + +class ImpStep2 extends Component { + constructor(props) { + super(props); + this.state = { + loading: false, columns: [], dataSource: [] + }; + } + + componentDidMount() { + this.init(); + } + + init = () => { + const { previewUrl, imageId } = this.props; + const payload = { imageId }; + this.setState({ loading: true }); + postFetch(previewUrl, payload).then(({ status, data }) => { + this.setState({ loading: false }); + if (status) { + const { headers, list } = data; + this.setState({ + columns: _.map(headers, (item, index) => ({ title: item, dataIndex: index + "", width: 120 })), + dataSource: _.map(list, item => { + return _.reduce(item, (pre, cur, key) => (_.assign(pre, { [key]: cur })), {}); + }) + }); + } + }).catch(() => this.setState({ loading: false })); + }; + + render() { + const { dataSource, columns, loading } = this.state; + return ( + + ); + } +} + +export default ImpStep2; diff --git a/pc4mobx/hrmSalary/components/importDialog/components/impStep3.js b/pc4mobx/hrmSalary/components/importDialog/components/impStep3.js new file mode 100644 index 00000000..481813b4 --- /dev/null +++ b/pc4mobx/hrmSalary/components/importDialog/components/impStep3.js @@ -0,0 +1,51 @@ +/* + * Author: 黎永顺 + * name: 导入-步骤3 + * Description: + * Date: 2023/8/11 + */ +import React, { Component } from "react"; +import { WeaLocaleProvider, WeaTable } from "ecCom"; +import successImg from "../../importModal/success.svg"; + +const getLabel = WeaLocaleProvider.getLabel; + +class ImpStep3 extends Component { + render() { + const { importResult } = this.props; + return ( +
+ { + !_.isEmpty(importResult) ? +
+

+

+ {getLabel(389249, "已导入")} + {importResult.successCount}   + {`${getLabel(30690, "条数据")},${getLabel(25009, "失败")}`} + {importResult.errorCount}  {getLabel(30690, "条数据")} +

+
: +
+

{getLabel(111, "导入失败")}

+
+ } + { + !_.isEmpty(importResult.errorData) && + + } +
+ ); + } +} + +export default ImpStep3; diff --git a/pc4mobx/hrmSalary/components/importDialog/index.js b/pc4mobx/hrmSalary/components/importDialog/index.js new file mode 100644 index 00000000..b7eafd97 --- /dev/null +++ b/pc4mobx/hrmSalary/components/importDialog/index.js @@ -0,0 +1,153 @@ +/* + * Author: 黎永顺 + * name: 导入弹框-步骤条 + * Description: + * Date: 2023/8/11 + */ +import React, { Component } from "react"; +import { Button, message, Modal } from "antd"; +import { WeaDialog, WeaLocaleProvider, WeaSteps } from "ecCom"; +import ImpStep1 from "./components/impStep1"; +import ImpStep2 from "./components/impStep2"; +import ImpStep3 from "./components/impStep3"; +import "./index.less"; + +const { getLabel } = WeaLocaleProvider; +const Step = WeaSteps.Step; + +class Index extends Component { + constructor(props) { + super(props); + this.state = { + current: 0 + }; + } + + componentWillReceiveProps(nextProps, nextContext) { + if (JSON.stringify(nextProps.importResult) !== JSON.stringify(this.props.importResult) && !_.isEmpty(nextProps.importResult)) { + this.setState({ + current: this.state.current + 1 + }); + } + if (nextProps.visible !== this.props.visible && !nextProps.visible) this.setState({ current: 0 }); + } + + renderChildren = () => { + const { current } = this.state; + const { importParams, link, excludeKey, importResult, exportDataDom = null } = this.props; + let CurrentDom = null; + switch (current) { + case 0: + CurrentDom = this.step1Ref = dom}/>; + break; + case 1: + CurrentDom = ; + if (excludeKey) { + CurrentDom = ; + } + break; + case 2: + CurrentDom = ; + break; + default: + CurrentDom = null; + break; + } + return CurrentDom; + }; + /* + * Author: 黎永顺 + * Description: 上一步 + * Params: + * Date: 2023/9/5 + */ + handlePreviousStep = () => { + Modal.confirm({ + title: getLabel(131329, "信息确认"), + content: getLabel(111, "是否放弃已上传的文件?"), + onOk: () => this.setState({ current: this.state.current - 1 }, () => this.props.onResetImportResult()) + }); + }; + /* + * Author: 黎永顺 + * Description: 下一步 + * Params: + * Date: 2023/8/11 + */ + handleNext = () => { + const { params, importResult } = this.props; + if (_.isEmpty(importResult)) { + const { fileList } = this.step1Ref.state; + if (!_.isEmpty(params)) { + if (!Object.values(params).every(o => !!o)) { + Modal.warning({ + title: getLabel(131329, "信息确认"), + content: getLabel(518702, "必要信息不完整,红色*为必填项!") + }); + return; + } + } + if (_.isEmpty(fileList)) { + message.warning(getLabel(111, "请先上传EXCEL文件")); + return; + } + const [file] = fileList; + const { response } = file; + this.props.nextCallback(response.data.fileid); + } else { + this.setState({ current: this.state.current + 1 }); + } + }; + + render() { + const { current } = this.state; + const stepData = [ + { key: 0, label: getLabel(543202, "上传EXCEL") }, + { key: 1, label: getLabel(543200, "数据预览") }, + { key: 2, label: getLabel(502835, "导入数据") } + ]; + const btns = [ + , + , + + ]; + return ( + +
+
+ + {/*this.props.key: 不需要展示的步骤*/} + { + _.map(_.filter(stepData, item => item.key !== this.props.excludeKey), it => ( + )) + } + +
+
+ { + this.renderChildren() + } +
+
+
+ ); + } +} + +export default Index; diff --git a/pc4mobx/hrmSalary/components/importDialog/index.less b/pc4mobx/hrmSalary/components/importDialog/index.less new file mode 100644 index 00000000..95cee40b --- /dev/null +++ b/pc4mobx/hrmSalary/components/importDialog/index.less @@ -0,0 +1,143 @@ +.importBox { + .importCont { + padding: 16px 8px; + + .weapp-batch-impsteps-picker-content-imp-steps { + width: 80%; + margin: 0 auto; + } + + .weapp-batch-impsteps-picker { + margin: 16px auto; + + .weapp-batch-impsteps-picker-content-imp-step1 { + width: 98%; + background-color: #fff; + margin: 8px auto; + border-radius: 3px; + padding: 1px 12px; + + .weapp-batch-impsteps-picker-content-imp-step1 div { + color: #111; + line-height: 22px; + } + + .weapp-salary-tb-border-bottom .weapp-salary-tb-filter.weapp-salary-import-param { + box-sizing: border-box; + padding: 16px; + height: auto; + flex-wrap: wrap; + width: 100%; + } + + .weapp-salary-import-param { + border: 1px solid #ebedf0; + padding: 8px; + margin: 4px 0 14px; + } + + .weapp-salary-tb-filter { + display: flex; + flex-wrap: wrap; + align-items: center; + height: 46px; + } + + .weapp-salary-tb-border-bottom .weapp-salary-tb-filter.weapp-salary-import-param .tbf-item { + display: flex; + justify-content: flex-start !important; + } + + .weapp-salary-tb-filter .tbf-item { + padding: 0 20px 0 0; + display: flex; + align-items: center; + font-size: 12px; + color: #111; + height: 40px; + } + + .weapp-salary-tb-filter .tbf-item > .tbfi-label { + flex-basis: 100px; + flex-shrink: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + padding-right: 10px; + color: #666; + } + + .draggerUploadWrapper { + margin: 16px 0 0; + + .ant-upload-drag-container { + padding: 24px 0 16px; + + .iconUpload { + i { + color: #5d9cec; + font-size: 43px; + } + } + + .uplaod-title { + font-size: 14px; + color: #333; + height: 24px; + line-height: 24px; + margin-top: 8px; + } + + .uplaod-subTitle { + height: 22px; + font-size: 12px; + color: #666; + text-align: center; + line-height: 22px; + } + } + } + + .bottom-border, .description { + margin-top: 12px; + + p { + font-size: 12px; + color: #666; + line-height: 15px; + margin: 12px 0; + } + } + + .bottom-border { + border-bottom: 1px solid #e5e5e5; + + .weapp-salary-link { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: #5d9cec; + } + } + + } + } + + .weapp-batch-impsteps-picker-content-imp-step3 { + .weapp-batch-impsteps-picker-spinText { + position: relative; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + text-align: center; + + p { + margin: 14px 0; + } + } + } + + } +} diff --git a/pc4mobx/hrmSalary/pages/socialSecurityBenefits/archives/config/index.js b/pc4mobx/hrmSalary/pages/socialSecurityBenefits/archives/config/index.js index de89e096..84bcb6ff 100644 --- a/pc4mobx/hrmSalary/pages/socialSecurityBenefits/archives/config/index.js +++ b/pc4mobx/hrmSalary/pages/socialSecurityBenefits/archives/config/index.js @@ -26,5 +26,12 @@ export const tabCondition = [ showcount: true, title: "停缴员工", viewcondition: "stop" - } + }, + { + color: "#000000", + groupid: "ext", + showcount: true, + title: "非系统人员", + viewcondition: "ext" + }, ]; diff --git a/pc4mobx/hrmSalary/pages/socialSecurityBenefits/archives/index.js b/pc4mobx/hrmSalary/pages/socialSecurityBenefits/archives/index.js index cab89a87..4caa10dc 100644 --- a/pc4mobx/hrmSalary/pages/socialSecurityBenefits/archives/index.js +++ b/pc4mobx/hrmSalary/pages/socialSecurityBenefits/archives/index.js @@ -2,7 +2,7 @@ import React from "react"; import { inject, observer } from "mobx-react"; import { toJS } from "mobx"; import { Button, Dropdown, Menu, message, Modal, Popover } from "antd"; -import { WeaHelpfulTip, WeaLocaleProvider, WeaNewScroll, WeaSlideModal, WeaTab, WeaTop } from "ecCom"; +import { WeaCheckbox, WeaHelpfulTip, WeaLocaleProvider, WeaNewScroll, WeaSlideModal, WeaTab, WeaTop } from "ecCom"; import { getSearchs, renderLoading } from "../../../util"; import BaseForm from "./baseForm"; import SlideModalTitle from "../../../components/slideModalTitle"; @@ -14,11 +14,16 @@ import * as API from "../../../apis/welfareArchive"; import ImportModal from "../../../components/importModal"; import TipLabel from "../../../components/TipLabel"; import UnifiedTable from "../../../components/UnifiedTable"; -import { convertToUrlString } from "../../../util/url"; +import { convertToUrlString, getURLParameters } from "../../../util/url"; import { salaryArchiveDelete } from "../../../apis/payrollFiles"; +import ImportDialog from "../../../components/importDialog"; import "./index.less"; const getLabel = WeaLocaleProvider.getLabel; +const APILIST = { + runStatuses: API["queryList"], + extWelArchiveList: API["getExtTable"] +}; @inject("archivesStore", "taxAgentStore") @observer export default class Archives extends React.Component { @@ -46,14 +51,20 @@ export default class Archives extends React.Component { stayAdd: 0, paying: 0, stayDel: 0, - stopPay: 0 + stopPay: 0, + ext: 0 }, pageInfo: { current: 1, pageSize: 10, total: 0 }, - salaryArchiveDelete: "" //待定薪、停薪员工 是否允许删除薪资档案 0: 否, 1: 是 + salaryArchiveDelete: "", //待定薪、停薪员工 是否允许删除薪资档案 0: 否, 1: 是 + importDialog: { + visible: false, title: "", nextloading: false, + link: "", importResult: {}, imageId: "", + previewUrl: "/api/bs/hrmsalary/scheme/preview" + } }; this.record = {}; } @@ -78,7 +89,7 @@ export default class Archives extends React.Component { const formParams = form.getFormParams() || {}; const payload = { ...pageInfo }; this.setState({ loading: { ...loading, query: true } }); - API.queryList({ ...formParams, ...payload, ...params }).then(({ data, status }) => { + APILIST[_.keys(params)[0]]({ ...formParams, ...payload, ...params }).then(({ data, status }) => { this.setState({ loading: { ...loading, query: false } }); if (status) { const { pageInfo: paganition, columns, datas: dataSource } = data; @@ -309,8 +320,19 @@ export default class Archives extends React.Component { // 导入 handleImport = (params) => { const { archivesStore: { importBatch } } = this.props; - const { runStatus } = this.state; - importBatch({ ...params, runStatus }); + const { runStatus, importDialog } = this.state; + this.setState(({ + importDialog: { + ...importDialog, nextloading: true, ...params + } + })); + importBatch({ ...params, runStatus }).then(({ status, data }) => { + this.setState(({ + importDialog: { + ...importDialog, nextloading: false, importResult: data, ...params + } + })); + }); }; // 导入完成 @@ -375,9 +397,12 @@ export default class Archives extends React.Component { case "suspend": this.queryList({ runStatuses: ["3"] }); break; - default: + case "stop": this.queryList({ runStatuses: ["4", "5"] }); break; + default: + this.queryList({ extWelArchiveList: true }); + break; } }; handleMenuBtnClick = () => { @@ -564,13 +589,15 @@ export default class Archives extends React.Component { {/*
4、数据进入【待减员】规则的第四种情况下,若还需要在当前个税扣缴义务人下进行缴纳的话,当前该员工的【待减员】数据进行【删除待办】操作即可;若不在该个税扣缴义务人下继续缴纳,维护好最后缴纳月后进行【减员】操作,员工进入【停缴员工】;
*/} ; break; - default: + case "stop": dom =
1、不需要缴纳社保福利的员工,保存在【停缴员工】;
{/*
2、【停缴员工】点击取消停缴,数据会回退到上次的位置(从【待减员】减员到停缴员工的,点击停缴返回到【在缴员工】,不返回到【待减员】);
*/} {/*
3、若员工的社保福利从一个个税扣缴义务人下转到另一个个税扣缴义务人下去缴纳,则在转后的个税扣缴义务人的【待增员】中进行增员操作成功后,员工进入待【在缴员工】,而在原个税扣缴义务人下的【停缴员工】中,该员工数据将会被删除;是否开启分权员工的档案数据都只保存一份;
*/}
; break; + default: + break; } return dom; }; @@ -584,7 +611,8 @@ export default class Archives extends React.Component { dataSource: dataSourceActive, pageInfo, tabCount, - loading + loading, + importDialog } = this.state; const { form, condition, showSearchAd, setShowSearchAd, @@ -719,7 +747,7 @@ export default class Archives extends React.Component { } type="ghost"> 导出全部 - ] : [ + ] : selectedKey === "stop" ? [ } @@ -733,6 +761,15 @@ export default class Archives extends React.Component { } type="ghost"> 导出全部 + ] : [ ]; const pagination = { @@ -775,6 +812,7 @@ export default class Archives extends React.Component { keyParam="viewcondition" //主键 selectedKey={selectedKey} onChange={this.handleChangeTab} + autoCalculateWidth searchType={["base", "advanced"]} // base:基础搜索框 advanced:显示高级搜索按钮 showSearchAd={showSearchAd} // 是否展开高级搜索面板 setShowSearchAd={bool => setShowSearchAd(bool)} //高级搜索面板受控 @@ -807,7 +845,7 @@ export default class Archives extends React.Component { xWidth={this.getColumns().length * 120} /> { - !_.isEmpty(this.getColumns()) && + !_.isEmpty(this.getColumns()) && selectedKey !== "ext" && {this.getTipChildren()} } @@ -878,6 +916,36 @@ export default class Archives extends React.Component { this.setState({ selectedTab: "0" }); })}/> } + this.setState({ + importDialog: { + ...importDialog, + visible: false, title: "", nextloading: false, + link: "", importResult: {}, imageId: "" + } + }, () => isFresh && this.query())} + onResetImportResult={() => this.setState(({ + importDialog: { ...importDialog, importResult: {}, imageId: "" } + }))} + exportDataDom={ + { + const formParams = form.getFormParams() || {}; + const payload = { exportData: val === "1", ...formParams }; + this.setState(({ + importDialog: { + ...importDialog, + link: `/api/bs/hrmsalary/scheme/template/export?extWelArchiveList=true&${convertToUrlString(payload)}` + } + })); + }} + /> + } + nextCallback={imageId => this.handleImport({ imageId })} + /> { this.state.importVisible && { diff --git a/pc4mobx/hrmSalary/pages/socialSecurityBenefits/standingBookDetail/components/index.less b/pc4mobx/hrmSalary/pages/socialSecurityBenefits/standingBookDetail/components/index.less index 7bb28208..0481abfb 100644 --- a/pc4mobx/hrmSalary/pages/socialSecurityBenefits/standingBookDetail/components/index.less +++ b/pc4mobx/hrmSalary/pages/socialSecurityBenefits/standingBookDetail/components/index.less @@ -4,10 +4,6 @@ height: 100%; background: #f6f6f6; - .wea-new-top-req-wapper .wea-new-top-req-main { - background: #f6f6f6 !important; - } - .wea-new-top-req-wapper .wea-new-top-req { z-index: 0 !important; } diff --git a/pc4mobx/hrmSalary/stores/archives.js b/pc4mobx/hrmSalary/stores/archives.js index 56bd3b12..383e585d 100644 --- a/pc4mobx/hrmSalary/stores/archives.js +++ b/pc4mobx/hrmSalary/stores/archives.js @@ -336,7 +336,7 @@ export class ArchivesStore { API.importBatch(params).then(res => { if (res.status) { this.importResult = res.data; - resolve(); + resolve(res); } else { message.error(res.errormsg || "导入失败", 1); reject(); diff --git a/pc4mobx/hrmSalary/util/url.js b/pc4mobx/hrmSalary/util/url.js index a69b4f81..d2802383 100644 --- a/pc4mobx/hrmSalary/util/url.js +++ b/pc4mobx/hrmSalary/util/url.js @@ -1,11 +1,10 @@ -// export const getQueryString = (name) => { -// let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); -// let r = window.location.hash.split("?")[1].match(reg); -// if (r != null) { -// return decodeURIComponent(r[2]); -// }; -// return null; -// } +export const getURLParameters = (url) => + (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce( + (a, v) => ( + (a[v.slice(0, v.indexOf("="))] = v.slice(v.indexOf("=") + 1)), a + ), + {} + ); export const getQueryString = (variable) => { let split = window.location.hash.split("?");