新增员工党员字段
This commit is contained in:
@@ -43,6 +43,10 @@ public class CcdiBaseStaff implements Serializable {
|
||||
/** 入职时间 */
|
||||
private Date hireDate;
|
||||
|
||||
/** 是否党员:0-否 1-是 */
|
||||
@TableField("is_party_member")
|
||||
private Integer partyMember;
|
||||
|
||||
/** 状态 */
|
||||
private String status;
|
||||
|
||||
|
||||
@@ -53,6 +53,10 @@ public class CcdiBaseStaffAddDTO implements Serializable {
|
||||
/** 入职时间 */
|
||||
private Date hireDate;
|
||||
|
||||
/** 是否党员:0-否 1-是 */
|
||||
@NotNull(message = "是否党员不能为空")
|
||||
private Integer partyMember;
|
||||
|
||||
/** 状态 */
|
||||
@NotBlank(message = "状态不能为空")
|
||||
private String status;
|
||||
|
||||
@@ -52,6 +52,10 @@ public class CcdiBaseStaffEditDTO implements Serializable {
|
||||
/** 入职时间 */
|
||||
private Date hireDate;
|
||||
|
||||
/** 是否党员:0-否 1-是 */
|
||||
@NotNull(message = "是否党员不能为空")
|
||||
private Integer partyMember;
|
||||
|
||||
/** 状态 */
|
||||
private String status;
|
||||
|
||||
|
||||
@@ -63,8 +63,15 @@ public class CcdiBaseStaffExcel implements Serializable {
|
||||
@ColumnWidth(15)
|
||||
private Date hireDate;
|
||||
|
||||
/** 是否党员 */
|
||||
@ExcelProperty(value = "是否党员", index = 7)
|
||||
@ColumnWidth(12)
|
||||
@DictDropdown(dictType = "ccdi_yes_no_flag")
|
||||
@Required
|
||||
private Integer partyMember;
|
||||
|
||||
/** 状态 */
|
||||
@ExcelProperty(value = "状态", index = 7)
|
||||
@ExcelProperty(value = "状态", index = 8)
|
||||
@ColumnWidth(10)
|
||||
@DictDropdown(dictType = "ccdi_employee_status")
|
||||
@Required
|
||||
|
||||
@@ -44,6 +44,9 @@ public class CcdiBaseStaffVO implements Serializable {
|
||||
/** 入职时间 */
|
||||
private Date hireDate;
|
||||
|
||||
/** 是否党员:0-否 1-是 */
|
||||
private Integer partyMember;
|
||||
|
||||
/** 状态 */
|
||||
private String status;
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@ public class ImportFailureVO {
|
||||
@Schema(description = "年收入")
|
||||
private BigDecimal annualIncome;
|
||||
|
||||
@Schema(description = "是否党员:0-否 1-是")
|
||||
private Integer partyMember;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
|
||||
|
||||
@@ -320,6 +320,9 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
||||
if (StringUtils.isEmpty(addDTO.getPhone())) {
|
||||
throw new RuntimeException("电话不能为空");
|
||||
}
|
||||
if (addDTO.getPartyMember() == null) {
|
||||
throw new RuntimeException("是否党员不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(addDTO.getStatus())) {
|
||||
throw new RuntimeException("状态不能为空");
|
||||
}
|
||||
@@ -357,6 +360,9 @@ public class CcdiBaseStaffImportServiceImpl implements ICcdiBaseStaffImportServi
|
||||
if (!"0".equals(addDTO.getStatus()) && !"1".equals(addDTO.getStatus())) {
|
||||
throw new RuntimeException("状态只能填写'在职'或'离职'");
|
||||
}
|
||||
if (addDTO.getPartyMember() != 0 && addDTO.getPartyMember() != 1) {
|
||||
throw new RuntimeException("是否党员只能填写'0'或'1'");
|
||||
}
|
||||
|
||||
validateAnnualIncome(addDTO.getAnnualIncome(), "年收入");
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
|
||||
CcdiBaseStaff staff = baseStaffMapper.selectById(staffId);
|
||||
CcdiBaseStaffVO vo = convertToVO(staff);
|
||||
if (staff != null) {
|
||||
vo.setAssetInfoList(assetInfoService.selectByFamilyId(staff.getIdCard()).stream().map(asset -> {
|
||||
vo.setAssetInfoList(assetInfoService.selectByFamilyIdAndPersonId(staff.getIdCard(), staff.getIdCard()).stream().map(asset -> {
|
||||
CcdiAssetInfoVO assetInfoVO = new CcdiAssetInfoVO();
|
||||
BeanUtils.copyProperties(asset, assetInfoVO);
|
||||
return assetInfoVO;
|
||||
@@ -131,6 +131,7 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
|
||||
@Transactional
|
||||
public int insertBaseStaff(CcdiBaseStaffAddDTO addDTO) {
|
||||
validateAnnualIncome(addDTO.getAnnualIncome(), "年收入");
|
||||
validatePartyMember(addDTO.getPartyMember(), "是否党员");
|
||||
// 检查员工ID唯一性
|
||||
if (baseStaffMapper.selectById(addDTO.getStaffId()) != null) {
|
||||
throw new RuntimeException("该员工ID已存在");
|
||||
@@ -161,6 +162,7 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
|
||||
@Transactional
|
||||
public int updateBaseStaff(CcdiBaseStaffEditDTO editDTO) {
|
||||
validateAnnualIncome(editDTO.getAnnualIncome(), "年收入");
|
||||
validatePartyMember(editDTO.getPartyMember(), "是否党员");
|
||||
CcdiBaseStaff existing = baseStaffMapper.selectById(editDTO.getStaffId());
|
||||
if (existing == null) {
|
||||
throw new RuntimeException("员工不存在");
|
||||
@@ -291,4 +293,13 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
|
||||
}
|
||||
}
|
||||
|
||||
private void validatePartyMember(Integer partyMember, String fieldLabel) {
|
||||
if (partyMember == null) {
|
||||
throw new RuntimeException(fieldLabel + "不能为空");
|
||||
}
|
||||
if (partyMember != 0 && partyMember != 1) {
|
||||
throw new RuntimeException(fieldLabel + "只能填写'0'或'1'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,13 +14,14 @@
|
||||
<result property="phone" column="phone"/>
|
||||
<result property="annualIncome" column="annual_income"/>
|
||||
<result property="hireDate" column="hire_date"/>
|
||||
<result property="partyMember" column="is_party_member"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectBaseStaffPageWithDept" resultMap="CcdiBaseStaffVOResult">
|
||||
SELECT
|
||||
e.staff_id, e.name, e.dept_id, e.id_card, e.phone, e.annual_income, 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.is_party_member, 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
|
||||
@@ -47,12 +48,12 @@
|
||||
<!-- 批量插入或更新员工信息(只更新非null字段) -->
|
||||
<insert id="insertOrUpdateBatch" parameterType="java.util.List">
|
||||
INSERT INTO ccdi_base_staff
|
||||
(staff_id, name, dept_id, id_card, phone, annual_income, hire_date, status,
|
||||
(staff_id, name, dept_id, id_card, phone, annual_income, hire_date, is_party_member, 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.annualIncome}, #{item.hireDate}, #{item.status}, NOW(),
|
||||
#{item.phone}, #{item.annualIncome}, #{item.hireDate}, #{item.partyMember}, #{item.status}, NOW(),
|
||||
#{item.createBy}, #{item.updateBy}, NOW())
|
||||
</foreach>
|
||||
ON DUPLICATE KEY UPDATE
|
||||
@@ -61,6 +62,7 @@
|
||||
phone = COALESCE(VALUES(phone), phone),
|
||||
annual_income = COALESCE(VALUES(annual_income), annual_income),
|
||||
hire_date = COALESCE(VALUES(hire_date), hire_date),
|
||||
is_party_member = COALESCE(VALUES(is_party_member), is_party_member),
|
||||
status = COALESCE(VALUES(status), status),
|
||||
update_by = COALESCE(VALUES(update_by), update_by),
|
||||
update_time = NOW()
|
||||
@@ -69,12 +71,12 @@
|
||||
<!-- 批量插入员工信息 -->
|
||||
<insert id="insertBatch" parameterType="java.util.List">
|
||||
INSERT INTO ccdi_base_staff
|
||||
(staff_id, name, dept_id, id_card, phone, annual_income, hire_date, status,
|
||||
(staff_id, name, dept_id, id_card, phone, annual_income, hire_date, is_party_member, 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.annualIncome}, #{item.hireDate}, #{item.status}, NOW(),
|
||||
#{item.phone}, #{item.annualIncome}, #{item.hireDate}, #{item.partyMember}, #{item.status}, NOW(),
|
||||
#{item.createBy}, #{item.updateBy}, NOW())
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
@@ -17,6 +17,8 @@ class CcdiBaseStaffMapperTest {
|
||||
|
||||
assertTrue(xml.contains("annual_income"), xml);
|
||||
assertTrue(xml.contains("#{item.annualIncome}"), xml);
|
||||
assertTrue(xml.contains("is_party_member"), xml);
|
||||
assertTrue(xml.contains("#{item.partyMember}"), xml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,28 @@ class CcdiBaseStaffImportServiceImplTest {
|
||||
assertDoesNotThrow(() -> service.validateStaffData(buildDto(new BigDecimal("12345.67")), false, Collections.emptySet(), Collections.emptySet()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldAllowPartyMemberValuesZeroAndOne() {
|
||||
CcdiBaseStaffAddDTO nonPartyMember = buildDto(null);
|
||||
nonPartyMember.setPartyMember(0);
|
||||
CcdiBaseStaffAddDTO partyMember = buildDto(null);
|
||||
partyMember.setPartyMember(1);
|
||||
|
||||
assertDoesNotThrow(() -> service.validateStaffData(nonPartyMember, false, Collections.emptySet(), Collections.emptySet()));
|
||||
assertDoesNotThrow(() -> service.validateStaffData(partyMember, false, Collections.emptySet(), Collections.emptySet()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldRejectInvalidPartyMemberValue() {
|
||||
CcdiBaseStaffAddDTO dto = buildDto(null);
|
||||
dto.setPartyMember(2);
|
||||
|
||||
RuntimeException exception = assertThrows(RuntimeException.class,
|
||||
() -> service.validateStaffData(dto, false, Set.of(), Set.of()));
|
||||
|
||||
assertEquals("是否党员只能填写'0'或'1'", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateStaffData_shouldRejectNegativeAnnualIncome() {
|
||||
RuntimeException exception = assertThrows(RuntimeException.class,
|
||||
@@ -51,6 +73,7 @@ class CcdiBaseStaffImportServiceImplTest {
|
||||
dto.setIdCard("320101199001010014");
|
||||
dto.setPhone("13812345678");
|
||||
dto.setStatus("0");
|
||||
dto.setPartyMember(1);
|
||||
dto.setAnnualIncome(annualIncome);
|
||||
return dto;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ class CcdiBaseStaffServiceImplTest {
|
||||
addDTO.setIdCard("320101199001010011");
|
||||
addDTO.setPhone("13812345678");
|
||||
addDTO.setStatus("0");
|
||||
addDTO.setPartyMember(1);
|
||||
addDTO.setAnnualIncome(new BigDecimal("12345.67"));
|
||||
addDTO.setAssetInfoList(List.of(
|
||||
buildAssetDto("房产"),
|
||||
@@ -70,6 +71,7 @@ class CcdiBaseStaffServiceImplTest {
|
||||
assertEquals(1, result);
|
||||
ArgumentCaptor<CcdiBaseStaff> staffCaptor = ArgumentCaptor.forClass(CcdiBaseStaff.class);
|
||||
verify(baseStaffMapper).insert(staffCaptor.capture());
|
||||
assertEquals(1, staffCaptor.getValue().getPartyMember());
|
||||
assertEquals(new BigDecimal("12345.67"), staffCaptor.getValue().getAnnualIncome());
|
||||
ArgumentCaptor<List<CcdiAssetInfoDTO>> captor = ArgumentCaptor.forClass(List.class);
|
||||
verify(assetInfoService).replaceByFamilyId(eq("320101199001010011"), captor.capture());
|
||||
@@ -92,6 +94,7 @@ class CcdiBaseStaffServiceImplTest {
|
||||
editDTO.setIdCard("320101199001010011");
|
||||
editDTO.setPhone("13812345678");
|
||||
editDTO.setStatus("0");
|
||||
editDTO.setPartyMember(0);
|
||||
editDTO.setAnnualIncome(new BigDecimal("45678.90"));
|
||||
editDTO.setAssetInfoList(List.of(buildAssetDto("车辆")));
|
||||
|
||||
@@ -104,6 +107,7 @@ class CcdiBaseStaffServiceImplTest {
|
||||
assertEquals(1, result);
|
||||
ArgumentCaptor<CcdiBaseStaff> staffCaptor = ArgumentCaptor.forClass(CcdiBaseStaff.class);
|
||||
verify(baseStaffMapper).updateById(staffCaptor.capture());
|
||||
assertEquals(0, staffCaptor.getValue().getPartyMember());
|
||||
assertEquals(new BigDecimal("45678.90"), staffCaptor.getValue().getAnnualIncome());
|
||||
verify(assetInfoService, never()).deleteByFamilyId("320101199001010011");
|
||||
verify(assetInfoService).replaceByFamilyId("320101199001010011", editDTO.getAssetInfoList());
|
||||
@@ -122,6 +126,7 @@ class CcdiBaseStaffServiceImplTest {
|
||||
editDTO.setIdCard("320101199001010011");
|
||||
editDTO.setPhone("13812345678");
|
||||
editDTO.setStatus("0");
|
||||
editDTO.setPartyMember(1);
|
||||
editDTO.setAssetInfoList(List.of(buildAssetDto("车辆")));
|
||||
|
||||
when(baseStaffMapper.selectById(1001L)).thenReturn(existing);
|
||||
@@ -135,17 +140,18 @@ class CcdiBaseStaffServiceImplTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void selectBaseStaffById_shouldReturnAssetInfoList() {
|
||||
void selectBaseStaffById_shouldReturnSelfOwnedAssetInfoList() {
|
||||
CcdiBaseStaff staff = new CcdiBaseStaff();
|
||||
staff.setStaffId(1001L);
|
||||
staff.setName("张三");
|
||||
staff.setIdCard("320101199001010011");
|
||||
staff.setStatus("0");
|
||||
staff.setPartyMember(1);
|
||||
staff.setAnnualIncome(new BigDecimal("88888.88"));
|
||||
|
||||
CcdiAssetInfo assetInfo = new CcdiAssetInfo();
|
||||
assetInfo.setFamilyId("320101199001010011");
|
||||
assetInfo.setPersonId("320101199201010022");
|
||||
assetInfo.setPersonId("320101199001010011");
|
||||
assetInfo.setAssetMainType("车辆");
|
||||
assetInfo.setAssetSubType("小汽车");
|
||||
assetInfo.setAssetName("家庭车辆");
|
||||
@@ -153,14 +159,16 @@ class CcdiBaseStaffServiceImplTest {
|
||||
assetInfo.setAssetStatus("正常");
|
||||
|
||||
when(baseStaffMapper.selectById(1001L)).thenReturn(staff);
|
||||
when(assetInfoService.selectByFamilyId("320101199001010011")).thenReturn(List.of(assetInfo));
|
||||
when(assetInfoService.selectByFamilyIdAndPersonId("320101199001010011", "320101199001010011"))
|
||||
.thenReturn(List.of(assetInfo));
|
||||
|
||||
CcdiBaseStaffVO result = service.selectBaseStaffById(1001L);
|
||||
|
||||
assertNotNull(result.getAssetInfoList());
|
||||
assertEquals(1, result.getPartyMember());
|
||||
assertEquals(new BigDecimal("88888.88"), result.getAnnualIncome());
|
||||
assertEquals(1, result.getAssetInfoList().size());
|
||||
assertEquals("320101199201010022", result.getAssetInfoList().get(0).getPersonId());
|
||||
assertEquals("320101199001010011", result.getAssetInfoList().get(0).getPersonId());
|
||||
assertEquals("车辆", result.getAssetInfoList().get(0).getAssetMainType());
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.ruoyi.info.collection.utils;
|
||||
|
||||
import com.ruoyi.common.core.domain.entity.SysDictData;
|
||||
import com.ruoyi.common.utils.DictUtils;
|
||||
import com.ruoyi.info.collection.domain.excel.CcdiBaseStaffExcel;
|
||||
import com.ruoyi.info.collection.domain.excel.CcdiAssetInfoExcel;
|
||||
import com.ruoyi.info.collection.domain.excel.CcdiStaffFmyRelationExcel;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
@@ -72,6 +73,31 @@ class EasyExcelUtilTemplateTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void importTemplateWithDictDropdown_shouldAddPartyMemberDropdownToBaseStaffTemplate() throws Exception {
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
try (MockedStatic<DictUtils> mocked = mockStatic(DictUtils.class)) {
|
||||
mocked.when(() -> DictUtils.getDictCache("ccdi_employee_status"))
|
||||
.thenReturn(List.of(
|
||||
buildDictData("在职", "0"),
|
||||
buildDictData("离职", "1")
|
||||
));
|
||||
mocked.when(() -> DictUtils.getDictCache("ccdi_yes_no_flag"))
|
||||
.thenReturn(List.of(
|
||||
buildDictData("是", "1"),
|
||||
buildDictData("否", "0")
|
||||
));
|
||||
|
||||
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiBaseStaffExcel.class, "员工信息");
|
||||
}
|
||||
|
||||
try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
|
||||
Sheet sheet = workbook.getSheetAt(0);
|
||||
assertTrue(hasValidationOnColumn(sheet, 7), "是否党员列应包含下拉校验");
|
||||
}
|
||||
}
|
||||
|
||||
private void assertTextColumn(Sheet sheet, int columnIndex) {
|
||||
CellStyle style = sheet.getColumnStyle(columnIndex);
|
||||
assertNotNull(style, "文本列应设置默认样式");
|
||||
@@ -90,9 +116,13 @@ class EasyExcelUtilTemplateTest {
|
||||
}
|
||||
|
||||
private SysDictData buildDictData(String label) {
|
||||
return buildDictData(label, label);
|
||||
}
|
||||
|
||||
private SysDictData buildDictData(String label, String value) {
|
||||
SysDictData dictData = new SysDictData();
|
||||
dictData.setDictLabel(label);
|
||||
dictData.setDictValue(label);
|
||||
dictData.setDictValue(value);
|
||||
return dictData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
# 员工基础信息新增是否党员字段后端实施计划
|
||||
|
||||
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 在员工基础信息后端链路中新增“是否党员”字段,保证数据库、实体、接口、导入导出与最小测试契约保持一致。
|
||||
|
||||
**Architecture:** 继续沿用 `ccdi_base_staff` 现有维护链路,在表上增加 `is_party_member` 字段,并在 `CcdiBaseStaff` 的实体、DTO、VO、Excel、Mapper XML 与服务校验中同步补齐。实现保持最短路径,不新增新的接口层或旁路转换逻辑,只在现有员工维护链路上扩字段。
|
||||
|
||||
**Tech Stack:** MySQL, Java 21, Spring Boot 3, MyBatis Plus, EasyExcel, JUnit 5, Markdown
|
||||
|
||||
---
|
||||
|
||||
## 文件结构与职责
|
||||
|
||||
**后端源码**
|
||||
|
||||
- `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/CcdiBaseStaff.java`
|
||||
新增 `partyMember` 字段并映射 `is_party_member`。
|
||||
- `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiBaseStaffAddDTO.java`
|
||||
新增新增接口入参字段与非空校验。
|
||||
- `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiBaseStaffEditDTO.java`
|
||||
新增编辑接口入参字段与非空校验。
|
||||
- `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/CcdiBaseStaffVO.java`
|
||||
新增详情/列表返回字段。
|
||||
- `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/excel/CcdiBaseStaffExcel.java`
|
||||
新增 Excel 导入导出列,并挂接“是/否”字典下拉。
|
||||
- `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/ImportFailureVO.java`
|
||||
新增导入失败记录字段回显。
|
||||
- `ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiBaseStaffMapper.xml`
|
||||
在列表查询、批量新增、批量更新 SQL 中补 `is_party_member`。
|
||||
- `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiBaseStaffServiceImpl.java`
|
||||
补新增/编辑链路校验,约束 `partyMember` 只能为 `0/1`。
|
||||
- `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiBaseStaffImportServiceImpl.java`
|
||||
补导入链路的必填和枚举值校验。
|
||||
|
||||
**SQL**
|
||||
|
||||
- `sql/migration/2026-04-17-add-base-staff-party-member.sql`
|
||||
以幂等方式为 `ccdi_base_staff` 增加字段,并补充 `ccdi_yes_no_flag` 字典数据。
|
||||
- `sql/ccdi_yes_no_flag_dict.sql`
|
||||
提供“是/否标记”字典初始化脚本,供新环境或独立初始化使用。
|
||||
|
||||
**测试**
|
||||
|
||||
- `ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiBaseStaffServiceImplTest.java`
|
||||
验证服务层新增/修改/详情查询会透传 `partyMember`。
|
||||
- `ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiBaseStaffImportServiceImplTest.java`
|
||||
验证导入场景仅允许 `0/1`。
|
||||
- `ccdi-info-collection/src/test/java/com/ruoyi/info/collection/mapper/CcdiBaseStaffMapperTest.java`
|
||||
验证 Mapper XML 已包含 `is_party_member` 与 `#{item.partyMember}`。
|
||||
- `ccdi-info-collection/src/test/java/com/ruoyi/info/collection/utils/EasyExcelUtilTemplateTest.java`
|
||||
验证员工模板已补“是否党员”下拉列。
|
||||
|
||||
## 实施步骤
|
||||
|
||||
- [ ] 在 `ccdi_base_staff` 表增加 `is_party_member`,默认值为 `0`,避免历史数据为空。
|
||||
- [ ] 在员工基础信息实体、DTO、VO、Excel 对象中补齐 `partyMember`。
|
||||
- [ ] 在 `CcdiBaseStaffMapper.xml` 的列表、批量新增、批量更新 SQL 中补 `is_party_member`。
|
||||
- [ ] 在 `CcdiBaseStaffServiceImpl` 与 `CcdiBaseStaffImportServiceImpl` 中增加 `0/1` 值域校验。
|
||||
- [ ] 新增 `ccdi_yes_no_flag` 字典脚本,保证导入模板下拉可用。
|
||||
- [ ] 补充并执行后端定向测试;若执行受现有依赖问题阻塞,需要在记录中明确注明阻塞原因。
|
||||
|
||||
## 验证记录
|
||||
|
||||
- 已尝试执行:
|
||||
|
||||
```bash
|
||||
mvn -pl ccdi-info-collection -Dtest=CcdiBaseStaffServiceImplTest,CcdiBaseStaffImportServiceImplTest,CcdiBaseStaffMapperTest,EasyExcelUtilTemplateTest test
|
||||
mvn -pl ccdi-info-collection -DskipTests compile
|
||||
```
|
||||
|
||||
- 当前结果:
|
||||
- `test` 在进入本次新增断言前,被模块内既有测试编译问题拦截,表现为缺少 `org.springframework.data.redis.core.*` 类型。
|
||||
- `compile` 被模块当前既有依赖缺失拦截,表现为缺少 `com.ruoyi.common.annotation.*`、`org.springframework.data.redis.core.*`、`IdCardUtil` 等类型。
|
||||
- 上述阻塞不是本次“是否党员”字段新增引入的新问题,但会影响自动化验证结论,需要后续先修复模块依赖基线。
|
||||
|
||||
## 完成标准
|
||||
|
||||
- 员工基础信息接口可读写 `partyMember`
|
||||
- 员工列表、详情、导入导出链路都包含 `partyMember`
|
||||
- 数据库字段与字典 SQL 已补齐
|
||||
- 后端测试契约已同步更新
|
||||
- 已明确记录当前自动化验证阻塞点
|
||||
@@ -0,0 +1,22 @@
|
||||
# 员工信息仅展示本人资产后端实施计划
|
||||
|
||||
## 变更目标
|
||||
|
||||
- 员工详情接口返回的 `assetInfoList` 仅包含员工本人资产
|
||||
- 员工信息页不再通过详情接口混入亲属资产数据
|
||||
|
||||
## 变更范围
|
||||
|
||||
- `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiBaseStaffServiceImpl.java`
|
||||
- `ccdi-info-collection/src/test/java/com/ruoyi/info/collection/service/CcdiBaseStaffServiceImplTest.java`
|
||||
|
||||
## 实施步骤
|
||||
|
||||
1. 将员工详情聚合资产的查询口径从 `family_id = 员工身份证号` 调整为 `family_id = 员工身份证号 and person_id = 员工身份证号`
|
||||
2. 保持员工新增、编辑时的 `replaceByFamilyId` 逻辑不变,继续由后端写入本人资产
|
||||
3. 调整单元测试,验证员工详情仅返回本人资产
|
||||
|
||||
## 验证要点
|
||||
|
||||
- 查询员工详情时,`assetInfoList` 不再返回亲属资产
|
||||
- 现有员工新增、编辑、删除链路不受影响
|
||||
@@ -0,0 +1,23 @@
|
||||
# 修复员工资产信息表注释乱码后端实施计划
|
||||
|
||||
## 变更目标
|
||||
|
||||
- 修复 `ccdi_asset_info` 表中 `family_id`、`person_id` 列注释乱码问题
|
||||
- 保持表结构、字段类型和业务数据不变,仅修正元数据注释
|
||||
|
||||
## 变更范围
|
||||
|
||||
- `sql/migration/2026-04-17-fix-ccdi-asset-info-comment-encoding.sql`
|
||||
|
||||
## 实施步骤
|
||||
|
||||
1. 查询 `information_schema.COLUMNS`,确认 `ccdi_asset_info` 列注释实际存在乱码
|
||||
2. 新增增量 SQL,使用 `ALTER TABLE ... MODIFY COLUMN ... COMMENT` 修复 `family_id`、`person_id` 注释
|
||||
3. 通过 `bin/mysql_utf8_exec.sh` 以 `utf8mb4` 会话执行脚本
|
||||
4. 再次查询 `information_schema.COLUMNS` 验证注释已恢复为中文
|
||||
|
||||
## 验证要点
|
||||
|
||||
- `family_id` 注释显示为“归属员工证件号”
|
||||
- `person_id` 注释显示为“资产实际持有人证件号”
|
||||
- 字段类型仍为 `VARCHAR(100) NOT NULL`
|
||||
@@ -0,0 +1,33 @@
|
||||
# 员工信息页资产提示文案移除前端实施计划
|
||||
|
||||
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 移除员工信息页资产信息区域中“员工信息页仅维护员工本人资产”“资产持有人默认为当前员工本人,无需额外填写”的备注展示。
|
||||
|
||||
**Architecture:** 本次仅调整员工信息维护页模板展示,不改动资产表单字段、默认值、提交参数或后端接口。实现上直接删除备注 DOM 和对应样式,保持页面其余交互不变。
|
||||
|
||||
**Tech Stack:** Vue 2, Element UI, JavaScript, Markdown
|
||||
|
||||
---
|
||||
|
||||
## 文件结构与职责
|
||||
|
||||
- `ruoyi-ui/src/views/ccdiBaseStaff/index.vue`
|
||||
删除资产信息区域的备注文案和无用样式。
|
||||
|
||||
## 实施步骤
|
||||
|
||||
- [ ] 删除资产信息区备注展示块
|
||||
- [ ] 删除 `assets-helper` 对应样式,避免残留无用 CSS
|
||||
- [ ] 运行前端构建确认页面模板调整未引入语法错误
|
||||
|
||||
## 验证
|
||||
|
||||
```bash
|
||||
source ~/.nvm/nvm.sh && nvm use 14.21.3 >/dev/null && npm run build:prod
|
||||
```
|
||||
|
||||
## 完成标准
|
||||
|
||||
- 员工信息页不再展示上述两条资产备注
|
||||
- 资产新增、编辑、提交逻辑保持不变
|
||||
@@ -0,0 +1,53 @@
|
||||
# 员工基础信息新增是否党员字段前端实施计划
|
||||
|
||||
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 在员工信息维护页面新增“是否党员”基础字段,并打通列表展示、详情回显、编辑录入与导入失败记录展示。
|
||||
|
||||
**Architecture:** 保持 `ruoyi-ui/src/views/ccdiBaseStaff/index.vue` 的现有页面结构不变,仅在已有“基本信息”区域与员工列表中插入一个新字段。字段值与后端保持一致,前端统一使用 `0/1` 数值口径,并通过页面内格式化方法展示为“是/否”。
|
||||
|
||||
**Tech Stack:** Vue 2, Element UI, JavaScript, npm, nvm, Markdown
|
||||
|
||||
---
|
||||
|
||||
## 文件结构与职责
|
||||
|
||||
**前端源码**
|
||||
|
||||
- `ruoyi-ui/src/views/ccdiBaseStaff/index.vue`
|
||||
新增列表列、编辑表单、详情弹窗、失败记录弹窗和格式化方法。
|
||||
|
||||
**依赖接口**
|
||||
|
||||
- `ruoyi-ui/src/api/ccdiBaseStaff.js`
|
||||
本次接口路径不变,继续复用现有新增/编辑/详情 API,只承接新增字段。
|
||||
|
||||
## 实施步骤
|
||||
|
||||
- [ ] 在员工列表中增加“是否党员”列,统一显示“是/否”。
|
||||
- [ ] 在新增/编辑弹窗的基本信息区域增加“是否党员”单选项,默认值设为“否”。
|
||||
- [ ] 在详情弹窗中增加“是否党员”展示,保证历史员工查看时能回显。
|
||||
- [ ] 在导入失败记录弹窗中增加“是否党员”列,便于排查模板数据问题。
|
||||
- [ ] 在页面 methods 中新增 `formatPartyMember`,统一处理 `0/1/null` 的展示。
|
||||
- [ ] 使用 `nvm` 选择当前机器可用的 Node 版本后执行前端构建验证。
|
||||
|
||||
## 验证记录
|
||||
|
||||
- 已尝试执行:
|
||||
|
||||
```bash
|
||||
source ~/.nvm/nvm.sh && nvm use
|
||||
source ~/.nvm/nvm.sh && nvm use 14.21.3 && npm run build:prod
|
||||
```
|
||||
|
||||
- 当前结果:
|
||||
- 仓库内未提供 `.nvmrc`,直接执行 `nvm use` 无法自动切到项目版本。
|
||||
- 当前机器存在 `v14.21.3`、`v25.9.0` 与 `system(v24.14.0)`,后续前端验证建议优先使用 `v14.21.3`。
|
||||
- 已使用 `v14.21.3` 成功执行 `npm run build:prod`,构建通过,仅保留项目原有的包体积告警。
|
||||
|
||||
## 完成标准
|
||||
|
||||
- 员工列表、详情、编辑弹窗可见“是否党员”
|
||||
- 提交新增/编辑时会带上 `partyMember`
|
||||
- 导入失败记录能展示该字段
|
||||
- 已明确前端构建使用 `nvm` 的版本前提与当前环境限制
|
||||
@@ -0,0 +1,24 @@
|
||||
# 员工信息仅展示本人资产前端实施计划
|
||||
|
||||
## 变更目标
|
||||
|
||||
- 员工信息页资产区域统一按“本人资产”口径展示
|
||||
- 详情弹窗移除“资产实际持有人身份证号”和“归属类型”
|
||||
- 员工资产编辑表单不再保留亲属资产相关提示与校验
|
||||
|
||||
## 变更范围
|
||||
|
||||
- `ruoyi-ui/src/views/ccdiBaseStaff/index.vue`
|
||||
|
||||
## 实施步骤
|
||||
|
||||
1. 更新资产信息区提示文案,明确员工信息页仅维护员工本人资产
|
||||
2. 删除详情弹窗中的“资产实际持有人身份证号”“归属类型”列
|
||||
3. 清理表单中 `personId` 的必填与格式校验,新增资产时默认带入当前员工身份证号
|
||||
4. 更新员工资产导入弹窗提示文案,明确仅允许导入员工本人资产
|
||||
|
||||
## 验证要点
|
||||
|
||||
- 员工详情弹窗仅显示本人资产字段
|
||||
- 新增、编辑员工资产时不再出现亲属资产口径提示
|
||||
- 员工身份证号变更后,表单内资产仍跟随当前员工身份证号
|
||||
@@ -116,6 +116,11 @@
|
||||
<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="partyMember" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatPartyMember(scope.row.partyMember) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<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>
|
||||
@@ -217,7 +222,14 @@
|
||||
<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-col :span="12">
|
||||
<el-form-item label="是否党员" prop="partyMember">
|
||||
<el-radio-group v-model="form.partyMember">
|
||||
<el-radio :label="1">是</el-radio>
|
||||
<el-radio :label="0">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
@@ -229,10 +241,6 @@
|
||||
<span>资产信息</span>
|
||||
<el-button type="primary" plain size="mini" icon="el-icon-plus" @click="handleAddAsset">新增资产</el-button>
|
||||
</div>
|
||||
<div class="assets-helper">
|
||||
<div>新增、编辑时无需填写实际持有人身份证号</div>
|
||||
<div>系统会默认带入并保留已有归属信息</div>
|
||||
</div>
|
||||
<el-form-item label-width="0" prop="assetInfoList">
|
||||
<div v-if="!form.assetInfoList || !form.assetInfoList.length" class="empty-assets">
|
||||
<i class="el-icon-office-building"></i>
|
||||
@@ -333,6 +341,9 @@
|
||||
<el-descriptions-item label="入职时间">
|
||||
{{ employeeDetail.hireDate ? parseTime(employeeDetail.hireDate, '{y}-{m}-{d}') : '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="是否党员">
|
||||
{{ formatPartyMember(employeeDetail.partyMember) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
<el-tag v-if="employeeDetail.status === '0'" type="success" size="small">在职</el-tag>
|
||||
<el-tag v-else type="danger" size="small">离职</el-tag>
|
||||
@@ -351,12 +362,6 @@
|
||||
暂无资产信息
|
||||
</div>
|
||||
<el-table v-else :data="employeeDetail.assetInfoList" border class="detail-assets-table">
|
||||
<el-table-column label="资产实际持有人身份证号" prop="personId" min-width="220" />
|
||||
<el-table-column label="归属类型" prop="ownerType" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatAssetOwnerType(scope.row) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="资产大类" prop="assetMainType" min-width="120" />
|
||||
<el-table-column label="资产小类" prop="assetSubType" min-width="120" />
|
||||
<el-table-column label="资产名称" prop="assetName" min-width="140" />
|
||||
@@ -429,7 +434,7 @@
|
||||
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline;" @click="importAssetTemplate">下载员工资产模板</el-link>
|
||||
</div>
|
||||
<div class="el-upload__tip" slot="tip">
|
||||
<span>仅支持导入员工本人资产数据,文件需为"xls"或"xlsx"格式,系统将根据 personId/person_id 自动识别归属员工。</span>
|
||||
<span>仅支持导入员工本人资产数据,文件需为"xls"或"xlsx"格式,导入身份证号需与员工本人一致。</span>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
@@ -460,12 +465,17 @@
|
||||
style="margin-bottom: 15px"
|
||||
/>
|
||||
|
||||
<el-table :data="failureList" v-loading="failureLoading">
|
||||
<el-table :data="failureList" v-loading="failureLoading">
|
||||
<el-table-column label="姓名" prop="name" align="center" />
|
||||
<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="partyMember" align="center" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatPartyMember(scope.row.partyMember) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="失败原因" prop="errorMessage" align="center" min-width="200" :show-overflow-tooltip="true" />
|
||||
</el-table>
|
||||
|
||||
@@ -622,6 +632,9 @@ export default {
|
||||
annualIncome: [
|
||||
{ validator: (rule, value, callback) => this.validateAnnualIncomeRule(value, callback, "年收入"), trigger: "blur" }
|
||||
],
|
||||
partyMember: [
|
||||
{ required: true, message: "请选择是否党员", trigger: "change" }
|
||||
],
|
||||
status: [
|
||||
{ required: true, message: "请选择状态", trigger: "change" }
|
||||
]
|
||||
@@ -701,8 +714,14 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'form.idCard'(newIdCard, oldIdCard) {
|
||||
this.syncAssetPersonIds(newIdCard, oldIdCard);
|
||||
'form.idCard'(newIdCard) {
|
||||
if (!Array.isArray(this.form.assetInfoList)) {
|
||||
return;
|
||||
}
|
||||
this.form.assetInfoList = this.form.assetInfoList.map(asset => ({
|
||||
...asset,
|
||||
personId: newIdCard || ""
|
||||
}));
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@@ -956,6 +975,7 @@ export default {
|
||||
phone: null,
|
||||
annualIncome: null,
|
||||
hireDate: null,
|
||||
partyMember: 0,
|
||||
status: "0",
|
||||
relatives: [],
|
||||
assetInfoList: []
|
||||
@@ -1008,7 +1028,6 @@ export default {
|
||||
},
|
||||
validateAssetInfoList(assetInfoList) {
|
||||
const requiredFields = [
|
||||
{ key: "personId", label: "资产实际持有人身份证号" },
|
||||
{ key: "assetMainType", label: "资产大类" },
|
||||
{ key: "assetSubType", label: "资产小类" },
|
||||
{ key: "assetName", label: "资产名称" },
|
||||
@@ -1033,11 +1052,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
if (!idCardPattern.test(asset.personId)) {
|
||||
this.$modal.msgError(`第${rowNo}条资产的资产实际持有人身份证号格式不正确`);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const field of numericFields) {
|
||||
const value = asset[field.key];
|
||||
if (value !== null && value !== undefined && String(value).trim() !== "") {
|
||||
@@ -1056,9 +1070,9 @@ export default {
|
||||
|
||||
return true;
|
||||
},
|
||||
createEmptyAssetRow(defaultPersonId = "") {
|
||||
createEmptyAssetRow() {
|
||||
return {
|
||||
personId: defaultPersonId || "",
|
||||
personId: this.form.idCard || "",
|
||||
assetMainType: "",
|
||||
assetSubType: "",
|
||||
assetName: "",
|
||||
@@ -1080,29 +1094,11 @@ export default {
|
||||
return value !== null && value !== undefined && String(value).trim() !== "";
|
||||
});
|
||||
},
|
||||
syncAssetPersonIds(newIdCard, oldIdCard) {
|
||||
if (!Array.isArray(this.form.assetInfoList)) {
|
||||
return;
|
||||
}
|
||||
this.form.assetInfoList = this.form.assetInfoList.map(asset => {
|
||||
if (!asset || typeof asset !== "object") {
|
||||
return asset;
|
||||
}
|
||||
const shouldSync = !asset.personId || asset.personId === oldIdCard;
|
||||
if (!shouldSync) {
|
||||
return asset;
|
||||
}
|
||||
return {
|
||||
...asset,
|
||||
personId: newIdCard || ""
|
||||
};
|
||||
});
|
||||
},
|
||||
handleAddAsset() {
|
||||
if (!Array.isArray(this.form.assetInfoList)) {
|
||||
this.form.assetInfoList = [];
|
||||
}
|
||||
this.form.assetInfoList.push(this.createEmptyAssetRow(this.form.idCard));
|
||||
this.form.assetInfoList.push(this.createEmptyAssetRow());
|
||||
},
|
||||
handleRemoveAsset(index) {
|
||||
if (!Array.isArray(this.form.assetInfoList)) {
|
||||
@@ -1110,11 +1106,14 @@ export default {
|
||||
}
|
||||
this.form.assetInfoList.splice(index, 1);
|
||||
},
|
||||
formatAssetOwnerType(asset) {
|
||||
if (!asset) {
|
||||
return "-";
|
||||
formatPartyMember(value) {
|
||||
if (value === 1 || value === "1") {
|
||||
return "是";
|
||||
}
|
||||
return asset.personId && asset.personId === this.employeeDetail.idCard ? "本人" : "亲属";
|
||||
if (value === 0 || value === "0") {
|
||||
return "否";
|
||||
}
|
||||
return "-";
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
@@ -1159,6 +1158,7 @@ export default {
|
||||
getBaseStaff(staffId).then(response => {
|
||||
this.form = {
|
||||
...response.data,
|
||||
partyMember: response.data.partyMember !== null && response.data.partyMember !== undefined ? response.data.partyMember : 0,
|
||||
assetInfoList: response.data.assetInfoList || []
|
||||
};
|
||||
this.form.annualIncome = response.data.annualIncome;
|
||||
@@ -1673,16 +1673,6 @@ export default {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.employee-edit-dialog .assets-helper {
|
||||
margin: -4px 0 12px;
|
||||
padding: 10px 12px;
|
||||
background: #f4f8ff;
|
||||
border: 1px solid #d9ecff;
|
||||
border-radius: 6px;
|
||||
color: #606266;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.employee-edit-dialog .assets-table-wrapper {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
|
||||
14
sql/ccdi_yes_no_flag_dict.sql
Normal file
14
sql/ccdi_yes_no_flag_dict.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
-- 是否标记字典初始化脚本
|
||||
|
||||
DELETE FROM sys_dict_data WHERE dict_type = 'ccdi_yes_no_flag';
|
||||
DELETE FROM sys_dict_type WHERE dict_type = 'ccdi_yes_no_flag';
|
||||
|
||||
INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark)
|
||||
VALUES ('是否标记', 'ccdi_yes_no_flag', '0', 'admin', NOW(), '是否标记列表');
|
||||
|
||||
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark)
|
||||
VALUES
|
||||
(1, '是', '1', 'ccdi_yes_no_flag', '', 'primary', 'N', '0', 'admin', NOW(), '是'),
|
||||
(2, '否', '0', 'ccdi_yes_no_flag', '', 'danger', 'Y', '0', 'admin', NOW(), '否');
|
||||
|
||||
-- 执行完成后,请在字典管理中刷新缓存,确保模板下拉立即生效。
|
||||
33
sql/migration/2026-04-17-add-base-staff-party-member.sql
Normal file
33
sql/migration/2026-04-17-add-base-staff-party-member.sql
Normal file
@@ -0,0 +1,33 @@
|
||||
SET @base_staff_party_member_sql = IF(
|
||||
EXISTS(
|
||||
SELECT 1
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = DATABASE()
|
||||
AND table_name = 'ccdi_base_staff'
|
||||
AND column_name = 'is_party_member'
|
||||
),
|
||||
'SELECT 1',
|
||||
'ALTER TABLE `ccdi_base_staff` ADD COLUMN `is_party_member` TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''是否党员:0-否 1-是'' AFTER `hire_date`'
|
||||
);
|
||||
|
||||
PREPARE base_staff_party_member_stmt FROM @base_staff_party_member_sql;
|
||||
EXECUTE base_staff_party_member_stmt;
|
||||
DEALLOCATE PREPARE base_staff_party_member_stmt;
|
||||
|
||||
INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark)
|
||||
SELECT '是否标记', 'ccdi_yes_no_flag', '0', 'admin', NOW(), '是否标记列表'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_dict_type WHERE dict_type = 'ccdi_yes_no_flag'
|
||||
);
|
||||
|
||||
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark)
|
||||
SELECT 1, '是', '1', 'ccdi_yes_no_flag', '', 'primary', 'N', '0', 'admin', NOW(), '是'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_dict_data WHERE dict_type = 'ccdi_yes_no_flag' AND dict_value = '1'
|
||||
);
|
||||
|
||||
INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark)
|
||||
SELECT 2, '否', '0', 'ccdi_yes_no_flag', '', 'danger', 'Y', '0', 'admin', NOW(), '否'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM sys_dict_data WHERE dict_type = 'ccdi_yes_no_flag' AND dict_value = '0'
|
||||
);
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE `ccdi_asset_info`
|
||||
MODIFY COLUMN `family_id` VARCHAR(100) NOT NULL COMMENT '归属员工证件号',
|
||||
MODIFY COLUMN `person_id` VARCHAR(100) NOT NULL COMMENT '资产实际持有人证件号';
|
||||
Reference in New Issue
Block a user