Merge branch 'feature/0612-工资单水印设置' into develop

This commit is contained in:
黎永顺 2023-06-15 18:30:42 +08:00
commit 3cad250c73
20 changed files with 1015 additions and 22 deletions

View File

@ -367,3 +367,16 @@ export const getAvailableSalaryItemSet = (params) => {
export const salaryBillSendSum = (params) => {
return postFetch("/api/bs/hrmsalary/salaryBill/send/sum", 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

@ -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

@ -35,6 +35,8 @@ 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";
@ -53,6 +55,7 @@ const SocialSecurityBenefits = (props) => props.children;
const DataAcquisition = (props) => props.children;
// mySalary 我的薪资福利
// mySalaryView 我的薪资福利-查看工资单
// socialSecurityBenefits 社保福利
// programme 社保福利方案
// archives 社保福利档案
@ -91,6 +94,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"
@ -135,6 +139,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

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: "",
@ -177,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 = {
@ -198,11 +198,11 @@ export default class SalaryDetail extends React.Component {
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;
@ -271,7 +271,8 @@ export default class SalaryDetail extends React.Component {
subtitle="编辑薪资"
editable={true}
showOperateBtn={showOperateBtn}
onSave={() => this.handleEditSlideSave()}
onSave={this.handleEditSlideSave}
loading={loading}
/>
}
content={<EditSalaryDetail id={this.recordId}/>}

View File

@ -1,7 +1,7 @@
import React from "react";
import { inject, observer } from "mobx-react";
import { DatePicker } from "antd";
import { WeaNewScroll, WeaTop } from "ecCom";
import { WeaLocaleProvider, WeaNewScroll, WeaTop } from "ecCom";
import { renderNoright } from "../../util"; // 渲染form数据的方法因为多个页面都会使用所以抽的公共方法在util中
import CustomTab from "../../components/customTab";
import moment from "moment";
@ -10,6 +10,7 @@ import Authority from "./authority";
import CustomPaginationTable from "../../components/customPaginationTable";
import "./index.less";
const { getLabel } = WeaLocaleProvider;
const { RangePicker } = DatePicker;
@inject("mySalaryStore")
@ -61,9 +62,8 @@ export default class MySalary extends React.Component {
dataIndex: "operate",
render: (text, record) => {
return (
<a onClick={() => {
this.handleView(record);
}}>查看</a>
<a target="_blank"
href={`${window.location.origin}/spa/hrmSalary/static/index.html#/main/hrmSalary/mySalary/${record.id}`}>{getLabel(33564, "查看")}</a>
);
}
});

View File

@ -0,0 +1,39 @@
/*
* Author: 黎永顺
* name: 查看我的薪资-工资单
* Description:
* Date: 2023/6/14
*/
import React, { Component } from "react";
import { inject, observer } from "mobx-react";
import { toJS } from "mobx";
import ComputerTemplate from "../payroll/templatePreview/computerTemplate";
import "../payroll/templatePreview/index.less";
@inject("mySalaryStore")
@observer
class MySalaryView extends Component {
componentDidMount() {
const { mySalaryStore: { getMySalaryBill }, params: { salaryInfoId } } = this.props;
getMySalaryBill(Number(salaryInfoId));
}
render() {
const { mySalaryStore: { mySalaryBill } } = this.props;
const employeeInformation = mySalaryBill.employeeInformation && toJS(mySalaryBill.employeeInformation);
const salaryGroups = mySalaryBill.salaryGroups && toJS(mySalaryBill.salaryGroups);
return (
<div>
<div className="templatePreview">
<ComputerTemplate
isPreview
salaryTemplateShowSet={JSON.stringify(mySalaryBill.salaryTemplate)}
salaryItemSet={!_.isEmpty(salaryGroups) ? JSON.stringify([employeeInformation, ...salaryGroups]) : []}
/>
</div>
</div>
);
}
}
export default MySalaryView;

View File

@ -0,0 +1,14 @@
import { WeaLocaleProvider } from "ecCom";
const getLabel = WeaLocaleProvider.getLabel;
export const commonVariables = [
{ id: "HRM_Name", name: getLabel(111, "当前操作者姓名")},
{ id: "HRM_Num", name: getLabel(111, "当前操作者编号")},
{ id: "HRM_Mobile", name: getLabel(111, "当前操作者移动电话")},
{ id: "HRM_Email", name: getLabel(111, "当前操作者电子邮件")},
{ id: "HRM_CurrentOperatorId", name: getLabel(111, "当前操作者人员id")},
{ id: "HRM_Department", name: getLabel(111, "当前操作者部门")},
{ id: "HRM_SecondDepartment", name: getLabel(111, "分部")},
{ id: "HRM_CurrentDate", name: getLabel(111, "当前日期")},
{ id: "HRM_CurrentTime", name: getLabel(111, "当前时间")},
];

View File

@ -46,3 +46,130 @@
}
}
}
.waterMarkSetWrapper {
& > .rodal {
right: 25% !important;
}
}
.waterMarkSetWrapper, .wmContentWrapper {
.rodal {
.rodal-dialog {
& > div:nth-child(2) {
height: calc(100% - 52px) !important;
padding-bottom: 0 !important;
}
}
}
.waterMark-select-header {
padding: 0 5px;
}
.wea-transfer-list-wrapper {
.transfer-tree {
li {
cursor: pointer;
margin: 10px 0;
}
}
}
.wea-slide-modal-content {
padding-bottom: 65px;
}
.wmTitle {
float: left;
margin-left: 16px;
}
.slideBottom {
display: flex;
justify-content: flex-end;
padding: 16px 25px;
border-top: 1px solid #e5e5e5;
position: absolute;
width: 100%;
bottom: 0;
background: #f4f4f4;
button:first-child {
margin-right: 16px;
}
}
.waterMarkWrapper {
padding-top: 16px;
}
.wmContGroup {
.wea-title {
border: 1px solid #e5e5e5;
border-bottom: none;
}
.wea-content {
padding-top: 0;
}
.content-box {
padding: 16px;
.ant-col-18 {
height: 319px;
}
}
.wea-form-cell-wrapper {
border-bottom: none;
}
}
.mt16 {
.wea-form-cell-wrapper {
border: 1px solid #e5e5e5;
}
}
.wea-form-cell-wrapper {
border: 1px solid #e5e5e5;
border-bottom: none;
}
.wea-form-item {
padding: 5px 16px;
border-bottom: 1px solid #e5e5e5;
}
.textSetting {
display: flex;
align-items: center;
margin-top: 7px;
min-width: 200px;
.icon-coms-Flow-setting {
font-size: 16px;
color: #666;
cursor: pointer;
}
img {
margin-left: 5px;
}
}
.previewBtn {
cursor: pointer;
color: #2db7f5;
position: relative;
margin-left: 10px;
}
.txtPrew {
margin-left: 20px !important;
}
}

View File

@ -0,0 +1,191 @@
/*
* Author: 黎永顺
* name: 水印设置-弹框
* Description:
* Date: 2023/6/13
*/
import React, { Component } from "react";
import {
WeaError,
WeaFormItem,
WeaInputNumber,
WeaLocaleProvider,
WeaSearchGroup,
WeaSelect,
WeaSlideModal
} from "ecCom";
import { Button } from "antd";
import ImageUploadList from "../../../components/upload";
import WmContentSetModal from "./wmContentSetModal";
import "./index.less";
const getLabel = WeaLocaleProvider.getLabel;
class WaterMarkSetModal extends Component {
constructor(props) {
super(props);
this.state = {
wmClassify: "text", wmNoTransparent: 0,
wmRotate: 0, wmImg: null, wmcontSet: {
visible: false, textSet: {}
}
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible && nextProps.visible) {
const { watermarkSetting } = nextProps;
const {
wmClassify = "text",
wmNoTransparent = 0,
wmRotate = 0,
wmImg,
wmOriginText,
wmHeight,
wmWidth,
pureWmText,
wmSelectedFieldIds,
wmText
} = watermarkSetting;
if (wmClassify === "text") {
this.setState({
wmClassify, wmNoTransparent, wmRotate,
wmcontSet: {
...this.state.wmcontSet, textSet: wmOriginText ? {
wmOriginText, wmHeight, wmWidth, pureWmText, wmSelectedFieldIds, wmText
} : {}
}
});
} else {
this.setState({
wmClassify, wmNoTransparent, wmRotate, wmImg
});
}
}
}
handleCustomSave = () => {
const { wmClassify, wmImg, wmRotate, wmNoTransparent, wmcontSet } = this.state;
if ((wmClassify === "text" && _.isEmpty(wmcontSet.textSet)) || (wmClassify !== "text" && !wmImg)) {
this.refs.watermarkContError.showError();
return;
}
if (wmClassify === "text") {
this.props.onChange({
wmSetting: {
wmClassify, ...wmcontSet.textSet,
wmNoTransparent, wmRotate
}
});
} else {
this.props.onChange({
wmSetting: {
wmClassify, wmImg,
wmNoTransparent, wmRotate
}
});
}
this.props.onClose();
};
render() {
const { wmClassify, wmNoTransparent, wmRotate, wmImg, wmcontSet } = this.state;
return (
<WeaSlideModal
{...this.props} className="waterMarkSetWrapper"
title={<span className="wmTitle">{getLabel(111, "水印设置")}</span>}
direction="right" top={20} width={800} height={400}
measureT={"%"} measureX="px" measureY="px"
content={
<React.Fragment>
<WeaSearchGroup showGroup needTigger={false} className="waterMarkWrapper">
<WeaFormItem label={getLabel(111, "水印类型")} labelCol={{ span: 5 }} wrapperCol={{ span: 10 }}>
<WeaSelect
value={wmClassify} detailtype={3}
options={[
{ key: "text", showname: getLabel(111, "文本") },
{ key: "image", showname: getLabel(111, "图片") }
]}
onChange={wmClassify => this.setState({ wmClassify })}
/>
</WeaFormItem>
<WeaFormItem label={getLabel(111, "水印类型")} labelCol={{ span: 5 }} wrapperCol={{ span: 10 }}>
{
wmClassify === "text" ?
<WeaError tipPosition="bottom" ref="watermarkContError" error={getLabel(385869, "此项必填")}>
<div className="textSetting">
<i className="icon-coms-Flow-setting"
onClick={() => this.setState({ wmcontSet: { ...wmcontSet, visible: true } })}/>
{
_.isEmpty(wmcontSet.textSet) ? <img src="/images/BacoError_wev9.png" alt=""/> :
<span className="previewBtn txtPrew"><i className="icon-coms-Selected" style={{
"color": "#093",
"marginRight": "5px"
}} onClick={() => {
window.open(`${window.location.origin}/spa/hrmSalary/static/index.html#/main/hrmSalary/payroll/watermark/preview`, "_blank");
}}/> 预览</span>
}
</div>
</WeaError> :
<WeaError tipPosition="bottom" ref="watermarkContError" error={getLabel(385869, "此项必填")}>
<div className="textSetting">
<ImageUploadList onChange={wmImg => this.setState({ wmImg }, () => {
window.localStorage.setItem("wmSetting", JSON.stringify({
wmSetting: {
wmClassify, wmRotate, wmNoTransparent,
...this.state.wmImg
}
}));
})} wmImg={wmImg}/>
{
!wmImg ? <img src="/images/BacoError_wev9.png" alt=""/> :
<span className="previewBtn" onClick={() => {
window.open(`${window.location.origin}/spa/hrmSalary/static/index.html#/main/hrmSalary/payroll/watermark/preview`, "_blank");
}}>预览</span>
}
</div>
</WeaError>
}
</WeaFormItem>
<WeaFormItem label={getLabel(111, "不透明(百分比)")} labelCol={{ span: 5 }} wrapperCol={{ span: 10 }}>
<WeaInputNumber
min={0} max={80} precision={2} value={wmNoTransparent}
onChange={wmNoTransparent => this.setState({ wmNoTransparent })}
/>
</WeaFormItem>
<WeaFormItem label={getLabel(111, "旋转角度(逆时针)")} labelCol={{ span: 5 }} wrapperCol={{ span: 10 }}>
<WeaInputNumber
min={0} max={360} precision={2} value={wmRotate}
onChange={wmRotate => this.setState({ wmRotate })}
/>
</WeaFormItem>
</WeaSearchGroup>
<div className="slideBottom">
<Button type="primary" onClick={this.handleCustomSave}>{getLabel(111, "确定")}</Button>
<Button type="ghost" onClick={this.props.onClose}>{getLabel(111, "取消")}</Button>
</div>
{/* 水印内容设置弹框*/}
<WmContentSetModal {...wmcontSet}
onClose={textSet => this.setState({
wmcontSet: {
...wmcontSet,
visible: false,
textSet
}
}, () => {
window.localStorage.setItem("wmSetting", JSON.stringify({
wmSetting: {
wmClassify, wmRotate, wmNoTransparent,
...this.state.wmcontSet.textSet
}
}));
})}
/>
</React.Fragment>
}
/>
);
}
}
export default WaterMarkSetModal;

View File

@ -0,0 +1,188 @@
/*
* Author: 黎永顺
* name: 水印内容设置
* Description:
* Date: 2023/6/14
*/
import React, { Component } from "react";
import {
WeaFormItem,
WeaHelpfulTip,
WeaInputNumber,
WeaInputSearch,
WeaLocaleProvider,
WeaRichText,
WeaSearchGroup,
WeaSlideModal,
WeaTransfer
} from "ecCom";
import { Button, Col, message, Row } from "antd";
import { commonVariables } from "./config";
import "./index.less";
const getLabel = WeaLocaleProvider.getLabel;
const WeaTransferList = WeaTransfer.list;
class WmContentSetModal extends Component {
constructor(props) {
super(props);
this.state = {
wmWidth: 100,
wmHeight: 100,
wmOriginText: "",
searchV: ""
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.visible !== this.props.visible) {
this.setState({
wmWidth: nextProps.textSet.wmWidth || 100,
wmHeight: nextProps.textSet.wmHeight || 100,
wmOriginText: nextProps.textSet.wmOriginText || ""
});
} else {
this.setState({
wmWidth: 100,
wmHeight: 100,
wmOriginText: "",
searchV: ""
});
}
}
handleSaveWMContent = () => {
const html = this.refs.TextContentRichText.getData().replace(/\n/ig, "");
if (!html) {
message.warning(getLabel(111, "请输入水印内容!"));
return;
}
const { wmWidth, wmHeight } = this.state;
this.props.onClose({
wmWidth, wmHeight,
wmSelectedFieldIds: this.getHtmlAttrVal(html),
pureWmText: this.convertToPlain(html),
wmOriginText: html, wmText: this.convertToWMText(html)
});
};
convertToWMText = (html) => {
_.map(commonVariables, item => {
const { id, name } = item;
const reg = eval("/" + name + "/g");
html = html.replace(reg, `$${id}`).replace(/ data-id=\"(.*?)\"/g, "");
});
return html.replace(/ contenteditable="false"/g, "");
};
getHtmlAttrVal = (html) => {
let attrAndValueArr = html.match(/ data-id=\"(.*?)\"/g);
let valueArr = []; // 放所有该属性的值
if (!_.isEmpty(attrAndValueArr)) {
for (let i = 0; i < attrAndValueArr.length; i++) {
valueArr.push(attrAndValueArr[i].replace(/ data-id=/g, "").replace(/\"/g, ""));
}
}
return valueArr;
};
convertToPlain = (html) => {
let tempDivElement = document.createElement("div");
tempDivElement.innerHTML = html;
return tempDivElement.textContent || tempDivElement.innerText || "";
};
renderItem = (item = {}) => {
return <span>{item.name}</span>;
};
selectHeader() {
return (
<div className={"waterMark-select-header"}>
<WeaInputSearch onSearchChange={(v) => {
this.setState({ searchV: v });
}}/>
</div>
);
}
render() {
const { wmWidth, wmHeight, wmOriginText, searchV } = this.state;
const ckConfig = {
toolbar: [
{ name: "paragraph", items: ["JustifyLeft", "JustifyCenter", "JustifyRight"] },
{ name: "styles", items: ["Font", "FontSize"] },
{ name: "colors", items: ["TextColor"] }
],
removePlugins: "resize",
height: 280
};
const tempOptions = _.filter(commonVariables, (item) => {
const { name } = item;
let flag = true;
if (searchV && name) {
flag = name.indexOf(searchV) > -1;
}
return flag;
});
return (
<WeaSlideModal
{...this.props} className="wmContentWrapper" onClose={() => this.props.onClose(this.props.textSet)}
title={<span className="wmTitle">{getLabel(111, "水印内容设置")}</span>}
direction="right" top={-10} width={800} height={480}
measureT={"%"} measureX="px" measureY="px"
content={
<React.Fragment>
<WeaSearchGroup
title={<span><span style={{ marginRight: 10 }}>{getLabel(111, "水印格式设置")}</span><WeaHelpfulTip
title={getLabel(111, "水印最小100px*100px")} placement="topLeft"/></span>}
showGroup needTigger={false} className="waterMarkWrapper wmContGroup">
<WeaFormItem label={getLabel(111, "水印宽度") + "px"} labelCol={{ span: 5 }} wrapperCol={{ span: 10 }}>
<WeaInputNumber
min={100} precision={3} value={wmWidth}
onChange={wmWidth => this.setState({ wmWidth })}
/>
</WeaFormItem>
<WeaFormItem label={getLabel(111, "水印高度") + "px"} labelCol={{ span: 5 }} wrapperCol={{ span: 10 }}>
<WeaInputNumber
min={100} precision={3} value={wmHeight}
onChange={wmHeight => this.setState({ wmHeight })}
/>
</WeaFormItem>
</WeaSearchGroup>
<WeaSearchGroup
title={getLabel(111, "内容")}
showGroup needTigger={false} className="waterMarkWrapper wmContGroup mt16">
<Row className="content-box" gutter={10}>
<Col span={18}>
<WeaRichText ckConfig={ckConfig} value={wmOriginText} ref={"TextContentRichText"}/>
</Col>
<Col span={6}>
<WeaTransferList
header={this.selectHeader()}
data={tempOptions}
renderItem={this.renderItem}
checkedCb={(keys) => {
let result = _.filter(commonVariables, (item) => item.id === keys[0]);
if (result && result.length > 0) {
this.refs.TextContentRichText.insertHTML(`&nbsp;<span contenteditable="false" data-id="${result[0].id}">${result[0].name}</span>&nbsp;`);
}
}}
height={280}
checkedKeys={[]}
/>
</Col>
</Row>
</WeaSearchGroup>
<div className="slideBottom">
<Button type="primary"
onClick={this.handleSaveWMContent}>{getLabel(111, "保存")}</Button>
<Button type="ghost"
onClick={() => this.props.onClose(this.props.textSet)}>{getLabel(111, "取消")}</Button>
</div>
</React.Fragment>
}
/>
);
}
}
export default WmContentSetModal;

View File

@ -3,8 +3,16 @@ import { inject, observer } from "mobx-react";
import { toJS } from "mobx";
import { Button, DatePicker, message, Modal } from "antd";
import moment from "moment";
import { WeaHelpfulTip, WeaInputSearch, WeaNewScroll, WeaSelect, WeaSlideModal, WeaTop } from "ecCom";
import { renderLoading } from "../../util"; // 渲染form数据的方法因为多个页面都会使用所以抽的公共方法在util中
import {
WeaHelpfulTip,
WeaInputSearch,
WeaLocaleProvider,
WeaNewScroll,
WeaSelect,
WeaSlideModal,
WeaTop
} from "ecCom";
import { renderLoading } from "../../util";
import CustomTab from "../../components/customTab";
import StepSlide from "../../components/stepSlide";
import BaseInformForm from "./stepForm/baseInformForm";
@ -12,11 +20,13 @@ import ShowSettingForm from "./stepForm/showSettingForm";
import SlideModalTitle from "../../components/slideModalTitle";
import TemplateSettingList from "./templateSettingList";
import TemplateSettingForm from "./stepForm/tmplateSettingForm";
import TemplateBaseSettings from "./templateBaseSettings";
import CopyModal from "./copyModal";
import SalarySendList from "./SalarySendList";
import { getReplenishForm } from "../../apis/payroll";
import "../dataAcquisition/cumDeduct/index.less";
const getLabel = WeaLocaleProvider.getLabel;
const { MonthPicker } = DatePicker;
@inject("payrollStore", "taxAgentStore")
@ -38,7 +48,8 @@ export default class Payroll extends React.Component {
templateCurrentId: "",
copyModalVisible: false,
startDate: moment(new Date()).startOf("year").format("YYYY-MM"),
endDate: moment(new Date()).startOf("month").format("YYYY-MM")
endDate: moment(new Date()).startOf("month").format("YYYY-MM"),
loading: false
};
this.recordId = "";
this.salaryYearMonth = [moment(new Date()).startOf("year").format("YYYY-MM"), moment(new Date()).startOf("month").format("YYYY-MM")];
@ -256,6 +267,10 @@ export default class Payroll extends React.Component {
{
title: "工资单模板设置",
viewcondition: "1"
},
{
title: getLabel(111, "工资单模板基础设置"),
viewcondition: "2"
}
];
const renderRightOperation = () => {
@ -333,6 +348,11 @@ export default class Payroll extends React.Component {
}}/>
</div>
);
} else if (this.state.selectedKey === "2") {
return <Button type="primary"
onClick={() => this.baseSetRef.salaryBillBaseSetSave()}
loading={this.state.loading}
>{getLabel(111, "保存")}</Button>;
}
};
const steps = ["基础设置", "正常核算工资单模板", "补发工资单模版"];
@ -405,6 +425,13 @@ export default class Payroll extends React.Component {
onDelete={(record) => this.handleTemplateListDelete(record)}
/>
}
{
this.state.selectedKey === "2" &&
<TemplateBaseSettings
ref={dom => this.baseSetRef = dom}
onChangeLoading={loading => this.setState({ loading })}
/>
}
</WeaNewScroll>
</div>
</WeaTop>

View File

@ -0,0 +1,22 @@
.waterMarkWrapper {
.wea-form-cell-wrapper {
border: 1px solid #e5e5e5;
border-bottom: none;
}
.wea-form-item {
padding: 5px 16px;
border-bottom: 1px solid #e5e5e5;
.waterMarkTitle {
margin-left: 10px;
cursor: pointer;
color: #2db7f5;
position: absolute;
display: inline-block;
width: 48px;
top: 50%;
margin-top: -10px;
}
}
}

View File

@ -0,0 +1,104 @@
/*
* Author: 黎永顺
* name: 工资单模板基础设置
* Description:
* Date: 2023/6/12
*/
import React, { Component } from "react";
import { WeaCheckbox, WeaFormItem, WeaLocaleProvider, WeaSearchGroup, WeaSelect } from "ecCom";
import { message } from "antd";
import { getSalaryBillBaseSetForm, salaryBillBaseSetSave } from "../../apis/payroll";
import WaterMarkSetModal from "./components/waterMarkSetModal";
import "./index.less";
const getLabel = WeaLocaleProvider.getLabel;
class TemplateBaseSettings extends Component {
constructor(props) {
super(props);
this.state = {
watermarkStatus: "0",
watermark: "DEFAULT",
wmSetting: null,
watermarkSet: {
visible: false, watermarkSetting: null
}
};
}
componentDidMount() {
this.getSalaryBillBaseSetForm();
}
getSalaryBillBaseSetForm = () => {
const { watermarkSet } = this.state;
getSalaryBillBaseSetForm().then(({ status, data }) => {
if (status) {
const { watermarkStatus, watermark = "DEFAULT", watermarkSetting } = data;
this.setState({
watermark, watermarkStatus: watermarkStatus ? "1" : "0",
watermarkSet: {
...watermarkSet,
watermarkSetting
}
}, () => window.localStorage.setItem("wmSetting", JSON.stringify({ wmSetting: watermarkSetting })));
}
});
};
salaryBillBaseSetSave = () => {
const { watermark, watermarkStatus, wmSetting } = this.state;
let payload = { watermarkStatus: watermarkStatus === "1" };
if (watermarkStatus === "1") payload = { ...payload, watermark };
if (!_.isNil(wmSetting)) payload = { ...payload, watermark, ...wmSetting };
this.props.onChangeLoading(true);
salaryBillBaseSetSave(payload).then(({ status, errormsg }) => {
this.props.onChangeLoading(false);
if (status) {
message.success(getLabel(111, "保存成功"));
this.getSalaryBillBaseSetForm();
} else {
message.error(errormsg || getLabel(111, "保存失败"));
}
}).catch(() => this.props.onChangeLoading(false));
};
render() {
const { watermarkStatus, watermark, watermarkSet } = this.state;
return (
<WeaSearchGroup title={getLabel(111, "水印设置")} showGroup needTigger className="waterMarkWrapper">
<WeaFormItem label={getLabel(111, "启用水印")} labelCol={{ span: 2 }} wrapperCol={{ span: 4 }}>
<WeaCheckbox value={watermarkStatus} display="switch"
onChange={watermarkStatus => this.setState({ watermarkStatus, watermark: "DEFAULT" })}/>
</WeaFormItem>
{
watermarkStatus === "1" &&
<WeaFormItem label={getLabel(111, "水印类型")} labelCol={{ span: 2 }} wrapperCol={{ span: 4 }}>
<WeaSelect
value={watermark}
options={[
{ key: "DEFAULT", showname: getLabel(111, "系统默认水印") },
{ key: "CUSTOM", showname: getLabel(111, "自定义水印") }
]}
onChange={watermark => this.setState({ watermark })}
/>
{
watermark === "CUSTOM" &&
<span className="waterMarkTitle" onClick={() => this.setState({
watermarkSet: {
...watermarkSet,
visible: true
}
})}>{getLabel(111, "水印设置")}</span>
}
<WaterMarkSetModal {...watermarkSet}
onClose={() => this.setState({ watermarkSet: { ...watermarkSet, visible: false } })}
onChange={wmSetting => this.setState({ wmSetting })}
/>
</WeaFormItem>
}
</WeaSearchGroup>
);
}
}
export default TemplateBaseSettings;

View File

@ -0,0 +1,56 @@
/*
* Author: 黎永顺
* name: 水印预览
* Description:
* Date: 2023/6/15
*/
import React, { Component } from "react";
import { salaryBillBaseSetPreviewWaterMark } from "../../apis/payroll";
import { WeaTools } from "ecCom";
const { watermark } = WeaTools;
class WatermarkPreview extends Component {
componentDidMount() {
const wmSetting = window.localStorage.getItem("wmSetting");
wmSetting && this.salaryBillBaseSetPreviewWaterMark(JSON.parse(wmSetting));
}
salaryBillBaseSetPreviewWaterMark = (payload) => {
salaryBillBaseSetPreviewWaterMark(payload).then(({ status, data }) => {
if (status) {
watermark({
text: data,
src: "",
rotate: `-15`,
alpha: 0.15,
interval: 2000,
intervalCheck: true,
clickCheck: true
});
}
});
};
render() {
return (
<div>
<h1 style={{ textAlign: "center" }}>水印预览效果</h1>
<p
style={{ fonsSize: 14 }}>水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果</p>
<p
style={{ fonsSize: 14 }}>水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果</p>
<p
style={{ fonsSize: 14 }}>水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果</p>
<p
style={{ fonsSize: 14 }}>水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果</p>
<p
style={{ fonsSize: 14 }}>水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果</p>
<p
style={{ fonsSize: 14 }}>水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果水印预览效果</p>
</div>
);
}
}
export default WatermarkPreview;

View File

@ -86,7 +86,7 @@ class ReportContent extends Component {
this.setState({ loading: true });
reportStatisticsReportGetData(payload).then(({ status, data }) => {
this.setState({ loading: false });
if (status) {
if (status && id.toString() === data.reportId.toString()) {
const { countResult, columns, pageInfo: { list } } = data;
this.setState({
countResult,

View File

@ -135,9 +135,15 @@ class Index extends Component {
<i
className="icon-coms02-currency"
title={getLabel(111, "统计数据范围及规则设置")}
onClick={() => this.setState({
statisticalPayload: { visible: true, id: report.id, dimension: report.dimensionId }
})}
onClick={() => {
if (this.reportRef.state.loading) {
message.info(getLabel(111, "列表正在加载中,请稍后"))
} else {
this.setState({
statisticalPayload: { visible: true, id: report.id, dimension: report.dimensionId }
});
}
}}
/>
<i className="icon-coms-export" onClick={this.exportData} title={getLabel(111, "导出")}/>
</div>

View File

@ -34,7 +34,15 @@ export default class SystemSalaryItemModal extends React.Component {
if (status) {
const { columns, list: dataSource, pageNum: current, pageSize, total } = data;
this.setState({
columns, dataSource,
columns: _.map(columns, item => {
return {
...item,
render: (text) => {
return <span className="ellipsis" title={text}>{text}</span>;
}
};
}),
dataSource,
pageInfo: { ...pageInfo, current, pageSize, total }
});
}

View File

@ -54,7 +54,7 @@ export const editConditions = [
conditionType: "INPUTNUMBER",
domkey: ["sortedIndex"],
fieldcol: 14,
label: "序",
label: "显示顺序",
labelcol: 6,
value: "",
viewAttr: 2,
@ -92,7 +92,7 @@ export const decentralizationConditions = [
conditionType: "INPUTNUMBER",
domkey: ["sortedIndex"],
fieldcol: 14,
label: "序",
label: "显示顺序",
labelcol: 6,
value: "",
viewAttr: 2,

View File

@ -1,11 +1,12 @@
import { action, observable } from "mobx";
import { message } from "antd";
import { WeaForm, WeaLogView, WeaTableNew } from "comsMobx";
import { WeaLocaleProvider } from "ecCom";
import { WeaLocaleProvider, WeaTools } from "ecCom";
import moment from "moment";
import * as API from "../apis/mySalaryBenefits";
const { watermark } = WeaTools;
const { LogStore } = WeaLogView;
const getLabel = WeaLocaleProvider.getLabel;
const { TableStore } = WeaTableNew;
@ -165,6 +166,45 @@ export class MySalaryStore {
return new Promise((resolve, reject) => {
API.mySalaryBill(payload).then(res => {
if (res.status) {
const { salaryTemplate } = res.data;
const { salaryWatermark } = salaryTemplate;
if (watermark && salaryWatermark) {
const { wmSetting } = JSON.parse(salaryWatermark);
const {
wmText,
wmHeight: height,
wmWidth: width,
wmNoTransparent,
wmRotate,
wmImg,
wmClassify
} = wmSetting;
if (wmClassify === "text") {
watermark({
text: wmText,
width,
height,
src: "",
rotate: `-${wmRotate || 15}`,
alpha: wmNoTransparent / 100 || 0.15,
interval: 2000,
intervalCheck: true,
clickCheck: true
});
} else {
watermark({
text: "",
width,
height,
src: wmImg[0].imgSrc,
rotate: `-${wmRotate || 15}`,
alpha: wmNoTransparent / 100 || 0.15,
interval: 2000,
intervalCheck: true,
clickCheck: true
});
}
}
this.mySalaryBill = res.data;
resolve(res.data);
} else {