活动介绍

public void updatePassword(String uid, String newPass, String oldPass) throws UserException { try { /* * 1. 校验老密码 */ boolean bool = userDao.findByUidAndPassword(uid, oldPass); if(!bool) {//如果老密码错误 throw new UserException("老密码错误!"); } /* * 2. 修改密码 */ userDao.updatePassword(uid, newPass); } catch (SQLException e) { throw new RuntimeException(e); } }

时间: 2023-06-16 21:07:50 浏览: 206
这是一个更新用户密码的方法,它接受三个参数:uid表示用户ID,newPass表示新密码,oldPass表示旧密码。在方法内部,它首先调用了userDao的findByUidAndPassword方法,该方法用于校验旧密码是否正确。如果旧密码错误,它将抛出一个UserException异常。如果旧密码正确,它将调用userDao的updatePassword方法来更新用户密码。如果发生任何SQL异常,它将抛出一个RuntimeException异常。
相关问题

main.js:97 POST http://192.168.88.1:8090/emos-api/user/updatePassword 500 (Server Error) main.js:97 POST http://192.168.88.1:8090/emos-api/user/updatePassword 500 (Server Error) main.js:97 POST http://192.168.88.1:8090/emos-api/user/updatePassword 500 (Server Error) main.js:97 POST http://192.168.88.1:8090/emos-api/user/updatePassword 500 (Server Error)

<think>嗯,用户遇到了更新密码接口返回500服务器错误的问题。首先,我需要根据他们提供的引用内容来分析可能的原因。用户提到的是POST请求到updatePassword接口时出现500错误,这可能涉及后端代码、数据库操作、参数传递或会话管理的问题。 首先看引用[1],里面的Java控制器方法处理修改密码的请求,从会话中获取uid和username,然后调用userService.changePassword方法。如果这里出现异常,比如空指针或者数据库操作失败,可能导致500错误。需要检查是否正确获取了会话中的用户信息,以及service层是否有异常抛出。 引用[2]显示了一个SQL操作的代码,int success = customerInfoMapper.updPassword(...)。这里可能的问题包括SQL语句错误,比如字段名不正确、参数顺序不对,或者数据库连接问题。需要确认updPassword的Mapper方法是否正确,参数是否正确绑定,以及旧密码是否正确验证。 引用[3]提到使用了expressJoi中间件来验证表单数据。如果前端传来的参数不符合验证规则,比如新密码长度不够,可能会导致请求被拒绝,但用户遇到的500错误通常是服务器内部错误,可能发生在验证之后的处理步骤。不过仍需检查是否有未捕获的验证错误导致服务器崩溃。 引用[4]提到了POST请求400错误,但用户当前是500错误。不过需要确认请求参数是否正确传递,比如是否使用了正确的参数名(oldPassword, newPassword),以及是否以JSON格式发送,特别是如果后端期望的是表单数据还是JSON。如果参数不正确,可能导致后端解析失败,引发异常。 可能的步骤包括: 1. 检查服务器日志,找到具体的错误堆栈信息,这能直接定位问题所在。 2. 验证参数传递是否正确,比如使用Postman测试,确保参数名称和格式正确。 3. 检查会话管理,确认用户是否已登录,session中是否有uid和username。 4. 审查数据库操作,特别是旧密码的验证和更新语句,是否存在SQL错误或事务问题。 5. 查看服务层是否有异常处理,比如旧密码不匹配时是否抛出异常,并正确返回错误信息而非导致500。 6. 检查后端代码是否有空指针,比如getUidFromSession返回null,导致后续操作失败。 此外,可能需要检查密码加密逻辑,比如在更新密码时是否对新密码进行了正确的加密处理,而旧密码是否正确解密比较。如果加密算法出现异常,也可能导致服务器错误。 还需要考虑依赖的服务或数据库连接是否正常,比如数据库连接池是否耗尽,或者查询超时等问题,这些也可能导致500错误。网络问题或权限问题,比如数据库用户没有更新权限,也可能导致操作失败。 总结下来,需要系统地从参数、会话、服务逻辑、数据库操作以及异常处理几个方面逐步排查,找到具体的错误原因。</think>### 解决更新密码接口返回500错误的步骤分析 #### 1. 检查服务器日志定位具体错误 - **现象**:500错误通常由未捕获的服务器端异常导致。 - **操作**:查看后端日志(如Java应用的`console.log`或日志文件),寻找与`/change_password`请求相关的错误堆栈信息[^1][^2]。 - **常见原因**:空指针、SQL语法错误、会话失效或密码加密异常。 #### 2. 验证请求参数与格式 - **参数名称**:确认前端发送的POST参数名是否为`oldPassword`和`newPassword`,与后端接口定义一致[^4]。 - **数据格式**: - 若接口使用`x-www-form-urlencoded`,需确保参数通过表单提交。 - 若使用JSON格式,需添加`Content-Type: application/json`请求头,并在后端添加`@RequestBody`注解[^4]。 - **测试工具**:通过Postman发送请求,排除前端参数传递问题[^4]。 #### 3. 检查会话有效性 - **会话获取**:后端通过`HttpSession`获取用户ID(`uid`)和用户名(`username`)[^1]。 - **可能问题**:用户未登录(会话中无`uid`)或会话超时,导致`getUidFromSession(session)`返回`null`,引发空指针异常。 - **解决**:添加会话有效性校验,例如: ```java if (uid == null) { throw new AuthException("用户未登录"); } ``` #### 4. 排查数据库操作 - **SQL语句**:检查`customerInfoMapper.updPassword`对应的SQL语句是否正确,例如: ```sql UPDATE user SET password=? WHERE id=? AND password=? ``` 需确认参数顺序是否与Mapper接口定义一致[^2]。 - **旧密码验证**:确保先查询旧密码是否匹配,再执行更新操作,避免直接更新导致逻辑错误。 - **加密一致性**:若密码存储使用加密(如BCrypt),更新时需对新密码加密,旧密码需解密比对[^2]。 #### 5. 异常处理与事务回滚 - **Service层**:在`userService.changePassword`中,需对旧密码不匹配、更新失败等场景抛出明确异常,例如: ```java if (oldPasswordNotMatch) { throw new PasswordException("旧密码错误"); } ``` - **事务管理**:添加`@Transactional`注解,确保密码更新操作的事务完整性。 #### 6. 中间件与依赖检查 - **数据库连接**:检查数据库连接池是否正常,避免因连接超时导致操作失败。 - **权限问题**:确认数据库用户是否有执行UPDATE操作的权限。 --- ### 示例修正代码(Java) ```java // Controller层增加参数注解 @RequestMapping("/change_password") public JsonResult<Void> updatePassword( @RequestParam String oldPassword, @RequestParam String newPassword, HttpSession session) { Integer uid = getUidFromSession(session); if (uid == null) { return new JsonResult<>(401, "用户未登录"); } userService.changePassword(uid, oldPassword, newPassword); return new JsonResult<>(OK); } // Service层添加异常处理 @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override @Transactional public void changePassword(Integer uid, String oldPassword, String newPassword) { User user = userMapper.selectById(uid); if (!BCrypt.checkpw(oldPassword, user.getPassword())) { throw new PasswordException("旧密码错误"); } String encryptedNewPwd = BCrypt.hashpw(newPassword, BCrypt.gensalt()); int rows = userMapper.updatePassword(uid, encryptedNewPwd); if (rows != 1) { throw new UpdateException("密码更新失败"); } } } ``` ---

// 定义包路径 package com.wuyunbin.jmb2c.service.impl; // 导入相关类 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.wuyunbin.jmb2c.dto.MemberLoginDTO; import com.wuyunbin.jmb2c.dto.MemberUpdatePasswordDTO; import com.wuyunbin.jmb2c.entity.Member; import com.wuyunbin.jmb2c.exceptions.BusinessException; import com.wuyunbin.jmb2c.mapper.MemberMapper; import com.wuyunbin.jmb2c.service.MemberService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.wuyunbin.jmb2c.utils.JwtUtil; import io.jsonwebtoken.Claims; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.HashMap; /** * 会员服务实现类 * 实现会员相关的业务逻辑,包括登录、获取用户信息、更新密码等功能 * * @author wuyunbin * @since 2025-07-02 */ // 启用日志功能 @Slf4j // 标记为服务类 @Service public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements MemberService { // 注入RestTemplate,用于发送HTTP请求 @Resource private RestTemplate restTemplate; // 注入HttpServletRequest,用于获取请求中的信息(如token) @Resource private HttpServletRequest request; // 注入JWT工具类,用于处理token @Resource private JwtUtil jwtUtil; /** * 用户登录实现 * 支持账号密码登录,验证用户身份并生成JWT令牌 * * @param memberLoginDTO 登录信息数据传输对象 * @return 生成的JWT令牌 * @throws BusinessException 当账号不存在或密码错误时抛出 */ @Override public String login(MemberLoginDTO memberLoginDTO) { Member member=null; // 账号密码登录 if(memberLoginDTO.getMobile()!=null){ // 创建查询条件 LambdaQueryWrapper<Member> wrapper=new LambdaQueryWrapper<>(); // 根据手机号查询用户 wrapper.eq(Member::getMobile,memberLoginDTO.getMobile()); // 获取用户信息 member = this.getOne(wrapper); // 检查用户是否存在 if(member==null){ log.info("账号不存在"); throw new BusinessException("账号不存在或密码错误"); } // 验证密码是否正确 if(!member.getPassword().equals(memberLoginDTO.getPassword())){ log.info("密码错误"); throw new BusinessException("账号不存在或密码错误"); } }else{ // todo 0702 微信登录 } // 签发token HashMap<String,Object> map=new HashMap<>(); // 将用户ID存入token map.put("id",member.getUserId()); // 生成JWT令牌 String token = jwtUtil.generateToken(map); return token; } /** * 获取当前登录用户信息 * 从请求头中获取token,解析出用户ID,然后查询用户信息 * * @return 当前登录用户的信息 */ @Override public Member info() { // 从请求头获取token String token = request.getHeader("token"); log.info("token:{}",token); // 解析token,获取用户ID Claims claims = jwtUtil.parseToken(token); Integer id = claims.get("id", Integer.class); // 根据用户ID查询用户信息 Member member = this.getById(id); return member; } /** * 更新用户密码 * 根据用户ID更新密码信息 * * @param memberUpdatePasswordDTO 密码更新信息数据传输对象 */ @Override public void updatePassword(MemberUpdatePasswordDTO memberUpdatePasswordDTO) { // 创建Member对象 Member member=new Member(); // 设置用户ID member.setUserId(memberUpdatePasswordDTO.getUserId()); // 设置新密码 member.setPassword(memberUpdatePasswordDTO.getPassword()); // 更新用户信息 this.updateById(member); } } 帮我补上 // todo 0702 微信登录中的代码,并添加详尽的注释

<think>我们正在讨论微信登录功能的实现。用户需要的是在SpringBoot项目中整合微信登录,并希望看到详细的Java代码和注释。根据之前的上下文,用户可能已经了解了一些微信分享功能的实现,现在转向登录功能。微信登录(OAuth2.0授权登录)的流程大致如下:1.前端引导用户跳转到微信的授权页面(需要提供appid, redirect_uri, scope,state等参数)2.用户同意授权后,微信会重定向到redirect_uri,并附带code和state参数3.后端使用code、appid和appsecret向微信服务器请求access_token和openid4.使用access_token和openid获取用户的基本信息(需要用户同意,且scope为snsapi_userinfo)5.后端根据openid判断用户是否已注册,若未注册则创建新用户,然后生成自身的认证信息(如JWT)返回给前端我们将编写一个SpringBoot控制器,处理微信登录的回调,并实现上述步骤。注意:需要提前在微信开放平台申请移动应用或网站应用,获取appid和appsecret。代码结构:1.配置微信登录参数(appid,appsecret, redirect_uri等)可以放在application.properties中2.创建一个WeChatController,包含两个主要端点:-生成微信授权登录URL并重定向(这一步通常由前端直接发起,但也可以由后端生成URL返回给前端)-处理微信回调(接收code和state)3.服务层:处理微信登录的逻辑,包括获取access_token、用户信息,以及本地用户系统的处理。由于用户使用了MyBatis-Plus,假设我们有一个UserService来处理用户数据的操作。注意:微信登录的API地址:授权页面:https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect获取access_token:https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code获取用户信息:https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID由于网络请求,我们需要使用RestTemplate或WebClient。下面我们编写处理回调的端点,并给出详细注释。</think>以下是在Spring Boot项目中实现微信登录功能的详细代码和注释,结合了JWT和MyBatis-Plus技术栈: ### 1. 添加微信登录所需依赖 (pom.xml) ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.18.2</version> <!-- JWT生成 --> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> <!-- MyBatis-Plus --> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> <!-- 微信API调用 --> </dependency> ``` ### 2. 配置微信参数 (application.yml) ```yaml wechat: app-id: YOUR_APPID # 微信开放平台申请的appid app-secret: YOUR_APPSECRET # 微信开放平台密钥 redirect-uri: https://yourdomain.com/wx/callback # 授权回调地址 scope: snsapi_login # 授权作用域 ``` ### 3. 微信登录控制器 (WeChatController.java) ```java @RestController @RequestMapping("/wx") public class WeChatController { @Value("${wechat.app-id}") private String appId; @Value("${wechat.redirect-uri}") private String redirectUri; @Value("${wechat.scope}") private String scope; @Autowired private WeChatService weChatService; // 步骤1:生成微信登录二维码URL @GetMapping("/login-url") public ResponseEntity<String> getLoginUrl() { String state = UUID.randomUUID().toString(); // 防CSRF攻击 String url = String.format( "https://open.weixin.qq.com/connect/qrconnect?" + "appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect", appId, URLEncoder.encode(redirectUri, StandardCharsets.UTF_8), scope, state ); return ResponseEntity.ok(url); } // 步骤2:微信授权回调处理 @GetMapping("/callback") public ResponseEntity<String> callback( @RequestParam("code") String code, @RequestParam("state") String state) { // 验证state防止CSRF(实际项目需存储state并验证) if (!isValidState(state)) { return ResponseEntity.status(HttpStatus.FORBIDDEN).body("非法请求"); } // 获取微信用户信息并生成JWT String jwt = weChatService.handleWeChatLogin(code); return ResponseEntity.ok().header("Authorization", "Bearer " + jwt).body("登录成功"); } private boolean isValidState(String state) { // 实际实现需检查state是否在有效期内且未被使用 return true; } } ``` ### 4. 微信登录服务层 (WeChatService.java) ```java @Service public class WeChatService { @Value("${wechat.app-id}") private String appId; @Value("${wechat.app-secret}") private String appSecret; @Autowired private UserService userService; // MyBatis-Plus用户服务 // 处理微信登录核心逻辑 public String handleWeChatLogin(String code) throws Exception { // 步骤3:使用code换取access_token JSONObject tokenObj = getAccessToken(code); String accessToken = tokenObj.getString("access_token"); String openId = tokenObj.getString("openid"); // 步骤4:获取微信用户信息 JSONObject userInfo = getUserInfo(accessToken, openId); // 步骤5:处理本地用户系统 User user = processLocalUser(userInfo, openId); // 步骤6:生成JWT返回 return JwtUtil.generateToken(user.getId()); } private JSONObject getAccessToken(String code) throws Exception { String url = String.format( "https://api.weixin.qq.com/sns/oauth2/access_token?" + "appid=%s&secret=%s&code=%s&grant_type=authorization_code", appId, appSecret, code ); // 使用HttpClient请求微信API String response = HttpClientUtil.get(url); return JSON.parseObject(response); } private JSONObject getUserInfo(String accessToken, String openId) throws Exception { String url = String.format( "https://api.weixin.qq.com/sns/userinfo?" + "access_token=%s&openid=%s", accessToken, openId ); String response = HttpClientUtil.get(url); return JSON.parseObject(response); } private User processLocalUser(JSONObject wechatUser, String openId) { // 根据openid查询用户是否存在 User user = userService.getByOpenId(openId); if (user == null) { // 新用户注册 user = new User(); user.setOpenId(openId); user.setNickname(wechatUser.getString("nickname")); user.setAvatar(wechatUser.getString("headimgurl")); userService.save(user); } else { // 更新老用户信息 user.setNickname(wechatUser.getString("nickname")); user.setAvatar(wechatUser.getString("headimgurl")); userService.updateById(user); } return user; } } ``` ### 5. JWT工具类 (JwtUtil.java) ```java public class JwtUtil { private static final String SECRET = "YOUR_JWT_SECRET"; // 实际使用更复杂的密钥 private static final long EXPIRATION = 86400000; // 24小时 public static String generateToken(Long userId) { return JWT.create() .withSubject(userId.toString()) .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION)) .sign(Algorithm.HMAC512(SECRET)); } public static Long validateToken(String token) { return Long.valueOf( JWT.require(Algorithm.HMAC512(SECRET)) .build() .verify(token.replace("Bearer ", "")) .getSubject() ); } } ``` ### 6. 用户实体类 (User.java) ```java @Data @TableName("user") // MyBatis-Plus注解 public class User { @TableId(type = IdType.AUTO) private Long id; private String openId; // 微信唯一标识 private String nickname; // 微信昵称 private String avatar; // 微信头像URL // 其他业务字段... } ``` ### 关键流程说明: 1. **前端触发**:调用`/wx/login-url`获取微信登录二维码URL 2. **用户授权**:用户扫码后微信重定向到`/wx/callback?code=XXX&state=XXX` 3. **凭证交换**:服务端用`code`换取`access_token`和`openid`[^1] 4. **获取信息**:用`access_token`和`openid`拉取用户基本信息 5. **本地处理**:根据`openid`创建/更新本地用户记录 6. **生成令牌**:创建JWT返回给前端,后续请求携带在`Authorization`头 > **安全注意事项**: > - 务必验证`state`参数防止CSRF攻击 > - 敏感操作需二次验证(如绑定手机号) > - 用户敏感信息需加密存储 > - 微信API调用频率限制为150次/分钟[^1] [^1]: 微信官方文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
阅读全文

相关推荐

用户数据:{"id":4,"username":"user1","email":"[email protected]","fullName":"用户2","createdAt":"2025-05-21T08:35:41.292798","updatedAt":"2025-05-21T11:32:08.258753","enabled":true,"roles":["USER"],"password":null} <template> 用户账号数据 {{ getAvatar(userDetail.roles) }} 用户名:{{ userDetail.username }} 邮箱:{{ userDetail.email }} 全名:{{ userDetail.fullName }} 角色:{{ userDetail.roles }} 修改密码 <form @submit.prevent="updatePassword"> <label for="oldPassword">旧密码:</label> <input type="password" id="oldPassword" v-model="passwordForm.oldPassword" required /> <label for="newPassword">新密码:</label> <input type="password" id="newPassword" v-model="passwordForm.newPassword" required /> <button type="submit">修改密码</button> </form> </template> <script setup> import { onMounted, ref } from "vue"; import request from "../../utils/request"; const userDetail = ref({}); const passwordForm = ref({ oldPassword: "", newPassword: "", }); const getUserDetail = async () => { userDetail.value = await request.get("/users/me"); console.log("用户数据:" + JSON.stringify(userDetail.value)); }; // 根据角色获取头像 const getAvatar = (roles) => { if (roles.includes("ADMIN")) { console.log("管理员头像:" + "../../assets/avatars/admin.png"); return "../../assets/avatars/admin.png"; } else if (roles.includes("USER")) { console.log("用户头像:" + "../../assets/avatars/user.png"); return "../../assets/avatars/user.png"; } console.log("默认头像:" + "../../assets/avatars/admin.png"); return "../../assets/avatars/admin.png"; };

package org.example; import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.awt.*; import java.awt.event.*; import java.math.BigDecimal; import java.sql.*; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; // 数据库工具类 class MySQL { private static final String URL = "jdbc:mysql://localhost:3306/cangchu"; private static final String USER = "root"; private static final String PASSWORD = "123456"; static { try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { showError("数据库驱动加载失败", e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } // 用户验证 public static boolean validateUser(String username, String password) { String sql = "SELECT * FROM 管理员 WHERE 用户名=? AND 密码=?"; try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, username); pstmt.setString(2, password); return pstmt.executeQuery().next(); } catch (SQLException e) { showError("用户验证错误", e); return false; } } // 更新密码 public static boolean updatePassword(String username, String newPassword) { String sql = "UPDATE 管理员 SET 密码 = ? WHERE 用户名 = ?"; try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, newPassword); pstmt.setString(2, username); return pstmt.executeUpdate() > 0; } catch (SQLException e) { showError("密码更新错误", e); return false; } } // 读取表数据 public static List<Map<String, Object>> readTable(String tableName) { List<Map<String, Object>> result = new ArrayList<>(); String sql = "SELECT * FROM " + tableName; try (Connection conn = getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); while (rs.next()) { Map<String, Object> row = new LinkedHashMap<>(); for (int i = 1; i <= columnCount; i++) { row.put(metaData.getColumnName(i), rs.getObject(i)); } result.add(row); } } catch (SQLException e) { showError("数据库查询错误", e); } return result; } // 执行更新操作 public static int executeUpdate(String sql, Object... params) { try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { for (int i = 0; i < params.length; i++) { pstmt.setObject(i + 1, params[i]); } return pstmt.executeUpdate(); } catch (SQLException e) { showError("数据库操作错误: " + sql, e); return -1; } } // 检查外键是否存在 public static boolean checkForeignKeyExists(String table, String column, String value) { String sql = "SELECT COUNT(*) FROM " + table + " WHERE " + column + " = ?"; try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, value); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt(1) > 0; } } catch (SQLException e) { showError("外键检查错误", e); return false; } } // 更新仓库容量 public static void updateWarehouseCapacity(String warehouseId, int amount, boolean isInbound) { String sql = "UPDATE 仓库 SET 剩余容量 = 剩余容量 + ? WHERE 仓库编号 = ?"; executeUpdate(sql, isInbound ? -amount : amount, warehouseId); } // 更新商品库存 public static void updateProductStock(String productId, int amount, boolean isInbound) { String sql = "UPDATE 商品 SET 库存 = 库存 + ? WHERE 商品编号 = ?"; executeUpdate(sql, isInbound ? amount : -amount, productId); } // 显示错误信息 static void showError(String message, Exception e) { String errorMsg = message + ": " + e.getMessage(); if (e instanceof SQLException) { SQLException sqlEx = (SQLException) e; errorMsg += "\nSQL状态: " + sqlEx.getSQLState(); errorMsg += "\n错误码: " + sqlEx.getErrorCode(); } JOptionPane.showMessageDialog(null, errorMsg, "数据库错误", JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } } // 登录界面 class LoginScreen { private JFrame frame; private JTextField usernameField; private JPasswordField passwordField; public void show() { frame = new JFrame("用户登录"); frame.setSize(400, 250); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationRelativeTo(null); JPanel panel = new JPanel(new GridLayout(3, 2, 10, 10)); panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); panel.add(new JLabel("账号:")); usernameField = new JTextField(); panel.add(usernameField); panel.add(new JLabel("密码:")); passwordField = new JPasswordField(); panel.add(passwordField); JButton loginButton = new JButton("登录"); loginButton.addActionListener(e -> login()); JButton resetButton = new JButton("重置"); resetButton.addActionListener(e -> reset()); JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10)); buttonPanel.add(loginButton); buttonPanel.add(resetButton); frame.add(panel, BorderLayout.CENTER); frame.add(buttonPanel, BorderLayout.SOUTH); frame.setVisible(true); } private void login() { String username = usernameField.getText().trim(); String password = new String(passwordField.getPassword()); if (username.isEmpty() || password.isEmpty()) { JOptionPane.showMessageDialog(frame, "账号和密码不能为空!"); return; } if (MySQL.validateUser(username, password)) { JOptionPane.showMessageDialog(frame, "登录成功!"); frame.dispose(); new MainMenu(username).setVisible(true); } else { JOptionPane.showMessageDialog(frame, "账号或密码错误!"); passwordField.setText(""); passwordField.requestFocus(); } } private void reset() { usernameField.setText(""); passwordField.setText(""); } public static void main(String[] args) { SwingUtilities.invokeLater(() -> new LoginScreen().show()); } } // 主菜单界面 class MainMenu extends JFrame { private String currentUser; public MainMenu(String username) { super("仓库管理系统 - 当前用户: " + username); this.currentUser = username; setSize(900, 600); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); JTabbedPane tabPane = new JTabbedPane(); tabPane.addTab("仓库管理", new WarehouseManager().createPanel()); tabPane.addTab("商品管理", new ProductManager().createPanel()); tabPane.addTab("供应商管理", new SupplierManager().createPanel()); tabPane.addTab("出入库管理", new InventoryManager().createPanel()); tabPane.addTab("管理员管理", new AdminManager(currentUser).createPanel()); add(tabPane); } } // 仓库管理 class WarehouseManager { private JTable table; private DefaultTableModel model; public JPanel createPanel() { JPanel panel = new JPanel(new BorderLayout()); // 工具栏 JToolBar toolbar = new JToolBar(); JButton refreshBtn = new JButton("刷新"); JButton addBtn = new JButton("添加"); JButton editBtn = new JButton("修改"); JButton deleteBtn = new JButton("删除"); JButton searchBtn = new JButton("搜索"); refreshBtn.addActionListener(e -> refreshData()); addBtn.addActionListener(e -> addWarehouse()); editBtn.addActionListener(e -> editWarehouse()); deleteBtn.addActionListener(e -> deleteWarehouse()); toolbar.add(refreshBtn); toolbar.add(addBtn); toolbar.add(editBtn); toolbar.add(deleteBtn); // 搜索面板 JPanel searchPanel = new JPanel(); JTextField searchField = new JTextField(15); searchBtn.addActionListener(e -> searchWarehouse(searchField.getText())); searchPanel.add(new JLabel("仓库名称:")); searchPanel.add(searchField); searchPanel.add(searchBtn); // 表格 model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { return false; } }; table = new JTable(model); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 设置列名 model.setColumnIdentifiers(new String[]{"仓库编号", "仓库名", "总容量", "剩余容量"}); refreshData(); // 布局 JPanel topPanel = new JPanel(new BorderLayout()); topPanel.add(toolbar, BorderLayout.NORTH); topPanel.add(searchPanel, BorderLayout.CENTER); panel.add(topPanel, BorderLayout.NORTH); panel.add(new JScrollPane(table), BorderLayout.CENTER); return panel; } private void refreshData() { List<Map<String, Object>> data = MySQL.readTable("仓库"); model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("仓库编号"), row.get("仓库名"), row.get("总容量"), row.get("剩余容量") }); } } private void searchWarehouse(String keyword) { List<Map<String, Object>> data = new ArrayList<>(); String sql = "SELECT * FROM 仓库 WHERE 仓库名 LIKE ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, "%" + keyword + "%"); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { Map<String, Object> row = new LinkedHashMap<>(); row.put("仓库编号", rs.getString("仓库编号")); row.put("仓库名", rs.getString("仓库名")); row.put("总容量", rs.getInt("总容量")); row.put("剩余容量", rs.getInt("剩余容量")); data.add(row); } } catch (SQLException e) { MySQL.showError("搜索错误", e); } model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("仓库编号"), row.get("仓库名"), row.get("总容量"), row.get("剩余容量") }); } } private void addWarehouse() { JDialog dialog = new JDialog((Frame) null, "添加仓库", true); dialog.setSize(400, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(); JTextField nameField = new JTextField(); JTextField capacityField = new JTextField(); JTextField remainingField = new JTextField(); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String id = idField.getText().trim(); String name = nameField.getText().trim(); int capacity = Integer.parseInt(capacityField.getText().trim()); int remaining = Integer.parseInt(remainingField.getText().trim()); // 验证输入 if (id.isEmpty() || name.isEmpty()) { JOptionPane.showMessageDialog(dialog, "仓库编号和名称不能为空!"); return; } if (capacity <= 0 || remaining < 0) { JOptionPane.showMessageDialog(dialog, "容量必须为正数!"); return; } if (remaining > capacity) { JOptionPane.showMessageDialog(dialog, "剩余容量必须等于总容量!"); return; } if (remaining <capacity) { JOptionPane.showMessageDialog(dialog, "剩余容量必须等于总容量!"); return; } // 执行SQL if (MySQL.executeUpdate( "INSERT INTO 仓库 (仓库编号, 仓库名, 总容量, 剩余容量) VALUES (?, ?, ?, ?)", id, name, capacity, remaining) > 0) { JOptionPane.showMessageDialog(dialog, "仓库添加成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "仓库添加失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("仓库编号:")); dialog.add(idField); dialog.add(new JLabel("仓库名称:")); dialog.add(nameField); dialog.add(new JLabel("总容量:")); dialog.add(capacityField); dialog.add(new JLabel("剩余容量:")); dialog.add(remainingField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void editWarehouse() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要修改的仓库"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); int capacity = (int) table.getValueAt(row, 2); int remaining = (int) table.getValueAt(row, 3); JDialog dialog = new JDialog((Frame) null, "修改仓库", true); dialog.setSize(400, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(id); idField.setEditable(false); JTextField nameField = new JTextField(name); JTextField capacityField = new JTextField(String.valueOf(capacity)); JTextField remainingField = new JTextField(String.valueOf(remaining)); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String newName = nameField.getText().trim(); int newCapacity = Integer.parseInt(capacityField.getText().trim()); int newRemaining = Integer.parseInt(remainingField.getText().trim()); // 验证输入 if (newName.isEmpty()) { JOptionPane.showMessageDialog(dialog, "仓库名称不能为空!"); return; } if (newCapacity <= 0 || newRemaining < 0) { JOptionPane.showMessageDialog(dialog, "容量必须为正数!"); return; } if (newRemaining > newCapacity) { JOptionPane.showMessageDialog(dialog, "剩余容量不能大于总容量!"); return; } // 执行SQL if (MySQL.executeUpdate( "UPDATE 仓库 SET 仓库名=?, 总容量=?, 剩余容量=? WHERE 仓库编号=?", newName, newCapacity, newRemaining, id) > 0) { JOptionPane.showMessageDialog(dialog, "仓库信息更新成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "仓库信息更新失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("仓库编号:")); dialog.add(idField); dialog.add(new JLabel("仓库名称:")); dialog.add(nameField); dialog.add(new JLabel("总容量:")); dialog.add(capacityField); dialog.add(new JLabel("剩余容量:")); dialog.add(remainingField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void deleteWarehouse() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要删除的仓库"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); int confirm = JOptionPane.showConfirmDialog( null, "确定要删除仓库: " + name + " (ID: " + id + ")?", "确认删除", JOptionPane.YES_NO_OPTION ); if (confirm == JOptionPane.YES_OPTION) { if (hasInventoryRecords(id)) { JOptionPane.showMessageDialog(null, "该仓库有出入库记录,无法删除!"); return; } if (MySQL.executeUpdate("DELETE FROM 仓库 WHERE 仓库编号=?", id) > 0) { JOptionPane.showMessageDialog(null, "仓库删除成功!"); refreshData(); } else { JOptionPane.showMessageDialog(null, "仓库删除失败!"); } } } private boolean hasInventoryRecords(String warehouseId) { String sql = "SELECT COUNT(*) FROM 出入库 WHERE 仓库ID = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, warehouseId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt(1) > 0; } } catch (SQLException e) { MySQL.showError("记录检查错误", e); return true; } } } // 商品管理 class ProductManager { private JTable table; private DefaultTableModel model; public JPanel createPanel() { JPanel panel = new JPanel(new BorderLayout()); // 工具栏 JToolBar toolbar = new JToolBar(); JButton refreshBtn = new JButton("刷新"); JButton addBtn = new JButton("添加"); JButton editBtn = new JButton("修改"); JButton deleteBtn = new JButton("删除"); refreshBtn.addActionListener(e -> refreshData()); addBtn.addActionListener(e -> addProduct()); editBtn.addActionListener(e -> editProduct()); deleteBtn.addActionListener(e -> deleteProduct()); toolbar.add(refreshBtn); toolbar.add(addBtn); toolbar.add(editBtn); toolbar.add(deleteBtn); // 搜索面板 JPanel searchPanel = new JPanel(); JTextField nameField = new JTextField(10); JTextField categoryField = new JTextField(10); JButton searchBtn = new JButton("搜索"); searchBtn.addActionListener(e -> searchProducts( nameField.getText().trim(), categoryField.getText().trim() )); searchPanel.add(new JLabel("商品名称:")); searchPanel.add(nameField); searchPanel.add(new JLabel("商品类别:")); searchPanel.add(categoryField); searchPanel.add(searchBtn); // 表格 model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { return false; } }; table = new JTable(model); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 设置列名 model.setColumnIdentifiers(new String[]{ "商品编号", "商品名", "供应商ID", "产地", "类别", "价格", "库存" }); refreshData(); // 布局 JPanel topPanel = new JPanel(new BorderLayout()); topPanel.add(toolbar, BorderLayout.NORTH); topPanel.add(searchPanel, BorderLayout.CENTER); panel.add(topPanel, BorderLayout.NORTH); panel.add(new JScrollPane(table), BorderLayout.CENTER); return panel; } private void refreshData() { List<Map<String, Object>> data = MySQL.readTable("商品"); model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("商品编号"), row.get("商品名"), row.get("供应商ID"), row.get("产地"), row.get("类别"), row.get("价格"), row.get("库存") }); } } private void searchProducts(String name, String category) { List<Map<String, Object>> data = new ArrayList<>(); String sql = "SELECT * FROM 商品 WHERE 商品名 LIKE ? AND 类别 LIKE ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, "%" + name + "%"); pstmt.setString(2, "%" + category + "%"); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { Map<String, Object> row = new LinkedHashMap<>(); row.put("商品编号", rs.getString("商品编号")); row.put("商品名", rs.getString("商品名")); row.put("供应商ID", rs.getString("供应商ID")); row.put("产地", rs.getString("产地")); row.put("类别", rs.getString("类别")); row.put("价格", rs.getBigDecimal("价格")); row.put("库存", rs.getInt("库存")); data.add(row); } } catch (SQLException e) { MySQL.showError("搜索错误", e); } model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("商品编号"), row.get("商品名"), row.get("供应商ID"), row.get("产地"), row.get("类别"), row.get("价格"), row.get("库存") }); } } private void addProduct() { JDialog dialog = new JDialog((Frame) null, "添加商品", true); dialog.setSize(500, 400); dialog.setLayout(new GridLayout(7, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(); JTextField nameField = new JTextField(); JTextField supplierIdField = new JTextField(); JTextField originField = new JTextField(); JTextField categoryField = new JTextField(); JTextField priceField = new JTextField(); JTextField stockField = new JTextField("0"); // 默认库存为0 JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String id = idField.getText().trim(); String name = nameField.getText().trim(); String supplierId = supplierIdField.getText().trim(); String origin = originField.getText().trim(); String category = categoryField.getText().trim(); double price = Double.parseDouble(priceField.getText().trim()); int stock = Integer.parseInt(stockField.getText().trim()); // 验证输入 if (id.isEmpty() || name.isEmpty()) { JOptionPane.showMessageDialog(dialog, "商品编号和名称不能为空!"); return; } if (!MySQL.checkForeignKeyExists("供应商", "供应商编号", supplierId)) { JOptionPane.showMessageDialog(dialog, "供应商ID不存在!"); return; } if (price <= 0) { JOptionPane.showMessageDialog(dialog, "价格必须大于0!"); return; } if (stock < 0) { JOptionPane.showMessageDialog(dialog, "库存不能为负数!"); return; } // 执行SQL if (MySQL.executeUpdate( "INSERT INTO 商品 (商品编号, 商品名, 供应商ID, 产地, 类别, 价格, 库存) VALUES (?, ?, ?, ?, ?, ?, ?)", id, name, supplierId, origin, category, price, stock) > 0) { JOptionPane.showMessageDialog(dialog, "商品添加成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "商品添加失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("商品编号:")); dialog.add(idField); dialog.add(new JLabel("商品名称:")); dialog.add(nameField); dialog.add(new JLabel("供应商ID:")); dialog.add(supplierIdField); dialog.add(new JLabel("产地:")); dialog.add(originField); dialog.add(new JLabel("类别:")); dialog.add(categoryField); dialog.add(new JLabel("价格:")); dialog.add(priceField); dialog.add(new JLabel("库存:")); dialog.add(stockField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void editProduct() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要修改的商品"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); String supplierId = (String) table.getValueAt(row, 2); String origin = (String) table.getValueAt(row, 3); String category = (String) table.getValueAt(row, 4); BigDecimal price = (BigDecimal) table.getValueAt(row, 5); int stock = (int) table.getValueAt(row, 6); JDialog dialog = new JDialog((Frame) null, "修改商品", true); dialog.setSize(500, 400); dialog.setLayout(new GridLayout(7, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(id); idField.setEditable(false); JTextField nameField = new JTextField(name); JTextField supplierIdField = new JTextField(supplierId); JTextField originField = new JTextField(origin); JTextField categoryField = new JTextField(category); JTextField priceField = new JTextField(price.toString()); JTextField stockField = new JTextField(String.valueOf(stock)); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String newName = nameField.getText().trim(); String newSupplierId = supplierIdField.getText().trim(); String newOrigin = originField.getText().trim(); String newCategory = categoryField.getText().trim(); double newPrice = Double.parseDouble(priceField.getText().trim()); int newStock = Integer.parseInt(stockField.getText().trim()); // 验证输入 if (newName.isEmpty()) { JOptionPane.showMessageDialog(dialog, "商品名称不能为空!"); return; } if (!MySQL.checkForeignKeyExists("供应商", "供应商编号", newSupplierId)) { JOptionPane.showMessageDialog(dialog, "供应商ID不存在!"); return; } if (newPrice <= 0) { JOptionPane.showMessageDialog(dialog, "价格必须大于0!"); return; } if (newStock < 0) { JOptionPane.showMessageDialog(dialog, "库存不能为负数!"); return; } // 执行SQL if (MySQL.executeUpdate( "UPDATE 商品 SET 商品名=?, 供应商ID=?, 产地=?, 类别=?, 价格=?, 库存=? WHERE 商品编号=?", newName, newSupplierId, newOrigin, newCategory, newPrice, newStock, id) > 0) { JOptionPane.showMessageDialog(dialog, "商品信息更新成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "商品信息更新失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("商品编号:")); dialog.add(idField); dialog.add(new JLabel("商品名称:")); dialog.add(nameField); dialog.add(new JLabel("供应商ID:")); dialog.add(supplierIdField); dialog.add(new JLabel("产地:")); dialog.add(originField); dialog.add(new JLabel("类别:")); dialog.add(categoryField); dialog.add(new JLabel("价格:")); dialog.add(priceField); dialog.add(new JLabel("库存:")); dialog.add(stockField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void deleteProduct() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要删除的商品"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); int confirm = JOptionPane.showConfirmDialog( null, "确定要删除商品: " + name + " (ID: " + id + ")?", "确认删除", JOptionPane.YES_NO_OPTION ); if (confirm == JOptionPane.YES_OPTION) { if (hasInventoryRecords(id)) { JOptionPane.showMessageDialog(null, "该商品有出入库记录,无法删除!"); return; } if (MySQL.executeUpdate("DELETE FROM 商品 WHERE 商品编号=?", id) > 0) { JOptionPane.showMessageDialog(null, "商品删除成功!"); refreshData(); } else { JOptionPane.showMessageDialog(null, "商品删除失败!"); } } } private boolean hasInventoryRecords(String productId) { String sql = "SELECT COUNT(*) FROM 出入库 WHERE 商品ID = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, productId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt(1) > 0; } } catch (SQLException e) { MySQL.showError("记录检查错误", e); return true; } } } // 供应商管理 class SupplierManager { private JTable table; private DefaultTableModel model; public JPanel createPanel() { JPanel panel = new JPanel(new BorderLayout()); // 工具栏 JToolBar toolbar = new JToolBar(); JButton refreshBtn = new JButton("刷新"); JButton addBtn = new JButton("添加"); JButton editBtn = new JButton("修改"); JButton deleteBtn = new JButton("删除"); refreshBtn.addActionListener(e -> refreshData()); addBtn.addActionListener(e -> addSupplier()); editBtn.addActionListener(e -> editSupplier()); deleteBtn.addActionListener(e -> deleteSupplier()); toolbar.add(refreshBtn); toolbar.add(addBtn); toolbar.add(editBtn); toolbar.add(deleteBtn); // 搜索面板 JPanel searchPanel = new JPanel(); JTextField nameField = new JTextField(10); JTextField regionField = new JTextField(10); JButton searchBtn = new JButton("搜索"); searchBtn.addActionListener(e -> searchSuppliers( nameField.getText().trim(), regionField.getText().trim() )); searchPanel.add(new JLabel("供应商名称:")); searchPanel.add(nameField); searchPanel.add(new JLabel("所在地区:")); searchPanel.add(regionField); searchPanel.add(searchBtn); // 表格 model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { return false; } }; table = new JTable(model); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 设置列名 model.setColumnIdentifiers(new String[]{ "供应商编号", "供应商名", "供应商地址", "供应商电话" }); refreshData(); // 布局 JPanel topPanel = new JPanel(new BorderLayout()); topPanel.add(toolbar, BorderLayout.NORTH); topPanel.add(searchPanel, BorderLayout.CENTER); panel.add(topPanel, BorderLayout.NORTH); panel.add(new JScrollPane(table), BorderLayout.CENTER); return panel; } private void refreshData() { List<Map<String, Object>> data = MySQL.readTable("供应商"); model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("供应商编号"), row.get("供应商名"), row.get("供应商地址"), row.get("供应商电话") }); } } private void searchSuppliers(String name, String region) { List<Map<String, Object>> data = new ArrayList<>(); String sql = "SELECT * FROM 供应商 WHERE 供应商名 LIKE ? AND 供应商地址 LIKE ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, "%" + name + "%"); pstmt.setString(2, "%" + region + "%"); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { Map<String, Object> row = new LinkedHashMap<>(); row.put("供应商编号", rs.getString("供应商编号")); row.put("供应商名", rs.getString("供应商名")); row.put("供应商地址", rs.getString("供应商地址")); row.put("供应商电话", rs.getString("供应商电话")); data.add(row); } } catch (SQLException e) { MySQL.showError("搜索错误", e); } model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("供应商编号"), row.get("供应商名"), row.get("供应商地址"), row.get("供应商电话") }); } } private void addSupplier() { JDialog dialog = new JDialog((Frame) null, "添加供应商", true); dialog.setSize(500, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(); JTextField nameField = new JTextField(); JTextField addressField = new JTextField(); JTextField phoneField = new JTextField(); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { String id = idField.getText().trim(); String name = nameField.getText().trim(); String address = addressField.getText().trim(); String phone = phoneField.getText().trim(); // 验证输入 if (id.isEmpty() || name.isEmpty()) { JOptionPane.showMessageDialog(dialog, "供应商编号和名称不能为空!"); return; } // 执行SQL if (MySQL.executeUpdate( "INSERT INTO 供应商 (供应商编号, 供应商名, 供应商地址, 供应商电话) VALUES (?, ?, ?, ?)", id, name, address, phone) > 0) { JOptionPane.showMessageDialog(dialog, "供应商添加成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "供应商添加失败!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("供应商编号:")); dialog.add(idField); dialog.add(new JLabel("供应商名称:")); dialog.add(nameField); dialog.add(new JLabel("供应商地址:")); dialog.add(addressField); dialog.add(new JLabel("供应商电话:")); dialog.add(phoneField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void editSupplier() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要修改的供应商"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); String address = (String) table.getValueAt(row, 2); String phone = (String) table.getValueAt(row, 3); JDialog dialog = new JDialog((Frame) null, "修改供应商", true); dialog.setSize(500, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(id); idField.setEditable(false); JTextField nameField = new JTextField(name); JTextField addressField = new JTextField(address); JTextField phoneField = new JTextField(phone); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { String newName = nameField.getText().trim(); String newAddress = addressField.getText().trim(); String newPhone = phoneField.getText().trim(); // 验证输入 if (newName.isEmpty()) { JOptionPane.showMessageDialog(dialog, "供应商名称不能为空!"); return; } // 执行SQL if (MySQL.executeUpdate( "UPDATE 供应商 SET 供应商名=?, 供应商地址=?, 供应商电话=? WHERE 供应商编号=?", newName, newAddress, newPhone, id) > 0) { JOptionPane.showMessageDialog(dialog, "供应商信息更新成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "供应商信息更新失败!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("供应商编号:")); dialog.add(idField); dialog.add(new JLabel("供应商名称:")); dialog.add(nameField); dialog.add(new JLabel("供应商地址:")); dialog.add(addressField); dialog.add(new JLabel("供应商电话:")); dialog.add(phoneField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void deleteSupplier() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要删除的供应商"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); int confirm = JOptionPane.showConfirmDialog( null, "确定要删除供应商: " + name + " (ID: " + id + ")?", "确认删除", JOptionPane.YES_NO_OPTION ); if (confirm == JOptionPane.YES_OPTION) { if (hasRelatedProducts(id)) { JOptionPane.showMessageDialog(null, "该供应商有商品记录,无法删除!"); return; } if (MySQL.executeUpdate("DELETE FROM 供应商 WHERE 供应商编号=?", id) > 0) { JOptionPane.showMessageDialog(null, "供应商删除成功!"); refreshData(); } else { JOptionPane.showMessageDialog(null, "供应商删除失败!"); } } } private boolean hasRelatedProducts(String supplierId) { String sql = "SELECT COUNT(*) FROM 商品 WHERE 供应商ID = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, supplierId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt(1) > 0; } } catch (SQLException e) { MySQL.showError("记录检查错误", e); return true; } } } // 出入库管理 class InventoryManager { private JTabbedPane tabbedPane = new JTabbedPane(); private Map<String, DefaultTableModel> models = new LinkedHashMap<>(); private Map<String, JTable> tables = new LinkedHashMap<>(); public JPanel createPanel() { JPanel panel = new JPanel(new BorderLayout()); tabbedPane.addTab("入库管理", createInventoryPanel("入库")); tabbedPane.addTab("出库管理", createInventoryPanel("出库")); panel.add(tabbedPane, BorderLayout.CENTER); return panel; } private JPanel createInventoryPanel(String type) { JPanel panel = new JPanel(new BorderLayout()); // 工具栏 JToolBar toolbar = new JToolBar(); JButton addBtn = new JButton("添加"); JButton editBtn = new JButton("修改"); JButton deleteBtn = new JButton("删除"); JButton refreshBtn = new JButton("刷新"); JButton capacityBtn = new JButton("仓库容量"); JButton stockBtn = new JButton("商品库存"); addBtn.addActionListener(e -> addRecord(type)); editBtn.addActionListener(e -> editRecord(type)); deleteBtn.addActionListener(e -> deleteRecord(type)); refreshBtn.addActionListener(e -> refreshData(type)); capacityBtn.addActionListener(e -> showWarehouseCapacity()); stockBtn.addActionListener(e -> showProductStock()); toolbar.add(addBtn); toolbar.add(editBtn); toolbar.add(deleteBtn); toolbar.add(refreshBtn); toolbar.add(capacityBtn); toolbar.add(stockBtn); // 搜索面板 JPanel searchPanel = new JPanel(); JTextField warehouseField = new JTextField(8); JTextField productField = new JTextField(8); JTextField dateField = new JTextField(8); JButton searchBtn = new JButton("搜索"); searchBtn.addActionListener(e -> searchRecords( type, warehouseField.getText().trim(), productField.getText().trim(), dateField.getText().trim() )); searchPanel.add(new JLabel("仓库ID:")); searchPanel.add(warehouseField); searchPanel.add(new JLabel("商品ID:")); searchPanel.add(productField); searchPanel.add(new JLabel("日期:")); searchPanel.add(dateField); searchPanel.add(searchBtn); // 表格 DefaultTableModel model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { return false; } }; model.setColumnIdentifiers(new String[]{"编号", "仓库ID", "商品ID", "商品数量", "日期", "类型"}); models.put(type, model); JTable table = new JTable(model); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); tables.put(type, table); refreshData(type); // 布局 JPanel topPanel = new JPanel(new BorderLayout()); topPanel.add(toolbar, BorderLayout.NORTH); topPanel.add(searchPanel, BorderLayout.CENTER); panel.add(topPanel, BorderLayout.NORTH); panel.add(new JScrollPane(table), BorderLayout.CENTER); return panel; } private void refreshData(String type) { List<Map<String, Object>> data = MySQL.readTable("出入库"); DefaultTableModel model = models.get(type); model.setRowCount(0); for (Map<String, Object> row : data) { if (type.equals(row.get("类型"))) { model.addRow(new Object[]{ row.get("编号"), row.get("仓库ID"), row.get("商品ID"), row.get("商品数量"), row.get("日期"), row.get("类型") }); } } } private void searchRecords(String type, String warehouseId, String productId, String date) { DefaultTableModel model = models.get(type); model.setRowCount(0); StringBuilder sql = new StringBuilder("SELECT * FROM 出入库 WHERE 类型=?"); List<Object> params = new ArrayList<>(); params.add(type); if (!warehouseId.isEmpty()) { sql.append(" AND 仓库ID LIKE ?"); params.add("%" + warehouseId + "%"); } if (!productId.isEmpty()) { sql.append(" AND 商品ID LIKE ?"); params.add("%" + productId + "%"); } if (!date.isEmpty()) { sql.append(" AND 日期 LIKE ?"); params.add("%" + date + "%"); } try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql.toString())) { for (int i = 0; i < params.size(); i++) { pstmt.setObject(i + 1, params.get(i)); } ResultSet rs = pstmt.executeQuery(); while (rs.next()) { model.addRow(new Object[]{ rs.getString("编号"), rs.getString("仓库ID"), rs.getString("商品ID"), rs.getInt("商品数量"), rs.getString("日期"), rs.getString("类型") }); } } catch (SQLException e) { MySQL.showError("搜索错误", e); } } private void addRecord(String type) { JDialog dialog = new JDialog((Frame) null, type + "记录", true); dialog.setSize(500, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField warehouseField = new JTextField(); JTextField productField = new JTextField(); JTextField quantityField = new JTextField(); JTextField dateField = new JTextField(); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String warehouseId = warehouseField.getText().trim(); String productId = productField.getText().trim(); int quantity = Integer.parseInt(quantityField.getText().trim()); String date = dateField.getText().trim(); // 验证输入 if (warehouseId.isEmpty() || productId.isEmpty() || date.isEmpty()) { JOptionPane.showMessageDialog(dialog, "所有字段都必须填写!"); return; } if (!MySQL.checkForeignKeyExists("仓库", "仓库编号", warehouseId)) { JOptionPane.showMessageDialog(dialog, "仓库ID不存在!"); return; } if (!MySQL.checkForeignKeyExists("商品", "商品编号", productId)) { JOptionPane.showMessageDialog(dialog, "商品ID不存在!"); return; } if (quantity <= 0) { JOptionPane.showMessageDialog(dialog, "商品数量必须大于0!"); return; } boolean isInbound = "入库".equals(type); // 检查容量/库存 if (isInbound && !checkWarehouseCapacity(warehouseId, quantity)) { JOptionPane.showMessageDialog(dialog, "仓库剩余容量不足!"); return; } if (!isInbound && !checkProductStock(productId, quantity)) { JOptionPane.showMessageDialog(dialog, "商品库存不足!"); return; } // 执行SQL if (MySQL.executeUpdate( "INSERT INTO 出入库 (仓库ID, 商品ID, 商品数量, 日期, 类型) VALUES (?, ?, ?, ?, ?)", warehouseId, productId, quantity, date, type) > 0) { // 更新仓库容量和商品库存 MySQL.updateWarehouseCapacity(warehouseId, quantity, isInbound); MySQL.updateProductStock(productId, quantity, isInbound); JOptionPane.showMessageDialog(dialog, type + "记录添加成功!"); dialog.dispose(); refreshData(type); } else { JOptionPane.showMessageDialog(dialog, type + "记录添加失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("仓库ID:")); dialog.add(warehouseField); dialog.add(new JLabel("商品ID:")); dialog.add(productField); dialog.add(new JLabel("商品数量:")); dialog.add(quantityField); dialog.add(new JLabel("日期(YYYY-MM-DD):")); dialog.add(dateField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private boolean checkWarehouseCapacity(String warehouseId, int quantity) { String sql = "SELECT 剩余容量 FROM 仓库 WHERE 仓库编号 = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, warehouseId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt("剩余容量") >= quantity; } } catch (SQLException e) { MySQL.showError("容量检查错误", e); return false; } } private boolean checkProductStock(String productId, int quantity) { String sql = "SELECT 库存 FROM 商品 WHERE 商品编号 = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, productId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt("库存") >= quantity; } } catch (SQLException e) { MySQL.showError("库存检查错误", e); return false; } } private void showWarehouseCapacity() { String warehouseId = JOptionPane.showInputDialog("请输入仓库编号:"); if (warehouseId != null && !warehouseId.isEmpty()) { String sql = "SELECT 剩余容量 FROM 仓库 WHERE 仓库编号 = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, warehouseId); try (ResultSet rs = pstmt.executeQuery()) { if (rs.next()) { JOptionPane.showMessageDialog(null, "仓库 " + warehouseId + " 的剩余容量: " + rs.getInt("剩余容量")); } else { JOptionPane.showMessageDialog(null, "未找到仓库!"); } } } catch (SQLException e) { MySQL.showError("查询错误", e); } } } private void showProductStock() { String productId = JOptionPane.showInputDialog("请输入商品编号:"); if (productId != null && !productId.isEmpty()) { String sql = "SELECT 库存 FROM 商品 WHERE 商品编号 = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, productId); try (ResultSet rs = pstmt.executeQuery()) { if (rs.next()) { JOptionPane.showMessageDialog(null, "商品 " + productId + " 的库存: " + rs.getInt("库存")); } else { JOptionPane.showMessageDialog(null, "未找到商品!"); } } } catch (SQLException e) { MySQL.showError("查询错误", e); } } } private void editRecord(String type) { JTable table = tables.get(type); int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要修改的记录"); return; } String id = (String) table.getValueAt(row, 0); String warehouseId = (String) table.getValueAt(row, 1); String productId = (String) table.getValueAt(row, 2); int quantity = (int) table.getValueAt(row, 3); String date = (String) table.getValueAt(row, 4); JDialog dialog = new JDialog((Frame) null, "修改记录", true); dialog.setSize(500, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField warehouseField = new JTextField(warehouseId); JTextField productField = new JTextField(productId); JTextField quantityField = new JTextField(String.valueOf(quantity)); JTextField dateField = new JTextField(date); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String newWarehouseId = warehouseField.getText().trim(); String newProductId = productField.getText().trim(); int newQuantity = Integer.parseInt(quantityField.getText().trim()); String newDate = dateField.getText().trim(); // 验证输入 if (newWarehouseId.isEmpty() || newProductId.isEmpty() || newDate.isEmpty()) { JOptionPane.showMessageDialog(dialog, "所有字段都必须填写!"); return; } if (!MySQL.checkForeignKeyExists("仓库", "仓库编号", newWarehouseId)) { JOptionPane.showMessageDialog(dialog, "仓库ID不存在!"); return; } if (!MySQL.checkForeignKeyExists("商品", "商品编号", newProductId)) { JOptionPane.showMessageDialog(dialog, "商品ID不存在!"); return; } if (newQuantity <= 0) { JOptionPane.showMessageDialog(dialog, "商品数量必须大于0!"); return; } boolean isInbound = "入库".equals(type); // 检查容量/库存 if (isInbound && !checkWarehouseCapacity(newWarehouseId, newQuantity)) { JOptionPane.showMessageDialog(dialog, "仓库剩余容量不足!"); return; } if (!isInbound && !checkProductStock(newProductId, newQuantity)) { JOptionPane.showMessageDialog(dialog, "商品库存不足!"); return; } // 执行SQL if (MySQL.executeUpdate( "UPDATE 出入库 SET 仓库ID=?, 商品ID=?, 商品数量=?, 日期=? WHERE 编号=?", newWarehouseId, newProductId, newQuantity, newDate, id) > 0) { // 撤销原操作的影响 MySQL.updateWarehouseCapacity(warehouseId, quantity, !isInbound); MySQL.updateProductStock(productId, quantity, !isInbound); // 应用新操作的影响 MySQL.updateWarehouseCapacity(newWarehouseId, newQuantity, isInbound); MySQL.updateProductStock(newProductId, newQuantity, isInbound); JOptionPane.showMessageDialog(dialog, "记录更新成功!"); dialog.dispose(); refreshData(type); } else { JOptionPane.showMessageDialog(dialog, "记录更新失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("仓库ID:")); dialog.add(warehouseField); dialog.add(new JLabel("商品ID:")); dialog.add(productField); dialog.add(new JLabel("商品数量:")); dialog.add(quantityField); dialog.add(new JLabel("日期(YYYY-MM-DD):")); dialog.add(dateField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void deleteRecord(String type) { JTable table = tables.get(type); int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要删除的记录"); return; } String id = (String) table.getValueAt(row, 0); String warehouseId = (String) table.getValueAt(row, 1); String productId = (String) table.getValueAt(row, 2); int quantity = (int) table.getValueAt(row, 3); int confirm = JOptionPane.showConfirmDialog( null, "确定要删除这条记录吗?", "确认删除", JOptionPane.YES_NO_OPTION ); if (confirm == JOptionPane.YES_OPTION) { if (MySQL.executeUpdate("DELETE FROM 出入库 WHERE 编号=?", id) > 0) { boolean isInbound = "入库".equals(type); // 撤销操作的影响 MySQL.updateWarehouseCapacity(warehouseId, quantity, !isInbound); MySQL.updateProductStock(productId, quantity, !isInbound); JOptionPane.showMessageDialog(null, "记录删除成功!"); refreshData(type); } else { JOptionPane.showMessageDialog(null, "记录删除失败!"); } } } } // 管理员管理 class AdminManager { private String currentUser; public AdminManager(String currentUser) { this.currentUser = currentUser; } public JPanel createPanel() { JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = new Insets(20, 20, 20, 20); gbc.gridx = 0; gbc.gridy = 0; JLabel titleLabel = new JLabel("用户管理"); titleLabel.setFont(new Font("宋体", Font.BOLD, 24)); panel.add(titleLabel, gbc); gbc.gridy++; JButton changePwdBtn = new JButton("修改密码"); changePwdBtn.setPreferredSize(new Dimension(200, 40)); changePwdBtn.addActionListener(e -> changePassword()); panel.add(changePwdBtn, gbc); return panel; } private void changePassword() { JDialog dialog = new JDialog((Frame) null, "修改密码", true); dialog.setSize(400, 250); dialog.setLayout(new GridLayout(4, 2, 10, 10)); dialog.setLocationRelativeTo(null); JPasswordField oldPwdField = new JPasswordField(); JPasswordField newPwdField = new JPasswordField(); JPasswordField confirmPwdField = new JPasswordField(); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { String oldPwd = new String(oldPwdField.getPassword()); String newPwd = new String(newPwdField.getPassword()); String confirmPwd = new String(confirmPwdField.getPassword()); if (oldPwd.isEmpty() || newPwd.isEmpty() || confirmPwd.isEmpty()) { JOptionPane.showMessageDialog(dialog, "所有字段都必须填写!"); return; } if (!MySQL.validateUser(currentUser, oldPwd)) { JOptionPane.showMessageDialog(dialog, "旧密码不正确!"); return; } if (!newPwd.equals(confirmPwd)) { JOptionPane.showMessageDialog(dialog, "两次输入的新密码不一致!"); return; } if (MySQL.updatePassword(currentUser, newPwd)) { JOptionPane.showMessageDialog(dialog, "密码修改成功!"); dialog.dispose(); } else { JOptionPane.showMessageDialog(dialog, "密码更新失败,请联系管理员"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); dialog.add(new JLabel("旧密码:")); dialog.add(oldPwdField); dialog.add(new JLabel("新密码:")); dialog.add(newPwdField); dialog.add(new JLabel("确认新密码:")); dialog.add(confirmPwdField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } }详细解释解释每一行

@WebServlet("/ChangePasswordServlet")public class ChangePasswordServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String oldPassword = request.getParameter("oldPassword"); String newPassword = request.getParameter("newPassword"); // 验证旧密码是否正确 if (checkPassword(username, oldPassword)) { // 更新密码 updatePassword(username, newPassword); response.sendRedirect("success.jsp"); } else { response.sendRedirect("error.jsp"); } } private boolean checkPassword(String username, String password) { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; boolean result = false; try { conn = DBUtil.getConnection(); String sql = "SELECT * FROM user WHERE username=? AND password=?"; stmt = conn.prepareStatement(sql); stmt.setString(1, username); stmt.setString(2, password); rs = stmt.executeQuery(); result = rs.next(); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(rs, stmt, conn); } return result; } private void updatePassword(String username, String password) { Connection conn = null; PreparedStatement stmt = null; try { conn = DBUtil.getConnection(); String sql = "UPDATE user SET password=? WHERE username=?"; stmt = conn.prepareStatement(sql); stmt.setString(1, password); stmt.setString(2, username); stmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(null, stmt, conn); } }}具体解释一下各代码意思

<template> <el-menu class="site-navbar__menu" mode="horizontal" style="height:38px;"> <el-menu-item v-if="sidebarIsShow" class="site-navbar__switch" id="myzhedie" index="0" @click="sidebarFold = !sidebarFold" style="width:64px;"> <icon-svg name="zhedie"></icon-svg> </el-menu-item> <el-menu-item v-else class="site-navbar__switch" index="0" id="myhome1" style="width:64px;"> <icon-svg name="home"></icon-svg> </el-menu-item> <el-menu-item class="site-navbar__switch" index="0" style="padding:0 0px;background-color:transparent;color:inherit;margin-left:-10px"> </el-menu-item> </el-menu> <el-menu id="myNavbar" :default-active="activeMenu" @select="handleSelect" class="site-navbar__menu" mode="horizontal" style="margin-left:21px;" default-active="home"> <el-menu-item v-if="isAuth('battery:bmsbatteryinfo:monitornavbar')" style="margin-left:-1%;font-size: 14px;" index="home" @click="openHomeHandle"> <icon-svg name="chezidingyi" class="site-sidebar__menu-icon"></icon-svg> 实时查询 </el-menu-item> <el-menu-item v-if="isAuth('battery:bmsbatteryinfo:traditionnavbar')" style="margin-left:-1%;font-size: 14px;" index="tradition" @click="openSideMenusHandle('31,118,150,153,214,1,46,32,67,-100')"> <icon-svg name="system" class="site-sidebar__menu-icon"></icon-svg> 数据管理中心 </el-menu-item> <el-menu-item v-if="isAuth('battery:bmsbatteryinfo:reportnavbar')" style="margin-left:-1%;font-size: 14px;" index="report" @click="openSideMenusHandle('445,453,458,459,462,-2')"> <icon-svg name="tubiao" class="site-sidebar__menu-icon"></icon-svg> 统计分析 </el-menu-item> <el-menu-item v-if="isAuth('battery:bmsbatteryinfo:statisticsnavbar')" style="margin-left:-1%;font-size: 14px;" index="statistics" @click="openSideMenusHandle('465,470,471,475,-1')"> <icon-svg name="shouye" class="site-sidebar__menu-icon"></icon-svg> 安全中心 </el-menu-item> <el-menu-item v-if="isAuth('battery:bmsbatteryinfo:managenavbar')" style="margin-left:-1%;font-size: 14px;" index="manage" @click="openSideMenusHandle('405,384,1,-3')"> <icon-svg name="config" class="site-sidebar__menu-icon"></icon-svg> 管理中心 </el-menu-item> <el-submenu id="myWindow" v-if="isAuth('battery:bmsbatteryinfo:largescreennavbar')" style="margin-left:-1%;font-size: 14px;" index="largescreen"> <template slot="title" style="margin-left:-1%;font-size: 14px;"> <icon-svg name="dashujukeshihua" class="site-sidebar__menu-icon"></icon-svg> 驾驶舱 </template> <el-menu-item index="2-1" @click="openEchartInNewWindow" v-if="isAuth('mqtt:mtbatteryinfolastest:largedep')"> <icon-svg name="dashujukeshihua" class="site-sidebar__menu-icon"></icon-svg> 欣动电池大屏 </el-menu-item> </el-submenu> </el-menu> <el-menu class="site-navbar__menu site-navbar__menu--right" mode="horizontal"> <el-menu-item index="1" id="mydaping" @click="openEchartInNewWindow" v-if="isAuth('mqtt:mtbatteryinfolastest:largeDatalist')"> <template slot="title"> <el-badge value="大屏"> <icon-svg name="dashujukeshihua" class="el-icon-rank"></icon-svg> </el-badge> </template> </el-menu-item> <el-menu-item index="2" id="myshezhi" @click="$router.push({ name: 'theme' })"> <template slot="title"> <el-badge value="设置"> <icon-svg name="shezhi" class="el-icon-setting"></icon-svg> </el-badge> </template> </el-menu-item> <el-menu-item class="site-navbar__avatar" index="3" id="myhuichu"> <el-dropdown :show-timeout="0" placement="bottom"> {{ userName }} <el-dropdown-menu slot="dropdown"> <el-dropdown-item @click.native="updatePasswordHandle()">修改密码</el-dropdown-item> <el-dropdown-item @click.native="logoutHandle()">退出</el-dropdown-item> </el-dropdown-menu> </el-dropdown> </el-menu-item> </el-menu> <update-password v-if="updatePassowrdVisible" ref="updatePassowrd"></update-password> </template> <script> import UpdatePassword from './main-navbar-update-password' import { clearLoginInfo,EventBus } from '@/utils' import Router from 'vue-router' import http from '@/utils/httpRequest' import { isURL } from '@/utils/validate' export default { data () { return { firstLogin: true, updatePassowrdVisible: false, activeMenu: 'tradition' // 默认激活的菜单项ID } }, components: { UpdatePassword }, computed: { navbarLayoutType: { get () { return this.$store.state.common.navbarLayoutType } }, sidebarFold: { get () { return this.$store.state.common.sidebarFold }, set (val) { this.$store.commit('common/updateSidebarFold', val) } }, mainTabs: { get () { return this.$store.state.common.mainTabs }, set (val) { this.$store.commit('common/updateMainTabs', val) } }, menuActiveName: { get () { return this.$store.state.common.menuActiveName }, set (val) { this.$store.commit('common/updateMenuActiveName', val) } }, userName: { get () { return this.$store.state.user.name } }, isHomePage(){ return this.$route.path === '/home' }, // 左侧菜单显示 sidebarIsShow: { get () { return this.$store.state.common.sidebarIsShow }, set (val) { this.$store.commit('common/updateSidebarIsShow', val) } }, // 顶部菜单的点击 // activeMenuIndex() { // return this.activeMenu.toString(); // 转换为字符串,以匹配模板中的index // } }, created() { // 刚登录进来,多点击监控中心,防止左侧缓存的菜单出现---20241217 this.firstLogin && ---------------------------------- if(localStorage.getItem('firstLogin')===null){ localStorage.clear(); console.log('本地存储已清除'); localStorage.setItem('firstLogin', '1'); this.firstLogin = false; // alert('第一次进来,firstLogin='+localStorage.getItem('firstLogin')) // 显示左侧菜单隐藏 this.openHomeHandle () setTimeout(() => { // alert('延时加载') this.openHomeHandle (); }, 1); setTimeout(() => { // alert('延时加载') this.openHomeHandle (); }, 100); }else{ // 显示左侧菜单显示 // alert('firstLogin='+localStorage.getItem('firstLogin')) // this.$store.state.common.sidebarIsShow = true } //------------------------------------------------------------------------------------------------------------ this.openHomeHandle () setTimeout(() => { // alert('延时加载') this.openHomeHandle (); }, 10); setTimeout(() => { // alert('延时加载') this.openHomeHandle (); }, 100); setTimeout(() => { // alert('延时加载') this.openHomeHandle (); }, 120); setTimeout(() => { // alert('延时加载') this.openHomeHandle (); }, 180); // 页面加载时尝试恢复之前的选中状态。刷新时一直保持点击颜色 this.activeMenu = sessionStorage.getItem('activeMenu') || this.activeMenu; }, methods: { handleSelect(key, keyPath) { // 菜单项被点击时保存选中状态 sessionStorage.setItem('activeMenu', key); // vue刷新页面数据不丢失-localStorage或sessionStorage保存数据 }, openEchartInNewWindow() { const routeData = this.$router.resolve({ name: 'echart' }); window.open(routeData.href, '_blank'); }, // 修改密码 updatePasswordHandle () { this.updatePassowrdVisible = true this.$nextTick(() => { this.$refs.updatePassowrd.init() }) }, // 退出 logoutHandle () { this.$confirm(确定进行[退出]操作?, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.$http({ url: this.$http.adornUrl('/sys/logout'), method: 'post', data: this.$http.adornData() }).then(({data}) => { if (data && data.code === 0) { clearLoginInfo() this.$router.push({ name: 'login' }) } }) }).catch(() => {}) }, openSideMenusHandle (parentMenuIds) { // alert(parentMenuIds) this.mainTabs = [] //清除打开的tab菜单 this.menuActiveName = '' // 左侧菜单显示 this.$store.state.common.sidebarIsShow = true // 折叠打开 this.$store.state.common.sidebarFold = false // 这里调用左侧菜单的方法 EventBus.$emit('callMethod',parentMenuIds); // 再次调用,防止点击监控中心--然后跳转到其他菜单时无反应 setTimeout(() => { // alert('延时加载') EventBus.$emit('callMethod',parentMenuIds); }, 150); setTimeout(() => { // alert('延时加载') EventBus.$emit('callMethod',parentMenuIds); }, 100); setTimeout(() => { // alert('延时加载') EventBus.$emit('callMethod',parentMenuIds); }, 220); setTimeout(() => { // alert('延时加载') EventBus.$emit('callMethod',parentMenuIds); }, 120); // this.$router.push({ name: 'center' }) // center home }, openHomeHandle () { // alert("jianko") // this.mainTabs = [] //清除打开的tab菜单 // this.menuActiveName = '' // this.isHomePage = true // 折叠关闭 this.$store.state.common.sidebarFold = true // 左侧菜单显示关闭 this.$store.state.common.sidebarIsShow = false this.$router.push({ name: 'home' }) }, //--------------------------------------------------------------------------------------------------- // tabs, 关闭全部tab tabsCloseAllHandle () { this.mainTabs = [] this.menuActiveName = '' this.$router.push({ name: 'home' }) }, reloadMenus(parentMenuIds){ this.$http({ url: this.$http.adornUrl('/sys/menu/navappoint'), method: 'get', // params: this.$http.adornParams() params: this.$http.adornParams({ 'parentMenuIds': parentMenuIds }) }).then(({data}) => { if (data && data.code === 0) { // alert("获取导航菜单成功") this.fnAddDynamicMenuRoutes(data.menuList) this.$router.options.isAddDynamicMenuRoutes = true sessionStorage.setItem('menuList', JSON.stringify(data.menuList || '[]')) sessionStorage.setItem('permissions', JSON.stringify(data.permissions || '[]')) // sessionStorage.setItem('menuList', '[]') // sessionStorage.setItem('permissions', '[]') // alert("添加菜单") // 这里调用左侧菜单的方法 EventBus.$emit('callMethod',parentMenuIds); this.tabsCloseAllHandle (); // 折叠打开 this.$store.state.common.sidebarFold = false this.$router.push({ name: 'home' }) // next({ ...to, replace: true }) // 刷新 // location.reload() // alert("前往首页") } else { sessionStorage.setItem('menuList', '[]') sessionStorage.setItem('permissions', '[]') // 折叠缩进 this.$store.state.common.sidebarFold = true next() } }).catch((e) => { // alert("请求菜单列表和权限失败-to.path="+to.path) console.log(%c${e} 请求菜单列表和权限失败,跳转至登录页!!, 'color:blue') // alert("权限失败login") // this.$router.push({ name: 'login' }) }) }, /** * 添加动态(菜单)路由 * @param {*} menuList 菜单列表 * @param {*} routes 递归创建的动态(菜单)路由 */ fnAddDynamicMenuRoutes (menuList = [], routes = []) { var temp = [] for (var i = 0; i < menuList.length; i++) { if (menuList[i].list && menuList[i].list.length >= 1) { temp = temp.concat(menuList[i].list) } else if (menuList[i].url && /\S/.test(menuList[i].url)) { menuList[i].url = menuList[i].url.replace(/^\//, '') var route = { path: menuList[i].url.replace('/', '-'), component: null, name: menuList[i].url.replace('/', '-'), meta: { menuId: menuList[i].menuId, title: menuList[i].name, isDynamic: true, isTab: true, iframeUrl: '' } } // url以http[s]://开头, 通过iframe展示 if (isURL(menuList[i].url)) { route['path'] = i-${menuList[i].menuId} route['name'] = i-${menuList[i].menuId} route['meta']['iframeUrl'] = menuList[i].url } else { try { route['component'] = _import(modules/${menuList[i].url}) || null } catch (e) {} } routes.push(route) } } if (temp.length >= 1) { this.fnAddDynamicMenuRoutes(temp, routes) } else { var mainRoutes = { name: 'main-dynamic', children: routes, path: '/' } // mainRoutes.name = 'main-dynamic' // mainRoutes.children = routes this.$router.addRoutes([ mainRoutes, { path: '*', redirect: { name: '404' } } ]) sessionStorage.setItem('dynamicMenuRoutes', JSON.stringify(mainRoutes.children || '[]')) console.log('\n') console.log('%c!<-------------------- 动态(菜单)路由 s -------------------->', 'color:blue') console.log(mainRoutes.children) console.log('%c!<-------------------- 动态(菜单)路由 e -------------------->', 'color:blue') } }, /** * 添加动态(菜单)路由 * @param {*} menuList 菜单列表 * @param {*} routes 递归创建的动态(菜单)路由 */ fnAddDynamicMenuRoutes2 (menuList) { var routes = [] var temp = [] // alert("添加动态(菜单)路由--"+menuList.length) for (var i = 0; i < menuList.length; i++) { // alert("添加动态URL----"+menuList[i].url) if (menuList[i].list && menuList[i].list.length >= 1) { temp = temp.concat(menuList[i].list) } else if (menuList[i].url && /\S/.test(menuList[i].url)) { menuList[i].url = menuList[i].url.replace(/^\//, '') var route = { path: menuList[i].url.replace('/', '-'), component: null, name: menuList[i].url.replace('/', '-'), meta: { menuId: menuList[i].menuId, title: menuList[i].name, isDynamic: true, isTab: true, iframeUrl: '' } } // alert("添加动态=isTab==="+route['meta']['isTab']) // url以http[s]://开头, 通过iframe展示 if (isURL(menuList[i].url)) { route['path'] = i-${menuList[i].menuId} route['name'] = i-${menuList[i].menuId} route['meta']['iframeUrl'] = menuList[i].url // alert("添加动态=isTab==="+route['meta']['isTab']) } else { try { route['component'] = _import(modules/${menuList[i].url}) || null } catch (e) {} } routes.push(route) } } if (temp.length >= 1) { this.fnAddDynamicMenuRoutes(temp, routes) } else { var mainRoutes = { name: 'main-dynamic', children: routes, path: '/' } // mainRoutes.name = 'main-dynamic' // mainRoutes.children = routes this.$router.addRoutes([ mainRoutes, { path: '*', redirect: { name: '404' } } ]) sessionStorage.setItem('dynamicMenuRoutes', JSON.stringify(mainRoutes.children || '[]')) console.log('\n') console.log('%c!<-------------------- 动态(菜单)路由 s -------------------->', 'color:blue') console.log(mainRoutes.children) console.log('%c!<-------------------- 动态(菜单)路由 e -------------------->', 'color:blue') } } //---------------------------------------------------------------------------------------------------------------------- } } </script> <style> #myNavbar .el-menu-item:hover { background-color: transparent !important; color: inherit !important; } /* 顶部菜单点击后的背景颜色 */ #myNavbar .el-menu-item.is-active { background-color:rgb(15, 89, 164) !important; color:rgb(235, 184, 17); /*选中颜色*/ span { color: #fff !important; } } /* 驾驶舱鼠标悬浮时 样式文件或组件内样式 */ #myNavbar .el-submenu__title:hover { background-color:rgb(15, 89, 164) !important; /* 使用!important确保覆盖默认样式 */ } .site-navbar__menu .el-menu-item, .site-navbar__menu .el-submenu > .el-submenu__title { height: 38px; line-height: 38px; } /* 左侧菜单选中与悬停样式 */ #myzhedie:hover { background-color: #409EFF !important; /* 使用!important确保覆盖默认样式 */ color: inherit !important; } #myzhedie.is-active { background-color: rgba(126, 203, 252, 1) !important; /* 使用!important确保覆盖默认样式 */ } #myhome1:hover { background-color: rgba(126, 203, 252, 1) !important; /* 使用!important确保覆盖默认样式 */ color: inherit !important; } #myhome1.is-active { background-color: rgba(126, 203, 252, 1) !important; /* 使用!important确保覆盖默认样式 */ } #myshezhi:hover { background-color: #409EFF !important; /* 使用!important确保覆盖默认样式 */ color: inherit !important; } #myshezhi.is-active { background-color: rgba(126, 203, 252, 1) !important; /* 使用!important确保覆盖默认样式 */ } #mydaping:hover { background-color: #409EFF !important; /* 使用!important确保覆盖默认样式 */ color: inherit !important; } #mydaping.is-active { background-color: rgba(126, 203, 252, 1) !important; /* 使用!important确保覆盖默认样式 */ } #myhuichu:hover { background-color: #409EFF !important; /* 使用!important确保覆盖默认样式 */ color: inherit !important; } #myhuichu.is-active { background-color: rgba(126, 203, 252, 1) !important; /* 使用!important确保覆盖默认样式 */ } /* 加载表头颜色设置 */ /* rgba(126, 203, 252, 1) rgba(211, 236, 255, 255) #cdccd9 #87CEEB; rgba(211, 236, 255, 255); rgba(137, 207, 240); */ /* .el-table thead th { color: #909399; background-color: rgba(211, 236, 255, 255); font-weight: 800; color: #1D3124; } */ </style>修改驾驶舱下拉框的背景颜色和当前菜单颜色风格一致

@Data public class Emp { private Integer id; //ID,主键 private String username; //用户名 private String password; //密码 private String newPassword; //新密码 /** * 修改密码接口 * @param emp 包含用户名和新密码的实体 * @return 操作结果 */ @PutMapping("/update") public Result updatePassword(@RequestBody Emp emp) { try { empService.updatePassword(emp); return Result.success("密码修改成功"); } catch (RuntimeException e) { return Result.error(e.getMessage()); } } /** * 修改密码 * @param emp */ @Update("update emp set password = #{newPassword} WHERE username = #{username} and password = #{password}") void updatePassword(Emp emp); <script lang="ts" setup> import { ref, onMounted, nextTick } from 'vue' import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus' import { useRouter } from 'vue-router' import request from '@/utils/request' import type { ResultModel } from '@/api/model/model' // 类型定义 interface PasswordForm { oldPassword: string newPassword: string confirmPassword: string } interface LoginUser { id: number name: string role: string } // API调用 const updatePasswordApi = (data: { oldPassword: string; newPassword: string }) => request.put<any, ResultModel>('/emps/update', data) const router = useRouter() const loginName = ref('管理员') const loginRole = ref('管理员') const showPasswordDialog = ref(false) const passwordForm = ref({ oldPassword: '', newPassword: '', confirmPassword: '', }) const passwordFormRef = ref<FormInstance>() const loading = ref(false) // 密码验证规则 const passwordRules: FormRules = { oldPassword: [ { required: true, message: '请输入旧密码', trigger: 'blur' }, { min: 6, max: 20, message: '密码长度6-20个字符', trigger: 'blur' }, ], newPassword: [ { required: true, message: '请输入新密码', trigger: 'blur' }, { min: 6, max: 20, message: '密码长度6-20个字符', trigger: 'blur' }, { validator: (_, value, callback) => { if (value === passwordForm.value.oldPassword) { callback(new Error('新密码不能与旧密码相同')) } else { callback() } }, trigger: 'blur', }, ], confirmPassword: [ { required: true, message: '请确认新密码', trigger: 'blur' }, { validator: (_, value, callback) => { if (value !== passwordForm.value.newPassword) { callback(new Error('两次输入的密码不一致')) } else { callback() } }, trigger: 'blur', }, ], } // 初始化用户信息 onMounted(() => { const token = localStorage.getItem('token') if (token) { try { const loginUser: LoginUser = JSON.parse(token) loginName.value = loginUser.name || '管理员' loginRole.value = loginUser.role || '管理员' } catch (e) { console.error('解析token失败:', e) } } }) // 打开修改密码对话框 const openPasswordDialog = () => { showPasswordDialog.value = true passwordForm.value = { oldPassword: '', newPassword: '', confirmPassword: '' } nextTick(() => { if (passwordFormRef.value) { passwordFormRef.value.resetFields() } }) } // 提交修改密码 const submitPassword = async () => { if (!passwordFormRef.value) return try { await passwordFormRef.value.validate() loading.value = true const response = await updatePasswordApi({ oldPassword: passwordForm.value.oldPassword, newPassword: passwordForm.value.newPassword, }) if (response.code === 1) { ElMessage.success('密码修改成功') showPasswordDialog.value = false // 清空表单 passwordFormRef.value.resetFields() // 模拟退出登录 setTimeout(logout, 1000) } else { ElMessage.error(response.msg || '密码修改失败') } } catch (error) { console.error('修改密码失败:', error) } finally { loading.value = false } } // 退出登录 const logout = () => { ElMessageBox.confirm('确定要退出登录吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', center: true, }) .then(() => { localStorage.removeItem('token') router.push('/login') ElMessage.success('退出登录成功') }) .catch(() => {}) } </script> <template> <el-container class="layout-container"> <el-header class="header"> AI教学管理系统 <el-avatar class="user-avatar" :size="36"> {{ loginName.charAt(0) }} </el-avatar> {{ loginName }} {{ loginRole }} <el-tooltip content="修改密码" placement="bottom"> <el-button class="tool-btn" type="text" @click="openPasswordDialog"> <el-icon class="icon"><EditPen /></el-icon> </el-button> </el-tooltip> <el-tooltip content="退出登录" placement="bottom"> <el-button class="tool-btn" type="text" @click="logout"> <el-icon class="icon"><SwitchButton /></el-icon> </el-button> </el-tooltip> </el-header> <el-container class="main-container"> <el-aside class="aside"> <el-scrollbar class="menu-scrollbar"> <el-menu router default-active="/index" class="side-menu" background-color="#2c3e50" text-color="#ecf0f1" active-text-color="#f39c12" > <el-menu-item index="/index"> <el-icon><Menu /></el-icon> 首页 </el-menu-item> <el-sub-menu index="2" class="menu-group"> <template #title> <el-icon><Document /></el-icon> 班级学员管理 </template> <el-menu-item index="/stu"> <el-icon><UserFilled /></el-icon> 学员管理 </el-menu-item> <el-menu-item index="/clazz"> <el-icon><HomeFilled /></el-icon> 班级管理 </el-menu-item> </el-sub-menu> <el-sub-menu index="3" class="menu-group"> <template #title> <el-icon><Avatar /></el-icon> 部门管理 </template> <el-menu-item index="/emp"> <el-icon><Avatar /></el-icon> 员工管理 </el-menu-item> <el-menu-item index="/dept"> <el-icon><HelpFilled /></el-icon> 部门管理 </el-menu-item> </el-sub-menu> <el-sub-menu index="4" class="menu-group"> <template #title> <el-icon></el-icon> 数据统计管理 </template> <el-menu-item index="/report/emp"> <el-icon><InfoFilled /></el-icon> 员工信息统计 </el-menu-item> <el-menu-item index="/report/stu"> <el-icon><Share /></el-icon> 学员信息统计 </el-menu-item> <el-menu-item index="/log"> <el-icon><Clock /></el-icon> 日志信息统计 </el-menu-item> </el-sub-menu> </el-menu> </el-scrollbar> </el-aside> <el-main class="main-content"> <router-view></router-view> </el-main> </el-container> </el-container> <el-dialog v-model="showPasswordDialog" title="修改密码" width="500px" center :close-on-click-modal="false" > <el-form ref="passwordFormRef" :model="passwordForm" :rules="passwordRules" label-width="100px" label-position="right" > <el-form-item label="旧密码" prop="oldPassword"> <el-input v-model="passwordForm.oldPassword" type="password" placeholder="请输入当前密码" show-password clearable /> </el-form-item> <el-form-item label="新密码" prop="newPassword"> <el-input v-model="passwordForm.newPassword" type="password" placeholder="6-20位字符" show-password clearable /> </el-form-item> <el-form-item label="确认密码" prop="confirmPassword"> <el-input v-model="passwordForm.confirmPassword" type="password" placeholder="请再次输入新密码" show-password clearable /> </el-form-item> </el-form> <template #footer> <el-button @click="showPasswordDialog = false">取消</el-button> <el-button type="primary" @click="submitPassword" :loading="loading"> 确认修改 </el-button> </template> </el-dialog> </template> <style scoped> /* 布局基础样式 */ .common-layout { height: 100vh; display: flex; flex-direction: column; background-color: #f5f7fa; } .layout-container { height: 100%; display: flex; flex-direction: column; } /* 头部样式 - 优化版 */ .header { background: linear-gradient(135deg, #2c3e50 0%, #1a2530 100%); color: white; height: 64px; padding: 0; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); z-index: 1000; position: relative; } .header-content { display: flex; justify-content: space-between; align-items: center; height: 100%; padding: 0 30px; max-width: 1600px; margin: 0 auto; width: 100%; } .logo-section { display: flex; align-items: center; gap: 15px; } .logo { width: 40px; height: 40px; background: linear-gradient(135deg, #3498db, #8e44ad); border-radius: 8px; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); } .title { font-size: 1.8rem; font-weight: 700; letter-spacing: 1px; background: linear-gradient(to right, #f39c12, #f1c40f); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); } .user-section { display: flex; align-items: center; gap: 20px; } .user-info { display: flex; align-items: center; gap: 12px; padding: 5px 15px; border-radius: 30px; background: rgba(255, 255, 255, 0.1); transition: all 0.3s ease; } .user-info:hover { background: rgba(255, 255, 255, 0.15); } .user-avatar { background: linear-gradient(135deg, #3498db, #8e44ad); display: flex; align-items: center; justify-content: center; font-weight: bold; color: white; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); } .user-details { display: flex; flex-direction: column; } .user-name { font-weight: 600; font-size: 15px; letter-spacing: 0.5px; } .user-role { font-size: 12px; color: #bdc3c7; margin-top: 2px; } .header-tools { display: flex; gap: 8px; } .tool-btn { color: #ecf0f1; font-size: 18px; padding: 8px; transition: all 0.3s ease; border-radius: 50%; width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; } .tool-btn:hover { background-color: rgba(255, 255, 255, 0.15); transform: translateY(-2px); } .tool-btn .icon { transition: transform 0.3s ease; } .tool-btn:hover .icon { transform: scale(1.2); } /* 侧边栏样式 */ .aside { background-color: #2c3e50; color: #ecf0f1; height: 100%; width: 240px !important; transition: width 0.3s ease; border-right: 1px solid #34495e; } .menu-scrollbar { height: calc(100vh - 64px); } .menu-scrollbar .el-scrollbar__bar.is-vertical { width: 6px; right: 2px; border-radius: 4px; background-color: rgba(255, 255, 255, 0.1); } .menu-scrollbar .el-scrollbar__thumb { background-color: rgba(255, 255, 255, 0.3); border-radius: 4px; transition: background-color 0.3s ease; } .menu-scrollbar .el-scrollbar__thumb:hover { background-color: rgba(255, 255, 255, 0.5); } .side-menu { background-color: transparent; border-right: none; padding: 15px 0; } .side-menu .el-menu-item, .side-menu .el-sub-menu .el-sub-menu__title { margin: 6px 10px; padding: 12px 20px; font-size: 14px; color: #ecf0f1; border-radius: 6px; transition: all 0.3s ease; height: 48px; display: flex; align-items: center; } .side-menu .el-menu-item:hover, .side-menu .el-sub-menu .el-sub-menu__title:hover { background-color: #34495e; transform: translateX(5px); } .side-menu .el-menu-item.is-active { background: linear-gradient(90deg, rgba(52, 152, 219, 0.3), transparent); color: #f39c12 !important; font-weight: bold; border-left: 3px solid #f39c12; } .menu-group .el-menu-item { font-size: 13px; padding-left: 50px !important; color: #dcdcdc; transition: all 0.3s ease; height: 42px; } .menu-group .el-menu-item:hover { background-color: #3a5267; transform: translateX(5px); } .menu-group .el-menu-item.is-active { background-color: #3a5267; color: #f1c40f; font-weight: 600; } /* 主内容区样式 */ .main-content { background-color: #f0f2f5; padding: 20px; flex: 1; overflow-y: auto; border-radius: 8px 8px 0 0; box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.05); } /* 对话框样式 */ .dialog-footer { display: flex; justify-content: center; padding: 10px 20px 0; } /* 响应式设计 */ @media (max-width: 992px) { .aside { width: 200px !important; } .header-content { padding: 0 20px; } .title { font-size: 1.5rem; } .user-info .user-name { display: none; } } @media (max-width: 768px) { .aside { width: 64px !important; } .logo-section .title, .user-info .user-details, .el-sub-menu .el-sub-menu__title span, .el-menu-item span { display: none; } .el-sub-menu .el-sub-menu__title, .el-menu-item { justify-content: center; padding: 0 !important; } .el-icon { margin-right: 0 !important; font-size: 20px; } .menu-group .el-menu-item { padding-left: 20px !important; justify-content: flex-start; } } </style> 根据后端的修改密码逻辑,把前端修改密码的逻辑改一下

public ArrayList<User> UserList(DBHelper dbHelper){ SQLiteDatabase db = dbHelper.getWritableDatabase(); Cursor cursor = db.query("user",new String[]{"id","username","role"}, null,null,null,null,"id desc"); ArrayList<User> list = new ArrayList<>(); if (cursor != null && cursor.getCount() > 0){ while (cursor.moveToNext()){ String id = cursor.getString(cursor.getColumnIndex("id")); String username = cursor.getString(cursor.getColumnIndex("username")); String role = cursor.getString(cursor.getColumnIndex("role")); User user = new User(id,username,role); list.add(user); } } db.close(); return list; } //用户管理详情页 public ArrayList<User> UserDetails(DBHelper dbHelper,String uid){ SQLiteDatabase db = dbHelper.getWritableDatabase(); Cursor cursor = db.query("user",new String[]{"id","username","passlock","passkey","role"}, "id = ?",new String[]{uid + ""},null,null,null); ArrayList<User> list = new ArrayList<>(); if (cursor != null && cursor.getCount() > 0){ while (cursor.moveToNext()){ String id = cursor.getString(cursor.getColumnIndex("id")); String username = cursor.getString(cursor.getColumnIndex("username")); String passlock = cursor.getString(cursor.getColumnIndex("passlock")); String passkey = cursor.getString(cursor.getColumnIndex("passkey")); String role = cursor.getString(cursor.getColumnIndex("role")); User user = new User(id,username,passlock,passkey,role); list.add(user); } } db.close(); return list; } //修改用户密码 public boolean UpdatePassword(DBHelper dbHelper,String new_password,String uid){ SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("password",new_password); int flag = db.update("user",values,"id=?",new String[]{uid}); boolean result; if (flag == -1){ result = false;解释每一行代码

<template> <el-menu class="site-navbar__menu" mode="horizontal" style="height:38px;"> <el-menu-item v-if="sidebarIsShow" class="site-navbar__switch" id="myzhedie" index="0" @click="sidebarFold = !sidebarFold" style="width:64px;"> <icon-svg name="zhedie" style="color: #fff;"></icon-svg> </el-menu-item> <el-menu-item v-else class="site-navbar__switch" index="0" id="myhome1" style="width:64px;"> <icon-svg name="home" style="color: #fff;"></icon-svg> </el-menu-item> <el-menu-item class="site-navbar__switch" index="0" style="padding:0 0px;background-color:transparent;color:inherit;margin-left:-10px"> </el-menu-item> </el-menu> <el-menu id="myNavbar" :default-active="activeMenu" @select="handleSelect" class="site-navbar__menu" mode="horizontal" style="margin-left:21px;" default-active="home" background-color="transparent" text-color="#e6f7ff" active-text-color="#ffffff"> <el-menu-item v-if="isAuth('battery:bmsbatteryinfo:monitornavbar')" style="margin-left:-1%;font-size: 15px;font-weight: 500;" index="home" @click="openHomeHandle"> <icon-svg name="chezidingyi" class="site-sidebar__menu-icon" style="color: #e6f7ff;"></icon-svg> 实时查询 </el-menu-item> <el-menu-item v-if="isAuth('battery:bmsbatteryinfo:traditionnavbar')" style="margin-left:-1%;font-size: 15px;font-weight: 500;" index="tradition" @click="openSideMenusHandle('31,118,150,153,214,1,46,32,67,-100')"> <icon-svg name="system" class="site-sidebar__menu-icon" style="color: #e6f7ff;"></icon-svg> 数据管理中心 </el-menu-item> <el-menu-item v-if="isAuth('battery:bmsbatteryinfo:reportnavbar')" style="margin-left:-1%;font-size: 15px;font-weight: 500;" index="report" @click="openSideMenusHandle('445,453,458,459,462,-2')"> <icon-svg name="tubiao" class="site-sidebar__menu-icon" style="color: #e6f7ff;"></icon-svg> 统计分析 </el-menu-item> <el-menu-item v-if="isAuth('battery:bmsbatteryinfo:statisticsnavbar')" style="margin-left:-1%;font-size: 15px;font-weight: 500;" index="statistics" @click="openSideMenusHandle('465,470,471,475,-1')"> <icon-svg name="shouye" class="site-sidebar__menu-icon" style="color: #e6f7ff;"></icon-svg> 安全中心 </el-menu-item> <el-menu-item v-if="isAuth('battery:bmsbatteryinfo:managenavbar')" style="margin-left:-1%;font-size: 15px;font-weight: 500;" index="manage" @click="openSideMenusHandle('405,384,1,-3')"> <icon-svg name="config" class="site-sidebar__menu-icon" style="color: #e6f7ff;"></icon-svg> 管理中心 </el-menu-item> <el-submenu id="myWindow" v-if="isAuth('battery:bmsbatteryinfo:largescreennavbar')" style="margin-left:-1%;font-size: 15px;font-weight: 500;" index="largescreen"> <template slot="title" style="margin-left:-1%;"> <icon-svg name="dashujukeshihua" class="site-sidebar__menu-icon" style="color:rgb(21, 162, 227);"></icon-svg> 驾驶舱 </template> <el-menu-item index="2-1" @click="openEchartInNewWindow" v-if="isAuth('mqtt:mtbatteryinfolastest:largedep')"> <icon-svg name="dashujukeshihua" class="site-sidebar__menu-icon" style="color: #1a2b5f;"></icon-svg> 欣动电池大屏 </el-menu-item> </el-submenu> </el-menu> <el-menu class="site-navbar__menu site-navbar__menu--right" mode="horizontal" background-color="transparent" text-color="#e6f7ff" active-text-color="#ffffff"> <el-menu-item index="1" id="mydaping" @click="openEchartInNewWindow" v-if="isAuth('mqtt:mtbatteryinfolastest:largeDatalist')"> <template slot="title"> <el-badge value="大屏" type="primary"> <icon-svg name="dashujukeshihua" class="el-icon-rank" style="color: #e6f7ff;"></icon-svg> </el-badge> </template> </el-menu-item> <el-menu-item index="2" id="myshezhi" @click="$router.push({ name: 'theme' })"> <template slot="title"> <el-badge value="设置" type="primary"> <icon-svg name="shezhi" class="el-icon-setting" style="color: #e6f7ff;"></icon-svg> </el-badge> </template> </el-menu-item> <el-menu-item class="site-navbar__avatar" index="3" id="myhuichu"> <el-dropdown :show-timeout="0" placement="bottom"> {{ userName }} <el-dropdown-menu slot="dropdown" style="background-color: #1a2b5f; border: 1px solid #4a9eff;"> <el-dropdown-item @click.native="updatePasswordHandle()" style="color: #e6f7ff;">修改密码</el-dropdown-item> <el-dropdown-item @click.native="logoutHandle()" style="color: #e6f7ff;">退出</el-dropdown-item> </el-dropdown-menu> </el-dropdown> </el-menu-item> </el-menu> <update-password v-if="updatePassowrdVisible" ref="updatePassowrd"></update-password> </template> <script> import UpdatePassword from './main-navbar-update-password' import { clearLoginInfo,EventBus } from '@/utils' import Router from 'vue-router' import http from '@/utils/httpRequest' import { isURL } from '@/utils/validate' export default { data () { return { firstLogin: true, updatePassowrdVisible: false, activeMenu: 'tradition' // 默认激活的菜单项ID } }, components: { UpdatePassword }, computed: { navbarLayoutType: { get () { return this.$store.state.common.navbarLayoutType } }, sidebarFold: { get () { return this.$store.state.common.sidebarFold }, set (val) { this.$store.commit('common/updateSidebarFold', val) } }, mainTabs: { get () { return this.$store.state.common.mainTabs }, set (val) { this.$store.commit('common/updateMainTabs', val) } }, menuActiveName: { get () { return this.$store.state.common.menuActiveName }, set (val) { this.$store.commit('common/updateMenuActiveName', val) } }, userName: { get () { return this.$store.state.user.name } }, isHomePage(){ return this.$route.path === '/home' }, // 左侧菜单显示 sidebarIsShow: { get () { return this.$store.state.common.sidebarIsShow }, set (val) { this.$store.commit('common/updateSidebarIsShow', val) } }, }, created() { // 刚登录进来,多点击监控中心,防止左侧缓存的菜单出现 if(localStorage.getItem('firstLogin')===null){ localStorage.clear(); localStorage.setItem('firstLogin', '1'); this.firstLogin = false; // 显示左侧菜单隐藏 this.openHomeHandle () setTimeout(() => { this.openHomeHandle (); }, 1); setTimeout(() => { this.openHomeHandle (); }, 100); }else{ } this.openHomeHandle () setTimeout(() => { this.openHomeHandle (); }, 10); setTimeout(() => { this.openHomeHandle (); }, 100); setTimeout(() => { this.openHomeHandle (); }, 120); setTimeout(() => { this.openHomeHandle (); }, 180); // 页面加载时尝试恢复之前的选中状态。刷新时一直保持点击颜色 this.activeMenu = sessionStorage.getItem('activeMenu') || this.activeMenu; }, methods: { handleSelect(key, keyPath) { // 菜单项被点击时保存选中状态 sessionStorage.setItem('activeMenu', key); }, openEchartInNewWindow() { const routeData = this.$router.resolve({ name: 'echart' }); window.open(routeData.href, '_blank'); }, // 修改密码 updatePasswordHandle () { this.updatePassowrdVisible = true this.$nextTick(() => { this.$refs.updatePassowrd.init() }) }, // 退出 logoutHandle () { this.$confirm(确定进行[退出]操作?, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.$http({ url: this.$http.adornUrl('/sys/logout'), method: 'post', data: this.$http.adornData() }).then(({data}) => { if (data && data.code === 0) { clearLoginInfo() this.$router.push({ name: 'login' }) } }) }).catch(() => {}) }, openSideMenusHandle (parentMenuIds) { this.mainTabs = [] //清除打开的tab菜单 this.menuActiveName = '' // 左侧菜单显示 this.$store.state.common.sidebarIsShow = true // 折叠打开 this.$store.state.common.sidebarFold = false // 这里调用左侧菜单的方法 EventBus.$emit('callMethod',parentMenuIds); // 再次调用,防止点击监控中心--然后跳转到其他菜单时无反应 setTimeout(() => { EventBus.$emit('callMethod',parentMenuIds); }, 150); setTimeout(() => { EventBus.$emit('callMethod',parentMenuIds); }, 100); setTimeout(() => { EventBus.$emit('callMethod',parentMenuIds); }, 220); setTimeout(() => { EventBus.$emit('callMethod',parentMenuIds); }, 120); }, openHomeHandle () { this.$store.state.common.sidebarFold = true // 左侧菜单显示关闭 this.$store.state.common.sidebarIsShow = false this.$router.push({ name: 'home' }) }, //关闭全部tab tabsCloseAllHandle () { this.mainTabs = [] this.menuActiveName = '' this.$router.push({ name: 'home' }) }, reloadMenus(parentMenuIds){ this.$http({ url: this.$http.adornUrl('/sys/menu/navappoint'), method: 'get', params: this.$http.adornParams({ 'parentMenuIds': parentMenuIds }) }).then(({data}) => { if (data && data.code === 0) { this.fnAddDynamicMenuRoutes(data.menuList) this.$router.options.isAddDynamicMenuRoutes = true sessionStorage.setItem('menuList', JSON.stringify(data.menuList || '[]')) sessionStorage.setItem('permissions', JSON.stringify(data.permissions || '[]')) EventBus.$emit('callMethod',parentMenuIds); this.tabsCloseAllHandle (); // 折叠打开 this.$store.state.common.sidebarFold = false this.$router.push({ name: 'home' }) } else { sessionStorage.setItem('menuList', '[]') sessionStorage.setItem('permissions', '[]') // 折叠缩进 this.$store.state.common.sidebarFold = true next() } }).catch((e) => { console.log(%c${e} 请求菜单列表和权限失败,跳转至登录页!!, 'color:blue') }) }, /** * 添加动态(菜单)路由 * @param {*} menuList 菜单列表 * @param {*} routes 递归创建的动态(菜单)路由 */ fnAddDynamicMenuRoutes (menuList = [], routes = []) { var temp = [] for (var i = 0; i < menuList.length; i++) { if (menuList[i].list && menuList[i].list.length >= 1) { temp = temp.concat(menuList[i].list) } else if (menuList[i].url && /\S/.test(menuList[i].url)) { menuList[i].url = menuList[i].url.replace(/^\//, '') var route = { path: menuList[i].url.replace('/', '-'), component: null, name: menuList[i].url.replace('/', '-'), meta: { menuId: menuList[i].menuId, title: menuList[i].name, isDynamic: true, isTab: true, iframeUrl: '' } } if (isURL(menuList[i].url)) { route['path'] = i-${menuList[i].menuId} route['name'] = i-${menuList[i].menuId} route['meta']['iframeUrl'] = menuList[i].url } else { try { route['component'] = _import(modules/${menuList[i].url}) || null } catch (e) {} } routes.push(route) } } if (temp.length >= 1) { this.fnAddDynamicMenuRoutes(temp, routes) } else { var mainRoutes = { name: 'main-dynamic', children: routes, path: '/' } this.$router.addRoutes([ mainRoutes, { path: '*', redirect: { name: '404' } } ]) sessionStorage.setItem('dynamicMenuRoutes', JSON.stringify(mainRoutes.children || '[]')) console.log('\n') console.log('%c!<-------------------- 动态(菜单)路由 s -------------------->', 'color:blue') console.log(mainRoutes.children) console.log('%c!<-------------------- 动态(菜单)路由 e -------------------->', 'color:blue') } }, /** * 添加动态(菜单)路由 * @param {*} menuList 菜单列表 * @param {*} routes 递归创建的动态(菜单)路由 */ fnAddDynamicMenuRoutes2 (menuList) { var routes = [] var temp = [] for (var i = 0; i < menuList.length; i++) { if (menuList[i].list && menuList[i].list.length >= 1) { temp = temp.concat(menuList[i].list) } else if (menuList[i].url && /\S/.test(menuList[i].url)) { menuList[i].url = menuList[i].url.replace(/^\//, '') var route = { path: menuList[i].url.replace('/', '-'), component: null, name: menuList[i].url.replace('/', '-'), meta: { menuId: menuList[i].menuId, title: menuList[i].name, isDynamic: true, isTab: true, iframeUrl: '' } } if (isURL(menuList[i].url)) { route['path'] = i-${menuList[i].menuId} route['name'] = i-${menuList[i].menuId} route['meta']['iframeUrl'] = menuList[i].url } else { try { route['component'] = _import(modules/${menuList[i].url}) || null } catch (e) {} } routes.push(route) } } if (temp.length >= 1) { this.fnAddDynamicMenuRoutes(temp, routes) } else { var mainRoutes = { name: 'main-dynamic', children: routes, path: '/' } this.$router.addRoutes([ mainRoutes, { path: '*', redirect: { name: '404' } } ]) sessionStorage.setItem('dynamicMenuRoutes', JSON.stringify(mainRoutes.children || '[]')) console.log('\n') console.log('%c!<-------------------- 动态(菜单)路由 s -------------------->', 'color:blue') console.log(mainRoutes.children) console.log('%c!<-------------------- 动态(菜单)路由 e -------------------->', 'color:blue') } } } } </script> <style scoped> /* 全局导航栏样式 */ .site-navbar { font-family: 'Microsoft YaHei', Arial, sans-serif; } /* 菜单项悬停效果 */ #myNavbar .el-menu-item:hover { background-color: rgba(42, 139, 242, 0.3) !important; color: #fff !important; } /* 顶部菜单点击后的背景颜色 */ #myNavbar .el-menu-item.is-active { background: linear-gradient(90deg, #2a8bf2 0%, #1e62c7 100%) !important; color: #fff !important; border-bottom: 2px solid #4affff; box-shadow: 0 2px 8px rgba(0, 120, 255, 0.3); } /* 驾驶舱菜单样式 */ #myWindow .el-submenu__title { color: #e6f7ff !important; font-weight: 500; } #myWindow .el-submenu__title:hover { background-color: rgba(42, 139, 242, 0.3) !important; } /* 右侧菜单项样式 */ .site-navbar__menu--right .el-menu-item { height: 38px !important; line-height: 38px !important; } .site-navbar__menu--right .el-menu-item:hover { background-color: rgba(42, 139, 242, 0.3) !important; } /* 用户头像区域 */ .site-navbar__avatar { padding: 0 10px !important; } .site-navbar__avatar:hover { background-color: rgba(42, 139, 242, 0.3) !important; } /* 下拉菜单样式 */ .el-dropdown-menu__item { font-size: 14px; padding: 8px 20px; } .el-dropdown-menu__item:hover { background-color: #2a8bf2 !important; color: #fff !important; } /* 折叠按钮样式 */ #myzhedie:hover, #myhome1:hover { background-color: rgba(42, 139, 242, 0.3) !important; } </style>驾驶舱子菜单字体看不清,改哪里

import { IBestNavBar } from "@ibestservices/ibest-ui-v2"; import { IBestField } from "@ibestservices/ibest-ui-v2"; import { IBestButton } from "@ibestservices/ibest-ui-v2"; import { IBestToast } from "@ibestservices/ibest-ui-v2"; @Entry @ComponentV2 export struct Xguser { router=this.getUIContext().getRouter() @Local value: string = '' @Local count: number = 60 @Local timer: number = 0 @Builder sendCodeButton() { IBestButton({ text: this.count == 60 ? '发送验证码' : 重新发送(${this.count}), type: 'primary', buttonSize: 'mini', onBtnClick: () => { this.sendCode() IBestToast.show("随机四位数") } }) } sendCode() { if (this.timer) { return } this.count = 60 this.timer = setInterval(() => { if (this.count > 0) { this.count-- } else { clearInterval(this.timer) this.timer = 0 this.count = 60 } }, 1000) } @Local value1: string = "" @Builder leftBuilder(){ Row({space: 14}){ Image($rawfile("img/back.png")) .width(16) } } @Builder rightBuilder() { Row({ space: 14 }) { Image($rawfile('img/search.png')) .width(16) } } build() { Column() { IBestNavBar({ onLeftClick:()=>{ this.router.back() }, title: "修改密码", titleFontSize:30, titleColor: "#fff", navBarBgColor: "#458DF6", leftBuilder: (): void => this.leftBuilder(), isShowRight: true, rightBuilder: (): void => this.rightBuilder() }) Column(){ IBestField({ leftIcon:$rawfile('img/密码.png'), value: this.value1!!, placeholder: "请输入旧密码", type: "password" }) IBestField({ leftIcon:$rawfile('img/密码.png'), value: this.value1!!, placeholder: "请输入新密码", type: "password" }) IBestField({ leftIcon:$rawfile('img/密码.png'), value: this.value1!!, placeholder: "请确认新密码", type: "password" }) } IBestField({ value: this.value!!, leftIcon:$rawfile('img/code.png'), placeholder: "请输入验证码", hasBorder: false, buttonBuilder: (): void => this.sendCodeButton() }) Button('修改密码') .width('100%') .margin({top:20}) .onClick(()=>{ }) } .width('100%') .height('100%') .backgroundColor('#f5f5f5') } }http://whhpweb.cn:3011/user/updatePassword 连接后台接口 oldPassword和 newPassword是参数

最新推荐

recommend-type

2022年网站美工个人年度工作总结(1).doc

2022年网站美工个人年度工作总结(1).doc
recommend-type

财务软件销售实习报告格式范文-实习报告格式(1).doc

财务软件销售实习报告格式范文-实习报告格式(1).doc
recommend-type

【航迹关联】基于标准 Hough 变换、修正 Hough 变换和序列 Hough 变换实现航迹起始算法研究Matlab代码.rar

【航迹关联】基于标准 Hough 变换、修正 Hough 变换和序列 Hough 变换实现航迹起始算法研究Matlab代码
recommend-type

Windows系统修复工具

Windows 系统修复工具主要用于解决 Windows 11/10 系统中的各种常见问题,具有操作简单、功能全面等特点: 文件资源管理器修复:可解决文件资源管理器卡死、崩溃、无响应等问题,能终止崩溃循环。还可修复右键菜单无响应或选项缺失问题,以及重建缩略图缓存,让图片、视频等文件的缩略图正常显示,此外,还能处理桌面缺少回收站图标、回收站损坏等问题。 互联网和连接修复:能够刷新 DNS 缓存,加速网页加载速度,减少访问延迟。可重置 TCP/IP 协议栈,增强网络连接稳定性,减少网络掉线情况,还能还原 Hosts 文件,清除恶意程序对网络设置的篡改,保障网络安全,解决电脑重装系统后网络无法连接、浏览器主页被篡改等问题。 系统修复:集成系统文件检查器(SFC),可自动扫描并修复受损的系统文件。能解决 Windows 激活状态异常的问题,还可重建 DLL 注册库,恢复应用程序兼容性,解决部分软件无法正常运行的问题,同时也能处理如 Windows 沙箱无法启动、Windows 将 JPG 或 JPEG 保存为 JFIF 等系统问题。 系统工具维护:提供启动管理器、服务管理器和进程管理器等工具,用户可控制和管理启动程序、系统服务和当前运行的进程,提高系统的启动和运行速度,防止不必要的程序和服务占用系统资源。还能查看系统规格,如处理器线程数、最大显示分辨率等。 故障排除:集成超过 20 个微软官方诊断工具,可对系统问题进行专业排查,还能生成硬件健康状态报告。能解决搜索和索引故障、邮件和日历应用程序崩溃、设置应用程序无法启动等问题,也可处理打印机、网络适配器、Windows 更新等相关故障。 其他修复功能:可以重置组策略设置、catroot2 文件夹、记事本等多种系统设置和组件,如重置 Windows 应用商店缓存、Windows 防火墙设置等。还能添加重建图标缓存支持,恢复粘滞便笺删除
recommend-type

获取本机IP地址的程序源码分析

从给定文件信息中我们可以提取出的关键知识点是“取本机IP”的实现方法以及与之相关的编程技术和源代码。在当今的信息技术领域中,获取本机IP地址是一项基本技能,广泛应用于网络通信类的软件开发中,下面将详细介绍这一知识点。 首先,获取本机IP地址通常需要依赖于编程语言和操作系统的API。不同的操作系统提供了不同的方法来获取IP地址。在Windows操作系统中,可以通过调用Windows API中的GetAdaptersInfo()或GetAdaptersAddresses()函数来获取网络适配器信息,进而得到IP地址。在类Unix操作系统中,可以通过读取/proc/net或是使用系统命令ifconfig、ip等来获取网络接口信息。 在程序设计过程中,获取本机IP地址的源程序通常会用到网络编程的知识,比如套接字编程(Socket Programming)。网络编程允许程序之间进行通信,套接字则是在网络通信过程中用于发送和接收数据的接口。在许多高级语言中,如Python、Java、C#等,都提供了内置的网络库和类来简化网络编程的工作。 在网络通信类中,IP地址是区分不同网络节点的重要标识,它是由IP协议规定的,用于在网络中唯一标识一个网络接口。IP地址可以是IPv4,也可以是较新的IPv6。IPv4地址由32位二进制数表示,通常分为四部分,每部分由8位构成,并以点分隔,如192.168.1.1。IPv6地址则由128位二进制数表示,其表示方法与IPv4有所不同,以冒号分隔的8组16进制数表示,如2001:0db8:85a3:0000:0000:8a2e:0370:7334。 当编写源代码以获取本机IP地址时,通常涉及到以下几个步骤: 1. 选择合适的编程语言和相关库。 2. 根据目标操作系统的API或系统命令获取网络接口信息。 3. 分析网络接口信息,提取出IP地址。 4. 将提取的IP地址转换成适合程序内部使用的格式。 5. 在程序中提供相应功能,如显示IP地址或用于网络通信。 例如,在Python中,可以使用内置的socket库来获取本机IP地址。一个简单的示例代码如下: ```python import socket # 获取主机名 hostname = socket.gethostname() # 获取本机IP local_ip = socket.gethostbyname(hostname) print("本机IP地址是:", local_ip) ``` 在实际应用中,获取本机IP地址通常是为了实现网络通信功能,例如建立客户端与服务器的连接,或者是在开发涉及到IP地址的其他功能时使用。 关于文件名称“getIP”,这是一个自解释的文件名,明显表示该文件或程序的作用是获取本机的IP地址。从标签“控件 源码 网络通信类 资源”中我们可以看出,这个文件很可能是一个可以嵌入其他软件中的代码片段,用以实现网络通信功能的一部分,具有较高的灵活性和重用性。 综上所述,获取本机IP地址是一个涉及到操作系统API、网络编程以及特定编程语言知识的技能。它不仅需要对编程语言提供的库函数有深入的理解,还要对操作系统的网络配置和IP协议有足够的认识。通过阅读和分析相关的源代码,如“getIP”,可以加深对网络编程实现细节的理解,并能够在实际开发中快速地应用这一技术。
recommend-type

【权威指南】:Win11笔记本上RTX4080驱动的安装与调试秘籍

# 1. Win11笔记本与RTX4080显卡介绍 随着技术的不断发展,笔记本电脑已不再是仅仅满足办公需求的移动设备,而是逐渐成为可以胜任复杂图形处理和游戏任务的强大工具。微软推出的Windows 11操作系统,以其全新的用户界面和改进的系统性能,为用户提供了更为流畅的操作体验。而在硬件方面,NVIDIA的RTX 4080显卡以其卓越的图形处理能力和AI支持,为笔记本电脑带来了前所未有的性能提升。本章节将带您初步了解Windows 11笔记本与NVIDIA RTX 4080显卡的基础信息,为进一步深入探讨它们的优化和调试技巧奠定基础。 ## 1.1 Win11笔记本的优势 Windows
recommend-type

windows环境举例

<think>好的,用户现在想在Windows环境下创建C函数库,需要具体的方法和示例代码。我需要结合之前的回答和用户提供的引用内容来给出合适的指导。 首先回顾之前的回答,用户已经了解了在Linux下创建静态库和动态库的方法,现在需要切换到Windows环境。根据引用[2],Windows下的C标准库和动态链接库的处理与Linux不同,比如使用dlfcn.h在Linux,而Windows可能需要其他方式。另外,引用[1]提到了在Windows下配置gcc环境(MinGW-w64),这可能是一个关键点,因为用户可能需要使用MinGW来编译库。 用户提供的引用[3]提到了使用MSVC编译器,这
recommend-type

QQ自动发送/回复系统源代码开放

根据提供的文件信息,我们可以了解到以下几点关键的知识点: ### 标题:“qqhelp” 1. **项目类型**: 标题“qqhelp”暗示这是一个与QQ相关的帮助工具或项目。QQ是中国流行的即时通讯软件,因此这个标题表明项目可能提供了对QQ客户端功能的辅助或扩展。 2. **用途**: “help”表明此项目的主要目的是提供帮助或解决问题。由于它提到了QQ,并且涉及“autosend/reply”功能,我们可以推测该项目可能用于自动化发送消息回复,或提供某种形式的自动回复机制。 ### 描述:“I put it to my web, but nobody sendmessage to got the source, now I public it. it supply qq,ticq autosend/reply ,full sourcecode use it as you like” 1. **发布情况**: 描述提到该项目原先被放置在某人的网站上,并且没有收到请求源代码的消息。这可能意味着项目不够知名或者需求不高。现在作者决定公开发布,这可能是因为希望项目能够被更多人了解和使用,或是出于开源共享的精神。 2. **功能特性**: 提到的“autosend/reply”表明该项目能够实现自动发送和回复消息。这种功能对于需要进行批量或定时消息沟通的应用场景非常有用,例如客户服务、自动化的营销通知等。 3. **代码可用性**: 作者指出提供了“full sourcecode”,意味着源代码完全开放,用户可以自由使用,无论是查看、学习还是修改,用户都有很大的灵活性。这对于希望学习编程或者有特定需求的开发者来说是一个很大的优势。 ### 标签:“综合系统类” 1. **项目分类**: 标签“综合系统类”表明这个项目可能是一个多功能的集成系统,它可能不仅限于QQ相关的功能,还可能包含了其他类型的综合服务或特性。 2. **技术范畴**: 这个标签可能表明该项目的技术实现比较全面,可能涉及到了多个技术栈或者系统集成的知识点,例如消息处理、网络编程、自动化处理等。 ### 压缩包子文件的文件名称列表: 1. **Unit1.dfm**: 这是一个Delphi或Object Pascal语言的窗体定义文件,用于定义应用程序中的用户界面布局。DFM文件通常用于存储组件的属性和位置信息,使得开发者可以快速地进行用户界面的设计和调整。 2. **qqhelp.dpr**: DPR是Delphi项目文件的扩展名,包含了Delphi项目的核心设置,如程序入口、使用的单元(Units)等。这个文件是编译和构建Delphi项目的起点,它能够帮助开发者了解项目的组织结构和编译指令。 3. **Unit1.pas**: PAS是Delphi或Object Pascal语言的源代码文件。这个文件可能包含了与QQ帮助工具相关的核心逻辑代码,例如处理自动发送和回复消息的算法等。 4. **readme.txt**: 这是一个常见的文本文件,包含项目的基本说明和使用指导,帮助用户了解如何获取、安装、运行和定制该项目。README文件通常是用户与项目首次交互时首先阅读的文件,因此它对于一个开源项目的用户友好度有着重要影响。 通过以上分析,我们可以看出“qqhelp”项目是一个针对QQ通讯工具的自动化消息发送与回复的辅助工具。项目包含完整的源代码,用户可以根据自己的需要进行查看、修改和使用。它可能包含Delphi语言编写的窗体界面和后端逻辑代码,具有一定的综合系统特性。项目作者出于某种原因将其开源,希望能够得到更广泛的使用和反馈。
recommend-type

【7步打造Win11深度学习利器】:Tensorflow-GPU与RTX4080终极优化指南

# 1. 深度学习与Windows 11的融合 在人工智能时代,深度学习已渗透到生活的方方面面,而Windows 11作为最新一代的操作系统,为深度学习提供了一个高效的工作平台。本章节将探讨深度学习技术如何与Windows 11系统融合,以及这一
recommend-type

ue画笔画画蓝图版

<think>我们正在讨论的是在UnrealEngine中使用蓝图实现画笔绘画功能。根据用户需求,重点在于通过蓝图系统实现类似毛笔的绘画效果。结合之前的回答和引用内容,我们将详细展开实现方法。核心思路:通过捕捉输入轨迹,动态生成笔触网格,并应用材质模拟墨迹效果。###详细实现步骤####1.创建绘画蓝图创建一个名为`BP_PaintBrush`的Actor蓝图:-**根组件**:SceneComponent-**关键组件**:-`SplineComponent`:用于存储绘画路径点-`InstancedStaticMeshComponent`:高效渲染重复笔触段(替代单个SplineMesh组