changed.更了好多

This commit is contained in:
lincube
2026-05-12 16:46:49 +08:00
parent 563f12caa1
commit 33c264f6dd
127 changed files with 5257 additions and 10534 deletions

View File

@@ -0,0 +1,459 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>课程表组件 Mock - 阑山桌面</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--bg-primary: #F7F8FC;
--bg-secondary: #ECEFF6;
--bg-card: #FFFFFF;
--text-primary: #151821;
--text-secondary: #667084;
--text-muted: #9AA3B2;
--border-color: rgba(0,0,0,0.06);
--surface-raised: #FFFFFF;
--accent: #FF4D5A;
--time-color: #848B99;
--divider-color: rgba(0,0,0,0.04);
}
.dark {
--bg-primary: #171A21;
--bg-secondary: #0C0E14;
--bg-card: rgba(255,255,255,0.04);
--text-primary: #F9FBFF;
--text-secondary: #848B99;
--text-muted: #5A6170;
--border-color: rgba(255,255,255,0.08);
--surface-raised: #1E2230;
--accent: #4FC3F7;
--time-color: #6B7280;
--divider-color: rgba(255,255,255,0.04);
}
body {
font-family: -apple-system, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
background: #1a1a2e;
display: flex;
flex-direction: column;
align-items: center;
gap: 32px;
padding: 40px 20px;
min-height: 100vh;
}
.controls {
display: flex;
gap: 16px;
align-items: center;
}
.controls button {
padding: 8px 20px;
border: 1px solid rgba(255,255,255,0.2);
border-radius: 8px;
background: rgba(255,255,255,0.1);
color: #fff;
cursor: pointer;
font-size: 14px;
transition: all 0.2s;
}
.controls button:hover { background: rgba(255,255,255,0.2); }
.controls button.active { background: rgba(79,195,247,0.3); border-color: #4FC3F7; }
.mock-container {
display: flex;
gap: 32px;
flex-wrap: wrap;
justify-content: center;
}
.widget {
width: 320px;
border-radius: 24px;
overflow: hidden;
background: linear-gradient(135deg, var(--bg-primary), var(--bg-secondary));
border: 1px solid var(--border-color);
box-shadow: 0 8px 32px rgba(0,0,0,0.12);
transition: all 0.3s;
}
.widget.large {
width: 380px;
}
.widget-header {
padding: 16px 16px 10px 16px;
display: flex;
align-items: center;
justify-content: space-between;
}
.date-group {
display: flex;
align-items: baseline;
gap: 1px;
}
.date-group .month, .date-group .day {
font-size: 32px;
font-weight: 700;
color: var(--text-primary);
line-height: 1;
}
.date-group .slash {
font-size: 32px;
font-weight: 700;
color: var(--accent);
line-height: 1;
margin: 0 1px;
}
.header-center {
flex: 1;
text-align: center;
}
.weekday {
font-size: 15px;
font-weight: 600;
color: var(--text-secondary);
}
.class-count-badge {
padding: 4px 10px;
border-radius: 10px;
background: rgba(79,195,247,0.12);
font-size: 13px;
font-weight: 600;
color: var(--accent);
white-space: nowrap;
}
.dark .class-count-badge {
background: rgba(79,195,247,0.15);
}
.course-list {
padding: 4px 12px 12px 12px;
display: flex;
flex-direction: column;
gap: 6px;
}
.course-item {
display: grid;
grid-template-columns: 44px 1fr;
gap: 8px;
align-items: stretch;
min-height: 56px;
}
.time-column {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-end;
padding-right: 4px;
gap: 2px;
}
.time-start {
font-size: 12px;
font-weight: 600;
color: var(--time-color);
line-height: 1.2;
font-variant-numeric: tabular-nums;
}
.time-end {
font-size: 10px;
font-weight: 500;
color: var(--text-muted);
line-height: 1.2;
font-variant-numeric: tabular-nums;
}
.course-card {
border-radius: 12px;
padding: 10px 12px;
position: relative;
overflow: hidden;
transition: all 0.2s;
min-height: 52px;
display: flex;
flex-direction: column;
gap: 2px;
}
.course-card.current {
min-height: 60px;
}
.course-card .accent-bar {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 3px;
border-radius: 0 2px 2px 0;
}
.course-name {
font-size: 14px;
font-weight: 700;
line-height: 1.3;
padding-left: 4px;
}
.course-detail {
font-size: 11px;
font-weight: 500;
color: var(--text-secondary);
line-height: 1.3;
padding-left: 4px;
}
.progress-container {
margin-top: 4px;
padding-left: 4px;
display: flex;
align-items: center;
gap: 6px;
}
.progress-bar {
flex: 1;
height: 3px;
border-radius: 2px;
background: rgba(255,255,255,0.15);
overflow: hidden;
}
.dark .progress-bar {
background: rgba(255,255,255,0.1);
}
.progress-fill {
height: 100%;
border-radius: 2px;
transition: width 0.5s ease;
}
.progress-text {
font-size: 10px;
font-weight: 600;
min-width: 28px;
text-align: right;
}
.break-indicator {
display: grid;
grid-template-columns: 44px 1fr;
gap: 8px;
padding: 2px 0;
}
.break-line {
grid-column: 2;
border-top: 1px dashed var(--divider-color);
margin: 2px 12px;
}
.status-empty {
padding: 40px 16px;
text-align: center;
color: var(--text-muted);
font-size: 14px;
}
.label {
color: #aaa;
font-size: 13px;
text-align: center;
margin-top: -16px;
}
</style>
</head>
<body>
<div class="controls">
<button id="btnLight" class="active" onclick="setTheme('light')">☀️ 亮色</button>
<button id="btnDark" onclick="setTheme('dark')">🌙 暗色</button>
</div>
<div class="mock-container">
<div>
<div class="widget" id="widgetLight">
<div class="widget-header">
<div class="date-group">
<span class="month">7</span>
<span class="slash">/</span>
<span class="day">24</span>
</div>
<div class="header-center">
<span class="weekday">周一</span>
</div>
<div class="class-count-badge">6节课</div>
</div>
<div class="course-list" id="courseListLight"></div>
</div>
<p class="label">2×4 标准尺寸</p>
</div>
<div>
<div class="widget large" id="widgetDark">
<div class="widget-header">
<div class="date-group">
<span class="month">7</span>
<span class="slash">/</span>
<span class="day">24</span>
</div>
<div class="header-center">
<span class="weekday">周一</span>
</div>
<div class="class-count-badge">6节课</div>
</div>
<div class="course-list" id="courseListDark"></div>
</div>
<p class="label">4×4 大尺寸</p>
</div>
</div>
<script>
const SUBJECT_COLORS = {
'语文': '#5B8FF9',
'数学': '#F6903D',
'英语': '#5AD8A6',
'物理': '#E8684A',
'化学': '#9270CA',
'生物': '#FF9845',
'历史': '#1E9493',
'地理': '#FF99C3',
'政治': '#7262FD',
'体育': '#78D3F8',
'音乐': '#F25E7E',
'美术': '#C2A1FD',
};
const DEFAULT_COLOR = '#8B95A5';
function getColor(name) {
for (const [key, val] of Object.entries(SUBJECT_COLORS)) {
if (name.includes(key)) return val;
}
let hash = 5381;
for (let i = 0; i < name.length; i++) hash = ((hash << 5) + hash) ^ name.charCodeAt(i);
const keys = Object.keys(SUBJECT_COLORS);
return SUBJECT_COLORS[keys[Math.abs(hash) % keys.length]];
}
function hexToRgba(hex, alpha) {
const r = parseInt(hex.slice(1,3), 16);
const g = parseInt(hex.slice(3,5), 16);
const b = parseInt(hex.slice(5,7), 16);
return `rgba(${r},${g},${b},${alpha})`;
}
const courses = [
{ name: '语文', start: '08:00', end: '08:45', detail: '王老师 · 教室301', isCurrent: false, progress: 0 },
{ name: '数学', start: '08:55', end: '09:40', detail: '李老师 · 教室205', isCurrent: true, progress: 0.62 },
{ name: '英语', start: '09:50', end: '10:35', detail: '张老师 · 教室108', isCurrent: false, progress: 0 },
{ name: '物理', start: '10:45', end: '11:30', detail: '赵老师 · 实验室2', isCurrent: false, progress: 0 },
{ name: '化学', start: '14:00', end: '14:45', detail: '陈老师 · 实验室1', isCurrent: false, progress: 0 },
{ name: '生物', start: '14:55', end: '15:40', detail: '刘老师 · 教室303', isCurrent: false, progress: 0 },
];
function renderCourseList(containerId, isDark) {
const container = document.getElementById(containerId);
container.innerHTML = '';
courses.forEach((course, idx) => {
const color = getColor(course.name);
const bgAlpha = course.isCurrent ? 0.15 : 0.07;
const bgColor = hexToRgba(color, bgAlpha);
const fgColor = isDark
? hexToRgba(color, 1).replace('rgb', 'rgb').replace(')', ',1)') || color
: color;
if (idx > 0) {
const breakEl = document.createElement('div');
breakEl.className = 'break-indicator';
breakEl.innerHTML = `<div></div><div class="break-line"></div>`;
container.appendChild(breakEl);
}
const item = document.createElement('div');
item.className = 'course-item';
const timeCol = document.createElement('div');
timeCol.className = 'time-column';
timeCol.innerHTML = `
<span class="time-start">${course.start}</span>
<span class="time-end">${course.end}</span>
`;
const card = document.createElement('div');
card.className = 'course-card' + (course.isCurrent ? ' current' : '');
card.style.background = bgColor;
let cardHTML = '';
if (course.isCurrent) {
cardHTML += `<div class="accent-bar" style="background:${color}"></div>`;
}
cardHTML += `<div class="course-name" style="color:${fgColor}">${course.name}</div>`;
cardHTML += `<div class="course-detail">${course.detail}</div>`;
if (course.isCurrent) {
const pct = Math.round(course.progress * 100);
cardHTML += `
<div class="progress-container">
<div class="progress-bar">
<div class="progress-fill" style="width:${pct}%;background:${color}"></div>
</div>
<span class="progress-text" style="color:${fgColor}">${pct}%</span>
</div>
`;
}
card.innerHTML = cardHTML;
item.appendChild(timeCol);
item.appendChild(card);
container.appendChild(item);
});
}
function setTheme(theme) {
const btnLight = document.getElementById('btnLight');
const btnDark = document.getElementById('btnDark');
const widgetLight = document.getElementById('widgetLight');
const widgetDark = document.getElementById('widgetDark');
if (theme === 'dark') {
btnDark.classList.add('active');
btnLight.classList.remove('active');
widgetLight.classList.add('dark');
widgetDark.classList.add('dark');
} else {
btnLight.classList.add('active');
btnDark.classList.remove('active');
widgetLight.classList.remove('dark');
widgetDark.classList.remove('dark');
}
renderCourseList('courseListLight', theme === 'dark');
renderCourseList('courseListDark', theme === 'dark');
}
renderCourseList('courseListLight', false);
renderCourseList('courseListDark', false);
</script>
</body>
</html>