新增信息维护年收入字段全链路支持
This commit is contained in:
@@ -5,6 +5,7 @@ import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@@ -36,6 +37,9 @@ public class CcdiBaseStaff implements Serializable {
|
||||
/** 电话 */
|
||||
private String phone;
|
||||
|
||||
/** 年收入 */
|
||||
private BigDecimal annualIncome;
|
||||
|
||||
/** 入职时间 */
|
||||
private Date hireDate;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@@ -53,6 +54,9 @@ public class CcdiStaffFmyRelation implements Serializable {
|
||||
/** 手机号码2 */
|
||||
private String mobilePhone2;
|
||||
|
||||
/** 家庭成员年收入 */
|
||||
private BigDecimal annualIncome;
|
||||
|
||||
/** 微信名称1 */
|
||||
private String wechatNo1;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@@ -46,6 +47,9 @@ public class CcdiBaseStaffAddDTO implements Serializable {
|
||||
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "电话格式不正确")
|
||||
private String phone;
|
||||
|
||||
/** 年收入 */
|
||||
private BigDecimal annualIncome;
|
||||
|
||||
/** 入职时间 */
|
||||
private Date hireDate;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@@ -45,6 +46,9 @@ public class CcdiBaseStaffEditDTO implements Serializable {
|
||||
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "电话格式不正确")
|
||||
private String phone;
|
||||
|
||||
/** 年收入 */
|
||||
private BigDecimal annualIncome;
|
||||
|
||||
/** 入职时间 */
|
||||
private Date hireDate;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@@ -75,6 +76,10 @@ public class CcdiStaffFmyRelationAddDTO implements Serializable {
|
||||
@Schema(description = "手机号码2")
|
||||
private String mobilePhone2;
|
||||
|
||||
/** 家庭成员年收入 */
|
||||
@Schema(description = "家庭成员年收入(元/年)")
|
||||
private BigDecimal annualIncome;
|
||||
|
||||
/** 微信名称1 */
|
||||
@Size(max = 50, message = "微信名称1长度不能超过50个字符")
|
||||
@Schema(description = "微信名称1")
|
||||
|
||||
@@ -10,6 +10,7 @@ import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@@ -81,6 +82,10 @@ public class CcdiStaffFmyRelationEditDTO implements Serializable {
|
||||
@Schema(description = "手机号码2")
|
||||
private String mobilePhone2;
|
||||
|
||||
/** 家庭成员年收入 */
|
||||
@Schema(description = "家庭成员年收入(元/年)")
|
||||
private BigDecimal annualIncome;
|
||||
|
||||
/** 微信名称1 */
|
||||
@Size(max = 50, message = "微信名称1长度不能超过50个字符")
|
||||
@Schema(description = "微信名称1")
|
||||
|
||||
@@ -8,6 +8,7 @@ import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@@ -52,13 +53,18 @@ public class CcdiBaseStaffExcel implements Serializable {
|
||||
@Required
|
||||
private String phone;
|
||||
|
||||
/** 年收入 */
|
||||
@ExcelProperty(value = "年收入(元/年)", index = 5)
|
||||
@ColumnWidth(18)
|
||||
private BigDecimal annualIncome;
|
||||
|
||||
/** 入职时间 */
|
||||
@ExcelProperty(value = "入职时间", index = 5)
|
||||
@ExcelProperty(value = "入职时间", index = 6)
|
||||
@ColumnWidth(15)
|
||||
private Date hireDate;
|
||||
|
||||
/** 状态 */
|
||||
@ExcelProperty(value = "状态", index = 6)
|
||||
@ExcelProperty(value = "状态", index = 7)
|
||||
@ColumnWidth(10)
|
||||
@DictDropdown(dictType = "ccdi_employee_status")
|
||||
@Required
|
||||
|
||||
@@ -9,6 +9,7 @@ import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@@ -77,43 +78,48 @@ public class CcdiStaffFmyRelationExcel implements Serializable {
|
||||
@ColumnWidth(15)
|
||||
private String mobilePhone2;
|
||||
|
||||
/** 家庭成员年收入 */
|
||||
@ExcelProperty(value = "家庭成员年收入(元/年)", index = 9)
|
||||
@ColumnWidth(18)
|
||||
private BigDecimal annualIncome;
|
||||
|
||||
/** 微信名称1 */
|
||||
@ExcelProperty(value = "微信名称1", index = 9)
|
||||
@ExcelProperty(value = "微信名称1", index = 10)
|
||||
@ColumnWidth(15)
|
||||
private String wechatNo1;
|
||||
|
||||
/** 微信名称2 */
|
||||
@ExcelProperty(value = "微信名称2", index = 10)
|
||||
@ExcelProperty(value = "微信名称2", index = 11)
|
||||
@ColumnWidth(15)
|
||||
private String wechatNo2;
|
||||
|
||||
/** 微信名称3 */
|
||||
@ExcelProperty(value = "微信名称3", index = 11)
|
||||
@ExcelProperty(value = "微信名称3", index = 12)
|
||||
@ColumnWidth(15)
|
||||
private String wechatNo3;
|
||||
|
||||
/** 详细联系地址 */
|
||||
@ExcelProperty(value = "详细联系地址", index = 12)
|
||||
@ExcelProperty(value = "详细联系地址", index = 13)
|
||||
@ColumnWidth(30)
|
||||
private String contactAddress;
|
||||
|
||||
/** 关系详细描述 */
|
||||
@ExcelProperty(value = "关系详细描述", index = 13)
|
||||
@ExcelProperty(value = "关系详细描述", index = 14)
|
||||
@ColumnWidth(30)
|
||||
private String relationDesc;
|
||||
|
||||
/** 生效日期 */
|
||||
@ExcelProperty(value = "生效日期", index = 14)
|
||||
@ExcelProperty(value = "生效日期", index = 15)
|
||||
@ColumnWidth(15)
|
||||
private Date effectiveDate;
|
||||
|
||||
/** 失效日期 */
|
||||
@ExcelProperty(value = "失效日期", index = 15)
|
||||
@ExcelProperty(value = "失效日期", index = 16)
|
||||
@ColumnWidth(15)
|
||||
private Date invalidDate;
|
||||
|
||||
/** 备注 */
|
||||
@ExcelProperty(value = "备注", index = 16)
|
||||
@ExcelProperty(value = "备注", index = 17)
|
||||
@ColumnWidth(30)
|
||||
private String remark;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@@ -37,6 +38,9 @@ public class CcdiBaseStaffVO implements Serializable {
|
||||
/** 电话 */
|
||||
private String phone;
|
||||
|
||||
/** 年收入 */
|
||||
private BigDecimal annualIncome;
|
||||
|
||||
/** 入职时间 */
|
||||
private Date hireDate;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@@ -71,6 +72,10 @@ public class CcdiStaffFmyRelationVO implements Serializable {
|
||||
@Schema(description = "手机号码2")
|
||||
private String mobilePhone2;
|
||||
|
||||
/** 家庭成员年收入 */
|
||||
@Schema(description = "家庭成员年收入(元/年)")
|
||||
private BigDecimal annualIncome;
|
||||
|
||||
/** 微信名称1 */
|
||||
@Schema(description = "微信名称1")
|
||||
private String wechatNo1;
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.ruoyi.info.collection.domain.vo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 导入失败记录VO
|
||||
*
|
||||
@@ -27,6 +29,9 @@ public class ImportFailureVO {
|
||||
@Schema(description = "电话")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "年收入")
|
||||
private BigDecimal annualIncome;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.ruoyi.info.collection.domain.vo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 员工亲属关系信息导入失败记录VO
|
||||
*
|
||||
@@ -41,6 +43,10 @@ public class StaffFmyRelationImportFailureVO {
|
||||
@Schema(description = "手机号码1")
|
||||
private String mobilePhone1;
|
||||
|
||||
/** 家庭成员年收入 */
|
||||
@Schema(description = "家庭成员年收入")
|
||||
private BigDecimal annualIncome;
|
||||
|
||||
/** 状态 */
|
||||
@Schema(description = "状态")
|
||||
private Integer status;
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -356,5 +357,19 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
||||
if (!"0".equals(addDTO.getStatus()) && !"1".equals(addDTO.getStatus())) {
|
||||
throw new RuntimeException("状态只能填写'在职'或'离职'");
|
||||
}
|
||||
|
||||
validateAnnualIncome(addDTO.getAnnualIncome(), "年收入");
|
||||
}
|
||||
|
||||
private void validateAnnualIncome(BigDecimal annualIncome, String fieldLabel) {
|
||||
if (annualIncome == null) {
|
||||
return;
|
||||
}
|
||||
if (annualIncome.compareTo(BigDecimal.ZERO) < 0) {
|
||||
throw new RuntimeException(fieldLabel + "不能为负数");
|
||||
}
|
||||
if (annualIncome.scale() > 2) {
|
||||
throw new RuntimeException(fieldLabel + "最多保留2位小数");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -129,6 +130,7 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
|
||||
@Override
|
||||
@Transactional
|
||||
public int insertBaseStaff(CcdiBaseStaffAddDTO addDTO) {
|
||||
validateAnnualIncome(addDTO.getAnnualIncome(), "年收入");
|
||||
// 检查员工ID唯一性
|
||||
if (baseStaffMapper.selectById(addDTO.getStaffId()) != null) {
|
||||
throw new RuntimeException("该员工ID已存在");
|
||||
@@ -158,6 +160,7 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
|
||||
@Override
|
||||
@Transactional
|
||||
public int updateBaseStaff(CcdiBaseStaffEditDTO editDTO) {
|
||||
validateAnnualIncome(editDTO.getAnnualIncome(), "年收入");
|
||||
CcdiBaseStaff existing = baseStaffMapper.selectById(editDTO.getStaffId());
|
||||
if (existing == null) {
|
||||
throw new RuntimeException("员工不存在");
|
||||
@@ -276,4 +279,16 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
|
||||
return vo;
|
||||
}
|
||||
|
||||
private void validateAnnualIncome(BigDecimal annualIncome, String fieldLabel) {
|
||||
if (annualIncome == null) {
|
||||
return;
|
||||
}
|
||||
if (annualIncome.compareTo(BigDecimal.ZERO) < 0) {
|
||||
throw new RuntimeException(fieldLabel + "不能为负数");
|
||||
}
|
||||
if (annualIncome.scale() > 2) {
|
||||
throw new RuntimeException(fieldLabel + "最多保留2位小数");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -338,5 +339,19 @@ public class CcdiStaffFmyRelationImportServiceImpl implements ICcdiStaffFmyRelat
|
||||
throw new RuntimeException("性别只能是:男、女、其他 或 M、F、O");
|
||||
}
|
||||
}
|
||||
|
||||
validateAnnualIncome(addDTO.getAnnualIncome(), "家庭成员年收入");
|
||||
}
|
||||
|
||||
private void validateAnnualIncome(BigDecimal annualIncome, String fieldLabel) {
|
||||
if (annualIncome == null) {
|
||||
return;
|
||||
}
|
||||
if (annualIncome.compareTo(BigDecimal.ZERO) < 0) {
|
||||
throw new RuntimeException(fieldLabel + "不能为负数");
|
||||
}
|
||||
if (annualIncome.scale() > 2) {
|
||||
throw new RuntimeException(fieldLabel + "最多保留2位小数");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -121,6 +122,7 @@ public class CcdiStaffFmyRelationServiceImpl implements ICcdiStaffFmyRelationSer
|
||||
@Override
|
||||
@Transactional
|
||||
public int insertRelation(CcdiStaffFmyRelationAddDTO addDTO) {
|
||||
validateAnnualIncome(addDTO.getAnnualIncome(), "家庭成员年收入");
|
||||
CcdiStaffFmyRelation relation = new CcdiStaffFmyRelation();
|
||||
BeanUtils.copyProperties(addDTO, relation);
|
||||
|
||||
@@ -146,6 +148,7 @@ public class CcdiStaffFmyRelationServiceImpl implements ICcdiStaffFmyRelationSer
|
||||
@Override
|
||||
@Transactional
|
||||
public int updateRelation(CcdiStaffFmyRelationEditDTO editDTO) {
|
||||
validateAnnualIncome(editDTO.getAnnualIncome(), "家庭成员年收入");
|
||||
CcdiStaffFmyRelation existing = relationMapper.selectById(editDTO.getId());
|
||||
if (existing == null) {
|
||||
throw new RuntimeException("员工亲属关系不存在");
|
||||
@@ -228,4 +231,16 @@ public class CcdiStaffFmyRelationServiceImpl implements ICcdiStaffFmyRelationSer
|
||||
BeanUtils.copyProperties(assetInfo, assetInfoVO);
|
||||
return assetInfoVO;
|
||||
}
|
||||
|
||||
private void validateAnnualIncome(BigDecimal annualIncome, String fieldLabel) {
|
||||
if (annualIncome == null) {
|
||||
return;
|
||||
}
|
||||
if (annualIncome.compareTo(BigDecimal.ZERO) < 0) {
|
||||
throw new RuntimeException(fieldLabel + "不能为负数");
|
||||
}
|
||||
if (annualIncome.scale() > 2) {
|
||||
throw new RuntimeException(fieldLabel + "最多保留2位小数");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<result property="deptName" column="dept_name"/>
|
||||
<result property="idCard" column="id_card"/>
|
||||
<result property="phone" column="phone"/>
|
||||
<result property="annualIncome" column="annual_income"/>
|
||||
<result property="hireDate" column="hire_date"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
@@ -19,7 +20,7 @@
|
||||
|
||||
<select id="selectBaseStaffPageWithDept" resultMap="CcdiBaseStaffVOResult">
|
||||
SELECT
|
||||
e.staff_id, e.name, e.dept_id, e.id_card, e.phone, e.hire_date, e.status, e.create_time,
|
||||
e.staff_id, e.name, e.dept_id, e.id_card, e.phone, e.annual_income, e.hire_date, e.status, e.create_time,
|
||||
d.dept_name
|
||||
FROM ccdi_base_staff e
|
||||
LEFT JOIN sys_dept d ON e.dept_id = d.dept_id
|
||||
@@ -46,18 +47,19 @@
|
||||
<!-- 批量插入或更新员工信息(只更新非null字段) -->
|
||||
<insert id="insertOrUpdateBatch" parameterType="java.util.List">
|
||||
INSERT INTO ccdi_base_staff
|
||||
(staff_id, name, dept_id, id_card, phone, hire_date, status,
|
||||
(staff_id, name, dept_id, id_card, phone, annual_income, hire_date, status,
|
||||
create_time, create_by, update_by, update_time)
|
||||
VALUES
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.staffId}, #{item.name}, #{item.deptId}, #{item.idCard},
|
||||
#{item.phone}, #{item.hireDate}, #{item.status}, NOW(),
|
||||
#{item.phone}, #{item.annualIncome}, #{item.hireDate}, #{item.status}, NOW(),
|
||||
#{item.createBy}, #{item.updateBy}, NOW())
|
||||
</foreach>
|
||||
ON DUPLICATE KEY UPDATE
|
||||
name = COALESCE(VALUES(name), name),
|
||||
dept_id = COALESCE(VALUES(dept_id), dept_id),
|
||||
phone = COALESCE(VALUES(phone), phone),
|
||||
annual_income = COALESCE(VALUES(annual_income), annual_income),
|
||||
hire_date = COALESCE(VALUES(hire_date), hire_date),
|
||||
status = COALESCE(VALUES(status), status),
|
||||
update_by = COALESCE(VALUES(update_by), update_by),
|
||||
@@ -67,12 +69,12 @@
|
||||
<!-- 批量插入员工信息 -->
|
||||
<insert id="insertBatch" parameterType="java.util.List">
|
||||
INSERT INTO ccdi_base_staff
|
||||
(staff_id, name, dept_id, id_card, phone, hire_date, status,
|
||||
(staff_id, name, dept_id, id_card, phone, annual_income, hire_date, status,
|
||||
create_time, create_by, update_by, update_time)
|
||||
VALUES
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.staffId}, #{item.name}, #{item.deptId}, #{item.idCard},
|
||||
#{item.phone}, #{item.hireDate}, #{item.status}, NOW(),
|
||||
#{item.phone}, #{item.annualIncome}, #{item.hireDate}, #{item.status}, NOW(),
|
||||
#{item.createBy}, #{item.updateBy}, NOW())
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<result property="relationCertNo" column="relation_cert_no"/>
|
||||
<result property="mobilePhone1" column="mobile_phone1"/>
|
||||
<result property="mobilePhone2" column="mobile_phone2"/>
|
||||
<result property="annualIncome" column="annual_income"/>
|
||||
<result property="wechatNo1" column="wechat_no1"/>
|
||||
<result property="wechatNo2" column="wechat_no2"/>
|
||||
<result property="wechatNo3" column="wechat_no3"/>
|
||||
@@ -40,7 +41,7 @@
|
||||
SELECT
|
||||
r.id, r.person_id, s.name as person_name, r.relation_type, r.relation_name,
|
||||
r.gender, r.birth_date, r.relation_cert_type, r.relation_cert_no,
|
||||
r.mobile_phone1, r.mobile_phone2, r.wechat_no1, r.wechat_no2, r.wechat_no3,
|
||||
r.mobile_phone1, r.mobile_phone2, r.annual_income, r.wechat_no1, r.wechat_no2, r.wechat_no3,
|
||||
r.contact_address, r.relation_desc, r.effective_date, r.invalid_date,
|
||||
r.status, r.remark, r.data_source, r.is_emp_family, r.is_cust_family,
|
||||
r.created_by, r.create_time, r.updated_by, r.update_time
|
||||
@@ -80,7 +81,7 @@
|
||||
SELECT
|
||||
r.id, r.person_id, s.name as person_name, r.relation_type, r.relation_name,
|
||||
r.gender, r.birth_date, r.relation_cert_type, r.relation_cert_no,
|
||||
r.mobile_phone1, r.mobile_phone2, r.wechat_no1, r.wechat_no2, r.wechat_no3,
|
||||
r.mobile_phone1, r.mobile_phone2, r.annual_income, r.wechat_no1, r.wechat_no2, r.wechat_no3,
|
||||
r.contact_address, r.relation_desc, r.effective_date, r.invalid_date,
|
||||
r.status, r.remark, r.data_source, r.is_emp_family, r.is_cust_family,
|
||||
r.created_by, r.create_time, r.updated_by, r.update_time
|
||||
@@ -94,7 +95,7 @@
|
||||
SELECT
|
||||
r.id, r.person_id, s.name as person_name, r.relation_type, r.relation_name,
|
||||
r.gender, r.birth_date, r.relation_cert_type, r.relation_cert_no,
|
||||
r.mobile_phone1, r.mobile_phone2, r.wechat_no1, r.wechat_no2, r.wechat_no3,
|
||||
r.mobile_phone1, r.mobile_phone2, r.annual_income, r.wechat_no1, r.wechat_no2, r.wechat_no3,
|
||||
r.contact_address, r.relation_desc, r.effective_date, r.invalid_date,
|
||||
r.status, r.remark, r.data_source, r.is_emp_family, r.is_cust_family,
|
||||
r.created_by, r.create_time, r.updated_by, r.update_time
|
||||
@@ -133,14 +134,14 @@
|
||||
<insert id="insertBatch">
|
||||
INSERT INTO ccdi_staff_fmy_relation
|
||||
(person_id, relation_type, relation_name, gender, birth_date, relation_cert_type, relation_cert_no,
|
||||
mobile_phone1, mobile_phone2, wechat_no1, wechat_no2, wechat_no3, contact_address, relation_desc,
|
||||
mobile_phone1, mobile_phone2, annual_income, wechat_no1, wechat_no2, wechat_no3, contact_address, relation_desc,
|
||||
effective_date, invalid_date, status, remark, data_source, is_emp_family, is_cust_family,
|
||||
created_by, create_time, updated_by, update_time)
|
||||
VALUES
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.personId}, #{item.relationType}, #{item.relationName}, #{item.gender},
|
||||
#{item.birthDate}, #{item.relationCertType}, #{item.relationCertNo}, #{item.mobilePhone1},
|
||||
#{item.mobilePhone2}, #{item.wechatNo1}, #{item.wechatNo2}, #{item.wechatNo3}, #{item.contactAddress},
|
||||
#{item.mobilePhone2}, #{item.annualIncome}, #{item.wechatNo1}, #{item.wechatNo2}, #{item.wechatNo3}, #{item.contactAddress},
|
||||
#{item.relationDesc}, #{item.effectiveDate}, #{item.invalidDate}, #{item.status}, #{item.remark},
|
||||
#{item.dataSource}, #{item.isEmpFamily}, #{item.isCustFamily}, #{item.createdBy}, NOW(), #{item.updatedBy}, NOW())
|
||||
</foreach>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ruoyi.info.collection.mapper;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class CcdiBaseStaffMapperTest {
|
||||
|
||||
@Test
|
||||
void mapperXml_shouldContainAnnualIncomeColumnsInCustomSql() throws Exception {
|
||||
try (InputStream inputStream = getClass().getClassLoader()
|
||||
.getResourceAsStream("mapper/info/collection/CcdiBaseStaffMapper.xml")) {
|
||||
String xml = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
|
||||
|
||||
assertTrue(xml.contains("annual_income"), xml);
|
||||
assertTrue(xml.contains("#{item.annualIncome}"), xml);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,16 @@ class CcdiStaffFmyRelationMapperTest {
|
||||
assertTrue(sql.contains("WHERE 1 = 1 AND r.is_emp_family = 1 AND r.person_id = ?"), sql);
|
||||
assertFalse(sql.contains("1AND"), sql);
|
||||
assertFalse(countSql.contains("1AND"), countSql);
|
||||
assertTrue(sql.contains("r.annual_income"), sql);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapperXml_shouldContainAnnualIncomeInBatchInsert() throws Exception {
|
||||
try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(RESOURCE)) {
|
||||
String xml = new String(inputStream.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
|
||||
assertTrue(xml.contains("annual_income"), xml);
|
||||
assertTrue(xml.contains("#{item.annualIncome}"), xml);
|
||||
}
|
||||
}
|
||||
|
||||
private MappedStatement loadMappedStatement(String statementId) throws Exception {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.ruoyi.info.collection.service;
|
||||
|
||||
import com.ruoyi.info.collection.domain.dto.CcdiBaseStaffAddDTO;
|
||||
import com.ruoyi.info.collection.service.impl.CcdiBaseStaffImportServiceImpl;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class CcdiBaseStaffImportServiceImplTest {
|
||||
|
||||
private final CcdiBaseStaffImportServiceImpl service = new CcdiBaseStaffImportServiceImpl();
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldAllowEmptyAnnualIncome() {
|
||||
assertDoesNotThrow(() -> service.validateStaffData(buildDto(null), false, Collections.emptySet(), Collections.emptySet()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldAllowZeroAndTwoDecimalAnnualIncome() {
|
||||
assertDoesNotThrow(() -> service.validateStaffData(buildDto(new BigDecimal("0.00")), false, Collections.emptySet(), Collections.emptySet()));
|
||||
assertDoesNotThrow(() -> service.validateStaffData(buildDto(new BigDecimal("12345.67")), false, Collections.emptySet(), Collections.emptySet()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldRejectNegativeAnnualIncome() {
|
||||
RuntimeException exception = assertThrows(RuntimeException.class,
|
||||
() -> service.validateStaffData(buildDto(new BigDecimal("-1.00")), false, Set.of(), Set.of()));
|
||||
|
||||
assertEquals("年收入不能为负数", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldRejectAnnualIncomeWithMoreThanTwoDecimals() {
|
||||
RuntimeException exception = assertThrows(RuntimeException.class,
|
||||
() -> service.validateStaffData(buildDto(new BigDecimal("12.345")), false, Set.of(), Set.of()));
|
||||
|
||||
assertEquals("年收入最多保留2位小数", exception.getMessage());
|
||||
}
|
||||
|
||||
private CcdiBaseStaffAddDTO buildDto(BigDecimal annualIncome) {
|
||||
CcdiBaseStaffAddDTO dto = new CcdiBaseStaffAddDTO();
|
||||
dto.setName("张三");
|
||||
dto.setStaffId(1001L);
|
||||
dto.setDeptId(10L);
|
||||
dto.setIdCard("320101199001010014");
|
||||
dto.setPhone("13812345678");
|
||||
dto.setStatus("0");
|
||||
dto.setAnnualIncome(annualIncome);
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,7 @@ class CcdiBaseStaffServiceImplTest {
|
||||
addDTO.setIdCard("320101199001010011");
|
||||
addDTO.setPhone("13812345678");
|
||||
addDTO.setStatus("0");
|
||||
addDTO.setAnnualIncome(new BigDecimal("12345.67"));
|
||||
addDTO.setAssetInfoList(List.of(
|
||||
buildAssetDto("房产"),
|
||||
buildAssetDto("车辆")
|
||||
@@ -67,6 +68,9 @@ class CcdiBaseStaffServiceImplTest {
|
||||
int result = service.insertBaseStaff(addDTO);
|
||||
|
||||
assertEquals(1, result);
|
||||
ArgumentCaptor<CcdiBaseStaff> staffCaptor = ArgumentCaptor.forClass(CcdiBaseStaff.class);
|
||||
verify(baseStaffMapper).insert(staffCaptor.capture());
|
||||
assertEquals(new BigDecimal("12345.67"), staffCaptor.getValue().getAnnualIncome());
|
||||
ArgumentCaptor<List<CcdiAssetInfoDTO>> captor = ArgumentCaptor.forClass(List.class);
|
||||
verify(assetInfoService).replaceByFamilyId(eq("320101199001010011"), captor.capture());
|
||||
List<CcdiAssetInfoDTO> savedAssets = captor.getValue();
|
||||
@@ -88,6 +92,7 @@ class CcdiBaseStaffServiceImplTest {
|
||||
editDTO.setIdCard("320101199001010011");
|
||||
editDTO.setPhone("13812345678");
|
||||
editDTO.setStatus("0");
|
||||
editDTO.setAnnualIncome(new BigDecimal("45678.90"));
|
||||
editDTO.setAssetInfoList(List.of(buildAssetDto("车辆")));
|
||||
|
||||
when(baseStaffMapper.selectById(1001L)).thenReturn(existing);
|
||||
@@ -97,6 +102,9 @@ class CcdiBaseStaffServiceImplTest {
|
||||
int result = service.updateBaseStaff(editDTO);
|
||||
|
||||
assertEquals(1, result);
|
||||
ArgumentCaptor<CcdiBaseStaff> staffCaptor = ArgumentCaptor.forClass(CcdiBaseStaff.class);
|
||||
verify(baseStaffMapper).updateById(staffCaptor.capture());
|
||||
assertEquals(new BigDecimal("45678.90"), staffCaptor.getValue().getAnnualIncome());
|
||||
verify(assetInfoService, never()).deleteByFamilyId("320101199001010011");
|
||||
verify(assetInfoService).replaceByFamilyId("320101199001010011", editDTO.getAssetInfoList());
|
||||
}
|
||||
@@ -133,6 +141,7 @@ class CcdiBaseStaffServiceImplTest {
|
||||
staff.setName("张三");
|
||||
staff.setIdCard("320101199001010011");
|
||||
staff.setStatus("0");
|
||||
staff.setAnnualIncome(new BigDecimal("88888.88"));
|
||||
|
||||
CcdiAssetInfo assetInfo = new CcdiAssetInfo();
|
||||
assetInfo.setFamilyId("320101199001010011");
|
||||
@@ -149,6 +158,7 @@ class CcdiBaseStaffServiceImplTest {
|
||||
CcdiBaseStaffVO result = service.selectBaseStaffById(1001L);
|
||||
|
||||
assertNotNull(result.getAssetInfoList());
|
||||
assertEquals(new BigDecimal("88888.88"), result.getAnnualIncome());
|
||||
assertEquals(1, result.getAssetInfoList().size());
|
||||
assertEquals("320101199201010022", result.getAssetInfoList().get(0).getPersonId());
|
||||
assertEquals("车辆", result.getAssetInfoList().get(0).getAssetMainType());
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.ruoyi.info.collection.service;
|
||||
|
||||
import com.ruoyi.info.collection.domain.dto.CcdiStaffFmyRelationAddDTO;
|
||||
import com.ruoyi.info.collection.service.impl.CcdiStaffFmyRelationImportServiceImpl;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class CcdiStaffFmyRelationImportServiceImplTest {
|
||||
|
||||
private final CcdiStaffFmyRelationImportServiceImpl service = new CcdiStaffFmyRelationImportServiceImpl();
|
||||
|
||||
@Test
|
||||
void validateRelationData_shouldRejectNegativeAnnualIncome() throws Exception {
|
||||
RuntimeException exception = assertThrows(RuntimeException.class,
|
||||
() -> invokeValidateRelationData(buildDto(new BigDecimal("-1.00"))));
|
||||
|
||||
assertEquals("家庭成员年收入不能为负数", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateRelationData_shouldRejectAnnualIncomeWithMoreThanTwoDecimals() throws Exception {
|
||||
RuntimeException exception = assertThrows(RuntimeException.class,
|
||||
() -> invokeValidateRelationData(buildDto(new BigDecimal("12.345"))));
|
||||
|
||||
assertEquals("家庭成员年收入最多保留2位小数", exception.getMessage());
|
||||
}
|
||||
|
||||
private void invokeValidateRelationData(CcdiStaffFmyRelationAddDTO dto) throws Exception {
|
||||
Method method = CcdiStaffFmyRelationImportServiceImpl.class
|
||||
.getDeclaredMethod("validateRelationData", CcdiStaffFmyRelationAddDTO.class);
|
||||
method.setAccessible(true);
|
||||
try {
|
||||
method.invoke(service, dto);
|
||||
} catch (InvocationTargetException ex) {
|
||||
Throwable targetException = ex.getTargetException();
|
||||
if (targetException instanceof RuntimeException runtimeException) {
|
||||
throw runtimeException;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
private CcdiStaffFmyRelationAddDTO buildDto(BigDecimal annualIncome) {
|
||||
CcdiStaffFmyRelationAddDTO dto = new CcdiStaffFmyRelationAddDTO();
|
||||
dto.setPersonId("320101199001010014");
|
||||
dto.setRelationType("配偶");
|
||||
dto.setRelationName("李四");
|
||||
dto.setRelationCertType("护照");
|
||||
dto.setRelationCertNo("A123456789");
|
||||
dto.setAnnualIncome(annualIncome);
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
@@ -77,6 +77,7 @@ class CcdiStaffFmyRelationServiceImplTest {
|
||||
addDTO.setRelationName("李四");
|
||||
addDTO.setRelationCertType("护照");
|
||||
addDTO.setRelationCertNo("A123456789");
|
||||
addDTO.setAnnualIncome(new BigDecimal("23456.78"));
|
||||
addDTO.setAssetInfoList(List.of(buildAssetDto("房产")));
|
||||
|
||||
when(relationMapper.insert(any(CcdiStaffFmyRelation.class))).thenReturn(1);
|
||||
@@ -89,6 +90,7 @@ class CcdiStaffFmyRelationServiceImplTest {
|
||||
assertEquals("MANUAL", relationCaptor.getValue().getDataSource());
|
||||
assertEquals(Boolean.TRUE, relationCaptor.getValue().getIsEmpFamily());
|
||||
assertEquals(Boolean.FALSE, relationCaptor.getValue().getIsCustFamily());
|
||||
assertEquals(new BigDecimal("23456.78"), relationCaptor.getValue().getAnnualIncome());
|
||||
verify(assetInfoService).replaceByFamilyIdAndPersonId("320101199001010011", "A123456789", addDTO.getAssetInfoList());
|
||||
}
|
||||
|
||||
@@ -154,6 +156,7 @@ class CcdiStaffFmyRelationServiceImplTest {
|
||||
editDTO.setRelationName("李四");
|
||||
editDTO.setRelationCertType("护照");
|
||||
editDTO.setRelationCertNo("A123456789");
|
||||
editDTO.setAnnualIncome(new BigDecimal("76543.21"));
|
||||
editDTO.setAssetInfoList(List.of(buildAssetDto("车辆")));
|
||||
|
||||
when(relationMapper.selectById(10L)).thenReturn(existing);
|
||||
@@ -162,6 +165,9 @@ class CcdiStaffFmyRelationServiceImplTest {
|
||||
int result = service.updateRelation(editDTO);
|
||||
|
||||
assertEquals(1, result);
|
||||
ArgumentCaptor<CcdiStaffFmyRelation> relationCaptor = ArgumentCaptor.forClass(CcdiStaffFmyRelation.class);
|
||||
verify(relationMapper).updateById(relationCaptor.capture());
|
||||
assertEquals(new BigDecimal("76543.21"), relationCaptor.getValue().getAnnualIncome());
|
||||
verify(assetInfoService).replaceByFamilyIdAndPersonId("320101199001010011", "A123456789", editDTO.getAssetInfoList());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# 信息维护年收入字段后端实施计划
|
||||
|
||||
## 目标
|
||||
- 员工信息维护新增 `annual_income`
|
||||
- 员工亲属关系维护新增 `annual_income`
|
||||
- 覆盖数据库、实体、DTO/VO、Mapper、导入导出、失败记录、服务层校验
|
||||
|
||||
## 实施内容
|
||||
1. 数据库变更
|
||||
- 在 `ccdi_base_staff` 新增 `annual_income DECIMAL(15,2) NULL`
|
||||
- 在 `ccdi_staff_fmy_relation` 新增 `annual_income DECIMAL(15,2) NULL`
|
||||
- 增量脚本落库到 `sql/migration/2026-03-17-add-annual-income-to-info-maintenance.sql`
|
||||
|
||||
2. 员工信息链路
|
||||
- 扩展 `CcdiBaseStaff`、`CcdiBaseStaffAddDTO`、`CcdiBaseStaffEditDTO`、`CcdiBaseStaffVO`
|
||||
- 扩展 `CcdiBaseStaffExcel` 与 `ImportFailureVO`
|
||||
- 更新 `CcdiBaseStaffMapper.xml` 的分页查询、批量插入、批量更新 SQL
|
||||
- 在 `CcdiBaseStaffServiceImpl` 与 `CcdiBaseStaffImportServiceImpl` 增加非负且最多两位小数校验
|
||||
|
||||
3. 员工亲属关系链路
|
||||
- 扩展 `CcdiStaffFmyRelation`、`CcdiStaffFmyRelationAddDTO`、`CcdiStaffFmyRelationEditDTO`、`CcdiStaffFmyRelationVO`
|
||||
- 扩展 `CcdiStaffFmyRelationExcel` 与 `StaffFmyRelationImportFailureVO`
|
||||
- 更新 `CcdiStaffFmyRelationMapper.xml` 的列表、详情、导出、批量插入 SQL
|
||||
- 在 `CcdiStaffFmyRelationServiceImpl` 与 `CcdiStaffFmyRelationImportServiceImpl` 增加非负且最多两位小数校验
|
||||
|
||||
## 测试
|
||||
- `CcdiBaseStaffServiceImplTest`
|
||||
- `CcdiStaffFmyRelationServiceImplTest`
|
||||
- `CcdiBaseStaffImportServiceImplTest`
|
||||
- `CcdiStaffFmyRelationImportServiceImplTest`
|
||||
- `CcdiBaseStaffMapperTest`
|
||||
- `CcdiStaffFmyRelationMapperTest`
|
||||
|
||||
## 验收标准
|
||||
- 列表、详情、导出和导入都能透传 `annualIncome`
|
||||
- 服务层可拦截负数与超过两位小数
|
||||
- 失败记录可返回原始年收入值
|
||||
@@ -0,0 +1,38 @@
|
||||
# 信息维护年收入字段前端实施计划
|
||||
|
||||
## 目标
|
||||
- 在员工信息维护页面新增“年收入”
|
||||
- 在员工亲属关系维护页面新增“家庭成员年收入”
|
||||
- 保持现有页面结构和接口调用方式不变
|
||||
|
||||
## 实施内容
|
||||
1. 员工信息维护页
|
||||
- 列表新增“年收入”列
|
||||
- 新增/编辑弹窗新增“年收入”输入框
|
||||
- 详情弹窗展示“年收入”
|
||||
- 导入失败记录弹窗新增“年收入”列
|
||||
- 提交前做空值兼容与金额格式校验
|
||||
|
||||
2. 员工亲属关系维护页
|
||||
- 列表新增“家庭成员年收入”列
|
||||
- 新增/编辑弹窗新增“家庭成员年收入”输入框
|
||||
- 详情弹窗展示“家庭成员年收入”
|
||||
- 导入失败记录弹窗新增“家庭成员年收入”列
|
||||
- 提交前做空值兼容与金额格式校验
|
||||
|
||||
3. 前端校验规则
|
||||
- 允许空值
|
||||
- 非空时仅允许非负金额
|
||||
- 最多保留两位小数
|
||||
- 不做单位换算,直接按“元/年”展示和提交
|
||||
|
||||
## 测试
|
||||
- `ruoyi-ui/tests/unit/employee-asset-submit-flow.test.js`
|
||||
- `ruoyi-ui/tests/unit/employee-asset-maintenance-layout.test.js`
|
||||
- `ruoyi-ui/tests/unit/staff-family-asset-submit-flow.test.js`
|
||||
- `ruoyi-ui/tests/unit/staff-family-asset-maintenance-layout.test.js`
|
||||
|
||||
## 验收标准
|
||||
- 两个页面都能新增、编辑、查看年收入字段
|
||||
- 历史空值数据页面正常展示
|
||||
- 前端能阻止非法金额提交
|
||||
@@ -115,6 +115,7 @@
|
||||
<el-table-column label="身份证号" align="center" prop="idCard" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="所属部门" align="center" prop="deptName" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="电话" align="center" prop="phone" width="120"/>
|
||||
<el-table-column label="年收入" align="center" prop="annualIncome" width="140"/>
|
||||
<el-table-column label="状态" align="center" prop="status" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.status === '0'" type="success">在职</el-tag>
|
||||
@@ -204,11 +205,19 @@
|
||||
<el-input v-model="form.phone" placeholder="请输入电话" maxlength="11" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="年收入" prop="annualIncome">
|
||||
<el-input v-model="form.annualIncome" placeholder="请输入年收入(元/年)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="入职时间" prop="hireDate">
|
||||
<el-date-picker v-model="form.hireDate" type="date" placeholder="选择入职时间" value-format="yyyy-MM-dd" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" />
|
||||
</el-row>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
@@ -318,6 +327,9 @@
|
||||
<el-descriptions-item label="所属部门">{{ employeeDetail.deptName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="身份证号">{{ employeeDetail.idCard || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="电话">{{ employeeDetail.phone || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="年收入">
|
||||
{{ employeeDetail.annualIncome !== null && employeeDetail.annualIncome !== undefined && employeeDetail.annualIncome !== '' ? employeeDetail.annualIncome : '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="入职时间">
|
||||
{{ employeeDetail.hireDate ? parseTime(employeeDetail.hireDate, '{y}-{m}-{d}') : '-' }}
|
||||
</el-descriptions-item>
|
||||
@@ -453,6 +465,7 @@
|
||||
<el-table-column label="柜员号" prop="staffId" align="center" />
|
||||
<el-table-column label="身份证号" prop="idCard" align="center" />
|
||||
<el-table-column label="电话" prop="phone" align="center" />
|
||||
<el-table-column label="年收入" prop="annualIncome" align="center" width="140" />
|
||||
<el-table-column label="失败原因" prop="errorMessage" align="center" min-width="200" :show-overflow-tooltip="true" />
|
||||
</el-table>
|
||||
|
||||
@@ -606,6 +619,9 @@ export default {
|
||||
{ required: true, message: "电话不能为空", trigger: "blur" },
|
||||
{ pattern: phonePattern, message: "请输入正确的11位手机号", trigger: "blur" }
|
||||
],
|
||||
annualIncome: [
|
||||
{ validator: (rule, value, callback) => this.validateAnnualIncomeRule(value, callback, "年收入"), trigger: "blur" }
|
||||
],
|
||||
status: [
|
||||
{ required: true, message: "请选择状态", trigger: "change" }
|
||||
]
|
||||
@@ -938,6 +954,7 @@ export default {
|
||||
deptId: null,
|
||||
idCard: null,
|
||||
phone: null,
|
||||
annualIncome: null,
|
||||
hireDate: null,
|
||||
status: "0",
|
||||
relatives: [],
|
||||
@@ -945,6 +962,36 @@ export default {
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
normalizeAnnualIncome(value) {
|
||||
if (value === null || value === undefined) {
|
||||
return null;
|
||||
}
|
||||
const normalized = String(value).trim();
|
||||
return normalized === "" ? null : normalized;
|
||||
},
|
||||
validateAnnualIncome(value, fieldLabel = "年收入") {
|
||||
const normalized = this.normalizeAnnualIncome(value);
|
||||
if (normalized === null) {
|
||||
return true;
|
||||
}
|
||||
if (!/^\d+(\.\d{1,2})?$/.test(normalized)) {
|
||||
this.$modal.msgError(`${fieldLabel}格式不正确,需为非负金额且最多保留2位小数`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
validateAnnualIncomeRule(value, callback, fieldLabel = "年收入") {
|
||||
const normalized = this.normalizeAnnualIncome(value);
|
||||
if (normalized === null) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
if (!/^\d+(\.\d{1,2})?$/.test(normalized)) {
|
||||
callback(new Error(`${fieldLabel}格式不正确,需为非负金额且最多保留2位小数`));
|
||||
return;
|
||||
}
|
||||
callback();
|
||||
},
|
||||
normalizeAssetInfoList() {
|
||||
const assetInfoList = Array.isArray(this.form.assetInfoList)
|
||||
? this.form.assetInfoList
|
||||
@@ -1114,6 +1161,7 @@ export default {
|
||||
...response.data,
|
||||
assetInfoList: response.data.assetInfoList || []
|
||||
};
|
||||
this.form.annualIncome = response.data.annualIncome;
|
||||
this.open = true;
|
||||
this.title = "编辑员工";
|
||||
});
|
||||
@@ -1123,18 +1171,27 @@ export default {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
this.form.assetInfoList = this.normalizeAssetInfoList();
|
||||
if (!this.validateAssetInfoList(this.form.assetInfoList)) {
|
||||
const payload = {
|
||||
...this.form,
|
||||
assetInfoList: this.form.assetInfoList
|
||||
};
|
||||
payload.annualIncome = this.normalizeAnnualIncome(payload.annualIncome);
|
||||
this.form.assetInfoList = payload.assetInfoList;
|
||||
if (!this.validateAnnualIncome(payload.annualIncome, "年收入")) {
|
||||
return;
|
||||
}
|
||||
if (!this.validateAssetInfoList(payload.assetInfoList)) {
|
||||
return;
|
||||
}
|
||||
if (this.isAdd) {
|
||||
addBaseStaff(this.form).then(response => {
|
||||
addBaseStaff(payload).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.isAdd = false;
|
||||
this.getList();
|
||||
});
|
||||
} else {
|
||||
updateBaseStaff(this.form).then(response => {
|
||||
updateBaseStaff(payload).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
|
||||
@@ -123,6 +123,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="关系人姓名" align="center" prop="relationName" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="家庭成员年收入" align="center" prop="annualIncome" width="160"/>
|
||||
<el-table-column label="性别" align="center" prop="gender" width="80">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.ccdi_indiv_gender" :value="scope.row.gender"/>
|
||||
@@ -282,6 +283,13 @@
|
||||
<el-input v-model="form.mobilePhone2" placeholder="请输入手机号码2" maxlength="20" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="家庭成员年收入" prop="annualIncome">
|
||||
<el-input v-model="form.annualIncome" placeholder="请输入家庭成员年收入(元/年)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="微信名称1" prop="wechatNo1">
|
||||
<el-input v-model="form.wechatNo1" placeholder="请输入微信名称1" maxlength="50" />
|
||||
@@ -466,6 +474,9 @@
|
||||
<el-descriptions-item label="出生日期">{{ relationDetail.birthDate || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号码1">{{ relationDetail.mobilePhone1 || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号码2">{{ relationDetail.mobilePhone2 || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="家庭成员年收入">
|
||||
{{ relationDetail.annualIncome !== null && relationDetail.annualIncome !== undefined && relationDetail.annualIncome !== '' ? relationDetail.annualIncome : '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="微信名称1">{{ relationDetail.wechatNo1 || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="微信名称2">{{ relationDetail.wechatNo2 || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="微信名称3">{{ relationDetail.wechatNo3 || '-' }}</el-descriptions-item>
|
||||
@@ -616,6 +627,7 @@
|
||||
<el-table-column label="员工身份证号" prop="personId" align="center" width="180"/>
|
||||
<el-table-column label="关系类型" prop="relationType" align="center" width="100"/>
|
||||
<el-table-column label="关系人姓名" prop="relationName" align="center" width="120"/>
|
||||
<el-table-column label="家庭成员年收入" prop="annualIncome" align="center" width="160"/>
|
||||
<el-table-column label="失败原因" prop="errorMessage" align="center" min-width="200" :show-overflow-tooltip="true" />
|
||||
</el-table>
|
||||
|
||||
@@ -766,6 +778,9 @@ export default {
|
||||
],
|
||||
mobilePhone2: [
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: "请输入正确的手机号码", trigger: "blur" }
|
||||
],
|
||||
annualIncome: [
|
||||
{ validator: (rule, value, callback) => this.validateAnnualIncomeRule(value, callback, "家庭成员年收入"), trigger: "blur" }
|
||||
]
|
||||
},
|
||||
// 导入参数
|
||||
@@ -963,6 +978,7 @@ export default {
|
||||
relationCertNo: null,
|
||||
mobilePhone1: null,
|
||||
mobilePhone2: null,
|
||||
annualIncome: null,
|
||||
wechatNo1: null,
|
||||
wechatNo2: null,
|
||||
wechatNo3: null,
|
||||
@@ -977,6 +993,36 @@ export default {
|
||||
this.staffOptions = [];
|
||||
this.resetForm("form");
|
||||
},
|
||||
normalizeAnnualIncome(value) {
|
||||
if (value === null || value === undefined) {
|
||||
return null;
|
||||
}
|
||||
const normalized = String(value).trim();
|
||||
return normalized === "" ? null : normalized;
|
||||
},
|
||||
validateAnnualIncome(value, fieldLabel = "家庭成员年收入") {
|
||||
const normalized = this.normalizeAnnualIncome(value);
|
||||
if (normalized === null) {
|
||||
return true;
|
||||
}
|
||||
if (!/^\d+(\.\d{1,2})?$/.test(normalized)) {
|
||||
this.$modal.msgError(`${fieldLabel}格式不正确,需为非负金额且最多保留2位小数`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
validateAnnualIncomeRule(value, callback, fieldLabel = "家庭成员年收入") {
|
||||
const normalized = this.normalizeAnnualIncome(value);
|
||||
if (normalized === null) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
if (!/^\d+(\.\d{1,2})?$/.test(normalized)) {
|
||||
callback(new Error(`${fieldLabel}格式不正确,需为非负金额且最多保留2位小数`));
|
||||
return;
|
||||
}
|
||||
callback();
|
||||
},
|
||||
createEmptyAssetRow() {
|
||||
return {
|
||||
assetMainType: "",
|
||||
@@ -1098,6 +1144,7 @@ export default {
|
||||
...response.data,
|
||||
assetInfoList: response.data.assetInfoList || []
|
||||
};
|
||||
this.form.annualIncome = response.data.annualIncome;
|
||||
// 加载员工信息以支持下拉显示
|
||||
if (this.form.personId) {
|
||||
this.searchStaff(this.form.personId);
|
||||
@@ -1131,6 +1178,10 @@ export default {
|
||||
...this.form,
|
||||
assetInfoList: this.form.assetInfoList.map(item => ({ ...item }))
|
||||
};
|
||||
payload.annualIncome = this.normalizeAnnualIncome(payload.annualIncome);
|
||||
if (!this.validateAnnualIncome(payload.annualIncome, "家庭成员年收入")) {
|
||||
return;
|
||||
}
|
||||
payload.assetInfoList.forEach((asset, index) => {
|
||||
delete payload.assetInfoList[index].familyId;
|
||||
delete payload.assetInfoList[index].personId;
|
||||
|
||||
@@ -9,6 +9,9 @@ const componentPath = path.resolve(
|
||||
const source = fs.readFileSync(componentPath, "utf8");
|
||||
|
||||
[
|
||||
"年收入",
|
||||
"v-model=\"form.annualIncome\"",
|
||||
"employeeDetail.annualIncome",
|
||||
"<el-dialog :title=\"title\" :visible.sync=\"open\" width=\"80%\"",
|
||||
"<el-dialog title=\"员工详情\" :visible.sync=\"detailOpen\" width=\"80%\"",
|
||||
"资产信息",
|
||||
|
||||
@@ -9,6 +9,13 @@ const componentPath = path.resolve(
|
||||
const source = fs.readFileSync(componentPath, "utf8");
|
||||
|
||||
[
|
||||
"annualIncome: null",
|
||||
"label=\"年收入\"",
|
||||
"v-model=\"form.annualIncome\"",
|
||||
"this.form.annualIncome = response.data.annualIncome",
|
||||
"payload.annualIncome = this.normalizeAnnualIncome(payload.annualIncome);",
|
||||
"normalizeAnnualIncome(value)",
|
||||
"validateAnnualIncome(value, fieldLabel = \"年收入\")",
|
||||
"assetInfoList: []",
|
||||
"normalizeAssetInfoList()",
|
||||
"this.form.assetInfoList = [];",
|
||||
|
||||
@@ -9,6 +9,9 @@ const componentPath = path.resolve(
|
||||
const source = fs.readFileSync(componentPath, "utf8");
|
||||
|
||||
[
|
||||
"家庭成员年收入",
|
||||
"v-model=\"form.annualIncome\"",
|
||||
"relationDetail.annualIncome",
|
||||
"亲属资产信息",
|
||||
"新增资产",
|
||||
"handleAddAsset()",
|
||||
|
||||
@@ -9,6 +9,13 @@ const componentPath = path.resolve(
|
||||
const source = fs.readFileSync(componentPath, "utf8");
|
||||
|
||||
[
|
||||
"annualIncome: null",
|
||||
"label=\"家庭成员年收入\"",
|
||||
"v-model=\"form.annualIncome\"",
|
||||
"this.form.annualIncome = response.data.annualIncome",
|
||||
"payload.annualIncome = this.normalizeAnnualIncome(payload.annualIncome);",
|
||||
"normalizeAnnualIncome(value)",
|
||||
"validateAnnualIncome(value, fieldLabel = \"家庭成员年收入\")",
|
||||
"assetInfoList: []",
|
||||
"normalizeAssetInfoList()",
|
||||
"response.data.assetInfoList || []",
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
SET @base_staff_annual_income_sql = IF(
|
||||
EXISTS(
|
||||
SELECT 1
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = DATABASE()
|
||||
AND table_name = 'ccdi_base_staff'
|
||||
AND column_name = 'annual_income'
|
||||
),
|
||||
'SELECT 1',
|
||||
'ALTER TABLE `ccdi_base_staff` ADD COLUMN `annual_income` DECIMAL(15, 2) NULL COMMENT ''年收入(元/年)'' AFTER `phone`'
|
||||
);
|
||||
|
||||
PREPARE base_staff_annual_income_stmt FROM @base_staff_annual_income_sql;
|
||||
EXECUTE base_staff_annual_income_stmt;
|
||||
DEALLOCATE PREPARE base_staff_annual_income_stmt;
|
||||
|
||||
SET @staff_fmy_relation_annual_income_sql = IF(
|
||||
EXISTS(
|
||||
SELECT 1
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = DATABASE()
|
||||
AND table_name = 'ccdi_staff_fmy_relation'
|
||||
AND column_name = 'annual_income'
|
||||
),
|
||||
'SELECT 1',
|
||||
'ALTER TABLE `ccdi_staff_fmy_relation` ADD COLUMN `annual_income` DECIMAL(15, 2) NULL COMMENT ''家庭成员年收入(元/年)'' AFTER `mobile_phone2`'
|
||||
);
|
||||
|
||||
PREPARE staff_fmy_relation_annual_income_stmt FROM @staff_fmy_relation_annual_income_sql;
|
||||
EXECUTE staff_fmy_relation_annual_income_stmt;
|
||||
DEALLOCATE PREPARE staff_fmy_relation_annual_income_stmt;
|
||||
Reference in New Issue
Block a user