【新增】完善用户管理

This commit is contained in:
2025-11-03 10:40:53 +08:00
parent bb7b4035fc
commit 0d1127f25e
8 changed files with 379 additions and 165 deletions

View File

@@ -0,0 +1,12 @@
package com.corewing.app.dto.biz.user;
import lombok.Data;
import java.util.List;
@Data
public class BizUserBatchDeleteRequest {
private List<Long> ids;
}

View File

@@ -0,0 +1,8 @@
package com.corewing.app.dto.biz.user;
import lombok.Data;
@Data
public class BizUserIdRequest {
private long id;
}

View File

@@ -0,0 +1,11 @@
package com.corewing.app.dto.biz.user;
import lombok.Data;
import java.util.List;
@Data
public class BizUserStatusRequest {
private List<Long> ids;
private Integer status;
}

View File

@@ -1,9 +1,9 @@
package com.corewing.app.dto.biz; package com.corewing.app.dto.biz.user;
import lombok.Data; import lombok.Data;
@Data @Data
public class ResetPassword { public class ResetPasswordRequest {
/** /**
* 用户id * 用户id

View File

@@ -2,15 +2,17 @@ package com.corewing.app.modules.admin.biz;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.corewing.app.common.Result; import com.corewing.app.common.Result;
import com.corewing.app.dto.biz.ResetPassword; import com.corewing.app.dto.biz.user.BizUserBatchDeleteRequest;
import com.corewing.app.entity.SysUser; import com.corewing.app.dto.biz.user.BizUserIdRequest;
import com.corewing.app.dto.biz.user.BizUserStatusRequest;
import com.corewing.app.dto.biz.user.ResetPasswordRequest;
import com.corewing.app.entity.User; import com.corewing.app.entity.User;
import com.corewing.app.service.UserService; import com.corewing.app.service.UserService;
import io.lettuce.core.ConnectionEvents;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List;
@Controller @Controller
@RequestMapping("/biz/user") @RequestMapping("/biz/user")
@@ -42,15 +44,63 @@ public class BizUserController {
/** /**
* 修改密码 * 修改密码
* @param resetPassword 修改密码DTO * @param resetPasswordRequest 修改密码DTO
* @return 成功 or 失败 * @return 成功 or 失败
*/ */
@PutMapping("/resetPassword") @PutMapping("/resetPassword")
@ResponseBody @ResponseBody
public Result<String> resetPassword(@RequestBody ResetPassword resetPassword) { public Result<String> resetPassword(@RequestBody ResetPasswordRequest resetPasswordRequest) {
boolean flag = userService.resetPassword(resetPassword); boolean flag = userService.resetPassword(resetPasswordRequest);
return Result.isBoolAsMsg(flag, "修改密码成功"); return Result.isBoolAsMsg(flag, "修改密码成功");
} }
/**
* 新增用户
* @param user
* @return
*/
@PostMapping("/save")
@ResponseBody
public Result<String> save(@RequestBody User user) {
return Result.isBool(userService.save(user));
}
/**
* 修改用户
* @param user
* @return
*/
@PostMapping("/update")
@ResponseBody
public Result<String> update(@RequestBody User user) {
return Result.isBool(userService.update(user));
}
/**
* 单删用户
* @param bizUserIdRequest
* @return
*/
@PostMapping("/delete")
@ResponseBody
public Result<String> delete(@RequestBody BizUserIdRequest bizUserIdRequest) {
return Result.isBool(userService.removeById(bizUserIdRequest.getId()));
}
/**
* 批量删除用户
* @return
*/
@PostMapping("/batchDelete")
@ResponseBody
public Result<String> batchDelete(@RequestBody BizUserBatchDeleteRequest bizUserBatchDeleteRequest) {
return Result.isBool(userService.removeByIds(bizUserBatchDeleteRequest.getIds()));
}
@PostMapping("/batchStatus")
@ResponseBody
public Result<String> batchStatus(@RequestBody BizUserStatusRequest bizUserStatusRequests) {
return Result.isBool(userService.batchStatus(bizUserStatusRequests));
}
} }

View File

@@ -2,17 +2,39 @@ package com.corewing.app.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.corewing.app.dto.biz.ResetPassword; import com.corewing.app.dto.biz.user.BizUserIdRequest;
import com.corewing.app.entity.SysUser; import com.corewing.app.dto.biz.user.BizUserStatusRequest;
import com.corewing.app.dto.biz.user.ResetPasswordRequest;
import com.corewing.app.entity.User; import com.corewing.app.entity.User;
import java.util.List;
/** /**
* 应用用户 Service 接口 * 应用用户 Service 接口
*/ */
public interface UserService extends IService<User> { public interface UserService extends IService<User> {
/**
* 获取用户分页数据
* @param user
* @return
*/
Page<User> page(User user); Page<User> page(User user);
/**
* 新增用户数据
* @param user
* @return
*/
boolean save(User user);
/**
* 更新用户数据
* @param user
* @return
*/
boolean update(User user);
/** /**
* 根据用户名查询用户 * 根据用户名查询用户
* *
@@ -82,8 +104,15 @@ public interface UserService extends IService<User> {
/** /**
* 修改密码 * 修改密码
* @param resetPassword * @param resetPasswordRequest
* @return * @return
*/ */
boolean resetPassword(ResetPassword resetPassword); boolean resetPassword(ResetPasswordRequest resetPasswordRequest);
/**
* 批量修改状态
* @param bizUserStatusRequest
* @return
*/
boolean batchStatus(BizUserStatusRequest bizUserStatusRequest);
} }

View File

@@ -2,10 +2,14 @@ package com.corewing.app.service.impl;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.corewing.app.common.page.PageContext; import com.corewing.app.common.page.PageContext;
import com.corewing.app.dto.biz.ResetPassword; import com.corewing.app.dto.biz.user.BizUserIdRequest;
import com.corewing.app.dto.biz.user.BizUserStatusRequest;
import com.corewing.app.dto.biz.user.ResetPasswordRequest;
import com.corewing.app.entity.User; import com.corewing.app.entity.User;
import com.corewing.app.mapper.UserMapper; import com.corewing.app.mapper.UserMapper;
import com.corewing.app.service.UserService; import com.corewing.app.service.UserService;
@@ -13,10 +17,13 @@ import com.corewing.app.service.VerifyCodeService;
import com.corewing.app.util.I18nUtil; import com.corewing.app.util.I18nUtil;
import com.corewing.app.util.Ip2RegionUtil; import com.corewing.app.util.Ip2RegionUtil;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils; import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
/** /**
* 应用用户 Service 实现类 * 应用用户 Service 实现类
@@ -44,6 +51,48 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
return page(page, queryWrapper); return page(page, queryWrapper);
} }
@Override
public boolean save(User user) {
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getUsername, user.getUsername());
if(count(queryWrapper) > 0) {
throw new RuntimeException(I18nUtil.getMessage(I18nUtil.getMessage("error.username.exists")));
}
return super.save(user);
}
@Override
public boolean update(User user) {
// 校验用户名
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getUsername, user.getUsername());
queryWrapper.ne(User::getId, user.getId());
if(count(queryWrapper) > 0) {
throw new RuntimeException(I18nUtil.getMessage(I18nUtil.getMessage("error.username.exists")));
}
// 校验手机号码
LambdaQueryWrapper<User> checkPhoneWrapper = new LambdaQueryWrapper<>();
checkPhoneWrapper.eq(User::getUsername, user.getUsername());
checkPhoneWrapper.ne(User::getId, user.getId());
if(count(checkPhoneWrapper) > 0) {
throw new RuntimeException(I18nUtil.getMessage(I18nUtil.getMessage("error.phone.exists")));
}
// 校验邮箱
LambdaQueryWrapper<User> checkEmailWrapper = new LambdaQueryWrapper<>();
checkEmailWrapper.eq(User::getUsername, user.getUsername());
checkEmailWrapper.ne(User::getId, user.getId());
if(count(checkEmailWrapper) > 0) {
throw new RuntimeException(I18nUtil.getMessage(I18nUtil.getMessage("error.email.exists")));
}
return updateById(user);
}
@Override @Override
public User getByUsername(String username) { public User getByUsername(String username) {
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
@@ -184,14 +233,26 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
} }
@Override @Override
public boolean resetPassword(ResetPassword resetPassword) { public boolean resetPassword(ResetPasswordRequest resetPasswordRequest) {
User user = getById(resetPassword.getUserId()); User user = getById(resetPasswordRequest.getUserId());
if(user == null) { if(user == null) {
throw new RuntimeException(I18nUtil.getMessage("error.user.not.found")); throw new RuntimeException(I18nUtil.getMessage("error.user.not.found"));
} }
// 更新新密码 // 更新新密码
String newPasswordMd5 = DigestUtils.md5DigestAsHex(resetPassword.getPassword().getBytes(StandardCharsets.UTF_8)); String newPasswordMd5 = DigestUtils.md5DigestAsHex(resetPasswordRequest.getPassword().getBytes(StandardCharsets.UTF_8));
user.setPassword(newPasswordMd5); user.setPassword(newPasswordMd5);
return updateById(user); return updateById(user);
} }
@Transactional(rollbackFor = Exception.class)
@Override
public boolean batchStatus(BizUserStatusRequest bizUserStatusRequest) {
bizUserStatusRequest.getIds().forEach(id -> {
LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(User::getId, id);
wrapper.set(User::getStatus, bizUserStatusRequest.getStatus());
this.update(wrapper);
});
return true;
}
} }

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户管理系统</title> <title>用户管理</title>
<!-- 外部引入库文件 --> <!-- 外部引入库文件 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css" rel="stylesheet">
@@ -14,7 +14,7 @@
<div class="main-container"> <div class="main-container">
<div class="table-container"> <div class="table-container">
<!-- 页面标题 --> <!-- 页面标题 -->
<h3 class="mb-4">用户管理</h3> <h4 class="mb-3">用户管理</h4>
<!-- 多参数搜索栏 --> <!-- 多参数搜索栏 -->
<div class="search-bar"> <div class="search-bar">
@@ -79,7 +79,7 @@
</div> </div>
<!-- 新增按钮 --> <!-- 新增按钮 -->
<div class="mb-3"> <div class="mb-2">
<button class="btn btn-info" @click="openAddModal()"> <button class="btn btn-info" @click="openAddModal()">
<i class="bi bi-plus-circle me-1"></i> 新增 <i class="bi bi-plus-circle me-1"></i> 新增
</button> </button>
@@ -99,9 +99,10 @@
@change="toggleSelectAll()" @change="toggleSelectAll()"
> >
</th> </th>
<th>ID</th>
<th>昵称</th> <th>昵称</th>
<th>用户名</th> <th>用户名</th>
<th>号码</th>
<th>邮箱</th>
<th>状态</th> <th>状态</th>
<th>创建时间</th> <th>创建时间</th>
<th style="width: 120px;">操作</th> <th style="width: 120px;">操作</th>
@@ -143,9 +144,10 @@
@change="toggleSelectItem(item.id)" @change="toggleSelectItem(item.id)"
> >
</td> </td>
<td>{{ item.id }}</td>
<td>{{ item.nickName }}</td> <td>{{ item.nickName }}</td>
<td>{{ item.username }}</td> <td>{{ item.username }}</td>
<td>{{ item.telephone }}</td>
<td>{{ item.email }}</td>
<td> <td>
<span class="badge" :class="item.status === 1 ? 'bg-success' : 'bg-danger'"> <span class="badge" :class="item.status === 1 ? 'bg-success' : 'bg-danger'">
{{ item.status === 1 ? '启用' : '禁用' }} {{ item.status === 1 ? '启用' : '禁用' }}
@@ -212,7 +214,8 @@
<li class="page-item" :class="{ disabled: pageNum === 1 }"> <li class="page-item" :class="{ disabled: pageNum === 1 }">
<a class="page-link" href="#" @click.prevent="changePage(pageNum - 1)">上一页</a> <a class="page-link" href="#" @click.prevent="changePage(pageNum - 1)">上一页</a>
</li> </li>
<li class="page-item active" v-for="page in pageList" :key="page"> <li class="page-item" :class="page === pageNum ? 'active' : ''" v-for="page in pageList"
:key="page">
<a class="page-link" href="#" @click.prevent="changePage(page)">{{ page }}</a> <a class="page-link" href="#" @click.prevent="changePage(page)">{{ page }}</a>
</li> </li>
<li class="page-item" :class="{ disabled: pageNum === totalPages }"> <li class="page-item" :class="{ disabled: pageNum === totalPages }">
@@ -240,27 +243,34 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form> <form>
<div class="mb-3"> <div class="mb-3 row">
<label for="recipient-name" class="col-form-label">昵称</label> <label class="col-sm-2 col-form-label">昵称</label>
<input type="text" class="form-control" disabled :value="resetPasswordDto.nickName"> <div class="col-sm-10">
<input type="text" class="form-control" v-model="resetPasswordDto.nickName" disabled>
</div> </div>
<div class="mb-3">
<label for="recipient-name" class="col-form-label">用户名:</label>
<input type="text" class="form-control" disabled :value="resetPasswordDto.username">
</div> </div>
<div class="mb-3 "> <div class="mb-3 row">
<label for="togglePassword" class="form-label">密码</label> <label class="col-sm-2 col-form-label">用户名</label>
<div class="position-relative"> <div class="col-sm-10">
<input type="text" class="form-control" v-model="resetPasswordDto.username" disabled>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2 col-form-label">密码</label>
<div class="col-sm-10 position-relative">
<!-- 密码输入框 --> <!-- 密码输入框 -->
<input :type="isPasswordVisible ? 'text' : 'password'" class="form-control pe-10" id="togglePassword" <input :type="isPasswordVisible ? 'text' : 'password'" class="form-control pe-10"
id="togglePassword"
placeholder="请输入密码" v-model="resetPasswordDto.password"> placeholder="请输入密码" v-model="resetPasswordDto.password">
<!-- 切换按钮(绝对定位在输入框右侧) --> <!-- 切换按钮(绝对定位在输入框右侧) -->
<button type="button" <button type="button"
@click="togglePasswordVisibility" @click="togglePasswordVisibility"
class="btn btn-transparent position-absolute end-0 top-0 h-100 px-3 border-0 bg-transparent" class="btn btn-transparent position-absolute end-0 top-0 h-100 px-3 border-0 bg-transparent"
id="toggleBtn"> id="toggleBtn">
<i :class="isPasswordVisible ? 'bi bi-eye-slash text-secondary' : 'bi bi-eye text-secondary'" id="toggleIcon"></i> <i :class="isPasswordVisible ? 'bi bi-eye-slash text-secondary' : 'bi bi-eye text-secondary'"
id="toggleIcon"></i>
</button> </button>
</div> </div>
</div> </div>
@@ -275,95 +285,88 @@
</div> </div>
<!-- 新增 --> <!-- 新增 or 编辑 -->
<div class="modal fade" id="addModal" tabindex="-1" aria-labelledby="addModalLabel" aria-hidden="true"> <div class="modal fade" id="addOrEditModel" tabindex="-1" aria-labelledby="addOrEditModalLabel" aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h1 class="modal-title fs-5" id="addModalLabel">New message</h1> <h1 class="modal-title fs-5" id="addOrEditModalLabel">{{ addOrEditTitle }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form> <form>
<div class="mb-3"> <div class="mb-3 row">
<label for="recipient-name" class="col-form-label">Recipient:</label> <label class="col-sm-2 col-form-label">昵称</label>
<input type="text" class="form-control"> <div class="col-sm-10">
<input type="text" class="form-control" v-model="addOrEditDto.nickName"
placeholder="请输入昵称">
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2 col-form-label">用户名</label>
<div class="col-sm-10">
<input type="text" class="form-control" v-model="addOrEditDto.username"
placeholder="请输入用户名">
</div>
</div>
<div class="mb-3 row" v-if="addOrEditDto.id == null">
<label class="col-sm-2 col-form-label">密码</label>
<div class="col-sm-10">
<input type="password" class="form-control" v-model="addOrEditDto.password"
placeholder="请输入密码">
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2 col-form-label">号码</label>
<div class="col-sm-10">
<input type="text" class="form-control" v-model="addOrEditDto.telephone"
placeholder="请输入号码">
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2 col-form-label">邮箱</label>
<div class="col-sm-10">
<input type="text" class="form-control" v-model="addOrEditDto.email"
placeholder="请输入邮箱">
</div> </div>
<div class="mb-3">
<label for="message-text" class="col-form-label">Message:</label>
<textarea class="form-control"></textarea>
</div> </div>
</form> </form>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary">Send message</button> <button type="button" class="btn btn-primary" @click.prevent="saveUser">保存</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- 修改 -->
<div class="modal fade" id="editModel" tabindex="-1" aria-labelledby="editModelModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="editModelModalLabel">New message</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form>
<div class="mb-3">
<label for="recipient-name" class="col-form-label">Recipient:</label>
<input type="text" class="form-control" id="recipient-name">
</div>
<div class="mb-3">
<label for="message-text" class="col-form-label">Message:</label>
<textarea class="form-control" id="message-text"></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Send message</button>
</div>
</div>
</div>
</div>
<!-- 外部引入库文件 -->
<script src="https://cdn.jsdelivr.net/npm/vue@3.3.4/dist/vue.global.prod.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue@3.3.4/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios@1.4.0/dist/axios.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/axios@1.4.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<!-- 外部引入模拟请求文件 -->
<script src="/assets/js/axiosRequest.js"></script> <script src="/assets/js/axiosRequest.js"></script>
<script src="/assets/js/message.js"></script>
<script src="/assets/js/confirmModal.js"></script>
<!-- 页面核心逻辑 -->
<script> <script>
const {createApp} = Vue; const {createApp} = Vue;
createApp({ createApp({
data() { data() {
return { return {
tableData: [], // 表格数据源 tableData: [],
loading: false, // 加载状态 loading: false,
// 多搜索参数绑定(与搜索栏对应)
searchParams: { searchParams: {
nickName: '', nickName: '',
username: '', username: '',
status: '', status: '',
}, },
// 分页参数 pageNum: 1,
pageNum: 1, // 当前页码 pageSize: 10,
pageSize: 10, // 每页条数 total: 0,
total: 0, // 总数据量 totalPages: 0,
totalPages: 0, // 总页数 selectedIds: [],
// 批量操作 selectAll: false,
selectedIds: [], // 选中的ID集合 batchAction: '',
selectAll: false, // 全选状态
batchAction: '', // 批量操作选择
// 分页显示范围最多显示5个页码
pageRange: 5, pageRange: 5,
modalInstances: {}, modalInstances: {},
resetPasswordDto: { resetPasswordDto: {
@@ -372,7 +375,17 @@
username: null, username: null,
password: null, password: null,
}, },
isPasswordVisible: false isPasswordVisible: false,
addOrEditTitle: '',
addOrEditDto: {
id: null,
username: null,
nickName: '',
password: null,
status: 1,
email: '',
telephone: ''
}
} }
}, },
computed: { computed: {
@@ -380,18 +393,13 @@
pageList() { pageList() {
const list = []; const list = [];
if (this.totalPages === 0) return list; if (this.totalPages === 0) return list;
// 总页数小于等于显示范围,直接显示所有页码
if (this.totalPages <= this.pageRange) { if (this.totalPages <= this.pageRange) {
for (let i = 1; i <= this.totalPages; i++) { for (let i = 1; i <= this.totalPages; i++) {
list.push(i); list.push(i);
} }
} else { } else {
// 总页数大于显示范围显示当前页前后2个页码
let start = Math.max(1, this.pageNum - 2); let start = Math.max(1, this.pageNum - 2);
let end = Math.min(this.totalPages, this.pageNum + 2); let end = Math.min(this.totalPages, this.pageNum + 2);
// 确保显示5个页码
if (end - start < this.pageRange - 1) { if (end - start < this.pageRange - 1) {
if (start === 1) { if (start === 1) {
end = this.pageRange; end = this.pageRange;
@@ -408,7 +416,6 @@
} }
}, },
methods: { methods: {
// 格式化时间(毫秒转字符串)
formatTime(time) { formatTime(time) {
if (!time) return '-'; if (!time) return '-';
const date = new Date(time); const date = new Date(time);
@@ -422,22 +429,20 @@
}); });
}, },
// 获取表格数据(核心方法)
async fetchData() { async fetchData() {
this.loading = true; this.loading = true;
try { try {
// 调用模拟接口获取数据
const response = await request.get('/biz/user/page', { const response = await request.get('/biz/user/page', {
...this.searchParams, // 传递所有搜索参数 ...this.searchParams,
current: this.pageNum, current: this.pageNum,
size: this.pageSize size: this.pageSize
}); });
console.log(response) console.log(response)
if (response.code === 200) { if (response.code === 200) {
this.tableData = response.data.records; // 列表数据 this.tableData = response.data.records;
this.total = response.data.total; // 总条数 this.total = response.data.total;
this.totalPages = response.data.pages; // 总页数 this.totalPages = response.data.pages;
} }
} catch (error) { } catch (error) {
console.error('获取数据失败:', error); console.error('获取数据失败:', error);
@@ -446,7 +451,7 @@
this.totalPages = 0; this.totalPages = 0;
} finally { } finally {
this.loading = false; this.loading = false;
this.clearSelected(); // 每次加载数据清空选中状态 this.clearSelected();
} }
}, },
@@ -455,28 +460,25 @@
// 边界判断 // 边界判断
if (page < 1 || page > this.totalPages || page === this.pageNum) return; if (page < 1 || page > this.totalPages || page === this.pageNum) return;
this.pageNum = page; this.pageNum = page;
this.fetchData(); // 切换页码后重新加载数据 this.fetchData();
}, },
// 重置搜索 // 重置搜索
resetSearch() { resetSearch() {
// 重置所有搜索参数
this.searchParams = { this.searchParams = {
nickName: '', nickName: '',
username: '', username: '',
status: '', status: '',
}; };
this.pageNum = 1; // 重置到第一页 this.pageNum = 1;
this.fetchData(); this.fetchData();
}, },
// 全选/取消全选 // 全选/取消全选
toggleSelectAll() { toggleSelectAll() {
if (this.selectAll) { if (this.selectAll) {
// 全选收集所有数据的ID
this.selectedIds = this.tableData.map(item => item.id); this.selectedIds = this.tableData.map(item => item.id);
} else { } else {
// 取消全选清空选中ID
this.selectedIds = []; this.selectedIds = [];
} }
}, },
@@ -516,55 +518,65 @@
// 批量删除 // 批量删除
async handleBatchDelete() { async handleBatchDelete() {
if (!confirm(`确定要删除选中的 ${this.selectedIds.length} 条数据吗?`)) return; showConfirmModal({
title: '删除确认',
content: `确定要删除选中的 ${this.selectedIds.length} 条数据吗?`,
onConfirm: async () => {
try { try {
const response = await request.post('/sys/data/batchDelete', { const response = await request.post('/biz/user/batchDelete', {ids: this.selectedIds});
ids: this.selectedIds
});
if (response.code === 200) { if (response.code === 200) {
alert('删除成功'); $message.success("删除成功");
this.fetchData(); // 重新加载数据
}
} catch (error) {
console.error('批量删除失败:', error);
alert('删除失败,请重试!');
}
},
// 批量修改状态(启用/禁用)
async handleBatchStatus(status) {
try {
const response = await request.post('/sys/data/batchUpdateStatus', {
ids: this.selectedIds,
status: status
});
if (response.code === 200) {
alert(`${status === 1 ? '启用' : '禁用'}选中数据!`);
this.fetchData(); // 重新加载数据
}
} catch (error) {
console.error('批量更新状态失败:', error);
alert('操作失败,请重试!');
}
},
// 单个删除
async handleDelete(id) {
if (!confirm('确定要删除这条数据吗?')) return;
try {
const response = await request.post('/sys/data/delete', {id});
if (response.code === 200) {
alert('删除成功!');
this.fetchData(); // 重新加载数据 this.fetchData(); // 重新加载数据
} }
} catch (error) { } catch (error) {
console.error('删除失败:', error); console.error('删除失败:', error);
alert('删除失败,请重试!'); alert('删除失败,请重试!');
} }
}
});
},
// 批量修改状态(启用/禁用)
async handleBatchStatus(status) {
showConfirmModal({
title: '提示',
content: '确认更新这些数据吗?',
onConfirm: async () => {
try {
const response = await request.post('/biz/user/batchStatus', {
ids: this.selectedIds,
status: status
});
if (response.code === 200) {
$message.success(`${status === 1 ? '启用' : '禁用'}选中数据!`);
this.fetchData();
}
} catch (error) {
console.error('批量更新状态失败:', error);
$message.error('操作失败,请重试!');
}
}
});
},
// 单个删除
async handleDelete(id) {
showConfirmModal({
title: '删除确认',
content: '确定要删除这条数据吗?',
onConfirm: async () => {
try {
const response = await request.post('/biz/user/delete', {id});
if (response.code === 200) {
$message.success("删除成功");
this.fetchData(); // 重新加载数据
}
} catch (error) {
console.error('删除失败:', error);
$message.error('删除失败,请重试!');
}
}
});
}, },
// 打开重置密码墨台框 // 打开重置密码墨台框
openPwdModal(item) { openPwdModal(item) {
@@ -572,51 +584,82 @@
this.resetPasswordDto.userId = item.id; this.resetPasswordDto.userId = item.id;
this.resetPasswordDto.username = item.username; this.resetPasswordDto.username = item.username;
this.resetPasswordDto.nickName = item.nickName; this.resetPasswordDto.nickName = item.nickName;
this.resetPasswordDto.password = '';
this.modalInstances['resetPwdModal'].show(); this.modalInstances['resetPwdModal'].show();
}, },
resetPwd() { resetPwd() {
request.put("/biz/user/resetPassword", this.resetPasswordDto) request.put("/biz/user/resetPasswordRequest", this.resetPasswordDto)
.then((result) => { .then((res) => {
console.log(result) if (res.code === 200) {
if (result.code === 200) { $message.success('修改成功!', 500);
alert('修改成功!');
this.modalInstances['resetPwdModal'].hide(); this.modalInstances['resetPwdModal'].hide();
} else { } else {
alert('修改失败!'); $message.error('修改失败,请重试');
} }
this.resetPasswordDto = {}; this.resetPasswordDto = {};
}); }).catch((error) => {
$message.error('修改失败,请重试!');
})
}, },
// 打开新增模态框 // 打开新增模态框
openAddModal() { openAddModal() {
alert('打开新增模态框'); this.addOrEditTitle = '新增';
// 实际项目中添加模态框显示逻辑 this.clearForm();
this.modalInstances['addOrEditModel'].show();
}, },
// 打开编辑模态框 // 打开编辑模态框
openEditModal(item) { openEditModal(item) {
alert(`打开编辑模态框编辑ID: ${item.id}`); this.clearForm();
// 实际项目中添加模态框显示和数据回显逻辑 this.addOrEditTitle = '编辑';
this.addOrEditDto = item;
this.modalInstances['addOrEditModel'].show();
},
saveUser() {
let url = (this.addOrEditDto === null || this.addOrEditDto.id === null) ? '/biz/user/save' : '/biz/user/update';
request.post(url, this.addOrEditDto)
.then((res) => {
if (res.code === 200) {
$message.success('保存成功!', 500);
this.fetchData();
this.modalInstances['addOrEditModel'].hide();
} else {
$message.error('保存失败!', 500);
}
this.clearForm();
}).catch(() => {
})
}, },
// 切换密码可见性的方法
togglePasswordVisibility() { togglePasswordVisibility() {
this.isPasswordVisible = !this.isPasswordVisible; // 反转状态 this.isPasswordVisible = !this.isPasswordVisible;
},
// 清空表单数据
clearForm() {
this.addOrEditDto = {
id: null,
username: null,
nickName: '',
password: null,
status: 1,
email: '',
telephone: ''
};
} }
}, },
mounted() { mounted() {
// 页面加载完成后初始化数据
this.fetchData(); this.fetchData();
const modalIds = ['resetPwdModal', 'editModel', 'addModel']; // 所有模态框的ID集合 const modalIds = ['resetPwdModal', 'addOrEditModel'];
modalIds.forEach(id => { modalIds.forEach(id => {
console.log(id) console.log(id)
const modalElement = document.getElementById(id); const modalElement = document.getElementById(id);
// 先检查元素是否存在,避免报错
if (modalElement) { if (modalElement) {
this.modalInstances[id] = new bootstrap.Modal(modalElement, { this.modalInstances[id] = new bootstrap.Modal(modalElement, {
backdrop: 'static', // 统一配置,也可单独设置 backdrop: 'static',
keyboard: true // 按 ESC 不关闭(可选) keyboard: true
}); });
} }
}); });