Merge branch 'release/3.0.0.2502.01-合并业务线' into custom/领悦业务线

# Conflicts:
#	pc4mobx/hrmSalary/components/CustomBrowser/components/associativeSearchMult.js
#	pc4mobx/hrmSalary/layout.js
This commit is contained in:
lys 2025-02-21 17:00:56 +08:00
commit 88f3397ff8
68 changed files with 1668 additions and 597 deletions

View File

@ -0,0 +1,26 @@
import { WeaTools } from "ecCom";
import { postFetch } from "../util/request";
// 推送配置列表
export const getPushSettingList = (params) => {
return postFetch("/api/bs/hrmsalary/push/setting/list", params);
};
// 保存推送配置
export const savePushSetting = (params) => {
return postFetch("/api/bs/hrmsalary/push/setting/save", params);
};
// 删除推送配置
export const deletePushSetting = (params) => {
return WeaTools.callApi("/api/bs/hrmsalary/push/setting/delete", "GET", params);
};
// 推送配置明细列表
export const getPushItemList = (params) => {
return postFetch("/api/bs/hrmsalary/push/item/list", params);
};
// 保存推送配置明细
export const savePushItemList = (params) => {
return postFetch("/api/bs/hrmsalary/push/item/save", params);
};
// 删除推送配置明细
export const deletePushItemList = (params) => {
return WeaTools.callApi("/api/bs/hrmsalary/push/item/delete", "GET", params);
};

View File

@ -142,6 +142,10 @@ export const savePageListSetting = (params) => {
export const savePageListTemplate = (params) => {
return postFetch("/api/bs/hrmsalary/common/pageList/template/save", params);
};
// 薪酬统计报表-导出模板示例下载
export const downloadPageListTemplate = (params) => {
return postExportFetch("/api/bs/hrmsalary/common/pageList/template/file/download", params);
};
//薪酬统计报表-获取页面模板
export const getPageListTemplatelist = (params) => {
return postFetch("/api/bs/hrmsalary/common/pageList/template/list", params);

View File

@ -33,29 +33,33 @@ class AssociativeSearchMult extends Component {
}
}
handleSearch = (value) => {
this.setState({ loading: true });
this.getData(value);
};
handleSearch = (value) => this.getData(value);
getData = (name = "") => {
const { browserConditionParam } = this.props;
const { completeURL, searchParamsKey, convertDatasource, dataParams = {} } = browserConditionParam;
const { browserConditionParam, tags } = this.props;
if (tags) return;
const {
completeURL, filterByName, searchParamsKey, convertDatasource, dataParams = {}
} = browserConditionParam;
if (_.trim(name)) {
postFetch(completeURL, { ...dataParams, [searchParamsKey]: name, current: 1, pageSize: 9999 })
.then(({ status, data }) => {
this.setState({ loading: false });
if (status && data.list) {
this.setState({
data: convertDatasource ? convertDatasource(data.list) : data.list,
activeKey: this.getActiveKey(convertDatasource ? convertDatasource(data.list) : data.list)
});
} else {
this.setState({
data: _.map(data, o => ({ ...o, id: String(o.id), name: o.name })),
activeKey: this.getActiveKey(data)
});
}
});
let payload = { ...dataParams };
searchParamsKey && (payload = { ...payload, [searchParamsKey]: name, current: 1, pageSize: 9999 });
this.setState({ loading: true });
postFetch(completeURL, payload).then(({ status, data }) => {
this.setState({ loading: false });
if (status && data.list) {
this.setState({
data: convertDatasource ? convertDatasource(data.list) : data.list,
activeKey: this.getActiveKey(convertDatasource ? convertDatasource(data.list) : data.list)
});
} else {
this.setState({
data: filterByName ? _.filter(_.map(data, o => ({
...o, id: String(o.id), name: o.name
})), k => k.name.indexOf(name) !== -1) : _.map(data, o => ({ ...o, id: String(o.id), name: o.name })),
activeKey: this.getActiveKey(data)
});
}
});
} else {
this.setState({ data: [], loading: false, activeKey: "" });
}
@ -100,7 +104,7 @@ class AssociativeSearchMult extends Component {
render() {
const { data, dropdownWidth } = this.state;
const { viewAttr, selectedValues, datas, isSingle, browserConditionParam = {} } = this.props;
const { viewAttr, selectedValues, datas, isSingle, browserConditionParam = {}, tags } = this.props;
const clsname = classNames({
"required": (viewAttr === 3 || viewAttr === "3") && _.isEmpty(selectedValues),
"mr12": viewAttr === "3" && _.isEmpty(selectedValues),
@ -122,7 +126,7 @@ class AssociativeSearchMult extends Component {
);
}
let options = data.map(d => <Option key={d.id} title={d.name}>{d.name}</Option>);
selectedValues && selectedValues.map((v) => {
!tags && selectedValues && selectedValues.map((v) => {
v && options.unshift(<Option key={v} title={datas[v].name}>{datas[v].name}</Option>);
});
const select = <Select

View File

@ -63,6 +63,8 @@ class CustomBrowserDialog extends Component {
listDatas: convertDatasource ? convertDatasource(data.list) : data.list,
pageInfo: { ...pageInfo, current, pageSize, total }
});
} else if (status && data.modeList) {
this.setState({ listDatas: _.map(data.modeList, o => ({ ...o, id: o.name })) });
} else {
this.setState({ listDatas: _.map(data, o => ({ ...o, id: String(o.id) })) });
}

View File

@ -97,17 +97,11 @@ class Index extends Component {
}, () => {
this.props.onChange && this.props.onChange(values.join(","));
this.props.onCustomChange && this.props.onCustomChange(this.state.selectedData);
if (form) {
form.updateFields({
[getKey(fieldConfig)]: { value: this.state.searchKeys.join(",") }
});
}
if (form) form.updateFields({ [getKey(fieldConfig)]: { value: this.state.searchKeys.join(",") } });
});
};
onBrowerClick = (keys, selectedObj) => {
if (_.isEmpty(keys)) {
this.setState({ searchKeys: [], selectedData: {}, rightDatas: [] });
}
if (_.isEmpty(keys)) this.setState({ searchKeys: [], selectedData: {}, rightDatas: [] });
this.setState({ browserDialog: { visible: true } });
};

View File

@ -53,7 +53,7 @@ class PersonalScopeModal extends Component {
if (!_.isEmpty(nextProps.record)) {
this.setState({
targetType: nextProps.record.targetType,
targetTypeIds: String(nextProps.record.targetId),
targetTypeIds: nextProps.record.targetType !== "SQL" ? String(nextProps.record.targetId) : nextProps.record.target,
targetTypeIdsNames: nextProps.record.targetName,
status: nextProps.record.status,
statusAll: ""

View File

@ -41,7 +41,7 @@ class PersonalScopeTable extends Component {
}
getPersonalScopeList = (tabActive = this.props.tabActive) => {
const { searchValue, searchKeyVal, APIFox } = this.props;
const { searchValue, searchKeyVal, APIFox, showOperateBtn } = this.props;
const { pageInfo, loading } = this.state;
const payload = {
[searchKeyVal["key"]]: searchKeyVal["value"],
@ -60,7 +60,7 @@ class PersonalScopeTable extends Component {
return {
...item,
render: (text, record) => {
if (item.dataIndex === "targetName") {
if (item.dataIndex === "targetName" && showOperateBtn) {
return <a href="javascript:void(0);" onClick={() => this.props.onEditScope(record)}>{text}</a>;
}
return <span className="tdEllipsis" title={text}>{text}</span>;

View File

@ -18,8 +18,10 @@ CodeMirror.extendMode("javascript", {
if (this.jsonMode) {
return /^[\[,{]$/.test(content) || /^}/.test(textAfter) || /^]/.test(textAfter);
} else {
if (content == ";" && state.lexical && state.lexical.type == ")") return false;
return /^[;{}]$/.test(content) && !/^;/.test(textAfter);
if (content == ";" && state.lexical && state.lexical.type == "}") return false;
// if (content == ";" && state.lexical && state.lexical.type == ")") return false;
return /[=,]/.test(content) || /.*\)/.test(textAfter);
// return /^[;{}]$/.test(content) && !/^;/.test(textAfter);
}
}
});
@ -94,7 +96,8 @@ CodeMirror.defineExtension("autoFormatRange", function (from, to) {
atSol = false;
}
if (!atSol && inner.mode.newlineAfterToken &&
inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos) || text[i + 1] || "", inner.state))
// inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos) || text[i + 1] || "", inner.state))
inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos, stream.pos + 2) || text[i + 1] || "", inner.state))
newline();
}
if (!stream.pos && outer.blankLine) outer.blankLine(state);

View File

@ -1,111 +0,0 @@
import React from "react";
import { inject, observer } from "mobx-react";
import { toJS } from "mobx";
import { Button } from "antd";
import { WeaLogView } from "comsMobx";
import { WeaLocaleProvider, WeaNewScroll, WeaTop } from "ecCom";
import { getSearchs, renderLoading, renderNoright } from "../util"; // 从util文件引入公共的方法
const getLabel = WeaLocaleProvider.getLabel;
const WeaLogViewComp = WeaLogView.Component;
@inject("baseFormStore")
@observer
export default class BaseForm extends React.Component {
componentWillMount() { // 初始化渲染页面
const { baseFormStore: { doInit } } = this.props;
doInit();
}
componentWillReceiveProps(nextProps) {
const { baseFormStore: { doInit } } = this.props;
if (this.props.location.key !== nextProps.location.key) { // 手动刷新、切换菜单 重新初始化
doInit();
}
}
// 渲染右键菜单和顶部下拉菜单
getRightMenu() {
const { baseFormStore: { setLogVisible, saveForm } } = this.props;
let btnArr = [
{
key: "BTN_SAVE",
icon: <i className="icon-coms-Preservation"/>,
content: `${getLabel(86, "保存")}`,
onClick: () => saveForm()
},
{
key: "log",
content: getLabel(83, "日志"),
icon: <i className="icon-coms-Print-log"/>,
onClick: () => setLogVisible(true)
}];
return btnArr;
}
render() {
/*
1判断是否无权限 是显示无权限页面
2渲染form页面:
2-1: WeaRightMenu 右键菜单
2-2: WeaTop: 顶部: 包括下拉菜单
2-3: renderLoading: 加载数据中的loading效果(统一封装在util中)
2-4: WeaNewScroll 顶部以下超长滚动处理
2-5: 通过getSearchs方法渲染form
*/
const { baseFormStore } = this.props;
const {
loading,
hasRight,
form,
condition,
logVisible,
logStore,
saveLoading,
setLogVisible,
saveForm
} = baseFormStore; // 从后台取数据 和 方法
if (!hasRight && !loading) { // 无权限处理
return renderNoright();
}
const btns = [ // 顶部按钮
<Button type="primary" loading={saveLoading} onClick={() => saveForm()}>保存</Button>
];
const collectParams = { // 收藏功能配置
favname: "基础表单",
favouritetype: 1,
objid: 0,
link: "wui/index.html#/ns_demo01/index",
importantlevel: 1
};
return (
<WeaTop
title="基础表单" // title
icon={<i className="icon-coms-fa"/>} // 左侧图标
iconBgcolor="#F14A2D" // 左侧图标背景色
buttons={btns} // 顶部按钮: 这里是保存按钮,不需要可以不显示
buttonSpace={10} // 按钮之间的间隔
showDropIcon={true} // 是否显示右侧下拉按钮
dropMenuDatas={this.getRightMenu()} // 下拉菜单(和页面的右键菜单相同)
dropMenuProps={{ collectParams }} // 收藏功能: 配置之后显示 收藏、帮助、显示页面地址 这3个功能
>
{loading ? renderLoading() :
<WeaNewScroll height="100%">
{getSearchs(form, toJS(condition), 1)}
</WeaNewScroll>
}
<WeaLogViewComp // 日志功能(一般后端的应用设置是需要的)
visible={logVisible} // 日志弹框的显示隐藏
onCancel={() => setLogVisible(false)} // 关闭日志弹框时的操作设置logVisible属性为false
logStore={logStore} // 日志的store
logType="1" // 模块编码: 该参数要根据模块来给
logSmallType="1" // 细分模块编码: 该参数要根据模块来给
/>
</WeaTop>
);
}
}

View File

@ -82,6 +82,8 @@
}
.data-detail {
padding-bottom: 16px;
.salary-group {
background: #FFF;

View File

@ -18,6 +18,8 @@ export const PAGE = {
"salaryField": ["/hrmSalary/fieldManagement"], //字段管理
"salaryItem": ["/hrmSalary/salaryItem"], //薪资项目管理
"siScheme": ["/socialSecurityBenefits/programme"], //社保福利方案
"report": ["/hrmSalary/analysisOfSalaryStatistics", "/hrmSalary/reportView"] //报表
"report": ["/hrmSalary/analysisOfSalaryStatistics", "/hrmSalary/reportView"], //报表
"dataPush": ["/hrmSalary/datapush"], //数据推送
"adjustRecord": ["/hrmSalary/adjustSalaryManage"] //调薪管理
};
export const EXCLUDE_PAGE = ["mobilepayroll"];

View File

@ -54,6 +54,7 @@ import AdjustSalaryManage from "./pages/adjustSalaryManage";
import TopologyMap from "./pages/topologyMap";
import SupplementaryCalc from "./pages/supplementaryCalc";
import VariableSalary from "./pages/variableSalary";
import Datapush from "./pages/datapush";
import Layout from "./layout";
import CustomRoutes from "./pages/custom-pages";
@ -118,6 +119,7 @@ const Routes = (
<Route key="fieldManagement" path="fieldManagement" component={FieldManagement}/>
<Route key="analysisOfSalaryStatistics" path="analysisOfSalaryStatistics" component={AnalysisOfSalaryStatistics}/>
<Route key="analysisOfSalaryStatisticsId" path="analysisOfSalaryStatistics/:employeeId" component={EmployeeList}/>
<Route key="datapush" path="datapush" component={Datapush}/>
<Route key="reportView" path="reportView" component={ReportView}/>
<Route key="externalPersonManage" path="externalPersonManage" component={ExternalPersonManage}/>
<Route key="topologyView" path="topologyView/:salarySobId/:salaryItemId" component={TopologyMap}/>

View File

@ -12,7 +12,7 @@ import { inject, observer } from "mobx-react";
import { WeaLocaleProvider, WeaTools } from "ecCom";
import Authority from "./pages/mySalary/authority";
import { EXCLUDE_PAGE } from "./config";
import store from "./stores";
import stores from "./stores";
const { ls } = WeaTools;
const { getLabel } = WeaLocaleProvider;
@ -27,6 +27,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");
@ -46,9 +48,9 @@ class Layout extends Component {
header.appendChild(link);
top.$(".ant-message").remove();
if (_.every(EXCLUDE_PAGE, page => window.location.hash.indexOf(page) === -1)) {
store.taxAgentStore.getPermission();
stores.taxAgentStore.getPermission();
} else {
store.taxAgentStore.initPageAndOptAuth();
stores.taxAgentStore.initPageAndOptAuth();
}
}
window.addEventListener("storage", this.setFontSize);

View File

@ -46,8 +46,8 @@ class Index extends Component {
const payload = {
...pageInfo, ...extra,
departmentIds: departmentIds ? departmentIds.split(",") : [],
positionIds: departmentIds ? departmentIds.split(",") : [],
operatorIds: departmentIds ? departmentIds.split(",") : [],
positionIds: positionIds ? positionIds.split(",") : [],
operatorIds: operatorIds ? operatorIds.split(",") : [],
effectiveTime: effectiveTime1 ? [effectiveTime1, effectiveTime2] : [],
operateTime: operateTime1 ? [operateTime1, operateTime2] : []
};

View File

@ -232,6 +232,25 @@ export const tempCondition = [
rules: "required|string",
viewAttr: 3
},
{
conditionType: "UPLOAD",
domkey: ["fileId"],
fieldcol: 14,
label: "导出模板",
lanId: 111,
labelcol: 6,
value: "",
datas: [],
multiSelection: false,
showClearAll: false,
showListBottom: true,
showListTop: true,
maxFilesNumber: 1,
limitType: "xlsx",
uploadUrl: "/api/doc/upload/uploadFile",
category: "111",
viewAttr: 2
},
{
conditionType: "SELECT",
domkey: ["sharedType"],

View File

@ -32,7 +32,8 @@ class SalaryDetails extends Component {
this.state = {
loading: false, dataSource: [], columns: [], selectedRowKeys: [], tempPageList: [], sumRow: {},
pageInfo: { current: 1, pageSize: 10, total: 0 }, payload: {}, templateId: "", tempManageQuery: false,
showTotalCell: false, updateSum: true, tempDialog: { visible: false, setting: [], id: "", template: {} },
showTotalCell: false, updateSum: true,
tempDialog: { visible: false, setting: [], heads: [], id: "", template: {} },
transferDialog: {
visible: false, searchParamsKey: "name", saveLoading: false,
dataParams: { page: "salary_details_report" },
@ -200,9 +201,14 @@ class SalaryDetails extends Component {
};
handelAddTemp = (templateId = "") => {
const { tempDialog, tempPageList } = this.state;
if (_.isEmpty(this.transferRef.state.rightDatas)) {
message.warning(getLabel(111, "请选择设置!"));
return;
}
this.setState({
tempDialog: {
...tempDialog, visible: true, setting: _.map(this.transferRef.state.rightDatas, o => o.id)
...tempDialog, visible: true, setting: _.map(this.transferRef.state.rightDatas, o => o.id),
heads: _.map(this.transferRef.state.rightDatas, o => o.name)
// template: _.find(tempPageList, o => o.key === templateId)
}
});
@ -303,7 +309,7 @@ class SalaryDetails extends Component {
{/*薪资明细模板设置*/}
<SalaryDetailsTempDialog {...tempDialog}
onCancel={callback => this.setState({
tempDialog: { ...tempDialog, visible: false, setting: [] }
tempDialog: { ...tempDialog, visible: false, setting: [], heads: [] }
}, () => callback && callback())}
onSuccess={this.getPageListTemplatelist}/>
{/*薪资明细自定义列模板管理*/}

View File

@ -9,10 +9,11 @@
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaDialog, WeaLocaleProvider, WeaTools } from "ecCom";
import { WeaDialog, WeaLoadingGlobal, WeaLocaleProvider, WeaTools } from "ecCom";
import { tempCondition } from "./conditions";
import { getTaxAgentSelectList } from "../../../apis/taxAgent";
import * as API from "../../../apis/statistics";
import { downloadPageListTemplate } from "../../../apis/statistics";
import { Button, message } from "antd";
import { getSearchs } from "../../../util";
@ -57,6 +58,13 @@ class SalaryDetailTempDialog extends Component {
value: id ? template["limitIds"].join(",") : "",
options: _.map(data, o => ({ key: o.id, showname: o.content }))
};
} else if (getKey(o) === "fileId") {
return {
...o, label: getLabel(o.lanId, o.label), value: id ? template[getKey(o)] : "",
datas: id && template[getKey(o)] ? [
{ fileid: template[getKey(o)], filename: template["fileName"], showDelete: true }
] : [], labelExtra: getLabel(111, "下载示例"), labelType: "download"
};
}
return { ...o, label: getLabel(o.lanId, o.label), value: id ? template[getKey(o)] : "" };
})
@ -73,12 +81,13 @@ class SalaryDetailTempDialog extends Component {
tempForm.validateForm().then(f => {
if (f.isValid) {
this.setState({ loading: true });
const { limitIds, ...formVal } = tempForm.getFormParams();
const { limitIds, fileId, ...formVal } = tempForm.getFormParams();
const payload = {
page: "salary_details_report", setting, id, ...formVal,
limitIds: !_.isEmpty(limitIds) ? limitIds.split(",") : []
};
API.savePageListTemplate(payload).then(({ status, errormsg }) => {
API.savePageListTemplate(_.assign(payload, fileId ? { fileId } : {})).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success(getLabel(111, "操作成功!"));
this.props.onCancel(this.props.onSuccess());
@ -92,6 +101,12 @@ class SalaryDetailTempDialog extends Component {
}).catch(() => this.setState({ loading: false }));
};
formFieldChange = (field) => {
if (field === "download") {
const { setting, heads } = this.props;
WeaLoadingGlobal.start();
const promise = downloadPageListTemplate({ setting, heads });
return;
}
const key = Object.keys(field)[0], value = field[key].value;
this.setState({
conditions: _.map(this.state.conditions, item => ({
@ -101,6 +116,12 @@ class SalaryDetailTempDialog extends Component {
...o, hide: value !== "0", viewAttr: value === "0" ? 3 : 1,
rules: value === "0" ? "required|string" : ""
};
} else if (key === "fileId" && getKey(o) === "fileId") {
return {
...o, value, datas: value ? _.map(field[key].valueSpan, o => ({
fileid: o.fileid, filename: o.filename, showDelete: true
})) : []
};
}
return { ...o };
})
@ -118,7 +139,8 @@ class SalaryDetailTempDialog extends Component {
<WeaDialog
{...this.props} style={{ width: 480, height: 127 }} initLoadCss title={getLabel(111, "模板保存")}
buttons={[<Button type="primary" onClick={this.save} loading={loading}>{getLabel(537558, "保存")}</Button>]}>
<div className="form-dialog-layout">{getSearchs(tempForm, conditions, 1, false, this.formFieldChange)}</div>
<div
className="form-dialog-layout tempDialog">{getSearchs(tempForm, conditions, 1, false, this.formFieldChange)}</div>
</WeaDialog>
);
}

View File

@ -40,6 +40,11 @@ class SalaryTempAdminDialog extends Component {
render() {
const { dataSource, selectedKeys } = this.state, { dataParams } = this.props;
const heads = _.reduce(selectedKeys, (pre, cur) => {
const item = dataSource.find(data => data.id === cur);
if (item) pre.push(item.name);
return pre;
}, []);
return (<WeaDialog
{...this.props} initLoadCss ref={dom => this.dialog = dom} title={getLabel(111, "模板管理")}
className="temp_admin_dialog" style={{
@ -47,7 +52,7 @@ class SalaryTempAdminDialog extends Component {
maxHeight: "90%", maxWidth: "90%", overflow: "hidden", transform: "translate(0px, 0px)"
}} buttons={[
<Button type="primary"
onClick={() => this.props.onAddTemp(dataParams.id, selectedKeys)}>{getLabel(111, "确 定")}</Button>,
onClick={() => this.props.onAddTemp(dataParams.id, selectedKeys, heads)}>{getLabel(111, "确 定")}</Button>,
<Button type="ghost" onClick={this.props.onCancel}>{getLabel(111, "取 消")}</Button>
]}>
<WeaTransfer data={dataSource} selectedKeys={selectedKeys} onChange={v => this.setState({ selectedKeys: v })}

View File

@ -20,7 +20,7 @@ class SalaryTempMangerDialog extends Component {
super(props);
this.state = {
selectedRowKeys: [], tempAdminDialog: { visible: false, dataParams: { page: "salary_details_report" } },
tempDialog: { visible: false, setting: [], id: "", template: {} }
tempDialog: { visible: false, setting: [], heads: [], id: "", template: {} }
};
}
@ -31,10 +31,10 @@ class SalaryTempMangerDialog extends Component {
handleTempAdminCols = (params = {}) => this.setState({
tempAdminDialog: { visible: true, dataParams: { ...this.state.tempAdminDialog.dataParams, ...params } }
});
handelAddTemp = (id = "", setting = []) => {
handelAddTemp = (id = "", setting = [], heads = []) => {
this.setState({
tempDialog: {
visible: true, setting, id, template: _.find(this.tempManageRef.state.listDatas, o => o.id === id)
visible: true, setting, heads, id, template: _.find(this.tempManageRef.state.listDatas, o => o.id === id)
}
});
};
@ -76,7 +76,7 @@ class SalaryTempMangerDialog extends Component {
{/*薪资明细模板设置*/}
<SalaryDetailsTempDialog {...tempDialog}
onCancel={callback => this.setState({
tempDialog: { ...tempDialog, visible: false, setting: [] }
tempDialog: { ...tempDialog, visible: false, setting: [], heads: [] }
}, () => callback && callback())}
onSuccess={() => this.setState({
tempAdminDialog: { visible: false, dataParams: { page: "salary_details_report" } }

View File

@ -382,3 +382,17 @@
}
}
.tempDialog {
.wea-form-item-label {
min-height: 50px;
}
.wea-form-item-label-extra {
position: absolute;
left: 0;
bottom: 0;
cursor: pointer;
color: #4d7ad8;
}
}

View File

@ -46,7 +46,8 @@ class EditSalaryBaseInfo extends Component {
default:
break;
}
return <WeaBrowser {...browserType} viewAttr={3} value={value} valueSpan={valueSpan} inputStyle={{ width: 200 }}
return <WeaBrowser {...browserType} viewAttr={this.props.viewAttr === 1 ? 1 : 3}
value={value} valueSpan={valueSpan} inputStyle={{ width: 200 }}
onChange={(value, valueSpan) => this.props.onChange(_.map(this.props.baseInfo, it => {
if (fieldCode === it.fieldCode) {
return { ...it, fieldValue: value, fieldValueObj: { id: value, name: valueSpan } };

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

@ -30,7 +30,7 @@ class EditCalcTable extends Component {
this.state = {
loading: false, pageInfo: { current: 1, pageSize: 10, total: 0 },
selectedRowKeys: [], progressVisible: false, progress: 0,
salaryCalcSlide: { visible: false, id: "" }, originPayloadData: {},
salaryCalcSlide: { visible: false, id: "", viewAttr: 2 }, originPayloadData: {},
batchUpdateDialog: {
visible: false, salaryAcctRecordId: "", idList: [], salaryItemId: "",
conditions: [], pattern: 0, dataType: ""
@ -73,9 +73,9 @@ class EditCalcTable extends Component {
this.updateEmpLockStatus({ ...params });
break;
case "EDIT":
const { id: salaryCalcId } = params;
const { id: salaryCalcId, showSee } = params;
this.setState({
salaryCalcSlide: { visible: true, id: salaryCalcId }
salaryCalcSlide: { visible: true, id: salaryCalcId, viewAttr: showSee ? 1 : 2 }
});
break;
case "DIAGRAM":
@ -238,7 +238,7 @@ class EditCalcTable extends Component {
"总计": getLabel(523, "总计"), "批量解锁": getLabel(111, "批量解锁"),
"批量锁定": getLabel(111, "批量锁定"), "批量更新": getLabel(111, "批量更新"),
"查看拓扑图": getLabel(111, "查看拓扑图"), "锁定": getLabel(111, "锁定"),
"解锁": getLabel(111, "解锁")
"解锁": getLabel(111, "解锁"), "查看": getLabel(111, "查看")
};
this.setState({ originPayloadData: { ...payload, i18n } });
const childFrameObj = document.getElementById("atdTable");
@ -269,7 +269,7 @@ class EditCalcTable extends Component {
const sumRowlistUrl = this.props.showTotalCell ? "/api/bs/hrmsalary/salaryacct/acctresult/sum" : "";
this.postMessageToChild({
dataSource, pageInfo, selectedRowKeys, showTotalCell: this.props.showTotalCell, sumRowlistUrl, payload,
calcDetail,
calcDetail, showSee: calcDetail,
columns: _.every(traverse(columns, calcDetail), (it, idx) => !it.fixed) ? _.map(traverse(columns, calcDetail), (it, idx) => ({
...it,
fixed: idx < 2 ? "left" : false
@ -304,10 +304,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) => {
@ -43,14 +43,17 @@ class EditSalaryCalcSlide extends Component {
});
};
renderTitle = () => {
const { loading } = this.state;
const { loading } = this.state, { viewAttr } = this.props;
return <div className="titleDialog">
<div className="titleCol titleLeftBox">
<div className="titleIcon"><i className="icon-coms-fa"/></div>
<div className="title">{getLabel(543559, "编辑薪资")}</div>
<div className="title">{viewAttr === 2 ? getLabel(543559, "编辑薪资") : getLabel(111, "查看薪资")}</div>
</div>
<div className="titleCol titleRightBox">
<Button type="primary" onClick={this.save} loading={loading}>{getLabel(537558, "保存")}</Button>
{
viewAttr === 2 &&
<Button type="primary" onClick={this.save} loading={loading}>{getLabel(537558, "保存")}</Button>
}
</div>
</div>;
};
@ -139,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"
@ -148,12 +153,14 @@ class EditSalaryCalcSlide extends Component {
/>
{
selectedKey === "0" && _.map(itemsByGroup, item => {
return <PayrollItemsTable {...item} onChangeIssueReissueValue={this.handleItemValueChange}/>;
return <PayrollItemsTable {...this.props} {...item}
onChangeIssueReissueValue={this.handleItemValueChange}/>;
})
}
{
selectedKey === "1" &&
<IssuedAndReissueTable
{...this.props}
dataSource={issuedAndReissueItems}
onChangeIssueReissueValue={this.handleItemValueChange}
/>

View File

@ -142,6 +142,7 @@
height: 100%;
.salary-calculate-esf-area {
position: relative;
background: #f6f6f6;
height: 100%;
overflow-y: auto;
@ -191,6 +192,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

@ -29,10 +29,11 @@ class IssuedAndReissueTable extends Component {
/>
</span>,
render: (text, record) => {
const { canEdit, pattern } = record;
const { canEdit, pattern } = record, { viewAttr } = this.props;
return <WeaInputNumber
disabled={!canEdit}
min={0}
viewAttr={viewAttr}
precision={pattern || 2}
value={text || 0}
onChange={(value) => onChangeIssueReissueValue(record.salaryItemName, value, "issuedAndReissueItems")}

View File

@ -37,8 +37,9 @@ class PayrollItemsTable extends Component {
</span>,
width: "20%",
render: (text, record) => {
const { canEdit, dataType, pattern } = record;
const { canEdit, dataType, pattern } = record, { viewAttr } = this.props;
return dataType === "number" ? <WeaInputNumber
viewAttr={viewAttr}
disabled={!canEdit}
precision={!_.isNil(pattern) ? pattern : 0}
value={text || 0}
@ -46,6 +47,7 @@ class PayrollItemsTable extends Component {
/> : <WeaInput
disabled={!canEdit}
value={text}
viewAttr={viewAttr}
onChange={(value) => onChangeIssueReissueValue(record.salaryItemId, value, "itemsByGroup", salarySobItemGroupId)}
/>;
}
@ -66,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

@ -564,8 +564,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

@ -0,0 +1,171 @@
/*
* 数据推送
* 新增编辑
* @Author: 黎永顺
* @Date: 2024/11/19
* @Wechat:
* @Email: 971387674@qq.com
* @description:
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaButtonIcon, WeaLocaleProvider, WeaSearchGroup, WeaSlideModal, WeaTable, WeaTools } from "ecCom";
import PDetailDialog from "../PDDialog";
import { postFetch } from "../../../../util/request";
import * as API from "../../../../apis/datapush";
import { conditions } from "../../conditions";
import { Button, message, Modal } from "antd";
import { formRender } from "../../formRender";
const getLabel = WeaLocaleProvider.getLabel;
const getKey = WeaTools.getKey;
@inject("baseFormStore") @observer
class Index extends Component {
constructor(props) {
super(props);
this.state = {
conditions: [], loading: false, columns: [], dataSource: [],
PDDialog: { visible: false, title: "", settingId: "", detail: {} } //推送明细弹框
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) {
document.querySelector(".datapush_wrapper").classList.add("zIndex0-weaslide-title");
this.initForm(nextProps);
}
if (nextProps.visible !== this.props.visible && !nextProps.visible) {
document.querySelector(".datapush_wrapper").classList.remove("zIndex0-weaslide-title");
this.props.baseFormStore.initForm();
}
}
initForm = async (props) => {
const { detail } = props;
const { data: salarySobList } = await postFetch("/api/bs/hrmsalary/salarysob/listAuth", { filterType: "ADMIN_DATA" });
this.setState({
conditions: _.map(conditions, item => ({
...item, title: getLabel(item.lanId, item.title), items: _.map(item.items, o => {
o = { ...o, label: getLabel(o.lanId, o.label), value: detail[getKey(o)] || "" };
if (getKey(o) === "salarySobIds") {
return {
...o, value: detail[getKey(o)] ? detail[getKey(o)] : "",
options: _.map(salarySobList, o => ({ key: String(o.id), showname: o.name }))
};
} else if (getKey(o) === "able") {
return { ...o, value: !_.isEmpty(detail) ? String(detail[getKey(o)]) : o.value };
}
return { ...o };
})
}))
}, () => {
props.baseFormStore.form.initFormFields(this.state.conditions);
!_.isEmpty(detail) && this.getPushItemList(props);
});
};
getPushItemList = (props) => {
const { detail } = props || this.props;
const { id: settingId } = detail;
API.getPushItemList({ settingId }).then(({ status, data }) => {
if (status) {
const { columns, list: dataSource } = data;
this.setState({
dataSource, columns: [...columns, {
title: getLabel(111, "操作"), width: 120, render: (__, record) => (<React.Fragment>
<a href="javascript: void(0);" style={{ marginRight: 10 }}
onClick={() => this.handleOpts("edit", record)}>{getLabel(111, "编辑")}</a>
<a href="javascript: void(0);" style={{ marginRight: 10 }}
onClick={() => this.handleOpts("del", record.id)}>{getLabel(111, "删除")}</a>
</React.Fragment>)
}],
PDDialog: { ...this.state.PDDialog, settingId }
});
}
});
};
handleOpts = (type, detail = {}) => {
switch (type) {
case "edit":
const { PDDialog } = this.state;
this.setState({ PDDialog: { ...PDDialog, visible: true, title: getLabel(111, "编辑"), detail } });
break;
case "del":
Modal.confirm({
title: getLabel(111, "信息确认"),
content: getLabel(111, "确认要删除吗?"),
onOk: () => {
API.deletePushItemList({ id: detail }).then(({ status, errormsg }) => {
if (status) {
message.success(getLabel(111, "删除成功"));
this.getPushItemList();
} else {
message.error(errormsg);
}
});
}
});
break;
default:
break;
}
};
save = () => {
const { baseFormStore: { form }, detail } = this.props;
form.validateForm().then(f => {
if (f.isValid) {
const { salarySobIds, ...payload } = form.getFormParams();
this.setState({ loading: true });
API.savePushSetting({ ...payload, salarySobIds: salarySobIds.split(","), id: detail.id })
.then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success(getLabel(30700, "操作成功"));
this.props.onClose(this.props.onSearch());
} else {
message.error(errormsg);
}
}).catch(() => this.setState({ loading: false }));
} else {
f.showErrors();
}
});
};
renderTitle = () => {
const { loading } = this.state, { title } = this.props;
return <div className="titleDialog">
<div className="titleCol titleLeftBox">
<div className="titleIcon"><i className="icon-coms-fa"/></div>
<div className="title">{title}</div>
</div>
<div className="titleCol titleRightBox">
<Button type="primary" loading={loading} onClick={this.save}>{getLabel(537558, "保存")}</Button>
</div>
</div>;
};
render() {
const { baseFormStore: { form }, detail } = this.props, { conditions, columns, dataSource, PDDialog } = this.state;
return (<WeaSlideModal
className="pushdata_create_dialog" {...this.props} direction="right"
top={0} width={800} height={100} measureT="%" measureX="px" measureY="%" title={this.renderTitle()}
content={<div className="form-dialog-layout">
{formRender(form, conditions)}
{!_.isEmpty(detail) &&
<WeaSearchGroup title={getLabel(111, "推送明细")} showGroup needTigger className="pushdata_detail">
<div className="opts">
<WeaButtonIcon buttonType="add" type="primary" title={getLabel(111, "添加")}
onClick={() => this.setState({
PDDialog: { ...PDDialog, visible: true, title: getLabel(111, "新建") }
})}/>
</div>
<WeaTable pagination={false} columns={columns} dataSource={dataSource} bordered/>
<PDetailDialog {...PDDialog} onSearch={this.getPushItemList}
onCancel={() => this.setState({ PDDialog: { ...PDDialog, visible: false, detail: {} } })}/>
</WeaSearchGroup>}
</div>}
/>);
}
}
export default Index;

View File

@ -0,0 +1,90 @@
/*
* 数据推送
* 自定义薪资项目选择树
* @Author: 黎永顺
* @Date: 2024/11/20
* @Wechat:
* @Email: 971387674@qq.com
* @description:
*/
import React, { Component } from "react";
import { WeaLocaleProvider } from "ecCom";
import { TreeSelect } from "antd";
import { formualSearchField, formualSearchGroup } from "../../../../apis/item";
import cs from "classnames";
const getLabel = WeaLocaleProvider.getLabel;
const TreeNode = TreeSelect.TreeNode;
class CustomTreeSelect extends Component {
constructor(props) {
super(props);
this.state = { sourceList: [] };
}
componentDidMount() {
formualSearchGroup({ referenceType: "sql" }).then(({ status, data }) => {
if (status) this.setState({ sourceList: _.map(data, o => ({ ...o, isLeaf: true })) });
});
}
getSourceItem = (sourceId) => {
formualSearchField({ sourceId, extendParam: { referenceType: "sql" } }).then(({ status, data }) => {
if (status) {
this.setState({
sourceList: _.map(this.state.sourceList, o => {
if (o.key === sourceId) return {
...o,
children: _.map(data, k => ({ key: k.fieldId, value: k.name, fieldType: k.fieldType, isLeaf: false }))
};
return { ...o };
})
});
}
});
};
generateTreeNodes = (data) => {
const treeNodes = [], showData = [...data];
showData.map((item) => {
let title = (
<div className="weapp-excel-code-action-list-variable">
<span className="weapp-excel-code-action-list-variable-name">{item.value}</span>
{
item.fieldType ?
<span
className={cs("weapp-excel-code-action-list-variable-tip", { "danger": item.fieldType === "string" })}>{item.fieldType === "number" ? getLabel(111, "数字") : getLabel(111, "文本")}</span> :
<span></span>
}
</div>
);
treeNodes.push(<TreeNode className="no-child-item" title={title} key={item.key} value={item.key}/>);
});
return treeNodes;
};
handleSelect = (nodeValue) => {
const { form } = this.props, { sourceList } = this.state;
const [source, __] = nodeValue.split("_");
const itemName = _.find(_.find(sourceList, o => o.key === source).children, k => k.key === nodeValue).value;
form.updateFields({ item: nodeValue, itemName, source });
};
render() {
const { sourceList } = this.state, { detail } = this.props;
const { itemName } = detail;
return (
<TreeSelect dropdownStyle={{ maxHeight: 320, overflow: "auto" }} defaultValue={itemName}
dropdownMatchSelectWidth className="custom_item_treeselect"
loadData={(node) => this.getSourceItem(node.props.value)}
onSelect={this.handleSelect}>
{
_.map(sourceList, o => (
<TreeNode title={o.value} key={o.key} value={o.key} isLeaf={o.isLeaf} selectable={false}>
{this.generateTreeNodes(o.children || [])}
</TreeNode>))
}
</TreeSelect>
);
}
}
export default CustomTreeSelect;

View File

@ -0,0 +1,96 @@
/*
* 数据推送
* 推送明细新增编辑
* @Author: 黎永顺
* @Date: 2024/11/20
* @Wechat:
* @Email: 971387674@qq.com
* @description:
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaDialog, WeaLocaleProvider, WeaTools } from "ecCom";
import { commonEnumList } from "../../../../apis/ruleconfig";
import * as API from "../../../../apis/datapush";
import { PDConditions } from "../../conditions";
import { Button, message } from "antd";
import { formRender } from "../../formRender";
const getLabel = WeaLocaleProvider.getLabel;
const getKey = WeaTools.getKey;
@inject("baseFormStore")
@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.initForm(nextProps);
if (nextProps.visible !== this.props.visible && !nextProps.visible) nextProps.baseFormStore.initFormExtra();
}
initForm = async (props) => {
const { detail = {} } = props;
const { data: fieldType } = await commonEnumList({ enumClass: "com.engine.salary.enums.push.PushItemFieldEnum" });
this.setState({
conditions: _.map(PDConditions, item => ({
...item, items: _.map(item.items, o => {
o = { ...o, label: getLabel(o.lanId, o.label), value: detail[getKey(o)] || "" };
if (getKey(o) === "fieldType") {
return {
...o, value: detail[getKey(o)] ? String(detail[getKey(o)]) : "",
options: _.map(fieldType, o => ({ key: o.enum, showname: o.defaultLabel }))
};
}
return { ...o };
})
}))
}, () => {
props.baseFormStore.formExtra.initFormFields(this.state.conditions);
});
};
save = () => {
const { baseFormStore: { formExtra }, detail: { id }, settingId } = this.props;
formExtra.validateForm().then(f => {
if (f.isValid) {
const payload = formExtra.getFormParams();
this.setState({ loading: true });
API.savePushItemList({ ...payload, settingId, id })
.then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success(getLabel(30700, "操作成功"));
this.props.onCancel(this.props.onSearch());
} else {
message.error(errormsg);
}
}).catch(() => this.setState({ loading: false }));
} else {
f.showErrors();
}
});
};
render() {
const { baseFormStore: { formExtra }, detail } = this.props, { loading, conditions } = this.state;
return (
<WeaDialog
{...this.props} style={{ width: 480, height: 174 }} initLoadCss className="Pdetail_dialog"
buttons={[
<Button onClick={this.props.onCancel}>{getLabel(111, "取消")}</Button>,
<Button type="primary" onClick={this.save} loading={loading}>{getLabel(111, "保存")}</Button>
]}
>
<div className="form-dialog-layout">{formRender(formExtra, conditions, detail)}</div>
</WeaDialog>
);
}
}
export default Index;

View File

@ -0,0 +1,86 @@
/*
* 数据推送列表
*
* @Author: 黎永顺
* @Date: 2024/11/19
* @Wechat:
* @Email: 971387674@qq.com
* @description:
*/
import React, { Component } from "react";
import { WeaCheckbox, WeaLocaleProvider, WeaTable } from "ecCom";
import * as API from "../../../../apis/datapush";
const getLabel = WeaLocaleProvider.getLabel;
class Index extends Component {
constructor(props) {
super(props);
this.state = {
columns: [], dataSource: [], loading: false, pageInfo: { current: 1, pageSize: 10, total: 0 }
};
}
componentDidMount() {
this.getPushSettingList();
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.isQuery !== this.props.isQuery) this.setState({
pageInfo: { ...this.state.pageInfo, current: 1 }
}, () => this.getPushSettingList(nextProps));
}
getPushSettingList = (props) => {
const { pageInfo } = this.state, { query } = props || this.props;
const payload = { ...pageInfo, ...query };
this.setState({ loading: true });
API.getPushSettingList(payload).then(({ status, data }) => {
this.setState({ loading: false });
if (status) {
const { columns, list: dataSource, pageNum: current, pageSize, total } = data;
this.setState({
pageInfo: { ...pageInfo, current, pageSize, total },
dataSource: _.map(dataSource, o => ({
...o, salarySobs: _.map(o.salarySobs, k => k.name).join(","),
salarySobIds: _.map(o.salarySobs, k => k.id).join(",")
})),
columns: [..._.map(columns, o => {
if (o.dataIndex === "able") return {
...o, render: v => (<WeaCheckbox value={String(v)} disabled display="switch"/>)
};
return { ...o };
}), {
title: getLabel(111, "操作"), dataIndex: "opts", width: 120, render: (__, record) => (<React.Fragment>
<a href="javascript: void(0);" style={{ marginRight: 10 }}
onClick={() => this.props.onChange("edit", record)}>{getLabel(111, "编辑")}</a>
<a href="javascript: void(0);" style={{ marginRight: 10 }}
onClick={() => this.props.onChange("del", record.id)}>{getLabel(111, "删除")}</a>
</React.Fragment>)
}]
});
}
});
};
render() {
const { columns, dataSource, loading, pageInfo } = 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.getPushSettingList());
},
onChange: current => {
this.setState({ pageInfo: { ...pageInfo, current } }, () => this.getPushSettingList());
}
};
return (<WeaTable loading={loading} dataSource={dataSource} columns={columns} pagination={pagination}
scroll={{ y: `calc(100vh - 182px)` }}/>);
}
}
export default Index;

View File

@ -0,0 +1,147 @@
// 推送配置表单
export const conditions = [
{
items: [
{
conditionType: "INPUT",
domkey: ["name"],
fieldcol: 14,
label: "任务名称",
lanId: 111,
labelcol: 6,
value: "",
rules: "required|string",
viewAttr: 3
},
{
conditionType: "SWITCH",
domkey: ["able"],
fieldcol: 14,
label: "是否启用",
lanId: 111,
labelcol: 6,
value: "0",
rules: "required|string",
viewAttr: 3
},
{
conditionType: "SELECT",
domkey: ["salarySobIds"],
fieldcol: 14,
label: "薪资账套",
lanId: 111,
labelcol: 6,
value: "",
multiple: true,
options: [],
rules: "required|string",
viewAttr: 3
},
{
browserConditionParam: {
completeURL: "/api/bs/hrmsalary/push/mode/list",
dataParams: {},
filterByName: true,
tableProps: {},
isSingle: true,
searchParamsKey: "name",
replaceDatas: [{}]
},
tags: true,
conditionType: "INPUT",
domkey: ["modeName"],
fieldcol: 14,
label: "建模名称",
lanId: 111,
labelcol: 6,
value: "",
viewAttr: 2
},
{
conditionType: "INPUT",
domkey: ["tableName"],
fieldcol: 14,
label: "数据表名",
lanId: 111,
labelcol: 6,
value: "",
viewAttr: 2
},
{
conditionType: "INPUT",
domkey: ["modeId"],
fieldcol: 14,
label: "建模ID",
lanId: 111,
labelcol: 6,
value: "",
viewAttr: 2
}
],
title: "基础信息",
lanId: 111,
col: 2,
defaultshow: true
}
];// 推送配置表单
export const PDConditions = [
{
items: [
{
conditionType: "INPUT",
domkey: ["item"],
fieldcol: 14,
label: "薪资项目",
lanId: 111,
labelcol: 6,
value: "",
rules: "required|string",
viewAttr: 3
},
{
conditionType: "INPUT",
domkey: ["itemName"],
fieldcol: 14,
label: "薪资名称",
lanId: 111,
labelcol: 6,
viewAttr: 2,
hide: true
},
{
conditionType: "INPUT",
domkey: ["source"],
fieldcol: 14,
label: "薪资资源",
lanId: 111,
labelcol: 6,
viewAttr: 2,
hide: true
},
{
conditionType: "INPUT",
domkey: ["fieldName"],
fieldcol: 14,
label: "字段名称",
lanId: 111,
labelcol: 6,
rules: "required|string",
viewAttr: 3
},
{
conditionType: "SELECT",
domkey: ["fieldType"],
fieldcol: 14,
label: "字段类型",
lanId: 111,
labelcol: 6,
value: "",
options: [],
rules: "required|string",
viewAttr: 3
}
],
title: "",
defaultshow: true
}
];// 推送详细配置表单

View File

@ -0,0 +1,51 @@
import React from "react";
import { WeaFormItem, WeaSearchGroup, WeaTools } from "ecCom";
import { WeaSwitch } from "comsMobx";
import CustomTreeSelect from "./components/PDDialog/customTreeSelect";
import CustomBrowser from "../../components/CustomBrowser";
const getKey = WeaTools.getKey;
export const formRender = (form, conditions, params) => {
const { isFormInit } = form;
const formParams = form.getFormParams();
let group = [];
isFormInit && conditions && conditions.map(c => {
let items = [];
c.items.map(fields => {
items.push({
com: (
<WeaFormItem label={fields.label} labelCol={{ span: `${fields.labelcol}` }}
wrapperCol={{ span: `${fields.fieldcol}` }} error={form.getError(fields)}
tipPosition="bottom">
{
getKey(fields) === "item" ?
<React.Fragment>
<CustomTreeSelect
detail={params} fieldConfig={fields} form={form} formParams={formParams}/>
{
_.isEmpty(formParams.item) &&
<span className="wea-required-e9" style={{ verticalAlign: "middle" }}>
<img src="/images/BacoError_wev9.png" alt=""/>
</span>
}
</React.Fragment>
:
getKey(fields) === "modeName" ?
<CustomBrowser fieldConfig={fields} form={form} formParams={formParams}
onCustomChange={(v) => !!_.values(v)[0] && form.updateFields({
tableName: _.values(v)[0].subname,
modeId: _.values(v)[0].domid
})}/>
: <WeaSwitch fieldConfig={fields} form={form} formParams={formParams}/>
}
</WeaFormItem>),
colSpan: 1,
hide: fields.hide
});
});
!_.isEmpty(items) && group.push(
<WeaSearchGroup col={c.col || 1} needTigger={true} showGroup={c.defaultshow} items={items} center={false}
title={c.title}/>);
});
return group;
};

View File

@ -0,0 +1,95 @@
/*
* 数据推送
*
* @Author: 黎永顺
* @Date: 2024/11/19
* @Wechat:
* @Email: 971387674@qq.com
* @description:
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaInputSearch, WeaLocaleProvider, WeaReqTop } from "ecCom";
import * as API from "../../apis/datapush";
import DatapushList from "./components/datapushList";
import DatapushDialog from "./components/DPDialog";
import { Button, message, Modal } from "antd";
import "./index.less";
const getLabel = WeaLocaleProvider.getLabel;
@inject("taxAgentStore", "baseFormStore")
@observer
class Index extends Component {
constructor(props) {
super(props);
this.state = {
selectedKey: "datapush", isQuery: false, query: { name: "" },
DPDialog: { visible: false, title: "", detail: {} } //数据推送弹框
};
}
handleAdvanceSearch = () => this.setState({ isQuery: !this.state.isQuery });
handleOperate = (type, detail = {}) => {
switch (type) {
case "create":
case "edit":
const title = type === "create" ? getLabel(111, "新建") : getLabel(111, "编辑");
this.setState({ DPDialog: { visible: true, title, detail } });
break;
case "del":
Modal.confirm({
title: getLabel(111, "信息确认"),
content: getLabel(111, "确认要删除吗?"),
onOk: () => {
API.deletePushSetting({ id: detail }).then(({ status, errormsg }) => {
if (status) {
message.success(getLabel(111, "删除成功"));
this.handleAdvanceSearch();
} else {
message.error(errormsg);
}
});
}
});
break;
default:
break;
}
};
render() {
const { selectedKey, DPDialog, isQuery, query } = this.state;
const { taxAgentStore: { PageAndOptAuth } } = this.props;
const showOperateBtn = PageAndOptAuth.opts.includes("admin");
const tabs = [
{
title: getLabel(111, "数据推送"), key: "datapush", showDropIcon: false, dropMenuDatas: [],
buttons: showOperateBtn ? [
<Button type="primary" onClick={() => this.handleOperate("create")}>{getLabel(111, "新建")}</Button>,
<WeaInputSearch style={{ top: -3 }} value={query.name} onSearch={this.handleAdvanceSearch}
onChange={v => this.setState({ query: { ...query, name: v } })}/>
] : [<WeaInputSearch style={{ top: -3 }} value={query.name} onSearch={this.handleAdvanceSearch}
onChange={v => this.setState({ query: { ...query, name: v } })}/>],
children: <DatapushList isQuery={isQuery} query={query} onChange={this.handleOperate}/>
}
];
return (
<WeaReqTop
title={getLabel(111, "数据推送")} icon={<i className="icon-coms-fa"/>} selectedKey={selectedKey}
iconBgcolor="#F14A2D" tabDatas={tabs} className="datapush_wrapper" buttonSpace={10}
buttons={_.find(tabs, o => selectedKey === o.key).buttons}
onChange={selectedKey => this.setState({ selectedKey })}
showDropIcon={_.find(tabs, o => selectedKey === o.key).showDropIcon} onDropMenuClick={this.handleOperate}
dropMenuDatas={_.find(tabs, o => selectedKey === o.key).dropMenuDatas}
>
{_.find(tabs, o => selectedKey === o.key).children}
{/*数据推送框*/}
<DatapushDialog {...DPDialog} onClose={() => this.setState({ DPDialog: { ...DPDialog, visible: false } })}
onSearch={this.handleAdvanceSearch}/>
</WeaReqTop>
);
}
}
export default Index;

View File

@ -0,0 +1,134 @@
.datapush_wrapper {
.wea-new-top-req-title > div:last-child {
right: 16px !important;
}
.wea-new-top-req-content {
padding: 8px 16px 0 16px;
.wea-new-table {
background: #FFF;
}
.ant-spin-nested-loading, .ant-spin-container {
height: 100% !important;
}
.pushdata_create_dialog {
.scroller {
background: #f6f6f6;
}
.pushdata_detail {
.opts {
width: 100%;
display: flex;
justify-content: flex-end;
align-items: center;
padding: 8px;
}
}
.wea-slide-modal-title {
border-bottom: 1px solid #ebebeb;
}
.titleDialog {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 46px 0 16px;
.titleCol {
flex: 1;
display: flex;
align-items: center;
}
.titleLeftBox {
.titleIcon {
color: #fff;
margin: 0;
width: 40px;
height: 40px;
line-height: 40px;
font-size: 22px;
display: flex;
align-items: center;
justify-content: center;
background: #F14A2D;
border-radius: 50%;
}
.title {
font-size: 14px;
color: #333;
padding-left: 6px;
}
}
.titleRightBox {
justify-content: flex-end;
button:last-child {
margin-left: 10px;
}
}
}
}
}
}
.custom_item_treeselect {
.weapp-excel-code-action-list-variable-tip {
display: none;
}
}
.no-child-item {
.ant-select-tree-switcher {
display: none !important;
}
.ant-select-tree-node-content-wrapper {
width: 100%;
}
.weapp-excel-code-action-list-variable {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
.weapp-excel-code-action-list-variable-name {
height: 20px;
line-height: 18px;
-webkit-flex: 1 1;
flex: 1 1;
overflow: hidden;
text-overflow: ellipsis;
word-break: keep-all;
white-space: nowrap;
cursor: pointer;
}
.danger {
color: rgb(255, 102, 106) !important;
border: 1px solid rgb(255, 193, 195) !important;
background-color: rgb(255, 223, 224) !important;
}
.weapp-excel-code-action-list-variable-tip {
width: 40px;
height: 20px;
line-height: 18px;
text-align: center;
vertical-align: middle;
color: rgb(255, 205, 80);
border: 1px solid rgb(255, 222, 138);
background-color: rgb(255, 245, 219);
border-radius: 2px;
}
}
}

View File

@ -12,6 +12,7 @@ import { getSearchs } from "../../../../util";
import { saveDeclare } 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;
@ -31,7 +32,8 @@ class Index extends Component {
if (nextProps.visible !== this.props.visible && !nextProps.visible) this.props.declareStore.initDeclareForm();
}
getTaxAgentSelectListAsAdmin = (props) => {
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 }) => {
@ -46,6 +48,11 @@ class Index extends Component {
options: _.map(data, g => ({ key: String(g.id), showname: g.name }))
// helpfulTitle: getLabel(563420, "提示:可选择单个个税扣缴义务人进行申报,若不选择,则批量对管理下的所有个税扣缴义务人进行申报;")
};
} 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) };
})
@ -60,7 +67,9 @@ class Index extends Component {
if (f.isValid) {
const payload = declareForm.getFormParams();
this.setState({ loading: true });
saveDeclare({ ...payload }).then(({ status, errormsg }) => {
saveDeclare({
...payload, taxCycle: `${payload.salaryMonthStr}-01`, salaryDate: `${payload.salaryMonthStr}-01`
}).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success(getLabel(30700, "操作成功"));

View File

@ -1,27 +1,24 @@
import React from "react";
import CustomTab from "../../components/customTab";
import { inject, observer } from "mobx-react";
import { WeaLocaleProvider, WeaTable, WeaTop } from "ecCom";
import { getQueryString } from "../../util/url";
import * as API from "../../apis/declare";
import { Button } from "antd";
import UnifiedTable from "../../components/UnifiedTable";
import "./index.less";
const { getLabel } = WeaLocaleProvider;
@inject("taxAgentStore")
@observer
export default class GenerateDeclarationDetail extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
dataSource: [],
columns: [],
pageInfo: { current: 1, pageSize: 10, total: 0 },
declareInfo: {}
loading: false, dataSource: [], columns: [], declareInfo: {},
pageInfo: { current: 1, pageSize: 10, total: 0 }
};
}
componentWillMount() {
componentDidMount() {
this.getDetailList();
this.getDeclareInfo();
}
@ -37,31 +34,19 @@ export default class GenerateDeclarationDetail extends React.Component {
if (status) {
const { columns, list: dataSource, pageNum: current, pageSize, total } = data;
this.setState({
dataSource,
pageInfo: {
...pageInfo,
current, pageSize, total
},
dataSource, pageInfo: { ...pageInfo, current, pageSize, total },
columns: _.map(_.filter(columns, it => it.dataIndex !== "jobNum"), item => {
if (item.dataIndex === "username") {
return {
...item,
render: (text, record) => {
return <a className="ellipsis"
href={`javaScript:openhrm(${record.employeeId});`}
onClick={e => window.pointerXY(e)}
title={text}
>
{text}
</a>;
}
...item, width: 180,
render: (text, record) => (<a className="ellipsis" href={`javaScript:openhrm(${record.employeeId});`}
onClick={e => window.pointerXY(e)}
title={text}>{text}</a>)
};
}
return {
...item,
render: (text) => {
return <span className="ellipsis" title={text}>{text}</span>;
}
...item, width: (item.dataIndex === "cardType" || item.dataIndex === "cardNum") ? 180 : 100,
render: (text) => (<span className="ellipsis" title={text}>{text}</span>)
};
})
});
@ -78,26 +63,19 @@ export default class GenerateDeclarationDetail extends React.Component {
const url = `${window.location.origin}/api/bs/hrmsalary/taxdeclaration/export?taxDeclarationId=${getQueryString("id")}`;
window.open(url, "_self");
};
renderTitle = () => {
const { declareInfo } = this.state;
return (<React.Fragment>
<span>{getLabel(111, "薪资所属月")}{declareInfo.salaryMonth}</span>
<span style={{ marginLeft: "10px" }}>{getLabel(111, "个税扣缴义务人")}{declareInfo.taxAgentName}</span>
</React.Fragment>);
};
render() {
const { declareInfo, loading, pageInfo, columns, dataSource } = this.state;
const { loading, pageInfo, columns, dataSource } = this.state;
const { taxAgentStore: { showOperateBtn } } = this.props;
const renderRightOperation = () => {
return (
<div style={{ display: "inline-block" }}>
<Button type="primary" onClick={this.handleExport}>导出</Button>
</div>
);
};
const renderLeftOperation = () => {
return (
<div style={{ display: "inline-block", lineHeight: "47px" }}>
<span>薪资所属月{declareInfo.salaryMonth}</span>
<span style={{ marginLeft: "10px" }}>个税扣缴义务人{declareInfo.taxAgentName}</span>
</div>
);
};
const buttons = showOperateBtn ? [<Button type="primary"
onClick={this.handleExport}>{getLabel(111, "导出全部")}</Button>] : [];
const pagination = {
...pageInfo,
showTotal: (total) => `${total}`,
@ -115,23 +93,12 @@ export default class GenerateDeclarationDetail extends React.Component {
}, () => this.getDetailList());
}
};
return (
<div className="generateDeclarationDetail">
<CustomTab
searchOperationItem={showOperateBtn && renderRightOperation()}
leftOperation={renderLeftOperation()}
/>
<div className="tableWrapper">
<UnifiedTable
rowKey="id"
columns={columns}
dataSource={dataSource}
pagination={pagination}
loading={loading}
xWidth={columns.length * 120}
/>
</div>
return (<WeaTop title={this.renderTitle()} icon={<i className="icon-coms-fa"/>} iconBgcolor="#F14A2D"
buttons={buttons}>
<div className="declare-detail-table-container">
<WeaTable columns={columns} dataSource={dataSource} pagination={pagination} loading={loading}
scroll={{ x: 1200, y: `calc(100vh - 186px)` }}/>
</div>
);
</WeaTop>);
}
}

View File

@ -1,11 +1,10 @@
.generateDeclarationDetail {
.tabWrapper {
padding-left: 10px
}
.declare-detail-table-container {
height: 100%;
background: #f6f6f6;
padding: 8px 16px;
.tableWrapper {
height: calc(100vh - 48px);
overflow: auto;
.wea-new-table {
background: #FFF;
}
}

View File

@ -63,7 +63,8 @@ class CopyLedgerModal extends Component {
const { copyForm: form } = ledgerStore;
form.validateForm().then(f => {
if (f.isValid) {
const payload = { id, ...form.getFormParams() };
const { taxAgentId, ...formParams } = form.getFormParams();
const payload = { id, ...formParams, taxAgentIds: taxAgentId.split(",") };
this.setState({ loading: true });
duplicateLedger(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });

View File

@ -91,39 +91,14 @@
//调薪计薪规则弹框
.adjustRuleModalWrapper {
.titleTipWrapper {
display: flex;
align-items: center;
.calcRules .cust {
line-height: 30px;
.title {
margin-right: 4px;
}
}
.adjustRuleDetailWrapper {
display: flex;
flex-direction: column;
.adjustSalaryFlex {
.child {
display: flex;
align-items: center;
margin-bottom: 10px;
}
}
.wea-select, .ant-select-selection, .ant-select {
width: 100%;
}
.wea-select {
display: inline-block;
position: relative;
}
.ant-select-selection {
height: 30px;
border-radius: 0;
}
}
// 回算薪资项目
@ -249,7 +224,7 @@
padding: 0;
background: transparent;
border: none;
font-size: 20px!important;
font-size: 20px !important;
line-height: 20px;
}

View File

@ -5,170 +5,139 @@
* Date: 2022/12/12
*/
import React, { Component } from "react";
import { WeaDialog, WeaFormItem, WeaHelpfulTip, WeaSearchGroup, WeaSelect } from "ecCom";
import { Button, Modal, Radio } from "antd";
import { monthDays } from "../config";
import { inject, observer } from "mobx-react";
import { WeaDialog, WeaFormItem, WeaHelpfulTip, WeaLocaleProvider, WeaSelect, WeaTools } from "ecCom";
import FormInfo from "../../../components/FormInfo";
import { WeaSwitch } from "comsMobx";
import { Button } from "antd";
import { listSalarySobItem } from "../../../apis/ledger";
import { monthDays, ruleConditions } from "../config";
import "./index.less";
const { getLabel } = WeaLocaleProvider;
const getKey = WeaTools.getKey;
@inject("ledgerStore")
@observer
class LedgerAdjustRuleAddModal extends Component {
constructor(props) {
super(props);
this.state = {
beforeAdjustmentType: 2,
afterAdjustmentType: 1,
salaryItemId: "",
salaryItemName: "",
dayOfMonth: "1",
salaryItemOptions: []
};
this.state = { conditions: [] };
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.salarySobId) this.listSalarySobItem(nextProps.salarySobId);
if (nextProps.visible !== this.props.visible && nextProps.visible) this.listSalarySobItem(nextProps.salarySobId);
if (nextProps.visible !== this.props.visible && !nextProps.visible) this.props.ledgerStore.initRuleForm();
}
listSalarySobItem = (salarySobId) => {
const { salaryRuleItemsList } = this.props;
const payload = {
excludeSalaryItemIds: _.map(salaryRuleItemsList, item => item.salaryItemId),
salarySobId
excludeSalaryItemIds: _.map(salaryRuleItemsList, item => item.salaryItemId), salarySobId
};
listSalarySobItem(payload).then(({ status, data }) => {
if (status) {
this.setState({
salaryItemOptions: _.map(data, it => ({ key: it.salaryItemId.toString(), showname: it.salaryItemName }))
});
conditions: _.map(ruleConditions, item => ({
...item, items: _.map(item.items, o => {
o = { ...o, label: getLabel(o.lanId, o.label) };
if (getKey(o) === "salaryItemId") {
return {
...o, options: _.map(data, it => ({ key: it.salaryItemId.toString(), showname: it.salaryItemName }))
};
} else if (getKey(o) === "dayOfMonth") {
return { ...o, options: monthDays };
} else if (getKey(o) === "beforeAdjustmentType" || getKey(o) === "afterAdjustmentType") {
return {
...o,
options: _.map(o.options, k => ({
...k,
showname: !k.helpfultip ? getLabel(k.lanId, k.showname) : <span>
<span style={{ marginRight: 4 }}>{getLabel(k.lanId, k.showname)}</span>
<WeaHelpfulTip title={`=${getLabel(k.helpfultiplanId, k.helpfultip)}`}/>
</span>
}))
};
}
return o;
})
}))
}, () => this.props.ledgerStore.ruleForm.initFormFields(this.state.conditions));
}
});
};
handleSave = () => {
const { salaryRuleItemsList, onSave } = this.props;
const { salaryItemOptions, ...extraItems } = this.state;
if (_.isEmpty(extraItems.salaryItemId)) {
Modal.warning({
title: "信息确认",
content: "必要信息不完整,红色*为必填项!"
});
return;
}
const items = { ...extraItems, salaryItemName: this.state.salaryItemName };
const { salaryItemName, salaryItemId, ...extraFileds } = items;
const salaryItemNameFiled = salaryItemName.split(","), salaryItemIdFiled = salaryItemId.split(",");
const fields = _.map(salaryItemNameFiled, (item, index) => {
return {
...extraFileds,
salaryItemName: item,
salaryItemId: salaryItemIdFiled[index]
};
});
this.handleReset();
onSave([...salaryRuleItemsList, ...fields]);
};
handleReset = () => {
this.setState({
beforeAdjustmentType: 2,
afterAdjustmentType: 1,
salaryItemId: "",
salaryItemName: "",
dayOfMonth: "1",
salaryItemOptions: []
}, () => {
const { onCancel } = this.props;
onCancel();
const { salaryRuleItemsList, onSave, ledgerStore: { ruleForm } } = this.props;
ruleForm.validateForm().then(f => {
if (f.isValid) {
const { salaryItemId } = ruleForm.getFormParams(), { fieldMap } = ruleForm;
const fields = _.map(salaryItemId.split(","), o => ({
...ruleForm.getFormParams(),
salaryItemId: o,
salaryItemName: _.find(fieldMap["salaryItemId"]["options"], k => k.key === o).showname
}));
this.props.onCancel(onSave([...salaryRuleItemsList, ...fields]));
} else {
f.showErrors();
}
});
};
render() {
const {
salaryItemId,
salaryItemOptions,
dayOfMonth,
beforeAdjustmentType,
afterAdjustmentType
} = this.state;
const { title, visible } = this.props;
const buttons = [<Button type="primary" onClick={this.handleSave}>保存</Button>];
return (
<WeaDialog
initLoadCss
className="adjustRuleModalWrapper"
title={title}
visible={visible}
style={{ width: 750 }}
buttons={buttons}
onCancel={this.handleReset}
>
<WeaSearchGroup col={1} needTigger title="" showGroup center>
<WeaFormItem label="薪资项目" labelCol={{ span: 4 }} wrapperCol={{ span: 20 }}
style={{ tableLayout: "fixed" }}>
<WeaSelect
multiple
viewAttr={3}
style={{ width: "350px" }}
options={salaryItemOptions}
value={salaryItemId}
onChange={(salaryItemId, salaryItemName) => this.setState({ salaryItemId, salaryItemName })}
/>
</WeaFormItem>
<WeaFormItem label={<AdjustTitle/>} labelCol={{ span: 4 }} wrapperCol={{ span: 20 }} colon={false}>
<div className="adjustRuleDetailWrapper">
<div className="adjustSalaryFlex">
<span>如果调薪生效日期在</span>
<WeaSelect
viewAttr={3}
style={{ width: 60, margin: "0 6px" }}
value={dayOfMonth}
options={monthDays}
onChange={(dayOfMonth) => this.setState({ dayOfMonth })}
/>
<span>之前</span>
const { ledgerStore: { ruleForm } } = this.props, { conditions } = this.state;
const buttons = [<Button type="primary" onClick={this.handleSave}>{getLabel(111, "保存")}</Button>];
const itemRender = {
salaryItemId: (field, textAreaProps, form, formParams) => {
return (<WeaSwitch fieldConfig={{ ...field, ...textAreaProps }} form={form} formParams={formParams}/>);
},
dayOfMonth: () => null,
beforeAdjustmentType: () => null,
afterAdjustmentType: () => null
};
const childrenComponents = {
salaryItemId: () => {
const { dayOfMonth, beforeAdjustmentType, afterAdjustmentType } = ruleForm.getFormParams();
const coms = [], { fieldMap } = ruleForm;
coms.push(
<WeaFormItem label={<span>
<span className="title">{getLabel(111, "计薪规则")}</span>
<WeaHelpfulTip
title={getLabel(111, "该规则适用于一个薪资核算周期内只调整一次薪资或个税扣缴义务人的情况,其他情况默认按照分段计薪规则核算")}/>
</span>} labelCol={{ span: 6 }} wrapperCol={{ span: 18 }}>
<div className="cust">
<div className="child">
<div className="lbl">{fieldMap["dayOfMonth"].label}</div>
<WeaSelect value={dayOfMonth} options={monthDays} style={{ width: 100 }}
onChange={v => ruleForm.updateFields({ dayOfMonth: { value: v } })}/>
<div className="rbl">{getLabel(111, "(含)之前")}</div>
</div>
<div className="adjustSalaryFlex">
<span>计薪规则为</span>
<Radio.Group onChange={(e) => this.setState({ beforeAdjustmentType: e.target.value })}
value={beforeAdjustmentType}>
<Radio value={2}>取调整后薪资</Radio>
<Radio value={4}>分段计薪<WeaHelpfulTip
style={{ marginLeft: "10px" }}
width={200}
title="=调整前薪资/当月自然日天数*调整前自然日天数+调整后薪资/当月自然日天数*调整后自然日天数"
placement="topLeft"
/></Radio>
<Radio value={3}>取平均<WeaHelpfulTip
style={{ marginLeft: "10px" }}
width={200}
title="=(调整前薪资+调整后薪资)/2"
placement="topLeft"
/>
</Radio>
</Radio.Group>
<div className="child">
<div className="lbl">{fieldMap["beforeAdjustmentType"].label}</div>
<WeaSelect value={beforeAdjustmentType} detailtype={fieldMap["beforeAdjustmentType"]["detailtype"]}
options={fieldMap["beforeAdjustmentType"]["options"]} style={{ flex: 1 }}
onChange={v => ruleForm.updateFields({ beforeAdjustmentType: { value: v } })}/>
</div>
<div style={{ marginBottom: 10 }}>否则调薪生效日期在{dayOfMonth}号之后</div>
<div className="adjustSalaryFlex">
<span>计薪规则为</span>
<Radio.Group onChange={(e) => this.setState({ afterAdjustmentType: e.target.value })}
value={afterAdjustmentType}>
<Radio value={1}>取调整前薪资</Radio>
<Radio value={4}>分段计薪<WeaHelpfulTip
style={{ marginLeft: "10px" }}
width={200}
title="=调整前薪资/当月自然日天数*调整前自然日天数+调整后薪资/当月自然日天数*调整后自然日天数"
placement="topLeft"
/></Radio>
<Radio value={3}>取平均<WeaHelpfulTip
style={{ marginLeft: "10px" }}
width={200}
title="=(调整前薪资+调整后薪资)/2"
placement="topLeft"
/>
</Radio>
</Radio.Group>
<div className="child">
<div className="lbl">{getLabel(111, "否则调薪生效日期在10号之后")}</div>
</div>
<div className="child">
<div className="lbl">{fieldMap["afterAdjustmentType"].label}</div>
<WeaSelect value={afterAdjustmentType} detailtype={fieldMap["afterAdjustmentType"]["detailtype"]}
options={fieldMap["afterAdjustmentType"]["options"]} style={{ flex: 1 }}
onChange={v => ruleForm.updateFields({ afterAdjustmentType: { value: v } })}/>
</div>
</div>
</WeaFormItem>
</WeaSearchGroup>
);
return [{ com: <div className="calcRules">{coms}</div>, col: 1 }];
}
};
return (
<WeaDialog {...this.props} initLoadCss style={{ width: 750, height: 236 }} buttons={buttons}
className="adjustRuleModalWrapper">
<FormInfo className="form-dialog-layout" center={false} itemRender={itemRender}
childrenComponents={childrenComponents} form={ruleForm} formFields={conditions}/>
</WeaDialog>
);
}
@ -176,14 +145,3 @@ class LedgerAdjustRuleAddModal extends Component {
export default LedgerAdjustRuleAddModal;
const AdjustTitle = () => {
return <div className="titleTipWrapper">
<span className="title">计薪规则</span>
<WeaHelpfulTip
width={200}
title="该规则适用于一个薪资核算周期内只调整一次薪资或个税扣缴义务人的情况,其他情况默认按照分段计薪规则核算"
placement="topLeft"
/>
<span className="title">:</span>
</div>;
};

View File

@ -287,6 +287,7 @@ class LedgerAssociatedPersonnel extends Component {
APIFox={APIFox}
tabActive={selectedKey}
searchValue={searchValue}
showOperateBtn={admin}
onChangeSelectKey={rowKeys => this.setState({ rowKeys })}
onEditScope={this.handleAddPersonal}
/>

View File

@ -18,10 +18,8 @@ class LedgerMovoTo extends Component {
];
return (
<WeaDialog
{...extraProps} style={{ width: 440, height: 232 }}
buttons={buttons} hasScroll initLoadCss
className="moveModalWrapper"
>
{...extraProps} buttons={buttons} hasScroll initLoadCss className="moveModalWrapper"
style={{ width: 440, height: Math.ceil((dataList.length - 1) / 3) * 25 + 41 }}>
<WeaSearchGroup showGroup needTigger={false}>
<WeaSelect
options={_.filter(dataList, item => item.showname === "未分类")}

View File

@ -254,20 +254,19 @@ class LedgerSalaryItem extends Component {
* Params:
* Date: 2022/12/14
*/
handleAddSalaryItems = (id, items) => {
handleAddSalaryItems = (id, items, insertId) => {
const { itemGroups } = this.state;
this.setState({
itemGroups: _.map(itemGroups, it => {
if (id === it.uuid) {
items = _.map(items, child => {
const { id: itemsId, ...extraItems } = child;
return { ...extraItems, salaryItemGroupId: it.uuid };
});
if (insertId) it.items.splice(_.findIndex(it.items, k => (k.id === insertId) || (k.key === insertId)) + 1, 0, ...items);
return {
...it, items: _.map([..._.map(items, child => {
const { id: itemsId, ...extraItems } = child;
return { ...extraItems, salaryItemGroupId: it.uuid };
}), ...it.items], (childItem, childItemIndex) => {
return {
...childItem,
sortedIndex: childItemIndex
};
...it, items: _.map(insertId ? it.items : [...items, ...it.items], (childItem, childItemIndex) => {
return { ...childItem, sortedIndex: childItemIndex };
})
};
}
@ -319,7 +318,7 @@ class LedgerSalaryItem extends Component {
items: [...it.items, {
...extraItems,
salaryItemGroupId: moveToItemId,
key: moveId,
key: moveId ? moveId : items.key,
sortedIndex: !_.isEmpty(it.items) ? it.items[it.items.length - 1].sortedIndex + 1 : 0
}]
};

View File

@ -1,25 +1,15 @@
import React from "react";
import { Button, Switch } from "antd";
import { WeaDialog, WeaInputSearch, WeaTable } from "ecCom";
import { Button, Spin } from "antd";
import { WeaCheckbox, WeaDialog, WeaInputSearch, WeaLocaleProvider, WeaTable } from "ecCom";
import { listSalaryItem } from "../../../apis/ledger";
const getLabel = WeaLocaleProvider.getLabel;
export default class LedgerSalaryItemAddModal extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: {
query: false
},
name: "",
selectedRowKeys: [],
dataSource: [],
dataSourceCopy: [],
columns: [],
pageInfo: {
current: 1,
pageSize: 10,
total: 0
}
loading: { query: false }, name: "", selectedRowKeys: [], dataSource: [],
dataSourceCopy: [], columns: [], pageInfo: { current: 1, pageSize: 10, total: 0 }
};
}
@ -42,12 +32,7 @@ export default class LedgerSalaryItemAddModal extends React.Component {
excludeIds.push(i.salaryItemId);
});
});
const payload = {
excludeIds,
name,
...pageInfo,
...extra
};
const payload = { excludeIds, name, ...pageInfo, ...extra };
this.setState({ loading: { ...loading, query: true } });
listSalaryItem(payload).then(({ status, data }) => {
this.setState({ loading: { ...loading, query: false } });
@ -56,9 +41,7 @@ export default class LedgerSalaryItemAddModal extends React.Component {
const tmpV = !_.isEmpty(dataSource) ? dataSource : [];
this.setState({
dataSourceCopy: [...dataSourceCopy, ...tmpV],
pageInfo: { ...pageInfo, current, pageSize, total },
dataSource: tmpV,
columns
pageInfo: { ...pageInfo, current, pageSize, total }, dataSource: tmpV, columns
});
}
}).catch(() => {
@ -76,7 +59,7 @@ export default class LedgerSalaryItemAddModal extends React.Component {
case "useDefault":
case "hideDefault":
case "useInEmployeeSalary":
return <Switch checked={text === 1}/>;
return <WeaCheckbox value={String(text)} disabled display="switch"/>;
default:
return <div dangerouslySetInnerHTML={{ __html: valueSpan }}/>;
}
@ -85,10 +68,9 @@ export default class LedgerSalaryItemAddModal extends React.Component {
});
return newColumns;
};
handleAdd = () => {
const { dataSourceCopy, selectedRowKeys } = this.state;
const { onAddSalaryItems, id, onCancel, itemGroups } = this.props;
const { onAddSalaryItems, id, onCancel, itemGroups, record } = this.props;
const arrItems = _.find(itemGroups, it => it.uuid === id).items || [];
let selectItems = [];
_.uniqWith(dataSourceCopy, _.isEqual).map((item) => {
@ -104,12 +86,21 @@ export default class LedgerSalaryItemAddModal extends React.Component {
});
});
onCancel();
onAddSalaryItems(id, selectItems);
onAddSalaryItems(id, selectItems, record.id || record.key);
};
renderTitle = () => {
const { name, pageInfo } = this.state;
return <div className="sys-item-title">
<span>{getLabel(111, "添加薪资项目")}</span>
<WeaInputSearch value={name} onChange={val => this.setState({ name: val })} style={{ width: 200 }}
placeholder={getLabel(111, "请输入薪资项目名称")} onSearch={() => this.setState({
pageInfo: { ...pageInfo, current: 1 }
}, () => this.listSalaryItem())}/>
</div>;
};
render() {
const { onCancel, visible } = this.props;
const { name, selectedRowKeys, pageInfo, dataSource, loading } = this.state;
const { selectedRowKeys, pageInfo, dataSource, loading } = this.state;
const pagination = {
...pageInfo,
showTotal: total => `${total}`,
@ -117,49 +108,31 @@ export default class LedgerSalaryItemAddModal extends React.Component {
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
onShowSizeChange: (current, pageSize) => {
this.setState({
pageInfo: { ...pageInfo, current, pageSize }
}, () => this.listSalaryItem());
this.setState({ pageInfo: { ...pageInfo, current: 1, pageSize } }, () => this.listSalaryItem());
},
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => this.listSalaryItem());
this.setState({ pageInfo: { ...pageInfo, current } }, () => this.listSalaryItem());
}
};
const rowSelection = {
selectedRowKeys,
onChange: (selectedRowKeys) => {
this.setState({ selectedRowKeys }, () => {
});
}
selectedRowKeys, onChange: (selectedRowKeys) => this.setState({ selectedRowKeys })
};
return (
<WeaDialog
visible={visible} onCancel={onCancel} hasScroll
title="添加薪资项目" style={{
width: "80vw", height: 606.6, minHeight: 200,
minWidth: 380, maxHeight: "80%", maxWidth: "80vw",
overflow: "hidden", transform: "translate(0px, 0px)"
}}
buttons={[<Button type="primary" onClick={this.handleAdd} disabled={_.isEmpty(selectedRowKeys)}>添加</Button>]}
>
<div style={{ display: "flex", justifyContent: "flex-end", alignItems: "center", padding: 20 }}>
<WeaInputSearch
placeholder="请输入薪资项目名称"
value={name}
onChange={(name) => this.setState({ name })}
onSearch={() => this.listSalaryItem({ current: 1 })}
/>
<WeaDialog {...this.props} initLoadCss className="sys-salary-wrapper" ref={dom => this.sysItemRef = dom}
title={this.renderTitle()}
buttons={[<Button type="primary" onClick={this.handleAdd}
disabled={_.isEmpty(selectedRowKeys)}>{getLabel(111, "添加")}</Button>]}
style={{
width: "60vw", height: 600, minHeight: 200, minWidth: 380,
maxHeight: "90%", maxWidth: "90%", overflow: "hidden", transform: "translate(0px, 0px)"
}}>
<div className="sys-item-table-box">
<Spin spinning={loading.query && pageInfo.total === 0}>
<WeaTable columns={this.getSalaryItemAddColumns()} dataSource={dataSource} pagination={pagination}
loading={loading.query} scroll={{ y: this.sysItemRef ? this.sysItemRef.state.height - 112 : 600 }}
rowKey={record => record.id || record.key} rowSelection={rowSelection}/>
</Spin>
</div>
<WeaTable
rowKey={record => record.id || record.key}
rowSelection={rowSelection}
dataSource={dataSource}
pagination={pagination}
loading={loading.query}
columns={this.getSalaryItemAddColumns()}
/>
</WeaDialog>
);
}

View File

@ -22,7 +22,7 @@ class LedgerSalaryItemNormal extends Component {
constructor(props) {
super(props);
this.state = {
addCategoryItemsVisible: false,
addCategoryItemsVisible: { visible: false, id: "", record: {} },
categoryModal: {
visible: false,
title: "新增分类",
@ -170,7 +170,11 @@ class LedgerSalaryItemNormal extends Component {
onEditCategory={this.handleAddCategory}
onDeleteCategory={this.handleDeleteCategory}
onDeleteCategoryItems={this.handleDeleteCategoryItems}
onAddCategoryItems={(id) => this.setState({ addCategoryItemsVisible: { visible: true, id } })}
onAddCategoryItems={(id) => this.setState({
addCategoryItemsVisible: {
...addCategoryItemsVisible, visible: true, id
}
})}
onUpgo={this.handleUpgo}
onDowngo={this.handleDowngo}
/>
@ -178,13 +182,16 @@ class LedgerSalaryItemNormal extends Component {
>
<LedgerSalaryItemTable
tableData={items}
dataSource={_.find(dataSource, childItem => childItem.id === id || childItem.uuid === uuid).items}
dataSource={_.find(newDateSource, childItem => childItem.uuid === uuid).items}
salarySobId={editId || saveSalarySobId}
selectedRowKeys={field.selectedRowKeys || []}
onDropCategoryItem={(data) => onDropCategoryItem(field, data)}
onHandleItemhide={(data) => onHandleItemhide(field, data)}
onChangeSelectedRowKeys={(data) => onChangeSelectedRowKeys(field, data)}
onMoveTo={this.handleMoveTo}
onAddCategoryItems={(record) => this.setState({
addCategoryItemsVisible: { visible: true, record, id: uuid }
})}
/>
</WeaSearchGroup>;
})
@ -198,7 +205,7 @@ class LedgerSalaryItemNormal extends Component {
<LedgerSalaryItemAddModal
{...addCategoryItemsVisible}
itemGroups={dataSource}
onCancel={() => this.setState({ addCategoryItemsVisible: { visible: false, id: "" } })}
onCancel={() => this.setState({ addCategoryItemsVisible: { visible: false, id: "", record: {} } })}
onAddSalaryItems={onAddSalaryItems}
/>
<CategoryAddModal

View File

@ -128,8 +128,10 @@ class LedgerSalaryItemTable extends Component {
formulaContent, formulaId, name,
hideDefault: _.isNil(hideDefault) ? "0" : hideDefault,
valueType, roundingMode, pattern,
originFormulaContent, originSqlContent,
useInEmployeeSalary: !_.isNil(useInEmployeeSalary) ? useInEmployeeSalary : "0"
useInEmployeeSalary: !_.isNil(useInEmployeeSalary) ? useInEmployeeSalary : "0",
//不能改成其他空值
originFormulaContent: _.isNil(originFormulaContent) ? formulaContent : originFormulaContent,
originSqlContent: _.isNil(originSqlContent) ? formulaContent : originSqlContent
},
record,
userStatusList: _.map(userStatusList, it => ({ key: it.value.toString(), showname: it.defaultLabel }))
@ -288,18 +290,22 @@ class LedgerSalaryItemTable extends Component {
width: 80,
render: (text, record) => <WeaCheckbox
value={text ? String(text) : !text ? "0" : "1"}
onChange={value => this.handleChangeItem(value, record.id || record.key)}
onChange={value => {
this.handleChangeItem(value, record.id || record.key);
}}
/>
},
{
title: "操作",
dataIndex: "operate",
key: "operate",
width: 120,
width: 180,
render: (_, record) => (
<React.Fragment>
<a href="javascript:void(0);" onClick={() => this.handleEditSalaryItem(record)}
style={{ marginRight: 10 }}>编辑</a>
<a href="javascript:void(0);" onClick={() => this.props.onAddCategoryItems(record)}
style={{ marginRight: 10 }}>{getLabel(111, "插入")}</a>
<a href="javascript:void(0);" onClick={() => onMoveTo(record)}>移动到</a>
</React.Fragment>
)

View File

@ -87,7 +87,7 @@ class LedgerSlide extends Component {
* Date: 2022/12/12
*/
saveLedgerAdjustRule = () => {
const { adjustRules, saveSalarySobId } = this.state;
const { adjustRules, saveSalarySobId, salaryApprovalStatus } = this.state;
const payload = {
salarySobId: this.props.editId || saveSalarySobId,
ruleParams: adjustRules
@ -97,6 +97,7 @@ class LedgerSlide extends Component {
this.setState({ loading: false });
if (status) {
message.success("保存成功");
!salaryApprovalStatus && this.handleClose();
} else {
message.success(errormsg || "保存失败");
}
@ -260,7 +261,7 @@ class LedgerSlide extends Component {
<Button type="ghost"
onClick={() => this.setState({ current: current - 1 })}>{getLabel(111, "上一步")}</Button>,
<Button type="primary"
onClick={() => this.setState({ current: current + 1 }, () => this.saveLedgerAdjustRule())}>{getLabel(111, "保存并进入下一步")}</Button>
onClick={() => this.setState({ current: !salaryApprovalStatus ? current : current + 1 }, () => this.saveLedgerAdjustRule())}>{!salaryApprovalStatus ? getLabel(111, "完成") : getLabel(111, "保存并进入下一步")}</Button>
],
editBtns: [
<Button type="primary" loading={loading}

View File

@ -859,3 +859,76 @@ export const classifyConditions = [
defaultshow: true
}
];
export const ruleConditions = [//调薪计薪规则项表单
{
items: [
{
conditionType: "SELECT",
domkey: ["salaryItemId"],
fieldcol: 8,
rules: "required|string",
label: "薪资项目",
lanId: 111,
labelcol: 6,
value: "",
multiple: true,
viewAttr: 3
},
{
conditionType: "SELECT",
domkey: ["dayOfMonth"],
fieldcol: 6,
label: "如果:调薪生效日期在",
lanId: 111,
labelcol: 0,
value: "1",
viewAttr: 2
},
{
conditionType: "SELECT",
domkey: ["beforeAdjustmentType"],
fieldcol: 6,
label: "计薪规则为:",
lanId: 111,
labelcol: 0,
value: "2",
options: [
{ key: "2", showname: "取调整后薪资", lanId: 111 },
{
key: "4", showname: "分段计薪", lanId: 111, helpfultiplanId: 111,
helpfultip: "调整前薪资/当月自然日天数*调整前自然日天数+调整后薪资/当月自然日天数*调整后自然日天数"
},
{
key: "3", showname: "取平均", lanId: 111,
helpfultip: "(调整前薪资+调整后薪资)/2", helpfultiplanId: 111
}
],
detailtype: 3,
viewAttr: 2
},
{
conditionType: "SELECT",
domkey: ["afterAdjustmentType"],
fieldcol: 6,
label: "计薪规则为:",
lanId: 111,
labelcol: 0,
value: "1",
options: [
{ key: "1", showname: "取调整前薪资", lanId: 111 },
{
key: "4", showname: "分段计薪", lanId: 111, helpfultiplanId: 111,
helpfultip: "调整前薪资/当月自然日天数*调整前自然日天数+调整后薪资/当月自然日天数*调整后自然日天数"
},
{
key: "3", showname: "取平均", lanId: 111,
helpfultip: "(调整前薪资+调整后薪资)/2", helpfultiplanId: 111
}
],
detailtype: 3,
viewAttr: 2
}
],
defaultshow: true
}
];

View File

@ -599,6 +599,7 @@ export default class PayrollGrant extends React.Component {
<WeaTab
datas={topTab} keyParam="viewcondition" selectedKey={selectedKey} searchType={["base", "advanced"]}
onChange={v => this.setState({ selectedKey: v }, () => {
this.pageInfo = { current: 1, pageSize: 10 };
getInfoList({ salarySendId: currentId, isGranted: v !== "0" });
})}
searchsBasePlaceHolder="请输入姓名" showSearchAd={grantListShowSearchAd} buttonsAd={adBtn}
@ -652,7 +653,7 @@ export default class PayrollGrant extends React.Component {
this.pageInfo = { current, pageSize };
this.handleShowSizeChange(this.pageInfo);
}}
scroll={{ y: `calc(100vh - 236px)` }}
scroll={{ y: `calc(100vh - 255px)` }}
/> : renderLoading()
}
</div>

View File

@ -41,7 +41,7 @@ export const payrollTempNormalSetForm = (form, condition, background, onChange =
/>
}
{
getKey(fields) === "theme" && c.viewAttr === 3 &&
getKey(fields) === "theme" && fields.viewAttr === 3 &&
<div className="sft-variables">
<span className="sftv-tip">{getLabel(500143, "插入变量")}</span>
<a className="sftv-item"

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

@ -188,6 +188,15 @@ export const conditions = [
lanId: 111,
labelcol: 8,
viewAttr: 2
},
{
conditionType: "SWITCH",
domkey: ["SHOT_EMP_BTN"],
fieldcol: 10,
label: "启用人事信息快照",
lanId: 111,
labelcol: 8,
viewAttr: 2
}
],
title: "薪资核算",
@ -213,6 +222,16 @@ export const conditions = [
lanId: 111,
labelcol: 8,
viewAttr: 2
},
{
conditionType: "SELECT",
domkey: ["TAX_DECLARATION_DATE_TYPE"],
fieldcol: 10,
label: "申报日期类型",
lanId: 111,
labelcol: 8,
options: [],
viewAttr: 2
}
],
title: "算税规则",

View File

@ -73,6 +73,13 @@ class RuleConfig extends Component {
...o,
hide: sysinfo["SALARY_APPROVAL_STATUS"] === "0" || _.isNil(sysinfo["SALARY_APPROVAL_STATUS"])
};
} else if (getKey(o) === "TAX_DECLARATION_DATE_TYPE") {
return {
...o, options: [
{ key: "0", showname: getLabel(111, "薪资所属月"), selected: true },
{ key: "1", showname: getLabel(111, "税款所属期"), selected: false }
]
};
}
return { ...o };
})
@ -154,6 +161,8 @@ class RuleConfig extends Component {
case "APPROVAL_CAN_RE_CALC_STATUS":
case "APPROVAL_CAN_EDIT_RESULT_STATUS":
case "ATTENDANCE_SERIAL_COLLECTION_BTN":
case "TAX_DECLARATION_DATE_TYPE":
case "SHOT_EMP_BTN":
if (!this.handleDebounce) {
this.handleDebounce = _.debounce(() => {
const confTitle = {
@ -171,7 +180,9 @@ class RuleConfig extends Component {
APPROVAL_CAN_MANUAL_FILE_STATUS: getLabel(111, "开启审批的核算记录允许手动归档"),
APPROVAL_CAN_RE_CALC_STATUS: getLabel(111, "开启审批的核算记录允许重新核算"),
APPROVAL_CAN_EDIT_RESULT_STATUS: getLabel(111, "审批流程发起后允许修改核算数据"),
ATTENDANCE_SERIAL_COLLECTION_BTN: getLabel(111, "考勤引用是否采集班次数据")
ATTENDANCE_SERIAL_COLLECTION_BTN: getLabel(111, "考勤引用是否采集班次数据"),
TAX_DECLARATION_DATE_TYPE: getLabel(111, "申报日期类型"),
SHOT_EMP_BTN: getLabel(111, "启用组织快照"),
};
this.unifiedSettings(key, confTitle[key]);
this.handleDebounce = null;

View File

@ -150,7 +150,7 @@ class PersonalScopeModal extends Component {
<Button type="ghost" onClick={() => personScopeForm.resetForm()}>{getLabel(111, "重置")}</Button>
];
return (
<WeaDialog {...this.props} initLoadCss title={title} style={{ width: 600 }} buttons={buttons}>
<WeaDialog {...this.props} initLoadCss title={title} style={{ width: 600, height: 159 }} buttons={buttons}>
<div className="form-dialog-layout">{this.renderForm()}</div>
</WeaDialog>
);

View File

@ -78,14 +78,12 @@ class SyncToSalaryAccountSetDialog extends Component {
const { conditions } = this.state;
return (
<WeaDialog
{...this.props} className="salarySetDialog" initLoadCss
style={{ width: 480 }} title={getLabel(111, "请选择薪资账套")}
{...this.props} className="salarySetDialog" initLoadCss title={getLabel(111, "请选择薪资账套")}
style={{ width: 480, height: _.reduce(conditions, (pre, cur) => (pre += cur.items.length), 0) * 47 + 33 }}
buttons={[<Button type="primary" onClick={this.save}
loading={this.state.loading}>{getLabel(537558, "确定")}</Button>]}
>
<div className="salarySetDialogContent">
{getSearchs(salarySetform, conditions, 1)}
</div>
<div className="salarySetDialogContent"> {getSearchs(salarySetform, conditions, 1, false)} </div>
</WeaDialog>
);
}

View File

@ -50,7 +50,7 @@ export default class SystemSalaryItemModal extends React.Component {
return <div className="sys-item-title">
<span>{getLabel(111, "添加系统薪资项目")}</span>
<WeaInputSearch value={name} onChange={val => this.setState({ name: val })} style={{ width: 200 }}
placeholder={getLabel(111, "请输入薪资项目名称")} a onSearch={() => this.setState({
placeholder={getLabel(111, "请输入薪资项目名称")} onSearch={() => this.setState({
pageInfo: { ...pageInfo, current: 1 }
}, () => this.getSysItemList())}/>
</div>;
@ -92,7 +92,7 @@ export default class SystemSalaryItemModal extends React.Component {
<div className="sys-item-table-box">
<Spin spinning={loading && pageInfo.total === 0}>
<WeaTable columns={columns} dataSource={dataSource} pagination={pagination} rowSelection={rowSelection}
loading={loading} scroll={{ y: this.importRef ? this.sysItemRef.state.height - 16 : 600 }}
loading={loading} scroll={{ y: this.sysItemRef ? this.sysItemRef.state.height - 16 : 600 }}
rowKey="id"/>
</Spin>
</div>

View File

@ -4,12 +4,16 @@
height: 100%;
background: #f6f6f6;
.wea-tab {
border-bottom: none !important;
}
.wea-new-top-req-wapper .wea-new-top-req {
z-index: 0 !important;
}
.wea-search-tab, .wea-input-focus {
background: #f6f6f6;
background: #f1f1f1;
}
.normalWapper {

View File

@ -118,7 +118,7 @@ class Index extends Component {
} else if (getKey(g).indexOf("StartTime") !== -1) {
return {
...g, label: getLabel(g.lanId, g.label),
viewAttr: (formData[o["typename"]][`${o.title}Name`] && showOperateBtn) ? 3 : g.viewAttr
viewAttr: (runStatuses === "4,5" || !showOperateBtn) ? 1 : (formData[o["typename"]][`${o.title}Name`] && showOperateBtn) ? 3 : g.viewAttr
};
}
return {

View File

@ -84,7 +84,7 @@ class PlanSetTable extends Component {
com: [{
type: "custom",
key: "custom",
render: text => (<span>{text}</span>)
render: text => (<span className="text-td-elli" title={text}>{text}</span>)
}]
},
{

View File

@ -232,6 +232,14 @@
text-overflow: ellipsis;
overflow: hidden;
}
.text-td-elli {
display: inline-block;
width: 120px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}

View File

@ -19,7 +19,6 @@ import SalaryItemList from "./components/salaryItemList";
import SalaryFileList from "./components/salaryFileList";
import SalaryFileImportDialog from "./components/salaryFileImportDialog";
import { Button, message } from "antd";
import cs from "classnames";
import "./index.less";
const getLabel = WeaLocaleProvider.getLabel;

View File

@ -1,64 +1,14 @@
import { action, observable } from "mobx";
import { message } from "antd";
import { WeaForm, WeaLogView } from "comsMobx";
import { WeaLocaleProvider } from "ecCom";
import { WeaForm } from "comsMobx";
import * as API from "../apis"; // 引入API接口文件
const { LogStore } = WeaLogView;
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 // 初始化操作: 一般用来初始化获取后台数据
doInit = () => {
this.getBaseForm();
};
@action // 获得form配置数据
getBaseForm = () => {
API.getBaseForm().then(action(result => {
this.loading = false;
this.hasRight = result.hasRight;
if (result.hasRight) {
this.condition = result.condition;
this.form.initFormFields(result.condition);
}
}));
};
@action // 保存
saveForm = () => {
this.form.validateForm().then(action(f => { // 表单的校验: 直接使用form的validateForm方法即可
if (f.isValid) { // 校验听过: 走保存接口
this.saveLoading = true;
const params = this.form.getFormParams();
API.saveForm(params).then(action(
result => {
this.saveLoading = false;
if (result.api_status) { // 保存成功: 1、给出提示 2、刷新form数据
message.success(`${getLabel(18758, "保存成功")}`);
this.getBaseForm();
} else {
message.error(`${getLabel(22620, "保存失败")}`);
}
}
));
} else {
f.showErrors();
}
}));
};
@action
@action("日志显隐开关")
setLogVisible = bool => this.logVisible = bool;
}

View File

@ -17,7 +17,8 @@ export class LedgerStore {
@action initAARForm = (v) => this.AARForm = new WeaForm();//重置核算审批规则form
@action initAARClassifyForm = (v) => this.AARClassifyForm = new WeaForm();//重置审批规则分类编辑form
@observable ruleForm = new WeaForm(); // 调薪计薪规则项form
@action initRuleForm = (v) => this.ruleForm = new WeaForm();//重置调薪计薪规则项form
/*******************************************************/
@observable tableStore = new TableStore(); // new table

View File

@ -39,6 +39,10 @@
.form-dialog-layout {
background: #f6f6f6;
.wea-form-item-wrapper {
display: block !important;
}
.wea-form-item .wea-form-item-wrapper .wea-field-readonly {
line-height: 28px;
}
@ -57,7 +61,7 @@
}
.ant-select-selection {
height: 30px;
height: 28px;
border-radius: 0;
}
@ -128,3 +132,10 @@
}
}
//公共表格操作按钮间距
.space_div {
a:not(:last-child) {
margin-right: 8px;
}
}

View File

@ -38,7 +38,13 @@ export const getSearchs = (form, condition, col, isCenter, onChange = () => void
items.push({
com: (
<WeaFormItem
label={`${fields.label}`} // label 标签的文本
label={<span>
<span>{`${fields.label}`}</span>
{
fields.labelExtra && <span className="wea-form-item-label-extra"
onClick={() => onChange(fields.labelType)}>{fields.labelExtra}</span>
}
</span>} // label 标签的文本
labelCol={{ span: `${fields.labelcol}` }} // label标签占一行比例
wrapperCol={{ span: `${fields.fieldcol}` }} // 右侧控件占一行比例
error={form.getError(fields)} // 错误提示: 处理表单中有必填项,保存的校验