From 2e972a4902460c8a158138fdbea2fe561b6368c1 Mon Sep 17 00:00:00 2001 From: hejl Date: Sun, 31 Aug 2025 21:58:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E7=BB=9F=E4=B8=80=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gofaster/add-test-roles.sql | 25 + gofaster/app/dist/renderer/js/index.js | 542 +++++++++++++----- .../renderer/assets/README-COMMON-STYLES.md | 12 +- .../app/src/renderer/assets/common-styles.css | 140 ++++- .../role-management/views/RoleManagement.vue | 108 +++- .../system-settings/views/Settings.vue | 8 +- .../user-management/views/UserManagement.vue | 99 +++- gofaster/check-role-data.sql | 28 + gofaster/test-icon-styles.html | 166 ++++++ gofaster/test-role-data.ps1 | 48 ++ 10 files changed, 976 insertions(+), 200 deletions(-) create mode 100644 gofaster/add-test-roles.sql create mode 100644 gofaster/check-role-data.sql create mode 100644 gofaster/test-icon-styles.html create mode 100644 gofaster/test-role-data.ps1 diff --git a/gofaster/add-test-roles.sql b/gofaster/add-test-roles.sql new file mode 100644 index 0000000..15469c8 --- /dev/null +++ b/gofaster/add-test-roles.sql @@ -0,0 +1,25 @@ +-- 添加测试角色数据 +INSERT INTO roles (name, code, description, created_at, updated_at) VALUES +('系统管理员', 'ADMIN', '拥有系统所有权限的管理员角色', NOW(), NOW()), +('普通用户', 'USER', '普通用户角色,具有基本权限', NOW(), NOW()), +('内容编辑', 'EDITOR', '负责内容编辑和管理的角色', NOW(), NOW()), +('数据查看员', 'VIEWER', '只能查看数据的角色', NOW(), NOW()), +('财务管理员', 'FINANCE', '负责财务管理的角色', NOW(), NOW()), +('人力资源', 'HR', '负责人力资源管理的角色', NOW(), NOW()), +('技术支持', 'SUPPORT', '提供技术支持的角色', NOW(), NOW()), +('项目经理', 'PM', '负责项目管理的角色', NOW(), NOW()), +('产品经理', 'PRODUCT', '负责产品管理的角色', NOW(), NOW()), +('测试工程师', 'TESTER', '负责软件测试的角色', NOW(), NOW()), +('开发工程师', 'DEVELOPER', '负责软件开发的角色', NOW(), NOW()), +('运维工程师', 'OPS', '负责系统运维的角色', NOW(), NOW()), +('安全管理员', 'SECURITY', '负责系统安全的角色', NOW(), NOW()), +('审计员', 'AUDITOR', '负责系统审计的角色', NOW(), NOW()), +('客户经理', 'ACCOUNT', '负责客户关系的角色', NOW(), NOW()), +('销售代表', 'SALES', '负责销售业务的角色', NOW(), NOW()), +('市场专员', 'MARKETING', '负责市场推广的角色', NOW(), NOW()), +('法务专员', 'LEGAL', '负责法务事务的角色', NOW(), NOW()), +('采购专员', 'PROCUREMENT', '负责采购事务的角色', NOW(), NOW()), +('仓库管理员', 'WAREHOUSE', '负责仓库管理的角色', NOW(), NOW()); + +-- 检查添加结果 +SELECT COUNT(*) as total_roles FROM roles; diff --git a/gofaster/app/dist/renderer/js/index.js b/gofaster/app/dist/renderer/js/index.js index 6ce3e12..0812bd2 100644 --- a/gofaster/app/dist/renderer/js/index.js +++ b/gofaster/app/dist/renderer/js/index.js @@ -2243,13 +2243,7 @@ ___CSS_LOADER_EXPORT___.push([module.id, ` max-width: 800px; } -/* 设置标题图标样式 */ -.page-header h2 i[data-v-69b5cd1d], -.settings-section h3 i[data-v-69b5cd1d] { - margin-right: 8px; - color: var(--accent-color); - font-size: 0.9em; -} + @@ -3242,7 +3236,7 @@ ___CSS_LOADER_EXPORT___.push([module.id, `/* ===== 通用管理页面样式 ==== .setting-item input[type="number"], .setting-item select { width: 100%; - padding: 8px 12px; + padding: 4px 12px; border: 1px solid var(--input-border); border-radius: 6px; font-size: 12px; @@ -3443,11 +3437,122 @@ th { justify-content: center; align-items: center; gap: 20px; + margin-top: 16px; } .page-info { - color: #666; - font-size: 14px; + color: var(--text-secondary); + font-size: 12px; + margin: 0 15px; +} + +/* 分页导航链接样式 */ +.pagination-nav { + display: flex; + align-items: center; + gap: 8px; +} + +.pagination-link { + color: var(--accent-color); + text-decoration: none; + padding: 4px 8px; + border-radius: 4px; + font-size: 12px; + transition: all 0.2s; + cursor: pointer; +} + +.pagination-link:hover { + background: var(--bg-secondary); + color: var(--accent-hover); +} + +.pagination-link.disabled { + color: var(--text-muted); + cursor: not-allowed; + pointer-events: none; +} + +.pagination-link.active { + background: var(--accent-color); + color: white; +} + +/* 分页设置区域 */ +.pagination-settings { + display: flex; + align-items: center; + gap: 10px; + margin-left: 20px; +} + +.pagination-settings label { + font-size: 12px; + color: var(--text-secondary); + margin: 0; +} + +.pagination-settings select { + padding: 4px 8px; + border: 1px solid var(--input-border); + border-radius: 4px; + font-size: 12px; + background-color: var(--input-bg); + color: var(--input-text); + min-width: 60px; +} + +.pagination-settings select:focus { + outline: none; + border-color: var(--accent-color); + box-shadow: 0 0 0 2px rgba(74, 158, 255, 0.2); +} + +/* 跳转页面输入框 */ +.page-jump { + display: flex; + align-items: center; + gap: 5px; + font-size: 12px; +} + +.page-jump span { + font-size: 12px; + color: var(--text-secondary); +} + +.page-jump input { + width: 50px; + padding: 4px 8px; + border: 1px solid var(--input-border); + border-radius: 4px; + font-size: 12px; + background-color: var(--input-bg); + color: var(--input-text); + text-align: center; +} + +.page-jump input:focus { + outline: none; + border-color: var(--accent-color); + box-shadow: 0 0 0 2px rgba(74, 158, 255, 0.2); +} + +.page-jump button { + color: var(--accent-color); + background: none; + border: none; + font-size: 12px; + cursor: pointer; + padding: 4px 8px; + border-radius: 4px; + transition: all 0.2s; +} + +.page-jump button:hover { + background: var(--bg-secondary); + color: var(--accent-hover); } /* 分页按钮字体大小统一 */ @@ -3466,7 +3571,7 @@ th { .page-header, .profile-header { text-align: center; - margin-bottom: 26px; + margin-bottom: 32px; } .page-header h2, @@ -3502,11 +3607,11 @@ th { /* 卡片头部 - 统一样式 */ .card-header, .settings-section h3 { - margin: 0 0 16px 0; + margin: 0 0 20px 0; color: var(--text-primary); font-size: 14px; border-bottom: 2px solid var(--border-color); - padding-bottom: 8px; + padding-bottom: 12px; } .card-header h2, @@ -3516,6 +3621,16 @@ th { color: var(--text-primary); } +/* 页面标题和分组标题图标样式 - 统一样式 */ +.page-header h2 i, +.profile-header h1 i, +.card-header h2 i, +.settings-section h3 i { + margin-right: 8px; + color: var(--accent-color); + font-size: 0.9em; +} + /* 信息网格 */ .info-grid { display: flex; @@ -3529,8 +3644,9 @@ th { display: flex; align-items: center; justify-content: space-between; - margin-bottom: 16px; - padding: 12px 0; + margin-top: 6px; + margin-bottom: 6px; + padding: 6px 0; border-bottom: 1px solid #f5f5f5; } @@ -3622,7 +3738,7 @@ th { display: flex; gap: 16px; justify-content: flex-end; - margin-top: 26px; + margin-top: 32px; } /* ===== 模态框样式 ===== */ @@ -6457,6 +6573,7 @@ __webpack_require__.r(__webpack_exports__); const pageSize = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)(10) const total = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)(0) const searchQuery = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)('') + const jumpPage = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)('') const roleForm = (0,vue__WEBPACK_IMPORTED_MODULE_0__.reactive)({ name: '', @@ -6497,7 +6614,9 @@ __webpack_require__.r(__webpack_exports__); roles: roles.value, total: total.value, page: currentPage.value, - pageSize: pageSize.value + pageSize: pageSize.value, + totalPages: Math.ceil((response.data.total || 0) / pageSize.value), + shouldShowPagination: (response.data.total || 0) > 0 }) } else { console.error('获取角色列表失败: 响应格式错误', response) @@ -6593,10 +6712,25 @@ __webpack_require__.r(__webpack_exports__); // 分页处理 const handleCurrentChange = (val) => { - currentPage.value = val + if (val >= 1 && val <= Math.ceil(total.value / pageSize.value)) { + currentPage.value = val + loadRoles() + } + } + + const handlePageSizeChange = () => { + currentPage.value = 1 loadRoles() } + const handleJumpPage = () => { + const totalPages = Math.ceil(total.value / pageSize.value) + if (jumpPage.value && jumpPage.value >= 1 && jumpPage.value <= totalPages) { + handleCurrentChange(jumpPage.value) + jumpPage.value = '' + } + } + // 格式化日期 const formatDate = (dateStr) => { if (!dateStr) return '' @@ -6631,6 +6765,7 @@ __webpack_require__.r(__webpack_exports__); pageSize, total, searchQuery, + jumpPage, roleForm, filteredRoles, createNewRole, @@ -6640,6 +6775,8 @@ __webpack_require__.r(__webpack_exports__); assignPermissions, handlePermissionsUpdated, handleCurrentChange, + handlePageSizeChange, + handleJumpPage, handleSearch, formatDate } @@ -7744,6 +7881,7 @@ __webpack_require__.r(__webpack_exports__); const searchQuery = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)('') const statusFilter = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)('') const roleFilter = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)('') + const jumpPage = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)('') const showAddUserModal = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)(false) const showEditUserModal = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)(false) @@ -7827,10 +7965,24 @@ __webpack_require__.r(__webpack_exports__); } const changePage = (page) => { - currentPage.value = page + if (page >= 1 && page <= totalPages.value) { + currentPage.value = page + loadUsers() + } + } + + const handlePageSizeChange = () => { + currentPage.value = 1 loadUsers() } + const handleJumpPage = () => { + if (jumpPage.value && jumpPage.value >= 1 && jumpPage.value <= totalPages.value) { + changePage(jumpPage.value) + jumpPage.value = '' + } + } + const editUser = (user) => { editingUser.value = user Object.assign(userForm, { @@ -7908,6 +8060,7 @@ __webpack_require__.r(__webpack_exports__); searchQuery, statusFilter, roleFilter, + jumpPage, showAddUserModal, showEditUserModal, showRoleAssignmentModal, @@ -7921,6 +8074,8 @@ __webpack_require__.r(__webpack_exports__); handleSearch, handleFilter, changePage, + handlePageSizeChange, + handleJumpPage, editUser, submitUser, deleteUser, @@ -9495,20 +9650,19 @@ const _hoisted_9 = { class: "actions" } const _hoisted_10 = ["onClick"] const _hoisted_11 = ["onClick"] const _hoisted_12 = ["onClick"] -const _hoisted_13 = { - key: 0, - class: "pagination" -} -const _hoisted_14 = ["disabled"] +const _hoisted_13 = { class: "pagination" } +const _hoisted_14 = { class: "pagination-nav" } const _hoisted_15 = { class: "page-info" } -const _hoisted_16 = ["disabled"] -const _hoisted_17 = { class: "modal-header" } -const _hoisted_18 = { class: "modal-body" } -const _hoisted_19 = { class: "form-group" } -const _hoisted_20 = { class: "form-group" } +const _hoisted_16 = { class: "pagination-settings" } +const _hoisted_17 = { class: "page-jump" } +const _hoisted_18 = ["max"] +const _hoisted_19 = { class: "modal-header" } +const _hoisted_20 = { class: "modal-body" } const _hoisted_21 = { class: "form-group" } -const _hoisted_22 = { class: "form-actions" } -const _hoisted_23 = ["disabled"] +const _hoisted_22 = { class: "form-group" } +const _hoisted_23 = { class: "form-group" } +const _hoisted_24 = { class: "form-actions" } +const _hoisted_25 = ["disabled"] function render(_ctx, _cache, $props, $setup, $data, $options) { const _component_RolePermissionAssignment = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("RolePermissionAssignment") @@ -9517,7 +9671,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 搜索和操作 "), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_2, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_3, [ - _cache[15] || (_cache[15] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-search" }, null, -1 /* CACHED */)), + _cache[22] || (_cache[22] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-search" }, null, -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", { "onUpdate:modelValue": _cache[0] || (_cache[0] = $event => (($setup.searchQuery) = $event)), type: "text", @@ -9531,7 +9685,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { class: "btn btn-primary", onClick: _cache[2] || (_cache[2] = (...args) => ($setup.createNewRole && $setup.createNewRole(...args))) - }, _cache[16] || (_cache[16] = [ + }, _cache[23] || (_cache[23] = [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-plus" }, null, -1 /* CACHED */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" 新建角色 ", -1 /* CACHED */) ])) @@ -9540,26 +9694,26 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 角色列表 "), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_5, [ ($setup.loading) - ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_6, _cache[17] || (_cache[17] = [ + ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_6, _cache[24] || (_cache[24] = [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-spinner fa-spin" }, null, -1 /* CACHED */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("span", null, "加载中...", -1 /* CACHED */) ]))) : ($setup.roles.length === 0) ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_7, [ - _cache[19] || (_cache[19] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("p", null, [ + _cache[26] || (_cache[26] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("p", null, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-inbox" }), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" 暂无角色数据") ], -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { class: "btn btn-primary", onClick: _cache[3] || (_cache[3] = (...args) => ($setup.createNewRole && $setup.createNewRole(...args))) - }, _cache[18] || (_cache[18] = [ + }, _cache[25] || (_cache[25] = [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-plus" }, null, -1 /* CACHED */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" 创建第一个角色 ", -1 /* CACHED */) ])) ])) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("table", _hoisted_8, [ - _cache[23] || (_cache[23] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("thead", null, [ + _cache[30] || (_cache[30] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("thead", null, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("tr", null, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("th", null, "ID"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("th", null, "角色名称"), @@ -9585,21 +9739,21 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { class: "btn btn-sm btn-info", onClick: $event => ($setup.editRole(role)), title: "编辑角色" - }, [...(_cache[20] || (_cache[20] = [ + }, [...(_cache[27] || (_cache[27] = [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-edit" }, null, -1 /* CACHED */) ]))], 8 /* PROPS */, _hoisted_10), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { class: "btn btn-sm btn-primary", onClick: $event => ($setup.assignPermissions(role)), title: "分配权限" - }, [...(_cache[21] || (_cache[21] = [ + }, [...(_cache[28] || (_cache[28] = [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-shield-alt" }, null, -1 /* CACHED */) ]))], 8 /* PROPS */, _hoisted_11), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { class: "btn btn-sm btn-danger", onClick: $event => ($setup.deleteRole(role)), title: "删除角色" - }, [...(_cache[22] || (_cache[22] = [ + }, [...(_cache[29] || (_cache[29] = [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-trash" }, null, -1 /* CACHED */) ]))], 8 /* PROPS */, _hoisted_12) ]) @@ -9610,55 +9764,102 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { ])) ]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 分页 "), - ($setup.total > $setup.pageSize) - ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_13, [ - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { - disabled: $setup.currentPage === 1, - onClick: _cache[4] || (_cache[4] = $event => ($setup.handleCurrentChange($setup.currentPage - 1))), - class: "btn btn-sm" - }, _cache[24] || (_cache[24] = [ - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-chevron-left" }, null, -1 /* CACHED */), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" 上一页 ", -1 /* CACHED */) - ]), 8 /* PROPS */, _hoisted_14), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("span", _hoisted_15, " 第 " + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.currentPage) + " 页,共 " + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(Math.ceil($setup.total / $setup.pageSize)) + " 页 ", 1 /* TEXT */), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_13, [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 分页导航 "), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_14, [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("a", { + class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['pagination-link', { disabled: $setup.currentPage === 1 }]), + onClick: _cache[4] || (_cache[4] = $event => ($setup.handleCurrentChange(1))), + title: "首页" + }, _cache[31] || (_cache[31] = [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-angle-double-left" }, null, -1 /* CACHED */) + ]), 2 /* CLASS */), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("a", { + class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['pagination-link', { disabled: $setup.currentPage === 1 }]), + onClick: _cache[5] || (_cache[5] = $event => ($setup.handleCurrentChange($setup.currentPage - 1))), + title: "上一页" + }, _cache[32] || (_cache[32] = [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-angle-left" }, null, -1 /* CACHED */) + ]), 2 /* CLASS */), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("span", _hoisted_15, " 第 " + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.currentPage) + " 页,共 " + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(Math.ceil($setup.total / $setup.pageSize)) + " 页 (共 " + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.total) + " 条记录) ", 1 /* TEXT */), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("a", { + class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['pagination-link', { disabled: $setup.currentPage >= Math.ceil($setup.total / $setup.pageSize) }]), + onClick: _cache[6] || (_cache[6] = $event => ($setup.handleCurrentChange($setup.currentPage + 1))), + title: "下一页" + }, _cache[33] || (_cache[33] = [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-angle-right" }, null, -1 /* CACHED */) + ]), 2 /* CLASS */), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("a", { + class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['pagination-link', { disabled: $setup.currentPage >= Math.ceil($setup.total / $setup.pageSize) }]), + onClick: _cache[7] || (_cache[7] = $event => ($setup.handleCurrentChange(Math.ceil($setup.total / $setup.pageSize)))), + title: "尾页" + }, _cache[34] || (_cache[34] = [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-angle-double-right" }, null, -1 /* CACHED */) + ]), 2 /* CLASS */) + ]), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 分页设置 "), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_16, [ + _cache[38] || (_cache[38] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "每页显示:", -1 /* CACHED */)), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("select", { + "onUpdate:modelValue": _cache[8] || (_cache[8] = $event => (($setup.pageSize) = $event)), + onChange: _cache[9] || (_cache[9] = (...args) => ($setup.handlePageSizeChange && $setup.handlePageSizeChange(...args))) + }, _cache[35] || (_cache[35] = [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createStaticVNode)("", 5) + ]), 544 /* NEED_HYDRATION, NEED_PATCH */), [ + [vue__WEBPACK_IMPORTED_MODULE_0__.vModelSelect, $setup.pageSize] + ]), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_17, [ + _cache[36] || (_cache[36] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("span", null, "跳至", -1 /* CACHED */)), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", { + "onUpdate:modelValue": _cache[10] || (_cache[10] = $event => (($setup.jumpPage) = $event)), + type: "number", + min: "1", + max: Math.ceil($setup.total / $setup.pageSize), + onKeyup: _cache[11] || (_cache[11] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withKeys)((...args) => ($setup.handleJumpPage && $setup.handleJumpPage(...args)), ["enter"])), + placeholder: "页码" + }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_18), [ + [ + vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, + $setup.jumpPage, + void 0, + { number: true } + ] + ]), + _cache[37] || (_cache[37] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("span", null, "页", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { - disabled: $setup.currentPage >= Math.ceil($setup.total / $setup.pageSize), - onClick: _cache[5] || (_cache[5] = $event => ($setup.handleCurrentChange($setup.currentPage + 1))), - class: "btn btn-sm" - }, _cache[25] || (_cache[25] = [ - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" 下一页 ", -1 /* CACHED */), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-chevron-right" }, null, -1 /* CACHED */) - ]), 8 /* PROPS */, _hoisted_16) - ])) - : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), + onClick: _cache[12] || (_cache[12] = (...args) => ($setup.handleJumpPage && $setup.handleJumpPage(...args))) + }, "跳转") + ]) + ]) + ]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 创建/编辑角色对话框 "), ($setup.showCreateDialog) ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", { - key: 1, + key: 0, class: "modal-overlay", - onClick: _cache[13] || (_cache[13] = $event => ($setup.showCreateDialog = false)) + onClick: _cache[20] || (_cache[20] = $event => ($setup.showCreateDialog = false)) }, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", { class: "modal", - onClick: _cache[12] || (_cache[12] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)(() => {}, ["stop"])) + onClick: _cache[19] || (_cache[19] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)(() => {}, ["stop"])) }, [ - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_17, [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_19, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h3", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.editingRole ? '编辑角色' : '新建角色'), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { class: "close-btn", - onClick: _cache[6] || (_cache[6] = $event => ($setup.showCreateDialog = false)) - }, _cache[26] || (_cache[26] = [ + onClick: _cache[13] || (_cache[13] = $event => ($setup.showCreateDialog = false)) + }, _cache[39] || (_cache[39] = [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-times" }, null, -1 /* CACHED */) ])) ]), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_18, [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_20, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("form", { - onSubmit: _cache[11] || (_cache[11] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)((...args) => ($setup.saveRole && $setup.saveRole(...args)), ["prevent"])) + onSubmit: _cache[18] || (_cache[18] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)((...args) => ($setup.saveRole && $setup.saveRole(...args)), ["prevent"])) }, [ - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_19, [ - _cache[27] || (_cache[27] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "角色名称 *", -1 /* CACHED */)), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_21, [ + _cache[40] || (_cache[40] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "角色名称 *", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", { - "onUpdate:modelValue": _cache[7] || (_cache[7] = $event => (($setup.roleForm.name) = $event)), + "onUpdate:modelValue": _cache[14] || (_cache[14] = $event => (($setup.roleForm.name) = $event)), type: "text", required: "", placeholder: "请输入角色名称" @@ -9666,10 +9867,10 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { [vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.roleForm.name] ]) ]), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_20, [ - _cache[28] || (_cache[28] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "角色代码 *", -1 /* CACHED */)), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_22, [ + _cache[41] || (_cache[41] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "角色代码 *", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", { - "onUpdate:modelValue": _cache[8] || (_cache[8] = $event => (($setup.roleForm.code) = $event)), + "onUpdate:modelValue": _cache[15] || (_cache[15] = $event => (($setup.roleForm.code) = $event)), type: "text", required: "", placeholder: "请输入角色代码" @@ -9677,27 +9878,27 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { [vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.roleForm.code] ]) ]), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_21, [ - _cache[29] || (_cache[29] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "描述", -1 /* CACHED */)), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_23, [ + _cache[42] || (_cache[42] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "描述", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("textarea", { - "onUpdate:modelValue": _cache[9] || (_cache[9] = $event => (($setup.roleForm.description) = $event)), + "onUpdate:modelValue": _cache[16] || (_cache[16] = $event => (($setup.roleForm.description) = $event)), rows: "3", placeholder: "请输入角色描述" }, null, 512 /* NEED_PATCH */), [ [vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.roleForm.description] ]) ]), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_22, [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_24, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { type: "button", class: "btn btn-secondary", - onClick: _cache[10] || (_cache[10] = $event => ($setup.showCreateDialog = false)) + onClick: _cache[17] || (_cache[17] = $event => ($setup.showCreateDialog = false)) }, " 取消 "), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { type: "submit", class: "btn btn-primary", disabled: $setup.saving - }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.saving ? '保存中...' : ($setup.editingRole ? '更新' : '创建')), 9 /* TEXT, PROPS */, _hoisted_23) + }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.saving ? '保存中...' : ($setup.editingRole ? '更新' : '创建')), 9 /* TEXT, PROPS */, _hoisted_25) ]) ], 32 /* NEED_HYDRATION */) ]) @@ -9707,7 +9908,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 权限分配对话框 "), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_RolePermissionAssignment, { modelValue: $setup.showPermissionDialog, - "onUpdate:modelValue": _cache[14] || (_cache[14] = $event => (($setup.showPermissionDialog) = $event)), + "onUpdate:modelValue": _cache[21] || (_cache[21] = $event => (($setup.showPermissionDialog) = $event)), role: $setup.selectedRole, onPermissionsUpdated: $setup.handlePermissionsUpdated }, null, 8 /* PROPS */, ["modelValue", "role", "onPermissionsUpdated"]) @@ -10457,22 +10658,24 @@ const _hoisted_9 = ["onClick"] const _hoisted_10 = ["onClick"] const _hoisted_11 = ["onClick"] const _hoisted_12 = { class: "pagination" } -const _hoisted_13 = ["disabled"] +const _hoisted_13 = { class: "pagination-nav" } const _hoisted_14 = { class: "page-info" } -const _hoisted_15 = ["disabled"] -const _hoisted_16 = { class: "modal-header" } -const _hoisted_17 = { class: "modal-body" } -const _hoisted_18 = { class: "form-group" } -const _hoisted_19 = ["disabled"] -const _hoisted_20 = { +const _hoisted_15 = { class: "pagination-settings" } +const _hoisted_16 = { class: "page-jump" } +const _hoisted_17 = ["max"] +const _hoisted_18 = { class: "modal-header" } +const _hoisted_19 = { class: "modal-body" } +const _hoisted_20 = { class: "form-group" } +const _hoisted_21 = ["disabled"] +const _hoisted_22 = { key: 0, class: "form-group" } -const _hoisted_21 = { class: "form-group" } -const _hoisted_22 = { class: "form-group" } const _hoisted_23 = { class: "form-group" } -const _hoisted_24 = { class: "form-actions" } -const _hoisted_25 = { +const _hoisted_24 = { class: "form-group" } +const _hoisted_25 = { class: "form-group" } +const _hoisted_26 = { class: "form-actions" } +const _hoisted_27 = { type: "submit", class: "btn btn-primary" } @@ -10484,7 +10687,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 搜索和筛选 "), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_2, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_3, [ - _cache[20] || (_cache[20] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-search" }, null, -1 /* CACHED */)), + _cache[27] || (_cache[27] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-search" }, null, -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", { "onUpdate:modelValue": _cache[0] || (_cache[0] = $event => (($setup.searchQuery) = $event)), type: "text", @@ -10498,7 +10701,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("select", { "onUpdate:modelValue": _cache[2] || (_cache[2] = $event => (($setup.statusFilter) = $event)), onChange: _cache[3] || (_cache[3] = (...args) => ($setup.handleFilter && $setup.handleFilter(...args))) - }, _cache[21] || (_cache[21] = [ + }, _cache[28] || (_cache[28] = [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "" }, "全部状态", -1 /* CACHED */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "1" }, "正常", -1 /* CACHED */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "2" }, "禁用", -1 /* CACHED */) @@ -10509,7 +10712,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { "onUpdate:modelValue": _cache[4] || (_cache[4] = $event => (($setup.roleFilter) = $event)), onChange: _cache[5] || (_cache[5] = (...args) => ($setup.handleFilter && $setup.handleFilter(...args))) }, [ - _cache[22] || (_cache[22] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "" }, "全部角色", -1 /* CACHED */)), + _cache[29] || (_cache[29] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "" }, "全部角色", -1 /* CACHED */)), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($setup.roles, (role) => { return ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("option", { key: role.id, @@ -10522,7 +10725,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { class: "btn btn-primary", onClick: _cache[6] || (_cache[6] = $event => ($setup.showAddUserModal = true)) - }, _cache[23] || (_cache[23] = [ + }, _cache[30] || (_cache[30] = [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-plus" }, null, -1 /* CACHED */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" 添加用户 ", -1 /* CACHED */) ])) @@ -10531,7 +10734,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 用户列表 "), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_6, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("table", null, [ - _cache[27] || (_cache[27] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("thead", null, [ + _cache[34] || (_cache[34] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("thead", null, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("tr", null, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("th", null, "ID"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("th", null, "用户名"), @@ -10573,19 +10776,19 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { class: "btn btn-sm btn-info", onClick: $event => ($setup.editUser(user)) - }, [...(_cache[24] || (_cache[24] = [ + }, [...(_cache[31] || (_cache[31] = [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-edit" }, null, -1 /* CACHED */) ]))], 8 /* PROPS */, _hoisted_9), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { class: "btn btn-sm btn-primary", onClick: $event => ($setup.assignRoles(user)) - }, [...(_cache[25] || (_cache[25] = [ + }, [...(_cache[32] || (_cache[32] = [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-user-shield" }, null, -1 /* CACHED */) ]))], 8 /* PROPS */, _hoisted_10), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { class: "btn btn-sm btn-danger", onClick: $event => ($setup.deleteUser(user.id)) - }, [...(_cache[26] || (_cache[26] = [ + }, [...(_cache[33] || (_cache[33] = [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-trash" }, null, -1 /* CACHED */) ]))], 8 /* PROPS */, _hoisted_11) ]) @@ -10597,62 +10800,111 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { ]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 分页 "), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_12, [ - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { - disabled: $setup.currentPage === 1, - onClick: _cache[7] || (_cache[7] = $event => ($setup.changePage($setup.currentPage - 1))), - class: "btn btn-sm" - }, _cache[28] || (_cache[28] = [ - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-chevron-left" }, null, -1 /* CACHED */), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" 上一页 ", -1 /* CACHED */) - ]), 8 /* PROPS */, _hoisted_13), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("span", _hoisted_14, " 第 " + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.currentPage) + " 页,共 " + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.totalPages) + " 页 ", 1 /* TEXT */), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { - disabled: $setup.currentPage === $setup.totalPages, - onClick: _cache[8] || (_cache[8] = $event => ($setup.changePage($setup.currentPage + 1))), - class: "btn btn-sm" - }, _cache[29] || (_cache[29] = [ - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" 下一页 ", -1 /* CACHED */), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-chevron-right" }, null, -1 /* CACHED */) - ]), 8 /* PROPS */, _hoisted_15) + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 分页导航 "), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_13, [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("a", { + class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['pagination-link', { disabled: $setup.currentPage === 1 }]), + onClick: _cache[7] || (_cache[7] = $event => ($setup.changePage(1))), + title: "首页" + }, _cache[35] || (_cache[35] = [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-angle-double-left" }, null, -1 /* CACHED */) + ]), 2 /* CLASS */), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("a", { + class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['pagination-link', { disabled: $setup.currentPage === 1 }]), + onClick: _cache[8] || (_cache[8] = $event => ($setup.changePage($setup.currentPage - 1))), + title: "上一页" + }, _cache[36] || (_cache[36] = [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-angle-left" }, null, -1 /* CACHED */) + ]), 2 /* CLASS */), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("span", _hoisted_14, " 第 " + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.currentPage) + " 页,共 " + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.totalPages) + " 页 (共 " + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.total) + " 条记录) ", 1 /* TEXT */), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("a", { + class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['pagination-link', { disabled: $setup.currentPage === $setup.totalPages }]), + onClick: _cache[9] || (_cache[9] = $event => ($setup.changePage($setup.currentPage + 1))), + title: "下一页" + }, _cache[37] || (_cache[37] = [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-angle-right" }, null, -1 /* CACHED */) + ]), 2 /* CLASS */), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("a", { + class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(['pagination-link', { disabled: $setup.currentPage === $setup.totalPages }]), + onClick: _cache[10] || (_cache[10] = $event => ($setup.changePage($setup.totalPages))), + title: "尾页" + }, _cache[38] || (_cache[38] = [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("i", { class: "fas fa-angle-double-right" }, null, -1 /* CACHED */) + ]), 2 /* CLASS */) + ]), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 分页设置 "), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_15, [ + _cache[42] || (_cache[42] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "每页显示:", -1 /* CACHED */)), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("select", { + "onUpdate:modelValue": _cache[11] || (_cache[11] = $event => (($setup.pageSize) = $event)), + onChange: _cache[12] || (_cache[12] = (...args) => ($setup.handlePageSizeChange && $setup.handlePageSizeChange(...args))) + }, _cache[39] || (_cache[39] = [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createStaticVNode)("", 5) + ]), 544 /* NEED_HYDRATION, NEED_PATCH */), [ + [vue__WEBPACK_IMPORTED_MODULE_0__.vModelSelect, $setup.pageSize] + ]), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_16, [ + _cache[40] || (_cache[40] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("span", null, "跳至", -1 /* CACHED */)), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", { + "onUpdate:modelValue": _cache[13] || (_cache[13] = $event => (($setup.jumpPage) = $event)), + type: "number", + min: "1", + max: $setup.totalPages, + onKeyup: _cache[14] || (_cache[14] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withKeys)((...args) => ($setup.handleJumpPage && $setup.handleJumpPage(...args)), ["enter"])), + placeholder: "页码" + }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_17), [ + [ + vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, + $setup.jumpPage, + void 0, + { number: true } + ] + ]), + _cache[41] || (_cache[41] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("span", null, "页", -1 /* CACHED */)), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { + onClick: _cache[15] || (_cache[15] = (...args) => ($setup.handleJumpPage && $setup.handleJumpPage(...args))) + }, "跳转") + ]) + ]) ]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 添加/编辑用户模态框 "), ($setup.showAddUserModal || $setup.showEditUserModal) ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", { key: 0, class: "modal-overlay", - onClick: _cache[18] || (_cache[18] = (...args) => ($setup.closeModal && $setup.closeModal(...args))) + onClick: _cache[25] || (_cache[25] = (...args) => ($setup.closeModal && $setup.closeModal(...args))) }, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", { class: "modal", - onClick: _cache[17] || (_cache[17] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)(() => {}, ["stop"])) + onClick: _cache[24] || (_cache[24] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)(() => {}, ["stop"])) }, [ - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_16, [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_18, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h3", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.showEditUserModal ? '编辑用户' : '添加用户'), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { class: "close-btn", - onClick: _cache[9] || (_cache[9] = (...args) => ($setup.closeModal && $setup.closeModal(...args))) + onClick: _cache[16] || (_cache[16] = (...args) => ($setup.closeModal && $setup.closeModal(...args))) }, "×") ]), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_17, [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_19, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("form", { - onSubmit: _cache[16] || (_cache[16] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)((...args) => ($setup.submitUser && $setup.submitUser(...args)), ["prevent"])) + onSubmit: _cache[23] || (_cache[23] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)((...args) => ($setup.submitUser && $setup.submitUser(...args)), ["prevent"])) }, [ - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_18, [ - _cache[30] || (_cache[30] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "用户名 *", -1 /* CACHED */)), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_20, [ + _cache[43] || (_cache[43] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "用户名 *", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", { - "onUpdate:modelValue": _cache[10] || (_cache[10] = $event => (($setup.userForm.username) = $event)), + "onUpdate:modelValue": _cache[17] || (_cache[17] = $event => (($setup.userForm.username) = $event)), type: "text", required: "", disabled: $setup.showEditUserModal - }, null, 8 /* PROPS */, _hoisted_19), [ + }, null, 8 /* PROPS */, _hoisted_21), [ [vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.userForm.username] ]) ]), (!$setup.showEditUserModal) - ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_20, [ - _cache[31] || (_cache[31] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "密码 *", -1 /* CACHED */)), + ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_22, [ + _cache[44] || (_cache[44] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "密码 *", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", { - "onUpdate:modelValue": _cache[11] || (_cache[11] = $event => (($setup.userForm.password) = $event)), + "onUpdate:modelValue": _cache[18] || (_cache[18] = $event => (($setup.userForm.password) = $event)), type: "password", required: "" }, null, 512 /* NEED_PATCH */), [ @@ -10660,43 +10912,43 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { ]) ])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_21, [ - _cache[32] || (_cache[32] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "邮箱 *", -1 /* CACHED */)), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_23, [ + _cache[45] || (_cache[45] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "邮箱 *", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", { - "onUpdate:modelValue": _cache[12] || (_cache[12] = $event => (($setup.userForm.email) = $event)), + "onUpdate:modelValue": _cache[19] || (_cache[19] = $event => (($setup.userForm.email) = $event)), type: "email", required: "" }, null, 512 /* NEED_PATCH */), [ [vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.userForm.email] ]) ]), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_22, [ - _cache[33] || (_cache[33] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "手机号", -1 /* CACHED */)), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_24, [ + _cache[46] || (_cache[46] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "手机号", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("input", { - "onUpdate:modelValue": _cache[13] || (_cache[13] = $event => (($setup.userForm.phone) = $event)), + "onUpdate:modelValue": _cache[20] || (_cache[20] = $event => (($setup.userForm.phone) = $event)), type: "tel" }, null, 512 /* NEED_PATCH */), [ [vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.userForm.phone] ]) ]), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_23, [ - _cache[35] || (_cache[35] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "状态", -1 /* CACHED */)), + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_25, [ + _cache[48] || (_cache[48] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("label", null, "状态", -1 /* CACHED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("select", { - "onUpdate:modelValue": _cache[14] || (_cache[14] = $event => (($setup.userForm.status) = $event)) - }, _cache[34] || (_cache[34] = [ + "onUpdate:modelValue": _cache[21] || (_cache[21] = $event => (($setup.userForm.status) = $event)) + }, _cache[47] || (_cache[47] = [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "1" }, "正常", -1 /* CACHED */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("option", { value: "2" }, "禁用", -1 /* CACHED */) ]), 512 /* NEED_PATCH */), [ [vue__WEBPACK_IMPORTED_MODULE_0__.vModelSelect, $setup.userForm.status] ]) ]), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_24, [ + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_26, [ (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", { type: "button", class: "btn btn-secondary", - onClick: _cache[15] || (_cache[15] = (...args) => ($setup.closeModal && $setup.closeModal(...args))) + onClick: _cache[22] || (_cache[22] = (...args) => ($setup.closeModal && $setup.closeModal(...args))) }, " 取消 "), - (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", _hoisted_25, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.showEditUserModal ? '更新' : '创建'), 1 /* TEXT */) + (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("button", _hoisted_27, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.showEditUserModal ? '更新' : '创建'), 1 /* TEXT */) ]) ], 32 /* NEED_HYDRATION */) ]) @@ -10706,7 +10958,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) { (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(" 角色分配对话框 "), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_UserRoleAssignment, { modelValue: $setup.showRoleAssignmentModal, - "onUpdate:modelValue": _cache[19] || (_cache[19] = $event => (($setup.showRoleAssignmentModal) = $event)), + "onUpdate:modelValue": _cache[26] || (_cache[26] = $event => (($setup.showRoleAssignmentModal) = $event)), user: $setup.selectedUser, onSaved: $setup.loadUsers }, null, 8 /* PROPS */, ["modelValue", "user", "onSaved"]) @@ -14808,7 +15060,7 @@ __webpack_require__.r(__webpack_exports__); /******/ /******/ /* webpack/runtime/getFullHash */ /******/ (() => { -/******/ __webpack_require__.h = () => ("46c51ec3a05924ce") +/******/ __webpack_require__.h = () => ("66bc1119729d1861") /******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ diff --git a/gofaster/app/src/renderer/assets/README-COMMON-STYLES.md b/gofaster/app/src/renderer/assets/README-COMMON-STYLES.md index 58c5ec4..cbc2c58 100644 --- a/gofaster/app/src/renderer/assets/README-COMMON-STYLES.md +++ b/gofaster/app/src/renderer/assets/README-COMMON-STYLES.md @@ -42,8 +42,17 @@ - 表格操作按钮的特殊样式 ### 7. 分页样式 -- `.pagination` - 分页容器 +- `.pagination` - 分页容器(总是显示,包含卡片样式) +- `.pagination-nav` - 分页导航区域 +- `.pagination-link` - 分页链接样式(超链接样式,非按钮) - `.page-info` - 页码信息 +- `.pagination-settings` - 分页设置区域 +- `.page-jump` - 页面跳转输入框 +- **功能特性**: + - 首页、上一页、下一页、尾页导航 + - 每页记录数设置(10、30、50、100、500) + - 跳转至指定页面 + - 超链接样式,支持主题适配 ### 8. 页面头部和卡片样式(统一) - `.page-header`, `.profile-header` - 页面头部统一样式 @@ -53,6 +62,7 @@ - `.info-item`, `.setting-item` - 字段项统一样式 - `.info-item label`, `.setting-item label` - 字段标签统一样式 - `.profile-actions`, `.settings-actions` - 操作按钮区域统一样式 +- **图标样式**:页面标题和分组标题中的图标使用 `var(--accent-color)` 颜色,浅色主题为蓝色,深色主题为白色 ### 9. 模态框样式 - `.modal-overlay` - 模态框遮罩 diff --git a/gofaster/app/src/renderer/assets/common-styles.css b/gofaster/app/src/renderer/assets/common-styles.css index 619a233..8c3e712 100644 --- a/gofaster/app/src/renderer/assets/common-styles.css +++ b/gofaster/app/src/renderer/assets/common-styles.css @@ -39,7 +39,7 @@ .setting-item input[type="number"], .setting-item select { width: 100%; - padding: 8px 12px; + padding: 4px 12px; border: 1px solid var(--input-border); border-radius: 6px; font-size: 12px; @@ -240,11 +240,122 @@ th { justify-content: center; align-items: center; gap: 20px; + margin-top: 16px; } .page-info { - color: #666; - font-size: 14px; + color: var(--text-secondary); + font-size: 12px; + margin: 0 15px; +} + +/* 分页导航链接样式 */ +.pagination-nav { + display: flex; + align-items: center; + gap: 8px; +} + +.pagination-link { + color: var(--accent-color); + text-decoration: none; + padding: 4px 8px; + border-radius: 4px; + font-size: 12px; + transition: all 0.2s; + cursor: pointer; +} + +.pagination-link:hover { + background: var(--bg-secondary); + color: var(--accent-hover); +} + +.pagination-link.disabled { + color: var(--text-muted); + cursor: not-allowed; + pointer-events: none; +} + +.pagination-link.active { + background: var(--accent-color); + color: white; +} + +/* 分页设置区域 */ +.pagination-settings { + display: flex; + align-items: center; + gap: 10px; + margin-left: 20px; +} + +.pagination-settings label { + font-size: 12px; + color: var(--text-secondary); + margin: 0; +} + +.pagination-settings select { + padding: 4px 8px; + border: 1px solid var(--input-border); + border-radius: 4px; + font-size: 12px; + background-color: var(--input-bg); + color: var(--input-text); + min-width: 60px; +} + +.pagination-settings select:focus { + outline: none; + border-color: var(--accent-color); + box-shadow: 0 0 0 2px rgba(74, 158, 255, 0.2); +} + +/* 跳转页面输入框 */ +.page-jump { + display: flex; + align-items: center; + gap: 5px; + font-size: 12px; +} + +.page-jump span { + font-size: 12px; + color: var(--text-secondary); +} + +.page-jump input { + width: 50px; + padding: 4px 8px; + border: 1px solid var(--input-border); + border-radius: 4px; + font-size: 12px; + background-color: var(--input-bg); + color: var(--input-text); + text-align: center; +} + +.page-jump input:focus { + outline: none; + border-color: var(--accent-color); + box-shadow: 0 0 0 2px rgba(74, 158, 255, 0.2); +} + +.page-jump button { + color: var(--accent-color); + background: none; + border: none; + font-size: 12px; + cursor: pointer; + padding: 4px 8px; + border-radius: 4px; + transition: all 0.2s; +} + +.page-jump button:hover { + background: var(--bg-secondary); + color: var(--accent-hover); } /* 分页按钮字体大小统一 */ @@ -263,7 +374,7 @@ th { .page-header, .profile-header { text-align: center; - margin-bottom: 26px; + margin-bottom: 32px; } .page-header h2, @@ -299,11 +410,11 @@ th { /* 卡片头部 - 统一样式 */ .card-header, .settings-section h3 { - margin: 0 0 16px 0; + margin: 0 0 20px 0; color: var(--text-primary); font-size: 14px; border-bottom: 2px solid var(--border-color); - padding-bottom: 8px; + padding-bottom: 12px; } .card-header h2, @@ -313,6 +424,16 @@ th { color: var(--text-primary); } +/* 页面标题和分组标题图标样式 - 统一样式 */ +.page-header h2 i, +.profile-header h1 i, +.card-header h2 i, +.settings-section h3 i { + margin-right: 8px; + color: var(--accent-color); + font-size: 0.9em; +} + /* 信息网格 */ .info-grid { display: flex; @@ -326,8 +447,9 @@ th { display: flex; align-items: center; justify-content: space-between; - margin-bottom: 16px; - padding: 12px 0; + margin-top: 6px; + margin-bottom: 6px; + padding: 6px 0; border-bottom: 1px solid #f5f5f5; } @@ -419,7 +541,7 @@ th { display: flex; gap: 16px; justify-content: flex-end; - margin-top: 26px; + margin-top: 32px; } /* ===== 模态框样式 ===== */ diff --git a/gofaster/app/src/renderer/modules/role-management/views/RoleManagement.vue b/gofaster/app/src/renderer/modules/role-management/views/RoleManagement.vue index 71fbcf7..52fa2cf 100644 --- a/gofaster/app/src/renderer/modules/role-management/views/RoleManagement.vue +++ b/gofaster/app/src/renderer/modules/role-management/views/RoleManagement.vue @@ -69,25 +69,72 @@ -