feat(课表小组件): SyllabusWidget改版直吃AcaSyllabu oapi结构——班级下拉切换器Teleport进卡头(通用header插槽能力),行=slotNo中文数字、列=周一~周五(周末有课才追加)、单元格=班级/科目;空态换原版no-data-box.svg插画;卡头钉死#f7f8f9+overflow visible供浮层溢出
build / build (push) Successful in 1m38s

This commit is contained in:
chenxing
2026-10-13 12:27:41 +08:00
parent a3ddb90a8a
commit 6f4b3f07d4
4 changed files with 289 additions and 74 deletions
+79
View File
@@ -0,0 +1,79 @@
<svg width="210" height="242" viewBox="0 0 210 242" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect opacity="0.01" x="0.5" y="0.5" width="209" height="209" stroke="#DCDEE0" stroke-dasharray="5"/>
<path opacity="0.8" fill-rule="evenodd" clip-rule="evenodd" d="M21 69.5625H47.25V171.938H24.9375H21H2.625V95.8125H21V69.5625Z" fill="url(#paint0_linear_25188_157943)"/>
<path opacity="0.8" fill-rule="evenodd" clip-rule="evenodd" d="M105 36.5217C104.368 36.671 103.709 36.75 103.031 36.75C98.3196 36.75 94.5 32.9304 94.5 28.2188C94.5 23.721 97.9807 20.0361 102.395 19.7108C102.382 19.486 102.375 19.2594 102.375 19.0312C102.375 12.8698 107.37 7.875 113.531 7.875C118.555 7.875 122.803 11.1953 124.201 15.7611C124.362 15.7537 124.524 15.75 124.688 15.75C130.486 15.75 135.188 20.451 135.188 26.25C135.188 32.049 130.486 36.75 124.688 36.75C124.243 36.75 123.805 36.7224 123.375 36.6688V36.75H105V36.5217Z" fill="url(#paint1_linear_25188_157943)"/>
<path opacity="0.8" fill-rule="evenodd" clip-rule="evenodd" d="M20.8304 43.8601C20.5247 43.9314 20.2058 43.969 19.878 43.969C17.5982 43.969 15.75 42.1461 15.75 39.8973C15.75 37.7506 17.4342 35.9919 19.5704 35.8367C19.5638 35.7293 19.5605 35.6211 19.5605 35.5121C19.5605 32.5714 21.9774 30.1875 24.9587 30.1875C27.3894 30.1875 29.4449 31.7722 30.1212 33.9512C30.1994 33.9477 30.2779 33.946 30.3569 33.946C33.1629 33.946 35.4376 36.1896 35.4376 38.9573C35.4376 41.725 33.1629 43.9687 30.3569 43.9687C30.1417 43.9687 29.9297 43.9555 29.7215 43.9299V43.9688H20.8304V43.8601Z" fill="url(#paint2_linear_25188_157943)"/>
<path opacity="0.8" fill-rule="evenodd" clip-rule="evenodd" d="M190.616 19.6875V38.0625H202.125V139.609H161.438V38.0625V19.6875H190.616Z" fill="url(#paint3_linear_25188_157943)"/>
<rect y="182.438" width="210" height="27.5625" fill="url(#paint4_radial_25188_157943)"/>
<path opacity="0.6" d="M182.123 151.822C182.393 150.842 183.783 150.842 184.052 151.822L189.953 173.298C190.128 173.934 189.649 174.562 188.988 174.562H177.187C176.527 174.562 176.048 173.934 176.223 173.298L182.123 151.822Z" fill="url(#paint5_linear_25188_157943)"/>
<rect opacity="0.6" x="181.121" y="174.562" width="3.93417" height="13.125" fill="url(#paint6_linear_25188_157943)"/>
<path opacity="0.6" d="M25.9359 151.822C26.2052 150.842 27.5951 150.842 27.8644 151.822L33.7652 173.298C33.9401 173.934 33.4611 174.562 32.801 174.562H20.9993C20.3392 174.562 19.8602 173.934 20.0351 173.298L25.9359 151.822Z" fill="url(#paint7_linear_25188_157943)"/>
<rect opacity="0.6" x="24.9331" y="174.562" width="3.93417" height="13.125" fill="url(#paint8_linear_25188_157943)"/>
<rect opacity="0.6" x="107.625" y="82.6875" width="47.25" height="69.5625" rx="2" fill="#DCDCDC"/>
<rect x="57.75" y="65.625" width="84" height="86.625" rx="2" fill="url(#paint9_linear_25188_157943)"/>
<rect x="65.625" y="73.5" width="68.25" height="72.1875" rx="1" fill="white"/>
<rect x="77.4375" y="87.9375" width="44.625" height="7.875" rx="1" fill="url(#paint10_linear_25188_157943)"/>
<rect x="77.4375" y="106.312" width="44.625" height="7.875" fill="url(#paint11_linear_25188_157943)"/>
<rect x="77.4375" y="124.688" width="44.625" height="7.875" rx="1" fill="url(#paint12_linear_25188_157943)"/>
<rect x="47.25" y="145.688" width="115.5" height="36.75" rx="1" fill="url(#paint13_linear_25188_157943)"/>
<rect x="85.3125" y="160.125" width="39.375" height="7.875" rx="1" fill="#F7F8FA"/>
<path d="M74.7124 230.804V231.984L71.7724 232.264V233.804H70.4524V232.364L66.2924 232.624L66.1124 231.344L70.4524 231.124V229.464H66.7324L66.4124 228.324C67.0124 227.63 67.539 226.864 67.9924 226.024H65.8524V224.744H68.6324C68.8724 224.157 69.0457 223.717 69.1524 223.424L70.5924 223.664C70.4057 224.144 70.259 224.504 70.1524 224.744H75.0324V226.024H69.5524C69.1124 226.85 68.639 227.604 68.1324 228.284H70.4524V226.964H71.7724V228.284H74.8924V229.464H71.7724V231.044L74.7124 230.804ZM77.5124 229.484C77.299 231.164 76.759 232.624 75.8924 233.864L74.8924 232.824C75.7857 231.504 76.2524 229.957 76.2924 228.184V225.044C78.7857 224.804 80.7324 224.364 82.1324 223.724L83.0524 224.804C81.5324 225.457 79.719 225.904 77.6124 226.144V228.224H83.6124V229.484H81.4924V233.824H80.1124V229.484H77.5124ZM81.3724 234.404V241.924H79.8924V241.144H69.7324V241.924H68.2524V234.404H81.3724ZM69.7324 239.904H79.8924V238.344H69.7324V239.904ZM69.7324 237.184H79.8924V235.624H69.7324V237.184ZM87.3524 224.664H101.712V226.064H94.5524V227.404C94.5124 228.724 94.4257 229.89 94.2924 230.904H103.332V232.284H97.1324V239.264C97.1324 239.917 97.4524 240.244 98.0924 240.244H100.632C101.112 240.244 101.466 240.11 101.692 239.844C101.972 239.537 102.159 238.604 102.252 237.044L103.612 237.484C103.452 239.43 103.152 240.624 102.712 241.064C102.339 241.424 101.732 241.604 100.892 241.604H97.6524C96.3457 241.604 95.6924 240.924 95.6924 239.564V232.284H94.0724C93.7524 234.017 93.2524 235.524 92.5724 236.804C91.319 238.99 89.3124 240.677 86.5524 241.864L85.7524 240.584C88.499 239.344 90.4124 237.71 91.4924 235.684C91.959 234.71 92.3257 233.577 92.5924 232.284H86.0124V230.904H92.8324C92.979 229.877 93.0657 228.71 93.0924 227.404V226.064H87.3524V224.664ZM117.852 228.024C117.719 228.504 117.626 228.857 117.572 229.084C118.066 231.35 118.719 233.344 119.532 235.064C120.306 233.037 120.732 230.69 120.812 228.024H117.852ZM118.872 236.544C118.086 234.97 117.426 233.204 116.892 231.244C116.546 232.124 116.152 232.944 115.712 233.704L114.812 232.604C115.999 230.35 116.792 227.33 117.192 223.544L118.592 223.784C118.499 224.61 118.352 225.564 118.152 226.644H123.432V228.024H122.132C122.052 231.357 121.459 234.21 120.352 236.584C121.406 238.344 122.639 239.697 124.052 240.644L123.232 241.864C121.859 240.904 120.666 239.59 119.652 237.924C118.679 239.524 117.439 240.864 115.932 241.944L115.172 240.724C116.732 239.644 117.966 238.25 118.872 236.544ZM110.772 233.024L110.372 234.124H114.532V235.344C114.092 236.65 113.366 237.784 112.352 238.744C113.299 239.144 114.199 239.584 115.052 240.064L114.272 241.224C113.352 240.677 112.339 240.157 111.232 239.664C109.886 240.584 108.219 241.324 106.232 241.884L105.532 240.644C107.199 240.204 108.599 239.657 109.732 239.004L106.952 237.884C107.512 236.964 107.966 236.144 108.312 235.424H105.972V234.124H108.912C109.246 233.19 109.399 232.77 109.372 232.864L110.772 233.024ZM110.972 238.164C111.972 237.35 112.706 236.437 113.172 235.424H109.792C109.459 236.104 109.099 236.737 108.712 237.324C109.512 237.604 110.266 237.884 110.972 238.164ZM107.552 224.024C108.072 224.837 108.499 225.657 108.832 226.484L107.712 227.004C107.299 226.057 106.846 225.197 106.352 224.424L107.552 224.024ZM114.732 224.444C114.319 225.35 113.806 226.217 113.192 227.044L112.112 226.464C112.752 225.557 113.246 224.697 113.592 223.884L114.732 224.444ZM106.032 227.424H109.932V223.604H111.272V227.424H114.912V228.684H111.272V228.904C112.366 229.45 113.472 230.064 114.592 230.744L113.852 231.864C112.852 231.064 111.992 230.424 111.272 229.944V232.544H109.932V228.744C109.279 230.304 108.086 231.67 106.352 232.844L105.652 231.684C107.199 230.777 108.272 229.777 108.872 228.684H106.032V227.424ZM126.272 241.744L125.972 240.384C126.546 240.45 127.052 240.484 127.492 240.484C127.999 240.484 128.252 240.19 128.252 239.604V234.724C127.319 235.07 126.532 235.344 125.892 235.544L125.532 234.144C126.439 233.93 127.346 233.657 128.252 233.324V228.804H125.852V227.424H128.252V223.644H129.652V227.424H131.572V228.804H129.652V232.744C130.292 232.464 130.912 232.164 131.512 231.844V233.264C131.099 233.477 130.479 233.77 129.652 234.144V239.964C129.652 241.15 129.092 241.744 127.972 241.744H126.272ZM133.952 232.904C133.712 236.317 132.932 239.324 131.612 241.924L130.492 240.924C131.906 238.284 132.626 234.857 132.652 230.644V224.384H143.192V229.244H139.432V231.604H143.712V232.904H139.432V235.364H142.792V241.924H141.452V240.944H136.032V241.924H134.692V235.364H138.032V232.904H133.952ZM138.032 229.244H134.052L134.032 231.604H138.032V229.244ZM136.032 239.664H141.452V236.644H136.032V239.664ZM141.792 225.724H134.052V227.944H141.792V225.724Z" fill="#969799"/>
<defs>
<linearGradient id="paint0_linear_25188_157943" x1="-3.63248" y1="171.938" x2="-3.63248" y2="69.5625" gradientUnits="userSpaceOnUse">
<stop stop-color="white" stop-opacity="0.5"/>
<stop offset="1" stop-color="#F2F3F5"/>
</linearGradient>
<linearGradient id="paint1_linear_25188_157943" x1="140.274" y1="35.8711" x2="140.274" y2="7.875" gradientUnits="userSpaceOnUse">
<stop stop-color="#F2F3F5" stop-opacity="0.3"/>
<stop offset="1" stop-color="#F2F3F5"/>
</linearGradient>
<linearGradient id="paint2_linear_25188_157943" x1="37.8985" y1="43.5495" x2="37.8985" y2="30.1875" gradientUnits="userSpaceOnUse">
<stop stop-color="#F2F3F5" stop-opacity="0.3"/>
<stop offset="1" stop-color="#F2F3F5"/>
</linearGradient>
<linearGradient id="paint3_linear_25188_157943" x1="207.83" y1="139.609" x2="207.83" y2="19.6875" gradientUnits="userSpaceOnUse">
<stop stop-color="white" stop-opacity="0.5"/>
<stop offset="1" stop-color="#F2F3F5"/>
</linearGradient>
<radialGradient id="paint4_radial_25188_157943" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(105 182.438) rotate(90) scale(27.5625 877.353)">
<stop stop-color="#EBEDF0"/>
<stop offset="1" stop-color="white" stop-opacity="0.01"/>
</radialGradient>
<linearGradient id="paint5_linear_25188_157943" x1="175.875" y1="148.312" x2="175.875" y2="174.562" gradientUnits="userSpaceOnUse">
<stop stop-color="#F2F3F5"/>
<stop offset="1" stop-color="#DCDEE0"/>
</linearGradient>
<linearGradient id="paint6_linear_25188_157943" x1="185.055" y1="187.688" x2="185.055" y2="174.562" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#DCDEE0"/>
</linearGradient>
<linearGradient id="paint7_linear_25188_157943" x1="19.6875" y1="148.312" x2="19.6875" y2="174.562" gradientUnits="userSpaceOnUse">
<stop stop-color="#F2F3F5"/>
<stop offset="1" stop-color="#DCDEE0"/>
</linearGradient>
<linearGradient id="paint8_linear_25188_157943" x1="28.8673" y1="187.688" x2="28.8673" y2="174.562" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#DCDEE0"/>
</linearGradient>
<linearGradient id="paint9_linear_25188_157943" x1="57.75" y1="65.625" x2="57.75" y2="152.25" gradientUnits="userSpaceOnUse">
<stop stop-color="#F2F3F5"/>
<stop offset="1" stop-color="#DCDEE0"/>
</linearGradient>
<linearGradient id="paint10_linear_25188_157943" x1="97.3111" y1="84" x2="95.1448" y2="97.782" gradientUnits="userSpaceOnUse">
<stop stop-color="#EAEDF1"/>
<stop offset="1" stop-color="#DCDEE0"/>
</linearGradient>
<linearGradient id="paint11_linear_25188_157943" x1="97.3111" y1="102.375" x2="95.1448" y2="116.157" gradientUnits="userSpaceOnUse">
<stop stop-color="#EAEDF1"/>
<stop offset="1" stop-color="#DCDEE0"/>
</linearGradient>
<linearGradient id="paint12_linear_25188_157943" x1="97.3111" y1="120.75" x2="95.1448" y2="134.532" gradientUnits="userSpaceOnUse">
<stop stop-color="#EAEDF1"/>
<stop offset="1" stop-color="#DCDEE0"/>
</linearGradient>
<linearGradient id="paint13_linear_25188_157943" x1="-4.18762" y1="164.063" x2="19.2534" y2="229.682" gradientUnits="userSpaceOnUse">
<stop stop-color="#EAEDF1"/>
<stop offset="1" stop-color="#DCDEE0"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

+20 -1
View File
@@ -49,7 +49,9 @@
.widget-item { .widget-item {
border-radius: 6px; border-radius: 6px;
background: rgba(255, 255, 255, 0.95); background: rgba(255, 255, 255, 0.95);
overflow: hidden; // 内置组件的浮层(如课表班级切换下拉)需溢出卡片,故不裁切;
// 卡片圆角由自身背景维持,疑似溢出子元素(iframe)自带底部圆角。
overflow: visible;
margin: 18px 14px 0 14px; margin: 18px 14px 0 14px;
&:first-child { &:first-child {
margin-top: 0; margin-top: 0;
@@ -71,17 +73,34 @@
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
border-bottom: 1px solid #e9e9e9; border-bottom: 1px solid #e9e9e9;
// 卡头浅灰底(原版观感;合成色曾随壁纸漂移,这里显式钉死)
background: #f7f8f9;
// .widget-item 已改 overflow:visible,卡头底色的顶部圆角需自补
border-radius: 6px 6px 0 0;
color: #344449; color: #344449;
font-weight: 700; font-weight: 700;
font-size: 16px; font-size: 16px;
svg { svg {
cursor: pointer; cursor: pointer;
} }
// 右区:内置组件 header 控件挂载点 + 关闭按钮(.widget-app-header 是 space-between,右区整体靠右)
.widget-header-right {
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
}
.widget-header-extra {
display: flex;
align-items: center;
}
} }
iframe { iframe {
width: 100%; width: 100%;
display: block; display: block;
min-height: 150px; min-height: 150px;
// .widget-item 已改为 overflow:visible,页面片段的底部圆角自行补齐
border-radius: 0 0 6px 6px;
} }
} }
+178 -65
View File
@@ -8,80 +8,124 @@
:paragraph="{ rows: 4 }" :paragraph="{ rows: 4 }"
animated animated
/> />
<div v-else-if="grid.length > 0" class="table-wrap">
<table class="my-table"> <template v-else-if="classes.length > 0">
<tr> <!-- 班级切换器:挂进卡片 header(index.vue 埋的 wg-hdr-<id> 锚点);多班(教师任教/班主任、校领导全校)才显示 -->
<th>节</th> <Teleport v-if="classes.length > 1" :to="'#wg-hdr-' + widgetId">
<th v-for="week in weekCols" :key="week.Weeks">{{ week.weekName }}</th> <div class="cls-dd" :class="{ open: ddOpen }">
</tr> <button type="button" class="cls-trigger" @click.stop="ddOpen = !ddOpen">
<tr v-for="row in grid" :key="row.label"> <span class="cls-name">{{ currentClass.className }}</span>
<td class="sec">{{ row.label }}</td> <svg class="caret" viewBox="0 0 1024 1024" width="10" height="10" aria-hidden="true">
<td v-for="(cell, index) in row.cells" :key="index"> <path fill="currentColor" d="M512 704 128 320l64-64 320 320 320-320 64 64z" />
<template v-if="cell"> </svg>
<div class="cla">{{ cell.ClassName }}</div> </button>
<div class="sub">{{ cell.SubName }}</div> <div v-show="ddOpen" class="cls-panel">
</template> <div
</td> v-for="(cls, index) in classes"
</tr> :key="cls.classId"
</table> class="cls-item"
</div> :class="{ on: index === clsIdx }"
<div v-else class="no-data">暂无数据</div> @click="pickClass(index)"
>
{{ cls.className }}
</div>
</div>
</div>
</Teleport>
<div v-if="slots.length > 0" class="table-wrap">
<table class="my-table">
<thead>
<tr>
<th>节</th>
<th v-for="day in dayCols" :key="day.index">{{ day.name }}</th>
</tr>
</thead>
<tbody>
<tr v-for="slot in slots" :key="slot.slotNo">
<td class="sec">{{ cnNum(slot.slotNo) }}</td>
<td v-for="day in dayCols" :key="day.index">
<template v-if="subjectOf(slot, day.index)">
<div class="cla">{{ currentClass.className }}</div>
<div class="sub">{{ subjectOf(slot, day.index) }}</div>
</template>
</td>
</tr>
</tbody>
</table>
</div>
<div v-else class="no-data-box"></div>
</template>
<div v-else class="no-data-box"></div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onMounted, onUnmounted, ref } from "vue"; import { computed, onBeforeUnmount, onMounted, ref } from "vue";
import UserSettingApi from "@/api/UserSettingApi"; import UserSettingApi from "@/api/UserSettingApi";
defineProps<{ widgetId: number }>(); defineProps<{ widgetId: number }>();
const emit = defineEmits(["loaded"]); const emit = defineEmits(["loaded"]);
/** 节次中文数字(下标 0 = 第 1 节) */
const CN_NUM = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十"];
/** 星期名(下标 0~6 = 周一~周日,对齐 slots[].subjects 下标口径) */
const WEEK_NAMES = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
const refRoot = ref<HTMLElement | null>(null); const refRoot = ref<HTMLElement | null>(null);
const loading = ref(true); const loading = ref(true);
const list = ref<any[]>([]); /** oapi data[]:每项一个班级(classId/className/timetable.slots…) */
const classes = ref<any[]>([]);
const clsIdx = ref(0);
const ddOpen = ref(false);
let observer: ResizeObserver | null = null; let observer: ResizeObserver | null = null;
/** 表头星期(按 Weeks 去重升序),口径同旧 syllabus_index.js weekArr */ const currentClass = computed<any>(() => classes.value[clsIdx.value] || {});
const weekCols = computed(() => {
const nameByKey: Record<number, string> = {}; /** 节次行:按 slotNo 升序(R2:按接口实际返回渲染) */
list.value.forEach(x => { const slots = computed<any[]>(() => {
if (nameByKey[x.Weeks] === undefined) nameByKey[x.Weeks] = x.weekName; const list = currentClass.value && currentClass.value.timetable && currentClass.value.timetable.slots;
}); if (!Array.isArray(list)) return [];
return Object.keys(nameByKey) return [...list].sort((a, b) => ((a && a.slotNo) || 0) - ((b && b.slotNo) || 0));
.map(key => ({ Weeks: Number(key), weekName: nameByKey[Number(key)] }))
.sort((a, b) => a.Weeks - b.Weeks);
}); });
/** 行节次(按 CourseTimes 去重升序),口径同旧 courseArr */ /** 星期列:恒 周一~周五;周六/周日有课才追加(R3) */
const courseRows = computed(() => { const dayCols = computed(() => {
const nameByKey: Record<number, string> = {}; const cols = [0, 1, 2, 3, 4];
list.value.forEach(x => { if (slots.value.some(slot => subjectOf(slot, 5))) cols.push(5);
if (nameByKey[x.CourseTimes] === undefined) nameByKey[x.CourseTimes] = x.CourseName; if (slots.value.some(slot => subjectOf(slot, 6))) cols.push(6);
}); return cols.map(index => ({ index, name: WEEK_NAMES[index] }));
return Object.keys(nameByKey)
.map(key => ({ CourseTimes: Number(key), CourseName: nameByKey[Number(key)] }))
.sort((a, b) => a.CourseTimes - b.CourseTimes);
}); });
const grid = computed(() => { function subjectOf(slot: any, index: number): string {
const cellByKey: Record<string, any> = {}; const arr = slot && slot.subjects;
list.value.forEach(x => { if (!Array.isArray(arr) || !arr[index]) return "";
cellByKey[`${x.CourseTimes}-${x.Weeks}`] = x; return String(arr[index]);
}); }
return courseRows.value.map(course => ({
label: (course.CourseName || "").replace("第", "").replace("节", ""), function cnNum(slotNo: number): string {
cells: weekCols.value.map(week => cellByKey[`${course.CourseTimes}-${week.Weeks}`]), return CN_NUM[slotNo - 1] || String(slotNo);
})); }
});
function pickClass(index: number) {
clsIdx.value = index;
ddOpen.value = false;
}
function closeDropdown() {
ddOpen.value = false;
}
onMounted(async () => { onMounted(async () => {
document.addEventListener("click", closeDropdown);
if (window.ResizeObserver && refRoot.value) { if (window.ResizeObserver && refRoot.value) {
observer = new ResizeObserver(reportHeight); observer = new ResizeObserver(reportHeight);
observer.observe(refRoot.value); observer.observe(refRoot.value);
} }
try { try {
const data: any = await UserSettingApi.getWidgetData("syllabus", ""); const data: any = await UserSettingApi.getWidgetData("syllabus", "");
list.value = Array.isArray(data) ? data : []; classes.value = Array.isArray(data) ? data : [];
} catch (e) { } catch (e) {
console.warn("[widget] syllabus 取数失败", e); console.warn("[widget] syllabus 取数失败", e);
} }
@@ -89,7 +133,8 @@ onMounted(async () => {
reportHeight(); reportHeight();
}); });
onUnmounted(() => { onBeforeUnmount(() => {
document.removeEventListener("click", closeDropdown);
if (observer) observer.disconnect(); if (observer) observer.disconnect();
}); });
@@ -100,8 +145,73 @@ function reportHeight() {
<style lang="scss" scoped> <style lang="scss" scoped>
.wg-syllabus { .wg-syllabus {
padding: 4px 0 10px; padding: 0 0 10px;
} }
/* ---------- 班级切换器(下拉;渲染在卡片 header 内,见 index.vue 的 wg-hdr-<id> 锚点) ---------- */
.cls-dd {
position: relative;
}
.cls-trigger {
display: inline-flex;
align-items: center;
gap: 4px;
border: 0;
background: transparent;
cursor: pointer;
font-family: inherit;
// header 是 700 粗体,切换器属次级信息 → 复位常规字重
font-weight: 400;
font-size: 13px;
color: #344449;
padding: 3px 8px;
border-radius: 6px;
line-height: 1.5;
&:hover {
background: #eef1f5;
}
.caret {
color: #98a2b0;
transition: transform 0.18s;
}
}
.cls-dd.open .caret {
transform: rotate(180deg);
}
.cls-panel {
position: absolute;
top: calc(100% + 6px);
right: 0;
z-index: 30;
min-width: 132px;
max-height: 264px;
overflow-y: auto;
background: #fff;
border: 1px solid #e7eaee;
border-radius: 8px;
box-shadow: 0 8px 24px rgba(16, 24, 40, 0.14);
padding: 4px;
}
.cls-item {
padding: 8px 12px;
border-radius: 6px;
font-size: 13px;
color: #344449;
cursor: pointer;
white-space: nowrap;
&:hover {
background: #f5f8fb;
}
&.on {
color: #2d8cf0;
background: #f0f7ff;
font-weight: 600;
}
}
/* ---------- 课表 ---------- */
.table-wrap { .table-wrap {
padding: 0 15px; padding: 0 15px;
} }
@@ -109,18 +219,19 @@ function reportHeight() {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
th { th {
line-height: 20px; height: 44px;
padding: 8px 0; font-size: 13px;
font-weight: 700; font-weight: 700;
font-size: 12px;
color: #6e7c87; color: #6e7c87;
text-align: center;
} }
td { td {
border-top: 1px solid #f7f7f7; height: 52px;
line-height: 15px; border-top: 1px solid #f2f4f6;
padding: 8px 0; padding: 4px 2px;
text-align: center; text-align: center;
font-size: 12px; font-size: 13px;
vertical-align: middle;
} }
td.sec { td.sec {
color: #6e7c87; color: #6e7c87;
@@ -128,17 +239,19 @@ function reportHeight() {
} }
.cla { .cla {
color: #344449; color: #344449;
line-height: 1.35;
} }
.sub { .sub {
color: #98a2b0; color: #98a2b0;
line-height: 1.35;
font-size: 12px;
} }
} }
.no-data { /* 空态:沿用原版 no-data-box.svg(插画 + 转曲「暂无数据」文案)。
min-height: 90px; 原版规则为 background-size:100px 100px(会压扁),此处取 100px auto 保比例。 */
display: flex; .no-data-box {
align-items: center; min-height: 130px;
justify-content: center; background: url("../../assets/image/no-data-box.svg") no-repeat 50% 50%;
color: #b9c2cc; background-size: 100px auto;
font-size: 13px;
} }
</style> </style>
+12 -8
View File
@@ -99,14 +99,18 @@
<div class="widget-item pr" v-for="item in widgetAppList"> <div class="widget-item pr" v-for="item in widgetAppList">
<div class="widget-app-header"> <div class="widget-app-header">
<span>{{ item.name }}</span> <span>{{ item.name }}</span>
<SvgIcon <!-- 内置组件在 header 里的挂载点:组件用 <Teleport> 把自身控件放进来(如课表班级切换器) -->
@click="onWidgetSelItemClick(item.id)" <div class="widget-header-right">
class="fr" <span class="widget-header-extra" :id="'wg-hdr-' + item.id"></span>
name="widget-close" <SvgIcon
size="18" @click="onWidgetSelItemClick(item.id)"
color="#999999" class="fr"
hoverColor="#646566" name="widget-close"
/> size="18"
color="#999999"
hoverColor="#646566"
/>
</div>
</div> </div>
<!-- ① front 工程内置组件:内容在代码库,不走 iframe --> <!-- ① front 工程内置组件:内容在代码库,不走 iframe -->
<component <component