保存薪资项目

This commit is contained in:
MustangDeng 2022-03-29 17:33:54 +08:00
parent fbe5a338ef
commit 5734b1001c
13 changed files with 568 additions and 39 deletions

View File

@ -126,7 +126,14 @@ export const getLedgerItemGroupForm = params => {
//保存薪资帐套薪资项目
export const saveLedgerItem = params => {
return WeaTools.callApi('/api/bs/hrmsalary/salarysob/item/save', 'POST', params);
return fetch('/api/bs/hrmsalary/salarysob/item/save', {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
}).then(res => res.json())
}
//薪资帐套薪资项目详情
@ -158,3 +165,20 @@ export const updateLedgerRuleFormula = params => {
export const deleteLedgerRule = params => {
return WeaTools.callApi('/api/bs/hrmsalary/salarysob/checkrule/delete', 'POST', params);
}
// 薪资项目可选列表
export const listSalaryItem = params => {
return fetch('/api/bs/hrmsalary/salarysob/item/listSalaryItem', {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
}).then(res => res.json())
}
// 员工信息字段列表
export const empFieldList = () => {
return WeaTools.callApi('/api/bs/hrmsalary/salarysob/empField/list', 'GET', {});
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -0,0 +1,33 @@
import React from 'react'
import { Icon } from 'antd'
import closeIcon from './close.png'
export default class CanDeleteItem extends React.Component {
constructor(props) {
super(props)
this.state = {
showDelete: false
}
}
handleMouseOver() {
this.setState({showDelete: true})
}
handelMouseout() {
setTimeout(() => {
this.setState({showDelete: false})
}, 400)
}
render() {
const { title } = this.props;
return (
<div style={{display: "inline-block", paddingLeft: "10px", paddingRight: '10px'}} onMouseEnter={() => this.handleMouseOver()} onMouseLeave={() => this.handelMouseout()}>
<span className="selectedItem" onBlur>{title}</span>
{
this.state.showDelete && <Icon type="cross" style={{cursor: "pointer", marginLeft: "5px", fontWeight: '600'}} onClick={() => this.props.onDelete(this.props.item)}/>
}
</div>
)
}
}

View File

@ -58,9 +58,9 @@ export const slideStep2Columns= [
export const slideStep3Columns = [
{
title: "薪资项目",
dataIndex: 'title',
key: 'title',
title: "名称",
dataIndex: 'name',
key: 'name',
},
{
title: "规则",
@ -68,14 +68,9 @@ export const slideStep3Columns = [
key: 'title',
},
{
title: "来源",
dataIndex: 'title',
key: 'title',
},
{
title: "类型",
dataIndex: 'title',
key: 'title',
title: "个税申请表对应字段",
dataIndex: 'taxDeclarationColumn',
key: 'taxDeclarationColumn',
}
]

View File

@ -88,6 +88,15 @@ export default class Ledger extends React.Component {
}
// 编辑Slide保存按钮
handleEditSlideSave() {
const { selectedTab } = this.state;
const { ledgerStore: {saveLedgerItem}} = this.props;
if(selectedTab == 2) {
saveLedgerItem()
}
}
// 增加编辑功能重写columns绑定事件
getColumns = (columns) => {
let newColumns = '';
@ -194,6 +203,8 @@ export default class Ledger extends React.Component {
nextStep()
}
return (
<div className="mySalaryBenefitsWrapper">
<WeaRightMenu
@ -290,13 +301,13 @@ export default class Ledger extends React.Component {
height={100}
direction={'right'}
measure={'%'}
title={
<SlideModalTitle
subtitle={"编辑账套"}
tabs={[{title: '基础设置', key: 0}, {title: "关联人员", key: 1}, {title: "薪资项目", key: 2}, {title: '调薪计薪规则', key: 3}, {title: "校验规则", key: 4}]}
editable={true}
selectedTab={selectedTab}
onSave={() => this.handleEditSlideSave()}
subItemChange={
(item) => {this.setState({selectedTab: item.key})}
}

View File

@ -87,10 +87,9 @@
.userInfoSelected {
margin-top: 10px;
margin-bottom: 10px;
.selectedItem {
margin-right: 10px;
}
padding: 10px;
border: 1px solid #eee;
border-radius: 5px;
}
.tableItemWrapper {
margin-top: 10px;
@ -101,6 +100,10 @@
color: #2db7f5;
}
}
.itemTitle {
font-size: 14px;
font-weight: 500;
}
}
}

View File

@ -1,22 +1,56 @@
import React from 'react'
import { Button, Icon, Table } from 'antd'
import { WeaInputSearch, WeaHelpfulTip } from 'ecCom'
import { WeaInputSearch, WeaHelpfulTip, WeaSelect } from 'ecCom'
import { slideStep3Columns, dataSource} from './columns'
import "./index.less"
import AddCategoryModal from './step3/AddCategoryModal'
import { inject, observer } from 'mobx-react';
import { toJS } from 'mobx';
import CanMoveItem from './step3/canMoveItem'
import UserInfoSelected from './step3/UserInfoSelect'
@inject('ledgerStore')
@observer
export default class SalaryItemForm extends React.Component {
constructor(props) {
super(props)
this.state = {
addCategoryVisible: false
}
const { ledgerStore: { empFieldList }} = this.props;
empFieldList();
}
handleAddCategorySave(name) {
const {ledgerStore: {addItemGroup}} = this.props;
addItemGroup(name);
}
handleCanMoveItemChange(dataSource, item) {
const {ledgerStore: {itemGroups, setItemGroups}} = this.props;
let groups = [...itemGroups]
groups.map(i => {
if(i.tlitle == item.title) {
item.items = dataSource
}
})
setItemGroups(groups)
}
render() {
const {ledgerStore: {itemGroups, salaryItems, empBrowserList, setAddCategoryVisible, addCategoryVisible}} = this.props;
return (
<div className="salaryItemForm">
<div className="btnBar">
<div className="btns">
<Button type="default">新增分类</Button>
<Button type="default" onClick={() => {setAddCategoryVisible(true)}}>新增分类</Button>
<Button type="default" style={{marginLeft: "10px"}}>预览</Button>
</div>
<div className="searchInputWrapper">
<WeaInputSearch />
<WeaInputSearch style={{width: "150px"}} />
</div>
</div>
<div className="userInfoWrapper">
@ -35,25 +69,26 @@ export default class SalaryItemForm extends React.Component {
</div>
<div className="userInfoSelected">
<span className="selectedItem">个税扣缴义务人</span>
<span className="selectedItem">姓名</span>
<span className="selectedItem">部门</span>
<Icon type="plus" />
</div>
</div>
<UserInfoSelected />
<div className="tableItemWrapper">
<div>
<span className="itemTitle">未分类</span>
<span className="rightBtnsWrapper">
<Icon className="iconItem" type="minus-square"/>
<Icon className="iconItem" type="plus-square" />
<Icon type="down" />
</span>
</div>
<Table dataSource={dataSource} columns={slideStep3Columns}/>
</div>
{
itemGroups && itemGroups.map(item => {
item.items.map(i => {i.key = i.id})
return (
<CanMoveItem dataSource={item.items} title={item.name} onChange={(dataSource) => {this.handleCanMoveItemChange(dataSource, item)}}/>
)
}
)
}
{
addCategoryVisible &&
<AddCategoryModal onSave={(value) => {this.handleAddCategorySave(value)}} visible={addCategoryVisible} onCancel={() => {
setAddCategoryVisible(false)
}} />
}
</div>
)
}

View File

@ -0,0 +1,29 @@
import React from 'react'
import { Row, Col, Modal, Button } from 'antd'
import { WeaInput } from 'ecCom'
export default class AddCategoryModal extends React.Component {
constructor(props) {
super(props)
this.state = {
name: ""
}
}
render() {
return (
<Modal title="新增分类" footer={<Button type="primary" onClick={() => {this.props.onSave(this.state.name)}}>保存</Button>} width={600}
visible={this.props.visible} onCancel={() => {this.props.onCancel()}}
>
<div style={{padding: "20px"}}>
<Row>
<Col span={6}>分类名称</Col>
<Col span={18}>
<WeaInput value={this.state.name} onChange={(value) => {this.setState({name: value})}}/>
</Col>
</Row>
</div>
</Modal>
)
}
}

View File

@ -0,0 +1,99 @@
import React from 'react'
import { inject, observer } from 'mobx-react';
import { Modal, Button, message, Switch } from 'antd'
import { WeaInputSearch } from 'ecCom'
import { WeaTableNew } from "comsMobx"
import { toJS } from 'mobx'
const WeaTable = WeaTableNew.WeaTable;
@inject('ledgerStore')
@observer
export default class AddSalaryItemModal extends React.Component {
constructor(props) {
super(props)
this.state = {
searchValue: ""
}
}
componentWillMount() {
const { ledgerStore: {listSalaryItem}} = this.props;
listSalaryItem()
}
// 增加编辑功能重写columns绑定事件
getColumns = (columns) => {
let newColumns = '';
newColumns = columns.map(column => {
let newColumn = column;
newColumn.render = (text, record, index) => { //前端元素转义
let valueSpan = record[newColumn.dataIndex + "span"] !== undefined ? record[newColumn.dataIndex + "span"] : record[newColumn.dataIndex];
switch(newColumn.dataIndex) {
case "useDefault":
case "useInEmployeeSalary":
return <Switch checked={text == 1}/>
default:
return <div dangerouslySetInnerHTML={{ __html: valueSpan }} />
}
}
return newColumn;
});
return newColumns;
}
handleAdd() {
const { ledgerStore } = this.props;
const { salaryItemTableStore, addItemsToGroup, addExcludeIds } = ledgerStore
const selectedRowKeys = toJS(salaryItemTableStore.selectedRowKeys) || [];
if(selectedRowKeys.length == 0) {
message.warning("未选择条目")
}
let selectItems = []
salaryItemTableStore.datas.map(item => {
selectedRowKeys.map(key => {
if(item.id == key) {
selectItems.push(item)
}
})
})
addItemsToGroup(this.props.title, selectItems)
this.props.onCancel();
}
handleSearch = (value) => {
const { ledgerStore: {listSalaryItem}} = this.props
listSalaryItem(value)
}
render() {
const { ledgerStore } = this.props;
const { salaryItemTableStore } = ledgerStore
const { searchValue } = this.state;
return (
<Modal
visible={this.props.visible} onCancel={() => {this.props.onCancel()}} width={800}
footer={null}
>
<div style={{height: "47px", lineHeight: '47px'}}>
<span style={{marginLeft: "10px", fontSize: '14px'}}>添加薪资项目</span>
<div style={{float: "right", marginRight: "40px"}}>
<Button type="primary" style={{marginRight: '10px'}} onClick={() => {this.handleAdd()}}>添加</Button>
<WeaInputSearch value={searchValue} onChange={(value) => {this.setState({searchValue: value})}} onSearch={(value) => {this.handleSearch(value)}}/>
</div>
</div>
<div style={{margin: "10px"}}>
<WeaTable // table内部做了loading加载处理页面就不需要再加了
comsWeaTableStore={salaryItemTableStore} // table store
hasOrder={true} // 是否启用排序
needScroll={true} // 是否启用table内部列表滚动将自适应到父级高度
getColumns={this.getColumns}
// onOperatesClick={this.onOperatesClick.bind(this)}
/>
</div>
</Modal>
)
}
}

View File

@ -0,0 +1,70 @@
import React from 'react'
import { Icon, message } from "antd"
import { WeaSelect } from 'ecCom'
import { inject, observer } from 'mobx-react';
import CanDeleteItem from '../../../components/canDeleteItem'
@inject('ledgerStore')
@observer
export default class UserInfoSelected extends React.Component {
constructor(props) {
super(props)
this.state = {
list: [],
showSelect: false
}
}
handleSelectChange(value) {
let list = [...this.state.list]
const { ledgerStore: {empBrowserList}} = this.props;
let selectedItem = {}
empBrowserList.map(item => {
if(item.key == value) {
selectedItem = item
}
})
let flag = false;
list.map(item => {
if(item.key == value) {
flag = true
}
})
if(!flag) {
list.push(selectedItem)
}
if(flag) {
message.warning("该信息已存在")
}
const { ledgerStore: {empFields, addEmpFields}} = this.props;
addEmpFields(value)
this.setState({list, showSelect: false})
}
handleItemDelete(item) {
let list = [...this.state.list]
this.setState({list: list.filter(i => item.key != i.key)})
}
render() {
const { ledgerStore: {empBrowserList} } = this.props;
return (
<div className="userInfoSelected">
{
this.state.list.map(item => (
<CanDeleteItem title={item.showname} item={item} onDelete={(item) => {
this.handleItemDelete(item)
}}/>
))
}
<Icon type="plus" style={{marginLeft: "10px", marginRight: "10px", cursor: "pointer"}} onClick={() => {this.setState({showSelect: true})}}/>
{
this.state.showSelect && empBrowserList.length > 0 && <WeaSelect showSearch options={empBrowserList} onChange={(value) => {
this.handleSelectChange(value)
}}/>
}
</div>
)
}
}

View File

@ -0,0 +1,83 @@
import React from 'react'
import { Icon, Table, message, Modal } from 'antd'
import { slideStep3Columns } from '../columns'
import AddSalaryItemModal from './AddSalaryItemModal'
import { inject, observer } from 'mobx-react';
@inject('ledgerStore')
@observer
export default class CanMoveItem extends React.Component {
constructor(props) {
super(props)
this.state = {
addItemVisible: false,
showContent: true,
selectedRowKeys: []
}
}
handleTiggleContent() {
this.setState({showContent: !this.state.showContent})
}
onSelectChange = selectedRowKeys => {
this.setState({ selectedRowKeys });
};
// 删除
handleDelete = () => {
const { selectedRowKeys } = this.state;
if(selectedRowKeys.length == 0) {
message.warning("为选择任何条目")
return
}
Modal.confirm({
title: '信息确认',
content: '确认删除',
onOk:() => {
const {dataSource} = this.props;
let result = [...dataSource]
this.props.onChange(result.filter(item => selectedRowKeys.indexOf(item.key) < 0))
},
onCancel: () => {
},
});
}
render() {
const {ledgerStore: {setAddItemVisible, addItemVisible}} = this.props;
const { selectedRowKeys } = this.state;
const rowSelection = {
selectedRowKeys,
onChange: this.onSelectChange,
};
return (
<div className="tableItemWrapper">
<div style={{padding: "10px"}}>
<span className="itemTitle">{this.props.title}</span>
<span className="rightBtnsWrapper">
<Icon className="iconItem" type="minus-square" onClick={() => {this.handleDelete()}}/>
<Icon className="iconItem" type="plus-square" onClick={() => { this.setState({addItemVisible: true}) }}/>
<Icon type={this.state.showContent ? "down" : 'left'} style={{cursor: "pointer"}} onClick={() => {this.handleTiggleContent()}}/>
</span>
</div>
{
this.state.showContent && <Table rowSelection={rowSelection} dataSource={this.props.dataSource} columns={slideStep3Columns} pagination={false}/>
}
{
this.state.addItemVisible && <AddSalaryItemModal
visible={this.state.addItemVisible}
title={this.props.title}
onCancel={() => { this.setState({addItemVisible: false})}}
/>
}
</div>
)
}
}

View File

@ -131,7 +131,6 @@ export default class Programme extends React.Component {
onCustomEdit(record) {
const { programmeStore: {getCustomForm, setCustomNewVisible, setCustomRequest}} = this.props;
setCustomNewVisible(true)
alert(JSON.stringify(record))
setCustomRequest(record)
}

View File

@ -17,6 +17,95 @@ export class LedgerStore {
@observable includeType=1; // 0排除、1包含
@observable userTableStore = {};
@observable addUserModalVisible = false;
@observable itemGroups = [
{
id:"default",
name: "未分类",
items: []
}
];
@observable salaryItemTableStore = new TableStore();
@observable empBrowserList = []
@observable empFields = []
@observable excludeIds = []
@observable addCategoryVisible = false; // 薪资项目-添加分类Modal
@action
setAddCategoryVisible = addCategoryVisible => this.addCategoryVisible = addCategoryVisible
@action
setExcludeIds = excludeIds => this.excludeIds = excludeIds
@action
addExcludeIds = id => {
let excludeIds = [...this.excludeIds]
excludeIds.push(id)
this.excludeIds = excludeIds
}
@action
addEmpFields = (fieldId) => {
let sortedIndex = 1;
if(this.empFields.length > 0) {
let lastSortedIndex = this.empFields[this.empFields.length - 1].sortedIndex
sortedIndex = parseInt(lastSortedIndex) + 1
}
let item = {
fieldId,
sortedIndex
}
let result = [...this.empFields]
result.push(item)
this.empFields = result
}
@action
setItemGroups = itemGroups => this.itemGroups = itemGroups
@action
addItemGroup = name => {
let itemGroups = [...this.itemGroups]
let flag = false;
itemGroups.map(item => {
if(item.name == name) {
flag = true;
}
})
if(flag) {
message.warning("分类已存在")
return
}
let item = {name, items: []}
itemGroups.unshift(item)
this.setItemGroups(itemGroups)
this.addCategoryVisible = false
}
@action
addItemsToGroup = (title, list) => {
let itemGroups = [...this.itemGroups]
itemGroups.map(item => {
if(item.name == title) {
item.items = item.items ? item.items.concat(list) : list
}
})
this.setItemGroups(itemGroups);
}
@action
addCategoryList = item => {
let list = [...this.categoryList]
list.push(item)
this.categoryList = list
}
@action
removeCategoryList = item => {
let list = [...this.categoryList]
list.filter(i => item.name != i.name)
this.categoryList = list;
}
@action
setAddUserModalVisible = addUserModalVisible => this.addUserModalVisible = addUserModalVisible;
@ -180,5 +269,64 @@ export class LedgerStore {
})
}
// 薪资项目可选列表
@action
listSalaryItem = (searchValue = "") => {
let excludeIds = []
this.itemGroups.map(item => {
item.items.map(i => {
excludeIds.push(i.id)
})
})
API.listSalaryItem({name:searchValue, excludeIds}).then(res => {
if(res.status) {
this.salaryItemTableStore.getDatas(res.data.datas);
} else {
message.error(res.errormsg || "获取数据失败")
}
})
}
@action
empFieldList = () => {
API.empFieldList().then(res => {
if(res.status) {
this.empBrowserList = res.data.map(item => {return {showname: item.name, key: item.id, selected: false}})
} else {
message.error(res.errormsg || "获取失败")
}
})
}
@action
saveLedgerItem = () => {
let itemGroups = [...this.itemGroups]
itemGroups = itemGroups.map(item => {
let result = {...item}
result.items = result.items.map((i,index) => (
{
salaryItemId: i.id,
sortedIndex: index + 1
}
))
return result;
})
let params = {
salarySobId: this.salarySobId,
empFields: this.empFields,
itemGroups: itemGroups.filter(item => item.id != "default"),
items: itemGroups.filter(item => item.id == 'default')[0].items
}
API.saveLedgerItem(params).then(res => {
if(res.status) {
message.success("保存成功");
} else {
message.error(res.errormsg || "保存失败")
}
})
}
}