数据库相关

This commit is contained in:
李玉东 2025-09-24 09:20:18 +08:00
parent 881c556f6a
commit e9ac9d5f99
10 changed files with 392 additions and 181 deletions

View File

@ -17,13 +17,17 @@
<properties> <properties>
<!-- 指定编译使用的 Java 版本 --> <!-- 指定编译使用的 Java 版本 -->
<maven.compiler.source>11</maven.compiler.source> <maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target> <maven.compiler.target>8</maven.compiler.target>
<!-- 可选:指定编译编码 --> <!-- 可选:指定编译编码 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId> <artifactId>spring-boot-dependencies</artifactId>

View File

@ -44,7 +44,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() http.authorizeRequests()
.antMatchers("/login", "/css/**", "/js/**", "/img/**", "/libs/**", "/captcha", "/toAuth", .antMatchers("/login", "/css/**", "/js/**", "/img/**", "/libs/**", "/captcha", "/toAuth","/redirect",
"/ws", "/swagger-ui.html", "/ws", "/swagger-ui.html",
"/swagger-ui/**", "/swagger-ui/**",
"/v3/api-docs", "/v3/api-docs",

View File

@ -1,76 +1,246 @@
package com.hshh.nation.login.controller; package com.hshh.nation.login.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hshh.nation.advice.GlobalExceptionHandler;
import com.hshh.nation.common.BaseController; import com.hshh.nation.common.BaseController;
import com.hshh.nation.common.OperateResult; import com.hshh.nation.common.OperateResult;
import com.hshh.nation.advice.GlobalExceptionHandler;
import com.hshh.nation.login.model.ExtendUserDetails; import com.hshh.nation.login.model.ExtendUserDetails;
import com.hshh.nation.set.service.ConfigService; import com.hshh.nation.set.service.ConfigService;
import com.hshh.nation.user.entity.User;
import com.hshh.nation.user.service.UserService;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
import java.util.Random;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository; import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import javax.annotation.Resource; import org.springframework.web.bind.annotation.RequestBody;
import javax.servlet.http.HttpServletRequest; import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Map; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.reactive.function.client.WebClient;
@Controller @Controller
@Slf4j @Slf4j
public class LoginController extends BaseController { public class LoginController extends BaseController {
@Resource @Resource
private ConfigService configService;//全局配置service private ConfigService configService;//全局配置service
private final WebClient webClient = WebClient.create();
@Autowired
private AuthenticationManager authenticationManager;
@Autowired @Value("${third.auth.client_id}")
private AuthenticationManager authenticationManager; private String clientId;
@Value("${third.auth.client_secret}")
private String clientSecret;
//导向到登录页面 @Value("${third.auth.token-url}")
@RequestMapping("/login") private String tokenUrl;
public String loginPage(Model model) { @Value("${third.auth.userinfo-url}")
Map<String, String> setMap = configService.getMapAllSet(); private String getUserUrl;
String systemTitle = setMap.get("system.title"); @Resource
model.addAttribute("systemTitle", systemTitle); private UserService userService;
return "login"; @Value("${third.auth.jump_url}")
private String jumpUrl;
@Value("${third.auth.redirect_url}")
private String redirectUrl;
@Value("${third.auth.logout_url}")
private String logoutUrl;
//导向到登录页面
@RequestMapping("/login")
public String loginPage(Model model) {
Random random = new Random();
Map<String, String> setMap = configService.getMapAllSet();
String url = jumpUrl + "?response_type=code&client_id=" + clientId + "&redirect_uri="
+ Base64.getUrlEncoder().encodeToString(redirectUrl.getBytes(StandardCharsets.UTF_8))
+ "&active_type=user&state=" + random.nextDouble();
log.info("jumpUrl::{}", url);
String systemTitle = setMap.get("system.title");
model.addAttribute("systemTitle", systemTitle);
model.addAttribute("jumpUrl", url);
return "login";
}
@GetMapping("/redirect")
public String redirect(String code, HttpServletRequest request) {
//获取token
String token = token(code);
LoginForm loginForm = getThirdUserAndSaveUserIfNotExit(token);
log.info("loginForm::{}", JSON.toJSONString(loginForm));
if (loginForm != null) {
authLoginForm(loginForm, request);
} }
request.getSession().setAttribute("token", token);
return "redirect:/home";
}
//登录 @GetMapping("/out")
@PostMapping("/toAuth") public String logout(HttpServletRequest request) {
@ResponseBody log.info("logout.....");
public OperateResult<String> login(@RequestBody LoginForm loginForm, HttpServletRequest request) { String token = request.getSession().getAttribute("token") == null ? ""
try { : request.getSession().getAttribute("token").toString();
log.info("username={}", loginForm.getUsername()); if (StringUtils.isNotBlank(token)) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loginForm.getUsername(), loginForm.getPassword()); //回收token
authenticationManager.authenticate(token); String url =
Authentication authentication = authenticationManager.authenticate(token); logoutUrl + "?client_id=" + clientId + "&client_secret=" + clientSecret + "&access_token="
SecurityContextHolder.getContext().setAuthentication(authentication); + token;
request.getSession().setAttribute("user", authentication.getPrincipal());
request.getSession(true).setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
} catch (Exception e) {
log.error(e.getMessage());
return OperateResult.error(null, e.getMessage(), GlobalExceptionHandler.SERVER_ERROR_CODE);
String result = webClient.get()
.uri(url)
.retrieve()
.bodyToMono(String.class)
.block();
log.info("result::{}", result);
if (result != null) {
JSONObject jsonObject = JSON.parseObject(result);
if (jsonObject.containsKey("code")) {
if (jsonObject.getInteger("code") == 200) {
}
} }
return OperateResult.success(); }
} }
@GetMapping("/home") request.getSession().removeAttribute("token");
public String home(Model model) { request.getSession().invalidate();
log.info("home"); return "redirect:/login";
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); }
ExtendUserDetails user = (ExtendUserDetails) authentication.getPrincipal();
model.addAttribute("currentUser", user); //登录
return "fragments/layout"; @PostMapping("/toAuth")
@ResponseBody
public OperateResult<String> login(@RequestBody LoginForm loginForm, HttpServletRequest request) {
try {
log.info("username={}", loginForm.getUsername());
authLoginForm(loginForm, request);
} catch (Exception e) {
log.error(e.getMessage());
return OperateResult.error(null, e.getMessage(), GlobalExceptionHandler.SERVER_ERROR_CODE);
} }
@Data return OperateResult.success();
private static class LoginForm{ }
String username;
String password; private void authLoginForm(LoginForm loginForm, HttpServletRequest request) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
loginForm.getUsername(), loginForm.getPassword());
authenticationManager.authenticate(token);
Authentication authentication = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
request.getSession().setAttribute("user", authentication.getPrincipal());
request.getSession(true)
.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
SecurityContextHolder.getContext());
}
@GetMapping("/home")
public String home(Model model) {
log.info("home");
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
ExtendUserDetails user = (ExtendUserDetails) authentication.getPrincipal();
model.addAttribute("currentUser", user);
return "fragments/layout";
}
@Data
public static class LoginForm {
String username;
String password;
}
private String token(String code) {
try {
String url = tokenUrl + "?client_id=" + clientId + "&client_secret=" + clientSecret
+ "&grant_type=authorization_code&code=" + code;
log.info("tokenUrl: {}", url);
String result = webClient.get()
.uri(url)
.retrieve()
.bodyToMono(String.class)
.block();
log.info("token: {}", result);
JSONObject resultObject = JSON.parseObject(result);
if (resultObject != null && resultObject.containsKey("code")) {
if (resultObject.getInteger("code") == 200) {
return resultObject.getJSONObject("data").getString("access_token");
}
return resultObject.getString("access_token");
}
} catch (Exception e) {
log.error(e.getMessage(), e);
} }
return null;
}
public LoginForm getThirdUserAndSaveUserIfNotExit(String token) {
String userUrl = getUserUrl + "?access_token=" + token;
log.info("getUserUrl: {}", userUrl);
try {
String result = webClient.get()
.uri(userUrl)
.retrieve()
.bodyToMono(String.class)
.block();
log.info("getUserUrl result: {}", result);
JSONObject resultObject = JSON.parseObject(result);
if (resultObject != null && resultObject.containsKey("code")) {
if (resultObject.getInteger("code") == 200) {
User user = getUser(resultObject.getJSONObject("data"));
User userInDb = userService.getUserByUserId(user.getUserId());
if (userInDb == null) {
//插入到数据库
User newUser = new User();
newUser.setUserId(user.getUserId());
newUser.setUserName(user.getUserName());
newUser.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
newUser.setNickName(user.getNickName());
newUser.setSuperFlag(1);
userService.save(newUser);
}
LoginForm loginForm = new LoginForm();
loginForm.setUsername(user.getUserName());
loginForm.setPassword(user.getPassword());
return loginForm;
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return null;
}
private User getUser(JSONObject userObject) {
User user = new User();
user.setUserId(userObject.getString("userId"));
user.setUserName(userObject.getString("userName"));
user.setNickName(userObject.getString("nickName"));
user.setPassword(userObject.getString("password"));
return user;
}
} }

View File

@ -1,6 +1,7 @@
package com.hshh.nation.login.model; package com.hshh.nation.login.model;
import com.hshh.nation.menu.entity.Menu; import com.hshh.nation.menu.entity.Menu;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import lombok.Data; import lombok.Data;
@ -37,7 +38,7 @@ public class ExtendUserDetails implements UserDetails {
@Override @Override
public Collection<? extends GrantedAuthority> getAuthorities() { public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of(); return new ArrayList<>();
} }
@Override @Override

View File

@ -1,6 +1,7 @@
package com.hshh.nation.user.entity; package com.hshh.nation.user.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable; import java.io.Serializable;
@ -43,4 +44,6 @@ public class User implements Serializable {
* 超级管理员标志. * 超级管理员标志.
*/ */
private int superFlag; private int superFlag;
private String userId;
} }

View File

@ -19,4 +19,5 @@ public interface UserService extends IService<User> {
* @return 用户对象. * @return 用户对象.
*/ */
User getUserByUsername(String username); User getUserByUsername(String username);
User getUserByUserId(String userId);
} }

View File

@ -28,4 +28,15 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
} }
return null; return null;
} }
@Override
public User getUserByUserId(String userId) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id", userId);
List<User> list = this.list(queryWrapper);
if (!list.isEmpty()) {
return list.get(0);
}
return null;
}
} }

View File

@ -17,14 +17,14 @@ spring:
max-wait: -1ms max-wait: -1ms
datasource: datasource:
# mysql # mysql
# url: jdbc:mysql://localhost:3306/nation_defence?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC url: jdbc:mysql://localhost:3306/nation_defence?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
# username: root username: root
# password: 123456 password: 123456
# driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:dm://192.168.0.52:5236 # url: jdbc:dm://127.0.0.1:5236
username: NATION_DEFENCE # username: SYSDBA
password: Lidy1234 # password: SYSDBA001
driver-class-name: dm.jdbc.driver.DmDriver # driver-class-name: dm.jdbc.driver.DmDriver
hikari: hikari:
minimum-idle: 5 minimum-idle: 5
maximum-pool-size: 20 maximum-pool-size: 20
@ -63,4 +63,13 @@ logging:
level: level:
com.baomidou.mybatisplus: warn com.baomidou.mybatisplus: warn
org.apache.ibatis: warn org.apache.ibatis: warn
third:
auth:
client_id: 233
client_secret: 123
token-url: http://32.15.80.150:99/oauth2Server/oauth2/token
userinfo-url: http://32.15.80.150:99/oauth2Server/oauth2/userinfo
jump_url: http://32.15.80.150:99/oauth2Server/oauth2/authorizeV2
redirect_url: http://32.15.191.88:8888/redirect
logout_url: ttp://32.15.80.150:99/oauth2Server/oauth2/logout

View File

@ -10,7 +10,7 @@
</div> </div>
</a> </a>
<div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow"> <div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow">
<a th:href="@{/logout}" class="dropdown-item">退出登录</a> <a th:href="@{/out}" class="dropdown-item">退出登录</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -2,160 +2,172 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"/> <meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"/> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"/>
<meta http-equiv="X-UA-Compatible" content="ie=edge"/> <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
<title>登录</title> <title>登录</title>
<!-- CSS files --> <!-- CSS files -->
<link th:href="@{/css/tabler.min.css?1684106062}" rel="stylesheet"/> <link th:href="@{/css/tabler.min.css?1684106062}" rel="stylesheet"/>
<link th:href="@{/css/tabler-flags.min.css?1684106062}" rel="stylesheet"/> <link th:href="@{/css/tabler-flags.min.css?1684106062}" rel="stylesheet"/>
<link th:href="@{/css/tabler-payments.min.css?1684106062}" rel="stylesheet"/> <link th:href="@{/css/tabler-payments.min.css?1684106062}" rel="stylesheet"/>
<link th:href="@{/css/tabler-vendors.min.css?1684106062}" rel="stylesheet"/> <link th:href="@{/css/tabler-vendors.min.css?1684106062}" rel="stylesheet"/>
<style> <style>
:root { :root {
--tblr-font-sans-serif: 'Inter Var', -apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif; --tblr-font-sans-serif: 'Inter Var', -apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif;
} }
body { body {
font-feature-settings: "cv03", "cv04", "cv11"; font-feature-settings: "cv03", "cv04", "cv11";
} }
.captcha-img { .captcha-img {
margin: 0; margin: 0;
padding: 0; padding: 0;
display: block; display: block;
} }
/* style.css */ /* style.css */
.error-message { .error-message {
/* 设置背景与边框,让错误信息更醒目 */ /* 设置背景与边框,让错误信息更醒目 */
background-color: #f8d7da; background-color: #f8d7da;
border: 1px solid #f5c6cb; border: 1px solid #f5c6cb;
color: #721c24; color: #721c24;
padding: 15px; padding: 15px;
border-radius: 5px; border-radius: 5px;
/* 居中显示 */ /* 居中显示 */
text-align: center; /* 内部文本水平居中 */ text-align: center; /* 内部文本水平居中 */
margin: 20px auto; /* 外边距自动左右居中 */ margin: 20px auto; /* 外边距自动左右居中 */
/* 宽度可以根据需要设置,也可以不设置 */ /* 宽度可以根据需要设置,也可以不设置 */
width: 80%; /* 设置一个宽度 */ width: 80%; /* 设置一个宽度 */
max-width: 400px; /* 最大宽度 */ max-width: 400px; /* 最大宽度 */
} }
</style> </style>
</head> </head>
<body class=" d-flex flex-column"> <body class=" d-flex flex-column">
<div class="page page-center"> <div class="page page-center">
<div class="container container-tight py-4"> <div class="container container-tight py-4">
<div class="card card-md">
<div class="card-body">
<h2 class="h2 text-center mb-4" th:text="${systemTitle}"></h2>
<form name="loginForm" id="loginForm" th:action="@{/toAuth}" method="get" autocomplete="off" novalidate>
<div class="mb-3">
<input type="text" id="username" name="username" class="form-control " placeholder="用户名"
autocomplete="off">
<div class="invalid-feedback" id="userName_error_tip"></div>
</div>
<div class="mb-2">
<div class="input-group input-group-flat">
<input type="password" id="password" name="password" class="form-control "
placeholder="密码" autocomplete="off">
<div class="invalid-feedback" id="password_error_tip"></div>
</div>
</div>
<div class="form-footer">
<button type="submit" class="btn btn-primary w-100">登录</button>
</div>
</form>
<div class="card card-md">
<div class="card-body">
<h2 class="h2 text-center mb-4" th:text="${systemTitle}"></h2>
<form name="loginForm" id="loginForm" th:action="@{/toAuth}" method="get" autocomplete="off"
novalidate>
<div class="mb-3">
<input type="text" id="username" name="username" class="form-control "
placeholder="用户名"
autocomplete="off">
<div class="invalid-feedback" id="userName_error_tip"></div>
</div>
<div class="mb-2">
<div class="input-group input-group-flat">
<input type="password" id="password" name="password" class="form-control "
placeholder="密码" autocomplete="off">
<div class="invalid-feedback" id="password_error_tip"></div>
</div> </div>
<div class="error-message" id="error_message" style="display:none;"> </div>
</div> <div class="form-footer">
<button type="submit" class="btn btn-primary w-100">登录</button>
</div> </div>
<div class="form-footer">
<button type="button" class="btn btn-success w-100" th:data-redirect-url="${jumpUrl}"
onclick="jump(this)">统一认证登录
</button>
</div>
</form>
</div>
<div class="error-message" id="error_message" style="display:none;">
</div>
</div> </div>
</div>
</div> </div>
<!-- Libs JS --> <!-- Libs JS -->
<!-- Tabler Core --> <!-- Tabler Core -->
<script th:src="@{/js/tabler.min.js}" defer></script> <script th:src="@{/js/tabler.min.js}" defer></script>
<script th:src="@{/js/common/common.js}" ></script> <script th:src="@{/js/common/common.js}"></script>
</body> </body>
</html> </html>
<script> <script>
document.getElementById('loginForm').addEventListener("submit", function (e) { function jump(obj) {
// 阻止默认表单提交
e.preventDefault();
//删除验证
removeValidCss("loginForm")
// 使用 FormData 获取表单数据
var formData = new FormData(this);
var object = {};
formData.forEach((value, key) => {
object[key] = value;
});
var jsonData = JSON.stringify(object);
console.log("转换得到的 JSON 数据:", jsonData);
// 从 form 的 action 属性获取 URLThymeleaf 渲染后会转换为实际地址) ;
var formAction = this.getAttribute('action'); window.location = obj.dataset.redirectUrl;
}
// 通过 fetch 发送 AJAX POST 请求Content-Type 为 application/json document.getElementById('loginForm').addEventListener("submit", function (e) {
fetch(formAction, { // 阻止默认表单提交
method: "POST", e.preventDefault();
headers: { //删除验证
"Content-Type": "application/json" removeValidCss("loginForm")
}, // 使用 FormData 获取表单数据
body: jsonData var formData = new FormData(this);
}) var object = {};
.then(response => { formData.forEach((value, key) => {
if (!response.ok) { object[key] = value;
throw new Error("网络响应异常");
}
return response.json();
})
.then(data => {
// 根据服务器返回的数据进行处理,比如跳转或显示提示信息
if (data.code === 0) {
// 例如:跳转到首页
window.location.href = "/home";
} else {
if (data.code === -1) {//验证错误
//遍历错误信息
for (const item of data.errors) {
document.getElementById(item.elementId).classList.add("is-invalid");
document.getElementById(item.elementId + "_error_tip").innerHTML = item.message;
}
}
if(data.code===500){//提交错误
document.getElementById("error_message").innerHTML = data.message;
document.getElementById("error_message").style.display = "block";
}
}
})
.catch(error => {
console.error("请求出错:", error);
// 你可以在这里显示错误提示信息
});
}); });
var jsonData = JSON.stringify(object);
console.log("转换得到的 JSON 数据:", jsonData);
// 从 form 的 action 属性获取 URLThymeleaf 渲染后会转换为实际地址)
var formAction = this.getAttribute('action');
// 通过 fetch 发送 AJAX POST 请求Content-Type 为 application/json
fetch(formAction, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: jsonData
})
.then(response => {
if (!response.ok) {
throw new Error("网络响应异常");
}
return response.json();
})
.then(data => {
// 根据服务器返回的数据进行处理,比如跳转或显示提示信息
if (data.code === 0) {
// 例如:跳转到首页
window.location.href = "home";
} else {
if (data.code === -1) {//验证错误
//遍历错误信息
for (const item of data.errors) {
document.getElementById(item.elementId).classList.add("is-invalid");
document.getElementById(item.elementId + "_error_tip").innerHTML = item.message;
}
}
if (data.code === 500) {//提交错误
document.getElementById("error_message").innerHTML = data.message;
document.getElementById("error_message").style.display = "block";
}
}
})
.catch(error => {
console.error("请求出错:", error);
// 你可以在这里显示错误提示信息
});
});
</script> </script>