【修改】表格修改项

This commit is contained in:
huababa1
2025-10-18 15:28:35 +08:00
parent a7fd185889
commit 24210dd1b7
42 changed files with 943 additions and 99 deletions

View File

@@ -18,6 +18,7 @@ import pc.exam.pp.module.system.convert.auth.AuthConvert;
import pc.exam.pp.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import pc.exam.pp.module.system.dal.dataobject.permission.MenuDO;
import pc.exam.pp.module.system.dal.dataobject.permission.RoleDO;
import pc.exam.pp.module.system.dal.dataobject.tenant.TenantDO;
import pc.exam.pp.module.system.dal.dataobject.user.AdminUserDO;
import pc.exam.pp.module.system.enums.logger.LoginLogTypeEnum;
import pc.exam.pp.module.system.service.auth.AdminAuthService;
@@ -25,6 +26,7 @@ import pc.exam.pp.module.system.service.permission.MenuService;
import pc.exam.pp.module.system.service.permission.PermissionService;
import pc.exam.pp.module.system.service.permission.RoleService;
import pc.exam.pp.module.system.service.social.SocialClientService;
import pc.exam.pp.module.system.service.tenant.TenantService;
import pc.exam.pp.module.system.service.user.AdminUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -37,6 +39,7 @@ import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import pc.exam.pp.module.system.util.oauth2.MacUtils;
import java.util.Collections;
import java.util.List;
@@ -79,6 +82,8 @@ public class AuthController {
private ConfigService configService;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private TenantService tenantService;
@GetMapping("/login_config")
@PermitAll
@@ -142,7 +147,7 @@ public class AuthController {
// 先判断管理员密码
ConfigDO config = configService.getConfigByKey("system_username_logout");
if (!config.getValue().equals(loginoutVo.getLoginOutPassword())) {
return CommonResult.error(900002, "系统管理员密码错误!");
return success("900002");
}
Set<String> oauth2_access_token_set = stringRedisTemplate.keys("oauth2_access_token:*");
for (String oauth2_access_token : oauth2_access_token_set) {

View File

@@ -7,10 +7,8 @@ import pc.exam.pp.framework.common.pojo.PageParam;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import pc.exam.pp.framework.excel.core.util.ExcelUtils;
import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantRespVO;
import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO;
import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantSpecialtyPointsVO;
import pc.exam.pp.framework.tenant.core.aop.TenantIgnore;
import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.*;
import pc.exam.pp.module.system.dal.dataobject.tenant.TenantDO;
import pc.exam.pp.module.system.dal.dataobject.tenant.TenantSpcialtyDO;
import pc.exam.pp.module.system.service.tenant.TenantService;
@@ -113,6 +111,7 @@ public class TenantController {
@GetMapping("/page")
@Operation(summary = "获得租户分页")
@PreAuthorize("@ss.hasPermission('system:tenant:query')")
@TenantIgnore
public CommonResult<PageResult<TenantRespVO>> getTenantPage(@Valid TenantPageReqVO pageVO) {
PageResult<TenantDO> pageResult = tenantService.getTenantPage(pageVO);
return success(BeanUtils.toBean(pageResult, TenantRespVO.class));
@@ -131,4 +130,14 @@ public class TenantController {
BeanUtils.toBean(list, TenantRespVO.class));
}
/**
* 重置租户管理员密码
*/
@PostMapping("/reset-password")
@Operation(summary = "重置租户管理员密码")
@TenantIgnore
public CommonResult<String> resetPassword(@RequestBody ResetPasswordReqVO reqVO) {
tenantService.resetPassword(reqVO);
return success("密码重置成功!");
}
}

View File

@@ -0,0 +1,9 @@
package pc.exam.pp.module.system.controller.admin.tenant.vo.tenant;
import lombok.Data;
@Data
public class ResetPasswordReqVO {
private Long id; // 租户ID 或 管理员ID
private String password; // 新密码
}

View File

@@ -19,8 +19,8 @@ public class TenantRespVO {
@ExcelProperty("租户编号")
private Long id;
@Schema(description = "户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
@ExcelProperty("户名")
@Schema(description = "学校用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
@ExcelProperty("学校用户名")
private String name;
@Schema(description = "联系人", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
@@ -36,7 +36,11 @@ public class TenantRespVO {
@DictFormat(DictTypeConstants.COMMON_STATUS)
private Integer status;
@Schema(description = "绑定域名", example = "https://www.iocoder.cn")
@Schema(description = "管理员账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "admin")
@ExcelProperty("管理员账号")
private String username;
@Schema(description = "绑定MAC地址", example = "https://www.iocoder.cn")
private String website;
@Schema(description = "租户套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@@ -52,4 +56,6 @@ public class TenantRespVO {
@ExcelProperty("创建时间")
private LocalDateTime createTime;
private String contactUserId;
}

View File

@@ -1,5 +1,6 @@
package pc.exam.pp.module.system.dal.dataobject.tenant;
import com.baomidou.mybatisplus.annotation.TableField;
import pc.exam.pp.framework.common.enums.CommonStatusEnum;
import pc.exam.pp.framework.mybatis.core.dataobject.BaseDO;
import pc.exam.pp.module.system.dal.dataobject.user.AdminUserDO;
@@ -79,5 +80,10 @@ public class TenantDO extends BaseDO {
private String queueName;
/**
* 管理员账号
*/
@TableField(exist = false)
private String username;
}

View File

@@ -70,4 +70,7 @@ public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {
List<UserRespVO> selectUserByIdList(@Param("id") Long id);
String selectOneById(Long id);
void updateByIdToPassword(@Param("password")String password, @Param("id")Long id);
}

View File

@@ -2,6 +2,7 @@ package pc.exam.pp.module.system.service.tenant;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.tenant.core.context.TenantContextHolder;
import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.ResetPasswordReqVO;
import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO;
import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantSpecialtyPointsVO;
@@ -145,4 +146,5 @@ public interface TenantService {
*/
void validTenant(Long id);
void resetPassword(ResetPasswordReqVO reqVO);
}

View File

@@ -4,16 +4,19 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.security.crypto.password.PasswordEncoder;
import pc.exam.pp.framework.common.enums.CommonStatusEnum;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.util.collection.CollectionUtils;
import pc.exam.pp.framework.common.util.date.DateUtils;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import pc.exam.pp.framework.mybatis.core.query.LambdaQueryWrapperX;
import pc.exam.pp.framework.tenant.config.TenantProperties;
import pc.exam.pp.framework.tenant.core.context.TenantContextHolder;
import pc.exam.pp.framework.tenant.core.util.TenantUtils;
import pc.exam.pp.module.exam.utils.rabbitmq.RabbitmqUtils;
import pc.exam.pp.module.system.controller.admin.permission.vo.role.RoleSaveReqVO;
import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.ResetPasswordReqVO;
import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO;
import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantSpecialtyPointsVO;
@@ -23,8 +26,10 @@ import pc.exam.pp.module.system.dal.dataobject.permission.RoleDO;
import pc.exam.pp.module.system.dal.dataobject.tenant.TenantDO;
import pc.exam.pp.module.system.dal.dataobject.tenant.TenantPackageDO;
import pc.exam.pp.module.system.dal.dataobject.tenant.TenantSpcialtyDO;
import pc.exam.pp.module.system.dal.dataobject.user.AdminUserDO;
import pc.exam.pp.module.system.dal.mysql.tenant.TenantMapper;
import pc.exam.pp.module.system.dal.mysql.tenant.TenantSpecialtyMapper;
import pc.exam.pp.module.system.dal.mysql.user.AdminUserMapper;
import pc.exam.pp.module.system.enums.permission.RoleCodeEnum;
import pc.exam.pp.module.system.enums.permission.RoleTypeEnum;
import pc.exam.pp.module.system.service.permission.MenuService;
@@ -81,7 +86,10 @@ public class TenantServiceImpl implements TenantService {
private MenuService menuService;
@Resource
private PermissionService permissionService;
@Resource
private AdminUserMapper userMapper;
@Resource
private PasswordEncoder passwordEncoder;
@Override
public List<Long> getTenantIdList() {
List<TenantDO> tenants = tenantMapper.selectList();
@@ -102,6 +110,13 @@ public class TenantServiceImpl implements TenantService {
}
}
@Override
public void resetPassword(ResetPasswordReqVO reqVO) {
AdminUserDO adminUserDO=new AdminUserDO();
String newPassword = passwordEncoder.encode(reqVO.getPassword());
userMapper.updateByIdToPassword(newPassword,reqVO.getId());
}
@Override
@DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换
public Long createTenant(TenantSaveReqVO createReqVO) {
@@ -276,7 +291,19 @@ public class TenantServiceImpl implements TenantService {
@Override
public PageResult<TenantDO> getTenantPage(TenantPageReqVO pageReqVO) {
return tenantMapper.selectPage(pageReqVO);
PageResult<TenantDO> tenantDOPageResult = tenantMapper.selectPage(pageReqVO);
List<TenantDO> list = tenantDOPageResult.getList();
if (list!=null&&list.size()>0){
for (TenantDO tenantDO : list) {
Long contactUserId = tenantDO.getContactUserId();
String userName= userMapper.selectOneById(contactUserId);
if (userName != null) {
tenantDO.setUsername(userName); //设置管理员账号
}
}
}
tenantDOPageResult.setList(list);
return tenantDOPageResult;
}
@Override

View File

@@ -840,17 +840,19 @@ public class AdminUserServiceImpl implements AdminUserService {
specialtyQueryVos = examSpecialtyMapper.selectExamSpecialtyAll();
} else {
// 查询部分数据
List<SpecialtyQueryVo> specialtyList = examSpecialtyMapper.selectExamSpecialtyByids(adminUserDO.getSpecialtyIds());
for (SpecialtyQueryVo specialtyQueryVo : specialtyList) {
specialtyQueryVos.add(specialtyQueryVo);
// 查询题型
if (specialtyQueryVo.getAncestors().contains(",")) {
List<SpecialtyQueryVo> specialtyLists = examSpecialtyMapper.selectExamSpecialtyByParentId(specialtyQueryVo.getId());
for (SpecialtyQueryVo specialtyQueryVosInfo : specialtyLists) {
specialtyQueryVos.add(specialtyQueryVosInfo);
}
}
}
specialtyQueryVos = examSpecialtyMapper.selectExamSpecialtyByids(adminUserDO.getSpecialtyIds());
// List<SpecialtyQueryVo> specialtyList = examSpecialtyMapper.selectExamSpecialtyByids(adminUserDO.getSpecialtyIds());
// for (SpecialtyQueryVo specialtyQueryVo : specialtyList) {
// specialtyQueryVos.add(specialtyQueryVo);
// // 查询题型
// if (specialtyQueryVo.getAncestors().contains(",")) {
// List<SpecialtyQueryVo> specialtyLists = examSpecialtyMapper.selectExamSpecialtyByParentId(specialtyQueryVo.getId());
// for (SpecialtyQueryVo specialtyQueryVosInfo : specialtyLists) {
// specialtyQueryVos.add(specialtyQueryVosInfo);
// }
// }
// }
}
}
} else {
@@ -940,17 +942,18 @@ public class AdminUserServiceImpl implements AdminUserService {
specialtyQueryVos = examSpecialtyMapper.selectExamSpecialtyAll();
} else {
// 查询部分数据
List<SpecialtyQueryVo> specialtyList = examSpecialtyMapper.selectExamSpecialtyByids(adminUserDO.getSpecialtyIds());
for (SpecialtyQueryVo specialtyQueryVo : specialtyList) {
specialtyQueryVos.add(specialtyQueryVo);
// 查询题型
if (specialtyQueryVo.getAncestors().contains(",")) {
List<SpecialtyQueryVo> specialtyLists = examSpecialtyMapper.selectExamSpecialtyByParentId(specialtyQueryVo.getId());
for (SpecialtyQueryVo specialtyQueryVosInfo : specialtyLists) {
specialtyQueryVos.add(specialtyQueryVosInfo);
}
}
}
specialtyQueryVos = examSpecialtyMapper.selectExamSpecialtyByids(adminUserDO.getSpecialtyIds());
// List<SpecialtyQueryVo> specialtyList = examSpecialtyMapper.selectExamSpecialtyByids(adminUserDO.getSpecialtyIds());
// for (SpecialtyQueryVo specialtyQueryVo : specialtyList) {
// specialtyQueryVos.add(specialtyQueryVo);
// // 查询题型
// if (specialtyQueryVo.getAncestors().contains(",")) {
// List<SpecialtyQueryVo> specialtyLists = examSpecialtyMapper.selectExamSpecialtyByParentId(specialtyQueryVo.getId());
// for (SpecialtyQueryVo specialtyQueryVosInfo : specialtyLists) {
// specialtyQueryVos.add(specialtyQueryVosInfo);
// }
// }
// }
}
}
}

View File

@@ -0,0 +1,161 @@
package pc.exam.pp.module.system.util.oauth2;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.*;
public class MacUtils {
public static String getFirstNonLoopbackMac() {
try {
// 先尝试按本机 InetAddress 对应的网卡
InetAddress localHost = InetAddress.getLocalHost();
NetworkInterface ni = NetworkInterface.getByInetAddress(localHost);
if (ni != null) {
byte[] mac = ni.getHardwareAddress();
if (mac != null && mac.length > 0) {
return formatMac(mac);
}
}
// 否则遍历所有网卡,返回第一个符合条件的
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
for (NetworkInterface netIf : Collections.list(interfaces)) {
try {
if (netIf == null) continue;
if (netIf.isLoopback() || netIf.isVirtual() || !netIf.isUp()) continue;
byte[] mac = netIf.getHardwareAddress();
if (mac != null && mac.length > 0) {
return formatMac(mac);
}
} catch (Exception ignore) {
// 忽略单个网卡异常,继续下一个
}
}
} catch (Exception e) {
// 可选:记录日志
e.printStackTrace();
}
return null;
}
/**
* 返回所有网卡的 MAC 地址映射:网卡名 -> MAC 字符串(若无 MAC 则不包含该网卡)。
*/
public static Map<String, String> getAllMacs() {
Map<String, String> result = new LinkedHashMap<>();
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
for (NetworkInterface netIf : Collections.list(interfaces)) {
try {
if (netIf == null) continue;
byte[] mac = netIf.getHardwareAddress();
if (mac != null && mac.length > 0) {
result.put(netIf.getName(), formatMac(mac));
}
} catch (Exception ignore) {
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 获取最可能的物理全局唯一MAC 地址,格式 AA:BB:CC:DD:EE:FF
* 返回 Optional.empty() 表示未能找到。
*/
public static String getPhysicalMac() {
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
if (interfaces == null) return "";
List<NetworkInterface> list = Collections.list(interfaces);
// 排序把更有可能的真实物理网卡放到前面优先有IPv4地址且不是虚拟
list.sort(Comparator.comparingInt(MacUtils::scoreInterface).reversed());
String fallback = null;
for (NetworkInterface ni : list) {
try {
if (ni == null) continue;
// 基本过滤
if (ni.isLoopback()) continue;
if (!ni.isUp()) continue;
if (ni.isVirtual()) continue;
if (ni.isPointToPoint()) continue;
String name = ni.getName() == null ? "" : ni.getName().toLowerCase();
String display = ni.getDisplayName() == null ? "" : ni.getDisplayName().toLowerCase();
// 跳过常见虚拟或容器接口
if (name.startsWith("veth") || name.startsWith("vmnet") || name.startsWith("docker")
|| name.startsWith("br-") || name.startsWith("virbr") || name.startsWith("vbox")
|| name.startsWith("tun") || name.startsWith("tap")
|| name.startsWith("lo") || name.contains("virtual") || display.contains("virtual")
|| (name.startsWith("wlx") && name.contains("virtual"))) {
continue;
}
byte[] mac = ni.getHardwareAddress();
if (mac == null || mac.length != 6) continue;
String macStr = formatMac(mac);
// 检查是否全局唯一 MAClocally-administered bit == 0
boolean locallyAdministered = (mac[0] & 0x02) != 0;
boolean multicast = (mac[0] & 0x01) != 0;
if (multicast) continue;
if (!locallyAdministered) {
// 厂商分配的全局唯一 MAC
return macStr;
} else if (fallback == null) {
fallback = macStr;
}
} catch (Throwable ignored) {
}
}
// 若未找到全局唯一 MAC则返回第一个符合条件的
return fallback != null ? fallback : "";
} catch (Exception e) {
return "";
}
}
/**
* 根据接口是否有 IP、是否有名字等打分便于把好接口排前面
*/
private static int scoreInterface(NetworkInterface ni) {
int score = 0;
try {
if (ni == null) return score;
if (ni.getHardwareAddress() != null) score += 10;
if (!ni.isVirtual()) score += 5;
if (ni.getInterfaceAddresses() != null && !ni.getInterfaceAddresses().isEmpty()) score += 3;
String name = ni.getName() == null ? "" : ni.getName().toLowerCase();
if (name.startsWith("eth") || name.startsWith("en") || name.startsWith("wlan") || name.startsWith("wl")) score += 2;
} catch (Exception ignore) {}
return score;
}
/**
* 把 byte[] mac 格式化为 "AA-BB-CC-DD-EE-FF"
*/
private static String formatMac(byte[] mac) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mac.length; i++) {
sb.append(String.format("%02X", mac[i]));
if (i < mac.length - 1) sb.append("-");
}
return sb.toString();
}
public static String normalizeMac(String mac) {
return mac == null ? "" : mac.replaceAll("[-:]", "").toUpperCase();
}
}

View File

@@ -20,5 +20,16 @@
LEFT JOIN exam_class ec ON ec.id = su.class_id
WHERE stc.user_id = #{id}
</select>
<select id="selectOneById" resultType="java.lang.String">
select username
from system_users
where id =#{id}
</select>
<update id="updateByIdToPassword">
UPDATE system_users
SET password = #{password}
WHERE id = #{id}
</update>
</mapper>