新增用户信息编辑抽屉

This commit is contained in:
柏码の讲师 2025-01-05 00:42:49 +08:00
parent 8609d8bee5
commit 735024b7ce
6 changed files with 148 additions and 7 deletions

View File

@ -3,12 +3,16 @@ package com.example.controller.admin;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.entity.RestBean; import com.example.entity.RestBean;
import com.example.entity.dto.Account;
import com.example.entity.dto.AccountDetails;
import com.example.entity.dto.AccountPrivacy;
import com.example.entity.vo.response.AccountVO; import com.example.entity.vo.response.AccountVO;
import com.example.service.AccountDetailsService;
import com.example.service.AccountPrivacyService;
import com.example.service.AccountService; import com.example.service.AccountService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.List;
@ -19,6 +23,12 @@ public class AccountAdminController {
@Resource @Resource
AccountService service; AccountService service;
@Resource
AccountDetailsService detailsService;
@Resource
AccountPrivacyService privacyService;
@GetMapping("/list") @GetMapping("/list")
public RestBean<JSONObject> accountList(int page, int size) { public RestBean<JSONObject> accountList(int page, int size) {
JSONObject object = new JSONObject(); JSONObject object = new JSONObject();
@ -31,4 +41,30 @@ public class AccountAdminController {
object.put("list", list); object.put("list", list);
return RestBean.success(object); return RestBean.success(object);
} }
@GetMapping("/detail")
public RestBean<JSONObject> accountDetail(int id) {
JSONObject object = new JSONObject();
object.put("detail", detailsService.findAccountDetailsById(id));
object.put("privacy", privacyService.accountPrivacy(id));
return RestBean.success(object);
}
@PostMapping("/save")
public RestBean<Void> saveAccount(@RequestBody JSONObject object) {
int id = object.getInteger("id");
Account account = service.findAccountById(id);
Account save = object.toJavaObject(Account.class);
BeanUtils.copyProperties(save, account, "password", "registerTime");
service.saveOrUpdate(account);
AccountDetails details = detailsService.findAccountDetailsById(id);
AccountDetails saveDetails = object.getJSONObject("detail").toJavaObject(AccountDetails.class);
BeanUtils.copyProperties(saveDetails, details);
detailsService.saveOrUpdate(details);
AccountPrivacy privacy = privacyService.accountPrivacy(id);
AccountPrivacy savePrivacy = object.getJSONObject("privacy").toJavaObject(AccountPrivacy.class);
BeanUtils.copyProperties(savePrivacy, privacy);
privacyService.saveOrUpdate(savePrivacy);
return RestBean.success();
}
} }

View File

@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
import com.example.entity.BaseData; import com.example.entity.BaseData;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date; import java.util.Date;
@ -14,6 +15,7 @@ import java.util.Date;
*/ */
@Data @Data
@TableName("db_account") @TableName("db_account")
@NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class Account implements BaseData { public class Account implements BaseData {
@TableId(type = IdType.AUTO) @TableId(type = IdType.AUTO)
@ -24,4 +26,6 @@ public class Account implements BaseData {
String role; String role;
String avatar; String avatar;
Date registerTime; Date registerTime;
boolean mute;
boolean banned;
} }

View File

@ -12,4 +12,6 @@ public class AccountVO {
String role; String role;
String avatar; String avatar;
Date registerTime; Date registerTime;
boolean mute;
boolean banned;
} }

View File

@ -109,7 +109,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
if(this.existsAccountByUsername(username)) return "该用户名已被他人使用,请重新更换"; if(this.existsAccountByUsername(username)) return "该用户名已被他人使用,请重新更换";
String password = passwordEncoder.encode(info.getPassword()); String password = passwordEncoder.encode(info.getPassword());
Account account = new Account(null, info.getUsername(), Account account = new Account(null, info.getUsername(),
password, email, Const.ROLE_DEFAULT, null, new Date()); password, email, Const.ROLE_DEFAULT, null, new Date(), false, false);
if(!this.save(account)) { if(!this.save(account)) {
return "内部错误,注册失败"; return "内部错误,注册失败";
} else { } else {

View File

@ -80,3 +80,9 @@ export const apiNotificationDelete = (id, success) =>
export const apiUserList = (page, size, success) => export const apiUserList = (page, size, success) =>
get(`api/admin/user/list?page=${page}&size=${size}`, success) get(`api/admin/user/list?page=${page}&size=${size}`, success)
export const apiUserDetailTotal = (id, success) =>
get(`api/admin/user/detail?id=${id}`, success)
export const apiUserSave = (data, success) =>
post('/api/admin/user/save', data, success)

View File

@ -1,11 +1,19 @@
<script setup> <script setup>
import {User} from "@element-plus/icons-vue"; import {EditPen, User} from "@element-plus/icons-vue";
import {apiUserList} from "@/net/api/user"; import {apiUserDetailTotal, apiUserList, apiUserSave} from "@/net/api/user";
import {reactive, watchEffect} from "vue"; import {reactive, watchEffect} from "vue";
import {useStore} from "@/store"; import {useStore} from "@/store";
import {ElMessage} from "element-plus";
const store = useStore() const store = useStore()
const editor = reactive({
id: 0,
display: false,
temp: {},
loading: false
})
const userTable = reactive({ const userTable = reactive({
page: 1, page: 1,
size: 10, size: 10,
@ -13,6 +21,36 @@ const userTable = reactive({
data: [] data: []
}) })
function userStatus(user) {
if(user.mute && user.banned)
return '禁言中、封禁中'
else if(user.mute)
return '禁言中'
else if(user.banned)
return '封禁中'
else
return '正常'
}
function openUserEditor(user) {
editor.id = user.id
editor.display = true
editor.loading = true
apiUserDetailTotal(editor.id, data => {
editor.temp = { ...data, ...user }
editor.loading = false
})
}
function saveUserDetail() {
editor.display = false
apiUserSave(editor.temp, () => {
const user = userTable.data.find(user => user.id === editor.id)
Object.assign(user, editor.temp)
ElMessage.success('数据保存成功')
})
}
watchEffect(() => apiUserList(userTable.page, userTable.size, data => { watchEffect(() => apiUserList(userTable.page, userTable.size, data => {
userTable.total = data.total userTable.total = data.total
userTable.data = data.list userTable.data = data.list
@ -50,6 +88,18 @@ watchEffect(() => apiUserList(userTable.page, userTable.size, data => {
{{ new Date(row.registerTime).toLocaleString() }} {{ new Date(row.registerTime).toLocaleString() }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="状态" align="center">
<template #default="{ row }">
{{ userStatus(row) }}
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="{ row }">
<el-button type="primary" size="small" :icon="EditPen"
@click="openUserEditor(row)"
:disabled="row.role === 'admin'">编辑</el-button>
</template>
</el-table-column>
</el-table> </el-table>
<div class="pagination"> <div class="pagination">
<el-pagination :total="userTable.total" <el-pagination :total="userTable.total"
@ -57,10 +107,49 @@ watchEffect(() => apiUserList(userTable.page, userTable.size, data => {
v-model:page-size="userTable.size" v-model:page-size="userTable.size"
layout="total, sizes, prev, pager, next, jumper"/> layout="total, sizes, prev, pager, next, jumper"/>
</div> </div>
<el-drawer v-model="editor.display">
<template #header>
<div>
<div style="font-weight: bold">
<el-icon><EditPen/></el-icon> 编辑用户信息
</div>
<div style="font-size: 13px">编辑完成后请点击下方保存按钮</div>
</div>
</template>
<el-form label-position="top">
<el-form-item label="用户名">
<el-input v-model="editor.temp.username"/>
</el-form-item>
<el-form-item label="电子邮件">
<el-input v-model="editor.temp.email"/>
</el-form-item>
<div style="display: flex;font-size: 14px;gap: 20px">
<div>
<span style="margin-right: 10px">禁言</span>
<el-switch v-model="editor.temp.mute"/>
</div>
<el-divider style="height: 30px" direction="vertical"/>
<div>
<span style="margin-right: 10px">账号封禁</span>
<el-switch v-model="editor.temp.banned"/>
</div>
</div>
<div style="margin-top: 10px;color: #606266;font-size: 14px">
注册时间: {{ new Date(editor.temp.registerTime).toLocaleString() }}
</div>
<el-divider/>
</el-form>
<template #footer>
<div style="text-align: center">
<el-button type="success" @click="saveUserDetail">保存</el-button>
<el-button type="info" @click="editor.display = false">取消</el-button>
</div>
</template>
</el-drawer>
</div> </div>
</template> </template>
<style scoped> <style lang="less" scoped>
.user-admin { .user-admin {
.title { .title {
font-weight: bold; font-weight: bold;
@ -84,5 +173,9 @@ watchEffect(() => apiUserList(userTable.page, userTable.size, data => {
display: flex; display: flex;
justify-content: right; justify-content: right;
} }
:deep(.el-drawer__header) {
margin-bottom: 0;
}
} }
</style> </style>