fix: refine dark mode and table scrolling
This commit is contained in:
@@ -388,15 +388,10 @@ async function handleLogout() {
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 20px 16px;
|
padding: 20px 16px;
|
||||||
border-right: 1px solid var(--border-subtle);
|
border-right: 1px solid var(--border-subtle);
|
||||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.16));
|
background: var(--sidebar-shell-bg);
|
||||||
backdrop-filter: blur(18px);
|
backdrop-filter: blur(18px);
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(html[data-theme="dark"]) .app-sidebar {
|
|
||||||
background: var(--bg-subtle);
|
|
||||||
border-right-color: var(--border-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(html[data-theme="dark"]) .app-nav-menu :deep(.el-menu-item.is-active) {
|
:global(html[data-theme="dark"]) .app-nav-menu :deep(.el-menu-item.is-active) {
|
||||||
background: linear-gradient(180deg, rgba(91, 168, 255, 0.18), rgba(91, 168, 255, 0.1));
|
background: linear-gradient(180deg, rgba(91, 168, 255, 0.18), rgba(91, 168, 255, 0.1));
|
||||||
box-shadow: inset 0 0 0 1px rgba(91, 168, 255, 0.2);
|
box-shadow: inset 0 0 0 1px rgba(91, 168, 255, 0.2);
|
||||||
@@ -671,15 +666,11 @@ async function handleLogout() {
|
|||||||
padding: 18px 20px;
|
padding: 18px 20px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
border: 1px solid var(--border-subtle);
|
border: 1px solid var(--border-subtle);
|
||||||
background: rgba(255, 255, 255, 0.56);
|
background: var(--topbar-shell-bg);
|
||||||
backdrop-filter: blur(16px);
|
backdrop-filter: blur(16px);
|
||||||
box-shadow: var(--shadow-soft);
|
box-shadow: var(--shadow-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(html[data-theme="dark"]) .app-topbar__main {
|
|
||||||
background: rgba(15, 27, 41, 0.78);
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-topbar__lead {
|
.app-topbar__lead {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|||||||
@@ -28,6 +28,10 @@
|
|||||||
--shadow-soft: 0 10px 30px rgba(15, 23, 38, 0.06);
|
--shadow-soft: 0 10px 30px rgba(15, 23, 38, 0.06);
|
||||||
--shadow-card: 0 18px 42px rgba(15, 23, 38, 0.08);
|
--shadow-card: 0 18px 42px rgba(15, 23, 38, 0.08);
|
||||||
--shadow-float: 0 24px 60px rgba(15, 23, 38, 0.12);
|
--shadow-float: 0 24px 60px rgba(15, 23, 38, 0.12);
|
||||||
|
--sidebar-shell-bg:
|
||||||
|
linear-gradient(180deg, rgba(255, 255, 255, 0.42), rgba(255, 255, 255, 0.18)),
|
||||||
|
var(--bg-emphasis);
|
||||||
|
--topbar-shell-bg: rgba(255, 255, 255, 0.56);
|
||||||
--radius-sm: 6px;
|
--radius-sm: 6px;
|
||||||
--radius-md: 8px;
|
--radius-md: 8px;
|
||||||
--radius-lg: 10px;
|
--radius-lg: 10px;
|
||||||
@@ -101,6 +105,10 @@ html[data-theme="dark"] {
|
|||||||
--shadow-soft: 0 12px 30px rgba(2, 6, 12, 0.32);
|
--shadow-soft: 0 12px 30px rgba(2, 6, 12, 0.32);
|
||||||
--shadow-card: 0 18px 40px rgba(2, 6, 12, 0.4);
|
--shadow-card: 0 18px 40px rgba(2, 6, 12, 0.4);
|
||||||
--shadow-float: 0 24px 60px rgba(2, 6, 12, 0.52);
|
--shadow-float: 0 24px 60px rgba(2, 6, 12, 0.52);
|
||||||
|
--sidebar-shell-bg:
|
||||||
|
linear-gradient(180deg, rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0)),
|
||||||
|
var(--bg-subtle);
|
||||||
|
--topbar-shell-bg: rgba(15, 27, 41, 0.78);
|
||||||
|
|
||||||
--el-color-primary: var(--accent);
|
--el-color-primary: var(--accent);
|
||||||
--el-color-primary-light-3: #7db9ff;
|
--el-color-primary-light-3: #7db9ff;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onBeforeUnmount, onMounted, reactive, ref } from "vue";
|
import { computed, nextTick, onBeforeUnmount, onMounted, reactive, ref } from "vue";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import apiClient, { getApiErrorMessage } from "@/api/client";
|
import apiClient, { getApiErrorMessage } from "@/api/client";
|
||||||
import { useViewport } from "@/composables/useViewport";
|
import { useViewport } from "@/composables/useViewport";
|
||||||
@@ -37,6 +37,10 @@ const rooms = ref<LiveRoom[]>([]);
|
|||||||
const selectedRooms = ref<LiveRoom[]>([]);
|
const selectedRooms = ref<LiveRoom[]>([]);
|
||||||
const loadError = ref("");
|
const loadError = ref("");
|
||||||
const { isMobile } = useViewport();
|
const { isMobile } = useViewport();
|
||||||
|
const roomsTableShellRef = ref<HTMLElement | null>(null);
|
||||||
|
const roomsTableProxyRef = ref<HTMLElement | null>(null);
|
||||||
|
const showRoomsTableProxyScroll = ref(false);
|
||||||
|
const roomsTableProxyInnerWidth = ref(0);
|
||||||
|
|
||||||
const createForm = reactive({
|
const createForm = reactive({
|
||||||
url: "",
|
url: "",
|
||||||
@@ -106,6 +110,142 @@ const recordDialogWidth = computed(() => (isMobile.value ? "min(100vw - 24px, 44
|
|||||||
const settingsDialogWidth = computed(() => (isMobile.value ? "min(100vw - 24px, 760px)" : "840px"));
|
const settingsDialogWidth = computed(() => (isMobile.value ? "min(100vw - 24px, 760px)" : "840px"));
|
||||||
const deleteDialogWidth = computed(() => (isMobile.value ? "min(100vw - 24px, 560px)" : "clamp(480px, 46vw, 560px)"));
|
const deleteDialogWidth = computed(() => (isMobile.value ? "min(100vw - 24px, 560px)" : "clamp(480px, 46vw, 560px)"));
|
||||||
let autoRefreshTimer: number | null = null;
|
let autoRefreshTimer: number | null = null;
|
||||||
|
let roomsTableScrollWrap: HTMLElement | null = null;
|
||||||
|
let roomsTableResizeObserver: ResizeObserver | null = null;
|
||||||
|
let observedRoomsTableShell: HTMLElement | null = null;
|
||||||
|
let observedRoomsTableWrap: HTMLElement | null = null;
|
||||||
|
let syncingRoomsTableProxy = false;
|
||||||
|
let syncingRoomsTableBody = false;
|
||||||
|
|
||||||
|
function cleanupRoomsTableScrollSync() {
|
||||||
|
if (roomsTableScrollWrap) {
|
||||||
|
roomsTableScrollWrap.removeEventListener("scroll", handleRoomsTableBodyScroll);
|
||||||
|
roomsTableScrollWrap = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
roomsTableResizeObserver?.disconnect();
|
||||||
|
roomsTableResizeObserver = null;
|
||||||
|
observedRoomsTableShell = null;
|
||||||
|
observedRoomsTableWrap = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRoomsTableScrollWrap() {
|
||||||
|
const shell = roomsTableShellRef.value;
|
||||||
|
|
||||||
|
if (!shell) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shell.querySelector<HTMLElement>(".el-table__body-wrapper .el-scrollbar__wrap") ??
|
||||||
|
shell.querySelector<HTMLElement>(".el-scrollbar__wrap") ??
|
||||||
|
shell.querySelector<HTMLElement>(".el-table__body-wrapper");
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleRoomsTableBodyScroll() {
|
||||||
|
if (syncingRoomsTableProxy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const proxy = roomsTableProxyRef.value;
|
||||||
|
|
||||||
|
if (!proxy || !roomsTableScrollWrap) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
syncingRoomsTableBody = true;
|
||||||
|
proxy.scrollLeft = roomsTableScrollWrap.scrollLeft;
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
syncingRoomsTableBody = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleRoomsTableProxyScroll() {
|
||||||
|
if (syncingRoomsTableBody || !roomsTableScrollWrap) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const proxy = roomsTableProxyRef.value;
|
||||||
|
|
||||||
|
if (!proxy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
syncingRoomsTableProxy = true;
|
||||||
|
roomsTableScrollWrap.scrollLeft = proxy.scrollLeft;
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
syncingRoomsTableProxy = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureRoomsTableResizeObserver() {
|
||||||
|
if (typeof ResizeObserver === "undefined") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const shell = roomsTableShellRef.value;
|
||||||
|
const wrap = roomsTableScrollWrap;
|
||||||
|
|
||||||
|
if (roomsTableResizeObserver && observedRoomsTableShell === shell && observedRoomsTableWrap === wrap) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
roomsTableResizeObserver?.disconnect();
|
||||||
|
roomsTableResizeObserver = new ResizeObserver(() => {
|
||||||
|
void syncRoomsTableProxyScroll();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (shell) {
|
||||||
|
roomsTableResizeObserver.observe(shell);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wrap) {
|
||||||
|
roomsTableResizeObserver.observe(wrap);
|
||||||
|
}
|
||||||
|
|
||||||
|
observedRoomsTableShell = shell;
|
||||||
|
observedRoomsTableWrap = wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function syncRoomsTableProxyScroll() {
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
if (isMobile.value) {
|
||||||
|
showRoomsTableProxyScroll.value = false;
|
||||||
|
roomsTableProxyInnerWidth.value = 0;
|
||||||
|
cleanupRoomsTableScrollSync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrap = getRoomsTableScrollWrap();
|
||||||
|
|
||||||
|
if (roomsTableScrollWrap !== wrap) {
|
||||||
|
roomsTableScrollWrap?.removeEventListener("scroll", handleRoomsTableBodyScroll);
|
||||||
|
roomsTableScrollWrap = wrap;
|
||||||
|
roomsTableScrollWrap?.addEventListener("scroll", handleRoomsTableBodyScroll, { passive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const proxy = roomsTableProxyRef.value;
|
||||||
|
|
||||||
|
if (!wrap) {
|
||||||
|
showRoomsTableProxyScroll.value = false;
|
||||||
|
roomsTableProxyInnerWidth.value = 0;
|
||||||
|
ensureRoomsTableResizeObserver();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const scrollWidth = Math.max(wrap.scrollWidth, wrap.firstElementChild?.scrollWidth ?? 0);
|
||||||
|
const clientWidth = wrap.clientWidth;
|
||||||
|
const canScrollHorizontally = scrollWidth > clientWidth + 1;
|
||||||
|
|
||||||
|
roomsTableProxyInnerWidth.value = scrollWidth;
|
||||||
|
showRoomsTableProxyScroll.value = canScrollHorizontally;
|
||||||
|
|
||||||
|
if (canScrollHorizontally && proxy && Math.abs(proxy.scrollLeft - wrap.scrollLeft) > 1) {
|
||||||
|
proxy.scrollLeft = wrap.scrollLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureRoomsTableResizeObserver();
|
||||||
|
}
|
||||||
|
|
||||||
async function loadRooms() {
|
async function loadRooms() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
@@ -114,6 +254,7 @@ async function loadRooms() {
|
|||||||
try {
|
try {
|
||||||
const { data } = await apiClient.get<LiveRoom[]>("/live-rooms");
|
const { data } = await apiClient.get<LiveRoom[]>("/live-rooms");
|
||||||
rooms.value = data;
|
rooms.value = data;
|
||||||
|
void syncRoomsTableProxyScroll();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
loadError.value = getApiErrorMessage(error, "直播间列表加载失败,请稍后重试。");
|
loadError.value = getApiErrorMessage(error, "直播间列表加载失败,请稍后重试。");
|
||||||
} finally {
|
} finally {
|
||||||
@@ -148,6 +289,7 @@ async function autoRefreshRooms() {
|
|||||||
const { data } = await apiClient.get<LiveRoom[]>("/live-rooms");
|
const { data } = await apiClient.get<LiveRoom[]>("/live-rooms");
|
||||||
rooms.value = data;
|
rooms.value = data;
|
||||||
loadError.value = "";
|
loadError.value = "";
|
||||||
|
void syncRoomsTableProxyScroll();
|
||||||
} catch {
|
} catch {
|
||||||
// Keep the current view stable; the background poller will try again.
|
// Keep the current view stable; the background poller will try again.
|
||||||
}
|
}
|
||||||
@@ -594,13 +736,17 @@ function nullableStringFromSelect(value: string | number) {
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await loadRooms();
|
await loadRooms();
|
||||||
|
void syncRoomsTableProxyScroll();
|
||||||
startAutoRefresh();
|
startAutoRefresh();
|
||||||
document.addEventListener("visibilitychange", handleVisibilityChange);
|
document.addEventListener("visibilitychange", handleVisibilityChange);
|
||||||
|
window.addEventListener("resize", syncRoomsTableProxyScroll);
|
||||||
});
|
});
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
stopAutoRefresh();
|
stopAutoRefresh();
|
||||||
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
||||||
|
window.removeEventListener("resize", syncRoomsTableProxyScroll);
|
||||||
|
cleanupRoomsTableScrollSync();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -745,7 +891,16 @@ onBeforeUnmount(() => {
|
|||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else class="table-scroll-shell rooms-table-shell">
|
<div v-else ref="roomsTableShellRef" class="table-scroll-shell rooms-table-shell">
|
||||||
|
<div
|
||||||
|
v-if="showRoomsTableProxyScroll"
|
||||||
|
ref="roomsTableProxyRef"
|
||||||
|
class="rooms-table-proxy-scroll"
|
||||||
|
@scroll.passive="handleRoomsTableProxyScroll"
|
||||||
|
>
|
||||||
|
<div class="rooms-table-proxy-scroll__inner" :style="{ width: `${roomsTableProxyInnerWidth}px` }"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<el-table
|
<el-table
|
||||||
:data="rooms"
|
:data="rooms"
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
@@ -1246,8 +1401,23 @@ onBeforeUnmount(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.rooms-table-shell {
|
.rooms-table-shell {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rooms-table-proxy-scroll {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 5;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding-bottom: 6px;
|
||||||
|
background: var(--surface);
|
||||||
|
scrollbar-width: thin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rooms-table-proxy-scroll__inner {
|
||||||
|
height: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rooms-table {
|
.rooms-table {
|
||||||
|
|||||||
@@ -1487,6 +1487,16 @@ onMounted(loadSettings);
|
|||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="settings-savebar">
|
||||||
|
<div class="settings-savebar__content">
|
||||||
|
<div class="settings-savebar__copy">
|
||||||
|
<div class="settings-savebar__title">当前修改不会自动保存</div>
|
||||||
|
<div class="settings-savebar__subtitle">滚动到页面任何位置都可以直接保存当前设置。</div>
|
||||||
|
</div>
|
||||||
|
<el-button type="primary" :loading="saving" @click="saveSettings">淇濆瓨璁剧疆</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -1494,12 +1504,17 @@ onMounted(loadSettings);
|
|||||||
.page-stack {
|
.page-stack {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
|
padding-bottom: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-error-alert {
|
.page-error-alert {
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page-toolbar :deep(.el-button--primary) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.settings-import-input {
|
.settings-import-input {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@@ -1515,6 +1530,56 @@ onMounted(loadSettings);
|
|||||||
grid-column: auto;
|
grid-column: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings-tabs :deep(.el-tabs__header) {
|
||||||
|
margin: 0;
|
||||||
|
border: 1px solid var(--border-subtle);
|
||||||
|
border-bottom: 0;
|
||||||
|
border-radius: 12px 12px 0 0;
|
||||||
|
background: linear-gradient(180deg, var(--surface-raised), var(--surface-muted));
|
||||||
|
box-shadow: var(--shadow-soft);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-tabs :deep(.el-tabs__nav-wrap) {
|
||||||
|
padding-inline: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-tabs :deep(.el-tabs__nav-wrap::after) {
|
||||||
|
background: var(--border-subtle);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-tabs :deep(.el-tabs__nav) {
|
||||||
|
border: 0 !important;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-tabs :deep(.el-tabs__item) {
|
||||||
|
height: 48px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
border: 0 !important;
|
||||||
|
transition:
|
||||||
|
color 0.18s ease,
|
||||||
|
background-color 0.18s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-tabs :deep(.el-tabs__item:hover) {
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-tabs :deep(.el-tabs__item.is-active) {
|
||||||
|
color: var(--text-primary);
|
||||||
|
background: var(--surface);
|
||||||
|
box-shadow: inset 0 -2px 0 var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-tabs :deep(.el-tabs__content) {
|
||||||
|
padding: 18px;
|
||||||
|
border: 1px solid var(--border-subtle);
|
||||||
|
border-top: 0;
|
||||||
|
border-radius: 0 0 12px 12px;
|
||||||
|
background: linear-gradient(180deg, var(--surface-raised), var(--surface));
|
||||||
|
box-shadow: var(--shadow-soft);
|
||||||
|
}
|
||||||
|
|
||||||
.settings-card :deep(.el-card__body) {
|
.settings-card :deep(.el-card__body) {
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
}
|
}
|
||||||
@@ -1756,6 +1821,56 @@ onMounted(loadSettings);
|
|||||||
border-color: rgba(245, 158, 11, 0.18);
|
border-color: rgba(245, 158, 11, 0.18);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(html[data-theme="dark"]) .test-result--success {
|
||||||
|
background: rgba(14, 43, 28, 0.88);
|
||||||
|
border-color: rgba(34, 197, 94, 0.28);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(html[data-theme="dark"]) .test-result--warning {
|
||||||
|
background: rgba(58, 34, 10, 0.88);
|
||||||
|
border-color: rgba(245, 158, 11, 0.28);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-savebar {
|
||||||
|
position: sticky;
|
||||||
|
bottom: 18px;
|
||||||
|
z-index: 24;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-savebar__content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 14px 18px;
|
||||||
|
border-radius: 14px;
|
||||||
|
border: 1px solid var(--border-base);
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0)),
|
||||||
|
var(--surface-raised);
|
||||||
|
box-shadow: var(--shadow-float);
|
||||||
|
backdrop-filter: blur(18px);
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-savebar__copy {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-savebar__title {
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-savebar__subtitle {
|
||||||
|
margin-top: 4px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
.test-result__title {
|
.test-result__title {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@@ -1797,9 +1912,30 @@ onMounted(loadSettings);
|
|||||||
.action-strip :deep(.el-button) {
|
.action-strip :deep(.el-button) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings-savebar__content {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-savebar__content :deep(.el-button) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
|
.page-stack {
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-tabs :deep(.el-tabs__nav-wrap) {
|
||||||
|
padding-inline: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-tabs :deep(.el-tabs__content) {
|
||||||
|
padding: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
.settings-card :deep(.el-col) {
|
.settings-card :deep(.el-col) {
|
||||||
flex: 0 0 100%;
|
flex: 0 0 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
@@ -1821,5 +1957,14 @@ onMounted(loadSettings);
|
|||||||
.template-section {
|
.template-section {
|
||||||
padding: 16px 16px 2px;
|
padding: 16px 16px 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings-savebar {
|
||||||
|
bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-savebar__content {
|
||||||
|
padding: 12px 14px;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user