产品-薪酬统计分析

This commit is contained in:
黎永顺 2023-04-17 17:32:16 +08:00
parent 167caa4f5b
commit 4929ff4db5
12 changed files with 230 additions and 72 deletions

View File

@ -43,3 +43,7 @@ export const getEncryptProgress = params => {
export const operateTaxDeclarationFunction = (params) => {
return postFetch('/api/bs/hrmsalary/sys/operateTaxDeclarationFunction', params);
}
//薪酬统计维度下拉列表
export const reportGetForm = params => {
return WeaTools.callApi('/api/bs/hrmsalary/report/statistics/report/getForm', 'GET', params);
}

View File

@ -1,3 +1,6 @@
import { WeaLocaleProvider } from "ecCom";
const { getLabel } = WeaLocaleProvider;
export const condition = [
{
items: [
@ -8,7 +11,7 @@ export const condition = [
conditionType: "SELECT",
domkey: ["dimType"],
fieldcol: 14,
label: "维度类型",
label: getLabel(111, "维度类型"),
labelcol: 6,
options: [],
detailtype: 3,
@ -20,7 +23,7 @@ export const condition = [
conditionType: "SELECT",
domkey: ["setting4Qualitative"],
fieldcol: 14,
label: "统计维度",
label: getLabel(111, "统计维度"),
labelcol: 6,
options: [],
rules: "required|string",
@ -31,7 +34,7 @@ export const condition = [
conditionType: "INPUT",
domkey: ["dimName"],
fieldcol: 14,
label: "统计维度名称",
label: getLabel(111, "统计维度名称"),
labelcol: 6,
value: "",
rules: "required|string",
@ -42,7 +45,7 @@ export const condition = [
conditionType: "SELECT",
domkey: ["dimCode"],
fieldcol: 14,
label: "分组所属字段",
label: getLabel(111, "分组所属字段"),
labelcol: 6,
options: [],
viewAttr: 2,
@ -54,13 +57,44 @@ export const condition = [
conditionType: "TEXTAREA",
domkey: ["remark"],
fieldcol: 14,
label: "描述",
label: getLabel(111, "描述"),
labelcol: 6,
value: "",
viewAttr: 2
}
],
title: "基础设置",
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: [],
viewAttr: 2,
helpfulTip: "",
hide: true
}
],
title: "",
defaultshow: true
}
];

View File

@ -5,7 +5,7 @@
* Date: 2023/4/11
*/
import React, { Component } from "react";
import { WeaDialog, WeaSearchGroup } from "ecCom";
import { WeaDialog, WeaSearchGroup, WeaLocaleProvider } from "ecCom";
import { Button, message, Modal } from "antd";
import { dimensionGetForm, dimensionSave } from "../../../apis/statistics";
import { getSearchs } from "../../../util";
@ -13,6 +13,7 @@ import GroupSpacingEditTable from "./groupSpacingEditTable";
import GroupIndividualEditTable from "./groupIndividualEditTable";
import "../index.less";
const { getLabel } = WeaLocaleProvider;
const keyObj = {
"RATION_GROUP_SPACING": "setting4RationGroupSpacing",
"RATION_GROUP_INDIVIDUAL": "setting4RationGroupIndividual"
@ -88,8 +89,8 @@ class DimensionSlide extends Component {
if (dimType === "QUALITATIVE") {
if (!setting4Qualitative || !extraParams.dimName) {
Modal.warning({
title: "信息确认",
content: "必要信息不完整,红色*为必填项!"
title: getLabel(111, "信息确认"),
content: getLabel(111, "必要信息不完整,红色*为必填项!")
});
return;
}
@ -99,8 +100,8 @@ class DimensionSlide extends Component {
} else {
if (!extraParams.dimName) {
Modal.warning({
title: "信息确认",
content: "必要信息不完整,红色*为必填项!"
title: getLabel(111, "信息确认"),
content: getLabel(111, "必要信息不完整,红色*为必填项!")
});
return;
}
@ -108,7 +109,7 @@ class DimensionSlide extends Component {
const { setting4RationGroupSpacing } = this.state;
const bool = _.every(setting4RationGroupSpacing, it => it.startValue !== "" && it.endValue !== "" && it.startValue <= it.endValue);
if (_.isEmpty(setting4RationGroupSpacing) || !bool) {
message.warning("请完善分组设置相关数据!分组设置不能为空,起始值结束值必填,且起始值需小于结束值!");
message.warning(getLabel(111, "请完善分组设置相关数据!分组设置不能为空,起始值结束值必填,且起始值需小于结束值!"));
return;
} else {
payload = {
@ -126,7 +127,7 @@ class DimensionSlide extends Component {
const { setting4RationGroupIndividual } = this.state;
const bool = _.every(setting4RationGroupIndividual, it => it.value !== "");
if (_.isEmpty(setting4RationGroupIndividual) || !bool) {
message.warning("请完善分组设置相关数据!分组设置不能为空,且数值必填");
message.warning(getLabel(111, "请完善分组设置相关数据!分组设置不能为空,且数值必填"));
return;
} else {
payload = {
@ -140,11 +141,11 @@ class DimensionSlide extends Component {
dimensionSave(payload).then(({ status, errormsg }) => {
this.setState({ loading: false });
if (status) {
message.success("保存成功");
message.success(getLabel(111, "保存成功"));
onCancel(true);
this.props.form.resetForm();
} else {
message.error(errormsg || "保存失败");
message.error(errormsg || getLabel(111, "保存失败"));
}
}).catch(() => this.setState({ loading: false }));
};
@ -175,15 +176,15 @@ class DimensionSlide extends Component {
className="dimensionSlideWrapper"
title={
<div className="dimensionTitle">
<span>新建统计维度</span>
<Button type="primary" onClick={this.handleSave} loading={loading}>保存</Button>
<span>{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="分组设置" showGroup>
<WeaSearchGroup title={getLabel(111, "分组设置")} showGroup>
{
dimType === "RATION_GROUP_SPACING" &&
<GroupSpacingEditTable onChange={this.handleConvertGroupDatasource}

View File

@ -5,11 +5,12 @@
* Date: 2023/4/11
*/
import React, { Component } from "react";
import { WeaTable } from "ecCom";
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) {
@ -46,15 +47,15 @@ class DimensionTable extends Component {
};
dimensionDelete = (payload) => {
Modal.confirm({
title: "信息确认",
content: "确认要删除吗?",
title: getLabel(111, "信息确认"),
content: getLabel(111, "确认要删除吗?"),
onOk: () => {
dimensionDelete(payload).then(({ status, errormsg }) => {
if (status) {
message.success("删除成功");
message.success(getLabel(111, "删除成功"));
this.dimensionList();
} else {
message.error(errormsg || "删除失败");
message.error(errormsg || getLabel(111, "删除失败"));
}
});
}
@ -66,7 +67,7 @@ class DimensionTable extends Component {
const { onEdit } = this.props;
const pagination = {
...pageInfo,
showTotal: total => `${total}`,
showTotal: total => `${getLabel(111, "共")} ${total} ${getLabel(111, "条")}`,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ["10", "20", "50", "100"],
@ -82,16 +83,17 @@ class DimensionTable extends Component {
}
};
const columns = [
{ dataIndex: "dimName", title: "统计维度" },
{ dataIndex: "remark", title: "描述" },
{ dataIndex: "dimType", title: "维度类型" },
{ dataIndex: "dimName", title: getLabel(111, "统计维度") },
{ dataIndex: "remark", title: getLabel(111, "描述") },
{ dataIndex: "dimType", title: getLabel(111, "维度类型") },
{
dataIndex: "operate", title: "操作",
dataIndex: "operate", title: getLabel(111, "操作"),
render: (_, record) => {
return (
<span className="space10">
<a href="javascript: void(0);" onClick={() => onEdit(record.id)}>编辑</a>
<a href="javascript: void(0);" onClick={() => this.dimensionDelete([record.id])}>删除</a>
<a href="javascript: void(0);" onClick={() => onEdit(record.id)}>{getLabel(111, "编辑")}</a>
<a href="javascript: void(0);"
onClick={() => this.dimensionDelete([record.id])}>{getLabel(111, "删除")}</a>
</span>
);
}

View File

@ -5,8 +5,9 @@
* Date: 2023/4/12
*/
import React, { Component } from "react";
import { WeaTableEdit } from "ecCom";
import { WeaLocaleProvider, WeaTableEdit } from "ecCom";
const { getLabel } = WeaLocaleProvider;
class GroupIndividualEditTable extends Component {
constructor(props) {
super(props);
@ -31,7 +32,7 @@ class GroupIndividualEditTable extends Component {
const { dataSource } = this.state;
const columns = [
{
title: "分组设置值",
title: getLabel(111, "分组设置值"),
dataIndex: "value",
key: "value",
com: [

View File

@ -5,7 +5,9 @@
* Date: 2023/4/12
*/
import React, { Component } from "react";
import { WeaTableEdit } from "ecCom";
import { WeaLocaleProvider, WeaTableEdit } from "ecCom";
const { getLabel } = WeaLocaleProvider;
class GroupSpacingEditTable extends Component {
constructor(props) {
@ -37,7 +39,7 @@ class GroupSpacingEditTable extends Component {
const { dataSource } = this.state;
const columns = [
{
title: "起始值",
title: getLabel(111, "起始值"),
dataIndex: "startValue",
key: "startValue",
com: [
@ -45,19 +47,19 @@ class GroupSpacingEditTable extends Component {
]
},
{
title: "含",
title: getLabel(111, "含"),
dataIndex: "includeStart",
key: "includeStart",
com: [
{
type: "CHECKBOX",
key: "includeStart",
otherParams: { content: "含" }
otherParams: { content: getLabel(111, "含") }
}
]
},
{
title: "至",
title: getLabel(111, "至"),
dataIndex: "to",
key: "to",
com: [
@ -65,7 +67,7 @@ class GroupSpacingEditTable extends Component {
]
},
{
title: "结束值",
title: getLabel(111, "结束值"),
dataIndex: "endValue",
key: "endValue",
com: [
@ -73,14 +75,14 @@ class GroupSpacingEditTable extends Component {
]
},
{
title: "含",
title: getLabel(111, "含"),
dataIndex: "includeEnd",
key: "includeEnd",
com: [
{
type: "CHECKBOX",
key: "includeEnd",
otherParams: { content: "含" }
otherParams: { content: getLabel(111, "含") }
}
]
}
@ -88,7 +90,7 @@ class GroupSpacingEditTable extends Component {
return (
<WeaTableEdit
draggable={true} deleteConfirm columns={columns}
datas={_.map(dataSource, item => ({ ...item, to: "至" }))}
datas={_.map(dataSource, item => ({ ...item, to: getLabel(111, "至") }))}
showCopy={false} onChange={this.handleChangeTableData}
/>
);

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,42 @@
/*
* Author: 黎永顺
* name: 统计表
* Description:
* Date: 2023/4/17
*/
import React, { Component } from "react";
import { WeaLocaleProvider } from "ecCom";
import { Col, Row } from "antd";
import "../index.less";
const { getLabel } = WeaLocaleProvider;
class ReportList extends Component {
render() {
const { dataSource } = this.props;
return (
<Row gutter={16} className="reportRow">
{
_.isEmpty(dataSource) ? <div className="empty">{getLabel(111, "暂无数据")}</div> :
_.map(dataSource, it => {
return <Col className="gutter-row" span={6}>
<div className="card-item">
<div className="left"><i className="icon-coms-fa"/></div>
<div className="center">
<span className="reportName"></span>
<div className="dimension">
<div className="label">{getLabel(111, "统计维度")}</div>
<div className="value"></div>
</div>
</div>
<div className="right"><i className="icon-coms-more"/></div>
</div>
</Col>;
})
}
</Row>
);
}
}
export default ReportList;

View File

@ -5,15 +5,17 @@
* Date: 2023/4/10
*/
import React, { Component } from "react";
import { WeaDialog } from "ecCom";
import { WeaDialog, WeaLocaleProvider } from "ecCom";
import { Button } from "antd";
import "../index.less";
const { getLabel } = WeaLocaleProvider;
class StatisticsModal extends Component {
render() {
const { typeKey, onCancel } = this.props;
const buttons = typeKey === "addReport" ? [
<Button type="primary">保存并进行详细统计设置</Button>
<Button type="primary">{getLabel(111, "保存并进行详细统计设置")}</Button>
] : [];
return (
<WeaDialog

View File

@ -6,16 +6,20 @@
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { WeaInputSearch, WeaReqTop } from "ecCom";
import { WeaInputSearch, WeaLocaleProvider, WeaReqTop } from "ecCom";
import { Button } from "antd";
import { condition } from "./components/conditions";
import { commonEnumList } from "../../apis/ruleconfig";
import { condition, reportCondition } from "./components/conditions";
import { commonEnumList, reportGetForm } from "../../apis/ruleconfig";
import { dimensionGetForm } from "../../apis/statistics";
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 "./index.less";
const { getLabel } = WeaLocaleProvider;
@inject("taxAgentStore", "attendanceStore")
@observer
class Index extends Component {
@ -35,6 +39,15 @@ class Index extends Component {
};
}
componentDidMount() {
this.initReportFormCondition();
}
initReportFormCondition = () => {
reportGetForm({}).then(({ status, data }) => {
console.log(data, reportCondition);
});
};
initCondition = async () => {
const { attendanceStore: { statisticsForm } } = this.props;
const [dimTypeEnum, dimCodeList] = await Promise.all([this.commonEnumList(), this.dimensionGetForm()]);
@ -145,10 +158,10 @@ class Index extends Component {
const { modalReq } = this.state;
const title = key === "dimension" ?
<div className="dimensionTitle">
<span>统计维度管理</span>
<Button type="primary" onClick={() => this.handleAddDimension()}>新建统计维度</Button>
<span>{getLabel(111, "统计维度管理")}</span>
<Button type="primary" onClick={() => this.handleAddDimension()}>{getLabel(111, "新建统计维度")}</Button>
</div>
: "新建报表";
: getLabel(111, "新建报表");
this.setState({
modalReq: {
...modalReq,
@ -188,40 +201,45 @@ class Index extends Component {
};
render() {
const { taxAgentStore: { showOperateBtn }, attendanceStore: { statisticsForm } } = this.props;
const { taxAgentStore: { showOperateBtn }, attendanceStore: { statisticsForm, reportForm } } = this.props;
const { selectedKey, modalReq, slideReq, conditions } = this.state;
const buttons = [
<Button type="primary" onClick={() => this.handleReqBtnsClick("addReport")}>新建报表</Button>,
<Button type="ghost" onClick={() => this.handleReqBtnsClick("dimension")}>维度统计管理</Button>,
<WeaInputSearch placeholder="请输入报表名称" className="search"
<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"
onSearch={() => this.handleReqBtnsClick("search")}/>
];
const tabs = [
{ key: "statistics", title: "统计表" },
{ key: "detail", title: "员工明细" }
{ key: "statistics", title: getLabel(111, "统计表") },
{ key: "detail", title: getLabel(111, "员工明细") }
];
return (
<WeaReqTop
title="薪酬统计分析" icon={<i className="icon-coms-fa"/>}
title={getLabel(111, "薪酬统计分析")} icon={<i className="icon-coms-fa"/>}
iconBgcolor="#F14A2D" buttons={!showOperateBtn ? buttons.slice(-1) : buttons} buttonSpace={10}
showDropIcon={false} tabDatas={tabs} className="xc_tj_fx_wrapper"
selectedKey={selectedKey} onChange={selectedKey => this.setState({ selectedKey })}
selectedKey={selectedKey}
onChange={selectedKey => this.setState({ selectedKey }, () => this.state.selectedKey === "statistics" && this.initReportFormCondition())}
>
<div style={{ height: 2000, background: "#fff" }}>
<StatisticsModal {...modalReq} onCancel={this.handleCancel}>
{
modalReq.typeKey === "dimension" &&
<DimensionTable ref={dom => this.dimensionTableRef = dom}
onEdit={id => this.handleAddDimension(id)}
/>
}
</StatisticsModal>
<DimensionSlide
{...slideReq} onCancel={this.handleClose}
form={statisticsForm} condition={conditions}
initCondition={this.initCondition} onChangeCondition={this.handleChangeCondition}
/>
</div>
{this.state.selectedKey === "statistics" && <ReportList dataSource={[]}/>}
<StatisticsModal {...modalReq} onCancel={this.handleCancel}>
{
modalReq.typeKey === "dimension" &&
<DimensionTable ref={dom => this.dimensionTableRef = dom}
onEdit={id => this.handleAddDimension(id)}
/>
}
{
modalReq.typeKey === "addReport" &&
<ReportForm form={reportForm} condition={reportCondition}/>
}
</StatisticsModal>
<DimensionSlide
{...slideReq} onCancel={this.handleClose}
form={statisticsForm} condition={conditions}
initCondition={this.initCondition} onChangeCondition={this.handleChangeCondition}
/>
</WeaReqTop>
);
}

View File

@ -4,6 +4,38 @@
margin-right: 10px;
width: 220px;
}
.wea-new-top-req-content {
background: #FFF;
.reportRow {
.gutter-row {
margin-bottom: 16px;
border-radius: 6px;
.card-item {
border-radius: 6px;
display: flex;
.center {
display: flex;
flex-direction: column;
.dimension {
display: flex;
}
}
}
}
.empty {
font-size: 16px;
width: 100%;
text-align: center;
margin-top: 26px;
}
}
}
}
//统计维度弹框

View File

@ -7,4 +7,5 @@ export class AttendanceStore {
@observable refenceform = new WeaForm();
//薪酬统计 新增form
@observable statisticsForm = new WeaForm();
@observable reportForm = new WeaForm();
}