✨ 优化主数据校验与运单导入空值处理

电报略码改为选填且填写时唯一;用户支持账号姓名手机模糊查询;合同名称允许重复;项目情况说明扩至1000字;导入运单未填里程费用不再落库-1。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-09 17:07:56 +08:00
parent 5ed2a5c0fc
commit ef9eab737f
19 changed files with 164 additions and 54 deletions
@@ -112,11 +112,12 @@ public class UserController {
@GetMapping("/list")
@BladeView(Views.Admin.class)
@Parameters({
@Parameter(name = "account", description = "账号名", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
@Parameter(name = "realName", description = "姓名", in = ParameterIn.QUERY, schema = @Schema(type = "string"))
@Parameter(name = "account", description = "账号名(模糊)", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
@Parameter(name = "realName", description = "姓名(模糊)", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
@Parameter(name = "phone", description = "手机号(模糊)", in = ParameterIn.QUERY, schema = @Schema(type = "string"))
})
@ApiOperationSupport(order = 3)
@Operation(summary = "列表", description = "传入account和realName")
@Operation(summary = "列表", description = "传入account、realName、phone,支持模糊搜索")
public R<IPage<UserVO>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> user, Query query) {
return R.data(userService.selectPage(user, query));
}
@@ -128,11 +129,12 @@ public class UserController {
@GetMapping("/page")
@BladeView(Views.Admin.class)
@Parameters({
@Parameter(name = "account", description = "账号名", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
@Parameter(name = "realName", description = "姓名", in = ParameterIn.QUERY, schema = @Schema(type = "string"))
@Parameter(name = "account", description = "账号名(模糊)", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
@Parameter(name = "realName", description = "姓名(模糊)", in = ParameterIn.QUERY, schema = @Schema(type = "string")),
@Parameter(name = "phone", description = "手机号(模糊)", in = ParameterIn.QUERY, schema = @Schema(type = "string"))
})
@ApiOperationSupport(order = 4)
@Operation(summary = "列表", description = "传入account和realName")
@Operation(summary = "列表", description = "传入account、realName、phone,支持模糊搜索")
public R<IPage<UserVO>> page(@Parameter(hidden = true) User user, Query query, Long deptId, BladeUser bladeUser) {
IPage<User> pages = userService.selectUserPage(Condition.getPage(query), user, deptId, (AuthUtil.isAdministrator() ? StringPool.EMPTY : bladeUser.getTenantId()));
return R.data(UserWrapper.build().pageVO(pages));
@@ -54,7 +54,7 @@ public class RailwayStationExcel implements Serializable {
@ExcelProperty("TMIS国标编码*")
private String tmisCode;
@ExcelProperty("电报略码*")
@ExcelProperty("电报略码")
private String telegraphCode;
@ExcelProperty("车站名称*")
@@ -56,7 +56,7 @@ public class RailwayStationExportExcel implements Serializable {
@ExcelProperty("TMIS国标编码*")
private String tmisCode;
@ExcelProperty("电报略码*")
@ExcelProperty("电报略码")
private String telegraphCode;
@ExcelProperty("车站名称*")
@@ -44,16 +44,16 @@
and bu.tenant_id = #{user.tenantId}
</if>
<if test="user.account!=null and user.account != ''">
and bu.account like concat(concat('%', #{user.account}), '%')
and bu.account like concat('%', #{user.account}, '%')
</if>
<if test="user.realName!=null and user.realName != ''">
and bu.real_name like concat(concat('%', #{user.realName}), '%')
and (
bu.real_name like concat('%', #{user.realName}, '%')
or bu.name like concat('%', #{user.realName}, '%')
)
</if>
<if test="user.phone!=null and user.phone != ''">
and (
bu.phone like concat(concat('%', #{user.phone}), '%')
or bu.account like concat(concat('%', #{user.phone}), '%')
)
and bu.phone like concat('%', #{user.phone}, '%')
</if>
<if test="user.userType!=null and user.userType != ''">
and bu.user_type = #{user.userType}
@@ -207,7 +207,7 @@ public class RailwayStationServiceImpl extends BaseServiceImpl<RailwayStationMap
private void normalizeImportRailwayStation(RailwayStation railwayStation) {
railwayStation.setTmisCode(trimToEmpty(railwayStation.getTmisCode()));
railwayStation.setCode(CODE_PREFIX + railwayStation.getTmisCode());
railwayStation.setTelegraphCode(trimToEmpty(railwayStation.getTelegraphCode()).toUpperCase(Locale.ROOT));
railwayStation.setTelegraphCode(normalizeTelegraphCode(railwayStation.getTelegraphCode()));
railwayStation.setName(trimToEmpty(railwayStation.getName()));
railwayStation.setProvinceCode(trimToNull(railwayStation.getProvinceCode()));
railwayStation.setProvinceName(trimToNull(railwayStation.getProvinceName()));
@@ -247,9 +247,7 @@ public class RailwayStationServiceImpl extends BaseServiceImpl<RailwayStationMap
validateImportUnique(RailwayStation::getTmisCode, railwayStation.getTmisCode(), "该TMIS国标编码已存在", validationErrors);
validateImportUnique(RailwayStation::getCode, railwayStation.getCode(), "该编码已存在", validationErrors);
}
if (Func.isEmpty(railwayStation.getTelegraphCode())) {
addValidationError(validationErrors, "电报略码不能为空");
} else {
if (Func.isNotEmpty(railwayStation.getTelegraphCode())) {
if (!TELEGRAPH_CODE_PATTERN.matcher(railwayStation.getTelegraphCode()).matches()) {
addValidationError(validationErrors, "电报略码为3位大写字母");
}
@@ -377,7 +375,7 @@ public class RailwayStationServiceImpl extends BaseServiceImpl<RailwayStationMap
private void prepare(RailwayStation railwayStation, String defaultDataSource) {
railwayStation.setTmisCode(trimToEmpty(railwayStation.getTmisCode()));
railwayStation.setCode(CODE_PREFIX + railwayStation.getTmisCode());
railwayStation.setTelegraphCode(trimToEmpty(railwayStation.getTelegraphCode()).toUpperCase(Locale.ROOT));
railwayStation.setTelegraphCode(normalizeTelegraphCode(railwayStation.getTelegraphCode()));
railwayStation.setName(trimToEmpty(railwayStation.getName()));
railwayStation.setRailwayLine(trimToNull(railwayStation.getRailwayLine()));
railwayStation.setProvinceCode(trimToNull(railwayStation.getProvinceCode()));
@@ -410,10 +408,8 @@ public class RailwayStationServiceImpl extends BaseServiceImpl<RailwayStationMap
if (!TMIS_CODE_PATTERN.matcher(railwayStation.getTmisCode()).matches()) {
throw new ServiceException("TMIS国标编码为5位数字");
}
if (Func.isEmpty(railwayStation.getTelegraphCode())) {
throw new ServiceException("电报略码格式不正确或已存在");
}
if (!TELEGRAPH_CODE_PATTERN.matcher(railwayStation.getTelegraphCode()).matches()) {
if (Func.isNotEmpty(railwayStation.getTelegraphCode())
&& !TELEGRAPH_CODE_PATTERN.matcher(railwayStation.getTelegraphCode()).matches()) {
throw new ServiceException("电报略码格式不正确或已存在");
}
if (Func.isEmpty(railwayStation.getName())) {
@@ -446,7 +442,9 @@ public class RailwayStationServiceImpl extends BaseServiceImpl<RailwayStationMap
validateDataSource(railwayStation.getDataSource());
validateStatus(railwayStation.getStatus());
validateUnique(railwayStation, RailwayStation::getTmisCode, railwayStation.getTmisCode(), "该TMIS编码已存在");
validateUnique(railwayStation, RailwayStation::getTelegraphCode, railwayStation.getTelegraphCode(), "电报略码格式不正确或已存在");
if (Func.isNotEmpty(railwayStation.getTelegraphCode())) {
validateUnique(railwayStation, RailwayStation::getTelegraphCode, railwayStation.getTelegraphCode(), "电报略码格式不正确或已存在");
}
validateUnique(railwayStation, RailwayStation::getCode, railwayStation.getCode(), "该编码已存在");
}
@@ -562,6 +560,11 @@ public class RailwayStationServiceImpl extends BaseServiceImpl<RailwayStationMap
return trimValue.isEmpty() ? null : trimValue;
}
private String normalizeTelegraphCode(String value) {
String telegraphCode = trimToNull(value);
return telegraphCode == null ? null : telegraphCode.toUpperCase(Locale.ROOT);
}
private String normalizeDataSource(String dataSource) {
String value = trimToEmpty(dataSource);
if (SOURCE_INITIAL_OLD.equals(value)) {
@@ -133,8 +133,12 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
@Override
public IPage<UserVO> selectPage(Map<String, Object> user, Query query) {
String account = Func.toStr(user.remove("account")).trim();
String realName = Func.toStr(user.remove("realName")).trim();
String phone = Func.toStr(user.remove("phone")).trim();
QueryWrapper<User> queryWrapper = Condition.getQueryWrapper(user, User.class);
applyTenantScope(queryWrapper);
applyUserFuzzyFilters(queryWrapper, account, realName, phone);
return UserWrapper.build().pageVO(page(Condition.getPage(query), queryWrapper));
}
@@ -378,6 +382,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
@Override
public IPage<User> selectUserPage(IPage<User> page, User user, Long deptId, String tenantId) {
normalizeUserSearch(user);
List<Long> deptIdList = SysCache.getDeptChildIds(deptId);
return page.setRecords(baseMapper.selectUserPage(page, user, deptIdList, tenantId));
}
@@ -713,8 +718,12 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
@Override
public List<UserExcel> exportUser(Map<String, Object> user) {
String account = Func.toStr(user.remove("account")).trim();
String realName = Func.toStr(user.remove("realName")).trim();
String phone = Func.toStr(user.remove("phone")).trim();
QueryWrapper<User> queryWrapper = Condition.getQueryWrapper(user, User.class);
applyTenantScope(queryWrapper);
applyUserFuzzyFilters(queryWrapper, account, realName, phone);
queryWrapper.lambda().eq(User::getIsDeleted, BladeConstant.DB_NOT_DELETED);
return exportUser(queryWrapper);
}
@@ -1127,6 +1136,35 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
}
}
/**
* 归一化用户列表搜索条件,避免首尾空格导致模糊匹配失效。
*/
private void normalizeUserSearch(User user) {
if (user == null) {
return;
}
if (user.getAccount() != null) {
user.setAccount(user.getAccount().trim());
}
if (user.getRealName() != null) {
user.setRealName(user.getRealName().trim());
}
if (user.getPhone() != null) {
user.setPhone(user.getPhone().trim());
}
}
/**
* 账号名、姓名、手机号统一按模糊匹配过滤。
*/
private void applyUserFuzzyFilters(QueryWrapper<User> queryWrapper, String account, String realName, String phone) {
queryWrapper.lambda().like(StringUtil.isNotBlank(account), User::getAccount, account);
if (StringUtil.isNotBlank(realName)) {
queryWrapper.lambda().and(wrapper -> wrapper.like(User::getRealName, realName).or().like(User::getName, realName));
}
queryWrapper.lambda().like(StringUtil.isNotBlank(phone), User::getPhone, phone);
}
@Override
public void decryptPhone(IPhone user) {