Merge branch 'master' into feature/v2-对接e10个税扣缴义务人设置-1121

# Conflicts:
#	pc4mobx/hrmSalary/util/index.js
This commit is contained in:
黎永顺 2023-07-18 09:35:33 +08:00
commit 37cb0f050a
283 changed files with 28807 additions and 13210 deletions

View File

@ -273,14 +273,14 @@ export const importAttendQuoteData = (params) => {
};
// 查看考勤详情
export const viewAttendQuote = (ids) => {
export const viewAttendQuote = (params) => {
return fetch("/api/bs/hrmsalary/attendQuote/view", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(ids),
body: JSON.stringify(params),
}).then((res) => res.json());
};

View File

@ -333,6 +333,17 @@ export const fileSalaryAcct = (params) => {
}
}).then(res => res.json());
};
// 薪资记录-回算
export const backCalculate = (params) => {
return fetch("/api/bs/hrmsalary/salaryacct/backCalculate", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
// 薪资记录-重新核算
export const reAccounting = (params) => {
@ -498,3 +509,62 @@ export const updateLockStatus = (params) => {
body: JSON.stringify(params)
}).then(res => res.json());
};
// 社保福利台账合计接口
export const siaccountDetailCommonListSum = (params) => {
return fetch("/api/bs/hrmsalary/siaccount/detail/common/list/sum", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
// 社保福利台账补缴合计接口
export const siaccountDetailSupplementaryListSum = (params) => {
return fetch("/api/bs/hrmsalary/siaccount/detail/supplementary/list/sum", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
// 社保福利台账退差合计接口
export const siaccountDetailRecessionListSum = (params) => {
return fetch("/api/bs/hrmsalary/siaccount/detail/recession/list/sum", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
// 社保福利台账补差合计接口
export const siaccountDetailBalanceListSum = (params) => {
return fetch("/api/bs/hrmsalary/siaccount/detail/balance/list/sum", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
// 导入薪资核算添加表头字段缓存
export const cacheImportField = (params) => {
return fetch("/api/bs/hrmsalary/salaryacct/acctresult/cacheImportField", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
//薪资核算-页面查看权限
export const salaryacctAcctresultCheckAuth = params => {
return WeaTools.callApi("/api/bs/hrmsalary/salaryacct/acctresult/checkAuth", "GET", params);
};

View File

@ -1,5 +1,5 @@
import { WeaTools } from "ecCom";
import { postFetch } from '../util/request';
import { postFetch } from "../util/request";
//数据采集-累计专项附加扣除列表
export const getCumDeductList = (params) => {
@ -7,9 +7,9 @@ export const getCumDeductList = (params) => {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(params),
body: JSON.stringify(params)
}).then((res) => res.json());
};
@ -52,9 +52,9 @@ export const getCumDeductDetailList = (params) => {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(params),
body: JSON.stringify(params)
}).then((res) => res.json());
};
@ -62,9 +62,9 @@ export const getCumDeductDetailList = (params) => {
export const exportCumDeductDetailList = (id, ids = "") => {
fetch(
"/api/bs/hrmsalary/addUpDeduction/exportDetail?accumulatedSpecialAdditionalDeductionId=" +
id +
"&ids=" +
ids+ "&taxAgentId=" + taxAgentId
id +
"&ids=" +
ids + "&taxAgentId=" + taxAgentId
).then((res) =>
res.blob().then((blob) => {
var filename = `累计专项附加扣除.xlsx`;
@ -84,9 +84,9 @@ export const importCumDeductParam = (params) => {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(params),
body: JSON.stringify(params)
}).then((res) => res.json());
};
@ -96,34 +96,44 @@ export const importCumDeductPreview = (params) => {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(params),
body: JSON.stringify(params)
}).then((res) => res.json());
};
//新增累计专项附加扣除
export const createAddUpDeduction = (params) => {
return postFetch('/api/bs/hrmsalary/addUpDeduction/createAddUpDeduction', params);
}
return postFetch("/api/bs/hrmsalary/addUpDeduction/createAddUpDeduction", params);
};
//查看信息
export const getAddUpDeduction = (params) => {
return postFetch('/api/bs/hrmsalary/addUpDeduction/getAddUpDeduction', params);
}
return postFetch("/api/bs/hrmsalary/addUpDeduction/getAddUpDeduction", params);
};
//编辑累计专项附加扣除
export const editAddUpDeduction = (params) => {
return postFetch('/api/bs/hrmsalary/addUpDeduction/editAddUpDeduction', params);
}
return postFetch("/api/bs/hrmsalary/addUpDeduction/editAddUpDeduction", params);
};
//批量删除累计专项附加扣除
export const deleteSelectAddUpDeduction = (params) => {
return postFetch('/api/bs/hrmsalary/addUpDeduction/deleteSelectAddUpDeduction', params);
}
return postFetch("/api/bs/hrmsalary/addUpDeduction/deleteSelectAddUpDeduction", params);
};
//一键清空累计专项附加扣除
export const deleteAllAddUpDeduction = (params) => {
return postFetch('/api/bs/hrmsalary/addUpDeduction/deleteAllAddUpDeduction', params);
}
return postFetch("/api/bs/hrmsalary/addUpDeduction/deleteAllAddUpDeduction", params);
};
//一键累计
export const autoAddAll = (params) => {
return postFetch('/api/bs/hrmsalary/addUpDeduction/autoAddAll', params);
}
return postFetch("/api/bs/hrmsalary/addUpDeduction/autoAddAll", params);
};
//数据采集列表查询
export const getTableDate = ({ url, ...params }) => {
return postFetch(url, params);
};
//数据采集列表详情记录查询
export const getTableRecordDate = ({ url, ...params }) => {
return postFetch(url, params);
};

View File

@ -1,4 +1,5 @@
import { WeaTools } from 'ecCom';
import { postFetch } from '../util/request';
//个税申报表-个税申报表列表
export const getDeclareList = params => {
@ -7,7 +8,7 @@ export const getDeclareList = params => {
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
},
body: JSON.stringify(params)
}).then(res => res.json())
}
@ -24,7 +25,7 @@ export const saveDeclare = params => {
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
},
body: JSON.stringify(params)
}).then(res => res.json())
}
@ -41,7 +42,7 @@ export const getDetailList = params => {
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
},
body: JSON.stringify(params)
}).then(res => res.json())
}
@ -52,13 +53,16 @@ export const exportSalaryArchive = (id = "") => {
fetch('/api/bs/hrmsalary/taxdeclaration/export?taxDeclarationId=' + id).then(res => res.blob().then(blob => {
var filename=`个税申报表.xlsx`
var a = document.createElement('a');
var url = window.URL.createObjectURL(blob);
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
}))
}
//个税申报表-撤回申报
export const withDrawTaxDeclaration = (params) => {
return postFetch('/api/bs/hrmsalary/taxdeclaration/withDrawTaxDeclaration', params);
}

View File

@ -0,0 +1,20 @@
import { WeaTools } from "ecCom";
import { postFetch } from "../util/request";
//获取编辑详情
export const getSalaryFieldForm = (params) => {
return WeaTools.callApi("/api/bs/hrmsalary/salaryField/getSalaryForm", "GET", params);
};
// 字段管理查询
export const salaryFieldList = (params) => {
return postFetch('/api/bs/hrmsalary/salaryField/list', params);
}
// 字段管理查询
export const saveSalaryField = (params) => {
return postFetch('/api/bs/hrmsalary/salaryField/save', params);
}
// 删除字段管理
export const deleteSalaryField = (params) => {
return postFetch('/api/bs/hrmsalary/salaryField/delete', params);
}

View File

@ -70,6 +70,7 @@ export const deleteItemList = params => {
//薪资项目-新增薪资项目
export const saveItem = params => {
delete params.formulaContent
return fetch('/api/bs/hrmsalary/salaryitem/save', {
method: 'POST',
mode: 'cors',
@ -106,6 +107,10 @@ export const saveSysItem = params => {
export const getItemTypeOption = params => {
return WeaTools.callApi('/api/bs/hrmsalary/salaryitem/listSalaryItemTypeOption', 'GET', params);
}
//获取公式描述
export const getFormulaDes = params => {
return WeaTools.callApi('/api/bs/hrmsalary/formula/des', 'GET', params);
}
// *** 公式 start ***
// 获取公式变量类型
@ -144,6 +149,17 @@ export const saveFormual = params => {
body: JSON.stringify(params)
}).then(res => res.json())
}
// 公式测试
export const testFormual = params => {
return fetch('/api/bs/hrmsalary/formula/mock', {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
}).then(res => res.json())
}
// 根据id获取formual
export const detailFormual = params => {

View File

@ -139,13 +139,32 @@ export const getLedgerItemGroupForm = params => {
//保存薪资帐套薪资项目
export const saveLedgerItem = params => {
const { itemGroups, items, ...extra } = params;
const payload = {
itemGroups: _.map(itemGroups, item => {
return {
...item,
items: _.map(item.items, it => {
delete it.formulaContent;
return { ...it };
})
};
}),
items: _.map(items, child => {
delete child.formulaContent;
return { ...child };
}) || [],
...extra
};
return fetch("/api/bs/hrmsalary/salarysob/item/save", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
body: JSON.stringify(payload)
}).then(res => res.json());
};
@ -268,3 +287,25 @@ export const listAdjustmentRule = params => {
body: JSON.stringify(params)
}).then(res => res.json());
};
//获取回算薪资项目
export const getAggregate = params => {
return WeaTools.callApi("/api/bs/hrmsalary/salarysob/backitem/getAggregate", "GET", params);
};
//编辑回算薪资项目详情
export const getBackitemForm = params => {
return WeaTools.callApi("/api/bs/hrmsalary/salarysob/backitem/getForm", "GET", params);
};
//保存回算薪资项目详情
export const salarysobBackitemSave = params => {
return postFetch("/api/bs/hrmsalary/salarysob/backitem/save", params);
};
//预览人员范围导入
export const salarysobRangePreview = params => {
return postFetch("/api/bs/hrmsalary/salarysob/range/preview", params);
};
//导入人员范围
export const salarysobRangeImportData = params => {
return postFetch("/api/bs/hrmsalary/salarysob/range/importData", params);
};

View File

@ -1,29 +1,45 @@
import { WeaTools } from 'ecCom';
import { WeaTools } from "ecCom";
// 工资单列表
export const mySalaryBillList = params => {
return fetch('/api/bs/hrmsalary/salaryBill/mySalaryBillList', {
method: 'POST',
mode: 'cors',
return fetch("/api/bs/hrmsalary/salaryBill/mySalaryBillList", {
method: "POST",
mode: "cors",
headers: {
'Content-Type': 'application/json'
},
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json())
}).then(res => res.json());
};
// 社保福利列表
export const welfareList = params => {
return WeaTools.callApi('/api/bs/hrmsalary/report/welfare/list', 'GET', params);
return WeaTools.callApi("/api/bs/hrmsalary/report/welfare/list", "GET", params);
};
// 调薪记录列表
export const recordList = params => {
return WeaTools.callApi('/api/bs/hrmsalary/report/record/list', 'GET', params);
return WeaTools.callApi("/api/bs/hrmsalary/report/record/list", "GET", params);
};
// 工资查看详情
export const mySalaryBill = params => {
return WeaTools.callApi('/api/bs/hrmsalary/salaryBill/mySalaryBill', 'GET', params);
};
return WeaTools.callApi("/api/bs/hrmsalary/salaryBill/mySalaryBill", "GET", params);
};
export const isNeedSecondPwdVerify = params => {
return WeaTools.callApi("/api/encrypt/secondauthsetting/isNeedSecondAuth", "POST", params);
};
export const getSecondAuthForm = params => {
return WeaTools.callApi("/api/encrypt/secondauthsetting/getSecondAuthForm", "POST", params);
};
export const doSecondAuth = params => {
return WeaTools.callApi("/api/encrypt/secondauthsetting/doSecondAuth", "POST", params);
};
export const checkPassword = params => {
return WeaTools.callApi("/api/hrm/secondarypwd/checkPassword", "POST", params);
};
export const saveSecondaryPwd = params => {
return WeaTools.callApi("/api/hrm/secondarypwd/saveSecondaryPwd", "POST", params);
};

View File

@ -1,4 +1,5 @@
import { WeaTools } from "ecCom";
import { postFetch } from "../util/request";
//工资单-工资单发放列表
export const getPayrollList = params => {
@ -11,6 +12,10 @@ export const getPayrollList = params => {
body: JSON.stringify(params)
}).then(res => res.json());
};
// 工资单发放进度条
export const getPayrollIssuanceProgressBar = (id) => {
return WeaTools.callApi("/api/bs/hrmsalary/progress/getRate?cacheKey=SALARY_GRANT_PROGRESS_" + id, "get", {});
};
//工资单-获取table提示信息
export const getPayrollInfo = params => {
@ -174,13 +179,14 @@ export const savePayroll = params => {
//工资单-编辑工资单
export const updatePayroll = params => {
const { background, ...extra } = params;
return fetch("/api/bs/hrmsalary/salaryBill/template/update", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
body: JSON.stringify({ background: _.isNil(background) ? "" : background, ...extra })
}).then(res => res.json());
};
@ -313,3 +319,72 @@ export const grantProxy = params => {
body: JSON.stringify(params)
}).then(res => res.json());
};
// 工资单发放-新建时获取补发工资单模板薪资项目设置
export const getReplenishForm = params => {
return fetch("/api/bs/hrmsalary/salaryBill/template/getReplenishForm", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
// 工资单发放-获取规则设置下拉框
export const getReplenishRuleSetOptions = ({ salarySobId }) => {
return fetch(`/api/bs/hrmsalary/salaryBill/template/getReplenishRuleSetOptions?salarySobId=${salarySobId}`, {
method: "GET",
mode: "cors",
headers: {
"Content-Type": "application/json"
}
}).then(res => res.json());
};
//添加发送和撤回人员范围列表
export const sendRangeList = (params) => {
return postFetch("/api/bs/hrmsalary/salaryBill/send/range/list", params);
};
//创建范围
export const sendRangeSave = (params) => {
return postFetch("/api/bs/hrmsalary/salaryBill/send/range/save", params);
};
//刪除范围
export const sendRangeDelete = (params) => {
return postFetch("/api/bs/hrmsalary/salaryBill/send/range/delete", params);
};
//工资单模板-获取模板可用的分组
export const getAvailableSalaryGroupSet = (params) => {
return postFetch("/api/bs/hrmsalary/salaryBill/template/getAvailableSalaryGroupSet", params);
};
//工资单模板-获取模板分组下可用的薪资项目
export const getAvailableSalaryItemSet = (params) => {
return postFetch("/api/bs/hrmsalary/salaryBill/template/getAvailableSalaryItemSet", params);
};
//工资单发放-查看详情页面列表合计行数据
export const salaryBillSendSum = (params) => {
return postFetch("/api/bs/hrmsalary/salaryBill/send/sum", params);
};
//工资单发放-发送短信验证码
export const sendMobileCode = (params) => {
return postFetch("/api/bs/hrmsalary/salaryBill/sendMobileCode", params);
};
//工资单-验证方式
export const payrollCheckType = params => {
return WeaTools.callApi("/api/bs/hrmsalary/salaryBill/payrollCheckType", "GET", params);
};
// 工资单基础设置-获取设置列表
export const getSalaryBillBaseSetForm = (id) => {
return WeaTools.callApi("/api/bs/hrmsalary/salaryBill/baseSet/getForm", "get", {});
};
//工资单基础设置-保存工资单基础设置(设置水印)
export const salaryBillBaseSetSave = (params) => {
return postFetch("/api/bs/hrmsalary/salaryBill/baseSet/save", params);
};
//工资单基础设置-保存工资单基础设置(水印预览)
export const salaryBillBaseSetPreviewWaterMark = (params) => {
return postFetch("/api/bs/hrmsalary/salaryBill/baseSet/previewWaterMark", params);
};

View File

@ -65,3 +65,11 @@ export const deletePendingTodo = (params) => {
export const deleteSuspendTodo = (params) => {
return postFetch('/api/bs/hrmsalary/salaryArchive/deleteSuspendTodo', params);
}
// 待定薪、停薪员工 是否允许删除薪资档案
export const salaryArchiveDelete = (params) => {
return WeaTools.callApi('/api/bs/hrmsalary/sys/conf/code?code=salaryArchiveDelete', 'GET', params);
}
// 删除薪资档案
export const deleteSalaryArchive = (params) => {
return postFetch('/api/bs/hrmsalary/salaryArchive/deleteSalaryArchive', params);
}

View File

@ -1,45 +1,65 @@
import { WeaTools } from 'ecCom';
import { postFetch } from '../util/request';
import { WeaTools } from "ecCom";
import { postFetch } from "../util/request";
//通用字典表 {enumClass:""}
export const commonEnumList = (params) => {
return WeaTools.callApi('/api/bs/hrmsalary/common/enum/list', 'GET', params);
}
return WeaTools.callApi("/api/bs/hrmsalary/common/enum/list", "GET", params);
};
export const sysOrderRule = params => {
return WeaTools.callApi('/api/bs/hrmsalary/sys/orderRule', 'GET', params);
}
return WeaTools.callApi("/api/bs/hrmsalary/sys/orderRule", "GET", params);
};
//保存排序规则
export const updateOrderRule = (params) => {
return postFetch('/api/bs/hrmsalary/sys/updateOrderRule', params);
}
return postFetch("/api/bs/hrmsalary/sys/updateOrderRule", params);
};
//导入规则详情信息
export const sysConfCodeRule = params => {
return WeaTools.callApi('/api/bs/hrmsalary/sys/conf/code', 'GET', params);
}
return WeaTools.callApi("/api/bs/hrmsalary/sys/conf/code", "GET", params);
};
//保存导入规则
export const saveMatchEmployeeModeRule = (params) => {
return postFetch('/api/bs/hrmsalary/sys/saveMatchEmployeeModeRule', params);
}
return postFetch("/api/bs/hrmsalary/sys/saveMatchEmployeeModeRule", params);
};
//应用配置查询
export const queryAppsetting = (params) => {
return WeaTools.callApi('/api/bs/hrmsalary/sys/app/setting', 'GET', params);
}
return WeaTools.callApi("/api/bs/hrmsalary/sys/app/setting", "GET", params);
};
//加密配置保存
export const saveEncryptSetting = (params) => {
return postFetch('/api/bs/hrmsalary/sys/app/setting/saveEncryptSetting', params);
}
return postFetch("/api/bs/hrmsalary/sys/app/setting/saveEncryptSetting", params);
};
//加密配置保存
export const appSettingSave = (params) => {
return postFetch('/api/bs/hrmsalary/sys/app/setting/save', params);
}
return postFetch("/api/bs/hrmsalary/sys/app/setting/save", params);
};
//获取加密进度条
export const getEncryptProgress = params => {
return WeaTools.callApi('/api/bs/hrmsalary/sys/app/getEncryptProgress', 'GET', params);
}
return WeaTools.callApi("/api/bs/hrmsalary/sys/app/getEncryptProgress", "GET", params);
};
//保存报税规则
export const operateTaxDeclarationFunction = (params) => {
return postFetch('/api/bs/hrmsalary/sys/operateTaxDeclarationFunction', params);
}
return postFetch("/api/bs/hrmsalary/sys/operateTaxDeclarationFunction", params);
};
//保存档案删除规则
export const saveArchiveDelete = (params) => {
return postFetch("/api/bs/hrmsalary/sys/saveArchiveDelete", params);
};
//保存个税申报撤回规则
export const saveWithDrawTaxDeclaration = (params) => {
return postFetch("/api/bs/hrmsalary/sys/saveWithDrawTaxDeclaration", params);
};
//保存匹配规则
export const saveSalaryAcctEmployeeRule = (params) => {
return postFetch("/api/bs/hrmsalary/sys/saveSalaryAcctEmployeeRule", params);
};
//保存薪酬统计报表
export const reportStatisticsReportSave = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/report/save", params);
};
//薪酬统计维度下拉列表
export const reportGetForm = params => {
return WeaTools.callApi("/api/bs/hrmsalary/report/statistics/report/getForm", "GET", params);
};

View File

@ -202,6 +202,14 @@ export const getWelfareList = () => {
{}
);
};
// 补差表单字段对应的接口
export const getBalanceWelfareList = () => {
return WeaTools.callApi(
"/api/bs/hrmsalary/siaccount/getBalanceWelfareList",
"get",
{}
);
};
// 社保福利台账-导入预览
export const welfarePreview = (params) => {
@ -226,6 +234,17 @@ export const importInsuranceAcctDetail = (params) => {
body: JSON.stringify(params)
}).then((res) => res.json());
};
// 社保福利台账-补差数据导入
export const importBalanceInsuranceDetail = (params) => {
return fetch("/api/bs/hrmsalary/siaccount/welfare/importBalanceInsuranceDetail", {
method: "post",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then((res) => res.json());
};
// 社保福利台账-线下对比数据导入
export const importExcelInsuranceDetail = (params) => {
@ -251,14 +270,30 @@ export const saveRecession = (params) => {
export const recessionList = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/detail/recession/list", params);
};
//查询补差列表
export const balanceList = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/detail/balance/list", params);
};
//删除退差数据
export const delRecession = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/delRecession", params);
};
//删除补差数据
export const delBalance = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/delBalance", params);
};
//编辑社保福利缴纳数据
export const editAccount = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/editAccount", params);
};
//获取指定月份的福利基数
export const getSupplementPaymentForm = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/detail/getSupplementPaymentForm", params);
};
//获取待编辑的补缴费用相关福利项
export const getPaymentGroup = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/detail/getPaymentGroup", params);
};
//获取核算项个人和公司社保福利缴纳详情
export const getPaymentById = ({ id }) => {
return fetch(`/api/bs/hrmsalary/siaccount/getPaymentById?id=${id}`, {
@ -266,6 +301,41 @@ export const getPaymentById = ({ id }) => {
mode: "cors",
headers: {
"Content-Type": "application/json"
},
}
}).then(res => res.json());
};
//获取社保福利项列表
export const compensationCategoryType = ({ id }) => {
return fetch(`/api/bs/hrmsalary/siaccount/compensationCategoryType?id=${id}`, {
method: "GET",
mode: "cors",
headers: {
"Content-Type": "application/json"
}
}).then(res => res.json());
};
//获取调差列表
export const getCompensationList = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/compensationList", params);
};
//获取可调差的人员列表
export const getEmployeeListToCompensation = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/getEmployeeListToCompensation", params);
};
//获取当前调差行-公司方支出总计
export const getCompensationComTotal = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/compensationComTotal", params);
};
//社保调差保存
export const compensationSave = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/compensationSave", params);
};
//社保调差默认配置保存
export const compensationConfigSave = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/compensationConfigSave", params);
};
//撤回调差数据
export const compensationBack = (params) => {
return postFetch("/api/bs/hrmsalary/siaccount/compensationBack", params);
};

View File

@ -0,0 +1,80 @@
import { WeaTools } from "ecCom";
import { postFetch } from "../util/request";
//薪酬统计维度下拉列表
export const dimensionGetForm = (params) => {
return WeaTools.callApi("/api/bs/hrmsalary/report/statistics/dimension/getForm", "GET", params);
};
//获取自定义统计项目表单
export const statisticsItemGetform = (params) => {
return WeaTools.callApi("/api/bs/hrmsalary/report/statistics/item/getForm", "GET", params);
};
//自定义统计项目列表
export const statisticsItemList = (params) => {
return WeaTools.callApi("/api/bs/hrmsalary/report/statistics/item/list", "GET", params);
};
// 保存薪酬统计维度
export const dimensionSave = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/dimension/save", params);
};
// 薪酬统计维度列表
export const dimensionList = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/dimension/list", params);
};
// 删除薪酬统计维度
export const dimensionDelete = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/dimension/delete", params);
};
//保存薪酬统计报表
export const reportStatisticsReportList = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/report/list", params);
};
//删除薪酬统计报表
export const reportStatisticsReportDelete = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/report/delete", params);
};
//获取薪酬统计报表数据
export const reportStatisticsReportGetData = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/report/getData", params);
};
//保存自定义统计项目
export const reportStatisticsItemSave = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/item/save", params);
};
//保存数据范围及负责设置
export const reportStatisticsSaveSearchCondition = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/report/saveSearchCondition", params);
};
//删除自定义统计项目
export const reportStatisticsItemDelete = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/item/delete", params);
};
//获取薪酬统计报表查询条件
export const reportStatisticsGetSearchCondition = (params) => {
return WeaTools.callApi("/api/bs/hrmsalary/report/statistics/report/getSearchCondition", "GET", params);
};
//分析图数据展示范围设置查询
export const queryRangeSetting = (params) => {
return WeaTools.callApi("/api/bs/hrmsalary/report/statistics/echarts/queryRangeSetting", "GET", params);
};
//分析图数据展示范围设置删除
export const deleteRangeSetting = (params) => {
return WeaTools.callApi("/api/bs/hrmsalary/report/statistics/echarts/deleteRangeSetting", "GET", params);
};
//分析图数据展示范围设置保存
export const saveRangeSetting = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/echarts/saveRangeSetting", params);
};
//员工列表
export const statisticsEmployeeList = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/employee/list", params);
};
//员工详情列表
export const statisticsEmployeeDetailList = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/employee/detailList", params);
};
//数据透视-列表查询
export const getDataPerspective = (params) => {
return postFetch("/api/bs/hrmsalary/report/statistics/report/getDataPerspective", params);
};

View File

@ -86,6 +86,14 @@ export const getTaxAgentRangeListExclude = (params) => {
export const getTaxAgentRangeForm = (params) => {
return postFetch("/api/bs/hrmsalary/taxAgent/range/getForm", params);
};
//预览个税扣缴义务人中人员范围
export const taxAgentRangePreview = (params) => {
return postFetch("/api/bs/hrmsalary/taxAgent/range/preview", params);
};
//导入个税扣缴义务人中人员范围
export const taxAgentRangeImportData = (params) => {
return postFetch("/api/bs/hrmsalary/taxAgent/range/importData", params);
};
//个税扣缴义务人下拉列表
export const getTaxAgentSelectList = (params) => {

View File

@ -1,142 +1,150 @@
import { WeaTools } from 'ecCom';
import { WeaTools } from "ecCom";
import { postFetch } from "../util/request";
export const tips = params => {
return WeaTools.callApi('/api/bs/hrmsalary/archives/tips', 'get', params);
return WeaTools.callApi("/api/bs/hrmsalary/archives/tips", "get", params);
};
export const getCondition = params => {
return WeaTools.callApi('/api/bs/hrmsalary/archives/getSearchCondition', 'get', params);
return WeaTools.callApi("/api/bs/hrmsalary/archives/getSearchCondition", "get", params);
};
//社保福利档案列表
export const queryList = (params) => {
return postFetch('/api/bs/hrmsalary/archives/getTable', params);
return postFetch("/api/bs/hrmsalary/archives/getTable", params);
};
//社保福利档案列表
export const queryInsuranceTabTotal = (params) => {
return WeaTools.callApi('/api/bs/hrmsalary/archives/queryInsuranceTabTotal', params);
return WeaTools.callApi("/api/bs/hrmsalary/archives/queryInsuranceTabTotal", params);
};
//删除待办
//删除待办-待增员
export const updateRunStatus = (params) => {
return postFetch('/api/bs/hrmsalary/archives/updateRunStatus', params);
return postFetch("/api/bs/hrmsalary/archives/updateRunStatus", params);
};
//删除待办-待减员
export const cancelStayDel = (params) => {
return postFetch("/api/bs/hrmsalary/archives/cancelStayDel", params);
};
//全量增员
export const allStayAddToPay = (params) => {
return WeaTools.callApi('/api/bs/hrmsalary/archives/allStayAddToPay', 'GET', params);
return WeaTools.callApi("/api/bs/hrmsalary/archives/allStayAddToPay", "GET", params);
};
//全量减员
export const allStayDelToStop = (params) => {
return WeaTools.callApi('/api/bs/hrmsalary/archives/allStayDelToStop', 'GET', params);
return WeaTools.callApi("/api/bs/hrmsalary/archives/allStayDelToStop", "GET", params);
};
//增员
export const stayAddToPay = (params) => {
return postFetch('/api/bs/hrmsalary/archives/stayAddToPay', params);
return postFetch("/api/bs/hrmsalary/archives/stayAddToPay", params);
};
//减员
export const stayDelToStop = (params) => {
return postFetch('/api/bs/hrmsalary/archives/stayDelToStop', params);
return postFetch("/api/bs/hrmsalary/archives/stayDelToStop", params);
};
//删除社保档案
export const deleteArchive = (params) => {
return postFetch("/api/bs/hrmsalary/archives/deleteArchive", params);
};
//取消停缴
export const cancelStopPayment = (params) => {
return postFetch('/api/bs/hrmsalary/archives/cancelStopPayment', params);
return postFetch("/api/bs/hrmsalary/archives/cancelStopPayment", params);
};
export const getTable = params => {
return fetch('/api/bs/hrmsalary/archives/getTable', {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
}).then(res => res.json())
return fetch("/api/bs/hrmsalary/archives/getTable", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
export const getBaseForm = params => {
return WeaTools.callApi('/api/bs/hrmsalary/archives/getBaseForm', 'get', params);
return WeaTools.callApi("/api/bs/hrmsalary/archives/getBaseForm", "get", params);
};
export const getPaymentForm = params => {
return WeaTools.callApi('/api/bs/hrmsalary/archives/getPaymentForm', 'get', params);
return WeaTools.callApi("/api/bs/hrmsalary/archives/getPaymentForm", "get", params);
};
// 保存
export const save = params => {
return fetch('/api/bs/hrmsalary/archives/save', {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
}).then(res => res.json())
return fetch("/api/bs/hrmsalary/archives/save", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
// 导出档案
export const exportDocument = params => {
return WeaTools.callApi('/api/bs/hrmsalary/archives/export', 'get', params);
return WeaTools.callApi("/api/bs/hrmsalary/archives/export", "get", params);
};
// 导入档案 - 获取组件的一些前置参数
export const getImportDocumentParams = params => {
return WeaTools.callApi('/api/bs/hrmsalary/archives/getImportParams', 'get', params);
return WeaTools.callApi("/api/bs/hrmsalary/archives/getImportParams", "get", params);
};
// 导入档案- 导出现有数据
export const exportCurData = params => {
fetch('/api/bs/hrmsalary/scheme/template/export',{
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
}).then(res => res.blob().then(blob => {
var filename=`社保福利档案模板.xlsx`
var a = document.createElement('a');
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
}))
fetch("/api/bs/hrmsalary/scheme/template/export", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.blob().then(blob => {
var filename = `社保福利档案模板.xlsx`;
var a = document.createElement("a");
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
}));
};
// 导入档案-预览
export const previewCurData = (params) => {
return fetch('/api/bs/hrmsalary/scheme/preview', {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
}).then(res => res.json())
}
return fetch("/api/bs/hrmsalary/scheme/preview", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
// 档案导入
export const importBatch = (params) => {
return fetch('/api/bs/hrmsalary/scheme/importBatch', {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
}).then(res => res.json())
}
return fetch("/api/bs/hrmsalary/scheme/importBatch", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
}).then(res => res.json());
};
// 导出档案
export const exportArchives = (ids) => {
fetch('/api/bs/hrmsalary/scheme/export?ids=' + ids).then(res => res.blob().then(blob => {
var filename=`社保福利档案.xlsx`
var a = document.createElement('a');
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
}))
}
fetch("/api/bs/hrmsalary/scheme/export?ids=" + ids).then(res => res.blob().then(blob => {
var filename = `社保福利档案.xlsx`;
var a = document.createElement("a");
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
}));
};

View File

@ -62,7 +62,15 @@ export const getCustomCategoryForm = params => {
return WeaTools.callApi('/api/bs/hrmsalary/sicategory/customCategoryForm', 'get', params);
};
export const getCustomCategoryList = params => {
return WeaTools.callApi('/api/bs/hrmsalary/sicategory/customCategoryList', 'get', params);
// return WeaTools.callApi('/api/bs/hrmsalary/sicategory/customCategoryList', 'get', params);
return fetch('/api/bs/hrmsalary/sicategory/customCategoryList', {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
}).then(res => res.json())
};
export const createSICategory = params => {
return fetch('/api/bs/hrmsalary/sicategory/createSICategory', {

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="151px" height="150px" viewBox="0 0 151 150" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon-empty-file</title>
<defs>
<polygon id="path-1" points="0 -0.0002 149.9997 -0.0002 149.9997 31.9998 0 31.9998"></polygon>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="知识文档" transform="translate(-112.000000, -299.000000)">
<g id="Group-40" transform="translate(113.000000, 321.000000)">
<g id="Group-3" transform="translate(0.000000, 89.259000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-2"></g>
<path d="M149.9997,15.9998 C149.9997,24.8368 116.4217,31.9998 74.9997,31.9998 C33.5787,31.9998 -0.0003,24.8368 -0.0003,15.9998 C-0.0003,7.1638 33.5787,-0.0002 74.9997,-0.0002 C116.4217,-0.0002 149.9997,7.1638 149.9997,15.9998" id="Fill-1" fill="#E6EFF0" mask="url(#mask-2)"></path>
</g>
<line x1="116.8337" y1="5.1465" x2="127.1277" y2="5.1465" id="Stroke-4" stroke="#D3D7DC"></line>
<line x1="121.9801" y1="0" x2="121.9801" y2="10.294" id="Stroke-6" stroke="#D3D7DC"></line>
<line x1="127.1276" y1="39.0801" x2="133.1026" y2="39.0801" id="Stroke-8" stroke="#D3D7DC"></line>
<line x1="130.1149" y1="36.0928" x2="130.1149" y2="42.0678" id="Stroke-10" stroke="#D3D7DC"></line>
<line x1="17.9655" y1="38.4541" x2="25.1085" y2="38.4541" id="Stroke-12" stroke="#D3D7DC"></line>
<line x1="21.5368" y1="34.8828" x2="21.5368" y2="42.0248" id="Stroke-14" stroke="#D3D7DC"></line>
<polygon id="Fill-16" fill="#FFFFFF" points="113.029 23.0694 99.885 10.2944 99.091 11.2664 98.32 17.1834 97.716 21.4544 100.529 24.2664 106.842 25.3914 110.675 25.0164 112.842 24.2874"></polygon>
<polygon id="Stroke-18" stroke="#CFD0D6" stroke-linecap="round" stroke-linejoin="round" points="113.029 23.0694 99.885 10.2944 99.091 11.2664 98.32 17.1834 97.716 21.4544 100.529 24.2664 106.842 25.3914 110.675 25.0164 112.842 24.2874"></polygon>
<path d="M96.6842,106.4366 L42.9702,106.4366 C39.6702,106.4366 36.9702,103.7376 36.9702,100.4366 L36.9702,26.3016 C36.9702,23.0006 39.6702,20.3016 42.9702,20.3016 L96.6842,20.3016 C99.9842,20.3016 102.6842,23.0006 102.6842,26.3016 L102.6842,100.4366 C102.6842,103.7376 99.9842,106.4366 96.6842,106.4366" id="Fill-20" fill="#FFFFFF"></path>
<path d="M96.6842,106.4366 L42.9702,106.4366 C39.6702,106.4366 36.9702,103.7376 36.9702,100.4366 L36.9702,26.3016 C36.9702,23.0006 39.6702,20.3016 42.9702,20.3016 L96.6842,20.3016 C99.9842,20.3016 102.6842,23.0006 102.6842,26.3016 L102.6842,100.4366 C102.6842,103.7376 99.9842,106.4366 96.6842,106.4366 Z" id="Stroke-22" stroke="#CFD0D6"></path>
<path d="M105.3727,23.5244 C102.1367,23.5244 99.4877,20.8764 99.4877,17.6394 L99.4877,10.2944 L53.2007,10.2944 C49.9637,10.2944 47.3157,12.9424 47.3157,16.1784 L47.3157,90.5454 C47.3157,93.7814 49.9637,96.4294 53.2007,96.4294 L107.1437,96.4294 C110.3817,96.4294 113.0287,93.7814 113.0287,90.5454 L113.0287,23.5244 L105.3727,23.5244 Z" id="Fill-24" fill="#FFFFFF"></path>
<path d="M105.3727,23.5244 C102.1367,23.5244 99.4877,20.8764 99.4877,17.6394 L99.4877,10.2944 L53.2007,10.2944 C49.9637,10.2944 47.3157,12.9424 47.3157,16.1784 L47.3157,90.5454 C47.3157,93.7814 49.9637,96.4294 53.2007,96.4294 L107.1437,96.4294 C110.3817,96.4294 113.0287,93.7814 113.0287,90.5454 L113.0287,23.5244 L105.3727,23.5244 Z" id="Stroke-26" stroke="#CFD0D6"></path>
<path d="M99.987,36.3116 L60.319,36.3116 C58.944,36.3116 57.819,35.1866 57.819,33.8116 C57.819,32.4366 58.944,31.3116 60.319,31.3116 L99.987,31.3116 C101.362,31.3116 102.487,32.4366 102.487,33.8116 C102.487,35.1866 101.362,36.3116 99.987,36.3116" id="Fill-28" fill="#E9E9E9"></path>
<path d="M99.987,48.2158 L60.319,48.2158 C58.944,48.2158 57.819,47.0908 57.819,45.7158 C57.819,44.3408 58.944,43.2158 60.319,43.2158 L99.987,43.2158 C101.362,43.2158 102.487,44.3408 102.487,45.7158 C102.487,47.0908 101.362,48.2158 99.987,48.2158" id="Fill-30" fill="#E9E9E9"></path>
<path d="M99.987,60.1192 L60.319,60.1192 C58.944,60.1192 57.819,58.9942 57.819,57.6192 C57.819,56.2442 58.944,55.1192 60.319,55.1192 L99.987,55.1192 C101.362,55.1192 102.487,56.2442 102.487,57.6192 C102.487,58.9942 101.362,60.1192 99.987,60.1192" id="Fill-32" fill="#E9E9E9"></path>
<path d="M84.529,72.0235 L60.319,72.0235 C58.944,72.0235 57.819,70.8985 57.819,69.5235 C57.819,68.1485 58.944,67.0235 60.319,67.0235 L84.529,67.0235 C85.904,67.0235 87.029,68.1485 87.029,69.5235 C87.029,70.8985 85.904,72.0235 84.529,72.0235" id="Fill-34" fill="#E9E9E9"></path>
<path d="M49.4841,92.169 L49.4651,12.311 C48.4411,13.349 47.8191,14.441 47.8191,16.439 L47.8191,90.587 C47.8191,92.703 49.0641,94.436 50.7221,95.325 C50.0211,94.344 49.4841,93.459 49.4841,92.169" id="Fill-36" fill="#EBF6FF"></path>
<path d="M39.1335,102.1446 L39.1965,22.3046 C38.1725,23.3426 37.4685,24.4166 37.4685,26.4146 L37.4685,100.5626 C37.4685,102.6786 38.7435,104.4116 40.4025,105.3006 C39.7005,104.3196 39.1335,103.4346 39.1335,102.1446" id="Fill-38" fill="#EBF6FF"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,227 @@
/*
* Author: 黎永顺
* name: 新增人员范围弹框
* Description:
* Date: 2022/11/30
*/
import React, { Component } from "react";
import { WeaBrowser, WeaDialog, WeaFormItem, WeaSearchGroup, WeaSelect } from "ecCom";
import { Button, message, Modal } from "antd";
import { getTaxAgentRangeForm } from "../../apis/taxAgent";
import { SelectWithAll } from "../../pages/socialSecurityBenefits/standingBookDetail/components/regAddEmployee";
import "./index.less";
class PersonalScopeModal extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
employeeStatus: [],
targetTypeList: [],
targetType: "EMPLOYEE",
targetTypeIds: "",
targetTypeIdsNames: "",
status: "",
statusAll: ""
};
}
componentDidMount() {
const { isTaxgent = true } = this.props;
if (isTaxgent) {
this.getTaxAgentRangeForm();
} else {
const employeeStatus = [
{ key: "TRIAL", showname: "试用" },
{ key: "FORMAL", showname: "正式" },
{ key: "TEMPORARY", showname: "临时" },
{ key: "DELAY", showname: "试用延期" },
{ key: "FIRE", showname: "解雇" },
{ key: "DEPARTURE", showname: "离职" },
{ key: "RETIRED", showname: "退休" }
];
const targetTypeList = [
{
key: "EMPLOYEE",
showname: "人员",
selected: false
},
{
key: "SUBCOMPANY",
showname: "分部",
selected: false
},
{
key: "DEPT",
showname: "部门",
selected: false
},
{
key: "POSITION",
showname: "岗位",
selected: false
}
];
this.setState({ targetTypeList, employeeStatus });
}
}
getTaxAgentRangeForm = () => {
getTaxAgentRangeForm().then(({ status, data }) => {
if (status) {
const { employeeStatus, targetTypeList } = data;
this.setState({
targetTypeList: _.map(targetTypeList, it => ({ key: it.id, showname: it.name })),
employeeStatus: _.map(employeeStatus, it => ({ key: it.id, showname: it.name }))
});
}
});
};
handleSubmit = () => {
const { status, targetTypeIds, targetType } = this.state;
const { includeType, saveKeyVal, onSuccess, onCancel, APISaveFox } = this.props;
if (_.isEmpty(status) || _.isEmpty(targetTypeIds)) {
Modal.warning({
title: "信息确认",
content: "必要信息不完整,红色*为必填项!"
});
return;
}
const payload = {
employeeStatus: status.split(","),
includeType,
targetParams: _.map(targetTypeIds.split(","), it => ({ targetType, targetId: it })),
[saveKeyVal["key"]]: saveKeyVal["value"],
};
this.setState({ loading: true });
APISaveFox["save"](payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success("保存成功");
this.handleReset();
onSuccess();
onCancel();
} else {
message.error(errormsg || "保存失败");
}
}).catch(() => this.setState({ loading: true }));
};
renderBrowser = () => {
const { targetType, targetTypeIds, targetTypeIdsNames } = this.state;
let browserType = {};
switch (targetType) {
case "EMPLOYEE":
browserType = { ...browserType, type: 17, title: "人员选择" };
break;
case "DEPT":
browserType = { ...browserType, type: 57, title: "部门选择" };
break;
case "SUBCOMPANY":
browserType = { ...browserType, type: 164, title: "分部选择" };
break;
case "POSITION":
browserType = { ...browserType, type: 278, title: "岗位选择" };
break;
default:
break;
}
return <WeaBrowser
{...browserType}
viewAttr={3}
isSingle={false}
value={targetTypeIds}
valueSpan={targetTypeIdsNames}
inputStyle={{ width: 200 }}
onChange={(targetTypeIds, targetTypeIdsNames) => {
this.setState({ targetTypeIds, targetTypeIdsNames });
}}
/>;
};
handleReset = () => {
this.setState({
targetType: "EMPLOYEE",
targetTypeIds: "",
status: "",
statusAll: ""
});
};
render() {
const { onCancel, title, visible } = this.props;
const { employeeStatus, targetTypeList, targetType, status, statusAll, loading } = this.state;
const buttons = [
<Button type="primary" onClick={this.handleSubmit} loading={loading}>确定</Button>,
<Button type="ghost" onClick={this.handleReset}>重置</Button>
];
return (
<WeaDialog
initLoadCss
className="personalScopeModalWrapper"
title={title}
visible={visible}
style={{ width: 600 }}
buttons={buttons}
onCancel={() => {
this.handleReset();
onCancel();
}}
>
<WeaSearchGroup col={1} needTigger title="" showGroup center>
<WeaFormItem
label="对象类型"
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
>
<div style={{ display: "flex", alignItems: "center" }}>
<WeaSelect
style={{ width: 60, marginRight: 12 }}
value={targetType}
options={targetTypeList}
onChange={(targetType) => this.setState({ targetType })}
/>
{this.renderBrowser()}
</div>
</WeaFormItem>
{
SelectWithAll({
label: "选择员工状态",
options: employeeStatus,
detailtype: 2,
valueAll: statusAll,
value: status,
onChangeAll: ({ selected }) => {
if (selected) {
this.setState({
status: _.map(employeeStatus, it => it.key).join(","),
statusAll: selected
});
} else {
this.setState({
status: "",
statusAll: selected
});
}
},
onChange: ({ selected }) => {
const bool = _.every(_.map(employeeStatus, it => it.key), item => selected.split(",").includes(item));
if (bool) {
this.setState({
status: selected,
statusAll: "0"
});
} else {
this.setState({
status: selected,
statusAll: ""
});
}
}
})
}
</WeaSearchGroup>
</WeaDialog>
);
}
}
export default PersonalScopeModal;

View File

@ -0,0 +1,14 @@
//添加关联人员弹框中的下拉框样式
.personalScopeModalWrapper{
.wea-select,.ant-select-selection,.ant-select{
width: 100%;
}
.wea-select{
display: inline-block;
position: relative;
}
.ant-select-selection{
height: 30px;
border-radius: 0;
}
}

View File

@ -0,0 +1,138 @@
/*
* Author: 黎永顺
* name: 人员范围列表数据
* Description:
* Date: 2022/11/30
*/
import React, { Component } from "react";
import { WeaTable } from "ecCom";
import { calcPageNo } from "../../util";
import "./index.less";
class PersonalScopeTable extends Component {
constructor(props) {
super(props);
this.state = {
loading: {
query: false
},
dataSource: [],
columns: [],
selectedRowKeys: [],
pageInfo: {
current: 1,
pageSize: 10,
total: 0
}
};
}
componentDidMount() {
this.getPersonalScopeList();
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.tabActive !== this.props.tabActive) {
this.setState({ selectedRowKeys: [] }, () => {
this.getPersonalScopeList(nextProps.tabActive);
nextProps.onChangeSelectKey([]);
});
}
}
getPersonalScopeList = (tabActive = this.props.tabActive) => {
const { searchValue, searchKeyVal, APIFox } = this.props;
const { pageInfo, loading } = this.state;
const payload = {
[searchKeyVal["key"]]: searchKeyVal["value"],
targetName: searchValue,
...pageInfo
};
this.setState({ loading: { ...loading, query: true } });
APIFox[tabActive](payload).then(({ status, data }) => {
this.setState({ loading: { ...loading, query: false } });
if (status) {
const { pageNum: current, pageSize, total, columns, list: dataSource } = data;
this.setState({
pageInfo: { ...pageInfo, current, pageSize, total },
dataSource,
columns: _.map(columns, item => {
return {
...item,
render: (text) => {
return <span className="tdEllipsis" title={text}>{text}</span>;
}
};
})
});
}
}).catch(() => {
this.setState({ loading: { ...loading, query: false } });
});
};
/*
* Author: 黎永顺
* Description: 清空选中项
* Params:
* Date: 2022/11/30
*/
clearRowkeys = () => {
const { pageInfo, selectedRowKeys } = this.state;
this.setState({
selectedRowKeys: [],
pageInfo: {
...pageInfo,
current: calcPageNo(pageInfo.total, pageInfo.current, 10, selectedRowKeys.length)
}
}, () => {
this.getPersonalScopeList();
});
};
render() {
const { dataSource, columns, pageInfo, loading, selectedRowKeys } = this.state;
const { onChangeSelectKey } = this.props;
const pagination = {
...pageInfo,
showTotal: total => `${total}`,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
onShowSizeChange: (current, pageSize) => {
this.setState({
pageInfo: { ...pageInfo, current, pageSize }
}, () => {
this.getPersonalScopeList();
});
},
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => {
this.getPersonalScopeList();
});
}
};
const rowSelection = {
selectedRowKeys,
onChange: (selectedRowKeys) => {
this.setState({ selectedRowKeys }, () => {
onChangeSelectKey(this.state.selectedRowKeys);
});
}
};
return (
<WeaTable
rowKey="id"
rowSelection={rowSelection}
dataSource={dataSource}
pagination={pagination}
loading={loading.query}
columns={columns}
/>
);
}
}
export default PersonalScopeTable;

View File

@ -0,0 +1,11 @@
.ledgerWrapper {
height: 100%;
.tdEllipsis {
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}

View File

@ -0,0 +1,26 @@
import React, { Component } from "react";
import { WeaTable } from "ecCom";
import "./index.less";
class Index extends Component {
render() {
const { columns, xWidth = 1440 } = this.props;
const unifiedColumns = _.map(columns, (item, index) => {
if (index === 0 || index === 2) {
return { ...item, fixed: "left", width: 150 };
} else if (index === 1) {
return { ...item, fixed: "left", width: 176 };
}
if (item.dataIndex === "operate") {
return { ...item, fixed: "right", width: item.width || "120px" };
}
return { ...item, width: "33%" };
});
return (
<WeaTable className="unifiedTable" {...this.props} columns={unifiedColumns} scroll={{ x: xWidth }}/>
);
}
}
export default Index;

View File

@ -0,0 +1,24 @@
.unifiedTable {
.ellipsis {
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.linkWapper {
//a {
// color: #4d7ad8;
// margin-right: 8px;
//}
i {
cursor: pointer;
}
//a:hover {
// text-decoration: none;
//}
}
}

View File

@ -0,0 +1,94 @@
/*
* Author: 黎永顺
* name: 验证码弹框
* Description:
* Date: 2023/6/16
*/
import React, { Component } from "react";
import { WeaDialog, WeaError, WeaFormItem, WeaInput, WeaLocaleProvider, WeaSearchGroup } from "ecCom";
import { sendMobileCode } from "../../apis/payroll";
import { Button } from "antd";
import "./index.less";
const { getLabel } = WeaLocaleProvider;
class Index extends Component {
constructor(props) {
super(props);
this.state = {
captcha: "",
time: 60
};
this.timeRef = null;
}
componentWillUnmount() {
clearInterval(this.timeRef);
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && !nextProps.visible) {
clearInterval(this.timeRef);
this.setState({ captcha: "", time: 60 });
}
}
handleSendCaptcha = () => {
sendMobileCode({ id: this.props.id }).then(({ status, data }) => {
if (status) {
console.log(data);
this.timeRef = setInterval(() => {
const { time } = this.state;
this.setState({ time: time - 1 }, () => {
if (this.state.time === -1) {
clearInterval(this.timeRef);
this.setState({ time: 60 });
}
});
}, 1000);
}
});
};
handleConfirm = () => {
if (!this.state.captcha) {
this.refs.weaError.showError();
// return
}
this.props.onCancel();
this.props.onConfirm();
};
render() {
const { captcha, time } = this.state;
return (
<WeaDialog
initLoadCss {...this.props} style={{ width: 550 }}
className="captchaWrapper" title={getLabel(111, "验证码验证")}
buttons={[
<Button type="primary" onClick={this.handleConfirm}>{getLabel(826, "确定")}</Button>
]}
>
<WeaSearchGroup needTigger={false} title="" showGroup>
<WeaFormItem
label={getLabel(111, "验证码")}
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
>
<WeaError tipPosition="bottom" ref="weaError" error={getLabel(826, "验证码未填写")}>
<div className="captchaInputBox">
<WeaInput value={captcha} onChange={captcha => this.setState({ captcha })}/>
<Button type="primary" onClick={this.handleSendCaptcha} disabled={time !== 60}>
{
time === 60 ? getLabel(111, "发送验证码") : `${time}S`
}
</Button>
</div>
</WeaError>
</WeaFormItem>
</WeaSearchGroup>
</WeaDialog>
);
}
}
export default Index;

View File

@ -0,0 +1,29 @@
.captchaWrapper {
.wea-dialog-body {
padding: 30px 20px;
.wea-form-item-wrapper {
.wea-error {
width: 100%;
.captchaInputBox {
display: flex;
align-items: center;
.wea-input-normal {
flex: 1;
}
button {
padding: 8px 10px;
border-radius: 0;
min-width: 80px;
text-align: center;
height: 30px;
line-height: 15px;
}
}
}
}
}
}

View File

@ -3,8 +3,7 @@ import CustomTable from "../../components/customTable";
class CustomPaginationTable extends PureComponent {
shouldComponentUpdate(nextProps, nextState, nextContext) {
if (nextProps.columnIndex && this.props.columnIndex !== nextProps.columnIndex) return false;
return true;
return !(nextProps.columnIndex && this.props.columnIndex !== nextProps.columnIndex);
}
render() {

View File

@ -0,0 +1,255 @@
/*
* Author: 黎永顺
* name: 公式列表
* Description:
* Date: 2023/4/25
*/
import React, { Component } from "react";
import { WeaInputSearch, WeaLocaleProvider } from "ecCom";
import { Tree } from "antd";
import { formualSearchField, formualSearchGroup, getFormulaDes } from "../../../apis/item";
import "../index.less";
const TreeNode = Tree.TreeNode;
const getLabel = WeaLocaleProvider.getLabel;
class CodeAction extends Component {
constructor(props) {
super(props);
this.state = {
disabled: false,
variableText: "",
funcText: "",
variItemText: "",
variableList: [], //变量列表
variableExpandedKeys: [], //变量展开的节点
funcList: [], //函数列表
funcExpandedKeys: [], //函数展开的节点
funcHoverItem: {} //选中的函数节点
};
}
componentDidMount() {
const { groupParams = {} } = this.props;
this.getFormulaDes();
this.formualSearchGroup(groupParams);
}
componentWillReceiveProps(nextProps, nextContext) {
const { isCustomFunction, isCustomFunctionClick, onChangeCustomFunction } = nextProps;
if (isCustomFunction === "1" && !isCustomFunctionClick) {
this.setState({ disabled: true });
} else {
this.setState({ disabled: false }, () => {
isCustomFunction === "1" && onChangeCustomFunction("0");
});
}
}
getFormulaDes = () => {
getFormulaDes().then(({ data }) => {
if (!_.isEmpty(data)) this.setState({ funcList: data });
});
};
formualSearchGroup = (payload) => {
formualSearchGroup(payload).then(({ status, data }) => {
if (status) this.setState({
variableList: _.map(data, item => ({
...item,
children: [{ name: "", fieldId: "searchInput" }]
}))
});
});
};
formualSearchField = (sourceId) => {
const { groupParams } = this.props;
const { variableList } = this.state;
formualSearchField({ sourceId, extendParam: { ...groupParams } }).then(({ status, data }) => {
if (status) {
this.setState({
variableList: _.map(variableList, it => ({
...it,
children: sourceId === it.key ? [...it.children, ...data] : [...it.children]
}))
});
}
});
};
handleExpandVari = (variableExpandedKeys, { expanded, node }) => {
const { props: { eventKey } } = node;
const { variableList } = this.state;
this.setState({ variableExpandedKeys });
if (expanded) {
this.formualSearchField(eventKey);
} else {
this.setState({
variableList: _.map(variableList, it => ({
...it,
children: eventKey === it.key ? [{ name: "", fieldId: "searchInput" }] : [...it.children]
}))
});
}
};
handleVariNode = (selectedKeys) => {
const { onVariSelect } = this.props;
const { variableList } = this.state;
const parentNode = _.map(variableList, it => it.key);
if (selectedKeys.join() && selectedKeys.join().indexOf("searchInput") === -1 &&
!parentNode.includes(selectedKeys.join())) {
const selectParentNodeKey = selectedKeys.join().split("_")[0];
const convertStr = _.reduce(variableList, (pre, cur) => {
if (cur.key === selectParentNodeKey) {
return pre + cur.value + "." + _.find(cur.children, child => child.fieldId === selectedKeys.join()).name;
}
return pre;
}, "");
onVariSelect(convertStr);
}
};
render() {
const {
variableList, variableExpandedKeys, variableText, variItemText,
funcList, funcText, funcExpandedKeys, funcHoverItem, disabled
} = this.state;
const { groupParams = {} } = this.props;
const { referenceType } = groupParams;
const variableDatalist = _.filter(variableList, it => it.value.indexOf(variableText) !== -1);
const funcDatalist = _.map(funcList, it => ({
...it,
children: _.filter(it.children, child => _.lowerCase(child.name).indexOf(_.lowerCase(funcText)) !== -1)
}));
return (
<div className="excel-codeAction">
<div className="excel-codeAction-item">
<div className="excel-codeAction-header">
<div className="excel-codeAction-header-title">{getLabel(111, "变量")}</div>
</div>
<div className="excel-codeAction-content">
<WeaInputSearch value={variableText} placeholder={getLabel(111, "请输入变量名称")}
className="variableOuterInput"
onChange={variableText => this.setState({ variableText })}/>
<Tree className="variableTree" showLine expandedKeys={variableExpandedKeys}
onExpand={this.handleExpandVari} onSelect={this.handleVariNode}
>
{
_.map(variableDatalist, item => {
const { key, value, children = [] } = item;
const itemChildren = _.filter(children.slice(1), it => it.name.indexOf(variItemText) !== -1);
return <TreeNode title={value} key={key}>
{
_.map([...children.slice(0, 1), ...itemChildren], (child, childIndex) => {
const { name, fieldId } = child;
return (
fieldId === "searchInput" ?
<TreeNode
title={
<WeaInputSearch
value={variItemText}
placeholder={getLabel(111, "请输入变量名称")}
onChange={variItemText => this.setState({ variItemText })}
/>
}
key={fieldId + "_" + childIndex}/> :
<TreeNode title={name} key={fieldId}/>
);
})
}
</TreeNode>;
})
}
</Tree>
</div>
</div>
{
referenceType !== "sql" &&
<React.Fragment>
<div className="excel-codeAction-item">
<div className="excel-codeAction-header">
<div className="excel-codeAction-header-title">{getLabel(111, "函数")}</div>
</div>
<div className="excel-codeAction-content">
<WeaInputSearch value={funcText} placeholder={getLabel(111, "请输入函数名称")}
className="variableOuterInput"
onChange={funcText => this.setState({ funcText })}/>
<Tree className="variableTree" showLine expandedKeys={funcExpandedKeys}
onExpand={funcExpandedKeys => this.setState({ funcExpandedKeys })}
>
{
_.map(funcDatalist, item => {
const { name, dataType, children = [] } = item;
return <TreeNode title={name} disabled={disabled} key={dataType}>
{
_.map(children, (child, childIndex) => {
const { name: childName, chineseName } = child;
return (
<TreeNode
disabled={disabled}
title={
<div className="funcListTitle"
onClick={() => this.props.onFuncSelect(childName)}
onMouseEnter={() => this.setState({ funcHoverItem: child })}>
<span className="functionName" title={childName}>{childName}</span>
<span className="functionDesc" title={chineseName}>{chineseName}</span>
</div>
}
key={childIndex}
/>
);
})
}
</TreeNode>;
})
}
</Tree>
</div>
</div>
<div className="excel-codeAction-item">
<div className="excel-codeAction-header">
<div className="excel-codeAction-header-title">
{!_.isEmpty(funcHoverItem) ? funcHoverItem.name : getLabel(111, "提示")}
</div>
</div>
<div className="excel-codeAction-content"><TipList tips={funcHoverItem}/></div>
</div>
</React.Fragment>
}
</div>
);
}
}
export default CodeAction;
const TipList = (props) => {
const { tips } = props;
const { paramDescs = [], formatString, description, example, result } = tips;
return _.isEmpty(tips) ? <div className="code-action-list">
<div className="code-action-tips">
{/*<div>{getLabel(111, "{C:选项} 用来选择特定选项字段下的备选项")}</div>*/}
{/*<div>{getLabel(111, "{U:姓名} 用来选择工作区成员")}</div>*/}
{/*<div>{getLabel(111, "{D:数据} 用来选择一个部门")}</div>*/}
</div>
</div> : <div className="code-action-list">
<div className="code-action-tips">
<div className="code-action-tips-title">{getLabel(111, "语法")}</div>
<div className="code-action-tips-info">
<div>{formatString}</div>
<div>{description}</div>
</div>
<div className="code-action-tips-title">{getLabel(111, "参数")}</div>
{
_.map(paramDescs, it => {
return <div className="code-action-tips-info">
<span>.</span>
<span>{it}</span>
</div>;
})
}
<div className="code-action-tips-title">{getLabel(111, "示例")}</div>
<span className="code-action-tips-info">{example}</span>
<div className="code-action-tips-title">{getLabel(111, "结果")}</div>
<span className="code-action-tips-info">{result}</span>
</div>
</div>;
};

View File

@ -0,0 +1,16 @@
export const keyboardBaseBtns=[
{ key:"+", label: "+" },
{ key:"-", label: "-" },
{ key:">", label: ">" },
{ key:">=", label: ">=" },
{ key:"=", label: "=" },
{ key:"*", label: "*" },
{ key:"/", label: "/" },
{ key:"<", label: "<" },
{ key:"<=", label: "<=" },
{ key:"!=", label: "!=" },
{ key:"()", label: "(" },
{ key:")", label: ")" },
{ key:"%", label: "%" },
{ key:" ", label: "space" },
]

View File

@ -0,0 +1,112 @@
// extendCodeMirror.js
/* eslint-disable */
import * as CodeMirror from "codemirror";
CodeMirror.extendMode("css", {
commentStart: "/*",
commentEnd: "*/",
newlineAfterToken: function (type, content) {
return /^[;{}]$/.test(content);
}
});
CodeMirror.extendMode("javascript", {
commentStart: "",
commentEnd: "",
// FIXME semicolons inside of for
newlineAfterToken: function (type, content, textAfter, state) {
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);
}
}
});
CodeMirror.extendMode("xml", {
commentStart: "<!--",
commentEnd: "-->",
newlineAfterToken: function (type, content, textAfter) {
return type == "tag" && />$/.test(content) || /^</.test(textAfter);
}
});
// Comment/uncomment the specified range
CodeMirror.defineExtension("commentRange", function (isComment, from, to) {
var cm = this, curMode = CodeMirror.innerMode(cm.getMode(), cm.getTokenAt(from).state).mode;
cm.operation(function () {
if (isComment) { // Comment range
cm.replaceRange(curMode.commentEnd, to);
cm.replaceRange(curMode.commentStart, from);
if (from.line == to.line && from.ch == to.ch) // An empty comment inserted - put cursor inside
cm.setCursor(from.line, from.ch + curMode.commentStart.length);
} else { // Uncomment range
var selText = cm.getRange(from, to);
var startIndex = selText.indexOf(curMode.commentStart);
var endIndex = selText.lastIndexOf(curMode.commentEnd);
if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
// Take string till comment start
selText = selText.substr(0, startIndex)
// From comment start till comment end
+ selText.substring(startIndex + curMode.commentStart.length, endIndex)
// From comment end till string end
+ selText.substr(endIndex + curMode.commentEnd.length);
}
cm.replaceRange(selText, from, to);
}
});
});
// Applies automatic mode-aware indentation to the specified range
CodeMirror.defineExtension("autoIndentRange", function (from, to) {
var cmInstance = this;
this.operation(function () {
for (var i = from.line; i <= to.line; i++) {
cmInstance.indentLine(i, "smart");
}
});
});
// Applies automatic formatting to the specified range
CodeMirror.defineExtension("autoFormatRange", function (from, to) {
var cm = this;
var outer = cm.getMode(), text = cm.getRange(from, to).split("\n");
var state = CodeMirror.copyState(outer, cm.getTokenAt(from).state);
var tabSize = cm.getOption("tabSize");
var out = "", lines = 0, atSol = from.ch == 0;
function newline() {
out += "\n";
atSol = true;
++lines;
}
for (var i = 0; i < text.length; ++i) {
var stream = new CodeMirror.StringStream(text[i], tabSize);
while (!stream.eol()) {
var inner = CodeMirror.innerMode(outer, state);
var style = outer.token(stream, state), cur = stream.current();
stream.start = stream.pos;
if (!atSol || /\S/.test(cur)) {
out += cur;
atSol = false;
}
if (!atSol && inner.mode.newlineAfterToken &&
inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos) || text[i + 1] || "", inner.state))
newline();
}
if (!stream.pos && outer.blankLine) outer.blankLine(state);
if (!atSol) newline();
}
cm.operation(function () {
cm.replaceRange(out, from, to);
for (var cur = from.line + 1, end = from.line + lines; cur <= end; ++cur)
cm.indentLine(cur, "smart");
cm.setSelection(from, cm.getCursor(false));
});
});
// export default CodeMirror;
module.exports = { CodeMirror };

View File

@ -0,0 +1,175 @@
import React, { Component } from "react";
import { Button } from "antd";
import { WeaLocaleProvider } from "ecCom";
import { Controlled as CodeMirror } from "react-codemirror2";
import { keyboardBaseBtns } from "./constants";
import CodeAction from "./components/codeAction";
import cs from "classnames";
import "./index.less";
import "codemirror/lib/codemirror.css";
import "codemirror/lib/codemirror.js";
import "codemirror/mode/javascript/javascript.js";
require("./extendCodeMirror");
const getLabel = WeaLocaleProvider.getLabel;
class ExcelEditor extends Component {
constructor(props) {
super(props);
this.state = {
value: "",
isFormter: false,
isCustomFunctionClick: false
};
this.editorRef = null;
this.timer = null;
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.value !== this.props.value && nextProps.value) this.setState({ value: nextProps.value });
}
componentWillUnmount() {
if (this.timer) clearInterval(this.timer);
this.setState({ isCustomFunctionClick: false });
}
autoFormatSelection = () => {
const { isFormter } = this.state;
if (isFormter) {
const script_length = this.editorRef.getValue().length;
const startPos = { line: 0, ch: 0, sticky: null };
const endPos = this.editorRef.doc.posFromIndex(script_length);
this.editorRef.setSelection(startPos, endPos);
this.editorRef.autoFormatRange(startPos, endPos);
this.editorRef.commentRange(true, startPos, endPos);
} else {
this.editorRef.undo();
// this.editorRef.undo();
}
};
insertText = text => {
const cursor = this.editorRef.getCursor();
this.editorRef.replaceRange(text, cursor);
this.editorRef.refresh();
this.editorRef.focus();
};
replaceToWidget = (editor) => {
editor.getAllMarks().forEach(m => m.clear());
};
handleVariSelect = str => this.insertText(`{${str}}`);
handleFuncSelect = str => {
const cursor = this.editorRef.getCursor();
this.editorRef.replaceRange(`${str}()`, cursor);
this.timer = setTimeout(() => {
const { line, ch } = this.editorRef.getCursor();
this.editorRef.setCursor({ line, ch: ch - 1 });
this.editorRef.refresh();
this.editorRef.focus();
}, 100);
};
handleEditorRedo = () => {
const { ch, line } = this.editorRef.getCursor();
const delStr = this.editorRef.getRange({ line, ch: ch - 1 }, { line, ch });
const codeValue = this.editorRef.getValue();
if (delStr === "}") {
if (codeValue.slice(0, ch).lastIndexOf("{") === -1) {
this.editorRef.replaceRange("", { line, ch: ch - 1 }, { line, ch });
} else {
this.editorRef.replaceRange("", { line, ch: codeValue.slice(0, ch).lastIndexOf("{") }, { line, ch });
}
} else {
this.editorRef.replaceRange("", { line, ch: ch - 1 }, { line, ch });
}
this.editorRef.refresh();
this.editorRef.focus();
};
handleBackSpaceRedo = () => {
const { ch, line } = this.editorRef.getCursor();
const delStr = this.editorRef.getRange({ line, ch: ch - 1 }, { line, ch });
const codeValue = this.editorRef.getValue();
if (delStr === "}") {
if (codeValue.slice(0, ch).lastIndexOf("{") === -1) {
this.editorRef.replaceRange("", { line, ch: ch - 1 }, { line, ch });
} else {
this.editorRef.replaceRange("", { line, ch: codeValue.slice(0, ch).lastIndexOf("{") + 1 }, { line, ch });
}
}
this.editorRef.refresh();
this.editorRef.focus();
};
render() {
const { isFormter, isCustomFunctionClick } = this.state;
const { groupParams = {}, isCustomFunction, value, onChangeCustomFunction } = this.props;
const { referenceType } = groupParams;
return (
<React.Fragment>
<div className="excel-codeWrap">
<div className="excel-codeBox">
<CodeMirror
editorDidMount={editor => this.editorRef = editor}
value={this.state.value}
onBeforeChange={(editor, data, value) => {
this.setState({ value }, () => this.props.onChange(this.state.value));
}}
onChange={(editor, data, value) => {
this.replaceToWidget(editor, data, value);
}}
options={{
lineNumbers: false,
mode: "javascript",
autofocus: false,
styleActiveLine: true,
lineWrapping: true,
matchBrackets: true,
lint: false,
indentUnit: 2,
cursorHeight: 0.85,
placeholder: "",
showCursorWhenSelecting: true
}}
onKeyDown={(_, { keyCode }) => keyCode === 8 && this.handleBackSpaceRedo()}
/>
</div>
{
referenceType !== "sql" &&
<div className="excel-codeBox-keyboard">
<div className="excel-codeBox-keyboard-operate">
<div className="excel-codeBox-keyboard-operate-content">
{
_.map(keyboardBaseBtns, item => {
const { key, label } = item;
return <Button
key={key} title={label} size="small"
className={cs(key === " " ? "excel-codeBox-keyboard-space" : "excel-codeBox-keyboard-base")}
onClick={() => this.insertText(key)}
>{label}</Button>;
})
}
</div>
<div className="excel-codeBox-keyboard-operate-clear">
<Button title="←" size="small" className="excel-codeBox-keyboard-del"
onClick={this.handleEditorRedo}></Button>
<Button title="C" size="small" className="excel-codeBox-keyboard-clear"
onClick={() => this.setState({ value: "", isCustomFunctionClick: true })}>C</Button>
</div>
</div>
<Button type="ghost"
onClick={() => this.setState({ isFormter: !isFormter }, () => this.autoFormatSelection())}>
{!isFormter ? getLabel(111, "格式美化") : getLabel(111, "格式还原")}
</Button>
</div>
}
</div>
{/*公式参数列表*/}
<CodeAction groupParams={groupParams} isCustomFunction={isCustomFunction} onVariSelect={this.handleVariSelect}
onFuncSelect={this.handleFuncSelect} codeVal={value} isCustomFunctionClick={isCustomFunctionClick}
onChangeCustomFunction={onChangeCustomFunction}
/>
</React.Fragment>
);
}
}
export default ExcelEditor;

View File

@ -0,0 +1,199 @@
.excel-codeWrap {
width: 100%;
display: flex;
justify-content: space-around;
padding: 0 0 8px;
.excel-codeBox {
flex: 1;
overflow: auto;
background: #fff;
box-sizing: content-box;
border: 1px solid #e5e5e5;
span {
font-family: Liberation Mono, LiberationMonoRegular, Courier New, monospace;
}
.CodeMirror-code {
font-size: 16px;
}
.CodeMirror-scroll {
overflow-x: visible !important;
padding: 4px;
}
.CodeMirror-sizer {
margin-left: 0 !important;
}
.CodeMirror-gutters {
border-right: none;
background-color: #f7f7f7;
opacity: 0;
display: none;
}
}
.excel-codeBox-keyboard {
width: 272px;
min-height: 232px;
padding: 20px;
background: #fff;
border: 1px solid #e5e5e5;
border-left: none;
.excel-codeBox-keyboard-operate {
display: flex;
.excel-codeBox-keyboard-operate-content {
display: flex;
flex-wrap: wrap;
flex: 1;
.excel-codeBox-keyboard-base {
width: 30px;
height: 30px;
text-align: center;
margin: 0 10px 10px 0;
}
.excel-codeBox-keyboard-space {
width: 70px;
height: 30px;
}
}
.excel-codeBox-keyboard-operate-clear {
width: 30px;
.excel-codeBox-keyboard-del {
width: 30px;
height: 70px;
}
.excel-codeBox-keyboard-clear {
width: 30px;
height: 30px;
margin-top: 10px;
}
}
}
}
}
.excel-codeAction {
width: 100%;
display: flex;
justify-content: space-between;
.excel-codeAction-item:last-child {
margin-right: 0;
.excel-codeAction-header-title {
color: rgb(217, 82, 189);
}
}
.excel-codeAction-item {
width: 33%;
min-height: 317px;
flex: 1;
background: #fff;
border: 1px solid #e5e5e5;
margin-right: 16px;
display: flex;
flex-direction: column;
.excel-codeAction-header {
display: flex;
padding: 10px 16px;
border-bottom: 1px solid #e5e5e5;
.excel-codeAction-header-title {
flex: 1;
font-weight: 600;
}
}
.excel-codeAction-content {
flex: 1;
overflow: hidden auto;
padding: 0 16px;
max-height: 280px;
position: relative;
.variableOuterInput {
width: 100%;
margin-top: 10px;
position: sticky;
top: 10px;
background-color: #fff;
z-index: 1;
}
.variableTree {
li a:hover, li a.ant-tree-node-selected {
background: transparent;
}
li:first-child {
a {
padding: 2px 5px;
}
}
li a {
width: calc(100% - 16px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.ant-tree-title {
display: inline-block;
width: 100%;
.funcListTitle {
width: 100%;
display: flex;
justify-content: space-between;
& > span {
display: inline-block;
flex: 1 1;
overflow: hidden;
text-overflow: ellipsis;
word-break: keep-all;
white-space: nowrap;
}
.functionName {
max-width: 100px;
}
.functionDesc {
max-width: 100px;
text-align: right;
color: #999;
}
}
}
}
}
.code-action-list {
padding: 10px 0;
.code-action-tips-title{
height: 22px;
line-height: 22px;
}
.code-action-tips-info{
color: #999
}
}
}
}
}

View File

@ -1,20 +1,20 @@
import React from "react"
import { Button } from "antd"
import { WeaCheckbox, WeaHelpfulTip } from "ecCom";
import React from "react";
import { Button } from "antd";
export default class HeaderSet extends React.Component {
render() {
return (
<div style={{display: "inline-block"}}>
<Button type="default" style={{marginLeft: "10px", marginRight: "10px"}} onClick={this.props.onSetClick}>表头设置</Button>
<WeaCheckbox style={{marginRight: "10px"}}/>
<WeaHelpfulTip
className="headSetTips"
width={200}
title="提示:勾选此项,则导出模板的考勤模块字段自动填充考勤模块的数据,导入时默认为覆盖导入"
placement="topLeft"
/>
</div>
)
}
}
render() {
return (
<div style={{ display: "inline-block" }}>
<Button type="default" style={{ marginLeft: "10px", marginRight: "10px" }} onClick={this.props.onSetClick}
loading={this.props.loading}>表头设置</Button>
{/*<WeaCheckbox style={{marginRight: "10px"}}/>*/}
{/*<WeaHelpfulTip*/}
{/* className="headSetTips"*/}
{/* width={200}*/}
{/* title="提示:勾选此项,则导出模板的考勤模块字段自动填充考勤模块的数据,导入时默认为覆盖导入"*/}
{/* placement="topLeft"*/}
{/*/>*/}
</div>
);
}
}

View File

@ -107,7 +107,8 @@ export default class ImportModal extends React.Component {
localStorage.removeItem("fileList");
this.props.onCancel();
}}
style={{ width: 850 }}
style={{ width: 850, height: 600 }}
hasScroll
className="importModalWrapper"
initLoadCss
buttons={

View File

@ -1,7 +1,5 @@
.importModalWrapper {
.wea-dialog-body {
height: 80vh;
overflow: hidden auto;
.ant-modal-body {
padding: 16px;
}

View File

@ -1,17 +1,17 @@
import React from 'react';
import { inject, observer } from 'mobx-react';
import { toJS } from 'mobx';
import React from "react";
import { inject, observer } from "mobx-react";
import { toJS } from "mobx";
import { Button } from 'antd';
import { WeaLogView } from 'comsMobx';
import { WeaTop, WeaRightMenu, WeaLocaleProvider, WeaNewScroll } from 'ecCom';
import { Button } from "antd";
import { WeaLogView } from "comsMobx";
import { WeaLocaleProvider, WeaNewScroll, WeaTop } from "ecCom";
import { renderNoright, renderLoading, getSearchs } from '../util'; // 从util文件引入公共的方法
import { getSearchs, renderLoading, renderNoright } from "../util"; // 从util文件引入公共的方法
const getLabel = WeaLocaleProvider.getLabel;
const WeaLogViewComp = WeaLogView.Component;
@inject('baseFormStore')
@inject("baseFormStore")
@observer
export default class BaseForm extends React.Component {
componentWillMount() { // 初始化渲染页面
@ -31,24 +31,24 @@ export default class BaseForm extends React.Component {
const { baseFormStore: { setLogVisible, saveForm } } = this.props;
let btnArr = [
{
key: 'BTN_SAVE',
icon: <i className='icon-coms-Preservation'/>,
content : `${getLabel(86,'保存')}`,
onClick : () => saveForm()
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),
},]
key: "log",
content: getLabel(83, "日志"),
icon: <i className="icon-coms-Print-log"/>,
onClick: () => setLogVisible(true)
}];
return btnArr;
}
render() {
/*
1判断是否无权限 是显示无权限页面
2渲染form页面:
2渲染form页面:
2-1: WeaRightMenu 右键菜单
2-2: WeaTop: 顶部: 包括下拉菜单
2-3: renderLoading: 加载数据中的loading效果(统一封装在util中)
@ -56,51 +56,56 @@ export default class BaseForm extends React.Component {
2-5: 通过getSearchs方法渲染form
*/
const { baseFormStore } = this.props;
const { loading, hasRight, form, condition, logVisible, logStore, saveLoading, setLogVisible, saveForm } = baseFormStore; // 从后台取数据 和 方法
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>,
<Button type="primary" loading={saveLoading} onClick={() => saveForm()}>保存</Button>
];
const collectParams = { // 收藏功能配置
favname: '基础表单',
favname: "基础表单",
favouritetype: 1,
objid: 0,
link: 'wui/index.html#/ns_demo01/index',
importantlevel: 1,
link: "wui/index.html#/ns_demo01/index",
importantlevel: 1
};
return (
<WeaRightMenu
datas={this.getRightMenu()} // 右键菜单
collectParams={collectParams} // 收藏功能: 配置之后显示 收藏、帮助、显示页面地址 这3个功能
<WeaTop
title="基础表单" // title
icon={<i className="icon-coms-fa"/>} // 左侧图标
iconBgcolor="#F14A2D" // 左侧图标背景色
buttons={btns} // 顶部按钮: 这里是保存按钮,不需要可以不显示
buttonSpace={10} // 按钮之间的间隔
showDropIcon={true} // 是否显示右侧下拉按钮
dropMenuDatas={this.getRightMenu()} // 下拉菜单(和页面的右键菜单相同)
dropMenuProps={{ collectParams }} // 收藏功能: 配置之后显示 收藏、帮助、显示页面地址 这3个功能
>
<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>
</WeaRightMenu>
)
{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

@ -5,24 +5,11 @@
* LastEditTime: 2022-06-29 10:06:13
*/
import React from "react";
import { WeaCheckbox, WeaInputSearch, WeaDialog } from "ecCom";
import { Button, Dropdown, Menu, Modal } from "antd";
import "../../pages/dataAcquisition/attendance/index.less"
import { WeaCheckbox, WeaDialog, WeaInputSearch } from "ecCom";
import { Button } from "antd";
import "./index.less";
export const items = [
{
key: "1",
title: "测试",
checked: false
},
{
key: "2",
title: "测试2",
checked: true
}
];
export default class SelectItemModal extends React.Component {
constructor(props) {
super(props);
@ -31,62 +18,52 @@ export default class SelectItemModal extends React.Component {
};
}
handleShowChecked(value) {
value = value == 1 ? true : false;
this.props.onShowChecked(value);
}
handleMenuClick(e) {
if (e.key == "1") { //恢复默认设置
this.props.onRestoreDefault();
} else if (e.key == "2") {
this.props.onSetDefault();
} else if (e.key == "3") {
}
componentWillReceiveProps(nextProps, nextContext) {
if (
nextProps.visible !== this.props.visible &&
!nextProps.visible
) this.setState({ searchValue: "" });
}
render() {
const menu = (
<Menu onClick={(e) => this.handleMenuClick(e)}>
<Menu.Item key="1">恢复默认设置</Menu.Item>
<Menu.Item key="2">设置默认设置</Menu.Item>
{/* <Menu.Item key="3">操作日志</Menu.Item> */}
</Menu>
);
const { searchValue } = this.state;
const {
title, onSearchItemSet, onShowOnlyChecked, children,
onMoreOpts, onSave, ...extra
} = this.props;
const btns = [<Button type="primary" onClick={onSave}>保存</Button>];
const moreBtn = {
datas: [
{
key: "recovery",
content: "恢复默认设置",
icon: <i className="icon-coms-Flow-setting"/>,
onClick: key => onMoreOpts(key)
},
{
key: "setting",
content: "设为默认设置",
icon: <i className="icon-coms-Flow-setting"/>,
onClick: key => onMoreOpts(key)
}
]
};
const titleComp = <div className="setHeaderWrapper">
<span>{title}</span>
<WeaInputSearch value={searchValue} onChange={searchValue => this.setState({ searchValue })}
placeholder="请输入关键字" style={{ width: 200 }}
onSearch={onSearchItemSet}
/>
</div>;
const bottomLeft = <WeaCheckbox content="只显示已选中字段" onChange={onShowOnlyChecked}/>;
return (
<WeaDialog
visible={this.props.visible}
style={{width:800}}
onCancel={this.props.onCancel}
initLoadCss
className="fieldSetWrapper"
title="导入字段设置"
buttons={[
<Button type="primary" style={{ marginRight: "10px" }} onClick={() => {
this.props.onSave();
}}>保存</Button>,
<Dropdown.Button overlay={menu}>更多</Dropdown.Button>
]}
<WeaDialog {...extra} hasScroll title={titleComp}
style={{ width: 592, height: 248 }}
buttons={btns} moreBtn={moreBtn}
initLoadCss className="setWrapper"
bottomLeft={bottomLeft}
>
<div className="searchWrapper">
<WeaInputSearch
placeholder={"请输入关键字"}
value={this.state.searchValue}
onChange={(value) => {
this.setState({ searchValue: value });
}}
onSearch={(value) => {
this.props.onSearch(value);
}}
/>
</div>
{this.props.children}
<div className="allInWrapper">
<WeaCheckbox content="只显示已选中字段" onChange={(value) => {
this.handleShowChecked(value);
}}/>
</div>
{children}
</WeaDialog>
);
}

View File

@ -0,0 +1,67 @@
.setWrapper {
.setHeaderWrapper, .setGroupWrapper {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.wea-title .ant-checkbox-wrapper > span:last-child, .setGroupWrapper > .checkedtitle {
color: #111;
font-weight: 600;
font-size: 12px;
padding-right: 8px;
}
.itemContUl {
display: flex;
align-items: center;
flex-wrap: wrap;
li {
width: 124px;
overflow: hidden;
padding: 4px 0;
.wea-checkbox {
width: 100%;
}
.ant-checkbox-wrapper {
display: flex;
align-items: center;
width: 100%;
span:last-child {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
.itemsWrapper {
height: 160px;
overflow: scroll;
border: 1px solid #e5e5e5;
border-radius: 4px;
padding: 16px;
width: 100%;
.empty {
line-height: 160px;
text-align: center;
font-size: 14px;
display: inline-block;
width: 100%;
}
}
.wea-more-button {
ul > li:last-child {
display: none !important;
}
}
}

View File

@ -1,78 +1,121 @@
import React from "react";
import { WeaCheckbox } from "ecCom";
import { Col, Icon, Row } from "antd";
/*
* Author: 黎永顺
* name: 设置项目
* Description:
* Date: 2023/3/6
*/
import React, { Component } from "react";
import { WeaCheckbox, WeaSearchGroup } from "ecCom";
export default class SelectItemsWrapper extends React.Component {
class SelectItemsWrapper extends Component {
constructor(props) {
super(props);
this.state = {
showContent: true,
checkStatus: false
searchVal: "",
selectItem: [],
groupItem: [],
showOnlyChecked: false
};
}
handleAllChecked(value) {
value = value == 1 ? true : false;
let items = [...this.props.items];
items.map(item => {
item.checked = value;
});
componentDidMount() {
const { dataSource } = this.props
this.setState({
checkStatus: value
selectItem: _.map(_.filter(_.reduce(dataSource, (pre, cur) => {
return [...pre, ...cur.items];
}, []), item => !!item.checked), it => it.id)
});
this.props.onChange(items);
}
handleItemChange(value, record) {
value = value == 1 ? true : false;
let items = [...this.props.items];
items.map(item => {
if (item.id == record.id) {
item.checked = value;
handleSearchItemSet = (searchVal) => this.setState({ searchVal });
handleShowOnlyChecked = (showOnlyChecked) => this.setState({ showOnlyChecked: !!Number(showOnlyChecked) });
handleSelectGroupAll = (groupId, checked) => {
const { selectItem, groupItem } = this.state;
const { dataSource } = this.props;
_.map(dataSource, item => {
if (item.groupId === groupId) {
if (!!Number(checked)) {
this.setState({
groupItem: [...groupItem, ..._.map(item.items, child => child.id)]
}, () => this.setState({ selectItem: [...selectItem, ...this.state.groupItem] }));
} else {
this.setState({
groupItem: _.differenceWith(groupItem, _.map(item.items, child => child.id), _.isEqual)
}, () => this.setState({ selectItem: this.state.groupItem }));
}
}
});
this.props.onChange(items);
}
};
handleSelectItem = (id, checked) => {
const { selectItem } = this.state;
this.setState({
selectItem: !!Number(checked) ? [...selectItem, id] : _.xorWith(selectItem, [id], _.isEqual)
});
};
renderTitle = (item) => {
const { onSelectGroupAll } = this.props;
const { groupName, groupId, items } = item;
const number = _.filter(items, it => !!it.checked).length;
const value = _.every(items, it => !!it.checked) ? "1" : "0";
return <div className="setGroupWrapper">
<WeaCheckbox content={groupName} value={value} onChange={(val) => onSelectGroupAll(groupId, val)}/>
<span className="checkedtitle">已选择{number}个字段</span>
</div>;
};
render() {
const { searchVal, selectItem, showOnlyChecked } = this.state;
const { onSelectItem, dataSource } = this.props;
let setItemList = _.map(dataSource, item => {
return {
...item,
items: _.filter(item.items || [], child => child.name.indexOf(searchVal) !== -1)
};
});
setItemList = _.map(setItemList, item => {
return {
...item,
items: _.map(item.items, child => {
return { ...child, checked: selectItem.includes(child.id) };
})
};
});
if (showOnlyChecked) {
setItemList = _.map(setItemList, item => {
return { ...item, items: _.filter(item.items, it => !!it.checked) };
});
}
return (
<div>
<div style={{ margin: "10px 0", cursor: "pointer" }}>
<div style={{ display: "inline-block" }}><WeaCheckbox
content={<span style={{ fontWeight: "600" }}>{this.props.title}</span>} onChange={(value) => {
this.handleAllChecked(value);
}} value={this.state.checkStatus}/></div>
<div style={{ float: "right", fontWeight: "600" }} onClick={() => this.setState({
showContent: !this.state.showContent
})}>已选中{this.props.items ? this.props.items.filter(item => item.checked).length : 0}个字段
<span style={{ marginLeft: "10px", fontWeight: "400" }}>
{
this.state.showContent ? <Icon type="down"/> : <Icon type="left"/>
}
</span>
</div>
</div>
<React.Fragment>
{
this.state.showContent && <div style={{
height: "160px",
border: "1px solid #eee",
padding: "10px",
overflowY: "scroll",
borderRadius: "5px"
}}>
<Row>
{
this.props.items && this.props.items.map(item => (
<Col span={6}><WeaCheckbox content={item.name} value={item.checked} onChange={(value) => {
this.handleItemChange(value, item);
}}/></Col>
))
}
</Row>
</div>
_.map(setItemList, item => {
const { items } = item;
return <WeaSearchGroup title={this.renderTitle(item)} showGroup>
<div className="itemsWrapper">
{
_.isEmpty(items) ?
<span className="empty">暂无数据</span> :
<ul className="itemContUl">
{
_.map(items, child => {
const { name, checked, id } = child;
return <li title={name}>
<WeaCheckbox
content={name} value={checked ? "1" : "0"}
onChange={(val) => onSelectItem(id, val)}
/>
</li>;
})
}
</ul>
}
</div>
</WeaSearchGroup>;
})
}
</div>
</React.Fragment>
);
}
}
export default SelectItemsWrapper;

View File

@ -50,7 +50,7 @@
.btnWrapper {
position: absolute;
right: 50px;
top: 0px;
top: 0;
}
}
@ -58,5 +58,8 @@
.wea-new-top-req-wapper .wea-new-top-req-title>div:last-child{
right: 16px!important;
}
.wea-new-top-req-wapper .wea-new-top-req-title>div:first-child>div:first-child{
min-width: 440px!important;
}
}

View File

@ -11,7 +11,7 @@ export default class StepSlide extends React.Component {
className='slideOuterWrapper'
visible={this.props.visible}
top={0}
width={40}
width={65}
height={100}
direction={"right"}
measure={"%"}

View File

@ -1,28 +1,29 @@
import React from 'react';
import { WeaSteps } from 'ecCom'
import React from "react";
import { WeaSteps } from "ecCom";
import "./index.less";
const Step = WeaSteps.Step;
import "./index.less"
export default class StepSlideHeader extends React.Component {
render() {
return (
<div className="stepSlideHeader">
<div className="headerWrapper">
<WeaSteps current={this.props.current}>
{
this.props.steps && this.props.steps.map(item =>
(
<Step description={item} />
)
)
}
</WeaSteps>
</div>
<div className="contentWrapper">
{this.props.children}
</div>
</div>
)
}
}
render() {
return (
<div className="stepSlideHeader">
<div className="headerWrapper">
<WeaSteps current={this.props.current}>
{
this.props.steps && this.props.steps.map(item =>
(
<Step description={item}/>
)
)
}
</WeaSteps>
</div>
<div className="contentWrapper">
{this.props.children}
</div>
</div>
);
}
}

View File

@ -0,0 +1,84 @@
import React, { Component } from "react";
import { WeaLocaleProvider, WeaTools, WeaUpload } from "ecCom";
import { Icon, Modal } from "antd";
import "./index.less";
const getLabel = WeaLocaleProvider.getLabel;
const { viewer } = WeaTools;
class ImageUploadList extends Component {
constructor(props) {
super(props);
this.state = {
imageUrl: ""
};
}
componentDidMount() {
const { wmImg } = this.props;
if (!_.isEmpty(wmImg)) {
this.setState({
imageUrl: wmImg[0].imgSrc
});
}
}
handleChange = (ids, list) => {
this.setState({
imageUrl: list[0].imgSrc
}, () => this.props.onChange([{ imgSrc: this.state.imageUrl }]));
};
handleDelete = () => {
Modal.confirm({
title: getLabel(111, "信息确认"),
content: getLabel(111, "确认要删除吗?"),
onOk: () => {
this.setState({
imageUrl: ""
}, () => this.props.onChange(null));
}
});
};
render() {
const { imageUrl } = this.state;
const uploadProps = {
uploadUrl: "/api/doc/upload/uploadFile",
listType: "img",
limitType: "jpg,jpeg,png,gif",
category: "string",
maxFilesNumber: 1,
onChange: this.handleChange
};
const imgPreviewProps = {
src: imageUrl,
width: 100,
height: 100
};
return (
<div className="uploadWrapper">
{
imageUrl &&
<div className="previewWrapper">
<img data-imgsrc={imgPreviewProps.src} {...imgPreviewProps} onClick={viewer} alt=""/>
<div className="operateWrapper">
<i className="icon-coms-Delete operateIcon" onClick={this.handleDelete}/>
</div>
</div>
}
{
!imageUrl &&
<WeaUpload {...uploadProps}>
<div className="upload-select-picture-card">
<Icon type="plus"/>
<div className="uploadText">{getLabel(111, "上传图片")}</div>
</div>
</WeaUpload>
}
</div>
);
}
}
export default ImageUploadList;

View File

@ -0,0 +1,68 @@
.textSetting {
.uploadWrapper {
display: flex;
align-items: center;
position: relative;
.previewWrapper {
border: 1px solid #d9d9d9 !important;
img {
width: 100%;
height: 100%;
margin-left: 0 !important;
cursor: pointer;
}
.operateWrapper {
display: none;
}
}
.previewWrapper:hover {
.operateWrapper {
display: flex;
position: absolute;
align-items: center;
justify-content: flex-end;
width: 30px;
height: 20px;
background-color: rgba(0, 0, 0, 0.3);
bottom: 4px;
right: 13px;
border-radius: 3px;
padding-right: 4px;
}
}
}
.upload-select-picture-card, .previewWrapper {
border: 1px dashed #d9d9d9;
width: 96px;
height: 96px;
padding: 0;
border-radius: 6px;
background-color: #fbfbfb;
text-align: center;
cursor: pointer;
-webkit-transition: border-color .3s ease;
-o-transition: border-color .3s ease;
transition: border-color .3s ease;
display: flex;
flex-direction: column;
justify-content: center;
margin-right: 8px;
margin-bottom: 8px;
span.rc-upload {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
}
.upload-select-picture-card:hover {
border-color: #2db7f5;
}
}

View File

@ -14,7 +14,7 @@ import OtherDeduct from "./pages/dataAcquisition/otherDeduct";
import CumSituation from "./pages/dataAcquisition/cumSituation";
import Attendance from "./pages/dataAcquisition/attendance";
import SpecialAddDeduction from "./pages/dataAcquisition/specialAddDeduction";
import Ledger from "./pages/ledger";
import Ledger from "./pages/ledgerPage";
import Calculate from "./pages/calculate";
import Payroll from "./pages/payroll";
import PayrollGrant from "./pages/payroll/payrollGrant";
@ -32,6 +32,12 @@ import MobilePayroll from "./pages/mobilePayroll";
import SysConfig from "./pages/sysConfig";
import RuleConfig from "./pages/ruleConfig";
import Appconfig from "./pages/appConfig";
import FieldManagement from "./pages/fieldManagement";
import AnalysisOfSalaryStatistics from "./pages/analysisOfSalaryStatistics";
import EmployeeList from "./pages/employeeView";
import ReportView from "./pages/reportView";
import MySalaryView from "./pages/mySalary/mySalaryView";
import WatermarkPreview from "./pages/payroll/watermarkPreview";
import stores from "./stores";
import "./style/index";
@ -50,6 +56,7 @@ const SocialSecurityBenefits = (props) => props.children;
const DataAcquisition = (props) => props.children;
// mySalary 我的薪资福利
// mySalaryView 我的薪资福利-查看工资单
// socialSecurityBenefits 社保福利
// programme 社保福利方案
// archives 社保福利档案
@ -77,6 +84,9 @@ const DataAcquisition = (props) => props.children;
// sysconfig 系統配置
// sysconfig-1 规则配置
// appconfig 应用配置
// fieldManagement 字段管理
// analysisOfSalaryStatistics 薪酬统计分析
// reportView 薪酬报表查看
const Routes = (
<Route
@ -85,6 +95,7 @@ const Routes = (
onEnter={getLocaleLabel}
component={Home}>
<Route key="mySalary" path="mySalary" component={MySalary}/>
<Route key="mySalaryView" path="mySalary/:salaryInfoId" component={MySalaryView}/>
<Route
key="socialSecurityBenefits"
path="socialSecurityBenefits"
@ -129,6 +140,7 @@ const Routes = (
/>
<Route key="compareDetail" path="compareDetail" component={CompareDetail}/>
<Route key="payroll" path="payroll" component={Payroll}/>
<Route key="watermarkPreview" path="payroll/watermark/preview" component={WatermarkPreview}/>
<Route key="payrollGrant" path="payrollGrant" component={PayrollGrant}/>
<Route key="payrollDetail" path="payrollDetail" component={PayrollDetail}/>
<Route
@ -148,6 +160,10 @@ const Routes = (
<Route key="sysconfig" path="sysconfig" component={SysConfig}/>
<Route key="sysconfig-1" path="sysconfig-1" component={RuleConfig}/>
<Route key="appconfig" path="appconfig" component={Appconfig}/>
<Route key="fieldManagement" path="fieldManagement" component={FieldManagement}/>
<Route key="analysisOfSalaryStatistics" path="analysisOfSalaryStatistics" component={AnalysisOfSalaryStatistics}/>
<Route key="analysisOfSalaryStatisticsId" path="analysisOfSalaryStatistics/:employeeId" component={EmployeeList}/>
<Route key="reportView" path="reportView" component={ReportView}/>
</Route>
);

View File

@ -0,0 +1,101 @@
import { WeaLocaleProvider } from "ecCom";
const { getLabel } = WeaLocaleProvider;
export const condition = [
{
items: [
{
colSpan: 1,
checkbox: false,
checkboxValue: false,
conditionType: "SELECT",
domkey: ["dimType"],
fieldcol: 14,
label: getLabel(111, "维度类型"),
labelcol: 6,
options: [],
detailtype: 3,
rules: "required|string",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "SELECT",
domkey: ["setting4Qualitative"],
fieldcol: 14,
label: getLabel(111, "统计维度"),
labelcol: 6,
options: [],
rules: "required|string",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "INPUT",
domkey: ["dimName"],
fieldcol: 14,
label: getLabel(111, "统计维度名称"),
labelcol: 6,
value: "",
rules: "required|string",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "SELECT",
domkey: ["dimCode"],
fieldcol: 14,
label: getLabel(111, "分组所属字段"),
labelcol: 6,
options: [],
viewAttr: 2,
helpfulTip: "",
hide: true
},
{
colSpan: 1,
conditionType: "TEXTAREA",
domkey: ["remark"],
fieldcol: 14,
label: getLabel(111, "描述"),
labelcol: 6,
value: "",
viewAttr: 2
}
],
title: getLabel(111, "基础设置"),
defaultshow: true
}
];
export const reportCondition = [
{
items: [
{
colSpan: 1,
conditionType: "INPUT",
domkey: ["reportName"],
fieldcol: 14,
label: getLabel(111, "报表名称"),
labelcol: 6,
value: "",
rules: "required|string",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "SELECT",
domkey: ["dimensionIds"],
fieldcol: 14,
label: getLabel(111, "统计维度"),
labelcol: 6,
options: [],
rules: "required|string",
viewAttr: 3,
helpfulTip: "",
hide: true
}
],
title: "",
defaultshow: true
}
];

View File

@ -0,0 +1,205 @@
/*
* Author: 黎永顺
* name: 新增统计维度弹框
* Description:
* Date: 2023/4/11
*/
import React, { Component } from "react";
import { WeaDialog, WeaLocaleProvider, WeaSearchGroup } from "ecCom";
import { Button, message, Modal } from "antd";
import { dimensionGetForm, dimensionSave } from "../../../apis/statistics";
import { getSearchs } from "../../../util";
import GroupSpacingEditTable from "./groupSpacingEditTable";
import GroupIndividualEditTable from "./groupIndividualEditTable";
import "../index.less";
const { getLabel } = WeaLocaleProvider;
const keyObj = {
"RATION_GROUP_SPACING": "setting4RationGroupSpacing",
"RATION_GROUP_INDIVIDUAL": "setting4RationGroupIndividual"
};
class DimensionSlide extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
dimType: "QUALITATIVE",
setting4RationGroupSpacing: [],
setting4RationGroupIndividual: []
};
}
componentDidMount() {
this.props.initCondition();
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.formId) this.dimensionGetForm({ id: nextProps.formId });
if (nextProps.visible !== this.props.visible && !nextProps.formId) {
nextProps.form.updateFields({
dimType: "QUALITATIVE"
});
nextProps.onChangeCondition("QUALITATIVE");
}
if (nextProps.visible !== this.props.visible && !nextProps.visible) {
this.setState({
loading: false,
dimType: "QUALITATIVE",
setting4RationGroupSpacing: [],
setting4RationGroupIndividual: []
});
}
}
dimensionGetForm = (payload) => {
dimensionGetForm(payload).then(({ status, data }) => {
if (status) {
const { baseForm: { data: formData } } = data;
const setting = formData.setting ? JSON.parse(formData.setting) : {};
this.props.onChangeCondition(formData["dimType"], 1);
this.setState({
dimType: formData.dimType,
[keyObj[formData["dimType"]]]: setting
}, () => {
const fields = _.map(this.props.condition[0].items, it => {
return it.domkey[0];
});
fields.map(item => {
if (item !== "setting4Qualitative") {
this.props.form.updateFields({
[item]: formData[item] || ""
});
} else if (item === "setting4Qualitative" && formData.statsDim) {
this.props.form.updateFields({
setting4Qualitative: formData.statsDim
});
}
});
});
}
});
};
handleSave = () => {
const { dimType } = this.state;
const { condition, onCancel, formId } = this.props;
const { setting4Qualitative, dimCode, ...extraParams } = this.props.form.getFormParams();
let payload = { id: formId, ...extraParams };
if (dimType === "QUALITATIVE") {
if (!setting4Qualitative || !extraParams.dimName) {
Modal.warning({
title: getLabel(111, "信息确认"),
content: getLabel(111, "必要信息不完整,红色*为必填项!")
});
return;
}
const tjOptions = _.find(condition[0].items, item => item.domkey[0] === "setting4Qualitative").options;
const tjObj = _.find(tjOptions, item => item.key === setting4Qualitative);
payload = { ...payload, setting4Qualitative: { id: tjObj.key, name: tjObj.showname } };
} else {
if (!extraParams.dimName) {
Modal.warning({
title: getLabel(111, "信息确认"),
content: getLabel(111, "必要信息不完整,红色*为必填项!")
});
return;
}
if (dimType === "RATION_GROUP_SPACING") {
const { setting4RationGroupSpacing } = this.state;
const bool = _.every(setting4RationGroupSpacing, it => it.startValue !== "" && it.endValue !== "" && it.startValue <= it.endValue);
if (_.isEmpty(setting4RationGroupSpacing) || !bool) {
message.warning(getLabel(111, "请完善分组设置相关数据!分组设置不能为空,起始值结束值必填,且起始值需小于结束值!"));
return;
} else {
payload = {
...payload, dimCode,
setting4RationGroupSpacing: _.map(setting4RationGroupSpacing, (it, index) => ({
id: index + 1,
endValue: it.endValue,
startValue: it.startValue,
includeEnd: it.includeEnd === "1",
includeStart: it.includeStart === "1"
}))
};
}
} else if (dimType === "RATION_GROUP_INDIVIDUAL") {
const { setting4RationGroupIndividual } = this.state;
const bool = _.every(setting4RationGroupIndividual, it => it.value !== "");
if (_.isEmpty(setting4RationGroupIndividual) || !bool) {
message.warning(getLabel(111, "请完善分组设置相关数据!分组设置不能为空,且数值必填"));
return;
} else {
payload = {
...payload, dimCode,
setting4RationGroupIndividual: _.map(setting4RationGroupIndividual, (it, index) => ({ id: index + 1, ...it }))
};
}
}
}
this.setState({ loading: true });
dimensionSave(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success(getLabel(111, "保存成功"));
onCancel(true);
this.props.form.resetForm();
} else {
message.error(errormsg || getLabel(111, "保存失败"));
}
}).catch(() => this.setState({ loading: false }));
};
formItemChange = (formObj) => {
const { onChangeCondition } = this.props;
const filedKey = _.keys(formObj)[0];
if (filedKey === "dimType") {
this.setState({
dimType: formObj[filedKey].value,
setting4RationGroupSpacing: [],
setting4RationGroupIndividual: []
}, () => onChangeCondition(formObj[filedKey].value));
}
};
handleConvertGroupDatasource = (data) => {
const { dimType } = this.state;
this.setState({ [keyObj[dimType]]: data });
};
render() {
const { loading, dimType, setting4RationGroupSpacing, setting4RationGroupIndividual } = this.state;
const { form, condition, formId } = this.props;
return (
<WeaDialog
{...this.props}
initLoadCss hasScroll
style={{ width: 900, height: 450 }}
className="dimensionSlideWrapper"
title={
<div className="dimensionTitle">
<span>{formId ? getLabel(111, "编辑统计维度") : getLabel(111, "新建统计维度")}</span>
<Button type="primary" onClick={this.handleSave} loading={loading}>{getLabel(111, "保存")}</Button>
</div>
}
>
{getSearchs(form, condition, 1, false, this.formItemChange)}
{
dimType !== "QUALITATIVE" &&
<WeaSearchGroup title={getLabel(111, "分组设置")} showGroup>
{
dimType === "RATION_GROUP_SPACING" &&
<GroupSpacingEditTable onChange={this.handleConvertGroupDatasource}
setting4RationGroupSpacing={setting4RationGroupSpacing}/>
}
{
dimType === "RATION_GROUP_INDIVIDUAL" &&
<GroupIndividualEditTable onChange={this.handleConvertGroupDatasource}
setting4RationGroupIndividual={setting4RationGroupIndividual}/>
}
</WeaSearchGroup>
}
</WeaDialog>
);
}
}
export default DimensionSlide;

View File

@ -0,0 +1,121 @@
/*
* Author: 黎永顺
* name: 统计维度管理列表
* Description:
* Date: 2023/4/11
*/
import React, { Component } from "react";
import { WeaLocaleProvider, WeaTable } from "ecCom";
import { message, Modal } from "antd";
import { dimensionDelete, dimensionList } from "../../../apis/statistics";
import "../index.less";
const { getLabel } = WeaLocaleProvider;
class DimensionTable extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
dataSource: [],
pageInfo: {
current: 1, pageSize: 10, total: 0
}
};
}
componentDidMount() {
this.dimensionList();
}
dimensionList = (extra = {}) => {
const { pageInfo } = this.state;
this.setState({ loading: true });
dimensionList({ ...pageInfo, ...extra }).then(({ status, data }) => {
this.setState({ loading: false });
if (status) {
const { pageNum: current, pageSize, total, list: dataSource } = data;
this.setState({
dataSource,
pageInfo: {
...pageInfo,
current, pageSize, total
}
});
}
}).catch(() => this.setState({ loading: false }));
};
dimensionDelete = (payload) => {
Modal.confirm({
title: getLabel(111, "信息确认"),
content: getLabel(111, "确认要删除吗?"),
onOk: () => {
dimensionDelete(payload).then(({ status, errormsg }) => {
if (status) {
message.success(getLabel(111, "删除成功"));
this.dimensionList();
} else {
message.error(errormsg || getLabel(111, "删除失败"));
}
});
}
});
};
render() {
const { dataSource, loading, pageInfo } = this.state;
const { onEdit } = this.props;
const pagination = {
...pageInfo,
showTotal: total => `${getLabel(111, "共")} ${total} ${getLabel(111, "条")}`,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
onShowSizeChange: (current, pageSize) => {
this.setState({
pageInfo: { ...pageInfo, current, pageSize }
}, () => this.dimensionList());
},
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => this.dimensionList());
}
};
const columns = [
{ dataIndex: "dimName", title: getLabel(111, "统计维度") },
{ dataIndex: "remark", title: getLabel(111, "描述") },
{ dataIndex: "dimType", title: getLabel(111, "维度类型") },
{
dataIndex: "operate", title: getLabel(111, "操作"),
render: (_, record) => {
return (
<span className="space10">
{
record.canEdit &&
<a href="javascript: void(0);" onClick={() => onEdit(record.id)}>{getLabel(111, "编辑")}</a>
}
{
record.canDelete &&
<a href="javascript: void(0);"
onClick={() => this.dimensionDelete([record.id])}>{getLabel(111, "删除")}</a>
}
</span>
);
}
}
];
return (
<WeaTable
rowKey="id"
className="dimensionTableWrapper"
dataSource={dataSource}
pagination={pagination}
loading={loading}
columns={columns}
/>
);
}
}
export default DimensionTable;

View File

@ -0,0 +1,103 @@
/*
* Author: 黎永顺
* name: 员工明细列表
* Description:
* Date: 2023/5/24
*/
import React, { Component } from "react";
import { WeaLocaleProvider, WeaTable } from "ecCom";
import { statisticsEmployeeList } from "../../../apis/statistics";
import "../index.less";
const { getLabel } = WeaLocaleProvider;
class EmployeeDetails extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
dataSource: [],
columns: [],
pageInfo: {
current: 1,
pageSize: 10,
total: 0
}
};
}
componentDidMount() {
this.statisticsEmployeeList();
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.year !== this.props.year) this.statisticsEmployeeList(nextProps);
}
statisticsEmployeeList = (props) => {
const { pageInfo } = this.state;
const payload = {
year: props ? props.year : this.props.year,
keyword: props ? props.keyword : this.props.keyword,
...pageInfo
};
this.setState({ loading: true });
statisticsEmployeeList(payload).then(({ status, data }) => {
this.setState({ loading: false });
if (status) {
const { columns, list: dataSource, pageNum: current, total, pageSize } = data;
this.setState({
pageInfo: { ...pageInfo, current, pageSize, total },
dataSource,
columns: [...columns, {
title: "操作",
dataIndex: "operate",
width: 80,
render: (_, record) => {
return <a target="_blank"
href={`${window.location.origin}/spa/hrmSalary/static/index.html#/main/hrmSalary/analysisOfSalaryStatistics/${record.id}?name=${record.name}&dept=${record.department || ""}`}>{getLabel(111, "查看")}</a>;
}
}]
});
}
}).catch(() => this.setState({ loading: false }));
};
render() {
const { dataSource, loading, columns, pageInfo } = this.state;
const pagination = {
...pageInfo,
showTotal: total => `${getLabel(111, "共")} ${total} ${getLabel(111, "条")}`,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
onShowSizeChange: (current, pageSize) => {
this.setState({
pageInfo: { ...pageInfo, current, pageSize }
}, () => {
this.statisticsEmployeeList();
});
},
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => {
this.statisticsEmployeeList();
});
}
};
return (
<WeaTable
rowKey="id"
className="employeeTableWrapper"
dataSource={dataSource}
pagination={pagination}
loading={loading}
columns={columns}
scroll={{ y: `calc(100vh - 174px)` }}
/>
);
}
}
export default EmployeeDetails;

View File

@ -0,0 +1,52 @@
/*
* Author: 黎永顺
* name: 分组设置-定量-单项式分组编辑表格
* Description:
* Date: 2023/4/12
*/
import React, { Component } from "react";
import { WeaLocaleProvider, WeaTableEdit } from "ecCom";
const { getLabel } = WeaLocaleProvider;
class GroupIndividualEditTable extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: []
};
}
componentDidMount() {
const { setting4RationGroupIndividual } = this.props;
this.setState({
dataSource: setting4RationGroupIndividual
});
}
handleChangeTableData = (dataSource) => {
const { onChange } = this.props;
this.setState({ dataSource }, () => onChange(this.state.dataSource));
};
render() {
const { dataSource } = this.state;
const columns = [
{
title: getLabel(111, "分组设置值"),
dataIndex: "value",
key: "value",
com: [
{ label: "", key: "value", type: "INPUTNUMBER" }
]
}
];
return (
<WeaTableEdit
draggable={true} columns={columns} datas={dataSource}
showCopy={false} deleteConfirm onChange={this.handleChangeTableData}
/>
);
}
}
export default GroupIndividualEditTable;

View File

@ -0,0 +1,100 @@
/*
* Author: 黎永顺
* name: 分组设置-定量-组距式分组编辑表格
* Description:
* Date: 2023/4/12
*/
import React, { Component } from "react";
import { WeaLocaleProvider, WeaTableEdit } from "ecCom";
const { getLabel } = WeaLocaleProvider;
class GroupSpacingEditTable extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: []
};
}
componentDidMount() {
const { setting4RationGroupSpacing } = this.props;
this.setState({
dataSource: _.map(setting4RationGroupSpacing, item => {
return {
...item,
includeStart: item.includeStart ? "1" : "0",
includeEnd: item.includeEnd ? "1" : "0"
};
})
});
}
handleChangeTableData = (dataSource) => {
const { onChange } = this.props;
this.setState({ dataSource }, () => onChange(this.state.dataSource));
};
render() {
const { dataSource } = this.state;
const columns = [
{
title: getLabel(111, "起始值"),
dataIndex: "startValue",
key: "startValue",
com: [
{ label: "", key: "startValue", type: "INPUTNUMBER" }
]
},
{
title: getLabel(111, "含"),
dataIndex: "includeStart",
key: "includeStart",
com: [
{
type: "CHECKBOX",
key: "includeStart",
otherParams: { content: getLabel(111, "含") }
}
]
},
{
title: getLabel(111, "至"),
dataIndex: "to",
key: "to",
com: [
{ label: "", type: "TEXT" }
]
},
{
title: getLabel(111, "结束值"),
dataIndex: "endValue",
key: "endValue",
com: [
{ label: "", key: "endValue", type: "INPUTNUMBER" }
]
},
{
title: getLabel(111, "含"),
dataIndex: "includeEnd",
key: "includeEnd",
com: [
{
type: "CHECKBOX",
key: "includeEnd",
otherParams: { content: getLabel(111, "含") }
}
]
}
];
return (
<WeaTableEdit
draggable={true} deleteConfirm columns={columns}
datas={_.map(dataSource, item => ({ ...item, to: getLabel(111, "至") }))}
showCopy={false} onChange={this.handleChangeTableData}
/>
);
}
}
export default GroupSpacingEditTable;

View File

@ -0,0 +1,19 @@
/*
* Author: 黎永顺
* name: 报表表单
* Description:
* Date: 2023/4/17
*/
import React, { Component } from "react";
import { getSearchs } from "../../../util";
class ReportForm extends Component {
render() {
const { form, condition } = this.props;
return (
<React.Fragment>{getSearchs(form, condition, 1, false)}</React.Fragment>
);
}
}
export default ReportForm;

View File

@ -0,0 +1,106 @@
/*
* Author: 黎永顺
* name: 统计表
* Description:
* Date: 2023/4/17
*/
import React, { Component } from "react";
import { WeaLocaleProvider } from "ecCom";
import { Button, Col, Dropdown, Menu, message, Modal, Row } from "antd";
import { reportStatisticsReportDelete, reportStatisticsReportList } from "../../../apis/statistics";
import "../index.less";
const SubMenu = Menu.SubMenu;
const { getLabel } = WeaLocaleProvider;
class ReportList extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: []
};
}
componentDidMount() {
this.reportStatisticsReportList();
}
handleOptsClick = ({ key }, id, dimensionId) => {
if (key === "delete") {
this.reportStatisticsReportDelete(id.split(","));
} else if (key === "edit") {
this.props.onEdit("addReport", id);
}
};
reportStatisticsReportDelete = (payload) => {
Modal.confirm({
title: getLabel(111, "信息确认"),
content: getLabel(111, "确认删除本条数据吗?"),
onOk: () => {
const { reportName = "" } = this.props;
reportStatisticsReportDelete(payload).then(({ status, errormsg }) => {
if (status) {
message.success(getLabel(111, "删除成功"));
this.reportStatisticsReportList({ reportName });
} else {
message.error(errormsg || getLabel(111, "删除失败"));
}
});
}
});
};
reportStatisticsReportList = (payload = {}) => {
reportStatisticsReportList(payload).then(({ status, data: dataSource }) => {
if (status) {
this.setState({ dataSource });
}
});
};
/*
* Author: 黎永顺
* Description: 报表查看
* Params:
* Date: 2023/4/20
*/
handleGoReportView = (id) => {
window.open(`${window.location.origin}/spa/hrmSalary/static/index.html#/main/hrmSalary/reportView?id=${id}`);
};
render() {
const { dataSource } = this.state;
return (
<Row gutter={16} className="reportRow">
{
_.isEmpty(dataSource) ? <div className="empty">{getLabel(111, "暂无数据")}</div> :
_.map(dataSource, it => {
const { reportName, dimension, id, dimensionId } = it;
return <Col className="gutter-row" span={6} onClick={() => this.handleGoReportView(id)}>
<div className="card-item">
<div className="cardLeft"><i className="icon-coms-fa"/></div>
<div className="cardCenter">
<span className="reportName">{reportName}</span>
<div className="dimension">
<div className="label">{getLabel(111, "统计维度")}</div>
<div className="value">{dimension}</div>
</div>
</div>
<div className="cardRight">
<Dropdown overlay={
<Menu onClick={e => this.handleOptsClick(e, id, dimensionId)}>
<Menu.Item key="edit">{getLabel(111, "编辑")}</Menu.Item>
<Menu.Item key="delete">{getLabel(111, "删除")}</Menu.Item>
</Menu>
}>
<Button type="ghost"><i className="icon-coms-more"/></Button>
</Dropdown>
</div>
</div>
</Col>;
})
}
</Row>
);
}
}
export default ReportList;

View File

@ -0,0 +1,70 @@
/*
* Author: 黎永顺
* name: 统计弹框
* Description:
* Date: 2023/4/10
*/
import React, { Component } from "react";
import { Button, message, Modal } from "antd";
import { WeaDialog, WeaLocaleProvider } from "ecCom";
import { reportStatisticsReportSave } from "../../../apis/ruleconfig";
import "../index.less";
const { getLabel } = WeaLocaleProvider;
class StatisticsModal extends Component {
constructor(props) {
super(props);
this.state = {
loading: false
};
}
handleSaveReportList = () => {
const { form, id, onCancel } = this.props;
form.validateForm().then(f => {
if (f.isValid) {
const { dimensionIds, reportName } = form.getFormParams();
const payload = { id, reportName, dimensionIds: dimensionIds.split(",") };
this.setState({ loading: true });
reportStatisticsReportSave(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
onCancel(true);
message.success(getLabel(111, "保存成功"));
form.resetForm();
} else {
message.error(errormsg || getLabel(111, "保存失败"));
}
}).catch(() => this.setState({ loading: false }));
} else {
Modal.warning({
title: getLabel(111, "信息确认"),
content: getLabel(111, "必要信息不完整,红色*为必填项!")
});
}
});
};
render() {
const { loading } = this.state;
const { typeKey, onCancel } = this.props;
const buttons = typeKey === "addReport" ? [
<Button type="primary" onClick={this.handleSaveReportList} loading={loading}>{getLabel(111, "保存")}</Button>
] : [];
return (
<WeaDialog
{...this.props} hasScroll
style={typeKey === "addReport" ? { width: 600 } : { width: 640, height: 540 }}
buttons={buttons}
onCancel={onCancel}
initLoadCss
className="dimensionModalWrapper"
>
{this.props.children}
</WeaDialog>
);
}
}
export default StatisticsModal;

View File

@ -0,0 +1,312 @@
/*
* Author: 黎永顺
* name: 薪酬统计分析
* Description:
* Date: 2023/4/10
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaDatePicker, WeaInputSearch, WeaLocaleProvider, WeaReqTop } from "ecCom";
import { Button } from "antd";
import { condition, reportCondition } from "./components/conditions";
import { commonEnumList, reportGetForm } from "../../apis/ruleconfig";
import { dimensionGetForm } from "../../apis/statistics";
import EmployeeDetails from "./components/employeeDetails";
import StatisticsModal from "./components/statisticsModal";
import DimensionSlide from "./components/dimensionSlide";
import DimensionTable from "./components/dimensionTable";
import ReportList from "./components/reportList";
import ReportForm from "./components/reportForm";
import moment from "moment";
import "./index.less";
const { getLabel } = WeaLocaleProvider;
@inject("taxAgentStore", "attendanceStore")
@observer
class Index extends Component {
constructor(props) {
super(props);
this.state = {
conditions: [],
convertConditions: [],
reportConditions: [],
selectedKey: "statistics",
reportName: "",
keyword: "",
year: moment().format("YYYY"),
slideReq: {
visible: false, formId: ""
},
modalReq: {
title: "", visible: false,
typeKey: "", id: ""
}
};
}
componentDidMount() {
this.initReportFormCondition();
}
initReportFormCondition = (payload = {}) => {
const { attendanceStore: { reportForm } } = this.props;
reportGetForm(payload).then(({ status, data }) => {
if (status) {
const { statsDimOptions, data: detailData } = data;
if (_.isEmpty(payload)) {
this.setState({
reportConditions: _.map(reportCondition, item => {
return {
...item,
items: _.map(item.items, child => {
if (child.domkey[0] === "dimensionIds") {
return {
...child,
options: _.map(statsDimOptions, dimTypeItem => ({
key: dimTypeItem.id,
showname: dimTypeItem.content
}))
};
}
return { ...child };
})
};
})
}, () => {
reportForm.initFormFields(this.state.reportConditions);
});
} else {
reportForm.updateFields({
reportName: detailData.reportName,
dimensionIds: detailData.dimension.join(",")
});
}
}
});
};
initCondition = async () => {
const { attendanceStore: { statisticsForm } } = this.props;
const [dimTypeEnum, dimCodeList] = await Promise.all([this.commonEnumList(), this.dimensionGetForm()]);
const { data: dimTypeData } = dimTypeEnum, { data: dimCodeData } = dimCodeList;
const { baseForm: { statsDimOptions, groupDimOptions, data: dimTypeValue } } = dimCodeData;
this.setState({
conditions: _.map(condition, item => {
return {
...item,
items: _.map(item.items, child => {
if (child.domkey[0] === "dimType") {
return {
...child,
value: dimTypeValue.dimType,
options: _.map(dimTypeData, dimTypeItem => ({
key: dimTypeItem.value,
showname: dimTypeItem.defaultLabel
}))
};
}
if (child.domkey[0] === "setting4Qualitative") {
return {
...child,
options: _.map(statsDimOptions, dimCodeItem => ({
key: dimCodeItem.id,
showname: dimCodeItem.content
}))
};
}
if (child.domkey[0] === "dimCode") {
return {
...child,
options: _.map(groupDimOptions, dimCodeItem => ({
key: dimCodeItem.id,
showname: dimCodeItem.content
}))
};
}
return { ...child };
})
};
})
}, () => {
this.setState({ convertConditions: this.state.conditions });
statisticsForm.initFormFields(this.state.conditions);
});
};
commonEnumList = () => {
const payload = {
enumClass: "com.engine.salary.report.enums.SalaryStatisticsDimensionTypeEnum"
};
return commonEnumList(payload);
};
dimensionGetForm = () => {
return dimensionGetForm();
};
handleChangeCondition = (val, viewAttr) => {
const { attendanceStore: { statisticsForm } } = this.props;
const helpfulTitle = val === "RATION_GROUP_SPACING" ?
"例:\n" +
" 若所属字段为【工龄】分组设置为【0-5】【5-10】统计项为【税前薪资】对应的统计规则为【求和】 则统计结果为【工龄】为【0-5】的所有人的【税前薪资】求和【工龄】为【5-10】的所有人的【税前薪资】求和\n" +
"若未选择所属字段分组设置为【0-10,000.00】【10,000.00-20,000.00】;若统计项为【税前薪资】,对应的统计规则为【计数】; 则统计结果为【税前薪资】为【0-10,000.00】有多少人【税前薪资】为【10,000.00-20,000.00】有多少人;" :
val === "RATION_GROUP_INDIVIDUAL" ?
"例:\n" +
" 若所属字段为【职级】分组设置为【1】【2】【3】统计项为【税前薪资】对应的统计规则为【平均值】 则统计结果为【职级】为【1】的所有人的【税前薪资】的平均值【职级】为【2】的所有人的【税前薪资】的平均值【职级】为【3】的所有人的【税前薪资】的平均值\n" +
"若未选择所属字段分组设置为【1】【2】【3】若统计项为【绩效】对应的统计规则为【计数】 则统计结果为【绩效】为【1】有多少人绩效为【2】有多少人绩效为【3】有多少人" : "";
if (val === "QUALITATIVE") {
this.setState({
conditions: _.map(this.state.convertConditions, item => {
return {
...item,
items: _.map(_.filter(item.items, child => child.domkey[0] !== "dimCode"), it => {
if (it.domkey[0] === "dimType") {
return { ...it, value: val, viewAttr: viewAttr ? viewAttr : it.viewAttr };
}
return { ...it };
})
};
})
}, () => {
statisticsForm.setCondition(this.state.conditions);
});
} else {
this.setState({
conditions: _.map(this.state.convertConditions, item => {
return {
...item,
items: _.map(_.filter(item.items, child => child.domkey[0] !== "setting4Qualitative"), it => {
if (it.domkey[0] === "dimType") {
return { ...it, value: val, viewAttr: viewAttr ? viewAttr : it.viewAttr };
} else if (it.domkey[0] === "dimCode") {
return { ...it, helpfulTitle };
}
return { ...it };
})
};
})
}, () => {
statisticsForm.setCondition(this.state.conditions);
});
}
};
handleReqBtnsClick = (key, id = "") => {
if (key === "search") {
const { reportName } = this.state;
this.reportListRef.reportStatisticsReportList({ reportName });
} else {
const { modalReq } = this.state;
const title = key === "dimension" ?
<div className="dimensionTitle">
<span>{getLabel(111, "统计维度管理")}</span>
<Button type="primary" onClick={() => this.handleAddDimension()}>{getLabel(111, "新建统计维度")}</Button>
</div>
: getLabel(111, id ? "编辑报表" : "新建报表");
this.setState({
modalReq: {
...modalReq, id, title,
visible: true, typeKey: key
}
}, () => id && this.initReportFormCondition({ id }));
}
};
handleCancel = (refresh = false) => {
const { attendanceStore: { reportForm } } = this.props;
const { modalReq } = this.state;
this.setState({
modalReq: {
...modalReq, visible: false, id: ""
}
}, () => {
const { selectedKey, reportName, modalReq: { typeKey } } = this.state;
selectedKey === "statistics" && reportForm.resetForm();
typeKey === "dimension" && this.initReportFormCondition();
refresh && selectedKey === "statistics" && this.reportListRef.reportStatisticsReportList({ reportName });
});
};
handleAddDimension = (formId = "") => {
const { slideReq } = this.state;
this.setState({
slideReq: {
...slideReq, visible: true,
formId
}
});
};
handleClose = (initTable = false) => {
const { attendanceStore: { statisticsForm } } = this.props;
const { slideReq } = this.state;
this.setState({
slideReq: {
...slideReq, visible: false, formId: ""
}
}, () => {
statisticsForm.resetForm();
initTable && this.dimensionTableRef.dimensionList();
});
};
render() {
const { taxAgentStore: { statisticsReportBtn }, attendanceStore: { statisticsForm, reportForm } } = this.props;
const { selectedKey, modalReq, slideReq, conditions, reportConditions, reportName, keyword, year } = this.state;
const buttons = selectedKey === "statistics" ? [
<Button type="primary" onClick={() => this.handleReqBtnsClick("addReport")}>{getLabel(111, "新建报表")}</Button>,
<Button type="ghost"
onClick={() => this.handleReqBtnsClick("dimension")}>{getLabel(111, "维度统计管理")}</Button>,
<WeaInputSearch placeholder={getLabel(111, "请输入报表名称")} className="search"
value={reportName}
onChange={reportName => this.setState({ reportName })}
onSearch={() => this.handleReqBtnsClick("search")}/>
] : [
<span className="employeeYearWrapper">
<span>{getLabel(111, "年薪资核算人员明细:")}</span>
<WeaDatePicker value={year} format="YYYY" onChange={year => this.setState({ year })}/>
</span>,
<WeaInputSearch placeholder={getLabel(111, "请输入姓名、工号、身份证号")} className="search"
value={keyword}
onChange={keyword => this.setState({ keyword })}
onSearch={() => this.employeeListRef.statisticsEmployeeList()}/>
];
const tabs = [
{ key: "statistics", title: getLabel(111, "统计表") },
{ key: "detail", title: getLabel(111, "员工明细") }
];
return (
<WeaReqTop
title={getLabel(111, "薪酬统计报表")} icon={<i className="icon-coms-fa"/>} selectedKey={selectedKey}
iconBgcolor="#F14A2D" tabDatas={tabs} className="xc_tj_fx_wrapper" showDropIcon={false}
buttons={(!statisticsReportBtn && selectedKey === "statistics") ? buttons.slice(-1) : buttons} buttonSpace={10}
onChange={selectedKey => this.setState({ selectedKey }, () => this.state.selectedKey === "statistics" && this.initReportFormCondition())}
>
{
selectedKey === "statistics" ?
<ReportList
ref={dom => this.reportListRef = dom}
reportName={reportName}
onEdit={this.handleReqBtnsClick}
/> : <EmployeeDetails
ref={dom => this.employeeListRef = dom}
keyword={keyword} year={year}
/>
}
<StatisticsModal {...modalReq} onCancel={this.handleCancel} form={reportForm}>
{
modalReq.typeKey === "dimension" &&
<DimensionTable ref={dom => this.dimensionTableRef = dom}
onEdit={id => this.handleAddDimension(id)}
/>
}
{
modalReq.typeKey === "addReport" &&
<ReportForm form={reportForm} condition={reportConditions}/>
}
</StatisticsModal>
<DimensionSlide
{...slideReq} onCancel={this.handleClose}
form={statisticsForm} condition={conditions}
initCondition={this.initCondition} onChangeCondition={this.handleChangeCondition}
/>
</WeaReqTop>
);
}
}
export default Index;

View File

@ -0,0 +1,178 @@
.xc_tj_fx_wrapper {
.search {
top: -3px;
margin-right: 10px;
width: 220px;
}
.employeeYearWrapper {
display: flex;
align-items: center;
& > span:first-child {
margin-right: 4px;
}
}
.wea-new-top-req-content {
background: #FFF;
.reportRow {
padding: 16px;
.gutter-row {
margin-bottom: 16px;
border-radius: 6px;
.card-item {
border-radius: 6px;
display: flex;
height: 90px;
justify-content: space-between;
padding: 22px 0 22px 16px;
border: 1px solid #e5e5e5;
.cardLeft {
display: flex;
align-items: center;
justify-content: center;
i {
padding: 10px;
color: #FFF;
font-size: 20px;
border-radius: 50%;
background-color: #ff666a;
}
}
.cardCenter {
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-between;
margin-left: 10px;
.reportName {
font-size: 14px;
color: #111;
font-weight: 600;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.dimension {
display: flex;
.label {
height: 12px;
font-size: 12px;
color: #999;
line-height: 12px;
font-weight: 400;
}
.value {
height: 12px;
font-size: 12px;
color: #111;
line-height: 12px;
font-weight: 400;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.cardRight {
display: flex;
align-items: center;
justify-content: center;
.ant-btn-ghost {
color: #999;
border: 1px solid transparent;
}
.ant-btn-ghost:focus, .ant-btn-ghost:hover,
.ant-btn-ghost.active, .ant-btn-ghost:active {
color: #2baee9;
background-color: #FFF;
border: 1px solid #e5e5e5;
}
}
}
}
.card-item:hover {
cursor: pointer;
box-shadow: 0 3px 12px 0 rgba(0, 0, 0, .12);
}
}
.empty {
font-size: 16px;
width: 100%;
text-align: center;
margin-top: 26px;
}
}
}
//统计维度弹框
.dimensionModalWrapper, .dimensionSlideWrapper {
.dimensionTitle {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
}
.dimensionTableWrapper {
.space10 {
a:first-child {
margin-right: 10px;
}
}
}
}
.dimensionSlideWrapper, .dimensionModalWrapper {
.wea-search-group {
.wea-select, .ant-select, .ant-select-selection {
width: 100%;
}
}
}
//员工明细
.employeeTableWrapper {
.operates i.icon-coms-more {
padding: 5px 0;
display: inline-block;
width: 40px;
font-size: 20px;
color: #333;
cursor: pointer;
font-weight: 400;
}
}
.operatePopover {
.ant-popover-inner {
min-width: 100px !important;
}
.ant-popover-inner-content {
padding: 0;
.ant-menu {
border-right: none;
}
}
}

View File

@ -5,9 +5,19 @@
* Date: 2022-09-27 18:17:02
*/
import React, { Component } from "react";
import { WeaCheckbox, WeaDatePicker, WeaFormItem, WeaSearchGroup, WeaTop } from "ecCom";
import { WeaCheckbox, WeaDatePicker, WeaFormItem, WeaInput, WeaSearchGroup, WeaTop } from "ecCom";
import * as API from "../../apis/ruleconfig";
import { Button, message } from "antd";
import "./index.less";
const Input = (props) => {
const { label, value } = props;
return (
<WeaFormItem label={label} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
<WeaInput viewAttr={1} value={value}/>
</WeaFormItem>
);
};
class AppConfig extends Component {
constructor(props) {
@ -15,6 +25,9 @@ class AppConfig extends Component {
this.state = {
openAcctResultSum: "0",
displayEmpInfoReport: "0",
isLog: "0",
openFormulaForcedEditing: "0",
version: "",
loading: false
};
}
@ -26,8 +39,13 @@ class AppConfig extends Component {
queryAppsetting = () => {
API.queryAppsetting().then(({ status, data }) => {
if (status) {
const { openAcctResultSum, displayEmpInfoReport } = data;
this.setState({ openAcctResultSum, displayEmpInfoReport });
const { openAcctResultSum, displayEmpInfoReport, isLog, openFormulaForcedEditing, version } = data;
this.setState({
openAcctResultSum, displayEmpInfoReport,
isLog: isLog === "true" ? "1" : "0",
openFormulaForcedEditing: openFormulaForcedEditing === "true" ? "1" : "0",
version
});
}
});
};
@ -46,9 +64,15 @@ class AppConfig extends Component {
};
render() {
const { openAcctResultSum, displayEmpInfoReport, loading } = this.state;
const { openAcctResultSum, displayEmpInfoReport, loading, openFormulaForcedEditing, isLog, version } = this.state;
const btns = [<Button type="primary" loading={loading} onClick={this.appSettingSave}>保存</Button>];
const items = [
{
com: Input({
label: "版本号",
value: version
})
},
{
com: CheckBox({
label: "显示薪资核算结果合计列",
@ -66,6 +90,20 @@ class AppConfig extends Component {
this.setState({ displayEmpInfoReport });
}
})
},
{
com: CheckBox({
label: "是否输出日志",
disabled: true,
value: isLog
})
},
{
com: CheckBox({
label: "是否可编辑系统公式",
disabled: true,
value: openFormulaForcedEditing
})
}
];
return (
@ -85,10 +123,10 @@ class AppConfig extends Component {
export default AppConfig;
export const CheckBox = payload => {
const { label, onChange, value } = payload;
const { label, onChange, value, disabled = false } = payload;
return (
<WeaFormItem label={label} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
<WeaCheckbox display="switch" value={value} onChange={onChange}/>
<WeaCheckbox display="switch" disabled={disabled} value={value} onChange={onChange}/>
</WeaFormItem>
);
};

View File

@ -0,0 +1,11 @@
.appConfigWrapper {
height: 100%;
display: flex;
flex-direction: column;
.wea-search-group {
flex: 1;
height: 100%;
overflow: auto;
}
}

View File

@ -1,16 +1,16 @@
import React from "react";
import { inject, observer } from "mobx-react";
import { Button, DatePicker, Dropdown, Menu, message, Modal } from "antd";
import { WeaInputSearch, WeaRightMenu, WeaTop } from "ecCom";
import { renderNoright } from "../../util"; // 渲染form数据的方法因为多个页面都会使用所以抽的公共方法在util中
import { Button, DatePicker, Dropdown, Menu, message, Modal, Tag } from "antd";
import { WeaInputSearch, WeaLocaleProvider, WeaNewScroll, WeaTop } from "ecCom";
import { renderNoright } from "../../util";
import CustomTab from "../../components/customTab";
import { columns } from "./columns";
import moment from "moment";
import BaseFormModal from "./baseFormModal";
import CustomPaginationTable from "../../components/customPaginationTable";
import ProgressModal from "../../components/progressModal";
import "./index.less";
const { getLabel } = WeaLocaleProvider;
const MonthPicker = DatePicker.MonthPicker;
@inject("calculateStore", "taxAgentStore")
@ -26,25 +26,7 @@ export default class Calculate extends React.Component {
searchValue: "",
startDate: moment(new Date()).startOf("year").format("YYYY-MM"),
endDate: moment(new Date()).startOf("month").format("YYYY-MM"),
current: 1,
columns: columns.map(item => {
if (item.dataIndex == "cz") {
item.render = () =>
<div>
<a style={{ marginRight: "10px" }}>核算</a>
<a style={{ marginRight: "10px" }}>归档</a>
<a
style={{ marginRight: "10px" }}
onClick={() =>
window.open(
"/spa/hrmSalary/static/index.html#/main/hrmSalary/placeOnFileDetail"
)}>
查看
</a>
<a>删除</a>
</div>;
}
})
current: 1
};
this.pageInfo = { current: 1, pageSize: 10 };
}
@ -60,16 +42,17 @@ export default class Calculate extends React.Component {
}
// 搜索
handleSearch(value) {
handleSearch = (value, extra = {}) => {
const { calculateStore } = this.props;
const { getSalaryAcctList } = calculateStore;
getSalaryAcctList({
name: value,
startMonthStr: this.state.startDate,
endMonthStr: this.state.endDate,
current: this.state.current
current: this.state.current,
...extra
});
}
};
handleRangePickerChange(type, value) {
const { calculateStore: { getSalaryAcctList } } = this.props;
@ -141,6 +124,12 @@ export default class Calculate extends React.Component {
message.success("归档成功");
this.handleSearch(this.state.searchValue);
});
}).catch(() => {
clearInterval(this.timer);
this.setState({
progressVisible: false,
progress: 0
});
});
}
@ -152,6 +141,20 @@ export default class Calculate extends React.Component {
});
}
// 回算
handleBackCalculate = (record) => {
Modal.confirm({
title: "信息确认",
content: "确定回算吗?\n 回算后,正常核算的数据会被覆盖,正常核算的工资单不能继续发放或撤回!",
onOk: () => {
const { calculateStore: { backCalculate } } = this.props;
backCalculate(record.id).then(() => {
this.handleSearch(this.state.searchValue);
});
}
});
};
// 查看详情回调
handleDetail(record) {
window.open(
@ -161,23 +164,33 @@ export default class Calculate extends React.Component {
}
// 获取列表
getColumns() {
getColumns = () => {
const {
calculateStore: { salaryListColumns },
taxAgentStore: { showOperateBtn }
} = this.props;
let columns = [...salaryListColumns];
let columns = [...salaryListColumns].filter(item => item.dataIndex !== "backCalcStatus" && item.dataIndex !== "acctTimes");
columns.map(item => {
if (item.title == "操作" && showOperateBtn) {
if (item.dataIndex === "salarySobName") {
item.width = 300;
item.render = (text, record) => {
const accountBtn = _.filter(
record.operate,
it => it.text == "核算" || it.text == "重新核算"
);
const notAccountBtn = _.filter(
record.operate,
it => it.text != "核算" && it.text != "重新核算"
);
return <div className="salarySobNameWrapper">
<span>{text}</span>
<div className="salarySobNameTagWrapper">
{
record.backCalcStatus === 1 &&
<i className="icon-coms-Refresh" title="回算"/>
}
<Tag color="blue">{`${record.acctTimes}`}</Tag>
</div>
</div>;
};
}
if (item.dataIndex === "operate" && showOperateBtn) {
item.width = 150;
item.render = (text, record) => {
const accountBtn = _.take(record.operate, 2);
const notAccountBtn = _.drop(record.operate, 2);
let operateBtn = [];
if (!_.isEmpty(accountBtn)) {
operateBtn.push(
@ -189,13 +202,8 @@ export default class Calculate extends React.Component {
style={{ display: "inline-block", marginRight: 8 }}>
<a
href="javascript:void(0);"
onClick={() => {
if (it.text == "核算" || it.text == "重新核算") {
it.text == "核算"
? this.handleAccount(record)
: this.handleReaccount(record);
}
}}>
style={(idx === 1 && it.text.length === 2) ? { padding: "0 12px" } : {}}
onClick={() => this.handleOperateClick(it.index, record)}>
{it.text}
</a>
</div>
@ -211,29 +219,14 @@ export default class Calculate extends React.Component {
{notAccountBtn.map(cz =>
<Menu.Item>
<a
onClick={() => {
if (cz.text == "核算") {
this.handleAccount(record);
} else if (cz.text == "删除") {
this.handleDeleteItem(record);
} else if (cz.text == "归档") {
this.handleFile(record);
} else if (cz.text == "重新核算") {
this.handleReaccount(record);
} else if (cz.text == "查看") {
this.handleDetail(record);
}
}}>
onClick={() => this.handleOperateClick(cz.index, record)}>
{cz.text}
</a>
</Menu.Item>
)}
</Menu>
}>
<i
className="icon-coms-more"
style={{ color: "#4d7ad8", cursor: "pointer" }}
/>
<a href="javascript:void(0);"><i className="icon-coms-more"/></a>
</Dropdown>
);
}
@ -241,8 +234,24 @@ export default class Calculate extends React.Component {
};
}
});
return showOperateBtn ? columns : _.filter(columns, it => it.title != "操作");
}
return showOperateBtn ? columns : _.filter(columns, it => it.title !== "操作");
};
handleOperateClick = (index, record) => {
if (index === "0") {
this.handleAccount(record);
} else if (index === "1") {
this.handleDeleteItem(record);
} else if (index === "2") {
this.handleFile(record);
} else if (index === "4") {
this.handleReaccount(record);
} else if (index === "3") {
this.handleDetail(record);
} else if (index === "5") {
this.handleBackCalculate(record);
}
};
// 分页
handleDataPageChange(value) {
@ -271,56 +280,13 @@ export default class Calculate extends React.Component {
render() {
const { calculateStore, taxAgentStore: { showOperateBtn } } = this.props;
const {
salaryListDataSource,
salaryListColumns,
loading,
hasRight,
form,
condition,
tableStore,
showSearchAd,
getTableDatas,
doSearch,
setShowSearchAd,
salaryListPageInfo
} = calculateStore;
const { salaryListDataSource, loading, hasRight, salaryListPageInfo } = calculateStore;
const { modalParam } = this.state;
if (!hasRight && !loading) {
// 无权限处理
return renderNoright();
}
const rightMenu = [
// 右键菜单
{
key: "BTN_COLUMN",
icon: <i className="icon-coms-Custom"/>,
content: "显示列定制",
onClick: this.showColumn
}
];
const collectParams = {
// 收藏功能配置
favname: "薪资核算",
favouritetype: 1,
objid: 0,
link: "wui/index.html#/ns_demo03/index",
importantlevel: 1
};
const adBtn = [
// 高级搜索内部按钮
<Button type="primary" onClick={doSearch}>
搜索
</Button>,
<Button type="ghost" onClick={() => form.resetForm()}>
重置
</Button>,
<Button type="ghost" onClick={() => setShowSearchAd(false)}>
取消
</Button>
];
const renderRightOperation = () => {
const { startDate, endDate } = this.state;
return (
@ -363,7 +329,7 @@ export default class Calculate extends React.Component {
this.setState({ searchValue: value });
}}
onSearch={value => {
this.handleSearch(value);
this.handleSearch(value, { current: 1 });
}}
/>
</div>
@ -372,60 +338,53 @@ export default class Calculate extends React.Component {
return (
<div className="mySalaryBenefitsWrapper">
<WeaRightMenu
datas={rightMenu} // 右键菜单
collectParams={collectParams}>
{/* 收藏功能: 配置之后显示 收藏、帮助、显示页面地址 这3个功能 */}
<WeaTop
title="薪资核算" // 文字
icon={<i className="icon-coms-fa"/>} // 左侧图标
iconBgcolor="#F14A2D" // 左侧图标背景色
showDropIcon={false} // 是否显示下拉按钮
dropMenuDatas={rightMenu} // 下拉菜单(和页面的右键菜单相同)
dropMenuProps={{ collectParams }}>
{/* 收藏功能: 配置之后显示 收藏、帮助、显示页面地址 这3个功能 */}
<CustomTab
searchOperationItem={renderRightOperation()}
onChange={v => {
}}
/>
<CustomPaginationTable
loading={loading}
columns={this.getColumns()}
dataSource={salaryListDataSource}
total={salaryListPageInfo.total}
current={salaryListPageInfo.pageNum}
pageSize={this.pageInfo.pageSize}
onPageChange={value => {
this.handleDataPageChange(value);
}}
onShowSizeChange={(current, pageSize) => {
this.pageInfo = { current, pageSize };
this.handleShowSizeChange(this.pageInfo);
}}
/>
</WeaTop>
{/*归档进度条*/}
{
this.state.progressVisible &&
<ProgressModal
title="正在归档请稍后"
visible={this.state.progressVisible}
onCancel={() => {
this.setState({ progressVisible: false, progress: 0 });
}}
progress={this.state.progress}
/>
}
{this.state.baseFormVisible &&
<BaseFormModal
visible={this.state.baseFormVisible}
onRefresh={() => this.handleSearch(this.state.searchValue)}
onCancel={() => {
this.setState({ baseFormVisible: false });
}}
/>}
</WeaRightMenu>
{/* 收藏功能: 配置之后显示 收藏、帮助、显示页面地址 这3个功能 */}
<WeaTop
title="薪资核算"
icon={<i className="icon-coms-fa"/>}
iconBgcolor="#F14A2D"
showDropIcon={false}>
<CustomTab searchOperationItem={renderRightOperation()}/>
<div className="tableWrapper">
<WeaNewScroll height="100%">
<CustomPaginationTable
loading={loading}
columns={this.getColumns()}
dataSource={salaryListDataSource}
total={salaryListPageInfo.total}
current={salaryListPageInfo.pageNum}
pageSize={this.pageInfo.pageSize}
onPageChange={value => {
this.handleDataPageChange(value);
}}
onShowSizeChange={(current, pageSize) => {
this.pageInfo = { current, pageSize };
this.handleShowSizeChange(this.pageInfo);
}}
/>
</WeaNewScroll>
</div>
</WeaTop>
{/*归档进度条*/}
{
this.state.progressVisible &&
<ProgressModal
title="正在归档请稍后"
visible={this.state.progressVisible}
onCancel={() => {
this.setState({ progressVisible: false, progress: 0 });
}}
progress={this.state.progress}
/>
}
{this.state.baseFormVisible &&
<BaseFormModal
visible={this.state.baseFormVisible}
onRefresh={() => this.handleSearch(this.state.searchValue)}
onCancel={() => {
this.setState({ baseFormVisible: false });
}}
/>}
</div>
);
}

View File

@ -1,11 +1,19 @@
.dataList-wrapper {
.ant-modal-body{
.ant-modal-body {
padding: 16px 120px
}
.formItem {
display: flex;
.ant-col-8 {
line-height: 30px;
}
.wea-select, .ant-select {
width: 100%;
}
.ant-select-selection {
width: 100%;
height: 30px;
@ -13,3 +21,25 @@
}
}
}
.salarySobNameWrapper {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
& > span {
flex: 1;
}
.salarySobNameTagWrapper {
display: flex;
align-items: center;
i {
color: #5d9cec;
margin-right: 10px;
cursor: pointer;
}
}
}

View File

@ -4,6 +4,8 @@ import { Badge, Button, message } from "antd";
import { inject, observer } from "mobx-react";
import SelectFieldModal from "./selectFieldModal";
import { getQueryString } from "../../../../util/url";
import AddHeaderFieldsModal from "./addHeaderFieldsModal";
import { cacheImportField } from "../../../../apis/calculate";
@inject("calculateStore", "standingBookStore")
@observer
@ -16,18 +18,17 @@ export default class AcctResultImportModal extends React.Component {
salaryItemIds: ""
},
step: 0,
selectFieldVisible: false
selectFieldVisible: false,
addHeadFields: {
visible: false, itemsByGroup: []
}
};
}
componentWillMount() {
const { id } = this.props;
if (id) {
let modalParam = { ...this.state.modalParam };
modalParam.salaryAcctRecordId = id;
this.setState({
modalParam
});
this.getImportField();
} else {
this.setState({
modalParam: { ...this.state.modalParam, salaryAcctRecordId: "123" }
@ -35,9 +36,35 @@ export default class AcctResultImportModal extends React.Component {
}
}
getImportField = () => {
const { calculateStore: { getImportField }, id } = this.props;
const { addHeadFields } = this.props;
getImportField(id).then(data => {
this.setState({
addHeadFields: {
...addHeadFields,
itemsByGroup: _.map(data.itemsByGroup, item => {
return {
...item,
salaryItems: _.map(item.salaryItems, it => ({
...it,
checked: false
}))
};
})
},
modalParam: {
...this.state.modalParam,
salaryAcctRecordId: id,
salaryItemIds: data.checkItems.join(",")
}
});
});
};
// 获取模板
handleAccResultTemplateLink() {
const { isStandingBook, standingBookTabKey } = this.props;
const { isStandingBook, standingBookTabKey, standingBookType } = this.props;
let url = "";
if (_.isEmpty(this.state.modalParam.salaryItemIds)) {
message.warning("请选择表单字段");
@ -52,6 +79,8 @@ export default class AcctResultImportModal extends React.Component {
url = `${window.location.origin}/api/bs/hrmsalary/siaccount/welfare/importtemplate/export?welfareNames=${this.state.modalParam.salaryItemIds}&billMonth=${billMonth}&paymentOrganization=${paymentOrganization}`;
} else if (standingBookTabKey === "3") {
url = `${window.location.origin}/api/bs/hrmsalary/siaccount/welfare/supplyimporttemplate/export?welfareNames=${this.state.modalParam.salaryItemIds}&billMonth=${billMonth}&paymentOrganization=${paymentOrganization}`;
} else if (standingBookType === "difference") {
url = `${window.location.origin}/api/bs/hrmsalary/siaccount/welfare/balanceimporttemplate/export?welfareNames=${this.state.modalParam.salaryItemIds}&billMonth=${billMonth}&paymentOrganization=${paymentOrganization}`;
}
}
window.open(url, "_self");
@ -82,24 +111,31 @@ export default class AcctResultImportModal extends React.Component {
}
// 渲染第一步表单
renderFormComponent() {
renderFormComponent = () => {
return <Badge
count={!_.isEmpty(this.state.modalParam.salaryItemIds) ? this.state.modalParam.salaryItemIds.split(",").length : 0}>
<Button onClick={() => {
this.handleSelectedField();
}}>请选择表单字段</Button>
<Button onClick={this.handleSelectedField}>请选择表单字段</Button>
</Badge>;
}
};
// 选择表单字段
handleSelectedField() {
this.setState({
selectFieldVisible: true
});
}
handleSelectedField = () => {
if (window.location.hash.indexOf("calculateDetail") !== -1) {
this.setState({
addHeadFields: {
...this.state.addHeadFields,
visible: true
}
});
} else {
this.setState({
selectFieldVisible: true
});
}
};
// 添加表头字段
handleAdd(fieldDate) {
handleAdd = (fieldDate) => {
let salaryItemIdsList = [];
if (!_.isEmpty(fieldDate.formulaItems)) {
fieldDate.formulaItems.map(item => {
@ -133,7 +169,7 @@ export default class AcctResultImportModal extends React.Component {
modalParam
});
this.props.onAdd(fieldDate);
}
};
// 初始化Import数据
handleImportModalInit() {
@ -162,8 +198,10 @@ export default class AcctResultImportModal extends React.Component {
}
render() {
const billMonth = getQueryString("billMonth");
//isStandingBook: 是否是社保福利台账核算的导入标识
const { calculateStore, standingBookStore, isStandingBook, visiable } = this.props;
//standingBookType: 是否是补差的导入标识
const { calculateStore, standingBookStore, isStandingBook, visiable, standingBookType } = this.props;
const {
fetchPreviewAcctResult,
previewAcctResultColumns,
@ -176,14 +214,16 @@ export default class AcctResultImportModal extends React.Component {
previewStandingBookAcctResultColumns,
previewStandingBookAcctResultDataSource,
importStandingBookAcctResult,
importInsuranceAcctDetail
importInsuranceAcctDetail,
importBalanceInsuranceDetail
} = standingBookStore;
const { step, selectFieldVisible, modalParam } = this.state;
const { step, modalParam, selectFieldVisible, addHeadFields } = this.state;
return (
<div>
{
visiable && <ImportModal
isStandingBook={isStandingBook}
standingBookType={standingBookType}
init={() => {
this.handleImportModalInit();
}}
@ -200,7 +240,11 @@ export default class AcctResultImportModal extends React.Component {
!isStandingBook ? fetchPreviewAcctResult(params) : welfarePreview(params);
}}
importFile={(params) => {
!isStandingBook ? fetchImportAcctResult(params) : importInsuranceAcctDetail(params);
!isStandingBook ?
fetchImportAcctResult(params) :
standingBookType === "difference" ?
importBalanceInsuranceDetail({ ...params, billMonth }) :
importInsuranceAcctDetail(params);
}}
templateLink={() => {
this.handleAccResultTemplateLink();
@ -215,6 +259,7 @@ export default class AcctResultImportModal extends React.Component {
{
selectFieldVisible && <SelectFieldModal
isStandingBook={isStandingBook}
standingBookType={standingBookType}
id={this.props.id}
visible={selectFieldVisible}
fieldData={this.props.fieldData}
@ -228,6 +273,24 @@ export default class AcctResultImportModal extends React.Component {
}}
/>
}
<AddHeaderFieldsModal {...addHeadFields} selectItems={modalParam.salaryItemIds}
onCancel={() => this.setState({ addHeadFields: { ...addHeadFields, visible: false } })}
onAdd={(salaryItemIds) => this.setState({
addHeadFields: {
...addHeadFields,
visible: false
},
modalParam: {
...modalParam,
salaryItemIds: salaryItemIds.join(",")
}
}, () => {
const { salaryItemIds } = this.state.modalParam;
cacheImportField({
salaryItems: salaryItemIds ? salaryItemIds.split(",") : []
}).then();
})}
/>
</div>
);
}

View File

@ -0,0 +1,105 @@
/*
* Author: 黎永顺
* name: 表头字段添加
* Description:
* Date: 2023/5/17
*/
import React, { Component } from "react";
import { Button, Col, Row } from "antd";
import { WeaCheckbox, WeaDialog, WeaLocaleProvider, WeaSearchGroup } from "ecCom";
import "./index.less";
const { getLabel } = WeaLocaleProvider;
class AddHeaderFieldsModal extends Component {
constructor(props) {
super(props);
this.state = {
itemsCheckeds: [],
showOnlyChecked: false
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) {
this.setState({
itemsCheckeds: nextProps.selectItems ? _.map(nextProps.selectItems.split(","), it => Number(it)) : []
});
}
}
handleShowOnlyChecked = (showOnlyChecked) => this.setState({ showOnlyChecked: !!Number(showOnlyChecked) });
handleSelectGroupAll = (groupId, checked) => {
const { itemsCheckeds } = this.state;
const { itemsByGroup } = this.props;
_.map(itemsByGroup, item => {
if (item.salarySobItemGroupId === groupId) {
if (!!Number(checked)) {
this.setState({
itemsCheckeds: [...itemsCheckeds, ..._.map(item.salaryItems, child => child.salaryItemId)]
});
} else {
this.setState({
itemsCheckeds: _.differenceWith(itemsCheckeds, _.map(item.salaryItems, child => child.salaryItemId), _.isEqual)
});
}
}
});
};
render() {
const { showOnlyChecked, itemsCheckeds } = this.state;
const { itemsByGroup } = this.props;
let dataSource = _.map(itemsByGroup, item => {
return {
...item,
salaryItems: _.map(item.salaryItems, child => {
return { ...child, checked: itemsCheckeds.includes(child.salaryItemId) };
})
};
});
if (showOnlyChecked) {
dataSource = _.map(dataSource, item => {
return { ...item, salaryItems: _.filter(item.salaryItems, it => !!it.checked) };
});
}
return (
<WeaDialog
{...this.props} hasScroll initLoadCss
scalable title={getLabel(111, "添加表头字段")}
style={{ width: 700, height: 484 }} className="addHeaderFieldsWrapper"
buttons={[
<Button type="primary" onClick={() => this.props.onAdd(itemsCheckeds)}>{getLabel(111, "添加")}</Button>,
<Button type="ghost" onClick={this.props.onCancel}>{getLabel(111, "取消")}</Button>
]}
bottomLeft={<WeaCheckbox content={getLabel(111, "只显示已选中字段")}
onChange={this.handleShowOnlyChecked}/>}
>
{
_.map(dataSource, item => {
const { salarySobItemGroupName, salaryItems, salarySobItemGroupId } = item;
const value = _.every(salaryItems, it => !!it.checked) ? "1" : "0";
return <WeaSearchGroup showGroup needTigger
title={<WeaCheckbox content={salarySobItemGroupName} value={value}
onChange={(val) => this.handleSelectGroupAll(salarySobItemGroupId, val)}/>}>
<Row gutter={16}>
{
!_.isEmpty(salaryItems) ?
_.map(salaryItems, it => {
const { salaryItemId, salaryItemName, checked } = it;
return <Col span={8} style={{ marginBottom: 16 }}>
<WeaCheckbox content={salaryItemName} value={checked ? "1" : "0"}
onChange={() => this.setState({ itemsCheckeds: _.xorWith(itemsCheckeds, [salaryItemId], _.isEqual) })}/>
</Col>;
}) : <Col span={24} style={{ minHeight: 20, padding: "5%", textAlign: "center" }}>暂无数据</Col>
}
</Row>
</WeaSearchGroup>;
})
}
</WeaDialog>
);
}
}
export default AddHeaderFieldsModal;

View File

@ -0,0 +1,11 @@
.addHeaderFieldsWrapper {
.wea-search-group {
.wea-title {
padding-left: 0 !important;
}
.wea-content {
padding: 8px 16px 0;
}
}
}

View File

@ -2,6 +2,7 @@ import React from "react";
import { Button, Col, Row } from "antd";
import { inject, observer } from "mobx-react";
import { WeaCheckbox, WeaDialog } from "ecCom";
import { cacheImportField } from "../../../../apis/calculate";
@inject("calculateStore", "standingBookStore")
@observer
@ -14,7 +15,11 @@ export default class SelectFieldModal extends React.Component {
}
componentWillMount() {
const { calculateStore: { getImportField }, standingBookStore: { getWelfareList }, isStandingBook } = this.props;
const {
calculateStore: { getImportField },
standingBookStore: { getWelfareList, getBalanceWelfareList },
isStandingBook, standingBookType
} = this.props;
if (!isStandingBook) {
getImportField(this.props.id).then(data => {
let fieldData = {};
@ -33,17 +38,30 @@ export default class SelectFieldModal extends React.Component {
if (this.props.fieldData.inputItems) {
sqlItems = this.props.fieldData.sqlItems;
}
fieldData.formulaItems = formulaItems;
fieldData.inputItems = inputItems;
fieldData.sqlItems = sqlItems;
this.setState({
fieldData
fieldData.formulaItems = _.map(formulaItems, item => {
if (data.checkItems.includes(item.salaryItemId)) {
return { ...item, checked: true };
}
return { ...item };
});
fieldData.inputItems = _.map(inputItems, item => {
if (data.checkItems.includes(item.salaryItemId)) {
return { ...item, checked: true };
}
return { ...item };
});
fieldData.sqlItems = _.map(sqlItems, item => {
if (data.checkItems.includes(item.salaryItemId)) {
return { ...item, checked: true };
}
return { ...item };
});
this.setState({ fieldData });
this.fieldData = fieldData;
});
} else {
getWelfareList().then(result => {
const APIFox = standingBookType === "difference" ? getBalanceWelfareList : getWelfareList;
APIFox().then(result => {
let fieldData = {};
let formulaItems = [];
formulaItems = _.map(result, it => ({ ...it, salaryItemId: it.salaryItemName }));
@ -90,10 +108,19 @@ export default class SelectFieldModal extends React.Component {
}
// 添加按钮点击回调
handleAddClick() {
handleAddClick = async () => {
//薪资核算详情页面的导入表单字段缓存功能
if (window.location.hash.indexOf("calculateDetail") !== -1) {
const { status } = await this.cacheImportField();
}
this.props.onAdd(this.fieldData);
this.props.onCancel();
}
};
cacheImportField = () => {
const salaryItemList = _.reduce(_.keys(this.fieldData), (pre, cur) => ([...pre, ...this.fieldData[cur]]), []);
const salaryItems = _.map(_.filter(salaryItemList, it => !!it.checked), item => item.salaryItemId);
return cacheImportField({ salaryItems });
};
// 标题checkbox点击
handleTitleCheckboxChange(value, flag) {
@ -146,22 +173,20 @@ export default class SelectFieldModal extends React.Component {
const { isStandingBook } = this.props;
return (
<WeaDialog
title='添加表头字段'
title="添加表头字段"
visible={this.props.visible}
style={{width:800}}
style={{ width: 800 }}
onCancel={() => {
this.props.onCancel();
}}
buttons={[
<Button type="primary" onClick={() => {
this.handleAddClick();
}}>添加</Button>
<Button type="primary" onClick={this.handleAddClick}>添加</Button>
]}
>
<div style={{ minHeight: "20vh", maxHeight: "50vh", overflow: "hidden auto", padding: "16px 20px" }}>
{
!_.isEmpty(fieldData.formulaItems) &&
<div >
<div>
<div style={{ height: "40px", lineHeight: "40px" }}>
<WeaCheckbox content={!isStandingBook ? "公式项" : "全选"} onChange={(value) => {
this.handleTitleCheckboxChange(value, "formula");

View File

@ -6,8 +6,10 @@ import CustomTab from "../../components/customTab";
import { inject, observer } from "mobx-react";
import CompareDetailImportModal from "./compareDetailImportModal";
import CustomPaginationTable from "../../components/customPaginationTable";
import { salaryacctAcctresultCheckAuth } from "../../apis/calculate";
import Authority from "../mySalary/authority";
@inject("calculateStore")
@inject("calculateStore", "taxAgentStore")
@observer
export default class CompareDetail extends React.Component {
constructor(props) {
@ -17,15 +19,14 @@ export default class CompareDetail extends React.Component {
onlyDiffEmployee: true,
onlyDiffSalaryItem: true,
importModalVisible: false,
searchValue: ""
searchValue: "",
calculateAuth: false
};
this.pageInfo = { current: 1, pageSize: 10 };
}
componentWillMount() {
let id = getQueryString("id");
this.id = id;
this.id = getQueryString("id");
const { calculateStore: { fetchComparisonResultList } } = this.props;
const { onlyDiffEmployee, onlyDiffSalaryItem } = this.state;
let params = {
@ -35,27 +36,50 @@ export default class CompareDetail extends React.Component {
current: 1
};
fetchComparisonResultList(params);
this.salaryacctAcctresultCheckAuth({ salaryAcctRecordId: getQueryString("id") })
}
getColumns(columns) {
salaryacctAcctresultCheckAuth = (params) => {
const { taxAgentStore: { getPermission } } = this.props;
getPermission().then(({ data }) => {
const { isOpenDevolution } = data;
if (isOpenDevolution) {
salaryacctAcctresultCheckAuth(params).then(({ status, data }) => {
this.setState({ calculateAuth: data && status });
});
} else {
this.setState({ calculateAuth: true });
}
});
};
getColumns = (columns) => {
let newColumns = [...columns];
newColumns.map(item => {
let n = Number(item.dataIndex);
if (!isNaN(n)) { // 数字
item.render = (text, record) => {
const showDifference = record[`${item.dataIndex}_type`] === "number";
const { acctResultValue, excelResultValue } = record[item.dataIndex];
return (
<div>
<div>系统值{record[item.dataIndex].acctResultValue}</div>
<div>线下值{record[item.dataIndex].excelResultValue}</div>
<div
style={{ color: "red" }}>差值{calculateCompares(record[item.dataIndex].acctResultValue, record[item.dataIndex].excelResultValue)}</div>
<div>系统值{acctResultValue}</div>
<div>线下值{excelResultValue}</div>
{
showDifference &&
<div style={{ color: "red" }}>
差值{calculateCompares(acctResultValue, excelResultValue)}
</div>
}
</div>
);
};
} else {
item.fixed = "left";
}
});
return newColumns;
}
};
// 导入
handleImportClick() {
@ -163,7 +187,7 @@ export default class CompareDetail extends React.Component {
comparisonResultColumns
}
} = this.props;
const { importModalVisible, searchValue } = this.state;
const { importModalVisible, searchValue, calculateAuth } = this.state;
const renderRightOperation = () => {
return (
<div style={{ display: "inline-block" }}>
@ -197,70 +221,70 @@ export default class CompareDetail extends React.Component {
);
};
return (
<div className="compareDetail">
<CustomTab
searchOperationItem={
renderRightOperation()
}
leftOperation={
renderLeftOperation()
}
/>
<div className="titleBarWrapper">
<div className="titleBar">
<span className="leftTitle">公式=</span>
<span className="rightTitle">系统值线下值<span style={{ color: "red" }}>差值</span></span>
<Authority ecId={`${this && this.props && this.props.ecId || ""}_Authority@lulowc`}
store={{ loading: false, hasRight: calculateAuth }}>
<div className="compareDetail">
<CustomTab
searchOperationItem={
renderRightOperation()
}
leftOperation={
renderLeftOperation()
}
/>
<div className="titleBarWrapper">
<div className="titleBar">
<span className="leftTitle">公式=</span>
<span className="rightTitle">系统值线下值<span style={{ color: "red" }}>差值</span></span>
</div>
</div>
</div>
<div className="tableWrapper">
<CustomPaginationTable
loading={loading}
dataSource={comparisonResultPageInfo.list ? comparisonResultPageInfo.list : []}
columns={this.getColumns(comparisonResultColumns ? comparisonResultColumns : [])}
scroll={{ x: this.getColumns(comparisonResultColumns ? comparisonResultColumns : []).length * 150, y: `calc(100vh - 199px)` }}
total={comparisonResultPageInfo.total}
current={comparisonResultPageInfo.pageNum}
pageSize={this.pageInfo.pageSize}
onPageChange={(value) => {
this.pageInfo.current = value;
this.handleDataPageChange(value);
}}
onShowSizeChange={(current, pageSize) => {
this.pageInfo = { current, pageSize };
this.handleShowSizeChange(this.pageInfo);
}}
/>
</div>
<div className="tableWrapper">
<CustomPaginationTable
loading={loading}
dataSource={comparisonResultPageInfo.list ? comparisonResultPageInfo.list : []}
columns={this.getColumns(comparisonResultColumns ? comparisonResultColumns : [])}
scroll={{
x: this.getColumns(comparisonResultColumns ? comparisonResultColumns : []).length * 150,
y: `calc(100vh - 199px)`
}}
total={comparisonResultPageInfo.total}
current={comparisonResultPageInfo.pageNum}
pageSize={this.pageInfo.pageSize}
onPageChange={(value) => {
this.pageInfo.current = value;
this.handleDataPageChange(value);
}}
onShowSizeChange={(current, pageSize) => {
this.pageInfo = { current, pageSize };
this.handleShowSizeChange(this.pageInfo);
}}
/>
</div>
{
importModalVisible && <CompareDetailImportModal
visiable={importModalVisible}
id={this.id}
onFinish={() => {
this.handleComparisonFinish();
}}
onCancel={() => {
this.setState({
importModalVisible: false
});
}}
/>
}
</div>
{
importModalVisible && <CompareDetailImportModal
visiable={importModalVisible}
id={this.id}
onFinish={() => {
this.handleComparisonFinish();
}}
onCancel={() => {
this.setState({
importModalVisible: false
});
}}
/>
}
</div>
</Authority>
);
}
}
// 计算差值
export const calculateCompares=(systemValue, excelValue)=> {
if (systemValue == null || excelValue == null) {
return "";
}
let systemNum = Number(systemValue);
let excelNum = Number(excelValue);
if (!isNaN(systemNum) || !isNaN(excelNum)) { // 数字
return (systemNum - excelNum).toFixed(2);
}
return "";
}
export const calculateCompares = (systemValue = 0, excelValue = 0) => {
const systemNum = Number(systemValue);
const excelNum = Number(excelValue);
return (systemNum - excelNum).toFixed(2);
};

View File

@ -1,7 +1,7 @@
import React from "react";
import ImportModal from "../../components/importModal";
import { inject, observer } from "mobx-react";
import { getQueryString } from "../../util/url";
import { convertToUrlString, getQueryString } from "../../util/url";
@inject("calculateStore", "standingBookStore")
@observer
@ -35,7 +35,12 @@ export default class CompareDetailImportModal extends React.Component {
if (this.props.id) {
url = "/api/bs/hrmsalary/salaryacct/comparisonresult/importtemplate/export?salaryAcctRecordId=" + this.props.id;
} else {
url = `/api/bs/hrmsalary/siaccount/comparisonwelfare/importtemplate/export`;
const payload = {
billMonth: getQueryString("billMonth"),
paymentOrganization: getQueryString("paymentOrganization"),
paymentStatus: 0
};
url = `/api/bs/hrmsalary/siaccount/comparisonwelfare/importtemplate/export?${convertToUrlString(payload)}`;
}
window.open(url);
}

View File

@ -1,41 +1,55 @@
import React from "react";
import { WeaHelpfulTip, WeaInput } from "ecCom";
import { Col, Row } from "antd";
import { WeaHelpfulTip, WeaTab } from "ecCom";
import IssuedAndReissueTable from "./issuedAndReissueTable";
import PayrollItemsTable from "./payrollItemsTable";
import { inject, observer } from "mobx-react";
import cs from "classnames";
import { toJS } from "mobx";
import "./index.less";
@inject("calculateStore")
@observer
export default class EditSalaryDetail extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedKey: "0"
};
}
componentWillMount() {
const { calculateStore: { acctresultDetail } } = this.props;
acctresultDetail(this.props.id);
}
handleItemValueChange(field, value, isInput) {
handleItemValueChange = (field, value, isInput, groupId) => {
const { calculateStore: { acctresultDetailForm, setAcctresultDetailForm } } = this.props;
let form = { ...acctresultDetailForm };
if (isInput) {
form.inputItems = acctresultDetailForm.inputItems.map(item => {
item = { ...item };
if (item.salaryItemName == field) {
item.resultValue = value;
if (isInput === "itemsByGroup") {
form.itemsByGroup = acctresultDetailForm.itemsByGroup.map(item => {
if (item.salarySobItemGroupId === groupId) {
return {
...item,
salaryItems: _.map(item.salaryItems, it => {
if (it.salaryItemId === field) {
return { ...it, resultValue: value };
}
return { ...it };
})
};
}
return item;
return { ...item };
});
} else {
form.formulaItems = acctresultDetailForm.formulaItems.map(item => {
} else if (isInput === "issuedAndReissueItems") {
form.issuedAndReissueItems = acctresultDetailForm.issuedAndReissueItems.map(item => {
item = { ...item };
if (item.salaryItemName == field) {
if (item.salaryItemName === field) {
item.resultValue = value;
}
return item;
});
}
setAcctresultDetailForm(form);
}
};
renderTableTr = (data, isInput) => {
const tables = [];
const len = data.length;
@ -59,22 +73,27 @@ export default class EditSalaryDetail extends React.Component {
return tables;
};
render() {
const { calculateStore: { acctresultDetailForm } } = this.props;
const { selectedKey } = this.state;
const { itemsByGroup = [] } = toJS(acctresultDetailForm);
const topTab = [
{
title: "正常工资薪金所得",
viewcondition: "0"
},
{
title: "已发补发",
viewcondition: "1"
}
];
return (
<div className="editSalaryDetail">
<div className="detailItemWrapper">
<div>
<span className="itemTitle">基本信息</span>
<WeaHelpfulTip
style={{ marginLeft: "10px" }}
width={200}
title="根据账套设置显示"
placement="topLeft"
/>
<WeaHelpfulTip style={{ marginLeft: "10px" }} title="提示:基本信息根据账套设置显示" placement="topLeft"/>
</div>
<div className="itemContent">
{
!_.isEmpty(acctresultDetailForm.employeeInfos) &&
@ -84,73 +103,27 @@ export default class EditSalaryDetail extends React.Component {
}
</div>
</div>
<div>
<div className="detailItemWrapper">
<span className="itemTitle">输入项</span>
<div className="itemContent">
<Row>
{
acctresultDetailForm.inputItems && acctresultDetailForm.inputItems.map((item, index) => {
const len = acctresultDetailForm.inputItems.length;
return (
<Col span={8}>
<Row>
<Col span={12}
className={cs("itemLabel", { "borderB-none": Math.ceil((index + 1) / 3) === len / 3 })}>{item.salaryItemName}</Col>
<Col span={12} className={cs("itemValue", {
"borderB-none": Math.ceil((index + 1) / 3) === len / 3,
"borderR-none": (index + 1) % 3 === 0
})}><WeaInput value={item.resultValue} disabled={!item.canEdit} onChange={(value) => {
this.handleItemValueChange(item.salaryItemName, value, true);
}}/></Col>
</Row>
</Col>
);
})
}
</Row>
</div>
</div>
</div>
<div>
<div className="detailItemWrapper">
<span className="itemTitle">
<span>公式项</span>
<WeaHelpfulTip
style={{ marginLeft: "10px" }}
width={200}
title="提示:修改后,若点击核算,将按照公式核算,覆盖修改的数据"
placement="topLeft"
/>
</span>
<div className="itemContent">
<Row>
{
acctresultDetailForm.formulaItems && acctresultDetailForm.formulaItems.map((item, index) => {
const len = acctresultDetailForm.formulaItems.length;
return (
<Col span={8}>
<Row>
<Col span={12}
className={cs("itemLabel", { "borderB-none": Math.ceil((index + 1) / 3) === len / 3 })}>{item.salaryItemName}</Col>
<Col span={12} className={cs("itemValue", {
"borderB-none": Math.ceil((index + 1) / 3) === len / 3,
"borderR-none": (index + 1) % 3 === 0
})}><WeaInput value={item.resultValue} disabled={!item.canEdit} onChange={(value) => {
this.handleItemValueChange(item.salaryItemName, value, false);
}}/></Col>
</Row>
</Col>
);
})
}
</Row>
</div>
</div>
</div>
{
!_.isEmpty(toJS(acctresultDetailForm.issuedAndReissueItems)) &&
<WeaTab
datas={topTab}
keyParam="viewcondition"
selectedKey={selectedKey}
onChange={v => this.setState({ selectedKey: v })}
/>
}
{
selectedKey === "0" && _.map(itemsByGroup, item => {
return <PayrollItemsTable {...item} onChangeIssueReissueValue={this.handleItemValueChange}/>;
})
}
{
selectedKey === "1" &&
<IssuedAndReissueTable
dataSource={toJS(acctresultDetailForm.issuedAndReissueItems)}
onChangeIssueReissueValue={this.handleItemValueChange}
/>
}
</div>
);
}

View File

@ -4,13 +4,16 @@ import { inject, observer } from "mobx-react";
import SalaryDetail from "./salaryDetail";
import { Button, Dropdown, Menu, message, Modal } from "antd";
import { WeaBrowser, WeaCheckbox, WeaDropdown, WeaFormItem, WeaInput, WeaSearchGroup, WeaSelect, WeaTab } from "ecCom";
import { getQueryString } from "../../util/url";
import { convertToUrlString, getQueryString } from "../../util/url";
import AcctResultImportModal from "./acctResult/importModal/acctResultImportModal";
import ProgressModal from "../../components/progressModal";
import { salaryacctAcctresultCheckAuth } from "../../apis/calculate";
import Authority from "../mySalary/authority";
const { ButtonSelect } = WeaDropdown;
@inject("calculateStore", "salaryFileStore")
@inject("calculateStore", "salaryFileStore", "taxAgentStore")
@observer
export default class CalculateDetail extends React.Component {
constructor(props) {
@ -19,10 +22,11 @@ export default class CalculateDetail extends React.Component {
showSearchAd: false,
searchItemsValue: {
employeeName: "",
workcode: "",
departmentIds: "",
positionIds: "",
subcompanyIds: "",
status: "",
statuses: "",
consolidatedTaxation: "0"
},
selectedKey: "0",
@ -30,37 +34,55 @@ export default class CalculateDetail extends React.Component {
acctResultImportVisiable: false,
progressVisible: false,
progress: 0,
accountIds: []
accountIds: [],
accountExceptInfo: "",
calculateAuth: false
};
this.id = "";
this.timer;
this.timer = null;
}
componentWillMount() {
async componentWillMount() {
let id = getQueryString("id");
this.id = id;
const { calculateStore: { checkTaxAgent }, salaryFileStore } = this.props;
const { commonEnumList } = salaryFileStore;
this.salaryacctAcctresultCheckAuth({ salaryAcctRecordId: id });
checkTaxAgent(this.id);
let modalParam = { ...this.state.modalParam, salaryAcctRecordId: id };
this.setState({ modalParam });
commonEnumList("user", { enumClass: "com.engine.salary.enums.salarysob.SalaryEmployeeStatusEnum" });
}
salaryacctAcctresultCheckAuth = (params) => {
const { taxAgentStore: { getPermission } } = this.props;
getPermission().then(({ data }) => {
const { isOpenDevolution } = data;
if (isOpenDevolution) {
salaryacctAcctresultCheckAuth(params).then(({ status, data }) => {
this.setState({ calculateAuth: data && status });
});
} else {
this.setState({ calculateAuth: true });
}
});
};
Input = (value, key) => {
const { employeeName } = this.state.searchItemsValue;
const { employeeName, workcode } = this.state.searchItemsValue;
return (
<WeaFormItem
label={value}
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
>
<WeaInput value={employeeName} onChange={(val) => this.setState({
searchItemsValue: {
...this.state.searchItemsValue,
[key]: val
}
})}/>
<WeaInput value={key === "employeeName" ? employeeName : workcode}
onChange={(val) => this.setState({
searchItemsValue: {
...this.state.searchItemsValue,
[key]: val
}
})}/>
</WeaFormItem>
);
};
@ -93,7 +115,7 @@ export default class CalculateDetail extends React.Component {
);
};
Select = (value, key) => {
const { status } = this.state.searchItemsValue;
const { statuses } = this.state.searchItemsValue;
return (
<WeaFormItem
label={value}
@ -101,10 +123,13 @@ export default class CalculateDetail extends React.Component {
wrapperCol={{ span: 18 }}
>
<WeaSelect
value={status}
multiple
value={statuses}
options={[
{ key: "", showname: "" }, { key: "ALL", showname: "全部" },
{ key: "NORMAL", showname: "在职" }, { key: "UNAVAILABLE", showname: "离职" }
{ key: "0", showname: "试用" }, { key: "1", showname: "正式" },
{ key: "2", showname: "临时" }, { key: "3", showname: "试用延期" },
{ key: "4", showname: "解雇" }, { key: "5", showname: "离职" },
{ key: "6", showname: "退休" }
]}
onChange={(val) => this.setState({ searchItemsValue: { ...this.state.searchItemsValue, [key]: val } })}/>
</WeaFormItem>
@ -160,7 +185,8 @@ export default class CalculateDetail extends React.Component {
this.timer = null;
this.setState({
progressVisible: false,
accountIds: []
accountIds: [],
accountExceptInfo: data.message
});
message.success("核算完成");
// acctResultList({ salaryAcctRecordId: this.id });
@ -172,7 +198,7 @@ export default class CalculateDetail extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/acctresult/list",
selectedRowKeys: [],
queryParams: {
salaryAcctRecordId,
salaryAcctRecordId
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
@ -181,7 +207,8 @@ export default class CalculateDetail extends React.Component {
this.timer = null;
this.setState({
progressVisible: false,
accountIds: []
accountIds: [],
accountExceptInfo: data.message
});
message.error(data.message);
}
@ -189,8 +216,6 @@ export default class CalculateDetail extends React.Component {
});
}, 1000);
});
},
onCancel() {
}
});
};
@ -208,8 +233,11 @@ export default class CalculateDetail extends React.Component {
this.id
);
} else if (e.key == "3") {
const { searchItemsValue } = this.state;
const { consolidatedTaxation, ...extra } = searchItemsValue;
const payload = { ...extra, consolidatedTaxation: consolidatedTaxation === "0" ? "" : consolidatedTaxation };
window.open(
"/api/bs/hrmsalary/salaryacct/acctresult/export?salaryAcctRecordId=" + this.id + "&ids="
`/api/bs/hrmsalary/salaryacct/acctresult/export?salaryAcctRecordId=${this.id}&ids=&${convertToUrlString(payload)}`
);
}
};
@ -246,8 +274,18 @@ export default class CalculateDetail extends React.Component {
}
}
downloadTxtfile = (value) => {
const element = document.createElement("a");
const file = new Blob([value], { type: "text/plain" });
element.href = URL.createObjectURL(file);
element.download = "核算异常信息.txt";
document.body.appendChild(element);
element.click();
};
render() {
const { selectedKey, acctResultImportVisiable, showSearchAd } = this.state;
const { selectedKey, acctResultImportVisiable, showSearchAd, calculateAuth } = this.state;
const { taxAgentStore: { payrollPermission } } = this.props;
const menu = (
<Menu onClick={this.handleMenuClick.bind(this)}>
<Menu.Item key="1">导入</Menu.Item>
@ -257,7 +295,8 @@ export default class CalculateDetail extends React.Component {
);
const renderRightOperation = () => {
return [
const { accountExceptInfo } = this.state;
let buttons = [
<ButtonSelect
datas={[
{ key: "ALL", show: "核算所有人", selected: true },
@ -270,6 +309,10 @@ export default class CalculateDetail extends React.Component {
更多
</Dropdown.Button>
];
accountExceptInfo && buttons.unshift(<Button type="ghost" shape="circle-outline" icon="download"
title="下载核算异常信息"
onClick={() => this.downloadTxtfile(accountExceptInfo)}/>);
return buttons;
};
const topTab = [
@ -295,9 +338,10 @@ export default class CalculateDetail extends React.Component {
<Button type="ghost" onClick={() => this.setState({
searchItemsValue: {
employeeName: "",
workcode: "",
departmentIds: "",
positionIds: "",
status: "",
statuses: "",
consolidatedTaxation: "0"
}
})}>
@ -311,66 +355,70 @@ export default class CalculateDetail extends React.Component {
const renderSearch = () => {
const searchItems = [
{ com: this.Input("姓名", "employeeName") },
{ com: this.Input("工号", "workcode") },
{ com: this.Browser("分部", "subcompanyIds") },
{ com: this.Browser("部门", "departmentIds") },
{ com: this.Browser("岗位", "positionIds") },
{ com: this.Select("状态", "status") },
{ com: this.Select("状态", "statuses") },
{ com: this.Checkbox("合并计税", "consolidatedTaxation") }
];
return <WeaSearchGroup title={"基本信息"} items={searchItems} showGroup/>;
};
return (
<div style={{ overflowY: "hidden", height: "100%" }}>
<WeaTab
datas={topTab}
selectedKey={selectedKey}
keyParam="viewcondition"
onChange={v => this.setState({ selectedKey: v })}
searchType={selectedKey == 1 ? ["base", "advanced"] : []} // base基础搜索框 advanced显示高级搜索按钮
showSearchAd={showSearchAd} // 是否展开高级搜索面板
setShowSearchAd={(bool) => this.setState({ showSearchAd: bool })} //高级搜索面板受控
searchsAd={renderSearch()} // 高级搜索内部数据getSearchs(form, toJS(condition), 2)
buttonsAd={adBtn} // 高级搜索内部按钮
onSearch={() => this.handleSearch(this.state.searchItemsValue)} // 点搜索按钮时的回调
buttons={selectedKey == 1 ? renderRightOperation() : []}
searchsBasePlaceHolder={"请输入姓名"}
onSearchChange={(v) =>
this.setState({
searchItemsValue: {
...this.state.searchItemsValue,
employeeName: v
}
})
} // 在搜索框中输入的文字改变时的回调: 这里需要同步高级搜索和外部搜索框的值form.updateFields({ username: v })
searchsBaseValue={this.state.searchItemsValue.employeeName} // 外部input搜索值受控: 这里和高级搜索的requestname同步form.getFormParams().username
/>
{selectedKey == 0 && <UserSure/>}
{selectedKey == 1 && <SalaryDetail onChangeAccountIds={(ids) => this.setState({ accountIds: ids })}
employeeName={this.state.searchValue}/>}
{acctResultImportVisiable &&
<AcctResultImportModal
visiable={acctResultImportVisiable}
fieldData={this.state.fieldData}
onAdd={fieldData => {
this.handleAcctModalAdd(fieldData);
}}
onCancel={() =>
<Authority ecId={`${this && this.props && this.props.ecId || ""}_Authority@lulowc`}
store={{ loading: false, hasRight: payrollPermission && calculateAuth }}>
<div style={{ overflowY: "hidden", height: "100%" }}>
<WeaTab
datas={topTab}
selectedKey={selectedKey}
keyParam="viewcondition"
onChange={v => this.setState({ selectedKey: v })}
searchType={selectedKey == 1 ? ["base", "advanced"] : []} // base基础搜索框 advanced显示高级搜索按钮
showSearchAd={showSearchAd} // 是否展开高级搜索面板
setShowSearchAd={(bool) => this.setState({ showSearchAd: bool })} //高级搜索面板受控
searchsAd={renderSearch()} // 高级搜索内部数据getSearchs(form, toJS(condition), 2)
buttonsAd={adBtn} // 高级搜索内部按钮
onSearch={() => this.handleSearch(this.state.searchItemsValue)} // 点搜索按钮时的回调
buttons={selectedKey == 1 ? renderRightOperation() : []}
searchsBasePlaceHolder={"请输入姓名"}
onSearchChange={(v) =>
this.setState({
acctResultImportVisiable: false,
fieldData: {}
})}
id={this.id}
/>}
{this.state.progressVisible &&
<ProgressModal
visible={this.state.progressVisible}
onCancel={() => {
this.setState({ progressVisible: false, progress: 0 });
}}
progress={this.state.progress}
/>}
</div>
searchItemsValue: {
...this.state.searchItemsValue,
employeeName: v
}
})
} // 在搜索框中输入的文字改变时的回调: 这里需要同步高级搜索和外部搜索框的值form.updateFields({ username: v })
searchsBaseValue={this.state.searchItemsValue.employeeName} // 外部input搜索值受控: 这里和高级搜索的requestname同步form.getFormParams().username
/>
{selectedKey == 0 && <UserSure/>}
{selectedKey == 1 && <SalaryDetail onChangeAccountIds={(ids) => this.setState({ accountIds: ids })}
employeeName={this.state.searchItemsValue}/>}
{acctResultImportVisiable &&
<AcctResultImportModal
visiable={acctResultImportVisiable}
fieldData={this.state.fieldData}
onAdd={fieldData => {
this.handleAcctModalAdd(fieldData);
}}
onCancel={() =>
this.setState({
acctResultImportVisiable: false,
fieldData: {}
})}
id={this.id}
/>}
{this.state.progressVisible &&
<ProgressModal
visible={this.state.progressVisible}
onCancel={() => {
this.setState({ progressVisible: false, progress: 0 });
}}
progress={this.state.progress}
/>}
</div>
</Authority>
);
}
}

View File

@ -80,8 +80,7 @@
}
.editSalaryDetail {
padding: 20px;
padding-bottom: 40px;
padding: 20px 20px 40px;
.detailItemWrapper {
.itemTitle {
@ -127,43 +126,15 @@
}
}
}
& > .ant-row {
border: 1px solid rgba(0, 0, 0, .06);
}
.itemLabel {
background-color: #fafafa;
padding: 12px 6px;
height: 45px;
display: flex;
align-items: center;
justify-content: flex-start;
border-right: 1px solid rgba(0, 0, 0, .06);
border-bottom: 1px solid rgba(0, 0, 0, .06);
}
.borderB-none {
border-bottom: none !important;
}
.borderR-none {
border-right: none !important;
}
.itemValue {
padding: 12px 6px;
display: flex;
align-items: center;
height: 45px;
border-right: 1px solid rgba(0, 0, 0, .06);
border-bottom: 1px solid rgba(0, 0, 0, .06);
}
}
}
.itemRow {
line-height: 40px;
.wea-search-group {
padding: 0 !important;
.wea-title {
padding: 0 !important;
}
}
}
@ -178,7 +149,9 @@
}
.tableWrapper {
margin-top: 10px;
padding: 10px;
height: calc(100vh - 121px);
overflow: hidden;
}
}
@ -252,7 +225,6 @@
z-index: 99;
top: 10px !important;
}
}
@media (min-width: 1260px) {

View File

@ -0,0 +1,68 @@
/*
* Author: 黎永顺
* name: 已发补发列表
* Description:
* Date: 2022/12/14
*/
import React, { Component } from "react";
import { WeaHelpfulTip, WeaInputNumber, WeaTable } from "ecCom";
class IssuedAndReissueTable extends Component {
render() {
const { dataSource, onChangeIssueReissueValue } = this.props;
const columns = [
{
dataIndex: "salaryItemName",
title: "薪资项目",
render: (text) => {
return <span className="tdEllipsis" title={text}>{text}</span>;
}
},
{
dataIndex: "resultValue",
title: <span>
<span style={{ marginRight: 8 }}>项目值</span>
<WeaHelpfulTip
title="若薪资项目有公式,手动编辑项目值后,需点击锁定图标输入值才生效;点击锁定图标,解锁手动编辑的项目值,公式生效,点击保存按照公式重新核算;重新核算后,不显示解锁图标。"
placement="bottom"
width={200}
/>
</span>,
render: (text, record) => {
const { canEdit } = record;
return <WeaInputNumber
disabled={!canEdit}
min={0}
precision={2}
value={text || 0}
onChange={(value) => onChangeIssueReissueValue(record.salaryItemName, value, "issuedAndReissueItems")}
/>;
}
},
{
dataIndex: "itemFormulaContent",
title: <span>
<span style={{ marginRight: 8 }}>核算公式</span>
<WeaHelpfulTip
title="若薪资项目有公式,且项目值手动编辑修改过并点击锁定图标,则公式失效;若解除锁定,则项目公式重新生效;"
placement="bottom"
width={200}
/>
</span>,
render: (text, record) => {
return <span className="tdEllipsis" title={text}>{_.isNil(text) ? "输入" : text}</span>;
}
}
];
return (
<WeaTable
rowKey="id"
dataSource={dataSource}
columns={columns}
pagination={false}
/>
);
}
}
export default IssuedAndReissueTable;

View File

@ -0,0 +1,82 @@
/*
* Author: 黎永顺
* name: 薪资项目表格
* Description:
* Date: 2023/5/16
*/
import React, { Component } from "react";
import { WeaHelpfulTip, WeaInput, WeaInputNumber, WeaLocaleProvider, WeaSearchGroup, WeaTable } from "ecCom";
const { getLabel } = WeaLocaleProvider;
class PayrollItemsTable extends Component {
render() {
const {
salarySobItemGroupId,
salarySobItemGroupName,
salaryItems: dataSource,
onChangeIssueReissueValue
} = this.props;
const columns = [
{
dataIndex: "salaryItemName",
title: getLabel(111, "薪资项目"),
width: "15%",
render: (text) => {
return <span className="tdEllipsis" title={text}>{text}</span>;
}
},
{
dataIndex: "resultValue",
title: <span>
<span style={{ marginRight: 8 }}>{getLabel(111, "项目值")}</span>
<WeaHelpfulTip
title={getLabel(111, "1.若薪资项目有公式,手动编辑项目值后,则默认将手动编辑的项目值锁定;点击锁定图标,解锁手动编辑的项目值,公式生效,点击保存按照公式重新核算;重新核算后,不显示解锁图标。")}
placement="top" width={250}
/>
</span>,
width: "20%",
render: (text, record) => {
const { canEdit, dataType } = record;
return dataType === "number" ? <WeaInputNumber
disabled={!canEdit}
precision={2}
value={text || 0}
onChange={(value) => onChangeIssueReissueValue(record.salaryItemId, value, "itemsByGroup", salarySobItemGroupId)}
/> : <WeaInput
disabled={!canEdit}
value={text}
onChange={(value) => onChangeIssueReissueValue(record.salaryItemId, value, "itemsByGroup", salarySobItemGroupId)}
/>;
}
},
{
dataIndex: "itemFormulaContent",
title: <span>
<span style={{ marginRight: 8 }}>{getLabel(111, "核算公式")}</span>
<WeaHelpfulTip
title={getLabel(111, "若薪资项目有公式,且项目值手动编辑修改过并点击锁定图标,则公式失效;若解除锁定,则项目公式重新生效;")}
placement="top" width={250}
/>
</span>,
width: "65%",
render: (text, record) => {
return <span className="tdEllipsis" title={text}>{_.isNil(text) ? "输入" : text}</span>;
}
}
];
return (
<WeaSearchGroup title={salarySobItemGroupName} showGroup needTigger>
<WeaTable
rowKey="salaryItemId"
dataSource={dataSource}
columns={columns}
bordered
pagination={false}
/>
</WeaSearchGroup>
);
}
}
export default PayrollItemsTable;

View File

@ -1,144 +1,119 @@
import React from "react";
import { toJS } from "mobx";
import CustomTab from "../../components/customTab";
import { Dropdown, Menu, message } from "antd";
import { WeaHelpfulTip, WeaInputSearch, WeaSlideModal } from "ecCom";
import { placeOnFileColumns } from "./columns";
import SlideModalTitle from "../../components/slideModalTitle";
import FileMergeDetail from "./fileMergeDetail";
import { getQueryString } from "../../util/url";
import { inject, observer } from "mobx-react";
import CustomPaginationTable from "../../components/customPaginationTable";
import { renderLoading } from "../../util";
import "./index.less";
@inject("calculateStore")
@observer
export default class PlaceOnFileDetail extends React.Component {
constructor(props) {
super(props);
placeOnFileColumns.map(item => {
if (item.dataIndex == "username") {
item.render = (text, record) => (
<a onClick={() => {
this.onDetail();
}}>{text}</a>
);
}
});
this.state = {
slideVisiable: false,
selectedRowKeys: [],
searchValue: ""
searchValue: "",
columnIndex: ""
};
this.id = "";
this.length = 0;
this.pageInfo = {
current: 1,
pageSize: 10
};
}
componentWillMount() {
let id = getQueryString("id");
this.id = id;
const { calculateStore: { getSalarySobCycle, acctResultList } } = this.props;
getSalarySobCycle(id);
acctResultList({ salaryAcctRecordId: id });
this.id = getQueryString("id");
const { calculateStore: { getSalarySobCycle } } = this.props;
getSalarySobCycle(this.id);
}
componentDidMount() {
window.addEventListener("message", this.handleClick, false);
}
// 获取列表的列
getColumns() {
const { calculateStore: { acctResultListTableStore, acctResultListColumns } } = this.props;
let columns = acctResultListColumns ? acctResultListColumns : [];
columns = columns.filter(item => item.hide == "FALSE").map(item => {
let result = { ...item };
result.title = item.text;
result.dataIndex = item.column;
result.oldWidth = result.width;
result.width = null;
this.length = 0;
if (result.children) {
result.children.map(child => {
child.width = 150;
child.title = child.text;
child.dataIndex = child.column;
this.length++;
});
} else {
this.length++;
result.width = 150;
componentWillUnmount() {
window.removeEventListener("message", this.handleClick, false);
}
handleClick = ({ data }) => {
const childFrameObj = document.getElementById("atdTable");
const salaryAcctRecordId = getQueryString("id");
const { type, data: { id, data: record, extraId = "" } = {} } = data;
if (type === "PR") {
if (id === "BATCHDELETE") {
this.setState({ selectedRowKeys: record });
} else if (id === "PAGEINFO") {
const { pageNum: current, size: pageSize } = record;
this.pageInfo = { current, pageSize };
const payload = {
type: "PR",
listType: "",
hasOperate: false,
url: "/api/bs/hrmsalary/salaryacct/acctresult/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.state.searchValue,
current, pageSize
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
} else if (id === "COLUMNINDEX") {
if (!extraId) {
this.setState({ columnIndex: record });
}
}
return result;
});
columns.push({
title: "操作",
key: "cz",
render: (text, record) => {
return <a onClick={() => {
this.handleEdit(record);
}}>编辑</a>;
} else {
const payload = {
type: "PR",
listType: "",
hasOperate: false,
url: "/api/bs/hrmsalary/salaryacct/acctresult/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.state.searchValue
}
};
type && childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
}
};
handleSearch = (employeeName) => {
const childFrameObj = document.getElementById("atdTable");
const salaryAcctRecordId = getQueryString("id");
const payload = {
type: "PR",
listType: "",
hasOperate: false,
url: "/api/bs/hrmsalary/salaryacct/acctresult/list",
queryParams: {
salaryAcctRecordId,
employeeName
}
});
return columns;
}
onDetail() {
this.setState({ slideVisiable: true });
}
handleSearch(employeeName) {
const { calculateStore: { acctResultList } } = this.props;
acctResultList({ salaryAcctRecordId: this.id, employeeName, ...this.pageInfo, current: 1 });
}
// 分页
handleDataPageChange(current) {
const { calculateStore: { acctResultList } } = this.props;
acctResultList({ salaryAcctRecordId: this.id, employeeName: this.state.searchValue, ...this.pageInfo, current });
}
handleShowSizeChange(pageInfo) {
const { calculateStore: { acctResultList } } = this.props;
acctResultList({
salaryAcctRecordId: this.id,
employeeName: this.state.searchValue, ...this.pageInfo, ...pageInfo
});
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
};
handleMenuClick() {
const { calculateStore: { exportAll } } = this.props;
const { selectedRowKeys } = this.state;
if (selectedRowKeys.length == 0) {
if (selectedRowKeys.length === 0) {
message.warning("未选择条目");
return;
}
exportAll(this.id, selectedRowKeys.join(","));
}
handleExportAll() {
handleExportAll = () => {
const { calculateStore: { exportAll } } = this.props;
exportAll(this.id);
}
onSelectChange = selectedRowKeys => {
this.setState({ selectedRowKeys });
};
render() {
const { calculateStore } = this.props;
const {
baseSalarySobCycle,
acctResultListDateSource,
acctResultListPageInfo
} = calculateStore;
const { selectedRowKeys, slideVisiable } = this.state;
const rowSelection = {
selectedRowKeys,
onChange: this.onSelectChange
};
const { baseSalarySobCycle, columnDescList } = calculateStore;
const { slideVisiable, columnIndex } = this.state;
const menu = (
<Menu onClick={(e) => this.handleMenuClick(e)}>
@ -161,9 +136,6 @@ export default class PlaceOnFileDetail extends React.Component {
);
};
if (this.getColumns().length === 1) { // 无权限处理
return renderLoading();
}
return (
<div className="placeOnFileDetail">
@ -172,7 +144,7 @@ export default class PlaceOnFileDetail extends React.Component {
renderRightOperation()
}
/>
<div className="tabWrapper">
<div className="tabWrapper" style={{ borderBottom: "none" }}>
<span>薪资所属月{baseSalarySobCycle.salaryMonth}</span>
<WeaHelpfulTip
width={100}
@ -187,43 +159,37 @@ export default class PlaceOnFileDetail extends React.Component {
placement="topLeft"
/>
</div>
<div className="tabWrapper">
<span>公式=</span>
<span>{toJS(columnDescList)[columnIndex] && toJS(columnDescList)[columnIndex].formulaContent}</span>
</div>
<div className="tableWrapper">
<CustomPaginationTable
columns={this.getColumns()}
scroll={{ x: this.length * 150 }}
dataSource={acctResultListDateSource}
rowSelection={rowSelection}
total={acctResultListPageInfo.total}
current={acctResultListPageInfo.pageNum}
pageSize={this.pageInfo.pageSize}
onPageChange={(value) => {
this.pageInfo.current = value;
this.handleDataPageChange(value);
}}
onShowSizeChange={(current, pageSize) => {
this.pageInfo = { current, pageSize };
this.handleShowSizeChange(this.pageInfo);
}}
<iframe
style={{ border: 0, width: "100%", height: "100%" }}
// src="http://localhost:7607/#/atdTable"
src="/spa/hrmSalary/hrmSalaryCalculateDetail/index.html#/atdTable"
id="atdTable"
/>
</div>
{
slideVisiable && <WeaSlideModal visible={slideVisiable}
top={0}
width={40}
height={100}
direction={"right"}
measure={"%"}
title={
<SlideModalTitle
subtitle={"合并计税详情"}
editable={true}
/>
}
content={(<FileMergeDetail/>)}
onClose={() => this.setState({ slideVisiable: false })}
showMask={true}
closeMaskOnClick={() => this.setState({ slideVisiable: false })}/>
slideVisiable &&
<WeaSlideModal
visible={slideVisiable}
top={0}
width={40}
height={100}
direction={"right"}
measure={"%"}
title={
<SlideModalTitle
subtitle={"合并计税详情"}
editable={true}
/>
}
content={(<FileMergeDetail/>)}
onClose={() => this.setState({ slideVisiable: false })}
showMask={true}
closeMaskOnClick={() => this.setState({ slideVisiable: false })}/>
}
</div>
);

View File

@ -16,6 +16,7 @@ export default class SalaryDetail extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
progressVisible: false,
progress: 0,
columnIndex: "",
@ -52,6 +53,8 @@ export default class SalaryDetail extends React.Component {
if (type === "PR") {
if (id === "EDIT") {
this.handleEdit(record);
} else if (id === "COSTCENTER") {
window.open(record ? record.url : "", "_blank");
} else if (id === "COLUMNINDEX") {
if (!extraId) {
this.setState({ columnIndex: record });
@ -91,7 +94,7 @@ export default class SalaryDetail extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/acctresult/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.props.employeeName,
...this.props.employeeName,
current, pageSize
}
};
@ -106,10 +109,10 @@ export default class SalaryDetail extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/acctresult/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.props.employeeName
...this.props.employeeName
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
type && childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
}
};
@ -155,7 +158,7 @@ export default class SalaryDetail extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/acctresult/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.props.employeeName
...this.props.employeeName
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
@ -175,13 +178,12 @@ export default class SalaryDetail extends React.Component {
}
// 侧边栏保存
handleEditSlideSave() {
handleEditSlideSave = () => {
const { calculateStore } = this.props;
const { saveAcctResult } = calculateStore;
this.setState({
slideVisiable: false
});
this.setState({ loading: true });
saveAcctResult(this.recordId).then(() => {
this.setState({ loading: false });
const childFrameObj = document.getElementById("atdTable");
const salaryAcctRecordId = getQueryString("id");
const payload = {
@ -190,17 +192,17 @@ export default class SalaryDetail extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/acctresult/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.props.employeeName
...this.props.employeeName
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
// acctResultList({ salaryAcctRecordId: this.id });
});
}
};
render() {
const { slideVisiable, columnIndex } = this.state;
const { slideVisiable, columnIndex, loading } = this.state;
const { calculateStore, taxAgentStore: { showOperateBtn } } = this.props;
const { baseSalarySobCycle, columnDescList } = calculateStore;
@ -266,10 +268,11 @@ export default class SalaryDetail extends React.Component {
measure={"%"}
title={
<SlideModalTitle
subtitle={"编辑薪资"}
subtitle="编辑薪资"
editable={true}
showOperateBtn={showOperateBtn}
onSave={() => this.handleEditSlideSave()}
onSave={this.handleEditSlideSave}
loading={loading}
/>
}
content={<EditSalaryDetail id={this.recordId}/>}

View File

@ -4,7 +4,6 @@ import { WeaBrowser, WeaFormItem, WeaHelpfulTip, WeaInput, WeaSearchGroup, WeaSe
import { inject, observer } from "mobx-react";
import "./index.less";
import { getQueryString } from "../../util/url";
import { calcPageNo } from "../../util";
@inject("calculateStore", "salaryFileStore")
@observer
@ -15,9 +14,10 @@ export default class UserSure extends React.Component {
showSearchAd: false,
searchItemsValue: {
employeeName: "",
workcode: "",
departmentIds: "",
positionIds: "",
status: ""
statuses: ""
},
selectedKey: "0",
selectedRowKeys: [], // table 选中项
@ -42,19 +42,20 @@ export default class UserSure extends React.Component {
}
Input = (value, key) => {
const { employeeName } = this.state.searchItemsValue;
const { employeeName, workcode } = this.state.searchItemsValue;
return (
<WeaFormItem
label={value}
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
>
<WeaInput value={employeeName} onChange={(val) => this.setState({
searchItemsValue: {
...this.state.searchItemsValue,
[key]: val
}
})}/>
<WeaInput value={key === "employeeName" ? employeeName : workcode}
onChange={(val) => this.setState({
searchItemsValue: {
...this.state.searchItemsValue,
[key]: val
}
})}/>
</WeaFormItem>
);
};
@ -77,7 +78,7 @@ export default class UserSure extends React.Component {
);
};
Select = (value, key) => {
const { status } = this.state.searchItemsValue;
const { statuses } = this.state.searchItemsValue;
return (
<WeaFormItem
label={value}
@ -85,10 +86,13 @@ export default class UserSure extends React.Component {
wrapperCol={{ span: 18 }}
>
<WeaSelect
value={String(status)}
multiple
value={String(statuses)}
options={[
{ key: "", showname: "" }, {key: "ALL", showname: "全部"},
{ key: "NORMAL", showname: "在职" }, {key: "UNAVAILABLE", showname: "离职"}
{ key: "0", showname: "试用" }, { key: "1", showname: "正式" },
{ key: "2", showname: "临时" }, { key: "3", showname: "试用延期" },
{ key: "4", showname: "解雇" }, { key: "5", showname: "离职" },
{ key: "6", showname: "退休" }
]}
onChange={(val) => this.setState({ searchItemsValue: { ...this.state.searchItemsValue, [key]: val } })}/>
</WeaFormItem>
@ -116,12 +120,14 @@ export default class UserSure extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/acctemployee/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.state.userListSearchValue
...this.state.searchItemsValue,
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*"); //window.postMessage
} else if (id === "DELETE") {
this.handleDeleteItem(record);
} else if (id === "COSTCENTER") {
window.open(record.url, "_blank");
} else if (id === "BATCHDELETE") {
this.onSelectChange(record);
} else if (id === "PAGEINFO") {
@ -134,7 +140,7 @@ export default class UserSure extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/acctemployee/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.state.userListSearchValue,
...this.state.searchItemsValue,
current,
pageSize
}
@ -144,10 +150,10 @@ export default class UserSure extends React.Component {
const payload = {
type: "PC",
listType: "MA",
url: this.state.selectedKey === '1'?"/api/bs/hrmsalary/salaryacct/reducedemployee/list":"/api/bs/hrmsalary/salaryacct/addedemployee/list",
url: this.state.selectedKey === "1" ? "/api/bs/hrmsalary/salaryacct/reducedemployee/list" : "/api/bs/hrmsalary/salaryacct/addedemployee/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.state.userListSearchValue,
...this.state.searchItemsValue,
current, pageSize
}
};
@ -174,7 +180,7 @@ export default class UserSure extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/acctemployee/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.state.userListSearchValue,
...this.state.searchItemsValue,
...this.pageInfo
}
};
@ -221,9 +227,9 @@ export default class UserSure extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/acctemployee/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.state.userListSearchValue,
...this.state.searchItemsValue,
...this.pageInfo,
current: 1,
current: 1
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
@ -252,8 +258,8 @@ export default class UserSure extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/acctemployee/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.state.userListSearchValue,
...this.pageInfo,
...this.state.searchItemsValue,
...this.pageInfo
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
@ -278,7 +284,7 @@ export default class UserSure extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/acctemployee/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.state.userListSearchValue,
...this.state.searchItemsValue,
...this.pageInfo
}
};
@ -339,7 +345,7 @@ export default class UserSure extends React.Component {
employeeName: "",
departmentIds: "",
positionIds: "",
status: ""
statuses: ""
}
})}>
重置
@ -352,9 +358,10 @@ export default class UserSure extends React.Component {
const renderSearch = () => {
const searchItems = [
{ com: this.Input("姓名", "employeeName") },
{ com: this.Input("工号", "workcode") },
{ com: this.Browser("部门", "departmentIds") },
{ com: this.Browser("岗位", "positionIds") },
{ com: this.Select("状态", "status") }
{ com: this.Select("状态", "statuses") }
];
return <WeaSearchGroup title={"基本信息"} items={searchItems} showGroup/>;
};
@ -423,7 +430,7 @@ export default class UserSure extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/acctemployee/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.state.userListSearchValue
...this.state.searchItemsValue,
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*"); //window.postMessage
@ -453,7 +460,7 @@ export default class UserSure extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/reducedemployee/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.state.userListSearchValue
...this.state.searchItemsValue,
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
@ -483,7 +490,7 @@ export default class UserSure extends React.Component {
url: "/api/bs/hrmsalary/salaryacct/addedemployee/list",
queryParams: {
salaryAcctRecordId,
employeeName: this.state.userListSearchValue
...this.state.searchItemsValue,
}
};
childFrameObj.contentWindow.postMessage(JSON.stringify(payload), "*");
@ -570,6 +577,7 @@ export default class UserSure extends React.Component {
<div style={{ width: "100%", height: "calc(100vh - 261px)" }}>
<iframe
style={{ border: 0, width: "100%", height: "100%" }}
// src="http://localhost:7607/#/atdTable"
src="/spa/hrmSalary/hrmSalaryCalculateDetail/index.html#/atdTable"
id="atdTable"
/>

View File

@ -27,12 +27,33 @@ class AddItems extends Component {
};
}
componentDidMount() {
this.setState({
baseInfo: {
...this.state.baseInfo,
declareMonth: this.props.editId.declareMonth || this.props.editId.taxYearMonth,
taxAgentId: this.props.editId.taxAgentId,
taxAgentName: this.props.editId.taxAgentName,
employeeId: this.props.editId.employeeId,
employeeName: this.props.editId.username
}
});
const fields = _.map(this.props.condition[0].items, it => {
return it.domkey[0];
});
fields.map(item => {
this.props.form.updateFields({
[item]: this.props.editId[item] || ""
});
});
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.editId !== this.props.editId) {
this.setState({
baseInfo: {
...this.state.baseInfo,
declareMonth: nextProps.editId.declareMonth,
declareMonth: nextProps.editId.declareMonth || nextProps.editId.taxYearMonth,
taxAgentId: nextProps.editId.taxAgentId,
taxAgentName: nextProps.editId.taxAgentName,
employeeId: nextProps.editId.employeeId,
@ -165,9 +186,10 @@ class AddItems extends Component {
return (
<div className="addItemsWrapper">
<WeaSearchGroup
className="baseForm"
title="基础信息"
items={!isCum ? items : baseInfo.personArea === "ORGANIZATION" ? [...cumSituationitems, ...insider] : baseInfo.personArea === "EXT_EMPLOYEE" ? [...cumSituationitems, ...noSysPerson] : cumSituationitems}
needTigger showGroup center/>
needTigger showGroup col={1}/>
{
getSearchs(form, condition, 2)
}

View File

@ -1,191 +1,213 @@
import { Switch } from 'antd'
export const columns = [
{
title: "姓名",
dataIndex: 'username',
key: 'username',
},
{
title: "个税扣缴义务人",
dataIndex: 'ywr',
key: 'ywr',
},
{
title: "部门",
dataIndex: 'bm',
key: 'title',
},
{
title: "手机号",
dataIndex: 'sjh',
key: 'sjh',
},
{
title: "工号",
dataIndex: 'gh',
key: 'gh',
},
{
title: "证件号码",
dataIndex: 'sfzh',
key: 'sfzh',
},
{
title: "入职日期",
dataIndex: 'rzrq',
key: 'rzrq',
},
{
title: "累计子女教育",
dataIndex: 'ljznjy',
key: 'ljznjy',
},
{
title: "累计继续教育",
dataIndex: 'ljjxjy',
key: 'ljjxjy',
},
{
title: "累计住房贷款利息",
dataIndex: 'ljzfdklx',
key: 'ljfdklx',
},
{
title: "累计住房租金",
dataIndex: 'ljzfzj',
key: 'ljzfzj',
},
{
title: "累计赡养老人",
dataIndex: 'ljsylr',
key: 'ljsylr',
},
{
title: "操作",
dataIndex: 'cz',
key: 'cz',
render: (text, record) => {
}
}
]
export const tab2Columns = [
{
title: "字段名称",
dataIndex: 'username',
key: 'username'
},
{
title: "来源",
dataIndex: 'username',
key: 'username'
},
{
title: "类型",
dataIndex: 'username',
key: 'username'
},
{
title: "是否启用",
render: (text) => {
return <Switch defaultChecked={false}/>
}
},
{
title: "备注",
dataIndex: 'username',
key: 'username'
}
]
export const slideColumns = [
{
title: "姓名",
dataIndex: 'username',
key: 'username'
},
{
title: "部门",
dataIndex: 'username',
key: 'username'
},
{
title: "手机号",
dataIndex: 'username',
key: 'username'
},
{
title: "工号",
dataIndex: 'username',
key: 'username'
},
{
title: "在职计薪天数",
dataIndex: 'username',
key: 'username'
},
{
title: "非在职计薪天数",
dataIndex: 'username',
key: 'username'
},
{
title: "应出勤天数(不含节假日)",
dataIndex: 'username',
key: 'username'
},
{
title: "实际出勤天数",
dataIndex: 'username',
key: 'username'
},
{
title: "工作日加班",
dataIndex: 'username',
key: 'username'
},
{
title: "双休日日加班",
dataIndex: 'username',
key: 'username'
},
{
title: "事假时长",
dataIndex: 'username',
key: 'username'
},
{
title: "病假时长",
dataIndex: 'username',
key: 'username'
}
]
export const slideDataSource = [{
username: "测试"
}]
export const dataSource = [
{
username: "测试",
ywr: "测试",
bm: "测试",
sjh: "测试",
gh: "测试",
sfzh: "测试",
rzrq: "测试",
ljznjy: "测试",
ljjxjy: "测试",
ljzfdklx: "测试",
ljzfzj: "测试",
ljsylr: "测试"
{
title: "姓名",
dataIndex: "username",
key: "username"
},
{
title: "个税扣缴义务人",
dataIndex: "ywr",
key: "ywr"
},
{
title: "部门",
dataIndex: "bm",
key: "title"
},
{
title: "手机号",
dataIndex: "sjh",
key: "sjh"
},
{
title: "工号",
dataIndex: "gh",
key: "gh"
},
{
title: "证件号码",
dataIndex: "sfzh",
key: "sfzh"
},
{
title: "入职日期",
dataIndex: "rzrq",
key: "rzrq"
},
{
title: "累计子女教育",
dataIndex: "ljznjy",
key: "ljznjy"
},
{
title: "累计继续教育",
dataIndex: "ljjxjy",
key: "ljjxjy"
},
{
title: "累计住房贷款利息",
dataIndex: "ljzfdklx",
key: "ljfdklx"
},
{
title: "累计住房租金",
dataIndex: "ljzfzj",
key: "ljzfzj"
},
{
title: "累计赡养老人",
dataIndex: "ljsylr",
key: "ljsylr"
},
{
title: "操作",
dataIndex: "cz",
key: "cz",
render: (text, record) => {
}
}
];
export const fieldsColumns = [
{
title: "id",
dataIndex: "id",
key: "id",
display: true
},
{
title: "字段名称",
dataIndex: "fieldName",
key: "fieldName",
display: true
},
{
title: "来源",
dataIndex: "sourceType",
key: "sourceType",
display: true
},
{
title: "类型",
dataIndex: "fieldType",
key: "fieldType",
display: true
},
{
title: "是否启用",
dataIndex: "enableStatus",
key: "enableStatus",
display: true
},
{
title: "备注",
dataIndex: "description",
key: "description",
display: true
}
];
export const conditions = [
{
items: [
{
colSpan: 1,
conditionType: "INPUT",
domkey: ["fieldName"],
fieldcol: 14,
rules: "required|string",
label: "字段名称",
labelcol: 6,
value: "",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "SELECT",
domkey: ["fieldType"],
fieldcol: 14,
isQuickSearch: false,
label: "类型",
labelcol: 6,
valueList:[],
options: [
{
key: "NUMBER",
selected: true,
showname: "数值"
},
{
key: "TEXT",
selected: false,
showname: "文本"
}
],
rules: "required|string",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "SWITCH",
domkey: ["enableStatus"],
fieldcol: 14,
label: "是否启用",
labelcol: 6,
viewAttr: 3,
rules: "required"
},
{
colSpan: 1,
conditionType: "INPUT",
domkey: ["description"],
fieldcol: 14,
label: "备注",
labelcol: 6,
value: "",
viewAttr: 2
}
],
defaultshow: true
}
];
export const reFrenceConditions = [
{
items: [
{
colSpan: 1,
conditionType: "MONTHPICKER",
domkey: ["salaryYearMonth"],
fieldcol: 18,
rules: "required|string",
label: "薪资所属月",
labelcol: 6,
value: "",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "SELECT",
domkey: ["salarySobId"],
fieldcol: 18,
isQuickSearch: false,
label: "薪资账套",
labelcol: 6,
valueList:[],
options: [],
rules: "required|string",
viewAttr: 3
},
{
colSpan: 1,
conditionType: "INPUT",
domkey: ["description"],
fieldcol: 18,
label: "备注",
labelcol: 6,
value: "",
viewAttr: 2
}
],
defaultshow: true
}
];

View File

@ -0,0 +1,76 @@
/*
* Author: 黎永顺
* name: 新建考勤自定义字段
* Description:
* Date: 2023/3/1
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaDialog } from "ecCom";
import { Button, message } from "antd";
import { conditions } from "../columns";
import { getSearchs } from "../../../../util";
import { saveAttendanceField } from "../../../../apis/attendance";
import "./index.less";
@inject("attendanceStore")
@observer
class AttendanceCustomFieldsModal extends Component {
componentDidMount() {
const { attendanceStore: { form } } = this.props;
form.initFormFields(conditions);
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) this.handleResetForm();
}
/*
* Author: 黎永顺
* Description: 保存考勤字段
* Params:
* Date: 2023/3/1
*/
handleSubmitFields = () => {
const { attendanceStore: { form }, onRefresh, onCancel } = this.props;
form.validateForm().then(f => {
if (f.isValid) {
const payload = form.getFormParams();
saveAttendanceField(payload).then(({ status, errormsg }) => {
if (status) {
message.success("新增成功");
onCancel();
onRefresh();
} else {
message.error(errormsg || "新增失败");
}
});
} else {
f.showErrors();
}
});
};
handleResetForm = () => {
const { attendanceStore: { form } } = this.props;
form.updateFields({ fieldName: "", fieldType: "NUMBER", enableStatus: "0", description: "" });
};
render() {
const { attendanceStore: { form } } = this.props;
const buttons = [
<Button type="primary" onClick={this.handleSubmitFields}>保存</Button>
];
return (
<WeaDialog
{...this.props} style={{ width: 440, height: 202 }}
buttons={buttons} hasScroll initLoadCss
className="modalWrapper"
>
{getSearchs(form, conditions, 1)}
</WeaDialog>
);
}
}
export default AttendanceCustomFieldsModal;

View File

@ -0,0 +1,419 @@
/*
* Author: 黎永顺
* name: 考勤数据
* Description:
* Date: 2023/2/24
*/
import React, { Component } from "react";
import { WeaTable } from "ecCom";
import { message, Modal } from "antd";
import {
deleteAttendance,
getAttendanceFieldSettingList,
getAttendanceList,
getLedgerList,
getSalaryCycleAndAttendCycle,
importAttendQuoteData,
previewAttendQuote,
returnToAttendanceFieldSettingDefault,
saveAttendanceFieldSetting,
saveAttendanceFieldSettingAsDefault
} from "../../../../apis/attendance";
import ImportModal from "../../../../components/importModal";
import HeaderSet from "../../../../components/importModal/headerSet";
import ImportFormOptions from "./importFormOptions";
import SelectItemModal from "../../../../components/selectItemsModal";
import moment from "moment";
import SelectItemsWrapper from "../../../../components/selectItemsModal/selectItemsWrapper";
import AttendanceRefrenceDataModal from "./attendanceRefrenceDataModal";
import AttendanceDataViewSlide from "./attendanceDataViewSlide";
class AttendanceDataComp extends Component {
constructor(props) {
super(props);
this.state = {
loading: {
query: false,
headset: false
},
dataSource: [],
columns: [],
pageInfo: {
current: 1,
pageSize: 10,
total: 0
},
importData: {
visiable: false, params: {}, step: 0,
columns: [], slideDataSource: [], importResult: []
},
importFormPayload: {
salaryYearMonth: moment().format("YYYY-MM"), salarySobList: [],
salarySobId: "", salaryCycle: "", attendCycle: ""
},
fieldSetPayload: { visible: false, title: "", children: null },
attendanceReferencePayload: { visible: false, title: "" },
attendanceViewPayload: { visible: false, attendQuoteId: "", salaryYearMonth: "" }
};
}
componentDidMount() {
this.getAttendanceList();
}
getAttendanceList = (extraPayload) => {
const { loading, pageInfo } = this.state;
const module = { ...pageInfo, ...extraPayload };
this.setState({ loading: { ...loading, query: true } });
getAttendanceList(module).then(({ status, data }) => {
this.setState({ loading: { ...loading, query: false } });
if (status) {
const { columns, list: dataSource, pageNum: current, pageSize, total } = data;
this.setState({
pageInfo: { ...pageInfo, current, pageSize, total },
dataSource,
columns: _.map(columns, item => {
if (item.dataIndex === "salaryYearMonth") {
return {
...item,
render: (text) => <span>{moment(text).format("YYYY-MM")}</span>
};
}
return { ...item };
})
});
}
}).catch(() => this.setState({ loading: { ...loading, query: false } }));
};
getLedgerList = () => {
const { importFormPayload } = this.state;
getLedgerList().then(({ status, data }) => {
if (status) {
this.setState({
importFormPayload: {
...importFormPayload,
salarySobList: _.map(data, it => ({ key: it.id, showname: it.content }))
}
});
}
});
};
handleChangeImportPayload = (key, value) => {
const { importFormPayload, importData } = this.state;
const { params } = importData;
this.setState({
importFormPayload: {
...importFormPayload,
[key]: value
},
importData: { ...importData, params: { ...params, [key]: value } }
}, () => {
if (this.state.importFormPayload.salaryYearMonth && this.state.importFormPayload.salarySobId) {
const payload = {
salaryYearMonthStr: this.state.importFormPayload.salaryYearMonth,
salarySobId: this.state.importFormPayload.salarySobId
};
getSalaryCycleAndAttendCycle(payload).then(({ status, data }) => {
if (status) {
this.setState({
importFormPayload: {
...this.state.importFormPayload,
...data
}
});
}
});
}
});
};
handleDeleteAttendanceData = ({ id }) => {
Modal.confirm({
title: "信息确认",
content: "确认要删除吗?",
onOk: () => {
deleteAttendance([id]).then(({ status, errormsg }) => {
if (status) {
message.success("删除成功");
this.getAttendanceList();
} else {
message.error(errormsg || "删除失败");
}
});
}
});
};
handleViewAttendanceData = ({ id, attendCycle }) => {
const { attendanceViewPayload } = this.state;
this.setState({
attendanceViewPayload: {
...attendanceViewPayload,
visible: true, attendQuoteId: id,
salaryYearMonth: attendCycle
}
});
};
handleImportAttendanceData = (importData) => {
const { importFormPayload } = this.state;
const { salaryYearMonth, salarySobId } = importFormPayload;
this.getLedgerList();
this.setState({ importData: { ...importData, params: { salaryYearMonth, salarySobId } } });
};
setStep = step => this.setState({ importData: { ...this.state.importData, step } });
handleFinish = () => {
const { importData } = this.state;
const { step } = importData;
this.setState({
importData: {
...importData, visiable: false, params: {}, step: 0,
columns: [], slideDataSource: [], importResult: []
}
});
step === 2 && this.getAttendanceList();
};
handlePreviewImport = (params) => {
const { importData } = this.state;
previewAttendQuote(params).then(({ status, data }) => {
if (status) {
const { headers, list } = data;
this.setState({
importData: {
...importData,
columns: _.map(headers, (it, dataIndex) => ({ title: it, dataIndex })),
slideDataSource: _.map(list, item => {
return _.reduce(item, (pre, cur, key) => (_.assign(pre, { [key]: cur })), {});
})
}
});
}
});
};
handleImport = (params) => {
const { importData } = this.state;
const { step } = importData;
importAttendQuoteData(params).then(({ status, data }) => {
if (status) {
this.setState({
importData: {
...importData,
step: step + 1,
importResult: data
}
});
}
});
};
handleTemplateLinkClick = () => {
const { importFormPayload } = this.state;
const { salarySobId, salaryYearMonth } = importFormPayload;
if (!salarySobId || !salaryYearMonth) {
message.warning("请完善导入选项,再下载");
return;
}
window.open(`/api/bs/hrmsalary/attendQuote/downloadTemplate?salaryYearMonth=${salaryYearMonth}&salarySobId=${salarySobId}`);
};
/*
* Author: 黎永顺
* Description: 表头设置
* Params:
* Date: 2023/3/6
*/
handleHeaderSettings = (params) => {
const { fieldSetPayload, loading } = this.state;
this.setState({ loading: { ...loading, headset: true } });
getAttendanceFieldSettingList(params).then(({ status, data }) => {
this.setState({ loading: { ...loading, headset: false } });
if (status) {
this.setState({
fieldSetPayload: {
...fieldSetPayload,
visible: true, title: "导入字段设置",
children: <SelectItemsWrapper
ref={dom => this.setItemRef = dom}
dataSource={data}
onSelectGroupAll={this.handleSelectGroupAll}
onSelectItem={this.handleSelectItem}
/>
}
});
}
}).catch(() => this.setState({ loading: { ...loading, headset: false } }));
};
handleCloseSettings = () => {
const { fieldSetPayload } = this.state;
this.setState({
fieldSetPayload: {
...fieldSetPayload,
visible: false, title: "", children: null
}
});
};
handleSearchItemSet = (val) => this.setItemRef.handleSearchItemSet(val);
handleShowOnlyChecked = (checked) => this.setItemRef.handleShowOnlyChecked(checked);
handleSelectGroupAll = (groupId, checked) => this.setItemRef.handleSelectGroupAll(groupId, checked);
handleSelectItem = (id, checked) => this.setItemRef.handleSelectItem(id, checked);
handleMoreOpts = (key) => {
switch (key) {
case "recovery":
returnToAttendanceFieldSettingDefault({ sourceType: "IMPORT" }).then(({ status, errormsg }) => {
if (status) {
message.success("操作成功");
this.handleHeaderSettings({ sourceType: "IMPORT" });
} else {
message.error(errormsg || "操作失败");
}
});
break;
case "setting":
const { state, props } = this.setItemRef;
let currentSettingFields = [];
const { selectItem } = state, { dataSource } = props;
_.forEach(dataSource, item => {
currentSettingFields = _.map([...currentSettingFields, ...item.items], child => {
return {
id: child.id,
checked: selectItem.includes(child.id)
};
});
});
const payload = { currentSettingFields, sourceType: "IMPORT" };
saveAttendanceFieldSettingAsDefault(payload).then(({ status, errormsg }) => {
if (status) {
message.success("操作成功");
} else {
message.error(errormsg || "操作失败");
}
});
break;
default:
break;
}
};
handleSave = () => {
const { state, props } = this.setItemRef;
let currentSettingFields = [];
const { selectItem } = state, { dataSource } = props;
_.forEach(dataSource, item => {
currentSettingFields = _.map([...currentSettingFields, ...item.items], child => {
return {
id: child.id,
checked: selectItem.includes(child.id)
};
});
});
const payload = { currentSettingFields, sourceType: "IMPORT" };
saveAttendanceFieldSetting(payload).then(({ status, errormsg }) => {
if (status) {
message.success("保存成功");
this.handleCloseSettings();
} else {
message.error(errormsg || "保存失败");
}
});
};
/*
* Author: 黎永顺
* Description: 考勤数据引用
* Params:
* Date: 2023/3/7
*/
handleQuoteAttendanceData = (payload) => {
const { attendanceReferencePayload } = this.state;
this.setState({ attendanceReferencePayload: { ...attendanceReferencePayload, ...payload } });
};
handleCloseQuoteModal = (isRefresh) => {
const { attendanceReferencePayload } = this.state;
this.setState({ attendanceReferencePayload: { ...attendanceReferencePayload, visible: false } }, () => {
isRefresh && this.getAttendanceList();
});
};
render() {
const {
dataSource, columns, pageInfo, loading, importData, importFormPayload, fieldSetPayload,
attendanceReferencePayload, attendanceViewPayload
} = this.state;
const { showOperateBtn, salaryYearMonth } = this.props;
const pagination = {
...pageInfo,
showTotal: total => `${total}`,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
onShowSizeChange: (current, pageSize) => {
this.setState({
pageInfo: { ...pageInfo, current, pageSize }
}, () => this.getAttendanceList({ salaryYearMonth: _.compact(salaryYearMonth) }));
},
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => this.getAttendanceList({ salaryYearMonth: _.compact(salaryYearMonth) }));
}
};
return (
<React.Fragment>
<WeaTable
columns={[
...columns,
{
title: "操作",
width: 120,
dataIndex: "operate",
render: (_, record) => {
return (
<div className="linkWapper">
<a href="javascript: void(0);" onClick={() => this.handleViewAttendanceData(record)}>查看</a>
{showOperateBtn &&
<a href="javascript: void(0);" onClick={() => this.handleDeleteAttendanceData(record)}>删除</a>
}
</div>
);
}
}
]}
dataSource={dataSource}
pagination={pagination}
loading={loading.query}
/>
{/* 考勤引用导入 */}
<ImportModal {...importData} setStep={this.setStep} onFinish={this.handleFinish}
previewImport={this.handlePreviewImport} importFile={this.handleImport}
templateLink={this.handleTemplateLinkClick} onCancel={this.handleFinish}
headerSetCompoent={<HeaderSet
loading={loading.headset}
onSetClick={() => this.handleHeaderSettings({ sourceType: "IMPORT" })}/>}
renderFormComponent={() => <ImportFormOptions
{...importFormPayload}
onChangeImportForm={this.handleChangeImportPayload}/>
}
/>
{/* 表头设置 */}
<SelectItemModal {...fieldSetPayload}
onCancel={this.handleCloseSettings}
onSearchItemSet={this.handleSearchItemSet}
onShowOnlyChecked={this.handleShowOnlyChecked}
onMoreOpts={this.handleMoreOpts} onSave={this.handleSave}
/>
{/* 考勤数据引用 */}
<AttendanceRefrenceDataModal
{...attendanceReferencePayload}
onCancel={this.handleCloseQuoteModal}
/>
{/* 考勤数据查看 */}
<AttendanceDataViewSlide
{...attendanceViewPayload}
showOperateBtn={showOperateBtn}
onClose={() => this.setState({
attendanceViewPayload: {
...attendanceViewPayload,
visible: false,
attendQuoteId: ""
}
})}
/>
</React.Fragment>
);
}
}
export default AttendanceDataComp;

View File

@ -0,0 +1,143 @@
/*
* Author: 黎永顺
* name: 考勤引用数据查看
* Description:
* Date: 2023/3/7
*/
import React, { Component } from "react";
import { WeaFormItem, WeaInput, WeaInputSearch, WeaSlideModal } from "ecCom";
import { Button } from "antd";
import SlideModalTitle from "../../../../components/slideModalTitle";
import { viewAttendQuote } from "../../../../apis/attendance";
import UnifiedTable from "../../../../components/UnifiedTable";
import "./index.less";
class AttendanceDataViewSlide extends Component {
constructor(props) {
super(props);
this.state = {
loading: {
query: false
},
keyword: "",
dataSource: [],
columns: [],
pageInfo: {
current: 1, pageSize: 10, total: 0
}
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) this.viewAttendQuote({}, nextProps);
}
viewAttendQuote = (extraPayload = {}, props) => {
const { loading, pageInfo, keyword } = this.state;
const { attendQuoteId } = props;
this.setState({ loading: { ...loading, query: true } });
viewAttendQuote({ ...pageInfo, attendQuoteId, keyword, ...extraPayload }).then(({ status, data }) => {
this.setState({ loading: { ...loading, query: false } });
if (status) {
const { columns, list: dataSource, pageNum: current, pageSize, total } = data.pageInfo;
this.setState({
pageInfo: { ...pageInfo, current, pageSize, total },
dataSource,
columns
});
}
}).catch(() => this.setState({ loading: { ...loading, query: false } }));
};
renderCustomOperate = () => {
const { keyword } = this.state;
const { showOperateBtn } = this.props;
return ([
<div style={{ display: "inline-block" }}>
{showOperateBtn && <Button type="primary" onClick={this.handleExportAttendQuote}>导出全部</Button>}
<WeaInputSearch
value={keyword}
style={{ marginLeft: 10 }}
placeholder="请输入姓名/部门/工号/手机号"
onChange={keyword => this.setState({ keyword })}
onSearch={() => this.viewAttendQuote({ current: 1 }, this.props)}
/>
</div>
]);
};
handleExportAttendQuote = () => {
if (!this.handleDebounce) {
this.handleDebounce = _.debounce(() => {
const { attendQuoteId } = this.props;
const url = `${window.location.origin}/api/bs/hrmsalary/attendQuote/export?attendQuoteId=${attendQuoteId}`;
window.open(url, "_self");
this.handleDebounce = null;
}, 500);
}
this.handleDebounce();
};
render() {
const { showOperateBtn, salaryYearMonth, ...extra } = this.props;
const { columns, dataSource, loading, pageInfo } = this.state;
const pagination = {
...pageInfo,
showTotal: (total) => `${total}`,
pageSizeOptions: ["10", "20", "50", "100"],
showSizeChanger: true,
showQuickJumper: true,
onShowSizeChange: (current, pageSize) => {
this.setState({
pageInfo: { ...pageInfo, current, pageSize }
}, () => this.viewAttendQuote({}, this.props));
},
onChange: (current) => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => this.viewAttendQuote({}, this.props));
}
};
return (
<WeaSlideModal
{...extra}
className="attendanceSlideWrapper"
top={0}
measureT="%"
width={80}
measureX="%"
height={100}
measureY="%"
direction="right"
title={
<SlideModalTitle
subtitle="考勤数据"
editable={false}
showOperateBtn={showOperateBtn}
customOperate={this.renderCustomOperate()}
/>
}
content={
<div>
<WeaFormItem label="考勤周期" labelCol={{ span: 4 }} wrapperCol={{ span: 20 }} underline>
<WeaInput value={salaryYearMonth} viewAttr={1}/>
</WeaFormItem>
<UnifiedTable
rowKey="id"
columns={_.map(columns, item => ({
...item,
render: (text) => {
return <span className="ellipsis" title={text}> {text} </span>;
}
}))}
dataSource={dataSource}
pagination={pagination}
loading={loading.query}
xWidth={columns.length * 180}
/>
</div>
}
/>
);
}
}
export default AttendanceDataViewSlide;

View File

@ -0,0 +1,230 @@
/*
* Author: 黎永顺
* name: 考勤数据引用
* Description:
* Date: 2023/3/1
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaDialog } from "ecCom";
import { Button, message } from "antd";
import { reFrenceConditions } from "../columns";
import { getSearchs } from "../../../../util";
import {
checkOperation,
getAttendanceFieldSettingList,
getLedgerList, returnToAttendanceFieldSettingDefault, saveAttendanceFieldSetting, saveAttendanceFieldSettingAsDefault,
syncAttendanceRefer
} from "../../../../apis/attendance";
import SelectItemModal from "../../../../components/selectItemsModal";
import SelectItemsWrapper from "../../../../components/selectItemsModal/selectItemsWrapper";
import "./index.less";
@inject("attendanceStore")
@observer
class AttendanceRefrenceDataModal extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
headerSetLoading: false,
condition: [],
headerSetPayload: { visible: false, title: "", children: null }
};
}
componentDidMount() {
this.getLedgerList();
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) this.handleResetForm();
}
getLedgerList = () => {
const { attendanceStore: { refenceform } } = this.props;
getLedgerList().then(({ status, data }) => {
if (status) {
this.setState({
condition: _.map(reFrenceConditions, (item) => {
const { items } = item;
return {
...item,
items: _.map(items, child => {
const { domkey } = child;
if (domkey[0] === "salarySobId") {
return { ...child, options: _.map(data, it => ({ key: it.id, showname: it.content })) };
}
return { ...child };
})
};
})
}, () => refenceform.initFormFields(this.state.condition));
}
});
};
/*
* Author: 黎永顺
* Description: 同步考勤数据
* Params:
* Date: 2023/3/1
*/
handleSubmitFields = () => {
const { attendanceStore: { refenceform }, onCancel } = this.props;
refenceform.validateForm().then(f => {
if (f.isValid) {
const payload = refenceform.getFormParams();
const checkPayload = { salaryYearMonthStr: payload.salaryYearMonth, salarySobId: payload.salarySobId };
this.setState({ loading: true });
checkOperation(checkPayload).then(({ status, errormsg: errormessage }) => {
if (status) {
syncAttendanceRefer(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success("同步成功");
onCancel(true);
} else {
message.error(errormsg || "同步失败");
}
}).catch(() => this.setState({ loading: false }));
} else {
this.setState({ loading: false });
message.error(errormessage);
}
}).catch(() => this.setState({ loading: false }));
} else {
f.showErrors();
}
});
};
handleResetForm = () => {
const { attendanceStore: { refenceform } } = this.props;
refenceform.resetForm();
};
/*
* Author: 黎永顺
* Description: 表头设置
* Params:
* Date: 2023/3/8
*/
handleHeaderSetting = () => {
const { headerSetPayload } = this.state;
this.setState({ headerSetLoading: true });
getAttendanceFieldSettingList({ sourceType: "QUOTE" }).then(({ status, data }) => {
this.setState({ headerSetLoading: false });
if (status) {
this.setState({
headerSetPayload: {
...headerSetPayload,
visible: true, title: "引用考勤字段设置",
children: <SelectItemsWrapper
ref={dom => this.setItemRef = dom}
dataSource={data}
onSelectGroupAll={this.handleSelectGroupAll}
onSelectItem={this.handleSelectItem}
/>
}
});
}
}).catch(() => this.setState({ headerSetLoading: false }));
};
handleCloseSettings = () => {
const { headerSetPayload } = this.state;
this.setState({
headerSetPayload: {
...headerSetPayload,
visible: false, title: "", children: null
}
});
};
handleSearchItemSet = (val) => this.setItemRef.handleSearchItemSet(val);
handleShowOnlyChecked = (checked) => this.setItemRef.handleShowOnlyChecked(checked);
handleSelectGroupAll = (groupId, checked) => this.setItemRef.handleSelectGroupAll(groupId, checked);
handleSelectItem = (id, checked) => this.setItemRef.handleSelectItem(id, checked);
handleMoreOpts = (key) => {
switch (key) {
case "recovery":
returnToAttendanceFieldSettingDefault({ sourceType: "QUOTE" }).then(({ status, errormsg }) => {
if (status) {
message.success("操作成功");
this.handleHeaderSetting({ sourceType: "QUOTE" });
} else {
message.error(errormsg || "操作失败");
}
});
break;
case "setting":
const { state, props } = this.setItemRef;
let currentSettingFields = [];
const { selectItem } = state, { dataSource } = props;
_.forEach(dataSource, item => {
currentSettingFields = _.map([...currentSettingFields, ...item.items], child => {
return {
id: child.id,
checked: selectItem.includes(child.id)
};
});
});
const payload = { currentSettingFields, sourceType: "QUOTE" };
saveAttendanceFieldSettingAsDefault(payload).then(({ status, errormsg }) => {
if (status) {
message.success("操作成功");
} else {
message.error(errormsg || "操作失败");
}
});
break;
default:
break;
}
};
handleSave = () => {
const { state, props } = this.setItemRef;
let currentSettingFields = [];
const { selectItem } = state, { dataSource } = props;
_.forEach(dataSource, item => {
currentSettingFields = _.map([...currentSettingFields, ...item.items], child => {
return {
id: child.id,
checked: selectItem.includes(child.id)
};
});
});
const payload = { currentSettingFields, sourceType: "QUOTE" };
saveAttendanceFieldSetting(payload).then(({ status, errormsg }) => {
if (status) {
message.success("保存成功");
this.handleCloseSettings();
} else {
message.error(errormsg || "保存失败");
}
});
};
render() {
const { condition, loading, headerSetLoading, headerSetPayload } = this.state;
const { attendanceStore: { refenceform } } = this.props;
const buttons = [
<Button type="primary" onClick={this.handleSubmitFields} loading={loading}>同步</Button>,
<Button type="ghost" onClick={this.handleHeaderSetting} loading={headerSetLoading}>表头设置</Button>
];
return (
<WeaDialog
{...this.props} style={{ width: 440, height: 156 }}
buttons={buttons} hasScroll initLoadCss
className="modalWrapper"
>
{getSearchs(refenceform, condition, 1)}
{/* 表头设置 */}
<SelectItemModal {...headerSetPayload}
onCancel={this.handleCloseSettings}
onSearchItemSet={this.handleSearchItemSet}
onShowOnlyChecked={this.handleShowOnlyChecked}
onMoreOpts={this.handleMoreOpts} onSave={this.handleSave}
/>
</WeaDialog>
);
}
}
export default AttendanceRefrenceDataModal;

View File

@ -0,0 +1,139 @@
/*
* Author: 黎永顺
* name:字段管理
* Description:
* Date: 2023/2/24
*/
import React, { Component } from "react";
import { WeaCheckbox, WeaTable } from "ecCom";
import { Col, message, Row } from "antd";
import AttendanceCustomFieldsModal from "./attendanceCustomFieldsModal";
import { getAttendanceFieldList, updateAttendanceFieldStatus } from "../../../../apis/attendance";
import TipLabel from "../../../../components/TipLabel";
import { fieldsColumns } from "../columns";
class FieldMangComp extends Component {
constructor(props) {
super(props);
this.state = {
loading: {
query: false
},
dataSource: [{}],
columns: fieldsColumns,
pageInfo: {
current: 1,
pageSize: 10,
total: 0
},
addPayload: {
visible: false,
title: "新建考勤自定义字段"
}
};
}
componentDidMount() {
this.getAttendanceFieldList();
}
getAttendanceFieldList = (extraPayload = {}) => {
const { loading, pageInfo } = this.state;
const module = { ...pageInfo, ...extraPayload };
this.setState({ loading: { ...loading, query: true } });
getAttendanceFieldList(module).then(({ status, data }) => {
this.setState({ loading: { ...loading, query: false } });
if (status) {
const { pageInfo: pageInfoData } = data;
const { list: dataSource, columns, pageNum: current, pageSize, total } = pageInfoData;
this.setState({
pageInfo: { ...pageInfo, current, pageSize, total },
dataSource, columns
});
}
}).catch(() => this.setState({ loading: { ...loading, query: false } }));
};
handleTriggerAttendFileds = () => {
const { addPayload } = this.state;
this.setState({ addPayload: { ...addPayload, visible: !addPayload.visible } });
};
handleAttendanceFieldSwitch = ({ id }, enableStatus) => {
const payload = { id, enableStatus: enableStatus === "1" };
updateAttendanceFieldStatus(payload).then(({ status, errormsg }) => {
if (status) {
message.success("操作成功");
this.getAttendanceFieldList();
} else {
message.error(errormsg || "操作失败");
}
});
};
getColumns = () => {
const { columns } = this.state;
const { showOperateBtn } = this.props;
return _.map(_.filter(columns, item => !!item.display), child => ({
...child,
render: (text, record) => {
switch (child.dataIndex) {
case "enableStatus":
return (
<WeaCheckbox
value={text} display="switch" disabled={!showOperateBtn}
onChange={value => this.handleAttendanceFieldSwitch(record, value)}
/>
);
default:
return <div dangerouslySetInnerHTML={{ __html: text }}/>;
}
}
}));
};
render() {
const { dataSource, pageInfo, loading, addPayload } = this.state;
const { fieldName } = this.props;
const pagination = {
...pageInfo,
showTotal: total => `${total}`,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
onShowSizeChange: (current, pageSize) => {
this.setState({
pageInfo: { ...pageInfo, current, pageSize }
}, () => this.getAttendanceFieldList({ fieldName }));
},
onChange: current => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => this.getAttendanceFieldList({ fieldName }));
}
};
return (
<Row gutter={20}>
<Col xs={24} sm={24} md={16} lg={18}>
<WeaTable
columns={this.getColumns()}
dataSource={dataSource}
pagination={pagination}
loading={loading.query}
/>
<AttendanceCustomFieldsModal
{...addPayload} onCancel={this.handleTriggerAttendFileds}
onRefresh={this.getAttendanceFieldList}
/>
</Col>
<Col xs={24} sm={24} md={8} lg={6}>
<TipLabel
tipList={[
"1、考勤字段包含自定义字段和考勤模块的统计字段所有字段不可重名",
"2、停用自定义字段将影响其参与计算的账套核算"
]}
/>
</Col>
</Row>
);
}
}
export default FieldMangComp;

View File

@ -0,0 +1,57 @@
/*
* Author: 黎永顺
* name: 考情数据导入的表单选项
* Description:
* Date: 2023/3/3
*/
import React, { Component } from "react";
import { WeaFormItem, WeaInput, WeaSearchGroup } from "ecCom";
import { DataCollectionDatePicker, DataCollectionSelect } from "../../cumDeduct";
import "./index.less";
const Input = (label, value, labelCol = 8, wrapperCol = 16) => {
return (
<WeaFormItem label={label} labelCol={{ span: labelCol }} wrapperCol={{ span: wrapperCol }}>
<WeaInput viewAttr={1} value={value}/>
</WeaFormItem>
);
};
class ImportFormOptions extends Component {
screenChange = ({ key, value }) => {
const { onChangeImportForm } = this.props;
onChangeImportForm(key, value);
};
render() {
const { salarySobList = [], salaryYearMonth, salarySobId, salaryCycle, attendCycle } = this.props;
const items = [
{
com: DataCollectionDatePicker({
label: "薪资所属月",
value: salaryYearMonth,
onChange: this.screenChange,
key: "salaryYearMonth",
screen: false
})
},
{
com: DataCollectionSelect({
label: "薪资账套",
value: salarySobId || "",
onChange: this.screenChange,
options: [{ key: "", showname: "" }, ...salarySobList],
key: "salarySobId"
})
},
{ com: Input("薪资周期", salaryCycle) },
{ com: Input("考勤周期", attendCycle, 10, 14) }
];
return (
<WeaSearchGroup className="attendanceFormWrapper" showGroup needTigger={false} items={items}
col={2}/>
);
}
}
export default ImportFormOptions;

View File

@ -0,0 +1,53 @@
.modalWrapper {
.wea-select, .ant-select-selection, .ant-select {
width: 100%;
}
.wea-date-picker {
width: 100%;
}
.wea-select {
display: inline-block;
position: relative;
}
.ant-select-selection {
height: 30px;
border-radius: 0;
}
}
.attendanceFormWrapper {
padding: 0;
}
.attendanceSlideWrapper {
.wea-slide-modal-title {
height: initial;
line-height: initial;
text-align: left;
}
.rodal-close {
z-index: 99;
top: 10px !important;
}
}
@media (min-width: 1260px) {
.attendanceSlideWrapper {
.reqTopWrapper .wea-new-top-req-title > div:first-child > div {
max-width: 100% !important;
}
}
}
@media screen and (min-width: 1060px) and (max-width: 1260px) {
.attendanceSlideWrapper {
.reqTopWrapper .wea-new-top-req-title > div:first-child > div {
max-width: calc(100% - 96px) !important;
}
}
}

View File

@ -1,115 +0,0 @@
import React from "react";
import { Row, Col, Table, DatePicker } from "antd";
import { inject, observer } from "mobx-react";
import {
WeaInput,
WeaTextarea,
WeaSearchGroup,
WeaSelect,
WeaCheckbox,
WeaTable
} from "ecCom";
import { slideColumns, slideDataSource, columns } from "./columns";
import "./editSlideContent.less";
// import { WeaTableNew } from "comsMobx"
// const WeaTable = WeaTableNew.WeaTable;
import moment from "moment";
const { MonthPicker } = DatePicker;
let emptyItem = {
incomeLowerLimit: "0.00",
incomeUpperLimit: "0.00",
dutyFreeValue: "0.00",
dutyFreeRate: "0.00",
taxableIncomeLl: "0.00",
taxableIncomeUl: "0.00",
taxRate: "0.00",
taxDeduction: "0.00"
};
@inject("attendanceStore")
@observer
export default class EditSlideContent extends React.Component {
constructor(props) {
super(props);
}
componentWillMount() {
// 初始化渲染页面
const { attendanceStore: { viewAttendQuote } } = this.props;
viewAttendQuote({ attendQuoteId: this.props.id });
}
getColumns(columns) {
let result = [...columns];
return result.filter(item => item.hide == "false");
}
getScrollWidth() {
const { attendanceStore } = this.props;
const { attendQuoteDetailTableStore } = attendanceStore;
return (
this.getColumns(
attendQuoteDetailTableStore.columns
? attendQuoteDetailTableStore.columns
: []
).length * 150
);
}
render() {
const {
attendanceStore,
attendanceStore: { viewAttendQuote }
} = this.props;
const {
attendQuoteDetailPageInfo,
attendQuoteDetailTableStore
} = attendanceStore;
const pagination = {
total: attendQuoteDetailPageInfo.total,
showTotal: total => `${total}`,
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
onShowSizeChange: (current, pageSize) => {
viewAttendQuote({ attendQuoteId: this.props.id, current, pageSize });
},
onChange: current => {
viewAttendQuote({
attendQuoteId: this.props.id,
current,
pageSize: attendQuoteDetailPageInfo.pageSize
});
}
};
return (
<div className="attendSlide">
<div className="titleWrapper">
{this.props.salaryYearMonth != "" &&
<div className="slideLeftTitle">
考勤周期 {this.props.salaryYearMonth}
</div>}
</div>
<div>
<WeaTable
columns={this.getColumns(
attendQuoteDetailTableStore.columns
? attendQuoteDetailTableStore.columns
: []
)}
dataSource={
attendQuoteDetailPageInfo.list
? attendQuoteDetailPageInfo.list
: []
}
pagination={pagination}
scroll={{ x: this.getScrollWidth() }}
/>
</div>
</div>
);
}
}

View File

@ -1,26 +0,0 @@
.attendSlide {
.titleWrapper {
height: 47px;
line-height: 47px;
overflow: hidden;
padding-left: 10px;
padding-right: 10px;
.slideLeftTitle {
float: left;
}
.rightTitle {
float: right;
}
}
.weaRangePickerWrapper {
display: inline-block;
.monthPickerWrapper {
width: 100px;
display: inline-block;
}
.betweenLable {
margin-left: 10px;
margin-right: 10px;
}
}
}

View File

@ -1,14 +0,0 @@
import React from 'react'
import { Modal } from 'antd'
import SelectItemModal, { items } from '../../../components/selectItemsModal/selectItemsWrapper';
export default class HeaderSetModal extends React.Component {
render() {
return (
<Modal width={800} visible={this.props.visible} onCancel={this.props.onCancel}>
<SelectItemsWrapper items={items} title={"考勤模块"}/>
</Modal>
)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,33 +1,66 @@
.attendenceImportWrapper{
.wea-dialog-body{
.attendanceRefWrapper {
height: 100%;
display: flex;
flex-direction: column;
.wea-form-item {
padding: 8px 16px;
.to {
padding: 0 10px
}
}
.tableWrapper {
flex: 1;
overflow: hidden;
}
.linkWapper {
& > a:first-child {
padding-right: 10px;
}
}
}
.attendenceImportWrapper {
.wea-dialog-body {
padding: 16px 120px;
.wea-select, .ant-select, .ant-select-selection{
.wea-select, .ant-select, .ant-select-selection {
width: 100%;
}
.ant-select-selection{
.ant-select-selection {
border-radius: 0;
height: 30px;
}
}
}
//导入字段设置
.fieldSetWrapper{
.wea-dialog-body{
.fieldSetWrapper {
.wea-dialog-body {
padding: 16px 20px;
}
.ant-modal-footer button{
margin-right: 0!important;
.ant-modal-footer button {
margin-right: 0 !important;
}
.ant-btn-group{
margin-left: 10px!important;
.ant-btn-group {
margin-left: 10px !important;
}
.searchWrapper{
.searchWrapper {
display: flex;
justify-content: flex-end;
align-items: center;
margin-bottom: 10px;
}
.allInWrapper{
.allInWrapper {
display: flex;
justify-content: flex-start;
margin-top: 10px;
@ -35,15 +68,17 @@
}
//新建考勤自定义字段弹框
.itemManageModalWrapper{
.wea-select,.ant-select-selection,.ant-select{
.itemManageModalWrapper {
.wea-select, .ant-select-selection, .ant-select {
width: 100%;
}
.wea-select{
.wea-select {
display: inline-block;
position: relative;
}
.ant-select-selection{
.ant-select-selection {
height: 30px;
border-radius: 0;
}

View File

@ -1,124 +0,0 @@
import React from "react";
import { Button, Col, Row, Switch } from "antd";
import { inject, observer } from "mobx-react";
import { WeaDialog, WeaInput, WeaSelect } from "ecCom";
import "./index.less";
@inject("attendanceStore")
@observer
export default class ItemMangeFormModal extends React.Component {
componentWillMount() {
const { attendanceStore: { currentItem, currentItemOperate } } = this.props;
if (currentItemOperate == "add") {
this.state = {
request: {
fieldName: "",
fieldType: "1",
enableStatus: 0,
description: ""
}
};
} else {
this.state = {
request: currentItem
};
}
}
handleChange(params) {
const { request } = this.state;
let result = { ...request, ...params };
this.setState({ request: result });
}
convertFieldType = (fileTypeStr) => {
if (fileTypeStr == "数值") {
return "1";
} else if (fileTypeStr == "文本") {
return "2";
} else if (fileTypeStr == "1" || fileTypeStr == "2") {
return fileTypeStr;
}
return "";
};
render() {
const options = [
{
key: "1",
selected: true,
showname: "数值"
},
{
key: "2",
selected: false,
showname: "文本"
}
];
const { request } = this.state;
const { fieldName, fieldType, enableStatus, description } = request;
let fileTypeKey = this.convertFieldType(fieldType);
const { attendanceStore: { currentItemOperate } } = this.props;
return (
<WeaDialog style={{ width: 600 }} visible={this.props.visible} onCancel={this.props.onCancel}
title="新建考勤自定义字段"
initLoadCss
className="itemManageModalWrapper"
buttons={[
<Button type="primary" onClick={() => {
currentItemOperate == "add" ? this.props.onSave(this.state.request) :
this.props.onUpdate(this.state.request);
}
}>保存</Button>
]}>
<div style={{ padding: "16px 120px" }}>
<Row gutter={[10, 10]} style={{ marginBottom: "10px" }}>
<Col span={8}>
字段名称
</Col>
<Col span={16}>
<WeaInput viewAttr={3} style={{ width: "200px" }} value={fieldName} onChange={(v) => {
this.handleChange({ fieldName: v });
}}/>
</Col>
</Row>
<Row gutter={[10, 10]} style={{ marginBottom: "10px" }}>
<Col span={8}>
类型
</Col>
<Col span={16}>
<WeaSelect style={{ width: "200px" }} options={options} value={fileTypeKey}
onChange={(v) => this.handleChange({ fieldType: v })}
/>
</Col>
</Row>
<Row gutter={[10, 10]} style={{ marginBottom: "10px" }}>
<Col span={8}>
是否启用
</Col>
<Col span={16}>
<Switch checked={enableStatus == 1} onChange={(value) => {
let enableStatus = 0;
if (value) {
enableStatus = 1;
}
this.handleChange({ enableStatus });
}}/>
</Col>
</Row>
<Row gutter={[10, 10]} style={{ marginBottom: "10px" }}>
<Col span={8}>
备注
</Col>
<Col span={16}>
<WeaInput style={{ width: "200px" }} value={description} onChange={(v) => {
this.handleChange({ description: v });
}}/>
</Col>
</Row>
</div>
</WeaDialog>
);
}
}

View File

@ -1,195 +0,0 @@
import React from "react";
import { Button, Col, message, Row, Select } from "antd";
import moment from "moment";
import { WeaDatePicker, WeaDialog, WeaError, WeaInput, WeaSelect } from "ecCom";
import SelectItemModal from "../../../components/selectItemsModal";
import SelectItemsWrapper from "../../../components/selectItemsModal/selectItemsWrapper";
import { inject, observer } from "mobx-react";
import { notNull } from "../../../util/validate";
const { Option } = Select;
@inject("attendanceStore")
@observer
export default class RefereAttendFormModal extends React.Component {
constructor(props) {
super(props);
this.state = {
headerSetVisible: false,
inited: false,
request: {
salarySobId: "",
salaryYearMonth: moment(new Date()).format("YYYY-MM"),
employeeIds: [],
description: ""
}
};
}
handleHeaderSet() {
this.setState({ headerSetVisible: true });
this.props.onHeaderSet();
}
componentWillMount() {
const { attendanceStore: { getLedgerList } } = this.props;
getLedgerList().then(() => {
this.setState({
inited: true
});
});
}
// 请求参数改变事件
handleRequestChange(params) {
const { request } = this.state;
let result = { ...request, ...params };
this.setState({ request: result });
}
// 同步点击回调
handleSync() {
const { attendanceStore: { syncAttendanceRefer, checkOperation } } = this.props;
if (!this.validate()) {
return;
}
const { salarySobId, salaryYearMonth: salaryYearMonthStr } = this.state.request;
const payload = {
salaryYearMonthStr,
salarySobId
};
checkOperation(payload).then(({ status, data, errorMsg }) => {
if (status && data) {
syncAttendanceRefer(this.state.request).then(() => {
this.props.onCancel();
});
} else {
message.warning("已经核算过不可操作");
}
});
}
// 校验数据
validate() {
const { request } = this.state;
if (!notNull(request.salarySobId) && !notNull(request.salaryYearMonth)) {
this.refs.weaError.showError();
this.refs.weaError1.showError();
return false;
}
if (!notNull(request.salarySobId)) {
this.refs.weaError1.showError();
return false;
}
if (!notNull(request.salaryYearMonth)) {
this.refs.weaError.showError();
return false;
}
return true;
}
render() {
const { attendanceStore: { importLedgerList } } = this.props;
return (
<WeaDialog
initLoadCss
className="attendenceImportWrapper"
style={{ width: 600 }}
title="引用考勤数据"
buttons={[
<Button type="primary" onClick={() => {
this.handleSync();
}}>同步</Button>,
<Button type="default" onClick={() => {
this.handleHeaderSet();
}}>表头设置</Button>
]}
visible={this.props.visible}
onCancel={this.props.onCancel}>
<Row style={{ marginBottom: "10px" }}>
<Col span={8}>薪资所属月</Col>
<Col span={16}>
<WeaError
style={{ width: "100%" }}
tipPosition="bottom"
ref="weaError"
error="请选择薪资所属月">
<WeaDatePicker
viewAttr={3}
format="YYYY-MM"
style={{ width: "100%" }}
value={this.state.request.salaryYearMonth}
onChange={(value) => {
if (value === "") this.refs.weaError.showError();
this.handleRequestChange({ salaryYearMonth: value });
}}
/>
</WeaError>
</Col>
</Row>
<Row style={{ marginBottom: "10px" }}>
<Col span={8}>薪资账套</Col>
<Col span={16}>
{
this.state.inited &&
<WeaError
style={{ width: "100%" }}
tipPosition="bottom"
ref="weaError1"
error="请选择薪资账套">
<WeaSelect
viewAttr={3}
value={this.state.request.salarySobId}
style={{ width: "100%" }}
options={
_.isEmpty(importLedgerList) ? [{ key: "", showname: "" }] :
[{ key: "", showname: "" }, ..._.map(importLedgerList, it => ({
key: it.id,
showname: it.content
}))]
}
onChange={(value) => {
if (value === "") this.refs.weaError1.showError();
this.handleRequestChange({ salarySobId: value });
}}/>
</WeaError>
}
</Col>
</Row>
<Row style={{ marginBottom: "10px" }}>
<Col span={8}>备注</Col>
<Col span={16}>
<WeaInput style={{ width: "100%" }} value={this.state.request.description} onChange={(value) => {
this.handleRequestChange({ description: value });
}}/>
</Col>
</Row>
<SelectItemModal
onShowChecked={(value) => {
this.props.onShowChecked(value);
}}
onRestoreDefault={() => {
this.props.onRestoreDefault();
}}
onSetDefault={() => {
this.props.onSetDefault();
}}
onSearch={(value) => {
this.props.onSearch(value);
}}
onSave={(value) => {
this.props.onSave(value);
}}
visible={this.state.headerSetVisible} onCancel={() => this.setState({ headerSetVisible: false })}>
<SelectItemsWrapper items={this.props.items} title={"考勤模块"} onChange={(value) => {
this.props.onChange(value);
}}/>
</SelectItemModal>
</WeaDialog>
);
}
}

View File

@ -0,0 +1,27 @@
.tableRecordWrapper {
.accumulated {
.wea-form-cell-wrapper {
& > div:first-child {
height: 46px !important;
line-height: 46px;
}
& > div:nth-child(2) {
//width: 40% !important;
.wea-form-item-wrapper {
display: flex !important;
align-items: center;
.to {
padding: 0 10px;
}
}
}
& > div:last-child {
//width: 40% !important;
}
}
}
}

View File

@ -0,0 +1,207 @@
/*
* Author: 黎永顺
* name: 数据采集-详情记录页面
* Description:
* Date: 2023/2/20
*/
import React, { Component } from "react";
import { WeaSearchGroup } from "ecCom";
import UnifiedTable from "../../../components/UnifiedTable";
import { getTableRecordDate } from "../../../apis/cumDeduct";
import { DataCollectionDateRangePick, DataCollectionSelect, Input } from "../cumDeduct";
import "./index.less";
class TableRecord extends Component {
constructor(props) {
super(props);
this.state = {
loading: {
query: false
},
width: 0,
dataSource: [],
columns: [],
selectedRowKeys: [],
pageInfo: {
current: 1, pageSize: 10, total: 0
},
recordPayload: {
accumulatedSpecialAdditionalDeductionId: "",
otherTaxExemptDeductionId: "",
accumulatedSituationId: "",
specialAddDeductionId: "",
taxAgentId: "",
declareMonth: null,
taxYearMonth: null
}
};
}
componentDidMount() {
this.setState({ width: window.innerWidth });
this.convertData(this.props);
window.addEventListener("resize", this.resizeWidth);
}
componentWillUnmount() {
window.removeEventListener("resize", this.resizeWidth);
}
componentWillReceiveProps(nextProps, nextContext) {
this.convertData(nextProps);
}
resizeWidth = (e) => {
this.setState({ width: e.target.innerWidth });
};
convertData = (props) => {
const { recordPayload } = this.state;
const { record, screenParams } = props;
const modules = _.reduce(screenParams, (pre, cur) => (_.assign(pre, {
[cur]: record[cur],
[screenParams[0]]: record.id
})), {});
this.setState({
recordPayload: {
...recordPayload,
...modules
},
pageInfo: {
current: 1, pageSize: 10, total: 0
}
}, () => this.getTableRecordData());
};
getTableRecordData = () => {
const { loading, pageInfo, recordPayload } = this.state;
const { url, screenParams } = this.props;
const monthkey = screenParams[screenParams.length - 1];
const module = {
...pageInfo, ...recordPayload, url,
[monthkey]: Object.prototype.toString.call(recordPayload[monthkey]) === "[object Array]" ? _.compact(recordPayload[monthkey]) : recordPayload[monthkey]
};
this.setState({ loading: { ...loading, query: true } });
getTableRecordDate(_.pick(module, [...screenParams, "current", "pageSize", "url"])).then(({ status, data }) => {
this.setState({ loading: { ...loading, query: false } });
if (status) {
const { columns, list: dataSource, pageNum: current, pageSize, total } = data;
this.setState({
pageInfo: { ...pageInfo, current, pageSize, total },
dataSource,
columns
});
}
}).catch(() => this.setState({ loading: { ...loading, query: false } }));
};
/*
* Author: 黎永顺
* Description: 详情页面-筛选操作
* Params:
* Date: 2023/2/20
*/
handleTablerecordScreen = ({ key, value }) => {
const { recordPayload } = this.state;
this.setState({
recordPayload: {
...recordPayload,
[key]: value
}
}, () => this.getTableRecordData());
};
handleResetSelectKeys = () => {
this.setState({
selectedRowKeys: [],
recordPayload: {
accumulatedSpecialAdditionalDeductionId: "",
otherTaxExemptDeductionId: "",
accumulatedSituationId: "",
specialAddDeductionId: "",
taxAgentId: "",
declareMonth: null,
taxYearMonth: null
}
});
};
render() {
const { className, screenParams, taxAgentOption, record } = this.props;
const { columns, dataSource, loading, selectedRowKeys, pageInfo, recordPayload, width } = this.state;
const rowSelection = {
selectedRowKeys,
onChange: (selectedRowKeys) => this.setState({ selectedRowKeys })
};
const pagination = {
...pageInfo,
showTotal: (total) => `${total}`,
pageSizeOptions: ["10", "20", "50", "100"],
showSizeChanger: true,
showQuickJumper: true,
onShowSizeChange: (current, pageSize) => {
this.setState({
pageInfo: { ...pageInfo, current, pageSize }
}, () => {
this.getTableRecordData();
});
},
onChange: (current) => {
this.setState({
pageInfo: { ...pageInfo, current }
}, () => {
this.getTableRecordData();
});
}
};
const items = screenParams.length === 1 ? [
{
com: Input({ value: record.username })
}
] : [
{
com: Input({ value: record.username })
},
{
com: DataCollectionDateRangePick({
label: "税款所属期",
range: recordPayload[screenParams[screenParams.length - 1]] || [],
onChange: this.handleTablerecordScreen,
key: screenParams[screenParams.length - 1]
})
},
{
com: DataCollectionSelect({
label: "个税扣缴义务人",
value: !_.isNil(recordPayload.taxAgentId) ? recordPayload.taxAgentId.toString() : "",
options: [{ key: "", showname: "全部" }, ...taxAgentOption],
onChange: this.handleTablerecordScreen,
key: "taxAgentId"
})
}
];
return (
<div className="tableRecordWrapper">
{
!_.isEmpty(screenParams) &&
<WeaSearchGroup className={className} showGroup needTigger={false} items={items} col={width > 1280 ? 3 : 2}/>
}
<UnifiedTable
rowKey="id"
rowSelection={rowSelection}
columns={_.map(columns, item => ({
...item,
render: (text) => {
return <span className="ellipsis" title={text}> {text} </span>;
}
}))}
dataSource={dataSource}
pagination={pagination}
loading={loading.query}
xWidth={columns.length * 180}
/>
</div>
);
}
}
export default TableRecord;

View File

@ -211,6 +211,186 @@ export const specialModalColumns = [
key: "seriousIllnessTreatment"
}
];
export const otherModalColumns = [
{
title: "姓名",
dataIndex: "username",
key: "username"
},
{
title: "个税扣缴义务人",
dataIndex: "taxAgentName",
key: "taxAgentName"
},
{
title: "部门",
dataIndex: "departmentName",
key: "departmentName"
},
{
title: "手机号",
dataIndex: "mobile",
key: "mobile"
},
{
title: "工号",
dataIndex: "jobNum",
key: "jobNum"
},
{
title: "证件号码",
dataIndex: "idNo",
key: "idNo"
},
{
title: "入职日期",
dataIndex: "hiredate",
key: "hiredate"
},
{
title: "商业健康保险",
dataIndex: "businessHealthyInsurance",
key: "businessHealthyInsurance"
},
{
title: "税延养老保险",
dataIndex: "taxDelayEndowmentInsurance",
key: "taxDelayEndowmentInsurance"
},
{
title: "其他",
dataIndex: "otherDeduction",
key: "otherDeduction"
},
{
title: "准予扣除的捐赠额",
dataIndex: "deductionAllowedDonation",
key: "deductionAllowedDonation"
}
];
export const situationModalColumns = [
{
title: "姓名",
dataIndex: "username",
key: "username"
},
{
title: "个税扣缴义务人",
dataIndex: "taxAgentName",
key: "taxAgentName"
},
{
title: "部门",
dataIndex: "departmentName",
key: "departmentName"
},
{
title: "手机号",
dataIndex: "mobile",
key: "mobile"
},
{
title: "工号",
dataIndex: "jobNum",
key: "jobNum"
},
{
title: "证件号码",
dataIndex: "idNo",
key: "idNo"
},
{
title: "入职日期",
dataIndex: "hiredate",
key: "hiredate"
},
{
title: "累计收入额",
dataIndex: "addUpIncome",
key: "addUpIncome"
},
{
title: "累计减除费用",
dataIndex: "addUpSubtraction",
key: "addUpSubtraction"
},
{
title: "累计社保个人合计",
dataIndex: "addUpSocialSecurityTotal",
key: "addUpSocialSecurityTotal"
},
{
title: "累计公积金个人合计",
dataIndex: "addUpAccumulationFundTotal",
key: "addUpAccumulationFundTotal"
},
{
title: "累计子女教育",
dataIndex: "addUpChildEducation",
key: "addUpChildEducation"
},
{
title: "累计继续教育",
dataIndex: "addUpContinuingEducation",
key: "addUpContinuingEducation"
},
{
title: "累计住房贷款利息",
dataIndex: "addUpHousingLoanInterest",
key: "addUpHousingLoanInterest"
},
{
title: "累计住房租金",
dataIndex: "addUpHousingRent",
key: "addUpHousingRent"
},
{
title: "累计赡养老人",
dataIndex: "addUpSupportElderly",
key: "addUpSupportElderly"
},
{
title: "累计企业(职业)年金及其他福利",
dataIndex: "addUpEnterpriseAndOther",
key: "addUpEnterpriseAndOther"
},
{
title: "累计其他免税扣除",
dataIndex: "addUpOtherDeduction",
key: "addUpOtherDeduction"
},
{
title: "累计免税收入",
dataIndex: "addUpTaxExemptIncome",
key: "addUpTaxExemptIncome"
},
{
title: "累计准予扣除的捐赠额",
dataIndex: "addUpAllowedDonation",
key: "addUpAllowedDonation"
},
{
title: "累计减免税额",
dataIndex: "addUpTaxSavings",
key: "addUpTaxSavings"
},
{
title: "累计已预扣预缴税额",
dataIndex: "addUpAdvanceTax",
key: "addUpAdvanceTax"
},
{
title: "累计婴幼儿照护",
dataIndex: "addUpInfantCare",
key: "addUpInfantCare"
},
{
title: "累计大病医疗",
dataIndex: "addUpIllnessMedical",
key: "addUpIllnessMedical"
}
];
export const dataSource = [];
@ -219,66 +399,73 @@ export const dataCollectCondition = [
{
items: [
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpChildEducation"],
fieldcol: 14,
label: "累计子女教育",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpContinuingEducation"],
fieldcol: 14,
label: "累计继续教育",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpHousingLoanInterest"],
fieldcol: 14,
label: "累计住房贷款利息",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpHousingRent"],
fieldcol: 14,
label: "累计住房租金",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpSupportElderly"],
fieldcol: 14,
label: "累计赡养老人",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpIllnessMedical"],
fieldcol: 14,
label: "累计大病医疗",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpInfantCare"],
fieldcol: 14,
label: "累计婴幼儿照护",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
}
],

View File

@ -0,0 +1,48 @@
/*
* Author: 黎永顺
* name: 数据采集-导入选项
* Description:
* Date: 2023/2/20
*/
import React, { Component } from "react";
import { WeaSearchGroup } from "ecCom";
import { DataCollectionDatePicker, DataCollectionSelect } from "../index";
class ImportFormCom extends Component {
screenChange = ({ key, value }) => {
const { onChangeImportForm } = this.props;
onChangeImportForm(key, value);
};
render() {
const { taxAgentOption = [], declareMonth, taxAgentId } = this.props;
const items = [
{
com: DataCollectionDatePicker({
label: "税款所属期",
value: declareMonth,
onChange: this.screenChange,
key: "declareMonth",
screen: false
})
},
{
com: DataCollectionSelect({
label: "个税扣缴义务人",
value: taxAgentId || "",
onChange: this.screenChange,
options: [{ key: "", showname: "全部" }, ...taxAgentOption],
key: "taxAgentId"
})
}
];
!declareMonth && items.shift();
_.isNil(taxAgentId) && items.pop();
return (
<WeaSearchGroup className="screenWrapper" showGroup needTigger={false} items={items}
col={2}/>
);
}
}
export default ImportFormCom;

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,15 @@
.cumDeductWrapper {
.cumDeductWrapper, .payrollDistributionWrapper {
.wea-new-top-content {
display: flex;
flex-direction: column;
overflow: hidden;
.tableWrapper {
flex: 1;
overflow: hidden;
}
}
.weaTabWrapper {
position: relative;
@ -34,18 +45,18 @@
}
.linkWapper {
a {
color: #4d7ad8;
margin-right: 8px;
}
//a {
// color: #4d7ad8;
// margin-right: 8px;
//}
i {
cursor: pointer;
}
a:hover {
text-decoration: none;
}
//a:hover {
// text-decoration: none;
//}
}
}

View File

@ -65,287 +65,177 @@ export const columns = [
key: "title"
}
];
export const modalColumns = [
{
title: "姓名",
dataIndex: "username",
key: "username"
},
{
title: "个税扣缴义务人",
dataIndex: "taxAgentName",
key: "taxAgentName"
},
{
title: "部门",
dataIndex: "departmentName",
key: "departmentName"
},
{
title: "手机号",
dataIndex: "mobile",
key: "mobile"
},
{
title: "工号",
dataIndex: "jobNum",
key: "jobNum"
},
{
title: "证件号码",
dataIndex: "idNo",
key: "idNo"
},
{
title: "入职日期",
dataIndex: "hiredate",
key: "hiredate"
},
{
title: "累计收入额",
dataIndex: "addUpIncome",
key: "addUpIncome"
},
{
title: "累计减除费用",
dataIndex: "addUpSubtraction",
key: "addUpSubtraction"
},
{
title: "累计社保个人合计",
dataIndex: "addUpSocialSecurityTotal",
key: "addUpSocialSecurityTotal"
},
{
title: "累计公积金个人合计",
dataIndex: "addUpAccumulationFundTotal",
key: "addUpAccumulationFundTotal"
},
{
title: "累计子女教育",
dataIndex: "addUpChildEducation",
key: "addUpChildEducation"
},
{
title: "累计继续教育",
dataIndex: "addUpContinuingEducation",
key: "addUpContinuingEducation"
},
{
title: "累计住房贷款利息",
dataIndex: "addUpHousingLoanInterest",
key: "addUpHousingLoanInterest"
},
{
title: "累计住房租金",
dataIndex: "addUpHousingRent",
key: "addUpHousingRent"
},
{
title: "累计赡养老人",
dataIndex: "addUpSupportElderly",
key: "addUpSupportElderly"
},
{
title: "累计企业(职业)年金及其他福利",
dataIndex: "addUpEnterpriseAndOther",
key: "addUpEnterpriseAndOther"
},
{
title: "累计其他免税扣除",
dataIndex: "addUpOtherDeduction",
key: "addUpOtherDeduction"
},
{
title: "累计免税收入",
dataIndex: "addUpTaxExemptIncome",
key: "addUpTaxExemptIncome"
},
{
title: "累计准予扣除的捐赠额",
dataIndex: "addUpAllowedDonation",
key: "addUpAllowedDonation"
},
{
title: "累计减免税额",
dataIndex: "addUpTaxSavings",
key: "addUpTaxSavings"
},
{
title: "累计已预扣预缴税额",
dataIndex: "addUpAdvanceTax",
key: "addUpAdvanceTax"
},
{
title: "累计婴幼儿照护",
dataIndex: "addUpInfantCare",
key: "addUpInfantCare"
},
{
title: "累计大病医疗",
dataIndex: "addUpIllnessMedical",
key: "addUpIllnessMedical"
}
];
export const dataSource = [];
export const dataCollectCondition = [
{
items: [
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpIncome"],
fieldcol: 14,
label: "累计收入额",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpSubtraction"],
fieldcol: 14,
label: "累计减除费用",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpSocialSecurityTotal"],
fieldcol: 14,
label: "累计社保个人合计",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpAccumulationFundTotal"],
fieldcol: 14,
label: "累计公积金个人合计",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpChildEducation"],
fieldcol: 14,
label: "累计子女教育",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpContinuingEducation"],
fieldcol: 14,
label: "累计继续教育",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpHousingLoanInterest"],
fieldcol: 14,
label: "累计住房贷款利息",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpHousingRent"],
fieldcol: 14,
label: "累计住房租金",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpSupportElderly"],
fieldcol: 14,
label: "累计赡养老人",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpIllnessMedical"],
fieldcol: 14,
label: "累计大病医疗",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpEnterpriseAndOther"],
fieldcol: 14,
label: "累计企业(职业)年金及其他福利",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpOtherDeduction"],
fieldcol: 14,
label: "累计其他免税扣除",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpTaxExemptIncome"],
fieldcol: 14,
label: "累计免税收入",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpAllowedDonation"],
fieldcol: 14,
label: "累计准予扣除的捐赠额",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpTaxSavings"],
fieldcol: 14,
label: "累计减免税额",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpAdvanceTax"],
fieldcol: 14,
label: "累计已预扣预缴税额",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
},
{
conditionType: "INPUT",
conditionType: "INPUTNUMBER",
domkey: ["addUpInfantCare"],
fieldcol: 14,
label: "累计婴幼儿照护",
labelcol: 8,
value: "",
precision: 2,
viewAttr: 2
}
],
@ -353,11 +243,10 @@ export const dataCollectCondition = [
defaultshow: true
}
];
export const taxOptions = [
{
key: "01",
showname: "一月",
showname: "一月"
},
{
key: "02",
@ -402,5 +291,5 @@ export const taxOptions = [
{
key: "12",
showname: "十二月"
},
}
];

View File

@ -1,201 +0,0 @@
import React from "react";
import { Col, DatePicker, Row } from "antd";
import { inject, observer } from "mobx-react";
import { WeaTable } from "ecCom";
import "./editSlideContent.less";
import moment from "moment";
const { MonthPicker } = DatePicker;
let emptyItem = {
incomeLowerLimit: "0.00",
incomeUpperLimit: "0.00",
dutyFreeValue: "0.00",
dutyFreeRate: "0.00",
taxableIncomeLl: "0.00",
taxableIncomeUl: "0.00",
taxRate: "0.00",
taxDeduction: "0.00"
};
@inject("cumSituationStore", "taxAgentStore")
@observer
export default class EditSlideContent extends React.Component {
constructor(props) {
super(props);
this.state = {
taxAgentId: "",
startDate: "",
endDate: "",
editable:
this.props.editable === undefined ? "true" : this.props.editable
};
}
componentWillMount() {
// 初始化渲染页面
const {
taxAgentStore: { fetchTaxAgentOption }
} = this.props;
fetchTaxAgentOption();
}
addItem() {
const {
taxRateStore: { setDataSource }
} = this.props;
let dataSource = [...this.props.taxRateStore.dataSource];
let indexNum = 1;
if (dataSource.length > 0) {
indexNum = dataSource[dataSource.length - 1].indexNum + 1;
}
let item = { ...emptyItem };
item.indexNum = indexNum;
dataSource.push(item);
setDataSource(dataSource);
}
fetchCumDeductDetailList(param) {
const { cumSituationStore } = this.props;
const { getCumDeductDetailList, currentRecord } = cumSituationStore;
getCumDeductDetailList(currentRecord.id, param);
}
// 日期格式变化加载数据
handleFetchCumDeductDetailList(startDate, endDate, taxAgentId) {
let declareMonth = [];
if (startDate != "" && startDate != undefined) {
declareMonth.push(startDate);
}
if (endDate != "" && endDate != undefined) {
declareMonth.push(endDate);
}
let item = {
taxAgentId: taxAgentId
};
if (declareMonth.length != 0) {
item.taxYearMonth = declareMonth;
}
this.fetchCumDeductDetailList(item);
}
onSelectChange = (val) => {
const { onChangeSlideSelectKey } = this.props;
onChangeSlideSelectKey && onChangeSlideSelectKey(val);
};
render() {
const { cumSituationStore } = this.props;
const { startDate, endDate, taxAgentId } = this.state;
const {
getCumDeductDetailList,
currentRecord,
slideColumns,
slidePageObj,
slideTableDataSource,
setSlidePageObj,
slideLoading
} = cumSituationStore;
const declareMonth = [startDate, endDate];
const pagination = {
current: slidePageObj.current,
pageSize: slidePageObj.pageSize,
total: slidePageObj.total,
showTotal: (total) => `${total}`,
showSizeChanger: true,
onShowSizeChange(current, pageSize) {
setSlidePageObj({ ...slidePageObj, current, pageSize });
getCumDeductDetailList(currentRecord.id, {
...slidePageObj,
current,
pageSize,taxAgentId:currentRecord.taxAgentId,
declareMonth: _.filter(declareMonth, item => item)
});
},
onChange(current) {
setSlidePageObj({
...slidePageObj,
current,taxAgentId:currentRecord.taxAgentId,
pageSize: slidePageObj.pageSize
});
getCumDeductDetailList(currentRecord.id, {
...slidePageObj,
current,
pageSize,
declareMonth: _.filter(declareMonth, item => item)
});
}
};
const newColumns = _.map([...slideColumns], (item) => ({ ...item }));
const rowSelection = {
selectedRowKeys: this.props.slideSelectedKey,
onChange: this.onSelectChange
};
return (
<div className="cumDeductSlide">
<Row className="topLabelBar">
<Col span={4}>
<span className="username">{currentRecord.username}</span>
</Col>
<Col span={12}>
<span className="formLabel">申报月份</span>
<div className="weaRangePickerWrapper">
<div className="monthPickerWrapper">
<MonthPicker
width={100}
format="YYYY-MM"
value={startDate}
onChange={(v) => {
let startDate = "";
if (v != "" && v != undefined) {
startDate = moment(v).format("YYYY-MM");
}
this.setState({ startDate });
this.handleFetchCumDeductDetailList(
startDate,
endDate,
taxAgentId
);
}}
/>
</div>
<span className="betweenLable"></span>
<div className="monthPickerWrapper">
<MonthPicker
width={100}
value={endDate}
onChange={(v) => {
let endDate = "";
if (v != "" && v != undefined) {
endDate = moment(v).format("YYYY-MM");
}
this.setState({ endDate });
this.handleFetchCumDeductDetailList(
startDate,
endDate,
currentRecord.taxAgentId
);
}}
/>
</div>
</div>
</Col>
</Row>
<div>
<WeaTable
rowKey="id"
rowSelection={rowSelection}
columns={newColumns}
dataSource={slideTableDataSource}
pagination={pagination}
loading={slideLoading}
scroll={{ x: newColumns ? newColumns.length * 150 : 900 }}
/>
</div>
</div>
);
}
}

View File

@ -1,22 +0,0 @@
.cumDeductSlide {
.topLabelBar {
padding: 10px 20px;
height: 40px;
line-height: 40px;
margin-bottom: 10px;
}
.formLabel {
margin-right: 10px;
}
.weaRangePickerWrapper {
display: inline-block;
.monthPickerWrapper {
width: 100px;
display: inline-block;
}
.betweenLable {
margin-left: 10px;
margin-right: 10px;
}
}
}

Some files were not shown because too many files have changed in this diff Show More