2025-04-22 10:22:33 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view class="mine-page">
|
2025-06-14 13:09:26 +08:00
|
|
|
|
<!-- 1. 顶部 Header - 复制自service页面 -->
|
|
|
|
|
|
<view class="header-section">
|
|
|
|
|
|
<view class="header-gradient"></view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 退出按钮 -->
|
|
|
|
|
|
<view class="logout-btn" @click="handleLogout">
|
|
|
|
|
|
<text class="logout-text">退出</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 老师信息 -->
|
|
|
|
|
|
<view class="teacher-info">
|
|
|
|
|
|
<view class="teacher-avatar">
|
|
|
|
|
|
<image
|
|
|
|
|
|
class="avatar-image"
|
|
|
|
|
|
:src="teacherData.avatar || '/static/base/default-avatar.png'"
|
|
|
|
|
|
mode="aspectFill"
|
|
|
|
|
|
></image>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="teacher-details">
|
|
|
|
|
|
<view class="teacher-name">{{ teacherData.name }}</view>
|
2025-08-27 22:25:20 +08:00
|
|
|
|
<view class="teacher-position">{{ teacherPosition }}</view>
|
2025-06-14 13:09:26 +08:00
|
|
|
|
<view class="teacher-class">{{ teacherData.className }}</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
2025-08-27 22:25:20 +08:00
|
|
|
|
<!-- 统计信息 - 暂时隐藏 -->
|
|
|
|
|
|
<!-- <view class="stats-info">
|
2025-06-14 13:09:26 +08:00
|
|
|
|
<view class="stat-item">
|
|
|
|
|
|
<text class="stat-label">积分:</text>
|
|
|
|
|
|
<text class="stat-value">{{ teacherData.score }}分</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="stat-divider">|</view>
|
|
|
|
|
|
<view class="stat-item">
|
|
|
|
|
|
<text class="stat-label">工作量:</text>
|
|
|
|
|
|
<text class="stat-value">{{ teacherData.workload }}课时</text>
|
|
|
|
|
|
</view>
|
2025-08-27 22:25:20 +08:00
|
|
|
|
</view> -->
|
2025-06-14 13:09:26 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- 介绍文字 -->
|
|
|
|
|
|
<view class="teacher-intro">
|
|
|
|
|
|
{{ teacherData.introduction }}
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 2. 日程管理区域 -->
|
|
|
|
|
|
<view class="main-content">
|
|
|
|
|
|
<!-- 近期日程标题 -->
|
|
|
|
|
|
<view class="schedule-header">
|
|
|
|
|
|
<text class="schedule-title">近期日程</text>
|
|
|
|
|
|
<view class="schedule-link" @click="goToSchedule">
|
|
|
|
|
|
<text class="link-text">查看日程</text>
|
|
|
|
|
|
<text class="link-arrow">></text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 日期选择器 -->
|
|
|
|
|
|
<view class="date-selector">
|
|
|
|
|
|
<view class="date-container">
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="date-item"
|
|
|
|
|
|
v-for="(date, index) in weekDates"
|
|
|
|
|
|
:key="index"
|
|
|
|
|
|
:class="{ active: selectedDateIndex === index }"
|
|
|
|
|
|
@click="selectDate(index)"
|
|
|
|
|
|
>
|
|
|
|
|
|
<text class="date-day">{{ date.day }}</text>
|
|
|
|
|
|
<text class="date-number">{{ date.number }}</text>
|
|
|
|
|
|
<view v-if="date.hasEvent" class="date-dot"></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 日程列表 -->
|
|
|
|
|
|
<scroll-view class="schedule-list" scroll-y="true" show-scrollbar="false" enhanced="true">
|
|
|
|
|
|
<view class="schedule-content">
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="schedule-item"
|
|
|
|
|
|
v-for="(item, index) in getCurrentSchedule"
|
|
|
|
|
|
:key="index"
|
|
|
|
|
|
>
|
|
|
|
|
|
<view class="time-column">
|
|
|
|
|
|
<text class="start-time">{{ item.startTime }}</text>
|
|
|
|
|
|
<text class="end-time" v-if="item.endTime">{{ item.endTime }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="content-column">
|
|
|
|
|
|
<view class="event-header">
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="event-tag"
|
|
|
|
|
|
:class="item.type"
|
|
|
|
|
|
v-if="item.tag"
|
|
|
|
|
|
>
|
|
|
|
|
|
<text class="tag-text">{{ item.tag }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<text class="event-title">{{ item.title }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="event-details" v-if="item.details">
|
|
|
|
|
|
<view class="event-location" v-if="item.location">
|
|
|
|
|
|
<text class="location-icon">📍</text>
|
|
|
|
|
|
<text class="location-text">{{ item.location }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="event-description" v-if="item.description">
|
|
|
|
|
|
<text class="description-icon">📝</text>
|
|
|
|
|
|
<text class="description-text">{{ item.description }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 无日程时的提示 -->
|
|
|
|
|
|
<view class="no-schedule" v-if="getCurrentSchedule.length === 0">
|
|
|
|
|
|
<text class="no-schedule-text">暂无日程安排</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</scroll-view>
|
|
|
|
|
|
</view>
|
2025-04-22 10:22:33 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2025-06-14 13:09:26 +08:00
|
|
|
|
import { useUserStore } from "@/store/modules/user";
|
2025-08-27 22:25:20 +08:00
|
|
|
|
import { useCommonStore } from "@/store/modules/common";
|
2025-06-14 13:09:26 +08:00
|
|
|
|
import { imagUrl } from "@/utils";
|
|
|
|
|
|
import { reactive, ref, computed, onMounted } from "vue";
|
|
|
|
|
|
|
|
|
|
|
|
// 定义老师数据接口
|
|
|
|
|
|
interface TeacherData {
|
|
|
|
|
|
name: string;
|
|
|
|
|
|
position: string;
|
|
|
|
|
|
className: string;
|
|
|
|
|
|
score: number;
|
|
|
|
|
|
workload: number;
|
|
|
|
|
|
introduction: string;
|
|
|
|
|
|
avatar?: string;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 日程数据接口
|
|
|
|
|
|
interface ScheduleItem {
|
|
|
|
|
|
startTime: string;
|
|
|
|
|
|
endTime?: string;
|
|
|
|
|
|
title: string;
|
|
|
|
|
|
type: string;
|
|
|
|
|
|
tag?: string;
|
|
|
|
|
|
location?: string;
|
|
|
|
|
|
description?: string;
|
|
|
|
|
|
details?: boolean;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 日期数据接口
|
|
|
|
|
|
interface DateItem {
|
|
|
|
|
|
day: string;
|
|
|
|
|
|
number: string;
|
|
|
|
|
|
hasEvent: boolean;
|
|
|
|
|
|
date: string;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-27 22:25:20 +08:00
|
|
|
|
const { logout, getUser, getJs } = useUserStore();
|
|
|
|
|
|
const { getZwListByLx } = useCommonStore();
|
|
|
|
|
|
|
|
|
|
|
|
// 职务标签
|
|
|
|
|
|
const dzZwLabel = ref<string>("");
|
|
|
|
|
|
const qtZwLabel = ref<string>("");
|
2025-06-14 13:09:26 +08:00
|
|
|
|
|
|
|
|
|
|
// 老师数据
|
|
|
|
|
|
const teacherData = reactive<TeacherData>({
|
2025-08-27 22:25:20 +08:00
|
|
|
|
name: getJs.jsxm || getUser.loginName,
|
|
|
|
|
|
position: "", // 将在初始化时设置
|
|
|
|
|
|
className: getJs.njz || "",
|
|
|
|
|
|
score: 88, // 默认值,后续可以从接口获取
|
|
|
|
|
|
workload: 40, // 默认值,后续可以从接口获取
|
|
|
|
|
|
introduction: getJs.introduction || "北冥有鱼,其名为鲲。鲲之大,不知其几千里也。",
|
2025-06-14 13:09:26 +08:00
|
|
|
|
avatar: imagUrl(getUser.profilePhoto),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-08-27 22:25:20 +08:00
|
|
|
|
// 计算属性:动态获取职务信息
|
|
|
|
|
|
const teacherPosition = computed(() => {
|
|
|
|
|
|
const positions = [];
|
|
|
|
|
|
if (dzZwLabel.value) positions.push(dzZwLabel.value);
|
|
|
|
|
|
if (qtZwLabel.value) positions.push(qtZwLabel.value);
|
|
|
|
|
|
return positions.join('、') || '暂无职务信息';
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-06-14 13:09:26 +08:00
|
|
|
|
// 退出登录
|
|
|
|
|
|
const handleLogout = () => {
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: "确认退出",
|
|
|
|
|
|
content: "确定要退出登录吗?",
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
if (res.confirm) {
|
|
|
|
|
|
logout();
|
|
|
|
|
|
uni.reLaunch({
|
|
|
|
|
|
url: "/pages/system/login/login",
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 日程相关数据
|
|
|
|
|
|
const selectedDateIndex = ref(0); // 默认选中第一天
|
|
|
|
|
|
|
|
|
|
|
|
// 生成一周的日期
|
|
|
|
|
|
const weekDates = ref<DateItem[]>([]);
|
|
|
|
|
|
|
2025-08-27 22:25:20 +08:00
|
|
|
|
// 生成空数据的函数
|
2025-06-14 13:09:26 +08:00
|
|
|
|
const generateScheduleData = () => {
|
|
|
|
|
|
const today = new Date();
|
|
|
|
|
|
const currentDay = today.getDay();
|
|
|
|
|
|
const mondayOffset = currentDay === 0 ? -6 : 1 - currentDay;
|
|
|
|
|
|
const startOfWeek = new Date(today);
|
|
|
|
|
|
startOfWeek.setDate(today.getDate() + mondayOffset);
|
|
|
|
|
|
|
|
|
|
|
|
const data: Record<string, ScheduleItem[]> = {};
|
|
|
|
|
|
|
2025-08-27 22:25:20 +08:00
|
|
|
|
// 生成一周的日期,但不包含任何日程数据
|
2025-06-14 13:09:26 +08:00
|
|
|
|
for (let i = 0; i < 7; i++) {
|
|
|
|
|
|
const date = new Date(startOfWeek);
|
|
|
|
|
|
date.setDate(startOfWeek.getDate() + i);
|
|
|
|
|
|
const dateStr = date.getDate().toString();
|
|
|
|
|
|
|
2025-08-27 22:25:20 +08:00
|
|
|
|
// 所有日期都没有日程安排
|
|
|
|
|
|
data[dateStr] = [];
|
2025-06-14 13:09:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return data;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 日程数据
|
|
|
|
|
|
const scheduleData = reactive<Record<string, ScheduleItem[]>>(generateScheduleData());
|
2025-04-22 10:22:33 +08:00
|
|
|
|
|
2025-06-14 13:09:26 +08:00
|
|
|
|
// 获取当前选中日期的日程
|
|
|
|
|
|
const getCurrentSchedule = computed(() => {
|
|
|
|
|
|
const currentDate = weekDates.value[selectedDateIndex.value];
|
|
|
|
|
|
if (!currentDate) return [];
|
|
|
|
|
|
return scheduleData[currentDate.number] || [];
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-08-27 22:25:20 +08:00
|
|
|
|
// 初始化职务信息
|
|
|
|
|
|
const initPositionInfo = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
let dzZw: string[] = [];
|
|
|
|
|
|
let qtZw: string[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
// 解析党政职务
|
|
|
|
|
|
if (getJs.dzzw && typeof getJs.dzzw === "string") {
|
|
|
|
|
|
dzZw = getJs.dzzw.split(",");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解析其他职务
|
|
|
|
|
|
if (getJs.qtzw && typeof getJs.qtzw === "string") {
|
|
|
|
|
|
qtZw = getJs.qtzw.split(",");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取党政职务名称
|
|
|
|
|
|
if (dzZw && dzZw.length > 0) {
|
|
|
|
|
|
const res = await getZwListByLx({ zwlx: "党政职务" });
|
|
|
|
|
|
dzZwLabel.value = dzZw
|
|
|
|
|
|
.map((zwId: string) => {
|
|
|
|
|
|
const zw = res.result.find((zw: any) => zwId === zw.id);
|
|
|
|
|
|
return zw ? zw.zwmc : "";
|
|
|
|
|
|
})
|
|
|
|
|
|
.filter(Boolean)
|
|
|
|
|
|
.join(", ");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取其他职务名称
|
|
|
|
|
|
if (qtZw && qtZw.length > 0) {
|
|
|
|
|
|
const res = await getZwListByLx({ zwlx: "其他职务" });
|
|
|
|
|
|
qtZwLabel.value = qtZw
|
|
|
|
|
|
.map((zwId: string) => {
|
|
|
|
|
|
const zw = res.result.find((zw: any) => zwId === zw.id);
|
|
|
|
|
|
return zw ? zw.zwmc : "";
|
|
|
|
|
|
})
|
|
|
|
|
|
.filter(Boolean)
|
|
|
|
|
|
.join(", ");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console.log("职务信息初始化完成:", { dzZwLabel: dzZwLabel.value, qtZwLabel: qtZwLabel.value });
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("初始化职务信息失败:", error);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-06-14 13:09:26 +08:00
|
|
|
|
// 初始化日期
|
|
|
|
|
|
const initDates = () => {
|
|
|
|
|
|
const days = ['一', '二', '三', '四', '五', '六', '日'];
|
|
|
|
|
|
const today = new Date();
|
|
|
|
|
|
const currentDay = today.getDay(); // 0-6,0是周日
|
|
|
|
|
|
|
|
|
|
|
|
// 计算本周的开始日期(周一)
|
|
|
|
|
|
const startOfWeek = new Date(today);
|
|
|
|
|
|
const mondayOffset = currentDay === 0 ? -6 : 1 - currentDay; // 如果是周日,往前推6天;否则推到周一
|
|
|
|
|
|
startOfWeek.setDate(today.getDate() + mondayOffset);
|
|
|
|
|
|
|
|
|
|
|
|
weekDates.value = [];
|
|
|
|
|
|
for (let i = 0; i < 7; i++) {
|
|
|
|
|
|
const date = new Date(startOfWeek);
|
|
|
|
|
|
date.setDate(startOfWeek.getDate() + i);
|
|
|
|
|
|
|
|
|
|
|
|
const dateStr = date.getDate().toString();
|
|
|
|
|
|
const hasEvent = scheduleData[dateStr] && scheduleData[dateStr].length > 0;
|
|
|
|
|
|
|
|
|
|
|
|
weekDates.value.push({
|
|
|
|
|
|
day: days[i],
|
|
|
|
|
|
number: dateStr,
|
|
|
|
|
|
hasEvent,
|
|
|
|
|
|
date: date.toISOString().split('T')[0]
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 选择日期
|
|
|
|
|
|
const selectDate = (index: number) => {
|
|
|
|
|
|
selectedDateIndex.value = index;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 跳转到日程页面
|
|
|
|
|
|
const goToSchedule = () => {
|
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
|
url: '/pages/view/schedule/index'
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-08-27 22:25:20 +08:00
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
// 初始化职务信息
|
|
|
|
|
|
await initPositionInfo();
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化日期
|
2025-06-14 13:09:26 +08:00
|
|
|
|
initDates();
|
2025-08-27 22:25:20 +08:00
|
|
|
|
|
2025-06-14 13:09:26 +08:00
|
|
|
|
// 默认选中今天
|
|
|
|
|
|
const today = new Date();
|
|
|
|
|
|
const currentDay = today.getDay();
|
|
|
|
|
|
const todayIndex = currentDay === 0 ? 6 : currentDay - 1; // 周日是6,其他是day-1
|
|
|
|
|
|
selectedDateIndex.value = todayIndex;
|
|
|
|
|
|
});
|
2025-04-22 10:22:33 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
2025-06-14 13:09:26 +08:00
|
|
|
|
.mine-page {
|
|
|
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 顶部 Header - 复制自service页面
|
|
|
|
|
|
.header-section {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 50%, #ec4899 100%);
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
padding: 40rpx 30rpx 30rpx;
|
|
|
|
|
|
height: auto;
|
2025-08-27 22:25:20 +08:00
|
|
|
|
min-height: 270rpx;
|
2025-06-14 13:09:26 +08:00
|
|
|
|
|
|
|
|
|
|
.header-gradient {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
background: linear-gradient(
|
|
|
|
|
|
45deg,
|
|
|
|
|
|
rgba(255, 255, 255, 0.1) 0%,
|
|
|
|
|
|
rgba(255, 255, 255, 0.05) 100%
|
|
|
|
|
|
);
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.logout-btn {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 40rpx;
|
|
|
|
|
|
right: 30rpx;
|
|
|
|
|
|
z-index: 3;
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.2);
|
|
|
|
|
|
border-radius: 20rpx;
|
|
|
|
|
|
padding: 10rpx 20rpx;
|
|
|
|
|
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
|
|
|
|
backdrop-filter: blur(10px);
|
|
|
|
|
|
|
|
|
|
|
|
.logout-text {
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.teacher-info {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-top: 20rpx;
|
|
|
|
|
|
z-index: 2;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
|
|
|
|
.teacher-avatar {
|
|
|
|
|
|
width: 120rpx;
|
|
|
|
|
|
height: 120rpx;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
border: 3px solid rgba(255, 255, 255, 0.3);
|
|
|
|
|
|
margin-right: 20rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.avatar-image {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.teacher-details {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
|
|
|
|
.teacher-name {
|
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
margin-bottom: 5rpx;
|
|
|
|
|
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.teacher-position {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.9);
|
|
|
|
|
|
margin-bottom: 5rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.teacher-class {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.8);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.stats-info {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
margin-top: 20rpx;
|
|
|
|
|
|
z-index: 2;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
|
|
|
|
.stat-item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
|
|
|
|
.stat-label {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.9);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.stat-value {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.stat-divider {
|
|
|
|
|
|
margin: 0 30rpx;
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.6);
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.teacher-intro {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.8);
|
|
|
|
|
|
margin-top: 20rpx;
|
|
|
|
|
|
line-height: 1.4;
|
|
|
|
|
|
z-index: 2;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 主要内容区域
|
|
|
|
|
|
.main-content {
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
padding: 20px 12px 0px 12px; // 减少左右padding
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
background: linear-gradient(
|
|
|
|
|
|
to bottom,
|
|
|
|
|
|
rgba(255, 255, 255, 0.95) 0%,
|
|
|
|
|
|
rgba(248, 250, 252, 0.98) 100%
|
|
|
|
|
|
);
|
|
|
|
|
|
border-radius: 20px 20px 0 0;
|
|
|
|
|
|
margin-top: -20px;
|
|
|
|
|
|
z-index: 3;
|
|
|
|
|
|
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
height: calc(100vh - 340rpx); // 固定高度
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
overflow: hidden; // 防止内容溢出
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 日程标题
|
|
|
|
|
|
.schedule-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
flex-shrink: 0; // 不压缩
|
|
|
|
|
|
|
|
|
|
|
|
.schedule-title {
|
|
|
|
|
|
font-size: 17px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #1f2937;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.schedule-link {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
|
|
|
|
.link-text {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
color: #6b7280;
|
|
|
|
|
|
margin-right: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.link-arrow {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
color: #6b7280;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 日期选择器
|
|
|
|
|
|
.date-selector {
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
flex-shrink: 0; // 不压缩
|
|
|
|
|
|
margin-left: 0;
|
|
|
|
|
|
margin-right: 0;
|
|
|
|
|
|
|
|
|
|
|
|
.date-container {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
padding: 8px 4px;
|
|
|
|
|
|
justify-content: space-around; // 使用space-around确保更好的分布
|
|
|
|
|
|
width: 100%; // 占满宽度
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.date-item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 6px 2px;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
flex: 1; // 平均分配空间
|
|
|
|
|
|
max-width: calc((100% - 32px) / 7); // 减去padding后平均分配
|
|
|
|
|
|
min-width: 0; // 允许压缩
|
|
|
|
|
|
|
|
|
|
|
|
.date-day {
|
|
|
|
|
|
font-size: 10px;
|
|
|
|
|
|
color: #6b7280;
|
|
|
|
|
|
margin-bottom: 2px;
|
|
|
|
|
|
white-space: nowrap; // 防止换行
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.date-number {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #374151;
|
|
|
|
|
|
white-space: nowrap; // 防止换行
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.date-dot {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
bottom: 1px;
|
|
|
|
|
|
width: 3px;
|
|
|
|
|
|
height: 3px;
|
|
|
|
|
|
background: #10b981;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
|
|
background: #10b981;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
transform: scale(1.02); // 减少放大倍数,避免超出
|
|
|
|
|
|
z-index: 1; // 确保选中项在最上层
|
|
|
|
|
|
margin: 0 -1px; // 轻微负边距补偿放大效果
|
|
|
|
|
|
|
|
|
|
|
|
.date-day,
|
|
|
|
|
|
.date-number {
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.date-dot {
|
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 日程列表
|
|
|
|
|
|
.schedule-list {
|
|
|
|
|
|
flex: 1; // 占据剩余空间
|
|
|
|
|
|
height: 0; // 配合flex使用,确保滚动正常
|
|
|
|
|
|
padding-bottom: 20px;
|
|
|
|
|
|
|
|
|
|
|
|
.schedule-content {
|
|
|
|
|
|
padding-bottom: 35px; // 底部留白
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.schedule-item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
padding: 14px 0;
|
|
|
|
|
|
border-bottom: 1px solid #f3f4f6;
|
|
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.time-column {
|
|
|
|
|
|
width: 60px;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
margin-right: 15px;
|
|
|
|
|
|
|
|
|
|
|
|
.start-time {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #374151;
|
|
|
|
|
|
line-height: 1.2;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.end-time {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
color: #6b7280;
|
|
|
|
|
|
margin-top: 2px;
|
|
|
|
|
|
line-height: 1.2;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.content-column {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
min-width: 0; // 允许内容压缩
|
|
|
|
|
|
|
|
|
|
|
|
.event-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
|
|
|
|
|
|
.event-tag {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 3px 8px;
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
flex-shrink: 0; // 标签不压缩
|
|
|
|
|
|
|
|
|
|
|
|
&.meeting {
|
|
|
|
|
|
background: #10b981;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.class {
|
|
|
|
|
|
background: #3b82f6;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.tutoring {
|
|
|
|
|
|
background: #f59e0b;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.preparation {
|
|
|
|
|
|
background: #8b5cf6;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.counseling {
|
|
|
|
|
|
background: #ef4444;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.tag-text {
|
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.event-title {
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: #1f2937;
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
line-height: 1.3;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
white-space: nowrap; // 单行显示,超出省略
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.event-details {
|
|
|
|
|
|
.event-location,
|
|
|
|
|
|
.event-description {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 4px;
|
|
|
|
|
|
|
|
|
|
|
|
.location-icon,
|
|
|
|
|
|
.description-icon {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
margin-right: 4px;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.location-text,
|
|
|
|
|
|
.description-text {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
color: #6b7280;
|
|
|
|
|
|
line-height: 1.3;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
white-space: nowrap; // 单行显示,超出省略
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.no-schedule {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
min-height: 200px;
|
|
|
|
|
|
|
|
|
|
|
|
.no-schedule-text {
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
color: #9ca3af;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-22 10:22:33 +08:00
|
|
|
|
|
2025-06-14 13:09:26 +08:00
|
|
|
|
// 动画定义
|
|
|
|
|
|
@keyframes fadeInUp {
|
|
|
|
|
|
from {
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
transform: translateY(30px);
|
|
|
|
|
|
}
|
|
|
|
|
|
to {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-22 10:22:33 +08:00
|
|
|
|
|
2025-06-14 13:09:26 +08:00
|
|
|
|
// 小屏幕适配
|
|
|
|
|
|
@media (max-width: 375px) {
|
|
|
|
|
|
.main-content {
|
|
|
|
|
|
padding: 20px 8px 0px 8px; // 进一步减少padding
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.date-selector {
|
|
|
|
|
|
.date-container {
|
|
|
|
|
|
padding: 8px 2px; // 减少内边距
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.date-item {
|
|
|
|
|
|
padding: 5px 1px; // 减少项目内边距
|
|
|
|
|
|
|
|
|
|
|
|
.date-day {
|
|
|
|
|
|
font-size: 9px; // 稍微减小字体
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.date-number {
|
|
|
|
|
|
font-size: 13px; // 稍微减小字体
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
|
|
transform: scale(1.01); // 进一步减少放大倍数
|
|
|
|
|
|
margin: 0; // 移除负边距
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-22 10:22:33 +08:00
|
|
|
|
</style>
|