Files
wechat-clock-mini/pages/plan/plan.wxss
王宏豪 ba2d9245ef feat(api): 重构图片地址管理与上传机制
- 替换开发环境API基础URL为本地服务地址
- 实现签名URL本地缓存机制,解决微信按URL缓存图片导致重复下载问题
- 添加缓存清理功能,包括过期清理和按需删除特定缓存项
- 集成阿里云OSS上传功能,支持直传减少服务器带宽占用
- 优化头像地址处理逻辑,统一使用签名缓存避免地址频繁变化
- 移除过时的OSS上传示例文件oss-upload.js
- 更新课程页面实现跳转第三方小程序功能
- 调整打卡记录图片地址获取方式,统一使用新的签名缓存逻辑
- 优化图片上传流程,增加压缩处理和批量上传支持
- 完善认证模块中的缓存清理逻辑,切换账号时清除相关图片缓存
- 添加后端环境变量配置模板和代理文档说明
2026-09-23 17:46:40 +08:00

341 lines
13 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
.page { height: 100vh; display: flex; flex-direction: column; box-sizing: border-box; overflow: hidden; background: #F6F2EC; }
.view-root { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.type-tabs { flex-shrink: 0; display: flex; align-items: center; gap: 8rpx; margin: 24rpx 32rpx 0; padding: 8rpx; background: #EFE7DC; border-radius: 999rpx; }
.type-tab { flex: 1; text-align: center; padding: 16rpx 0; color: #8B7A6A; background: transparent; border-radius: 999rpx; font-size: 28rpx; font-weight: 600; transition: all .18s ease; }
.type-tab.active { background: #fff; color: #C67B30; font-weight: 700; box-shadow: 0 4rpx 12rpx rgba(198,123,48,0.18); }
.type-tab-hover { opacity: .85; }
.view-scroll { flex: 1; min-height: 0; padding: 8rpx 32rpx 32rpx; box-sizing: border-box; }
.overview-head { display: flex; align-items: flex-end; justify-content: space-between; padding: 24rpx 4rpx 16rpx; }
.head-title-wrap { min-width: 0; }
.head-title { font-size: 38rpx; font-weight: 800; color: #2C1810; letter-spacing: 1rpx; }
.head-sub { margin-top: 6rpx; font-size: 24rpx; color: #A99A89; }
.head-pill { flex-shrink: 0; padding: 8rpx 20rpx; border-radius: 999rpx; font-size: 22rpx; background: #fff; color: #C67B30; box-shadow: 0 2rpx 8rpx rgba(44,24,16,0.06); }
.detail-head { display: flex; align-items: center; gap: 16rpx; padding: 28rpx 4rpx 8rpx; }
.detail-title-wrap { min-width: 0; }
.back { color: #C67B30; font-size: 30rpx; flex-shrink: 0; padding: 10rpx 16rpx 10rpx 0; border-radius: 12rpx; font-weight: 600; }
.back-hover { opacity: .7; }
.my-status { display: flex; align-items: center; gap: 18rpx; padding: 24rpx; margin-bottom: 20rpx; border-radius: 20rpx; background: #fff; box-shadow: 0 6rpx 20rpx rgba(44,24,16,0.05); }
.my-status.checked { border-left: 8rpx solid #2E7D32; }
.my-status.unchecked { border-left: 8rpx solid #C0392B; }
.my-state-icon { width: 64rpx; height: 64rpx; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 30rpx; font-weight: 800; flex-shrink: 0; }
.my-state-icon.done { background: linear-gradient(135deg, #2E7D32, #43A047); color: #fff; box-shadow: 0 4rpx 12rpx rgba(46,125,50,0.25); }
.my-state-icon.todo { background: linear-gradient(135deg, #C0392B, #E5736C); color: #fff; box-shadow: 0 4rpx 12rpx rgba(192,57,43,0.22); }
.my-status-left { flex: 1; min-width: 0; }
.my-status-label { font-size: 24rpx; color: #8B7A6A; }
.my-status-text { font-size: 32rpx; font-weight: 800; color: #2C1810; margin-top: 6rpx; }
.btn-mystatus { width: 208rpx; margin: 0; flex-shrink: 0; background: linear-gradient(135deg, #C67B30, #E4A05E); color: #fff; border-radius: 999rpx; font-size: 28rpx; font-weight: 700; box-shadow: 0 6rpx 14rpx rgba(198,123,48,0.3); }
.btn-mystatus.outline { background: #fff; color: #C67B30; border: 2rpx solid #C67B30; box-shadow: none; }
.btn-mystatus[disabled] { background: #D8C7B4; color: #fff; border: none; box-shadow: none; }
.btn-hover { opacity: .9; transform: scale(.98); }
.window-msg { margin: 0 8rpx 20rpx; padding: 14rpx 22rpx; background: #FFF3E6; border-radius: 14rpx; text-align: center; color: #C0392B; font-size: 24rpx; border: 1rpx solid #F7D9B9; }
.my-plan { margin-bottom: 20rpx; padding: 24rpx; border-radius: 20rpx; background: #fff; box-shadow: 0 6rpx 20rpx rgba(44,24,16,0.05); }
.my-plan-head { display: flex; align-items: center; justify-content: space-between; }
.my-plan-title { font-size: 26rpx; font-weight: 700; color: #6B5D50; }
.my-plan-status { padding: 6rpx 16rpx; border-radius: 999rpx; font-size: 22rpx; font-weight: 700; background: #E8F4EB; color: #2E7D32; }
.my-plan-status.pending { background: #FFF3E6; color: #C67B30; }
.my-plan-meta { margin-top: 8rpx; font-size: 22rpx; color: #A99A89; }
.my-plan-content { margin-top: 14rpx; padding: 16rpx 20rpx; background: #FBF7F1; border-radius: 14rpx; font-size: 28rpx; line-height: 1.7; color: #2C1810; white-space: pre-wrap; word-break: break-all; }
.my-plan-thumbs { display: flex; flex-wrap: wrap; gap: 14rpx; margin-top: 16rpx; }
.my-plan-thumb { width: 148rpx; height: 148rpx; border-radius: 14rpx; background: #F2EDE7; box-shadow: 0 2rpx 6rpx rgba(44,24,16,0.08); }
.group-card { background: #fff; border-radius: 20rpx; padding: 22rpx 24rpx; margin-bottom: 18rpx; box-shadow: 0 6rpx 20rpx rgba(44,24,16,0.05); }
.group-card-hover { transform: scale(.99); box-shadow: 0 10rpx 24rpx rgba(44,24,16,0.10); }
.group-row { display: flex; align-items: center; gap: 16rpx; }
.group-avatar { width: 52rpx; height: 52rpx; border-radius: 14rpx; background: linear-gradient(135deg, #F3E3CF, #FBE7D1); color: #C67B30; font-size: 26rpx; font-weight: 800; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.group-name { font-size: 30rpx; font-weight: 800; color: #2C1810; flex-shrink: 0; }
.chevron { color: #CDBFAE; font-size: 32rpx; line-height: 1; flex-shrink: 0; transition: transform .15s ease; }
.group-card-hover .chevron { transform: translateX(4rpx); }
.group-counts { display: flex; align-items: center; justify-content: flex-end; gap: 10rpx; flex: 1; min-width: 0; }
.count { font-size: 22rpx; white-space: nowrap; }
.count.done { color: #2E7D32; background: #E8F4EB; padding: 6rpx 12rpx; border-radius: 999rpx; font-weight: 700; }
.count.total { color: #C67B30; background: #FFF3E6; padding: 6rpx 12rpx; border-radius: 999rpx; font-weight: 700; }
.progress-track { height: 10rpx; border-radius: 999rpx; background: #F2EDE7; margin-top: 18rpx; overflow: hidden; }
.progress-bar { height: 100%; border-radius: 999rpx; background: linear-gradient(90deg, #C67B30, #EFA45D); transition: width .35s ease; box-shadow: 0 2rpx 6rpx rgba(198,123,48,0.35); }
.unassigned { margin: 4rpx 8rpx 20rpx; font-size: 24rpx; color: #8B7A6A; }
.member-list { background: #fff; border-radius: 20rpx; padding: 8rpx 24rpx; box-shadow: 0 6rpx 20rpx rgba(44,24,16,0.05); }
.member-left { display: flex; align-items: center; min-width: 0; }
.member { display: flex; flex-direction: column; align-items: stretch; padding: 22rpx 0; border-bottom: 1rpx solid #F2EDE7; }
.member:last-child { border-bottom: none; }
.member-row { display: flex; align-items: center; justify-content: space-between; }
.member-avatar { width: 64rpx; height: 64rpx; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 26rpx; font-weight: 800; flex-shrink: 0; }
.member-avatar.done { background: linear-gradient(135deg, #E8F4EB, #CFEAD5); color: #2E7D32; }
.member-avatar.unchecked { background: linear-gradient(135deg, #FDECEA, #F9D9D5); color: #C0392B; }
.member-info { margin-left: 18rpx; min-width: 0; }
/* 姓名与学号同一行;姓名过长时省略,学号始终完整 */
.member-line { display: flex; align-items: baseline; gap: 12rpx; }
.member-name { font-size: 28rpx; font-weight: 700; color: #2C1810; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.member-sid { font-size: 22rpx; color: #A99A89; flex-shrink: 0; }
.member-meta { margin-top: 6rpx; font-size: 22rpx; color: #A99A89; }
.badge { flex-shrink: 0; padding: 8rpx 18rpx; border-radius: 999rpx; font-size: 22rpx; font-weight: 700; }
.badge.done { background: #E8F4EB; color: #2E7D32; }
.badge.unchecked { background: #FDECEA; color: #C0392B; }
.state-block { padding: 64rpx 0; text-align: center; color: #A99A89; font-size: 26rpx; }
.state-icon { font-size: 40rpx; margin-bottom: 12rpx; color: #D8C7B4; animation: pulse 1.2s ease-in-out infinite; }
@keyframes pulse { 0%,100%{opacity:.4} 50%{opacity:1} }
.empty { padding: 64rpx 0; text-align: center; color: #A99A89; font-size: 26rpx; }
/* 小组标题 */
.section-title { padding: 8rpx 4rpx 16rpx; font-size: 28rpx; font-weight: 700; color: #6B5D50; }
/* 学员小组 tab:周期选择行 */
.group-period-row {
display: flex;
align-items: center;
padding: 12rpx 8rpx;
font-size: 28rpx;
font-weight: 700;
color: #C67B30;
}
.group-period-text {
flex: 1;
}
/* 学员单小组卡片 */
.student-group { margin-bottom: 20rpx; }
/* 学员 tab 切换 */
.student-tabs {
display: flex;
border-bottom: 1rpx solid #EEE;
margin: 8rpx 0 8rpx;
}
.student-tab {
flex: 1;
text-align: center;
padding: 22rpx 0;
color: #7A6A5C;
transition: color .15s ease;
font-size: 28rpx;
}
.student-tab.active {
color: #C67B30;
font-weight: 700;
border-bottom: 4rpx solid #C67B30;
transform: translateY(-2rpx);
}
.tab-hover {
background: #f6efe6;
}
.student-group-panel {
padding: 4rpx 0 24rpx;
}
.student-history-panel {
padding: 16rpx 0 24rpx;
}
/* 历史记录卡片 */
.history-card {
background: #fff;
border-radius: 20rpx;
padding: 24rpx;
margin-bottom: 18rpx;
box-shadow: 0 6rpx 20rpx rgba(44, 24, 16, 0.05);
transition: transform .15s ease, box-shadow .15s ease;
}
.history-card-hover { transform: scale(.99); box-shadow: 0 10rpx 24rpx rgba(44, 24, 16, 0.10); }
.history-head {
display: flex;
align-items: center;
justify-content: space-between;
}
.history-period {
font-size: 30rpx;
font-weight: 700;
color: #2C1810;
}
.history-status {
padding: 6rpx 16rpx;
border-radius: 999rpx;
font-size: 22rpx;
font-weight: 700;
}
.history-meta {
margin-top: 8rpx;
font-size: 22rpx;
color: #A99A89;
}
/* 历史卡片内的正文预览:最多 3 行,超出截断 */
.history-content {
margin-top: 14rpx;
padding: 16rpx 20rpx;
background: #FBF7F1;
border-radius: 14rpx;
font-size: 26rpx;
line-height: 1.7;
color: #2C1810;
white-space: pre-wrap;
word-break: break-all;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}
/* 历史卡片内的缩略图:最多 2 张,其余进详情弹层 */
.history-thumbs {
display: flex;
flex-wrap: wrap;
gap: 12rpx;
margin-top: 14rpx;
}
.history-thumb {
width: 148rpx;
height: 148rpx;
border-radius: 12rpx;
background: #F2EDE7;
}
/* 周期选择相关 */
.head-hover { opacity: .8; }
.head-arrow { color: #C67B30; font-size: 22rpx; }
.picker-mask {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.4);
z-index: 100;
}
.picker-panel {
position: fixed;
left: 0; right: 0; bottom: 0;
background: #fff;
border-radius: 28rpx 28rpx 0 0;
z-index: 101;
max-height: 70vh;
display: flex;
flex-direction: column;
overflow: hidden;
transform: translateY(100%);
transition: transform .28s ease;
}
.picker-panel.show {
transform: translateY(0);
}
.picker-title {
flex-shrink: 0;
padding: 28rpx 32rpx 20rpx;
font-size: 30rpx;
font-weight: 700;
color: #2C1810;
text-align: center;
border-bottom: 1rpx solid #F2EDE7;
}
/* flex:1 撑满剩余高度,max-height 兜底(同 .cd-body,防 flex 高度解析失败后滚不动) */
.picker-list {
flex: 1 1 auto;
min-height: 0;
max-height: 64vh;
padding: 8rpx 0 32rpx;
}
.picker-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx 32rpx;
font-size: 28rpx;
color: #2C1810;
}
.picker-item:active {
background: #FBF7F1;
}
.picker-item.active {
color: #C67B30;
font-weight: 700;
}
.picker-check {
font-size: 28rpx;
color: #C67B30;
}
/* 底部留白 */
.bottom-space { height: 40rpx; }
/* 信息行的点击反馈;正文与图片统一在详情弹层里看 */
.member-row-hover { opacity: .7; }
.tap-hint { margin-top: 10rpx; text-align: right; font-size: 22rpx; color: #C67B30; }
.tap-hint-hover { opacity: .7; }
/* 内容详情弹层 */
.cd-mask {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.45);
z-index: 200;
}
.cd-panel {
position: fixed;
left: 0; right: 0; bottom: 0;
z-index: 201;
max-height: 86vh;
display: flex;
flex-direction: column;
overflow: hidden;
background: #fff;
border-radius: 28rpx 28rpx 0 0;
animation: cdIn .22s ease;
}
@keyframes cdIn {
from { transform: translateY(40rpx); opacity: .5; }
to { transform: translateY(0); opacity: 1; }
}
.cd-head { flex-shrink: 0; display: flex; align-items: flex-start; gap: 16rpx; padding: 28rpx 32rpx 16rpx; }
.cd-head-text { flex: 1; min-width: 0; }
.cd-title { font-size: 34rpx; font-weight: 800; color: #2C1810; }
.cd-sub { margin-top: 8rpx; font-size: 24rpx; color: #A99A89; }
.cd-close {
flex-shrink: 0;
width: 56rpx; height: 56rpx; line-height: 56rpx;
text-align: center;
border-radius: 50%;
background: #F6F2EC;
color: #8B7A6A;
font-size: 26rpx;
}
.cd-close-hover { opacity: .7; }
.cd-meta {
flex-shrink: 0;
padding: 0 32rpx 16rpx;
font-size: 22rpx;
color: #A99A89;
border-bottom: 1rpx solid #F2EDE7;
}
/*
* 滚动区:flex:1 吃掉剩余高度;max-height 兜底 —— 部分基础库下
* max-height 父容器里的 flex 子项算不出高度,会导致内容被截断且滚不动。
* 双保险下无论哪种情况都有明确高度上限,内容超出即可上下滑动。
*/
.cd-body {
flex: 1 1 auto;
min-height: 0;
max-height: 64vh;
padding: 20rpx 32rpx calc(60rpx + env(safe-area-inset-bottom));
box-sizing: border-box;
}
.cd-content {
padding: 20rpx 24rpx;
background: #FBF7F1;
border-radius: 14rpx;
font-size: 28rpx;
line-height: 1.8;
color: #2C1810;
white-space: pre-wrap;
word-break: break-all;
}
.cd-no-content { padding: 12rpx 4rpx; font-size: 26rpx; color: #A99A89; }
.cd-thumbs { margin-top: 20rpx; }
.cd-thumb {
display: block;
width: 100%;
margin-bottom: 16rpx;
border-radius: 14rpx;
background: #F2EDE7;
}