加入分组查询、姓名查询,修复了页面闪烁问题,人脸质量等统一提示问题
This commit is contained in:
parent
499d5426c8
commit
0cf047ed03
|
|
@ -471,6 +471,15 @@ class FaceFeatureExtractor:
|
||||||
processing_time) / self.stats['total_extractions']
|
processing_time) / self.stats['total_extractions']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Check if we detected faces but filtered them all out due to quality
|
||||||
|
if not face_infos and boxes:
|
||||||
|
return FeatureExtractionResult(
|
||||||
|
success=False,
|
||||||
|
faces=[],
|
||||||
|
processing_time=processing_time,
|
||||||
|
error_message="Face quality check failed (brightness/clarity/pose)"
|
||||||
|
)
|
||||||
|
|
||||||
return FeatureExtractionResult(
|
return FeatureExtractionResult(
|
||||||
success=len(face_infos) > 0,
|
success=len(face_infos) > 0,
|
||||||
faces=face_infos,
|
faces=face_infos,
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,10 @@ public class UserController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public Map<String, Object> listUsers() {
|
public Map<String, Object> listUsers(
|
||||||
List<User> users = userService.getAllUsers();
|
@RequestParam(value = "name", required = false) String name,
|
||||||
|
@RequestParam(value = "groupId", required = false) Long groupId) {
|
||||||
|
List<User> users = userService.getUsers(name, groupId);
|
||||||
|
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
result.put("code", 200);
|
result.put("code", 200);
|
||||||
|
|
@ -94,4 +96,14 @@ public class UserController {
|
||||||
result.put("msg", "批量删除成功");
|
result.put("msg", "批量删除成功");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/count")
|
||||||
|
public Map<String, Object> countUsers() {
|
||||||
|
long count = userService.countUsers();
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("code", 200);
|
||||||
|
result.put("msg", "success");
|
||||||
|
result.put("data", count);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.bonuos.face.handler;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestControllerAdvice
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
@ExceptionHandler(RuntimeException.class)
|
||||||
|
public Map<String, Object> handleRuntimeException(RuntimeException e) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("code", 500);
|
||||||
|
|
||||||
|
// 提取核心错误信息,去除 "java.lang.RuntimeException: " 前缀
|
||||||
|
String msg = e.getMessage();
|
||||||
|
if (msg != null && msg.contains(": ")) {
|
||||||
|
// 如果是包装过的异常,尝试提取更有意义的部分,但这里简单返回 message 即可,
|
||||||
|
// 因为我们在 Service 层已经精心构造了 message
|
||||||
|
}
|
||||||
|
|
||||||
|
result.put("msg", msg != null ? msg : "系统内部错误");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public Map<String, Object> handleException(Exception e) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("code", 500);
|
||||||
|
result.put("msg", "系统未知错误: " + e.getMessage());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,11 +17,15 @@ public interface UserService {
|
||||||
User addUser(String name, Long groupId, MultipartFile photo);
|
User addUser(String name, Long groupId, MultipartFile photo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询所有用户
|
* 查询用户列表(支持过滤)
|
||||||
*
|
*
|
||||||
|
* @param name 姓名(模糊查询)
|
||||||
|
* @param groupId 分组ID
|
||||||
* @return 用户列表
|
* @return 用户列表
|
||||||
*/
|
*/
|
||||||
List<User> getAllUsers();
|
List<User> getUsers(String name, Long groupId);
|
||||||
|
|
||||||
|
long countUsers();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据ID查询用户
|
* 根据ID查询用户
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.bonuos.face.service.impl;
|
package com.bonuos.face.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.io.FileUtil;
|
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import com.bonuos.face.entity.User;
|
import com.bonuos.face.entity.User;
|
||||||
import com.bonuos.face.mapper.UserMapper;
|
import com.bonuos.face.mapper.UserMapper;
|
||||||
|
|
@ -64,6 +63,13 @@ public class UserServiceImpl implements UserService {
|
||||||
List<Float> features = faceFeatureExtractorClient.extractFeature(dest);
|
List<Float> features = faceFeatureExtractorClient.extractFeature(dest);
|
||||||
featureJson = convertFeaturesToJson(features);
|
featureJson = convertFeaturesToJson(features);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
// 处理特征提取失败的异常
|
||||||
|
if (e.getMessage().contains("No face detected") ||
|
||||||
|
e.getMessage().contains("未检测到人脸") ||
|
||||||
|
e.getMessage().contains("Face quality check failed") ||
|
||||||
|
e.getMessage().toLowerCase().contains("feature extraction failed")) {
|
||||||
|
throw new RuntimeException("请上传正确且清晰的人脸照片", e);
|
||||||
|
}
|
||||||
throw new RuntimeException("特征提取失败: " + e.getMessage(), e);
|
throw new RuntimeException("特征提取失败: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,11 +101,28 @@ public class UserServiceImpl implements UserService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<User> getAllUsers() {
|
public List<User> getUsers(String name, Long groupId) {
|
||||||
|
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<User> queryWrapper = new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>();
|
||||||
// 只返回活跃用户(status=1)
|
// 只返回活跃用户(status=1)
|
||||||
return userMapper.selectList(
|
queryWrapper.eq("status", 1);
|
||||||
new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<User>()
|
|
||||||
.eq("status", 1));
|
if (name != null && !name.isEmpty()) {
|
||||||
|
queryWrapper.like("name", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groupId != null) {
|
||||||
|
queryWrapper.eq("group_id", groupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
queryWrapper.orderByDesc("create_time");
|
||||||
|
|
||||||
|
return userMapper.selectList(queryWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long countUsers() {
|
||||||
|
return userMapper
|
||||||
|
.selectCount(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<User>().eq("status", 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -142,6 +165,13 @@ public class UserServiceImpl implements UserService {
|
||||||
List<Float> features = faceFeatureExtractorClient.extractFeature(dest);
|
List<Float> features = faceFeatureExtractorClient.extractFeature(dest);
|
||||||
user.setFeatureData(convertFeaturesToJson(features));
|
user.setFeatureData(convertFeaturesToJson(features));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
// 处理特征提取失败的异常
|
||||||
|
if (e.getMessage().contains("No face detected") ||
|
||||||
|
e.getMessage().contains("未检测到人脸") ||
|
||||||
|
e.getMessage().contains("Face quality check failed") ||
|
||||||
|
e.getMessage().toLowerCase().contains("feature extraction failed")) {
|
||||||
|
throw new RuntimeException("请上传正确且清晰的人脸照片", e);
|
||||||
|
}
|
||||||
throw new RuntimeException("照片保存或特征提取失败: " + e.getMessage(), e);
|
throw new RuntimeException("照片保存或特征提取失败: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,8 @@ public class FaceFeatureExtractorClient {
|
||||||
} else {
|
} else {
|
||||||
throw new IOException("API call failed with status: " + response.getStatusCode());
|
throw new IOException("API call failed with status: " + response.getStatusCode());
|
||||||
}
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw e;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOException("Error calling Face Feature Extractor API", e);
|
throw new IOException("Error calling Face Feature Extractor API", e);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,11 +126,17 @@
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border: 1px solid #eee;
|
border: 1px solid #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[v-cloak] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
|
||||||
|
<body>
|
||||||
|
<div id="app" v-cloak>
|
||||||
<el-container style="height: 100vh;">
|
<el-container style="height: 100vh;">
|
||||||
<el-aside width="220px">
|
<el-aside width="220px">
|
||||||
<div
|
<div
|
||||||
|
|
@ -187,7 +193,7 @@
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<template #header><span>👤 总用户数</span></template>
|
<template #header><span>👤 总用户数</span></template>
|
||||||
<h2 style="margin: 0; color: #409EFF;">{{ users.length }}</h2>
|
<h2 style="margin: 0; color: #409EFF;">{{ totalUserCount }}</h2>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
|
|
@ -203,7 +209,18 @@
|
||||||
<div v-show="activeMenu === 'users'">
|
<div v-show="activeMenu === 'users'">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<span class="page-title">用户列表</span>
|
<span class="page-title">用户列表</span>
|
||||||
<div>
|
<div style="display: flex; gap: 10px; align-items: center;">
|
||||||
|
<el-select v-model="searchForm.groupId" placeholder="分组查询" clearable
|
||||||
|
style="width: 150px" @change="loadUsers">
|
||||||
|
<el-option v-for="g in groups" :key="g.id" :label="g.groupName"
|
||||||
|
:value="g.id"></el-option>
|
||||||
|
</el-select>
|
||||||
|
<el-input v-model="searchForm.name" placeholder="姓名查询" style="width: 150px"
|
||||||
|
clearable @clear="loadUsers" @keyup.enter="loadUsers">
|
||||||
|
<template #append>
|
||||||
|
<el-button :icon="Search" @click="loadUsers" />
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
<el-button @click="loadUsers" :icon="Refresh" circle></el-button>
|
<el-button @click="loadUsers" :icon="Refresh" circle></el-button>
|
||||||
<el-button type="danger" :disabled="selectedUsers.length === 0"
|
<el-button type="danger" :disabled="selectedUsers.length === 0"
|
||||||
@click="handleBatchDelete">批量删除</el-button>
|
@click="handleBatchDelete">批量删除</el-button>
|
||||||
|
|
@ -357,6 +374,9 @@
|
||||||
const selectedFile = ref(null);
|
const selectedFile = ref(null);
|
||||||
const selectedUsers = ref([]);
|
const selectedUsers = ref([]);
|
||||||
|
|
||||||
|
// Stats
|
||||||
|
const totalUserCount = ref(0);
|
||||||
|
|
||||||
// Dialog States
|
// Dialog States
|
||||||
const userDialog = reactive({ visible: false, isEdit: false });
|
const userDialog = reactive({ visible: false, isEdit: false });
|
||||||
const groupDialog = reactive({ visible: false });
|
const groupDialog = reactive({ visible: false });
|
||||||
|
|
@ -382,10 +402,27 @@
|
||||||
} catch (e) { console.error(e); }
|
} catch (e) { console.error(e); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const searchForm = reactive({ name: '', groupId: null });
|
||||||
|
|
||||||
|
const loadUserCount = async () => {
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${API_USER}/count`).then(r => r.json());
|
||||||
|
if (res.code === 200) {
|
||||||
|
totalUserCount.value = res.data;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to load user count", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const loadUsers = async () => {
|
const loadUsers = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`${API_USER}/list`).then(r => r.json());
|
const params = new URLSearchParams();
|
||||||
|
if (searchForm.name) params.append('name', searchForm.name);
|
||||||
|
if (searchForm.groupId) params.append('groupId', searchForm.groupId);
|
||||||
|
|
||||||
|
const res = await fetch(`${API_USER}/list?${params.toString()}`).then(r => r.json());
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
users.value = res.data;
|
users.value = res.data;
|
||||||
}
|
}
|
||||||
|
|
@ -442,6 +479,7 @@
|
||||||
ElementPlus.ElMessage.success(userDialog.isEdit ? '更新成功' : '注册成功');
|
ElementPlus.ElMessage.success(userDialog.isEdit ? '更新成功' : '注册成功');
|
||||||
userDialog.visible = false;
|
userDialog.visible = false;
|
||||||
loadUsers();
|
loadUsers();
|
||||||
|
loadUserCount();
|
||||||
loadData(); // Refresh all
|
loadData(); // Refresh all
|
||||||
} else {
|
} else {
|
||||||
ElementPlus.ElMessage.error(res.msg || '操作失败');
|
ElementPlus.ElMessage.error(res.msg || '操作失败');
|
||||||
|
|
@ -459,6 +497,7 @@
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
ElementPlus.ElMessage.success('删除成功');
|
ElementPlus.ElMessage.success('删除成功');
|
||||||
loadUsers();
|
loadUsers();
|
||||||
|
loadUserCount();
|
||||||
} else {
|
} else {
|
||||||
ElementPlus.ElMessage.error(res.msg);
|
ElementPlus.ElMessage.error(res.msg);
|
||||||
}
|
}
|
||||||
|
|
@ -491,6 +530,7 @@
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
ElementPlus.ElMessage.success('批量删除成功');
|
ElementPlus.ElMessage.success('批量删除成功');
|
||||||
loadUsers();
|
loadUsers();
|
||||||
|
loadUserCount();
|
||||||
} else {
|
} else {
|
||||||
ElementPlus.ElMessage.error(res.msg);
|
ElementPlus.ElMessage.error(res.msg);
|
||||||
}
|
}
|
||||||
|
|
@ -544,6 +584,7 @@
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
await loadGroups();
|
await loadGroups();
|
||||||
await loadUsers();
|
await loadUsers();
|
||||||
|
await loadUserCount();
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
@ -558,11 +599,13 @@
|
||||||
handleSelectionChange, handleBatchDelete, selectedUsers,
|
handleSelectionChange, handleBatchDelete, selectedUsers,
|
||||||
groupDialog, groupForm, openGroupDialog, submitGroup, handleDeleteGroup,
|
groupDialog, groupForm, openGroupDialog, submitGroup, handleDeleteGroup,
|
||||||
loadUsers, loadGroups,
|
loadUsers, loadGroups,
|
||||||
loadUsers, loadGroups,
|
|
||||||
handleFileChange,
|
handleFileChange,
|
||||||
handleCommand,
|
handleCommand,
|
||||||
|
searchForm,
|
||||||
|
totalUserCount,
|
||||||
Plus: ElementPlusIconsVue.Plus,
|
Plus: ElementPlusIconsVue.Plus,
|
||||||
Refresh: ElementPlusIconsVue.Refresh
|
Refresh: ElementPlusIconsVue.Refresh,
|
||||||
|
Search: ElementPlusIconsVue.Search
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -575,6 +618,6 @@
|
||||||
app.use(ElementPlus);
|
app.use(ElementPlus);
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -126,11 +126,17 @@
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border: 1px solid #eee;
|
border: 1px solid #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[v-cloak] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
|
||||||
|
<body>
|
||||||
|
<div id="app" v-cloak>
|
||||||
<el-container style="height: 100vh;">
|
<el-container style="height: 100vh;">
|
||||||
<el-aside width="220px">
|
<el-aside width="220px">
|
||||||
<div
|
<div
|
||||||
|
|
@ -187,7 +193,7 @@
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-card shadow="hover">
|
<el-card shadow="hover">
|
||||||
<template #header><span>👤 总用户数</span></template>
|
<template #header><span>👤 总用户数</span></template>
|
||||||
<h2 style="margin: 0; color: #409EFF;">{{ users.length }}</h2>
|
<h2 style="margin: 0; color: #409EFF;">{{ totalUserCount }}</h2>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
|
|
@ -203,7 +209,18 @@
|
||||||
<div v-show="activeMenu === 'users'">
|
<div v-show="activeMenu === 'users'">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<span class="page-title">用户列表</span>
|
<span class="page-title">用户列表</span>
|
||||||
<div>
|
<div style="display: flex; gap: 10px; align-items: center;">
|
||||||
|
<el-select v-model="searchForm.groupId" placeholder="分组查询" clearable
|
||||||
|
style="width: 150px" @change="loadUsers">
|
||||||
|
<el-option v-for="g in groups" :key="g.id" :label="g.groupName"
|
||||||
|
:value="g.id"></el-option>
|
||||||
|
</el-select>
|
||||||
|
<el-input v-model="searchForm.name" placeholder="姓名查询" style="width: 150px"
|
||||||
|
clearable @clear="loadUsers" @keyup.enter="loadUsers">
|
||||||
|
<template #append>
|
||||||
|
<el-button :icon="Search" @click="loadUsers" />
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
<el-button @click="loadUsers" :icon="Refresh" circle></el-button>
|
<el-button @click="loadUsers" :icon="Refresh" circle></el-button>
|
||||||
<el-button type="danger" :disabled="selectedUsers.length === 0"
|
<el-button type="danger" :disabled="selectedUsers.length === 0"
|
||||||
@click="handleBatchDelete">批量删除</el-button>
|
@click="handleBatchDelete">批量删除</el-button>
|
||||||
|
|
@ -357,6 +374,9 @@
|
||||||
const selectedFile = ref(null);
|
const selectedFile = ref(null);
|
||||||
const selectedUsers = ref([]);
|
const selectedUsers = ref([]);
|
||||||
|
|
||||||
|
// Stats
|
||||||
|
const totalUserCount = ref(0);
|
||||||
|
|
||||||
// Dialog States
|
// Dialog States
|
||||||
const userDialog = reactive({ visible: false, isEdit: false });
|
const userDialog = reactive({ visible: false, isEdit: false });
|
||||||
const groupDialog = reactive({ visible: false });
|
const groupDialog = reactive({ visible: false });
|
||||||
|
|
@ -382,10 +402,27 @@
|
||||||
} catch (e) { console.error(e); }
|
} catch (e) { console.error(e); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const searchForm = reactive({ name: '', groupId: null });
|
||||||
|
|
||||||
|
const loadUserCount = async () => {
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${API_USER}/count`).then(r => r.json());
|
||||||
|
if (res.code === 200) {
|
||||||
|
totalUserCount.value = res.data;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to load user count", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const loadUsers = async () => {
|
const loadUsers = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`${API_USER}/list`).then(r => r.json());
|
const params = new URLSearchParams();
|
||||||
|
if (searchForm.name) params.append('name', searchForm.name);
|
||||||
|
if (searchForm.groupId) params.append('groupId', searchForm.groupId);
|
||||||
|
|
||||||
|
const res = await fetch(`${API_USER}/list?${params.toString()}`).then(r => r.json());
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
users.value = res.data;
|
users.value = res.data;
|
||||||
}
|
}
|
||||||
|
|
@ -442,6 +479,7 @@
|
||||||
ElementPlus.ElMessage.success(userDialog.isEdit ? '更新成功' : '注册成功');
|
ElementPlus.ElMessage.success(userDialog.isEdit ? '更新成功' : '注册成功');
|
||||||
userDialog.visible = false;
|
userDialog.visible = false;
|
||||||
loadUsers();
|
loadUsers();
|
||||||
|
loadUserCount();
|
||||||
loadData(); // Refresh all
|
loadData(); // Refresh all
|
||||||
} else {
|
} else {
|
||||||
ElementPlus.ElMessage.error(res.msg || '操作失败');
|
ElementPlus.ElMessage.error(res.msg || '操作失败');
|
||||||
|
|
@ -459,6 +497,7 @@
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
ElementPlus.ElMessage.success('删除成功');
|
ElementPlus.ElMessage.success('删除成功');
|
||||||
loadUsers();
|
loadUsers();
|
||||||
|
loadUserCount();
|
||||||
} else {
|
} else {
|
||||||
ElementPlus.ElMessage.error(res.msg);
|
ElementPlus.ElMessage.error(res.msg);
|
||||||
}
|
}
|
||||||
|
|
@ -491,6 +530,7 @@
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
ElementPlus.ElMessage.success('批量删除成功');
|
ElementPlus.ElMessage.success('批量删除成功');
|
||||||
loadUsers();
|
loadUsers();
|
||||||
|
loadUserCount();
|
||||||
} else {
|
} else {
|
||||||
ElementPlus.ElMessage.error(res.msg);
|
ElementPlus.ElMessage.error(res.msg);
|
||||||
}
|
}
|
||||||
|
|
@ -544,6 +584,7 @@
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
await loadGroups();
|
await loadGroups();
|
||||||
await loadUsers();
|
await loadUsers();
|
||||||
|
await loadUserCount();
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
@ -558,11 +599,13 @@
|
||||||
handleSelectionChange, handleBatchDelete, selectedUsers,
|
handleSelectionChange, handleBatchDelete, selectedUsers,
|
||||||
groupDialog, groupForm, openGroupDialog, submitGroup, handleDeleteGroup,
|
groupDialog, groupForm, openGroupDialog, submitGroup, handleDeleteGroup,
|
||||||
loadUsers, loadGroups,
|
loadUsers, loadGroups,
|
||||||
loadUsers, loadGroups,
|
|
||||||
handleFileChange,
|
handleFileChange,
|
||||||
handleCommand,
|
handleCommand,
|
||||||
|
searchForm,
|
||||||
|
totalUserCount,
|
||||||
Plus: ElementPlusIconsVue.Plus,
|
Plus: ElementPlusIconsVue.Plus,
|
||||||
Refresh: ElementPlusIconsVue.Refresh
|
Refresh: ElementPlusIconsVue.Refresh,
|
||||||
|
Search: ElementPlusIconsVue.Search
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -575,6 +618,6 @@
|
||||||
app.use(ElementPlus);
|
app.use(ElementPlus);
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
Loading…
Reference in New Issue