✨ 用户添加和更新完成
This commit is contained in:
parent
b4bb4f8418
commit
ae77d2905c
|
@ -1,6 +1,7 @@
|
|||
package com.spring.step2.domain.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
@ -13,13 +14,18 @@ import lombok.NoArgsConstructor;
|
|||
@Schema(name = "UserDTO对象", title = "用户", description = "用户的DTO对象")
|
||||
public class UserDto {
|
||||
|
||||
@Schema(name = "id", title = "主键")
|
||||
private Long id;
|
||||
|
||||
@Schema(name = "username", title = "用户名")
|
||||
@NotBlank(message = "用户名不能为空")
|
||||
private String username;
|
||||
|
||||
@Schema(name = "password", title = "密码")
|
||||
private String password;
|
||||
|
||||
@Schema(name = "email", title = "邮箱")
|
||||
@NotBlank(message = "邮箱不能为空")
|
||||
private String email;
|
||||
|
||||
}
|
|
@ -15,6 +15,7 @@ import org.springframework.beans.BeanUtils;
|
|||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -65,8 +66,11 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> impleme
|
|||
UserEntity user = new UserEntity();
|
||||
BeanUtils.copyProperties(dto, user);
|
||||
|
||||
// 设置用户密码
|
||||
// 用户密码是否为空,为空设置默认密码
|
||||
String password = user.getPassword();
|
||||
password = StringUtils.hasText(password) ? password : "123456";
|
||||
|
||||
// 设置用户密码
|
||||
String encodePassword = passwordEncoder.encode(password);
|
||||
user.setPassword(encodePassword);
|
||||
|
||||
|
@ -82,6 +86,14 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> impleme
|
|||
public void updateUser(UserDto dto) {
|
||||
UserEntity user = new UserEntity();
|
||||
BeanUtils.copyProperties(dto, user);
|
||||
|
||||
// 设置用户密码
|
||||
String password = user.getPassword();
|
||||
if (StringUtils.hasText(password)) {
|
||||
String encodePassword = passwordEncoder.encode(password);
|
||||
user.setPassword(encodePassword);
|
||||
}
|
||||
|
||||
updateById(user);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
const {defineComponent} = Vue;
|
||||
/*
|
||||
// pagination 类型
|
||||
const pagination = {
|
||||
// 当前页
|
||||
pageNo: 0,
|
||||
// 分页大小
|
||||
pageSize: 0,
|
||||
// 总分页数
|
||||
pages: 0,
|
||||
}
|
||||
*/
|
||||
|
||||
const Pagination = defineComponent({
|
||||
name: "Pagination",
|
||||
template: `
|
||||
<nav aria-label="Page navigation" class="mt-3">
|
||||
<ul class="pagination justify-content-center">
|
||||
<li class="page-item" :class="{disabled:this.pagination.pageNo == 1}">
|
||||
<a @click="pageNoDecrease" class="page-link" href="javascript:">上一页</a>
|
||||
</li>
|
||||
|
||||
<li :class="{active:page===pagination.pageNo}" :key="index" class="page-item"
|
||||
v-for="(page,index) in pagination.pages">
|
||||
<a class="page-link" href="javascript:" @click="onCurrentPageClick(page)">{{page}}</a>
|
||||
</li>
|
||||
|
||||
<li class="page-item" :class="{disabled:this.pagination.pageNo >= this.pagination.pages}">
|
||||
<a @click="pageNoIncrease" class="page-link" href="javascript:">下一页</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
`,
|
||||
props: {
|
||||
pagination: {type: Object, required: true},
|
||||
// 初始化加载数据
|
||||
onSearch: {type: Function, required: true},
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
/* 当前分页+1 */
|
||||
pageNoIncrease() {
|
||||
this.pagination.pageNo++;
|
||||
this.$emit("update:pagination", this.pagination);
|
||||
this.onSearch();
|
||||
},
|
||||
/* 当前分页-1 */
|
||||
pageNoDecrease() {
|
||||
this.pagination.pageNo--;
|
||||
this.$emit("update:pagination", this.pagination);
|
||||
this.onSearch();
|
||||
},
|
||||
/* 点击当前页 */
|
||||
onCurrentPageClick(page) {
|
||||
this.pagination.pageNo = page;
|
||||
this.$emit("update:pagination", this.pagination);
|
||||
this.onSearch();
|
||||
}
|
||||
}
|
||||
})
|
|
@ -0,0 +1,94 @@
|
|||
const DialogUser = defineComponent({
|
||||
name: "DialogUser",
|
||||
template: `
|
||||
<div class="modal fade" id="userBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
|
||||
aria-labelledby="userBackdropLabel" aria-hidden="true" ref="modalRef">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
|
||||
<!-- 头部 -->
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">{{isAdd?"新增用户":"修改用户"}}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<form @submit.prevent="onSubmit">
|
||||
<!-- 内容 -->
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="dialogUsername"><i class="fas fa-user me-1"></i>用户名</label>
|
||||
<input autocomplete="false" class="form-control" id="dialogUsername" placeholder="请输入用户名"
|
||||
type="text" v-model="userinfo.username" required>
|
||||
<div class="form-text">在这里输入你的用户名。</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="dialogPassword"><i class="fas fa-lock me-1"></i>密码</label>
|
||||
<input autocomplete="false" class="form-control" id="dialogPassword" placeholder="请输入密码"
|
||||
type="password" v-model="userinfo.password">
|
||||
<div class="form-text">如果不修改或添加不填写此项。</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="dialogEmail"><i class="fas fa-envelope me-1"></i>邮箱</label>
|
||||
<input autocomplete="false" class="form-control" id="dialogEmail" placeholder="请输入邮箱"
|
||||
type="email" v-model="userinfo.email" required>
|
||||
<div class="form-text">在这里输入你的邮箱。</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- 底部 -->
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||||
<button type="submit" class="btn btn-primary">确认</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
props: {
|
||||
// 是否添加
|
||||
isAdd: {type: Boolean, default: false},
|
||||
// 用户信息
|
||||
userinfo: {type: Object, required: true},
|
||||
// 加载函数
|
||||
onSearch: {type: Function, required: true},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
modalInstance: ref(null)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async onSubmit() {
|
||||
// 是否添加表单
|
||||
const {code, message} = this.isAdd ?
|
||||
await axiosInstance.post("/user", this.userinfo) :
|
||||
await axiosInstance.put("/user", this.userinfo);
|
||||
|
||||
if (code === 200) {
|
||||
antd.message.success(message);
|
||||
// 关闭模态框
|
||||
this.modalInstance.hide();
|
||||
this.onSearch();
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 初始化模态框实例
|
||||
const modalEl = this.$refs.modalRef;
|
||||
this.modalInstance = new bootstrap.Modal(modalEl, {
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
});
|
||||
},
|
||||
beforeUnmount() {
|
||||
// 组件销毁时清理模态框实例
|
||||
if (this.modalInstance) {
|
||||
this.modalInstance.dispose();
|
||||
}
|
||||
}
|
||||
});
|
|
@ -32,6 +32,9 @@
|
|||
</head>
|
||||
<body>
|
||||
<div class="container-fluid" id="app">
|
||||
<dialog-user :is-add="dialogFormFlag" :on-search="onSearch" :userinfo="userinfo"></dialog-user>
|
||||
|
||||
<!-- 头部 -->
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<span><i class="fas fa-search me-2"></i>用户查询</span>
|
||||
|
@ -42,12 +45,12 @@
|
|||
<div class="col-md-4">
|
||||
<label class="form-label" for="username"><i class="fas fa-user me-1"></i>用户名</label>
|
||||
<input autocomplete="false" class="form-control" id="username" placeholder="请输入用户名"
|
||||
type="text" v-model="form.username">
|
||||
type="text" v-model="searchForm.username">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" for="email"><i class="fas fa-envelope me-1"></i>邮箱</label>
|
||||
<input autocomplete="false" class="form-control" id="email" placeholder="请输入邮箱"
|
||||
type="email" v-model="form.email">
|
||||
type="email" v-model="searchForm.email">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="search-btn-group">
|
||||
|
@ -64,10 +67,11 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<span><i class="fas fa-users me-2"></i>用户列表</span>
|
||||
<button class="btn btn-sm btn-success ">
|
||||
<button @click="onAdd" class="btn btn-sm btn-success" data-bs-target="#userBackdrop" data-bs-toggle="modal">
|
||||
<i class="fas fa-plus me-1"></i>新增用户
|
||||
</button>
|
||||
</div>
|
||||
|
@ -93,11 +97,11 @@
|
|||
<td>{{formatDate(user.updateTime)}}</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button @click="onEdit(user)" class="btn btn-outline-primary btn-action">
|
||||
<button @click="onEdit(user)" class="btn btn-outline-primary btn-action"
|
||||
data-bs-target="#userBackdrop" data-bs-toggle="modal">
|
||||
<i class="fas fa-edit"></i> 修改
|
||||
</button>
|
||||
<button @click="onDeleted(user)" class="btn btn-outline-danger btn-action"
|
||||
data-bs-target="#staticBackdrop">
|
||||
<button @click="onDeleted(user)" class="btn btn-outline-danger btn-action">
|
||||
<i class="fas fa-trash"></i> 删除
|
||||
</button>
|
||||
</div>
|
||||
|
@ -107,20 +111,8 @@
|
|||
</table>
|
||||
</div>
|
||||
|
||||
<nav aria-label="Page navigation" class="mt-3">
|
||||
<ul class="pagination justify-content-center">
|
||||
<li class="page-item">
|
||||
<a @click="pageNoDecrease" class="page-link" href="javascript:">上一页</a>
|
||||
</li>
|
||||
<li :class="{active:page===form.pageNo}" :key="index" class="page-item"
|
||||
v-for="(page,index) in form.pages">
|
||||
<a class="page-link" href="javascript:">1</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a @click="pageNoIncrease" class="page-link" href="javascript:">下一页</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<!-- 表格分页 -->
|
||||
<pagination :on-search="onSearch" v-model:pagination="searchForm"></pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -129,20 +121,29 @@
|
|||
<script th:src="@{/src/config/popper-config.js}"></script>
|
||||
<!-- 加载全局axios配置 -->
|
||||
<script th:src="@{/src/config/axios-config.js}"></script>
|
||||
|
||||
<!-- 分页 -->
|
||||
<script th:src="@{/src/components/Pagination.js}"></script>
|
||||
<!-- 用户表单 -->
|
||||
<script th:src="@{/src/views/user/DialogUser.js}"></script>
|
||||
<script>
|
||||
const {createApp, ref} = Vue;
|
||||
|
||||
const app = createApp({
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
form: ref({
|
||||
// 查询表单
|
||||
searchForm: ref({
|
||||
username: undefined,
|
||||
email: undefined,
|
||||
pageNo: 1,
|
||||
pageSize: 30,
|
||||
pages: 3
|
||||
pages: 0
|
||||
}),
|
||||
// 用户信息
|
||||
userinfo: ref({}),
|
||||
// 弹窗标题
|
||||
dialogFormFlag: ref(false),
|
||||
// 查询用户列表
|
||||
userList: ref([])
|
||||
};
|
||||
|
@ -153,39 +154,44 @@
|
|||
formatDate(date) {
|
||||
return dayjs(date).format('YYYY-MM-DD HH:mm:ss');
|
||||
},
|
||||
/* 当前分页+1 */
|
||||
pageNoIncrease() {
|
||||
this.form.pageNo++;
|
||||
this.onSearch();
|
||||
},
|
||||
/* 当前分页-1 */
|
||||
pageNoDecrease() {
|
||||
this.form.pageNo--;
|
||||
this.onSearch();
|
||||
},
|
||||
|
||||
/* 加载数据 */
|
||||
async onSearch() {
|
||||
const {pageNo, pageSize} = this.form;
|
||||
const {pageNo, pageSize} = this.searchForm;
|
||||
// 查询数据
|
||||
const {data, message} = await axiosInstance.get(`/user/${pageNo}/${pageSize}`, {params: this.form})
|
||||
|
||||
// 提示加载成功
|
||||
antd.message.success(message);
|
||||
|
||||
// 赋值数据
|
||||
this.userList = data.list;
|
||||
this.form.pageNo = data.pageNo;
|
||||
this.form.pageSize = data.pageSize;
|
||||
this.form.pages = data.pages;
|
||||
|
||||
// 设置分页内容
|
||||
this.searchForm.pageNo = data.pageNo;
|
||||
this.searchForm.pageSize = data.pageSize;
|
||||
this.searchForm.pages = data.pages;
|
||||
},
|
||||
|
||||
/* 重制表单 */
|
||||
onRest() {
|
||||
this.form.username = undefined;
|
||||
this.form.email = undefined;
|
||||
this.searchForm.username = undefined;
|
||||
this.searchForm.email = undefined;
|
||||
this.onSearch();
|
||||
},
|
||||
/* 修改 */
|
||||
onEdit() {
|
||||
|
||||
/* 添加 */
|
||||
onAdd() {
|
||||
this.dialogFormFlag = true;
|
||||
this.userinfo = {};
|
||||
},
|
||||
|
||||
/* 修改 */
|
||||
onEdit(user) {
|
||||
this.dialogFormFlag = false;
|
||||
this.userinfo = user;
|
||||
},
|
||||
|
||||
/* 删除 */
|
||||
async onDeleted(user) {
|
||||
const result = confirm("确认删除?");
|
||||
|
@ -203,6 +209,8 @@
|
|||
},
|
||||
});
|
||||
|
||||
app.component('Pagination', Pagination)
|
||||
app.component('DialogUser', DialogUser)
|
||||
app.mount('#app');
|
||||
</script>
|
||||
</html>
|
Loading…
Reference in New Issue