调整员工信息维护列表和个人资料校验

This commit is contained in:
wjj
2026-07-16 09:51:35 +08:00
parent ded07a2c33
commit 15aa9117c3
7 changed files with 137 additions and 25 deletions

View File

@@ -28,6 +28,14 @@ public interface CcdiBaseStaffMapper extends BaseMapper<CcdiBaseStaff> {
Page<CcdiBaseStaffVO> selectBaseStaffPageWithDept(@Param("page") Page<CcdiBaseStaffVO> page, Page<CcdiBaseStaffVO> selectBaseStaffPageWithDept(@Param("page") Page<CcdiBaseStaffVO> page,
@Param("query") CcdiBaseStaffQueryDTO queryDTO); @Param("query") CcdiBaseStaffQueryDTO queryDTO);
/**
* 查询员工详情(包含部门名称)
*
* @param staffId 员工ID
* @return 员工详情
*/
CcdiBaseStaffVO selectBaseStaffByIdWithDept(@Param("staffId") Long staffId);
int insertOrUpdateBatch(@Param("list") List<CcdiBaseStaff> list); int insertOrUpdateBatch(@Param("list") List<CcdiBaseStaff> list);
/** /**

View File

@@ -119,10 +119,10 @@ public class CcdiBaseStaffServiceImpl implements ICcdiBaseStaffService {
*/ */
@Override @Override
public CcdiBaseStaffVO selectBaseStaffById(Long staffId) { public CcdiBaseStaffVO selectBaseStaffById(Long staffId) {
CcdiBaseStaff staff = baseStaffMapper.selectById(staffId); CcdiBaseStaffVO vo = baseStaffMapper.selectBaseStaffByIdWithDept(staffId);
CcdiBaseStaffVO vo = convertToVO(staff); if (vo != null) {
if (staff != null) { vo.setStatusDesc(EmployeeStatus.getDescByCode(vo.getStatus()));
vo.setAssetInfoList(assetInfoService.selectByFamilyIdAndPersonId(staff.getIdCard(), staff.getIdCard()).stream().map(asset -> { vo.setAssetInfoList(assetInfoService.selectByFamilyIdAndPersonId(vo.getIdCard(), vo.getIdCard()).stream().map(asset -> {
CcdiAssetInfoVO assetInfoVO = new CcdiAssetInfoVO(); CcdiAssetInfoVO assetInfoVO = new CcdiAssetInfoVO();
BeanUtils.copyProperties(asset, assetInfoVO); BeanUtils.copyProperties(asset, assetInfoVO);
return assetInfoVO; return assetInfoVO;

View File

@@ -42,7 +42,16 @@
AND e.status = #{query.status} AND e.status = #{query.status}
</if> </if>
</where> </where>
ORDER BY e.create_time DESC, e.staff_id DESC ORDER BY e.hire_date DESC, e.staff_id DESC
</select>
<select id="selectBaseStaffByIdWithDept" resultMap="CcdiBaseStaffVOResult">
SELECT
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
WHERE e.staff_id = #{staffId}
</select> </select>
<!-- 批量插入或更新员工信息只更新非null字段 --> <!-- 批量插入或更新员工信息只更新非null字段 -->

View File

@@ -0,0 +1,31 @@
# 员工信息维护列表与详情展示调整实施记录
## 修改时间
2026-07-15
## 修改内容
1. 员工信息维护列表移除首列多选框。
2. 列表“创建时间”列调整为“入职时间”,展示 `hireDate`,空值显示 `-`
3. 列表默认排序由创建时间倒序改为入职时间倒序,同一天按柜员号倒序。
4. 列表“身份证号”和“所属部门”列增加最小宽度,避免 18 位身份证号和部门名称显示过窄。
5. 员工列表首列增加左侧留白,移除多选框后保持表格视觉间距;入职时间列适当收窄,为前部字段释放横向空间。
6. 列表“年收入”字段按万元展示,列名调整为“年收入(万元)”,空值显示 `-`,有效数值保留 2 位小数;详情仍按原字段值展示且不显示小数位。
7. 员工详情接口改为关联 `sys_dept` 查询部门名称,修复详情“所属部门”为空的问题。
## 影响范围
- 前端页面:`ruoyi-ui/src/views/ccdiBaseStaff/index.vue`
- 后端 Mapper`ccdi-info-collection/src/main/java/com/ruoyi/info/collection/mapper/CcdiBaseStaffMapper.java`
- 后端 SQL`ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiBaseStaffMapper.xml`
- 后端服务:`ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiBaseStaffServiceImpl.java`
## 验证情况
- 后端编译验证:`mvn -pl ccdi-info-collection -am compile -DskipTests` 通过。
- 后端打包验证:`mvn -pl ruoyi-admin -am package -DskipTests` 通过。
- 后端启动验证Windows PowerShell 环境缺少 `sh``lsof``pgrep`,未使用 `bin/restart_java_backend.sh`;改用 Windows 原生命令重启真实 `ruoyi-admin.jar``http://127.0.0.1:62318/swagger-ui.html` 返回 200。
- 前端环境验证:`.nvmrc` 为 Node 14.21.3,但本机该版本切换后当前会话无法找到 `node/npm`;按项目规则改用 Node 22.22.3 + npm 10.9.8。
- 前端构建验证:`npm run build:prod` 通过,存在既有资源体积 warning。
- 页面验证:打开真实前端 `http://127.0.0.1:8088/maintain/baseStaff`,确认列表无多选框、表头为“入职时间”、身份证号列完整展示、列表按入职时间倒序展示;点击第一条员工详情,确认“所属部门”显示为部门名称。

View File

@@ -0,0 +1,20 @@
# 个人基本信息联系方式校验调整实施记录
## 修改时间
2026-07-16
## 修改内容
1. 个人基本信息编辑中,手机号码和邮箱取消必填限制。
2. 手机号码和邮箱保留可选格式校验:为空时允许保存;填写后仍需符合对应格式。
## 影响范围
- 前端个人资料页:`ruoyi-ui/src/views/system/user/profile/userInfo.vue`
## 验证情况
- 前端环境验证:使用 Node 22.22.3 + npm 10.9.8。
- 前端构建验证:`npm run build:prod` 通过,存在既有资源体积 warning。
- 页面验证:打开真实前端 `http://127.0.0.1:8088/user/profile`,清空手机号码和邮箱输入框并触发失焦,未出现必填提示。本次页面验证未点击保存,未修改用户资料。

View File

@@ -112,14 +112,17 @@
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="baseStaffList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="baseStaffList" class="base-staff-table">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="姓名" align="center" prop="name" :show-overflow-tooltip="true"/> <el-table-column label="姓名" align="center" prop="name" :show-overflow-tooltip="true"/>
<el-table-column label="柜员号" align="center" prop="staffId" :show-overflow-tooltip="true"/> <el-table-column label="柜员号" align="center" prop="staffId" :show-overflow-tooltip="true"/>
<el-table-column label="身份证号" align="center" prop="idCard" :show-overflow-tooltip="true"/> <el-table-column label="身份证号" align="center" prop="idCard" min-width="190" :show-overflow-tooltip="true"/>
<el-table-column label="所属部门" align="center" prop="deptName" :show-overflow-tooltip="true"/> <el-table-column label="所属部门" align="center" prop="deptName" min-width="180" :show-overflow-tooltip="true"/>
<el-table-column label="电话" align="center" prop="phone" width="120"/> <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="annualIncome" width="120">
<template slot-scope="scope">
<span>{{ formatAnnualIncomeWan(scope.row.annualIncome) }}</span>
</template>
</el-table-column>
<el-table-column label="是否党员" align="center" prop="partyMember" width="100"> <el-table-column label="是否党员" align="center" prop="partyMember" width="100">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ formatPartyMember(scope.row.partyMember) }}</span> <span>{{ formatPartyMember(scope.row.partyMember) }}</span>
@@ -131,9 +134,9 @@
<el-tag v-else type="danger">离职</el-tag> <el-tag v-else type="danger">离职</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180"> <el-table-column label="入职时间" align="center" prop="hireDate" width="140">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span> <span>{{ scope.row.hireDate ? parseTime(scope.row.hireDate, '{y}-{m}-{d}') : '-' }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
@@ -340,7 +343,7 @@
<el-descriptions-item label="身份证号">{{ employeeDetail.idCard || '-' }}</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.phone || '-' }}</el-descriptions-item>
<el-descriptions-item label="年收入"> <el-descriptions-item label="年收入">
{{ employeeDetail.annualIncome !== null && employeeDetail.annualIncome !== undefined && employeeDetail.annualIncome !== '' ? employeeDetail.annualIncome : '-' }} {{ formatAnnualIncome(employeeDetail.annualIncome) }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="入职时间"> <el-descriptions-item label="入职时间">
{{ employeeDetail.hireDate ? parseTime(employeeDetail.hireDate, '{y}-{m}-{d}') : '-' }} {{ employeeDetail.hireDate ? parseTime(employeeDetail.hireDate, '{y}-{m}-{d}') : '-' }}
@@ -967,6 +970,26 @@ export default {
maximumFractionDigits: 2 maximumFractionDigits: 2
})} 万元`; })} 万元`;
}, },
formatAnnualIncome(value) {
if (value === null || value === undefined || value === "") {
return "-";
}
const amount = Number(value);
if (!Number.isFinite(amount)) {
return "-";
}
return amount.toFixed(0);
},
formatAnnualIncomeWan(value) {
if (value === null || value === undefined || value === "") {
return "-";
}
const amount = Number(value);
if (!Number.isFinite(amount)) {
return "-";
}
return (amount / 10000).toFixed(2);
},
normalizeAnnualIncome(value) { normalizeAnnualIncome(value) {
if (value === null || value === undefined) { if (value === null || value === undefined) {
return null; return null;
@@ -1511,6 +1534,11 @@ export default {
margin-bottom: 10px; margin-bottom: 10px;
} }
.base-staff-table ::v-deep .el-table__header-wrapper th:first-child .cell,
.base-staff-table ::v-deep .el-table__body-wrapper td:first-child .cell {
padding-left: 24px;
}
/* 详情弹窗样式 */ /* 详情弹窗样式 */
.employee-detail-dialog .detail-container { .employee-detail-dialog .detail-container {
padding: 10px 0; padding: 10px 0;

View File

@@ -25,6 +25,32 @@
<script> <script>
import { updateUserProfile } from "@/api/system/user" import { updateUserProfile } from "@/api/system/user"
const validateOptionalEmail = (rule, value, callback) => {
if (!value) {
callback()
return
}
const emailPattern = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/
if (!emailPattern.test(value)) {
callback(new Error("请输入正确的邮箱地址"))
return
}
callback()
}
const validateOptionalPhone = (rule, value, callback) => {
if (!value) {
callback()
return
}
const phonePattern = /^1[3|4|5|6|7|8|9][0-9]\d{8}$/
if (!phonePattern.test(value)) {
callback(new Error("请输入正确的手机号码"))
return
}
callback()
}
export default { export default {
props: { props: {
user: { user: {
@@ -40,20 +66,10 @@ export default {
{ required: true, message: "用户昵称不能为空", trigger: "blur" } { required: true, message: "用户昵称不能为空", trigger: "blur" }
], ],
email: [ email: [
{ required: true, message: "邮箱地址不能为空", trigger: "blur" }, { validator: validateOptionalEmail, trigger: ["blur", "change"] }
{
type: "email",
message: "请输入正确的邮箱地址",
trigger: ["blur", "change"]
}
], ],
phonenumber: [ phonenumber: [
{ required: true, message: "手机号码不能为空", trigger: "blur" }, { validator: validateOptionalPhone, trigger: "blur" }
{
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
message: "请输入正确的手机号码",
trigger: "blur"
}
] ]
} }
} }