style(一周安排小组件): 箭头加 hover 药丸、今日方块 28px 同基线、加载骨架结构化三态同高、查看概览移卡头直跳
build / build (push) Successful in 44s

① 翻页箭头:定尺寸 24×24 inline-flex 双向居中 + 圆角 4 + 过渡;
   hover 灰底药丸(#eef1f5/#344449),active 加深一档,禁用态不响应
② 今日方块:height 28px + line-height 28px,margin-top 由 5px 改 −1px
   (28px 行盒使数字中心下移 5.5px,−0.75 取整补回,与其余 6 天同基线);
   圆点改锚数字块(b::after bottom:-8px),今日格圆点 bottom:-5.5px 补位,七格圆点同线
③ 加载态:通用 4 行 Skeleton(158px)换成结构化骨架(标题 40 + 七日条 63 + 列表 171
   + 备注区 66.59),与内容逐段同构同高;备注区恒占位(min-height 58.59px,无备注只留白)
   ⇒ 加载/空周/有备注周三态恒等 364.6px,切换零高度跳变(方案 B)
④ 删除「日常详情」标题行;「查看概览」改 a 标签直跳(target=_blank),
   Teleport 进卡头右侧 #wg-hdr-<id> 锚点(与课程表班级切换器同机制),
   样式复刻 .cls-trigger 一族;index.vue 不用改

harness 真组件复测:三态 364.58/364.58/364.59;今日墨迹中心 84 vs 其余 84.25(差 0.25px);
七格圆点中心全 101.5;箭头药丸 24×24 双盒一致;ov-link 落位卡头右区、关闭按钮左侧 6px。
This commit is contained in:
chenxing
2026-10-16 14:38:25 +08:00
parent 84bbf2faf4
commit 04c12e2076
+228 -53
View File
@@ -1,13 +1,34 @@
<template>
<div class="wg-weekplan" ref="refRoot">
<Skeleton
v-if="loading"
style="padding: 15px"
:loading="true"
:title="false"
:paragraph="{ rows: 4 }"
animated
/>
<!-- ④ 「查看概览」:Teleport 进卡片 header 右侧(index.vue 埋的 #wg-hdr-<id> 锚点,
与课程表班级切换器同一机制);a 标签直跳子应用,加载中/空态都在位,不随周数据闪灭 -->
<Teleport v-if="overviewUrl" :to="'#wg-hdr-' + widgetId">
<a class="ov-link" :href="overviewUrl" target="_blank" rel="noopener">查看概览</a>
</Teleport>
<!-- 加载态:结构化骨架。各段与真实内容同构同高(标题 40 + 七日条 63 + 列表 171 + 备注区 66.6),
换周不再「先塌再弹」;方案 B 下加载/空周/有备注周三态恒等 ≈364.6px -->
<div v-if="loading" class="wk-skeleton" aria-hidden="true">
<div class="sk-title">
<i class="bar" style="width: 46%"></i>
<span class="sk-pager"><i></i><i></i></span>
</div>
<div class="sk-days">
<div class="sd on"><span class="w"></span><b><i></i></b></div>
<div class="sd"><span class="w"></span><b><i></i></b></div>
<div class="sd"><span class="w"></span><b><i></i></b></div>
<div class="sd"><span class="w"></span><b><i></i></b></div>
<div class="sd"><span class="w"></span><b><i></i></b></div>
<div class="sd"><span class="w"></span><b><i></i></b></div>
<div class="sd"><span class="w"></span><b><i></i></b></div>
</div>
<div class="sk-list">
<div class="sr"><div class="l"><span class="c"></span><span class="t"></span></div><div class="m"></div></div>
<div class="sr"><div class="l"><span class="c"></span><span class="t"></span></div><div class="m"></div></div>
<div class="sr"><div class="l"><span class="c"></span><span class="t"></span></div><div class="m"></div></div>
</div>
<div class="sk-remark-slot"><i class="b1"></i><i class="b2"></i></div>
</div>
<!-- 门控用 hasWeek(有 title 的周对象)而非 hasData:空周(hasData=false)
也必须保留标题行 + 翻页箭头,否则用户翻进空周后没有出口 -->
@@ -34,17 +55,6 @@
</div>
</div>
<div class="wk-tips-row">
<span class="wk-tips">日常详情</span>
<!-- 外跳地址由后端按「子应用 code + 路由」解析下发(应用注册表 pc_url),前端不写死域名 -->
<a
v-if="overviewUrl"
class="wk-overview"
:href="overviewUrl"
target="_blank"
rel="noopener"
>查看概览</a>
</div>
<!-- 列表区固定高度(= 3 条 × --wk-row):超出滚动;空态(休/节假日/无安排)同高,卡片高度不跳 -->
<div class="wk-list-area">
<ul v-if="currentList.length > 0" class="wk-list">
@@ -60,12 +70,15 @@
<div v-else class="no-data">{{ currentDayLabel }}</div>
</div>
<!-- 备注:无备注整块不渲染(不占位,卡片高度随内容);
<!-- 备注区恒占位(min-height = 2 行折叠高 58.59px):无备注只留白、不出灰盒,
与骨架/空周/有备注周同高 ⇒ 任意切换零高度变化(方案 B)。
默认 2 行截断,溢出才给「展开」(折叠态按钮贴第二行末尾) -->
<div class="wk-remark-slot">
<div v-if="remarkText" class="wk-remark">
<div ref="refRemark" class="rk-txt" :class="{ expanded: remarkExpanded }">{{ remarkText }}</div>
<span v-if="remarkOverflow" class="rk-more" @click="toggleRemark">{{ remarkExpanded ? "收起" : "展开" }}</span>
</div>
</div>
</template>
<!-- 空态:模板内联 SVG,不依赖外部图片 / CSS 背景 -->
@@ -293,6 +306,8 @@ $wk-primary-dark: #4864d8;
+ 上下 padding 12 + 分隔线 1 ≈ 56.25px ⇒ 取 57px 留余量。
有/无「地点·负责人·参与人」的条目都占这个高度,标题行始终对齐。 */
--wk-row: 57px;
/* 结构化骨架的灰条颜色 */
--wk-skel: rgba(190, 190, 190, 0.35);
padding: 6px 0 10px;
}
.wk-title {
@@ -310,25 +325,45 @@ $wk-primary-dark: #4864d8;
text-overflow: ellipsis;
white-space: nowrap;
}
.pager i {
.pager {
display: flex;
gap: 2px;
i {
font-style: normal;
font-size: 16px;
font-weight: 400;
color: #6e7c87;
padding: 0 6px;
/* 定尺寸 + flex 双向居中:行盒(24px)里字形贴基线,直接给背景会把字形顶偏 */
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
line-height: 1;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.16s, color 0.16s;
user-select: none;
&.disabled {
color: #d6dbe1;
cursor: default;
}
&:not(.disabled):hover {
background: #eef1f5;
color: #344449;
}
&:not(.disabled):active {
background: #e2e7ee;
}
}
}
}
.wk-days {
display: flex;
margin: 0 15px 6px;
/* 下边距 6→8:删除「日常详情」行后补回原视觉间距(原来 6 与 tips 的 8 塌缩取 max=8) */
margin: 0 15px 8px;
gap: 4px;
.d {
position: relative;
flex: 1 1 0;
text-align: center;
font-size: 14px;
@@ -343,13 +378,15 @@ $wk-primary-dark: #4864d8;
color: #344449;
margin-top: 2px;
font-weight: 600;
// 圆点改锚数字块(不再锚格子):格子被今日格 28px 方块拉高时圆点不再跟着沉
position: relative;
}
// 圆点绝对定位在单元格底部(今日的蓝底方块不会把它盖住)
// 圆点绝对定位在数字块下方 6px(bottom:-8px ⇒ 点中心 = b 底边 + 6,与线上旧位一致)
b::after {
content: "";
position: absolute;
left: 50%;
bottom: 3px;
bottom: -8px;
transform: translateX(-50%);
width: 4px;
height: 4px;
@@ -366,46 +403,44 @@ $wk-primary-dark: #4864d8;
color: #98a2b0;
}
// 今日:蓝底白字方块(置最后,压过 rest / holiday 的日期字色)
// 数字居中:flex 双向居中 + 定高 22px;line-height:1 去掉行盒 descender 余量
//(原 15px/1.5 行盒:数字视觉偏上 ≈1.2px,且行盒底部 descender 空白把方块"顶高")
// margin-top 1px:让方块里的数字与其余 6 天同基线(实测差 ≤0.5px)
// 28px 行盒会把数字中心相对 22.5px 行盒下移 5.5px(canvas 字体度量实测墨迹中心
// 11.25 → 14),margin-top 取 −1px(精确 −0.75 取整)补回,数字与其余 6 天同基线
&.is-on {
color: $wk-primary;
b {
display: flex;
align-items: center;
justify-content: center;
display: block;
width: 28px;
height: 22px;
margin: 1px auto 0;
line-height: 1;
height: 28px;
margin: -1px auto 0;
line-height: 28px;
background: $wk-primary;
color: #fff;
border-radius: 4px;
}
// 方块比数字行盒高 5.5px,圆点随之低 2.5px ⇒ 上收 2.5px,七格圆点同线(格顶 + 55.5)
b::after {
bottom: -5.5px;
}
}
}
}
.wk-tips-row {
display: flex;
/* ④ 「查看概览」:渲染在卡片 header 右侧(Teleport 到 index.vue 的 #wg-hdr-<id> 锚点),
样式复刻课程表班级切换器 .cls-trigger 一族;a 标签直跳、无浮层 */
.ov-link {
display: inline-flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin: 8px 15px 0;
}
.wk-tips {
font-size: 16px;
font-weight: 700;
color: #1f2329;
}
.wk-overview {
flex: 0 0 auto;
font-family: inherit;
font-size: 13px;
color: $wk-primary;
font-weight: 400;
color: #344449;
text-decoration: none;
cursor: pointer;
padding: 3px 8px;
border-radius: 6px;
line-height: 1.5;
transition: background-color 0.15s, color 0.15s;
&:hover {
color: $wk-primary-dark;
background: #eef1f5;
color: $wk-primary;
}
}
/* 列表区:固定高度 = 3 条(3 × --wk-row,即 171px);多条滚动、空态占位同高,
@@ -476,16 +511,156 @@ $wk-primary-dark: #4864d8;
white-space: nowrap;
}
}
/* 备注:与「安排数据」区分——上方一条分割线 + 浅底块,跟白色列表拉开层次;无备注整块不渲染 */
/* ---------- 加载态:结构化骨架(与内容逐段同构同高,换周不塌不跳) ----------
标题 40 + 七日条 63 + 列表 171 + 备注区 66.59 + 根部 padding 16 ≈ 364.6px,
与「空周内容」「有备注周内容」严格相等(方案 B)。注意根部勿再加 padding */
.wk-skeleton {
.sk-title {
margin: 0 15px;
padding: 6px 0 10px;
display: flex;
align-items: center;
justify-content: space-between;
.bar {
height: 16px;
width: 46%;
border-radius: 4px;
background: var(--wk-skel);
}
// font-size 16 撑出与真实 pager 相同的 24px 行盒(标题段总高 40 的关键)
.sk-pager {
font-size: 16px;
i {
display: inline-block;
width: 10px;
height: 16px;
margin-left: 12px;
border-radius: 2px;
background: var(--wk-skel);
}
}
}
.sk-days {
display: flex;
margin: 0 15px 8px;
gap: 4px;
.sd {
flex: 1 1 0;
text-align: center;
font-size: 14px;
padding: 4px 0 11px;
// 星期条:inline-block 10px 高,行盒由 14px 字体的 21px strut 决定(与真实星期同行高)
.w {
display: inline-block;
width: 14px;
height: 10px;
border-radius: 3px;
background: var(--wk-skel);
}
b {
display: block;
font-size: 15px;
margin-top: 2px;
i {
display: inline-block;
width: 20px;
height: 16px;
border-radius: 3px;
background: var(--wk-skel);
}
}
// 今日格:与真实 .d.is-on b 同几何(28px 方块 + margin-top −1)
&.on b {
width: 28px;
height: 28px;
margin: -1px auto 0;
i {
width: 28px;
height: 28px;
border-radius: 4px;
background: $wk-primary;
opacity: 0.55;
}
}
}
}
.sk-list {
height: calc(var(--wk-row) * 3);
.sr {
height: var(--wk-row);
margin: 0 15px;
padding: 6px 0;
border-bottom: 1px solid #f2f4f7;
&:last-child {
border-bottom: 0;
}
.l {
height: 22.5px;
display: flex;
align-items: center;
gap: 10px;
.c {
height: 14px;
width: 58%;
border-radius: 4px;
background: var(--wk-skel);
}
.t {
height: 14px;
width: 64px;
border-radius: 4px;
background: var(--wk-skel);
}
}
.m {
margin-top: 2px;
height: 10px;
width: 32%;
border-radius: 4px;
background: var(--wk-skel);
}
}
}
// 备注区占位:与 .wk-remark-slot 同高(min-height 58.59,无 padding,盒尺寸与全局 border-box 无关)
.sk-remark-slot {
margin: 8px 15px 0;
min-height: 58.59px;
border-radius: 6px;
background: #f7f8fa;
border-top: 1px solid #eef1f5;
i {
display: block;
height: 12px;
border-radius: 4px;
background: var(--wk-skel);
&.b1 {
width: 78%;
margin: 11px 10px 0;
}
&.b2 {
width: 56%;
margin: 9px 10px 0;
}
}
}
}
/* 备注区恒占位(方案 B):min-height = 2 行折叠高 58.59px。
无备注时只留白、不出灰盒;有备注时灰盒至少填满该区(1 行备注也不缩)。
⇒ 加载 / 空周 / 有备注周三态同高,任意切换零高度变化 */
.wk-remark-slot {
margin: 8px 15px 0;
min-height: 58.59px;
}
/* 备注:与「安排数据」区分——上方一条分割线 + 浅底块,跟白色列表拉开层次 */
.wk-remark {
position: relative;
margin: 8px 15px 0;
padding: 8px 10px;
background: #f7f8fa;
border-top: 1px solid #eef1f5;
border-radius: 6px;
font-size: 13px;
color: #5b6672;
min-height: 58.59px;
.rk-txt {
line-height: 1.6;
// 备注可能是含换行的多行文本:pre-line 保留换行;折叠态截断 2 行