This commit is contained in:
huangchenhao 2025-11-12 10:24:21 +08:00
commit 3458857fa7
3 changed files with 107 additions and 20 deletions

View File

@ -1,5 +1,16 @@
@use './mixins.scss' as *;
/**
* 全局 CSS 容器查询回退
*
* 这些根级别变量为不支持容器查询的浏览器提供默认的视口单位
* 设置了 container-type 的组件会在支持时覆盖这些值为容器单位cqw/cqh
*/
:root {
--cq-inline-100: 100vw;
--cq-block-100: 100vh;
}
* {
margin: 0;
padding: 0;

View File

@ -1,22 +1,40 @@
// 屏幕适配工具
// 屏幕适配工具支持容器查询
// 设计稿基准1920px () × 982px (不含头部)
//
// 容器查询支持
// 当组件嵌入到其他系统时会自动使用容器单位cqw/cqh而非视口单位vw/vh
// 这确保了子组件相对于父容器而非整个视口进行缩放
//
// 回退策略
// 使用 CSS 变量 --cq-inline-100 --cq-block-100 提供渐进增强
// 不支持容器查询的浏览器会回退到视口单位
// px 转换为 vw (基于设计稿宽度 1920px)
$design-width: 1920;
$design-height: 982;
// px 转换为容器宽度单位基于设计稿宽度 1920px
// 在支持容器查询的浏览器中使用 cqw否则回退到 vw
@function vw($px) {
@return calc($px / 1920 * 100vw);
@return calc($px / $design-width * var(--cq-inline-100, 100vw));
}
// px 转换为 vh (基于设计稿内容区域高度 982px)
// px 转换为容器高度单位基于设计稿内容区域高度 982px
// 在支持容器查询的浏览器中使用 cqh否则回退到 vh
@function vh($px) {
@return calc($px / 982 * 100vh);
@return calc($px / $design-height * var(--cq-block-100, 100vh));
}
// 字体大小转换 (使用 vw 确保响应式)
// 字体大小转换使用容器宽度确保响应式
// 字体随容器宽度缩放保持与其他元素的比例关系
@function fs($px) {
@return calc($px / 1920 * 100vw);
@return vw($px);
}
// 使用示例
// width: vw(580); // 580px vw
// height: vh(400); // 400px vh
// font-size: fs(16); // 16px vw
// width: vw(580); // 580px cqw ( vw 作为 fallback)
// height: vh(400); // 400px cqh ( vh 作为 fallback)
// font-size: fs(16); // 16px cqw ( vw 作为 fallback)
//
// 注意这些函数需要父容器设置了 container-type: inline-size size
// 例如在 CockpitLayout.vue 中已经设置了相应的容器类型

View File

@ -29,32 +29,89 @@ import YearStatistics from './YearStatistics.vue'
</script>
<style scoped lang="scss">
@use '@/styles/mixins.scss' as *;
/**
* 驾驶舱布局 - 可嵌入组件
*
* 此组件设计为可嵌入到其他系统中iframe/组件
* 使用百分比和 rem 单位而非 vw/vh以适应父容器尺寸
*
* CSS 自定义属性可被父级覆盖
* - --cockpit-side-width: 侧边栏宽度默认minmax(15rem, 28%)
* - --cockpit-gap: 网格间距和面板间距默认1.25rem
* - --cockpit-padding-x: 水平内边距默认0.625rem
* - --cockpit-padding-top: 顶部内边距默认0
* - --cockpit-padding-bottom: 底部内边距默认0
* - --cockpit-min-height: 最小高度默认600px
*
* 父级使用方式<CockpitLayout style="--cockpit-gap: 2rem" />
* 窄容器嵌入<1100px 宽度添加 .is-compact 修饰符类
* <CockpitLayout class="is-compact" />
* 如需在滚动父容器中嵌入可覆盖 overflow: hidden
*
* 浏览器兼容性需要 CSS 自定义属性支持Chrome 49+, Safari 9.1+, Firefox 31+
* 未来计划支持容器查询以实现响应式窄屏布局
*
* 基于 1920px 设计稿根字体大小 16px
*/
.cockpit-layout {
width: 100vw;
height: 100vh;
/* 容器查询设置,用于嵌入场景的自适应缩放 */
container-name: cockpit-layout;
container-type: size;
/* 为旧版浏览器提供视口单位回退 */
--cq-inline-100: 100vw;
--cq-block-100: 100vh;
/* 当支持容器单位时覆盖为容器单位 */
@supports (width: 1cqw) {
--cq-inline-100: 100cqw;
}
@supports (height: 1cqh) {
--cq-block-100: 100cqh;
}
/* 嵌入场景的 CSS 自定义属性 */
--cockpit-side-width: minmax(15rem, 28%);
--cockpit-gap: 1.25rem;
--cockpit-padding-x: 0.625rem;
--cockpit-padding-top: 0;
--cockpit-padding-bottom: 0;
--cockpit-min-height: 600px;
/* 使用 100% 填充父容器而非视口 */
width: 100%;
height: 100%;
min-height: var(--cockpit-min-height);
min-width: 0; /* 允许 flex 子元素收缩 */
background: url(../assets/img/cockpit-main-bg.png) no-repeat;
background-size: cover;
display: flex;
flex-direction: column;
overflow: hidden;
overflow: auto; /* 当宿主高度 < 最小高度时允许滚动 */
}
/* 窄容器嵌入的紧凑布局(<1100px 宽度)*/
.cockpit-layout.is-compact {
--cockpit-side-width: minmax(12rem, 24%);
--cockpit-gap: 1rem;
}
.cockpit-main {
flex: 1;
min-height: 0; /* 允许网格在 flex 上下文中收缩 */
display: grid;
grid-template-columns: vw(580) 1fr vw(580);
gap: vw(20);
padding: 0 vw(10);
// padding-top: 0;
grid-template-columns: var(--cockpit-side-width) 1fr var(--cockpit-side-width);
gap: var(--cockpit-gap);
padding: var(--cockpit-padding-top) var(--cockpit-padding-x) var(--cockpit-padding-bottom);
}
.left-panel,
.right-panel {
display: flex;
flex-direction: column;
gap: vw(20);
gap: var(--cockpit-gap);
min-width: 0; /* 防止在窄容器中溢出 */
}
.center-panel {
@ -62,5 +119,6 @@ import YearStatistics from './YearStatistics.vue'
align-items: center;
justify-content: center;
position: relative;
min-width: 0; /* 确保地图可以在需要时收缩 */
}
</style>