diff --git a/src/views/personal-center/index.vue b/src/views/personal-center/index.vue index e906a1f..1774f7d 100644 --- a/src/views/personal-center/index.vue +++ b/src/views/personal-center/index.vue @@ -422,15 +422,16 @@ async function handleAvatarChange(event: Event) { return } - // 验证文件大小(5MB) - if (file.size > 5 * 1024 * 1024) { - coiMsgError('图片大小不能超过5MB') + // 验证文件大小(2MB) + const fileSizeMB = file.size / 1024 / 1024 + if (fileSizeMB > 2) { + coiMsgError(`头像文件大小超出限制!当前文件:${fileSizeMB.toFixed(2)}MB,最大允许:2MB`) return } try { uploading.value = true - const result = await uploadAvatar(file, 5) + const result = await uploadAvatar(file, 2) if (result.isSuccess) { // 使用配置文件中的服务地址构建头像访问URL const baseUrl = serviceConfig[import.meta.env.MODE].url @@ -446,8 +447,38 @@ async function handleAvatarChange(event: Event) { coiMsgError('头像上传失败') } } - catch { - coiMsgError('头像上传失败') + catch (error: any) { + // 解析后端返回的错误信息 + let errorMessage = '头像上传失败' + + // 检查是否是服务返回的结构化错误 + if (error?.isSuccess === false) { + // alova 返回的结构化错误 + if (error.message) { + errorMessage = error.message + } + else if (error.msg) { + errorMessage = error.msg + } + } + else if (error?.response?.data?.msg) { + // 原始HTTP响应错误 + errorMessage = error.response.data.msg + } + else if (error?.message) { + // 网络错误或其他错误 + if (error.message.includes('413')) { + errorMessage = '头像文件大小超出限制,请选择较小的文件' + } + else if (error.message.includes('400')) { + errorMessage = '头像文件格式不支持或文件无效' + } + else { + errorMessage = error.message + } + } + + coiMsgError(errorMessage) } finally { uploading.value = false diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue index 2b2cf2b..4890ef8 100644 --- a/src/views/system/role/index.vue +++ b/src/views/system/role/index.vue @@ -103,6 +103,21 @@ 新增 + + + 修改 + + 删除 + + + + 分配权限 +
@@ -307,6 +337,12 @@ :type="allExpanded ? 'default' : 'primary'" @click="toggleExpandAll" > + {{ allExpanded ? '折叠' : '展开' }} @@ -315,6 +351,12 @@ :type="allSelected ? 'default' : 'primary'" @click="toggleSelectAll" > + {{ allSelected ? '全不选' : '全选' }} @@ -323,6 +365,11 @@ :type="cascadeEnabled ? 'primary' : 'default'" @click="toggleCascade" > + 父子联动 @@ -331,6 +378,11 @@ :type="showPermissionCode ? 'primary' : 'default'" @click="togglePermissionCode" > + 权限标识
@@ -372,7 +424,7 @@ import type { DataTableColumns, FormInst } from 'naive-ui' import { NButton, NIcon, NPopconfirm, NSpace, NSwitch, NTag, NTooltip, NTree } from 'naive-ui' import IconParkOutlineEditOne from '~icons/icon-park-outline/edit-one' import IconParkOutlineDelete from '~icons/icon-park-outline/delete' -import IconParkOutlineShield from '~icons/icon-park-outline/shield' +import IconParkOutlineKey from '~icons/icon-park-outline/key' import CoiDialog from '@/components/common/CoiDialog.vue' import CoiEmpty from '@/components/common/CoiEmpty.vue' import { @@ -553,7 +605,7 @@ const columns: DataTableColumns = [ { title: '操作', key: 'actions', - width: 160, + width: 200, align: 'center', fixed: 'right', render: (row) => { @@ -615,7 +667,7 @@ const columns: DataTableColumns = [ class: 'action-btn action-btn-warning', onClick: () => handleAssignMenu(row), }, { - icon: () => h(NIcon, { size: 18 }, { default: () => h(IconParkOutlineShield) }), + icon: () => h(NIcon, { size: 18 }, { default: () => h(IconParkOutlineKey) }), }), })) } @@ -780,6 +832,31 @@ function handleRowSelectionChange(rowKeys: (string | number)[]) { selectedRows.value = tableData.value.filter(row => numericKeys.includes(row.roleId)) } +// 批量修改(选中一个角色进行修改) +function handleBatchEdit() { + if (selectedRows.value.length !== 1) { + coiMsgWarning('请选择一个角色进行修改') + return + } + handleEdit(selectedRows.value[0]) +} + +// 批量分配权限(选中一个角色进行权限分配) +function handleBatchAssignMenu() { + if (selectedRows.value.length !== 1) { + coiMsgWarning('请选择一个角色进行权限分配') + return + } + + const selectedRole = selectedRows.value[0] + if (selectedRole.roleId === 1) { + coiMsgError('超级管理员角色无需分配权限') + return + } + + handleAssignMenu(selectedRole) +} + // 新增角色 async function handleAdd() { modalTitle.value = '新增角色' @@ -1111,10 +1188,12 @@ function renderPermissionCode({ option }: { option: any }) { return null } - return h('span', { - class: 'ml-2 px-2 py-1 bg-blue-50 text-blue-600 text-xs rounded font-mono border border-blue-200', + return h(NTag, { + type: 'primary', + size: 'small', + class: 'ml-2 font-mono', style: 'font-size: 11px; line-height: 1.2; transform: translateY(-5px); display: inline-flex; align-items: center;', - }, code) + }, { default: () => code }) } // 提交表单 diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue index c18e848..cdfc617 100644 --- a/src/views/system/user/index.vue +++ b/src/views/system/user/index.vue @@ -1140,14 +1140,12 @@ async function getUserList() { pagination.value.itemCount = data.total || 0 } else { - console.warn('获取用户列表失败,可能是权限或网络问题') coiMsgError('获取用户列表失败,请检查网络连接或联系管理员') tableData.value = [] pagination.value.itemCount = 0 } } - catch (error) { - console.error('获取用户列表失败:', error) + catch { coiMsgError('获取用户列表失败,请检查网络连接') tableData.value = [] pagination.value.itemCount = 0 @@ -1166,8 +1164,7 @@ async function getRoleList() { roleOptions.value = data } } - catch (error) { - console.warn('获取角色列表失败,将不显示角色选择:', error) + catch { } } @@ -1291,8 +1288,7 @@ async function handleEdit(user: UserVo) { } } } - catch (error) { - console.error('获取用户详情失败:', error) + catch { // 如果获取详情出错,使用列表数据作为备用 formData.value = { loginName: user.loginName, @@ -1324,8 +1320,7 @@ async function handleDelete(userId: number) { coiMsgError('删除失败') } } - catch (error) { - console.error('删除失败:', error) + catch { coiMsgError('删除失败') } } @@ -1359,8 +1354,7 @@ async function handleBatchDelete() { coiMsgError('批量删除失败') } } - catch (error) { - console.error('批量删除失败:', error) + catch { coiMsgError('批量删除失败') } } @@ -1382,8 +1376,7 @@ async function handleToggleStatus(user: UserVo) { coiMsgError(`用户${statusText}失败`) } } - catch (error) { - console.error('状态修改失败:', error) + catch { coiMsgError('状态修改失败,请检查网络连接') } } @@ -1425,8 +1418,7 @@ async function handleConfirmResetPassword() { coiMsgError('重置密码失败,请稍后重试') } } - catch (error) { - console.error('重置密码API调用失败:', error) + catch { coiMsgError('重置密码失败,请检查网络连接') } } @@ -1567,8 +1559,7 @@ async function handleExportCurrent() { downloadBlob(response, filename) coiMsgSuccess('导出成功') } - catch (error) { - console.error('导出失败:', error) + catch { coiMsgError('导出失败,请重试') } } @@ -1583,8 +1574,7 @@ async function handleExportAll() { downloadBlob(response, filename) coiMsgSuccess('导出成功') } - catch (error) { - console.error('导出失败:', error) + catch { coiMsgError('导出失败,请重试') } } @@ -1599,8 +1589,7 @@ async function handleDownloadTemplate() { downloadBlob(response, filename) coiMsgSuccess('模板下载成功') } - catch (error) { - console.error('模板下载失败:', error) + catch { coiMsgError('模板下载失败,请重试') } } @@ -1631,6 +1620,8 @@ function handleImport() { // 文件选择处理 function handleFileSelect(file: File) { + // 添加调试日志 + // 验证文件类型 const allowedTypes = [ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx @@ -1642,9 +1633,10 @@ function handleFileSelect(file: File) { return false } - // 验证文件大小(限制为10MB) - if (file.size > 10 * 1024 * 1024) { - coiMsgError('文件大小不能超过10MB') + // 验证文件大小(限制为2MB) + const fileSizeMB = file.size / 1024 / 1024 + if (fileSizeMB > 2) { + coiMsgError(`Excel文件大小超出限制!当前文件:${fileSizeMB.toFixed(2)}MB,最大允许:2MB`) return false } @@ -1698,9 +1690,38 @@ async function handleConfirmImport() { coiMsgError(response.message || '导入失败,请重试') } } - catch (error) { - console.error('导入失败:', error) - coiMsgError('导入失败,请检查文件格式或联系管理员') + catch (error: any) { + // 解析后端返回的错误信息 + let errorMessage = '导入失败,请检查文件格式或联系管理员' + + // 检查是否是服务返回的结构化错误 + if (error?.isSuccess === false) { + // alova 返回的结构化错误 + if (error.message) { + errorMessage = error.message + } + else if (error.msg) { + errorMessage = error.msg + } + } + else if (error?.response?.data?.msg) { + // 原始HTTP响应错误 + errorMessage = error.response.data.msg + } + else if (error?.message) { + // 网络错误或其他错误 + if (error.message.includes('413')) { + errorMessage = 'Excel文件大小超出限制,请选择较小的文件' + } + else if (error.message.includes('400')) { + errorMessage = 'Excel文件格式不支持或文件内容有误' + } + else { + errorMessage = error.message + } + } + + coiMsgError(errorMessage) } finally { // 清理定时器 @@ -1866,8 +1887,7 @@ async function handleSubmit() { coiMsgError(isEdit.value ? '更新失败,请稍后重试' : '创建失败,请稍后重试') } } - catch (error) { - console.error('API调用失败:', error) + catch { coiMsgError(isEdit.value ? '更新失败,请检查网络连接' : '创建失败,请检查网络连接') } }