2025-06-14 14:08:44 +08:00

627 lines
14 KiB
Vue
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.

<template>
<view class="service-page">
<!-- 1. 顶部 Header -->
<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="section-block"
v-for="(section, index) in sections"
:key="section.id"
>
<view class="section-title">
<view
class="title-decorator"
:style="{ backgroundColor: getSectionColor(index) }"
></view>
<text>{{ section.title }}</text>
<view class="title-line"></view>
</view>
<view class="section-grid-card">
<template v-for="item in section.items" :key="item.id">
<view
v-if="item.show"
class="grid-item"
@click="handleGridItemClick(item)"
>
<view
class="grid-icon-container"
:style="{ backgroundColor: getIconBgColor(index) }"
>
<image
class="grid-icon"
:src="`/static/base/home/${item.icon}.png`"
mode="aspectFit"
></image>
</view>
<text class="grid-text">{{ item.text }}</text>
</view>
</template>
</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { useUserStore } from "@/store/modules/user";
import { imagUrl } from "@/utils";
import { reactive, ref } from "vue";
interface GridItem {
id: number | string;
icon: string; // 图标文件名 (不含扩展名)
text: string;
show: boolean; // 是否显示
// 可以添加 permissionKey 等字段
path?: string; // 页面路径
}
interface Section {
id: number | string;
title: string;
items: GridItem[];
}
// 定义老师数据接口
interface TeacherData {
name: string;
position: string;
className: string;
score: number;
workload: number;
introduction: string;
avatar?: 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 sections = reactive<Section[]>([
{
id: "routine",
title: "常规",
items: [
// {
// id: 10,
// text: "一师一策",
// icon: "clipboardfill",
// path: "/pages/view/routine/yishiyice/index",
// show: true,
// },
{
id: "r2",
icon: "stack-fill",
text: "教学资源",
show: true,
path: "/pages/view/routine/JiaoXueZiYuan/index",
},
{
id: "r5",
icon: "file-mark-fill",
text: "积分评价",
show: true,
path: "/pages/view/routine/JiFenPingJia/JiFenPingJia",
},
// {
// id: "r3",
// icon: "file-list-3-fil",
// text: "活动资源",
// show: true,
// path: "/pages/view/routine/HuoDongZiYuan/index",
// },
{
id: "r3",
icon: "file-list-3-fil",
text: "工作量",
show: true,
path: "/pages/view/routine/GongZuoLiang/index",
},
// {
// id: "r4",
// icon: "file-paper-2-fill",
// text: "公文流转",
// show: true,
// path: "/pages/view/routine/GongWenLiuZhuan/index",
// },
{
id: "r4",
icon: "file-paper-2-fill",
text: "任教任职",
show: true,
path: "/pages/view/routine/RengJiaoRengZhi/index",
},
{
id: "r6",
icon: "pass-pending-fill",
text: "课服巡查",
show: true,
path: "/pages/view/routine/kefuxuncha/KeFuXunCha",
},
],
},
{
id: "home-school",
title: "家校",
items: [
{
id: "hs1",
icon: "file-text-fill",
text: "教师课表",
show: true,
path: "/pages/view/homeSchool/JiaoShiKeBiao",
},
{
id: "hs2",
icon: "file-text-fill-2",
text: "班级课表",
show: true,
path: "/pages/view/homeSchool/BanJiKeBiao",
},
{
id: "hs3",
icon: "file-paper-2-fill",
text: "家长通讯录",
show: true,
path: "/pages/view/homeSchool/parentAddressBook/index",
},
{
id: "hs4",
icon: "newspaper-fill",
text: "通知列表",
show: true,
path: "/pages/view/notice/index",
},
{
id: "hs6",
icon: "filechart2fil",
text: "成绩分析",
show: true,
path: "/pages/view/homeSchool/ChengJiFenXi",
},
],
},
{
id: "hr",
title: "人事",
items: [
{
id: "hr1",
icon: "draftfill",
text: "请假申请",
show: true,
path: "/pages/view/hr/leaveApplication/index",
},
{
id: "hr2",
icon: "file-user-fill",
text: "教师档案",
show: true,
path: "/pages/view/hr/teacherProfile/index",
},
{
id: "hr3",
icon: "newspaper-fill",
text: "工资条",
show: true,
path: "/pages/view/hr/salarySlip/index",
},
],
},
]);
// 获取分区颜色
const getSectionColor = (index: number) => {
const colors = ["#4F46E5", "#059669", "#DC2626"];
return colors[index % colors.length];
};
// 获取图标背景颜色
const getIconBgColor = (index: number) => {
const colors = [
"rgba(79, 70, 229, 0.1)",
"rgba(5, 150, 105, 0.1)",
"rgba(220, 38, 38, 0.1)",
];
return colors[index % colors.length];
};
// 处理网格项点击事件
const handleGridItemClick = (item: GridItem) => {
console.log("Clicked item:", item);
if (item.path) {
uni.navigateTo({ url: item.path });
} else {
uni.showToast({ title: `功能 ${item.text} 暂未开放`, icon: "none" });
}
};
</script>
<style scoped lang="scss">
.service-page {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
position: relative;
}
// 顶部 Header
.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 {
padding: 20px 15px 40px 15px;
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);
}
// 功能分区块
.section-block {
margin-bottom: 25px;
animation: fadeInUp 0.6s ease-out;
&:nth-child(1) {
animation-delay: 0.1s;
}
&:nth-child(2) {
animation-delay: 0.2s;
}
&:nth-child(3) {
animation-delay: 0.3s;
}
.section-title {
display: flex;
align-items: center;
margin-bottom: 15px;
padding-left: 5px;
position: relative;
.title-decorator {
width: 8px;
height: 8px;
border-radius: 50%;
margin-right: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
text {
font-size: 20px;
font-weight: 600;
color: #1f2937;
letter-spacing: 0.5px;
}
.title-line {
flex: 1;
height: 1px;
background: linear-gradient(
to right,
rgba(156, 163, 175, 0.3),
transparent
);
margin-left: 15px;
}
}
.section-grid-card {
background: #ffffff;
border-radius: 16px;
padding: 20px 15px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
border: 1px solid rgba(255, 255, 255, 0.8);
backdrop-filter: blur(10px);
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px 15px;
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
}
}
}
// 网格项
.grid-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
cursor: pointer;
padding: 10px 5px;
border-radius: 12px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
&:hover {
transform: translateY(-3px) scale(1.05);
background: rgba(79, 70, 229, 0.05);
}
&:active {
transform: translateY(-1px) scale(1.02);
}
.grid-icon-container {
width: 48px;
height: 48px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 8px;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
.grid-icon {
width: 24px;
height: 24px;
transition: all 0.3s ease;
}
}
.grid-text {
font-size: 14px;
color: #4b5563;
font-weight: 500;
line-height: 1.3;
transition: color 0.3s ease;
}
&:hover .grid-text {
color: #1f2937;
}
&:hover .grid-icon-container {
transform: scale(1.1);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
}
}
// 动画定义
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
// 响应式优化
@media (max-width: 375px) {
.section-grid-card {
gap: 15px 8px;
padding: 15px 10px;
}
.grid-item {
padding: 8px 3px;
}
.grid-icon-container {
width: 42px;
height: 42px;
.grid-icon {
width: 20px;
height: 20px;
}
}
}
</style>