From 143d33e285c86c781de66c12ffbd5f625bebf712 Mon Sep 17 00:00:00 2001 From: CGD <3030332422@qq.com> Date: Wed, 2 Apr 2025 08:05:03 +0800 Subject: [PATCH 01/18] =?UTF-8?q?=E2=80=9C=E5=88=86=E9=A1=B5=E6=9F=A5?= =?UTF-8?q?=E6=89=BE=E7=94=A8=E6=88=B7=E2=80=9D=E6=9C=89=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=8C=E2=80=9C=E7=94=A8=E6=88=B7=E5=88=A0=E9=99=A4=E2=80=9D?= =?UTF-8?q?=E5=B7=B2=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/manager-web/src/apis/module/admin.js | 35 ++++++-- main/manager-web/src/views/UserManagement.vue | 82 +++++++++++-------- 2 files changed, 78 insertions(+), 39 deletions(-) diff --git a/main/manager-web/src/apis/module/admin.js b/main/manager-web/src/apis/module/admin.js index 977437ab..ecc413b0 100644 --- a/main/manager-web/src/apis/module/admin.js +++ b/main/manager-web/src/apis/module/admin.js @@ -4,20 +4,41 @@ import {getServiceUrl} from '../api' export default { // 用户列表 - getUserList(callback) { + getUserList(params, callback) { + const queryParams = new URLSearchParams({ + page: params.page, + limit: params.limit, + mobile: params.mobile + }).toString(); + + RequestService.sendRequest() + .url(`${getServiceUrl()}/api/v1/admin/users?${queryParams}`) + .method('GET') + .success((res) => { + RequestService.clearRequestTime() + callback(res) + }) + .fail((err) => { + console.error('请求失败:', err) + RequestService.reAjaxFun(() => { + this.getUserList(callback) + }) + }).send() + }, + // 删除用户 + deleteUser(id, callback) { RequestService.sendRequest() - .url(`${getServiceUrl()}/api/v1/admin/users`) - .method('GET') + .url(`${getServiceUrl()}/api/v1/admin/users/${id}`) + .method('DELETE') .success((res) => { RequestService.clearRequestTime() callback(res) }) .fail((err) => { - console.error('请求失败:', err) + console.error('删除失败:', err) RequestService.reAjaxFun(() => { - this.getUserList(callback) + this.deleteUser(id, callback) }) - }) - .send() + }).send() } } diff --git a/main/manager-web/src/views/UserManagement.vue b/main/manager-web/src/views/UserManagement.vue index 53697b8e..4c3bc7b4 100644 --- a/main/manager-web/src/views/UserManagement.vue +++ b/main/manager-web/src/views/UserManagement.vue @@ -13,9 +13,9 @@ - + - + @@ -68,12 +63,14 @@ From c811beadb4f8d76e47759a0ba38cace535ab70d4 Mon Sep 17 00:00:00 2001 From: Ran_Chen <1908198662@qq.com> Date: Wed, 2 Apr 2025 12:05:09 +0800 Subject: [PATCH 06/18] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/manager-web/src/views/ModelConfig.vue | 210 +++++++++++---------- 1 file changed, 113 insertions(+), 97 deletions(-) diff --git a/main/manager-web/src/views/ModelConfig.vue b/main/manager-web/src/views/ModelConfig.vue index b139c492..ba252620 100644 --- a/main/manager-web/src/views/ModelConfig.vue +++ b/main/manager-web/src/views/ModelConfig.vue @@ -106,7 +106,7 @@ - + - + @@ -33,10 +33,10 @@
- 全选 - 启用 - 禁用 - 删除 + 全选 + 启用 + 禁用 + 删除
@@ -124,6 +124,10 @@ export default { this.currentPage = 1; this.fetchUsers(); }, + // 全选 + handleSelectAll() { + this.$refs.userTable.toggleAllSelection(); + }, batchDelete() { console.log('执行批量删除操作'); }, @@ -170,11 +174,7 @@ export default { }) }).catch(() => {}) }, - handleSizeChange(val) { - this.pageSize = val; - console.log('每页条数:', val); - }, - headerCellClassName({column, columnIndex}) { + headerCellClassName({columnIndex}) { if (columnIndex === 0) { return 'custom-selection-header' } @@ -285,78 +285,203 @@ $table-bg-color: #ecf1fd; .ctrl_btn { display: flex; align-items: center; - margin-left: 25px; - } -} + margin-left: 30px; + .el-button { + min-width: 72px; + height: 30px; + padding: 7px 12px; + font-size: 12px; + border-radius: 4px; + line-height: 1; + font-weight: 500; + border: none; + transition: all 0.3s ease; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); + position: relative; + overflow: hidden; -.rotated-icon { - display: inline-block; - transform: rotate(45deg); - margin-right: 4px; - color: black; -} + &:hover { + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); + } -:deep(.el-table) { - background: $table-bg-color; + &:active { + transform: translateY(0); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + } - &.transparent-table { - .el-table__header th { - background: $table-bg-color !important; + &::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 5px; + height: 5px; + background: rgba(255, 255, 255, 0.5); + opacity: 0; + border-radius: 100%; + transform: scale(1, 1) translate(-50%, -50%); + transform-origin: 50% 50%; + } + + &:focus:not(:active)::after { + animation: ripple 0.6s ease-out; + } + } + + /* 全选按钮 */ + .el-button--primary { + background: #5f70f3; + box-shadow: 0 2px 6px rgba(95, 112, 243, 0.3); + + &:hover { + background: #4d5fe1; + box-shadow: 0 4px 8px rgba(95, 112, 243, 0.4); + } + + &:active { + background: #3a4bcf; + box-shadow: 0 2px 4px rgba(95, 112, 243, 0.2); + } + } + + /* 启用按钮 */ + .el-button--success { + background: #5bc98c; + box-shadow: 0 2px 6px rgba(91, 201, 140, 0.3); + + &:hover { + background: #4ab57d; + box-shadow: 0 4px 8px rgba(91, 201, 140, 0.4); + } + + &:active { + background: #3aa16e; + box-shadow: 0 2px 4px rgba(91, 201, 140, 0.2); + } + } + + /* 禁用按钮 */ + .el-button--warning { + background: #f6d075; color: black; + box-shadow: 0 2px 6px rgba(246, 208, 117, 0.3); + + &:hover { + background: #e4c068; + box-shadow: 0 4px 8px rgba(246, 208, 117, 0.4); + } + + &:active { + background: #d2b05b; + box-shadow: 0 2px 4px rgba(246, 208, 117, 0.2); + } + + .rotated-icon { + display: inline-block; + transform: rotate(45deg); + margin-right: 4px; + color: black; + } } - &::before { - display: none; - } + /* 删除按钮 */ + .el-button--danger { + background: #fd5b63; + box-shadow: 0 2px 6px rgba(253, 91, 99, 0.3); - &:last-child td { - border-bottom: none !important; - } + &:hover { + background: #e44a52; + box-shadow: 0 4px 8px rgba(253, 91, 99, 0.4); + } - .el-table__body tr { - background-color: $table-bg-color; - td { - border: { - top: 1px solid rgba(0, 0, 0, 0.04); - bottom: 1px solid rgba(0, 0, 0, 0.04); + &:active { + background: #cb3941; + box-shadow: 0 2px 4px rgba(253, 91, 99, 0.2); + } + } + } + + @keyframes ripple { + 0% { + transform: scale(0, 0); + opacity: 0.5; + } + 100% { + transform: scale(20, 20); + opacity: 0; + } + } + } + + .rotated-icon { + display: inline-block; + transform: rotate(45deg); + margin-right: 4px; + color: black; + } + + :deep(.el-table) { + background: $table-bg-color; + + &.transparent-table { + .el-table__header th { + background: $table-bg-color !important; + color: black; + } + + &::before { + display: none; + } + + &:last-child td { + border-bottom: none !important; + } + + .el-table__body tr { + background-color: $table-bg-color; + td { + border: { + top: 1px solid rgba(0, 0, 0, 0.04); + bottom: 1px solid rgba(0, 0, 0, 0.04); + } } } } } -} -.search-input { - width: 300px; - margin-right: 10px; + .search-input { + width: 300px; + margin-right: 10px; - :deep(.el-input__inner) { - background-color: transparent; - border-color: #d3d6dc; + :deep(.el-input__inner) { + background-color: transparent; + border-color: #d3d6dc; - &:focus { - border-color: #409eff; - } + &:focus { + border-color: #409eff; + } - &::placeholder { - color: #606266; - opacity: 0.7; + &::placeholder { + color: #606266; + opacity: 0.7; + } } } -} -:deep(.custom-selection-header) { - .el-checkbox { - display: none !important; - } + :deep(.custom-selection-header) { + .el-checkbox { + display: none !important; + } - &::after { - content: '选择'; - display: inline-block; - color: black; - font-weight: bold; - padding-bottom: 18px; + &::after { + content: '选择'; + display: inline-block; + color: black; + font-weight: bold; + padding-bottom: 18px; + } } -} .custom-pagination { display: flex; From f7a6de912c422f34b7b252ffd7268d95f796f2f6 Mon Sep 17 00:00:00 2001 From: CGD <3030332422@qq.com> Date: Wed, 2 Apr 2025 15:14:41 +0800 Subject: [PATCH 08/18] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E5=90=AF=E7=94=A8=EF=BC=8C=E6=89=B9=E9=87=8F=E5=88=A0=E9=99=A4?= =?UTF-8?q?=EF=BC=8C=E6=89=B9=E9=87=8F=E7=A6=81=E6=AD=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/manager-web/src/views/UserManagement.vue | 84 ++++++++++++++++++- 1 file changed, 80 insertions(+), 4 deletions(-) diff --git a/main/manager-web/src/views/UserManagement.vue b/main/manager-web/src/views/UserManagement.vue index 6440c999..7e92aa55 100644 --- a/main/manager-web/src/views/UserManagement.vue +++ b/main/manager-web/src/views/UserManagement.vue @@ -34,7 +34,7 @@
全选 - 启用 + 启用 禁用 删除
@@ -124,16 +124,90 @@ export default { this.currentPage = 1; this.fetchUsers(); }, + // 全选 handleSelectAll() { this.$refs.userTable.toggleAllSelection(); }, + + // 批量删除用户 batchDelete() { - console.log('执行批量删除操作'); + const selectedUsers = this.$refs.userTable.selection; + if (selectedUsers.length === 0) { + this.$message.warning('请先选择需要删除的用户'); + return; + } + + this.$confirm(`确定要删除选中的${selectedUsers.length}个用户吗?`, '警告', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }).then(async () => { + const loading = this.$loading({ + lock: true, + text: '正在删除中...', + spinner: 'el-icon-loading', + background: 'rgba(0, 0, 0, 0.7)' + }); + + try { + const results = await Promise.all( + selectedUsers.map(user => { + return new Promise((resolve) => { + adminApi.deleteUser(user.userid, ({data}) => { + if (data.code === 0) { + resolve({success: true, userid: user.userid}); + } else { + resolve({success: false, userid: user.userid, msg: data.msg}); + } + }); + }); + }) + ); + + const successCount = results.filter(r => r.success).length; + const failCount = results.length - successCount; + + if (failCount === 0) { + this.$message.success(`成功删除${successCount}个用户`); + } else if (successCount === 0) { + this.$message.error(`删除失败,请重试`); + } else { + this.$message.warning(`成功删除${successCount}个用户,${failCount}个删除失败`); + } + + this.fetchUsers(); + } catch (error) { + this.$message.error('删除过程中发生错误'); + } finally { + loading.close(); + } + }).catch(() => { + this.$message.info('已取消删除'); + }); }, + + // 批量启用用户 + batchEnable() { + const selectedUsers = this.$refs.userTable.selection; + if (selectedUsers.length === 0) { + this.$message.warning('请先选择需要启用的用户'); + return; + } + selectedUsers.forEach(user => { + user.status = '正常'; + }); + this.$message.success('启用操作成功'); + }, + + // 批量禁用用户 batchDisable() { - console.log('执行批量禁用操作'); + this.userList.forEach(user => { + user.status = '禁用'; + }); + this.$message.success('状态已更新为禁用'); }, + // 重置密码 resetPassword(row) { this.$confirm('重置后将会生成新密码,是否继续?', '提示', { @@ -157,6 +231,7 @@ export default { row.status = '正常'; console.log('恢复用户:', row); }, + // 用户删除 deleteUser(row) { this.$confirm('确定要删除该用户吗?', '警告', { @@ -200,6 +275,7 @@ export default { this.currentPage = page; this.fetchUsers(); }, + } }; @@ -288,7 +364,7 @@ $table-bg-color: #ecf1fd; margin-left: 30px; .el-button { min-width: 72px; - height: 30px; + height: 32px; padding: 7px 12px; font-size: 12px; border-radius: 4px; From bdedc48aca39d4c1ced0941a5310904bc38efb86 Mon Sep 17 00:00:00 2001 From: Ran_Chen <1908198662@qq.com> Date: Wed, 2 Apr 2025 15:38:04 +0800 Subject: [PATCH 09/18] =?UTF-8?q?=E5=AE=8C=E6=88=90device=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E8=B0=83=E6=95=B4=EF=BC=8C=E8=B0=83=E6=95=B4=E5=BC=B9?= =?UTF-8?q?=E7=AA=97=E8=AE=BE=E7=BD=AE=EF=BC=8C=E4=BC=98=E5=8C=96Headerbar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/manager-web/src/apis/module/device.js | 54 +++++++++++++++++++ main/manager-web/src/apis/module/user.js | 52 ------------------ .../src/components/AddDeviceDialog.vue | 4 +- .../src/components/ChangePasswordDialog.vue | 9 ++-- main/manager-web/src/components/HeaderBar.vue | 5 -- main/manager-web/src/components/TtsModel.vue | 9 +++- main/manager-web/src/main.js | 1 + main/manager-web/src/utils/index.js | 9 ++-- .../src/views/DeviceManagement.vue | 45 ++++++++-------- 9 files changed, 99 insertions(+), 89 deletions(-) create mode 100644 main/manager-web/src/apis/module/device.js diff --git a/main/manager-web/src/apis/module/device.js b/main/manager-web/src/apis/module/device.js new file mode 100644 index 00000000..e8dc2c71 --- /dev/null +++ b/main/manager-web/src/apis/module/device.js @@ -0,0 +1,54 @@ +import RequestService from '../httpRequest' +import {getServiceUrl} from '../api' + +export default { + // 已绑设备 + getAgentBindDevices(agentId, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/api/v1/device/bind/${agentId}`) + .method('GET') + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .fail((err) => { + console.error('获取设备列表失败:', err); + RequestService.reAjaxFun(() => { + this.getAgentBindDevices(agentId, callback); + }); + }).send(); + }, + // 解绑设备 + unbindDevice(device_id, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/api/v1/device/unbind`) + .method('POST') + .data({ deviceId: device_id }) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .fail((err) => { + console.error('解绑设备失败:', err); + RequestService.reAjaxFun(() => { + this.unbindDevice(device_id, callback); + }); + }).send(); + }, + // 绑定设备 + bindDevice(agentId, deviceCode, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/api/v1/device/bind/${agentId}/${deviceCode}`) + .method('POST') + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .fail((err) => { + console.error('绑定设备失败:', err); + RequestService.reAjaxFun(() => { + this.bindDevice(agentId, deviceCode, callback); + }); + }).send(); + }, +} \ No newline at end of file diff --git a/main/manager-web/src/apis/module/user.js b/main/manager-web/src/apis/module/user.js index 8e7513fe..8464794c 100755 --- a/main/manager-web/src/apis/module/user.js +++ b/main/manager-web/src/apis/module/user.js @@ -21,7 +21,6 @@ export default { }, // 获取验证码 getCaptcha(uuid, callback) { - RequestService.sendRequest() .url(`${getServiceUrl()}/api/v1/user/captcha?uuid=${uuid}`) .method('GET') @@ -52,7 +51,6 @@ export default { .fail(() => { }).send() }, - // 保存设备配置 saveDeviceConfig(device_id, configData, callback) { RequestService.sendRequest() @@ -106,54 +104,4 @@ export default { }) .send(); }, - - // 已绑设备 - getAgentBindDevices(agentId, callback) { - RequestService.sendRequest() - .url(`${getServiceUrl()}/api/v1/user/agent/device/bind/${agentId}`) - .method('GET') - .success((res) => { - RequestService.clearRequestTime(); - callback(res); - }) - .fail((err) => { - console.error('获取设备列表失败:', err); - RequestService.reAjaxFun(() => { - this.getAgentBindDevices(agentId, callback); - }); - }).send(); - }, - // 解绑设备 - unbindDevice(device_id, callback) { - RequestService.sendRequest() - .url(`${getServiceUrl()}/api/v1/user/device/unbind/${device_id}`) - .method('PUT') - .success((res) => { - RequestService.clearRequestTime(); - callback(res); - }) - .fail((err) => { - console.error('解绑设备失败:', err); - RequestService.reAjaxFun(() => { - this.unbindDevice(device_id, callback); - }); - }).send(); - }, - // 绑定设备 - bindDevice(agentId, code, callback) { - RequestService.sendRequest() - .url(`${getServiceUrl()}/api/v1/user/agent/device/bind/${agentId}`) - .method('POST') - .data({ code }) - .success((res) => { - RequestService.clearRequestTime(); - callback(res); - }) - .fail((err) => { - console.error('绑定设备失败:', err); - RequestService.reAjaxFun(() => { - this.bindDevice(agentId, code, callback); - }); - }).send(); - }, } diff --git a/main/manager-web/src/components/AddDeviceDialog.vue b/main/manager-web/src/components/AddDeviceDialog.vue index 129ed156..a1ba5540 100644 --- a/main/manager-web/src/components/AddDeviceDialog.vue +++ b/main/manager-web/src/components/AddDeviceDialog.vue @@ -49,8 +49,8 @@ export default { return; } this.loading = true; - import('@/apis/module/user').then(({ default: userApi }) => { - userApi.bindDevice( + import('@/apis/module/device').then(({ default: deviceApi }) => { + deviceApi.bindDevice( this.agentId, this.deviceCode, ({data}) => { this.loading = false; diff --git a/main/manager-web/src/components/ChangePasswordDialog.vue b/main/manager-web/src/components/ChangePasswordDialog.vue index 5d1217ef..a0bb1f7d 100644 --- a/main/manager-web/src/components/ChangePasswordDialog.vue +++ b/main/manager-web/src/components/ChangePasswordDialog.vue @@ -1,9 +1,11 @@