Browse Source

样式统一基本完成

master
hejl 6 days ago
parent
commit
2e972a4902
  1. 25
      gofaster/add-test-roles.sql
  2. 542
      gofaster/app/dist/renderer/js/index.js
  3. 12
      gofaster/app/src/renderer/assets/README-COMMON-STYLES.md
  4. 140
      gofaster/app/src/renderer/assets/common-styles.css
  5. 108
      gofaster/app/src/renderer/modules/role-management/views/RoleManagement.vue
  6. 8
      gofaster/app/src/renderer/modules/system-settings/views/Settings.vue
  7. 99
      gofaster/app/src/renderer/modules/user-management/views/UserManagement.vue
  8. 28
      gofaster/check-role-data.sql
  9. 166
      gofaster/test-icon-styles.html
  10. 48
      gofaster/test-role-data.ps1

25
gofaster/add-test-roles.sql

@ -0,0 +1,25 @@ @@ -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;

542
gofaster/app/dist/renderer/js/index.js vendored

@ -2243,13 +2243,7 @@ ___CSS_LOADER_EXPORT___.push([module.id, ` @@ -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, `/* ===== 通用管理页面样式 ==== @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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__); @@ -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__); @@ -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__); @@ -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__); @@ -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__); @@ -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__); @@ -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__); @@ -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__); @@ -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__); @@ -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" } @@ -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) { @@ -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) { @@ -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) { @@ -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) { @@ -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) { @@ -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)("<option value=\"10\" data-v-03643bfa>10</option><option value=\"30\" data-v-03643bfa>30</option><option value=\"50\" data-v-03643bfa>50</option><option value=\"100\" data-v-03643bfa>100</option><option value=\"500\" data-v-03643bfa>500</option>", 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) { @@ -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) { @@ -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) { @@ -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"] @@ -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) { @@ -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) { @@ -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) { @@ -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) { @@ -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) { @@ -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) { @@ -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) { @@ -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)("<option value=\"10\" data-v-7889d364>10</option><option value=\"30\" data-v-7889d364>30</option><option value=\"50\" data-v-7889d364>50</option><option value=\"100\" data-v-7889d364>100</option><option value=\"500\" data-v-7889d364>500</option>", 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) { @@ -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) { @@ -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__); @@ -14808,7 +15060,7 @@ __webpack_require__.r(__webpack_exports__);
/******/
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("46c51ec3a05924ce")
/******/ __webpack_require__.h = () => ("66bc1119729d1861")
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */

12
gofaster/app/src/renderer/assets/README-COMMON-STYLES.md

@ -42,8 +42,17 @@ @@ -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 @@ @@ -53,6 +62,7 @@
- `.info-item`, `.setting-item` - 字段项统一样式
- `.info-item label`, `.setting-item label` - 字段标签统一样式
- `.profile-actions`, `.settings-actions` - 操作按钮区域统一样式
- **图标样式**:页面标题和分组标题中的图标使用 `var(--accent-color)` 颜色,浅色主题为蓝色,深色主题为白色
### 9. 模态框样式
- `.modal-overlay` - 模态框遮罩

140
gofaster/app/src/renderer/assets/common-styles.css

@ -39,7 +39,7 @@ @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -419,7 +541,7 @@ th {
display: flex;
gap: 16px;
justify-content: flex-end;
margin-top: 26px;
margin-top: 32px;
}
/* ===== 模态框样式 ===== */

108
gofaster/app/src/renderer/modules/role-management/views/RoleManagement.vue

@ -69,25 +69,72 @@ @@ -69,25 +69,72 @@
</div>
<!-- 分页 -->
<div v-if="total > pageSize" class="pagination">
<button
:disabled="currentPage === 1"
@click="handleCurrentChange(currentPage - 1)"
class="btn btn-sm"
>
<i class="fas fa-chevron-left"></i> 上一页
</button>
<span class="page-info">
{{ currentPage }} {{ Math.ceil(total / pageSize) }}
</span>
<button
:disabled="currentPage >= Math.ceil(total / pageSize)"
@click="handleCurrentChange(currentPage + 1)"
class="btn btn-sm"
>
下一页 <i class="fas fa-chevron-right"></i>
</button>
<div class="pagination">
<!-- 分页导航 -->
<div class="pagination-nav">
<a
:class="['pagination-link', { disabled: currentPage === 1 }]"
@click="handleCurrentChange(1)"
title="首页"
>
<i class="fas fa-angle-double-left"></i>
</a>
<a
:class="['pagination-link', { disabled: currentPage === 1 }]"
@click="handleCurrentChange(currentPage - 1)"
title="上一页"
>
<i class="fas fa-angle-left"></i>
</a>
<span class="page-info">
{{ currentPage }} {{ Math.ceil(total / pageSize) }} ( {{ total }} 条记录)
</span>
<a
:class="['pagination-link', { disabled: currentPage >= Math.ceil(total / pageSize) }]"
@click="handleCurrentChange(currentPage + 1)"
title="下一页"
>
<i class="fas fa-angle-right"></i>
</a>
<a
:class="['pagination-link', { disabled: currentPage >= Math.ceil(total / pageSize) }]"
@click="handleCurrentChange(Math.ceil(total / pageSize))"
title="尾页"
>
<i class="fas fa-angle-double-right"></i>
</a>
</div>
<!-- 分页设置 -->
<div class="pagination-settings">
<label>每页显示:</label>
<select v-model="pageSize" @change="handlePageSizeChange">
<option value="10">10</option>
<option value="30">30</option>
<option value="50">50</option>
<option value="100">100</option>
<option value="500">500</option>
</select>
<div class="page-jump">
<span>跳至</span>
<input
v-model.number="jumpPage"
type="number"
min="1"
:max="Math.ceil(total / pageSize)"
@keyup.enter="handleJumpPage"
placeholder="页码"
/>
<span></span>
<button @click="handleJumpPage">跳转</button>
</div>
</div>
</div>
<!-- 创建/编辑角色对话框 -->
<div v-if="showCreateDialog" class="modal-overlay" @click="showCreateDialog = false">
@ -171,6 +218,7 @@ export default { @@ -171,6 +218,7 @@ export default {
const pageSize = ref(10)
const total = ref(0)
const searchQuery = ref('')
const jumpPage = ref('')
const roleForm = reactive({
name: '',
@ -211,7 +259,9 @@ export default { @@ -211,7 +259,9 @@ export default {
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)
@ -307,10 +357,25 @@ export default { @@ -307,10 +357,25 @@ export default {
//
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 ''
@ -345,6 +410,7 @@ export default { @@ -345,6 +410,7 @@ export default {
pageSize,
total,
searchQuery,
jumpPage,
roleForm,
filteredRoles,
createNewRole,
@ -354,6 +420,8 @@ export default { @@ -354,6 +420,8 @@ export default {
assignPermissions,
handlePermissionsUpdated,
handleCurrentChange,
handlePageSizeChange,
handleJumpPage,
handleSearch,
formatDate
}

8
gofaster/app/src/renderer/modules/system-settings/views/Settings.vue

@ -334,13 +334,7 @@ export default { @@ -334,13 +334,7 @@ export default {
max-width: 800px;
}
/* 设置标题图标样式 */
.page-header h2 i,
.settings-section h3 i {
margin-right: 8px;
color: var(--accent-color);
font-size: 0.9em;
}

99
gofaster/app/src/renderer/modules/user-management/views/UserManagement.vue

@ -83,23 +83,68 @@ @@ -83,23 +83,68 @@
<!-- 分页 -->
<div class="pagination">
<button
:disabled="currentPage === 1"
@click="changePage(currentPage - 1)"
class="btn btn-sm"
>
<i class="fas fa-chevron-left"></i> 上一页
</button>
<span class="page-info">
{{ currentPage }} {{ totalPages }}
</span>
<button
:disabled="currentPage === totalPages"
@click="changePage(currentPage + 1)"
class="btn btn-sm"
>
下一页 <i class="fas fa-chevron-right"></i>
</button>
<!-- 分页导航 -->
<div class="pagination-nav">
<a
:class="['pagination-link', { disabled: currentPage === 1 }]"
@click="changePage(1)"
title="首页"
>
<i class="fas fa-angle-double-left"></i>
</a>
<a
:class="['pagination-link', { disabled: currentPage === 1 }]"
@click="changePage(currentPage - 1)"
title="上一页"
>
<i class="fas fa-angle-left"></i>
</a>
<span class="page-info">
{{ currentPage }} {{ totalPages }} ( {{ total }} 条记录)
</span>
<a
:class="['pagination-link', { disabled: currentPage === totalPages }]"
@click="changePage(currentPage + 1)"
title="下一页"
>
<i class="fas fa-angle-right"></i>
</a>
<a
:class="['pagination-link', { disabled: currentPage === totalPages }]"
@click="changePage(totalPages)"
title="尾页"
>
<i class="fas fa-angle-double-right"></i>
</a>
</div>
<!-- 分页设置 -->
<div class="pagination-settings">
<label>每页显示:</label>
<select v-model="pageSize" @change="handlePageSizeChange">
<option value="10">10</option>
<option value="30">30</option>
<option value="50">50</option>
<option value="100">100</option>
<option value="500">500</option>
</select>
<div class="page-jump">
<span>跳至</span>
<input
v-model.number="jumpPage"
type="number"
min="1"
:max="totalPages"
@keyup.enter="handleJumpPage"
placeholder="页码"
/>
<span></span>
<button @click="handleJumpPage">跳转</button>
</div>
</div>
</div>
<!-- 添加/编辑用户模态框 -->
@ -193,6 +238,7 @@ export default { @@ -193,6 +238,7 @@ export default {
const searchQuery = ref('')
const statusFilter = ref('')
const roleFilter = ref('')
const jumpPage = ref('')
const showAddUserModal = ref(false)
const showEditUserModal = ref(false)
@ -276,10 +322,24 @@ export default { @@ -276,10 +322,24 @@ export default {
}
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, {
@ -357,6 +417,7 @@ export default { @@ -357,6 +417,7 @@ export default {
searchQuery,
statusFilter,
roleFilter,
jumpPage,
showAddUserModal,
showEditUserModal,
showRoleAssignmentModal,
@ -370,6 +431,8 @@ export default { @@ -370,6 +431,8 @@ export default {
handleSearch,
handleFilter,
changePage,
handlePageSizeChange,
handleJumpPage,
editUser,
submitUser,
deleteUser,

28
gofaster/check-role-data.sql

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
-- 检查角色表中的数据
SELECT
COUNT(*) as total_roles,
MIN(id) as min_id,
MAX(id) as max_id
FROM roles;
-- 查看所有角色数据
SELECT
id,
name,
code,
description,
created_at,
updated_at
FROM roles
ORDER BY id ASC
LIMIT 20;
-- 检查是否有足够的角色数据来测试分页
SELECT
CASE
WHEN COUNT(*) > 10 THEN '有足够数据测试分页'
WHEN COUNT(*) > 0 THEN '数据不足,需要添加更多角色'
ELSE '没有角色数据'
END as data_status,
COUNT(*) as role_count
FROM roles;

166
gofaster/test-icon-styles.html

@ -0,0 +1,166 @@ @@ -0,0 +1,166 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图标样式测试</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
/* 模拟主题变量 */
:root {
--accent-color: #1976d2;
--text-primary: #333333;
}
.theme-dark {
--accent-color: #ffffff;
--text-primary: #ffffff;
}
/* 图标样式 */
.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;
}
/* 页面样式 */
body {
font-family: Arial, sans-serif;
margin: 20px;
background: #f5f5f5;
}
.theme-dark {
background: #2d4a8a;
color: white;
}
.test-container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.theme-dark .test-container {
background: rgba(255, 255, 255, 0.08);
}
.page-header {
text-align: center;
margin-bottom: 30px;
}
.page-header h2 {
font-size: 16px;
color: var(--text-primary);
margin: 0;
}
.settings-section {
margin-bottom: 20px;
padding: 20px;
border: 1px solid #e0e0e0;
border-radius: 8px;
}
.theme-dark .settings-section {
border-color: rgba(255, 255, 255, 0.2);
}
.settings-section h3 {
font-size: 14px;
color: var(--text-primary);
margin: 0 0 16px 0;
border-bottom: 2px solid #e0e0e0;
padding-bottom: 8px;
}
.theme-dark .settings-section h3 {
border-bottom-color: rgba(255, 255, 255, 0.2);
}
.theme-toggle {
position: fixed;
top: 20px;
right: 20px;
padding: 10px 20px;
background: #1976d2;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.theme-toggle:hover {
background: #1565c0;
}
</style>
</head>
<body>
<button class="theme-toggle" onclick="toggleTheme()">切换主题</button>
<div class="test-container">
<div class="page-header">
<h2><i class="fas fa-user"></i> 个人资料</h2>
</div>
<div class="settings-section">
<h3><i class="fas fa-info-circle"></i> 基本信息</h3>
<p>这是基本信息部分的内容</p>
</div>
<div class="settings-section">
<h3><i class="fas fa-lock"></i> 登录信息</h3>
<p>这是登录信息部分的内容</p>
</div>
<div class="settings-section">
<h3><i class="fas fa-crown"></i> 角色信息</h3>
<p>这是角色信息部分的内容</p>
</div>
<div class="settings-section">
<h3><i class="fas fa-cog"></i> 用户设置</h3>
<p>这是用户设置部分的内容</p>
</div>
<div class="settings-section">
<h3><i class="fas fa-user-cog"></i> 个人偏好</h3>
<p>这是个人偏好部分的内容</p>
</div>
<div class="settings-section">
<h3><i class="fas fa-tools"></i> 应用设置</h3>
<p>这是应用设置部分的内容</p>
</div>
<div class="settings-section">
<h3><i class="fas fa-user-shield"></i> 用户设置</h3>
<p>这是用户设置部分的内容</p>
</div>
<div class="settings-section">
<h3><i class="fas fa-bell"></i> 通知偏好</h3>
<p>这是通知偏好部分的内容</p>
</div>
<div class="settings-section">
<h3><i class="fas fa-database"></i> 数据管理</h3>
<p>这是数据管理部分的内容</p>
</div>
</div>
<script>
function toggleTheme() {
document.body.classList.toggle('theme-dark');
}
</script>
</body>
</html>

48
gofaster/test-role-data.ps1

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
# 测试角色管理API分页功能
Write-Host "🔍 测试角色管理API分页功能..." -ForegroundColor Green
# 测试获取角色列表(第1页,每页10条)
Write-Host "`n📋 测试获取角色列表(第1页,每页10条)..." -ForegroundColor Yellow
$response1 = Invoke-RestMethod -Uri "http://localhost:8080/auth/roles?page=1&pageSize=10" -Method GET -Headers @{
"Authorization" = "Bearer your-token-here"
"Content-Type" = "application/json"
} -ErrorAction SilentlyContinue
if ($response1) {
Write-Host "✅ 响应成功:" -ForegroundColor Green
Write-Host " Code: $($response1.code)"
Write-Host " Message: $($response1.message)"
if ($response1.data) {
Write-Host " Data:" -ForegroundColor Cyan
Write-Host " Total: $($response1.data.total)"
Write-Host " Page: $($response1.data.page)"
Write-Host " Size: $($response1.data.size)"
Write-Host " Records: $($response1.data.data.Count)"
}
} else {
Write-Host "❌ 请求失败或没有响应" -ForegroundColor Red
}
# 测试获取角色列表(第2页,每页5条)
Write-Host "`n📋 测试获取角色列表(第2页,每页5条)..." -ForegroundColor Yellow
$response2 = Invoke-RestMethod -Uri "http://localhost:8080/auth/roles?page=2&pageSize=5" -Method GET -Headers @{
"Authorization" = "Bearer your-token-here"
"Content-Type" = "application/json"
} -ErrorAction SilentlyContinue
if ($response2) {
Write-Host "✅ 响应成功:" -ForegroundColor Green
Write-Host " Code: $($response2.code)"
Write-Host " Message: $($response2.message)"
if ($response2.data) {
Write-Host " Data:" -ForegroundColor Cyan
Write-Host " Total: $($response2.data.total)"
Write-Host " Page: $($response2.data.page)"
Write-Host " Size: $($response2.data.size)"
Write-Host " Records: $($response2.data.data.Count)"
}
} else {
Write-Host "❌ 请求失败或没有响应" -ForegroundColor Red
}
Write-Host "`n🔍 测试完成!" -ForegroundColor Green
Loading…
Cancel
Save