完善全局样式

This commit is contained in:
2026-04-28 16:52:22 +08:00
parent 6eca9768cc
commit 539889a346
5 changed files with 367 additions and 208 deletions

View File

@@ -128,7 +128,7 @@ redisson:
singleServerConfig: singleServerConfig:
# 客户端名称 # 客户端名称
clientName: ${ruoyi.name} clientName: ${ruoyi.name}
# 最小空闲连接数 # 最小空闲连接数ACT_ID_PROPERTY
connectionMinimumIdleSize: 32 connectionMinimumIdleSize: 32
# 连接池大小 # 连接池大小
connectionPoolSize: 64 connectionPoolSize: 64

View File

@@ -101,25 +101,9 @@
border-radius: 4px; border-radius: 4px;
} }
:global(.el-button) { /* 按钮结构样式(颜色逻辑统一在 index.scss 管理) */
color: #fff !important; .el-button {
} border-radius: 4px !important;
font-weight: 600 !important;
:global(.el-button > span), letter-spacing: 0.4px !important;
:global(.el-button > span *) ,
:global(.el-button .svg-icon),
:global(.el-button i) {
color: inherit !important;
fill: currentColor;
}
:global(.el-button--default) {
color: var(--app-primary) !important;
}
:global(.el-button--default > span),
:global(.el-button--default > span *),
:global(.el-button--default .svg-icon),
:global(.el-button--default i) {
color: inherit !important;
} }

View File

@@ -53,63 +53,45 @@ body {
// ====================== 5. 组件尺寸样式(按优先级合并)====================== // ====================== 5. 组件尺寸样式(按优先级合并)======================
// ---------------------- 5.1 按钮(紧凑尺寸)---------------------- // ---------------------- 5.1 按钮(紧凑尺寸)----------------------
@mixin button-variant() { @mixin button-variant() {
border-radius: 6px; border-radius: 4px;
transition: all .25s ease; transition: background .15s ease, border-color .15s ease, box-shadow .15s ease;
height: $--btn-height; height: $--btn-height;
padding: 0 var(--spacing-lg); padding: 0 var(--spacing-lg);
font-size: 13px; font-size: 13px;
font-weight: 600;
letter-spacing: 0.4px;
&:hover, &:hover,
&:focus { &:focus {
transform: translateY(-1px); box-shadow: inset 0 0 0 1px rgba(255,255,255,0.15);
} }
&:active { &:active {
transform: translateY(1px); filter: brightness(0.88);
} }
&.is-disabled, &.is-disabled,
&[disabled] { &[disabled] {
cursor: not-allowed; cursor: not-allowed;
opacity: 0.55;
} }
} }
// 主按钮(尺寸相关 // 各类型按钮统一套 mixin颜色由 index.scss CSS变量控制
.el-button--primary { .el-button--primary,
@include button-variant();
background: $industrial-primary;
border-color: $industrial-primary;
color: #fff !important;
&:hover,
&:focus {
background: $industrial-secondary;
border-color: $industrial-secondary;
color: #fff !important;
}
}
// 功能按钮(尺寸相关)
.el-button--success, .el-button--success,
.el-button--danger, .el-button--danger,
.el-button--info { .el-button--info,
@include button-variant();
}
.el-button--warning { .el-button--warning {
@include button-variant(); @include button-variant();
color: #1c2b3a !important;
&:hover,
&:focus {
color: #1c2b3a !important;
}
} }
// 文本按钮(尺寸相关) // 文本/Link按钮
.el-button--text { .el-button--text,
.el-button.is-text {
height: auto; height: auto;
padding: 4px 8px; padding: 2px 6px;
border-radius: 4px !important;
} }
// 图标按钮(圆形紧凑尺寸) // 图标按钮(圆形紧凑尺寸)

View File

@@ -219,49 +219,89 @@ aside {
} }
.el-button { .el-button {
--el-button-disabled-text-color: rgba(255, 255, 255, 0.72); /* 不在此设全局 color由各类型规则单独控制 */
color: #ffffff;
} }
.el-button__text, .el-button > span,
.el-button span,
.el-button .svg-icon, .el-button .svg-icon,
.el-button i { .el-button i {
color: inherit; color: inherit;
fill: currentColor;
} }
.el-button--default { /* ════════════════════════════════════════════
--el-button-text-color: var(--app-primary); 按钮色彩系统
color: var(--app-primary); 实心按钮 → 白字
Plain变体 → 浅底色 + 比边框更深的文字
Link/Text变体 → 透明底 + 各类型色文字
════════════════════════════════════════════ */
/* 子元素颜色继承 */
.el-button > span,
.el-button .svg-icon,
.el-button i {
color: inherit !important;
fill: currentColor;
} }
.el-button--default .el-button__text, /* ── Default白底工业蓝描边 ── */
.el-button--default span, .el-button--default:not(.is-link):not(.is-text) {
.el-button--default .svg-icon, color: #1d4e89 !important;
.el-button--default i {
color: inherit;
} }
.el-button--default.is-link,
.el-button--default.is-text,
.el-button--text { .el-button--text {
--el-button-text-color: var(--app-primary); color: #1d4e89 !important;
color: var(--app-primary); background: transparent !important;
background: transparent; border-color: transparent !important;
border-color: transparent;
padding: 0 4px;
} }
.el-button--text:hover, /* ── Primary ── */
.el-button--text:focus { .el-button.el-button--primary:not(.is-plain):not(.is-link):not(.is-text) { color: #ffffff !important; }
color: var(--app-secondary); .el-button.el-button--primary.is-plain { color: #122f55 !important; }
background: transparent; .el-button.el-button--primary.is-link,
border-color: transparent; .el-button.el-button--primary.is-text { color: #1d4e89 !important; background: transparent !important; border-color: transparent !important; }
} .el-button.el-button--primary.is-link:hover,
.el-button.el-button--primary.is-text:hover { color: #2471a3 !important; }
.el-button--text .el-button__text, /* ── Success ── */
.el-button--text span, .el-button.el-button--success:not(.is-plain):not(.is-link):not(.is-text) { color: #ffffff !important; }
.el-button--text .svg-icon, .el-button.el-button--success.is-plain { color: #1b5e20 !important; }
.el-button--text i { .el-button.el-button--success.is-link,
color: inherit; .el-button.el-button--success.is-text { color: #388e3c !important; background: transparent !important; border-color: transparent !important; }
.el-button.el-button--success.is-link:hover,
.el-button.el-button--success.is-text:hover { color: #2e7d32 !important; }
/* ── Warning ── */
.el-button.el-button--warning:not(.is-plain):not(.is-link):not(.is-text) { color: #ffffff !important; }
.el-button.el-button--warning.is-plain { color: #7f3300 !important; }
.el-button.el-button--warning.is-link,
.el-button.el-button--warning.is-text { color: #e65100 !important; background: transparent !important; border-color: transparent !important; }
.el-button.el-button--warning.is-link:hover,
.el-button.el-button--warning.is-text:hover { color: #f57c00 !important; }
/* ── Danger ── */
.el-button.el-button--danger:not(.is-plain):not(.is-link):not(.is-text) { color: #ffffff !important; }
.el-button.el-button--danger.is-plain { color: #7f0000 !important; }
.el-button.el-button--danger.is-link,
.el-button.el-button--danger.is-text { color: #c62828 !important; background: transparent !important; border-color: transparent !important; }
.el-button.el-button--danger.is-link:hover,
.el-button.el-button--danger.is-text:hover { color: #e53935 !important; }
/* ── Info ── */
.el-button.el-button--info:not(.is-plain):not(.is-link):not(.is-text) { color: #ffffff !important; }
.el-button.el-button--info.is-plain { color: #263238 !important; }
.el-button.el-button--info.is-link,
.el-button.el-button--info.is-text { color: #455a64 !important; background: transparent !important; border-color: transparent !important; }
.el-button.el-button--info.is-link:hover,
.el-button.el-button--info.is-text:hover { color: #37474f !important; }
/* ── Link / Text hover 通用背景 ── */
.el-button.is-link:hover,
.el-button.is-text:hover,
.el-button--text:hover {
background: rgba(0, 0, 0, 0.04) !important;
border-color: transparent !important;
} }
.el-card__header { .el-card__header {
@@ -278,65 +318,97 @@ aside {
--el-table-row-hover-bg-color: #f7fbff; --el-table-row-hover-bg-color: #f7fbff;
} }
.el-button--primary, /* ── Element Plus CSS变量 → 各类型独立色彩系统 ── */
.el-button--success,
.el-button--danger,
.el-button--info {
--el-button-text-color: #fff;
--el-button-disabled-text-color: rgba(255, 255, 255, 0.72);
}
.el-button--warning {
--el-button-text-color: #ffffff;
--el-button-disabled-text-color: rgba(255, 255, 255, 0.72);
--el-button-bg-color: var(--app-warning);
--el-button-border-color: var(--app-warning);
--el-button-hover-bg-color: #e09a1b;
--el-button-hover-border-color: #e09a1b;
--el-button-active-bg-color: #c97f0f;
--el-button-active-border-color: #c97f0f;
color: #ffffff;
}
.el-button--warning.is-plain {
--el-button-text-color: #d68910;
--el-button-border-color: #f0c674;
--el-button-bg-color: #fff6e5;
--el-button-hover-text-color: #d68910;
--el-button-hover-bg-color: #fff0d6;
--el-button-hover-border-color: #d68910;
--el-button-active-text-color: #c97f0f;
--el-button-active-border-color: #c97f0f;
color: #d68910;
}
.el-button--primary { .el-button--primary {
--el-button-bg-color: #1d4e89; --el-button-bg-color: #1d4e89;
--el-button-border-color: #1d4e89; --el-button-border-color: #1d4e89;
--el-button-hover-bg-color: #2471a3; --el-button-hover-bg-color: #2471a3;
--el-button-hover-border-color: #2471a3; --el-button-hover-border-color: #2471a3;
--el-button-active-bg-color: #1c2b3a; --el-button-active-bg-color: #163a68;
--el-button-active-border-color: #1c2b3a; --el-button-active-border-color: #163a68;
--el-button-disabled-bg-color: #6b96c4;
--el-button-disabled-border-color: #6b96c4;
--el-button-text-color: #fff;
--el-button-disabled-text-color: rgba(255,255,255,.6);
}
.el-button--primary.is-plain {
--el-button-bg-color: #e8f0fb;
--el-button-border-color: #1d4e89;
--el-button-hover-bg-color: #d4e4f7;
--el-button-hover-border-color: #2471a3;
--el-button-text-color: #122f55;
} }
.el-button--success { .el-button--success {
--el-button-bg-color: #4b8b3b; --el-button-bg-color: #388e3c;
--el-button-border-color: #4b8b3b; --el-button-border-color: #388e3c;
--el-button-hover-bg-color: #2e7d32;
--el-button-hover-border-color: #2e7d32;
--el-button-active-bg-color: #1b5e20;
--el-button-active-border-color: #1b5e20;
--el-button-text-color: #fff;
--el-button-disabled-text-color: rgba(255,255,255,.6);
}
.el-button--success.is-plain {
--el-button-bg-color: #e8f5e9;
--el-button-border-color: #388e3c;
--el-button-hover-bg-color: #d4edda;
--el-button-hover-border-color: #2e7d32;
--el-button-text-color: #1b5e20;
} }
.el-button--warning { .el-button--warning {
--el-button-bg-color: #d68910; --el-button-bg-color: #f57c00;
--el-button-border-color: #d68910; --el-button-border-color: #f57c00;
--el-button-hover-bg-color: #e65100;
--el-button-hover-border-color: #e65100;
--el-button-active-bg-color: #bf360c;
--el-button-active-border-color: #bf360c;
--el-button-text-color: #fff;
--el-button-disabled-text-color: rgba(255,255,255,.6);
}
.el-button--warning.is-plain {
--el-button-bg-color: #fff3e0;
--el-button-border-color: #f57c00;
--el-button-hover-bg-color: #ffe0b2;
--el-button-hover-border-color: #e65100;
--el-button-text-color: #bf360c;
} }
.el-button--danger { .el-button--danger {
--el-button-bg-color: #c0392b; --el-button-bg-color: #c62828;
--el-button-border-color: #c0392b; --el-button-border-color: #c62828;
--el-button-hover-bg-color: #b71c1c;
--el-button-hover-border-color: #b71c1c;
--el-button-active-bg-color: #8b0000;
--el-button-active-border-color: #8b0000;
--el-button-text-color: #fff;
--el-button-disabled-text-color: rgba(255,255,255,.6);
}
.el-button--danger.is-plain {
--el-button-bg-color: #ffebee;
--el-button-border-color: #c62828;
--el-button-hover-bg-color: #ffcdd2;
--el-button-hover-border-color: #b71c1c;
--el-button-text-color: #8b0000;
} }
.el-button--info { .el-button--info {
--el-button-bg-color: #1c2b3a; --el-button-bg-color: #455a64;
--el-button-border-color: #1c2b3a; --el-button-border-color: #455a64;
--el-button-hover-bg-color: #37474f;
--el-button-hover-border-color: #37474f;
--el-button-active-bg-color: #263238;
--el-button-active-border-color: #263238;
--el-button-text-color: #fff;
--el-button-disabled-text-color: rgba(255,255,255,.6);
}
.el-button--info.is-plain {
--el-button-bg-color: #eceff1;
--el-button-border-color: #455a64;
--el-button-hover-bg-color: #cfd8dc;
--el-button-hover-border-color: #37474f;
--el-button-text-color: #263238;
} }
.el-tag--success { .el-tag--success {

View File

@@ -1,16 +1,31 @@
<template> <template>
<div :class="{ 'hidden': hidden }" class="pagination-container"> <div v-if="!hidden" class="gear-pagination">
<el-pagination <span class="gear-pg-info"> <b>{{ total }}</b> </span>
:background="background"
v-model:current-page="currentPage" <select v-model="pageSize" class="gear-pg-select" @change="handleSizeChange">
v-model:page-size="pageSize" <option v-for="s in pageSizes" :key="s" :value="s">{{ s }}/</option>
:layout="layout" </select>
:page-sizes="pageSizes"
:pager-count="pagerCount" <div class="gear-pg-pager">
:total="total" <button class="gear-pg-btn gear-pg-nav" :disabled="currentPage <= 1" @click="changePage(currentPage - 1)">
@size-change="handleSizeChange" <svg width="8" height="8" viewBox="0 0 8 8" fill="none"><path d="M5.5 1L2.5 4L5.5 7" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"/></svg>
@current-change="handleCurrentChange" </button>
/>
<template v-for="(p, i) in displayPages" :key="i">
<span v-if="p === '...'" class="gear-pg-ellipsis">···</span>
<button v-else :class="['gear-pg-btn', { active: p === currentPage }]" @click="changePage(p)">{{ p }}</button>
</template>
<button class="gear-pg-btn gear-pg-nav" :disabled="currentPage >= totalPages" @click="changePage(currentPage + 1)">
<svg width="8" height="8" viewBox="0 0 8 8" fill="none"><path d="M2.5 1L5.5 4L2.5 7" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"/></svg>
</button>
</div>
<div class="gear-pg-jumper">
<span class="gear-pg-label">前往</span>
<input v-model.number="jumpVal" type="number" class="gear-pg-input" :min="1" :max="totalPages" @keyup.enter="handleJump" />
<span class="gear-pg-label"></span>
</div>
</div> </div>
</template> </template>
@@ -18,88 +33,194 @@
import { scrollTo } from '@/utils/scroll-to' import { scrollTo } from '@/utils/scroll-to'
const props = defineProps({ const props = defineProps({
total: { total: { required: true, type: Number },
required: true, page: { type: Number, default: 1 },
type: Number limit: { type: Number, default: 20 },
}, pageSizes: { type: Array, default: () => [10, 20, 30, 50] },
page: { pagerCount: { type: Number, default: document.body.clientWidth < 992 ? 5 : 7 },
type: Number, autoScroll: { type: Boolean, default: true },
default: 1 hidden: { type: Boolean, default: false }
},
limit: {
type: Number,
default: 20
},
pageSizes: {
type: Array,
default() {
return [10, 20, 30, 50]
}
},
// 移动端页码按钮的数量端默认值5
pagerCount: {
type: Number,
default: document.body.clientWidth < 992 ? 5 : 7
},
layout: {
type: String,
default: 'total, sizes, prev, pager, next, jumper'
},
background: {
type: Boolean,
default: true
},
autoScroll: {
type: Boolean,
default: true
},
hidden: {
type: Boolean,
default: false
}
}) })
const emit = defineEmits() const emit = defineEmits(['update:page', 'update:limit', 'pagination'])
const jumpVal = ref(props.page)
const currentPage = computed({ const currentPage = computed({
get() { get: () => props.page,
return props.page set: val => emit('update:page', val)
},
set(val) {
emit('update:page', val)
}
}) })
const pageSize = computed({ const pageSize = computed({
get() { get: () => props.limit,
return props.limit set: val => emit('update:limit', val)
},
set(val){
emit('update:limit', val)
}
}) })
function handleSizeChange(val) { const totalPages = computed(() => Math.max(1, Math.ceil(props.total / props.limit)))
if (currentPage.value * val > props.total) {
currentPage.value = 1 const displayPages = computed(() => {
} const total = totalPages.value
emit('pagination', { page: currentPage.value, limit: val }) const cur = currentPage.value
if (props.autoScroll) { const count = props.pagerCount
scrollTo(0, 800) if (total <= count) return Array.from({ length: total }, (_, i) => i + 1)
} const half = Math.floor(count / 2)
let start = Math.max(1, cur - half)
let end = Math.min(total, start + count - 1)
if (end - start < count - 1) start = Math.max(1, end - count + 1)
const pages = []
if (start > 1) { pages.push(1); if (start > 2) pages.push('...') }
for (let i = start; i <= end; i++) pages.push(i)
if (end < total) { if (end < total - 1) pages.push('...'); pages.push(total) }
return pages
})
function changePage(p) {
if (p < 1 || p > totalPages.value || p === currentPage.value) return
currentPage.value = p
jumpVal.value = p
emit('pagination', { page: p, limit: pageSize.value })
if (props.autoScroll) scrollTo(0, 800)
} }
function handleCurrentChange(val) { function handleSizeChange() {
emit('pagination', { page: val, limit: pageSize.value }) const newPage = currentPage.value * pageSize.value > props.total ? 1 : currentPage.value
if (props.autoScroll) { currentPage.value = newPage
scrollTo(0, 800) emit('pagination', { page: newPage, limit: pageSize.value })
if (props.autoScroll) scrollTo(0, 800)
} }
function handleJump() {
changePage(Math.min(Math.max(1, Math.round(jumpVal.value)), totalPages.value))
} }
watch(() => props.page, val => { jumpVal.value = val })
</script> </script>
<style scoped> <style scoped lang="scss">
.pagination-container { $p: #1d4e89;
background: #fff; $pd: #122f55;
$pl: #2471a3;
$bd: #c8d4e4;
$h: 22px;
.gear-pagination {
display: flex;
align-items: center;
gap: 8px;
padding: 4px 0;
margin-top: 8px;
border-top: 2px solid $p;
flex-wrap: wrap;
} }
.pagination-container.hidden {
display: none; .gear-pg-info {
font-size: 12px;
color: #7a8fa6;
white-space: nowrap;
b { color: $p; font-weight: 700; }
}
.gear-pg-select {
height: $h;
padding: 0 18px 0 6px;
border: 1px solid $bd;
border-left: 2px solid $p;
background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5' viewBox='0 0 8 5'%3E%3Cpath d='M0 0l4 5 4-5z' fill='%231d4e89'/%3E%3C/svg%3E") right 5px center no-repeat;
background-size: 7px;
appearance: none;
font-size: 12px;
font-weight: 600;
color: #1c2b3a;
cursor: pointer;
border-radius: 2px;
outline: none;
&:hover { border-color: $pl; }
}
.gear-pg-pager {
display: flex;
align-items: center;
gap: 2px;
}
.gear-pg-btn {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: $h;
height: $h;
padding: 0 4px;
border: 1px solid $bd;
background: #fff;
color: #1c2b3a;
font-size: 12px;
font-weight: 600;
cursor: pointer;
border-radius: 2px;
transition: background .1s, color .1s, border-color .1s;
&:hover:not(:disabled) {
border-color: $p;
color: $p;
background: #f0f5ff;
}
&.active {
background: $p;
border-color: $p;
border-left: 2px solid $pd;
color: #fff;
}
}
.gear-pg-nav {
color: $p;
border-color: $p;
&:disabled { opacity: 0.3; cursor: not-allowed; }
}
.gear-pg-ellipsis {
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: $h;
font-size: 11px;
color: #7a8fa6;
user-select: none;
}
.gear-pg-jumper {
display: flex;
align-items: center;
gap: 3px;
margin-left: auto;
}
.gear-pg-label {
font-size: 12px;
color: #7a8fa6;
white-space: nowrap;
}
.gear-pg-input {
width: 36px;
height: $h;
border: 1px solid $bd;
border-left: 2px solid $p;
border-radius: 2px;
padding: 0 3px;
font-size: 12px;
font-weight: 600;
color: #1c2b3a;
text-align: center;
outline: none;
-moz-appearance: textfield;
transition: border-color .1s;
&::-webkit-inner-spin-button, &::-webkit-outer-spin-button { display: none; }
&:hover, &:focus { border-color: $pl; }
}
@media (max-width: 768px) {
.gear-pg-jumper, .gear-pg-select { display: none; }
} }
</style> </style>