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>
|
|
|
|
|
|
<view class="teacher-position">{{ teacherData.position }}</view>
|
|
|
|
|
|
<view class="teacher-class">{{ teacherData.className }}</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 统计信息 -->
|
|
|
|
|
|
<view class="stats-info">
|
|
|
|
|
|
<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>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 介绍文字 -->
|
|
|
|
|
|
<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";
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const { logout, getUser } = useUserStore();
|
|
|
|
|
|
|
|
|
|
|
|
// 老师数据
|
|
|
|
|
|
const teacherData = reactive<TeacherData>({
|
|
|
|
|
|
name: getUser.loginName,
|
|
|
|
|
|
position: "教研组长",
|
|
|
|
|
|
className: "2014级1班班主任",
|
|
|
|
|
|
score: 48,
|
|
|
|
|
|
workload: 20,
|
|
|
|
|
|
introduction: "北冥有鱼,其名为鲲。鲲之大,不知其几千里也。",
|
|
|
|
|
|
avatar: imagUrl(getUser.profilePhoto),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 退出登录
|
|
|
|
|
|
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[]>([]);
|
|
|
|
|
|
|
|
|
|
|
|
// 生成假数据的函数
|
|
|
|
|
|
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[]> = {};
|
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < 7; i++) {
|
|
|
|
|
|
const date = new Date(startOfWeek);
|
|
|
|
|
|
date.setDate(startOfWeek.getDate() + i);
|
|
|
|
|
|
const dateStr = date.getDate().toString();
|
|
|
|
|
|
|
|
|
|
|
|
// 为每天生成不同的假数据
|
|
|
|
|
|
switch (i) {
|
|
|
|
|
|
case 0: // 周一
|
|
|
|
|
|
data[dateStr] = [
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '08:30',
|
|
|
|
|
|
endTime: '10:00',
|
|
|
|
|
|
title: '语文课',
|
|
|
|
|
|
type: 'class',
|
|
|
|
|
|
tag: '课程',
|
|
|
|
|
|
location: '教学楼A201',
|
|
|
|
|
|
description: '高一(3)班语文课',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '14:00',
|
|
|
|
|
|
endTime: '15:30',
|
|
|
|
|
|
title: '班主任会议',
|
|
|
|
|
|
type: 'meeting',
|
|
|
|
|
|
tag: '会议',
|
|
|
|
|
|
location: '会议室B302',
|
|
|
|
|
|
description: '讨论期中考试安排',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
}
|
|
|
|
|
|
];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 1: // 周二
|
|
|
|
|
|
data[dateStr] = [
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '09:00',
|
|
|
|
|
|
endTime: '10:30',
|
|
|
|
|
|
title: '教研活动',
|
|
|
|
|
|
type: 'meeting',
|
|
|
|
|
|
tag: '教研',
|
|
|
|
|
|
location: '教研室',
|
|
|
|
|
|
description: '语文组教研活动',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '15:00',
|
|
|
|
|
|
endTime: '16:30',
|
|
|
|
|
|
title: '家长会准备',
|
|
|
|
|
|
type: 'preparation',
|
|
|
|
|
|
tag: '准备',
|
|
|
|
|
|
location: '办公室',
|
|
|
|
|
|
description: '准备家长会材料',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
}
|
|
|
|
|
|
];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2: // 周三
|
|
|
|
|
|
data[dateStr] = [
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '08:00',
|
|
|
|
|
|
endTime: '09:30',
|
|
|
|
|
|
title: '早读辅导',
|
|
|
|
|
|
type: 'tutoring',
|
|
|
|
|
|
tag: '辅导',
|
|
|
|
|
|
location: '教学楼A201',
|
|
|
|
|
|
description: '高一(3)班早读辅导',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '10:00',
|
|
|
|
|
|
endTime: '12:00',
|
|
|
|
|
|
title: '教研英语无痕计划(OMO)',
|
|
|
|
|
|
type: 'meeting',
|
|
|
|
|
|
tag: '会议',
|
|
|
|
|
|
location: 'POHCSOO007',
|
|
|
|
|
|
description: '智慧校园211楼会议室',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '14:00',
|
|
|
|
|
|
endTime: '16:00',
|
|
|
|
|
|
title: '德法内科学习课',
|
|
|
|
|
|
type: 'class',
|
|
|
|
|
|
tag: '课程',
|
|
|
|
|
|
location: 'POHCSOO007',
|
|
|
|
|
|
description: '智慧校园211楼会议室',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
} , {
|
|
|
|
|
|
startTime: '08:00',
|
|
|
|
|
|
endTime: '09:30',
|
|
|
|
|
|
title: '早读辅导',
|
|
|
|
|
|
type: 'tutoring',
|
|
|
|
|
|
tag: '辅导',
|
|
|
|
|
|
location: '教学楼A201',
|
|
|
|
|
|
description: '高一(3)班早读辅导',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '10:00',
|
|
|
|
|
|
endTime: '12:00',
|
|
|
|
|
|
title: '教研英语无痕计划(OMO)',
|
|
|
|
|
|
type: 'meeting',
|
|
|
|
|
|
tag: '会议',
|
|
|
|
|
|
location: 'POHCSOO007',
|
|
|
|
|
|
description: '智慧校园211楼会议室',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '14:00',
|
|
|
|
|
|
endTime: '16:00',
|
|
|
|
|
|
title: '德法内科学习课',
|
|
|
|
|
|
type: 'class',
|
|
|
|
|
|
tag: '课程',
|
|
|
|
|
|
location: 'POHCSOO007',
|
|
|
|
|
|
description: '智慧校园211楼会议室',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
}, {
|
|
|
|
|
|
startTime: '08:00',
|
|
|
|
|
|
endTime: '09:30',
|
|
|
|
|
|
title: '早读辅导',
|
|
|
|
|
|
type: 'tutoring',
|
|
|
|
|
|
tag: '辅导',
|
|
|
|
|
|
location: '教学楼A201',
|
|
|
|
|
|
description: '高一(3)班早读辅导',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '10:00',
|
|
|
|
|
|
endTime: '12:00',
|
|
|
|
|
|
title: '教研英语无痕计划(OMO)',
|
|
|
|
|
|
type: 'meeting',
|
|
|
|
|
|
tag: '会议',
|
|
|
|
|
|
location: 'POHCSOO007',
|
|
|
|
|
|
description: '智慧校园211楼会议室',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '14:00',
|
|
|
|
|
|
endTime: '16:00',
|
|
|
|
|
|
title: '德法内科学习课',
|
|
|
|
|
|
type: 'class',
|
|
|
|
|
|
tag: '课程',
|
|
|
|
|
|
location: 'POHCSOO007',
|
|
|
|
|
|
description: '智慧校园211楼会议室',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
}
|
|
|
|
|
|
];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 3: // 周四
|
|
|
|
|
|
data[dateStr] = [
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '08:30',
|
|
|
|
|
|
endTime: '10:00',
|
|
|
|
|
|
title: '语文课',
|
|
|
|
|
|
type: 'class',
|
|
|
|
|
|
tag: '课程',
|
|
|
|
|
|
location: '教学楼A201',
|
|
|
|
|
|
description: '高一(3)班语文课',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '10:30',
|
|
|
|
|
|
endTime: '12:00',
|
|
|
|
|
|
title: '作文批改',
|
|
|
|
|
|
type: 'preparation',
|
|
|
|
|
|
tag: '批改',
|
|
|
|
|
|
location: '办公室',
|
|
|
|
|
|
description: '批改学生作文',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '14:00',
|
|
|
|
|
|
endTime: '15:30',
|
|
|
|
|
|
title: '课程设计',
|
|
|
|
|
|
type: 'preparation',
|
|
|
|
|
|
tag: '备课',
|
|
|
|
|
|
location: '办公室',
|
|
|
|
|
|
description: '准备下周课程内容',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '16:00',
|
|
|
|
|
|
endTime: '17:00',
|
|
|
|
|
|
title: '学生谈话',
|
|
|
|
|
|
type: 'counseling',
|
|
|
|
|
|
tag: '谈话',
|
|
|
|
|
|
location: '办公室',
|
|
|
|
|
|
description: '与学生张三谈话',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
}
|
|
|
|
|
|
];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 4: // 周五
|
|
|
|
|
|
data[dateStr] = [
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '08:00',
|
|
|
|
|
|
endTime: '09:30',
|
|
|
|
|
|
title: '晨会',
|
|
|
|
|
|
type: 'meeting',
|
|
|
|
|
|
tag: '晨会',
|
|
|
|
|
|
location: '办公室',
|
|
|
|
|
|
description: '教师晨会',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '09:00',
|
|
|
|
|
|
endTime: '10:30',
|
|
|
|
|
|
title: '公开课',
|
|
|
|
|
|
type: 'class',
|
|
|
|
|
|
tag: '公开课',
|
|
|
|
|
|
location: '教学楼A201',
|
|
|
|
|
|
description: '语文公开课展示',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '11:00',
|
|
|
|
|
|
endTime: '12:00',
|
|
|
|
|
|
title: '课后辅导',
|
|
|
|
|
|
type: 'tutoring',
|
|
|
|
|
|
tag: '辅导',
|
|
|
|
|
|
location: '教学楼A201',
|
|
|
|
|
|
description: '学困生辅导',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '14:30',
|
|
|
|
|
|
endTime: '16:00',
|
|
|
|
|
|
title: '周总结会议',
|
|
|
|
|
|
type: 'meeting',
|
|
|
|
|
|
tag: '会议',
|
|
|
|
|
|
location: '会议室B302',
|
|
|
|
|
|
description: '本周工作总结',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '16:30',
|
|
|
|
|
|
endTime: '17:30',
|
|
|
|
|
|
title: '家长沟通',
|
|
|
|
|
|
type: 'counseling',
|
|
|
|
|
|
tag: '沟通',
|
|
|
|
|
|
location: '办公室',
|
|
|
|
|
|
description: '与家长电话沟通',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
}
|
|
|
|
|
|
];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 5: // 周六
|
|
|
|
|
|
data[dateStr] = [
|
|
|
|
|
|
{
|
|
|
|
|
|
startTime: '09:00',
|
|
|
|
|
|
endTime: '11:00',
|
|
|
|
|
|
title: '补课',
|
|
|
|
|
|
type: 'class',
|
|
|
|
|
|
tag: '补课',
|
|
|
|
|
|
location: '教学楼A201',
|
|
|
|
|
|
description: '高一(3)班语文补课',
|
|
|
|
|
|
details: true
|
|
|
|
|
|
}
|
|
|
|
|
|
];
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 6: // 周日
|
|
|
|
|
|
data[dateStr] = []; // 周日休息,无安排
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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] || [];
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化日期
|
|
|
|
|
|
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'
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
initDates();
|
|
|
|
|
|
// 默认选中今天
|
|
|
|
|
|
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;
|
|
|
|
|
|
min-height: 320rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.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>
|