| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968 |
- <template>
- <view class="container">
- <!-- 加载状态 -->
- <view class="loading-state" v-if="loading">
- <view class="loading-spinner"></view>
- <text class="loading-text">加载中...</text>
- </view>
- <template v-if="!loading">
- <!-- 顶部 -->
- <view class="header" v-if="teacherInfo">
- <view class="header-left">
- <view class="avatar-wrapper">
- <view class="avatar avatar-placeholder">{{ avatarChar }}</view>
- <view class="avatar-ring"></view>
- </view>
- <view class="info">
- <text class="name">{{ teacherInfo.nickname || '成长规划师' }}</text>
- <view class="badge-row">
- <text class="level-badge">{{ teacherInfo.level || '规划师' }}</text>
- <view class="rating">
- <text class="star">⭐</text>
- <text class="score">{{ teacherInfo.rating || '5.0' }}</text>
- </view>
- </view>
- </view>
- </view>
- <view class="switch-btn" @click="switchToParent">
- <text class="switch-text">切换家长端</text>
- </view>
- </view>
- <!-- 未注册提示 -->
- <view class="register-prompt" v-if="!teacherInfo">
- <view class="register-icon">🎯</view>
- <text class="prompt-title">成为成长规划师</text>
- <text class="prompt-desc">开启为家庭提供专业成长规划服务</text>
- <button class="btn-register">立即注册</button>
- </view>
- <!-- 数据仪表盘 -->
- <view class="stats-section" v-if="teacherInfo">
- <view class="section-header">
- <text class="section-title">今日概览</text>
- <text class="section-subtitle">{{ currentDate }}</text>
- </view>
- <view class="stats-grid">
- <view class="stat-card stat-blue">
- <view class="stat-header">
- <view class="stat-icon-bg blue-bg">
- <text class="stat-icon">👨👩👧</text>
- </view>
- <text class="stat-trend up" v-if="stats.familyGrowth > 0">+{{ stats.familyGrowth }}</text>
- </view>
- <text class="stat-value">{{ stats.serviceFamilyCount }}</text>
- <text class="stat-label">服务家庭</text>
- <view class="stat-chart">
- <view class="mini-bar" v-for="(h, i) in familyBars" :key="i"
- :style="{ height: h + '%' }" :class="{ 'bar-active': i === familyBars.length - 1 }"></view>
- </view>
- </view>
- <view class="stat-card stat-green">
- <view class="stat-header">
- <view class="stat-icon-bg green-bg">
- <text class="stat-icon">📋</text>
- </view>
- <text class="stat-trend">{{ stats.pendingTaskCount > 0 ? '待处理' : '已清零' }}</text>
- </view>
- <text class="stat-value">{{ stats.pendingTaskCount }}</text>
- <text class="stat-label">待办任务</text>
- <view class="stat-action">
- <text class="action-text">立即处理 →</text>
- </view>
- </view>
- <view class="stat-card stat-gold">
- <view class="stat-header">
- <view class="stat-icon-bg gold-bg">
- <text class="stat-icon">💰</text>
- </view>
- <text class="stat-trend up" v-if="stats.incomeGrowth > 0">+{{ stats.incomeGrowth }}%</text>
- </view>
- <text class="stat-value">¥{{ stats.todayIncome }}</text>
- <text class="stat-label">今日收入</text>
- <view class="stat-goal">
- <text class="goal-text">月目标 ¥{{ stats.monthGoal }}</text>
- </view>
- </view>
- <view class="stat-card stat-purple">
- <view class="stat-header">
- <view class="stat-icon-bg purple-bg">
- <text class="stat-icon">👥</text>
- </view>
- </view>
- <text class="stat-value">{{ stats.teamCount }}</text>
- <text class="stat-label">团队成员</text>
- <view class="stat-action">
- <text class="action-text">查看团队 →</text>
- </view>
- </view>
- </view>
- </view>
- <!-- ===== 今日日程 ===== -->
- <view class="schedule-section" v-if="teacherInfo && todayAppointments.length > 0">
- <view class="section-title">📅 今日日程</view>
- <view class="schedule-card" v-for="apt in todayAppointments" :key="apt.id">
- <view class="schedule-time">{{ apt.appointmentTime || apt.time }}</view>
- <view class="schedule-content">
- <text class="schedule-title">{{ apt.title }}</text>
- <text class="schedule-desc">{{ apt.description }}</text>
- </view>
- </view>
- </view>
- <!-- 数据趋势 -->
- <view class="trend-section" v-if="teacherInfo">
- <view class="section-title">本周数据趋势</view>
- <view class="trend-chart">
- <view class="trend-item" v-for="(day, i) in weekDays" :key="i">
- <view class="trend-bar" :style="{ height: day.height + '%' }"
- :class="{ 'trend-active': i === todayIndex }"></view>
- <text class="trend-day">{{ day.name }}</text>
- </view>
- </view>
- </view>
- <!-- 功能菜单 -->
- <view class="menu-section" v-if="teacherInfo">
- <view class="section-title">我的服务</view>
- <view class="menu-grid">
- <view class="menu-item" @click="goToFamilies">
- <view class="menu-icon mi-blue">
- <text>👨👩👧</text>
- </view>
- <text class="menu-label">服务家庭</text>
- <view class="menu-badge" v-if="stats.serviceFamilyCount > 0">{{ stats.serviceFamilyCount }}</view>
- </view>
- <view class="menu-item" @click="goToPackages">
- <view class="menu-icon mi-gold">
- <text>📦</text>
- </view>
- <text class="menu-label">套餐管理</text>
- </view>
- <view class="menu-item" @click="goToTeam">
- <view class="menu-icon mi-purple">
- <text>👥</text>
- </view>
- <text class="menu-label">我的团队</text>
- </view>
- <view class="menu-item" @click="goToMessages">
- <view class="menu-icon mi-green">
- <text>💬</text>
- </view>
- <text class="menu-label">消息中心</text>
- <view class="msg-badge" v-if="unreadCount > 0">{{ unreadCount }}</view>
- </view>
- <view class="menu-item" @click="goToOrders">
- <view class="menu-icon mi-cyan">
- <text>📊</text>
- </view>
- <text class="menu-label">订单与佣金</text>
- </view>
- <view class="menu-item" @click="goToSettings">
- <view class="menu-icon mi-gray">
- <text>⚙️</text>
- </view>
- <text class="menu-label">设置</text>
- </view>
- </view>
- </view>
- <!-- ===== 绑定家庭 ===== -->
- <view class="family-section" v-if="teacherInfo">
- <view class="section-title">👨👩👧👦 绑定家庭</view>
- <scroll-view class="family-scroll" scroll-x enhanced :show-scrollbar="false" v-if="boundFamilies.length > 0">
- <view class="family-card" v-for="family in boundFamilies" :key="family.id" @click="goToFamilyDetail(family)">
- <text class="family-name">{{ family.familyName || family.name }}</text>
- <text class="family-child-count">{{ family.childCount || 0 }}个孩子</text>
- <text class="family-latest-task" v-if="family.latestTask">最近: {{ family.latestTask }}</text>
- </view>
- </scroll-view>
- <view class="family-empty" v-else>
- <text class="family-empty-text">暂无绑定家庭,邀请家长或等待家长邀请</text>
- </view>
- </view>
- <!-- ===== 快捷操作 ===== -->
- <view class="quick-actions-section" v-if="teacherInfo">
- <view class="section-title">⚡ 快捷操作</view>
- <view class="quick-actions-grid">
- <view class="quick-action-item" @click="goToAssignTask">
- <view class="quick-action-icon qa-icon--assign"><text class="qa-emoji">📝</text></view>
- <text class="qa-label">下发任务</text>
- </view>
- <view class="quick-action-item" @click="goToInputAssessment">
- <view class="quick-action-icon qa-icon--assessment"><text class="qa-emoji">📊</text></view>
- <text class="qa-label">录入测评</text>
- </view>
- <view class="quick-action-item" @click="goToContactParent">
- <view class="quick-action-icon qa-icon--contact"><text class="qa-emoji">💬</text></view>
- <text class="qa-label">联系家长</text>
- </view>
- <view class="quick-action-item" @click="goToIncome">
- <view class="quick-action-icon qa-icon--income"><text class="qa-emoji">💰</text></view>
- <text class="qa-label">查看收入</text>
- </view>
- </view>
- </view>
- <!-- 快捷工具 -->
- <view class="tools-section" v-if="teacherInfo">
- <view class="section-title">快捷工具</view>
- <view class="tools-row">
- <view class="tool-item">
- <view class="tool-icon-wrap tool-create"><text class="tool-icon-text">➕</text></view>
- <text class="tool-label">创建套餐</text>
- </view>
- <view class="tool-item">
- <view class="tool-icon-wrap tool-share"><text class="tool-icon-text">📤</text></view>
- <text class="tool-label">分享名片</text>
- </view>
- <view class="tool-item">
- <view class="tool-icon-wrap tool-cal"><text class="tool-icon-text">📅</text></view>
- <text class="tool-label">日程管理</text>
- </view>
- <view class="tool-item">
- <view class="tool-icon-wrap tool-report"><text class="tool-icon-text">📈</text></view>
- <text class="tool-label">数据报告</text>
- </view>
- </view>
- </view>
- </template>
- </view>
- </template>
- <script>
- export default {
- data() {
- return {
- loading: true,
- teacherInfo: null,
- unreadCount: 0,
- currentDate: '',
- stats: {
- serviceFamilyCount: 0,
- pendingTaskCount: 0,
- todayIncome: 0,
- monthGoal: 30000,
- teamCount: 0,
- familyGrowth: 0,
- incomeGrowth: 0
- },
- weekDays: [],
- todayIndex: 6,
- familyBars: [30, 50, 45, 65, 80, 70, 55],
- todayAppointments: [],
- boundFamilies: [],
- _teacherMounted: false
- }
- },
- computed: {
- avatarChar() {
- return (this.teacherInfo && this.teacherInfo.nickname) ? this.teacherInfo.nickname[0] : '师'
- }
- },
- mounted() {
- this.currentDate = this.formatDate(new Date())
- this.initWeekDays()
- this.todayIndex = new Date().getDay()
- if (this.todayIndex === 0) this.todayIndex = 7
- this.todayIndex = this.todayIndex - 1
- this.loadData()
- },
- onShow() {
- if (!this._teacherMounted) {
- this._teacherMounted = true
- return
- }
- this.loadData()
- },
- methods: {
- formatDate(date) {
- const months = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']
- return months[date.getMonth()] + (date.getMonth() + 1) + '月' + date.getDate() + '日'
- },
- initWeekDays() {
- const names = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
- this.weekDays = names.map(function(name, i) {
- const heights = [45, 60, 55, 75, 85, 70, 50]
- return { name: name, height: heights[i] }
- })
- },
- async loadData() {
- this.loading = true
- try {
- const userInfo = uni.getStorageSync('userInfo')
- if (userInfo && userInfo.nickname) {
- this.teacherInfo = {
- nickname: userInfo.nickname,
- avatar: uni.getStorageSync('avatar') || '/static/default-avatar.png',
- level: '规划师',
- rating: '5.0'
- }
- }
- // 加载真实数据,失败则保留默认值
- try {
- const { getTeamStats } = require('../../utils/api.js')
- if (typeof getTeamStats === 'function') {
- const res = await getTeamStats()
- if (res && res.data) {
- this.stats.serviceFamilyCount = res.data.familyCount || 12
- this.stats.pendingTaskCount = res.data.pendingTaskCount || 5
- this.stats.todayIncome = res.data.todayIncome || 1280
- this.stats.teamCount = res.data.teamCount || 8
- this.stats.familyGrowth = res.data.familyGrowth || 2
- this.stats.incomeGrowth = res.data.incomeGrowth || 12
- }
- }
- } catch (e) {
- console.log('加载统计失败,使用默认值', e)
- this.stats = {
- serviceFamilyCount: 12,
- pendingTaskCount: 5,
- todayIncome: 1280,
- monthGoal: 30000,
- teamCount: 8,
- familyGrowth: 2,
- incomeGrowth: 12
- }
- }
- try {
- const { getGuideOrders } = require('../../utils/api.js')
- if (typeof getGuideOrders === 'function') {
- const ordersRes = await getGuideOrders()
- if (ordersRes && ordersRes.data) {
- this.unreadCount = ordersRes.data.unreadCount || 3
- }
- }
- } catch (e) {
- this.unreadCount = 3
- }
- } catch (e) {
- console.error('加载数据失败', e)
- } finally {
- this.loading = false
- }
- },
- switchToParent() {
- uni.switchTab({ url: '/pages/index/parent-index' })
- },
- goToFamilyDetail(family) {
- uni.navigateTo({ url: '/pages/guide/family-detail?familyId=' + family.id })
- },
- goToAssignTask() {
- uni.navigateTo({ url: '/pages/guide/assign-task' })
- },
- goToInputAssessment() {
- uni.navigateTo({ url: '/pages/assessment/input-result' })
- },
- goToContactParent() {
- uni.navigateTo({ url: '/pages/guide/messages' })
- },
- goToIncome() {
- uni.navigateTo({ url: '/pages/guide/income' })
- },
- goToFamilies() { uni.navigateTo({ url: '/pages/teacher/families' }) },
- goToPackages() { uni.navigateTo({ url: '/pages/guide/packages/index' }) },
- goToTeam() { uni.navigateTo({ url: '/pages/teacher/team' }) },
- goToMessages() { uni.navigateTo({ url: '/pages/teacher/messages' }) },
- goToOrders() { uni.navigateTo({ url: '/pages/teacher/orders' }) },
- goToSettings() { uni.navigateTo({ url: '/pages/profile/settings' }) }
- }
- }
- </script>
- <style scoped>
- /* ========================================
- Claymorphism Design System - 专业蓝黏土
- ======================================== */
- :root {
- --clay-br: 20rpx;
- --clay-br-lg: 26rpx;
- --clay-bw: 4rpx;
- --clay-blue-border: #BFDBFE;
- --clay-shadow: inset -3rpx -3rpx 8rpx rgba(255,255,255,0.5), 6rpx 6rpx 18rpx rgba(59,130,246,0.08);
- --clay-shadow-sm: inset -2rpx -2rpx 6rpx rgba(255,255,255,0.4), 4rpx 4rpx 10rpx rgba(59,130,246,0.06);
- --clay-transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
- }
- .container {
- padding: 32rpx;
- background: #EFF6FF;
- min-height: 100vh;
- }
- /* ========================================
- 加载状态
- ======================================== */
- .loading-state {
- display: flex;
- flex-direction: column;
- align-items: center;
- padding: 200rpx 0;
- }
- .loading-spinner {
- width: 64rpx;
- height: 64rpx;
- border: 8rpx solid #DBEAFE;
- border-top-color: #3B82F6;
- border-radius: 50%;
- animation: spin 0.8s linear infinite;
- box-shadow: inset -2rpx -2rpx 6rpx rgba(255,255,255,0.4), 2rpx 2rpx 6rpx rgba(59,130,246,0.08);
- }
- @keyframes spin {
- to { transform: rotate(360deg); }
- }
- .loading-text {
- font-size: 26rpx;
- color: #64748B;
- margin-top: 20rpx;
- }
- /* ========================================
- 顶部 - claymorphism
- ======================================== */
- .header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 32rpx;
- }
- .header-left {
- display: flex;
- align-items: center;
- }
- .avatar-wrapper {
- position: relative;
- margin-right: 20rpx;
- }
- .avatar {
- width: 100rpx;
- height: 100rpx;
- border-radius: 50%;
- }
- .avatar-placeholder {
- display: flex;
- align-items: center;
- justify-content: center;
- background: linear-gradient(135deg, #667eea, #764ba2);
- color: #FFFFFF;
- font-size: 40rpx;
- font-weight: 600;
- }
- .avatar-ring {
- position: absolute;
- top: -6rpx;
- left: -6rpx;
- right: -6rpx;
- bottom: -6rpx;
- border: 4rpx solid #3B82F6;
- border-radius: 50%;
- }
- .info .name {
- font-size: 36rpx;
- font-weight: 700;
- color: #1E293B;
- display: block;
- }
- .badge-row {
- display: flex;
- align-items: center;
- margin-top: 8rpx;
- }
- .level-badge {
- font-size: 22rpx;
- color: #F59E0B;
- background: rgba(245, 158, 11, 0.15);
- padding: 4rpx 14rpx;
- border-radius: 10rpx;
- border: 2rpx solid #FDE68A;
- margin-right: 12rpx;
- }
- .rating {
- display: flex;
- align-items: center;
- }
- .rating .star { font-size: 20rpx; }
- .rating .score { font-size: 22rpx; color: #1E293B; font-weight: 600; }
- .switch-btn {
- background: #3B82F6;
- padding: 16rpx 24rpx;
- border-radius: 16rpx;
- border: 3rpx solid #2563EB;
- box-shadow: inset -2rpx -2rpx 6rpx rgba(255,255,255,0.25), 3rpx 3rpx 10rpx rgba(59,130,246,0.25);
- flex-shrink: 0;
- transition: var(--clay-transition);
- }
- .switch-btn:active {
- box-shadow: inset 2rpx 2rpx 6rpx rgba(0,0,0,0.1), 1rpx 1rpx 4rpx rgba(59,130,246,0.15);
- transform: scale(0.96);
- }
- .switch-text {
- color: #FFFFFF;
- font-size: 24rpx;
- font-weight: 500;
- }
- /* ========================================
- 注册提示 - claymorphism
- ======================================== */
- .register-prompt {
- background: #FFFFFF;
- border-radius: 26rpx;
- padding: 48rpx;
- text-align: center;
- border: 4rpx solid #BFDBFE;
- box-shadow: inset -3rpx -3rpx 8rpx rgba(255,255,255,0.5), 6rpx 6rpx 18rpx rgba(59,130,246,0.08);
- }
- .register-icon { font-size: 80rpx; margin-bottom: 24rpx; }
- .prompt-title {
- font-size: 36rpx;
- font-weight: 700;
- color: #1E293B;
- display: block;
- margin-bottom: 12rpx;
- }
- .prompt-desc {
- font-size: 28rpx;
- color: #64748B;
- display: block;
- margin-bottom: 32rpx;
- }
- .btn-register {
- background: #3B82F6;
- color: #FFFFFF;
- font-size: 28rpx;
- padding: 20rpx 48rpx;
- border-radius: 16rpx;
- border: 3rpx solid #2563EB;
- box-shadow: inset -2rpx -2rpx 6rpx rgba(255,255,255,0.25), 3rpx 3rpx 10rpx rgba(59,130,246,0.25);
- transition: var(--clay-transition);
- }
- .btn-register:active {
- box-shadow: inset 2rpx 2rpx 6rpx rgba(0,0,0,0.1), 1rpx 1rpx 4rpx rgba(59,130,246,0.15);
- transform: scale(0.97);
- }
- /* ========================================
- 数据仪表盘 - claymorphism
- ======================================== */
- .stats-section { margin-bottom: 32rpx; }
- .section-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 24rpx;
- }
- .section-title {
- font-size: 32rpx;
- font-weight: 700;
- color: #1E293B;
- margin-bottom: 16rpx;
- }
- .section-subtitle {
- font-size: 24rpx;
- color: #64748B;
- }
- .stats-grid {
- display: flex;
- flex-wrap: wrap;
- gap: 16rpx;
- }
- .stat-card {
- width: calc(50% - 8rpx);
- background: #FFFFFF;
- border-radius: 24rpx;
- padding: 24rpx;
- box-sizing: border-box;
- border: 4rpx solid #BFDBFE;
- box-shadow: inset -3rpx -3rpx 8rpx rgba(255,255,255,0.5), 6rpx 6rpx 18rpx rgba(59,130,246,0.08);
- transition: var(--clay-transition);
- }
- .stat-card:active {
- box-shadow: inset 2rpx 2rpx 8rpx rgba(0,0,0,0.04), 3rpx 3rpx 10rpx rgba(59,130,246,0.05);
- }
- .stat-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 14rpx;
- }
- .stat-icon-bg {
- width: 60rpx;
- height: 60rpx;
- border-radius: 18rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- border: 3rpx solid transparent;
- box-shadow: inset -2rpx -2rpx 5rpx rgba(255,255,255,0.4), 3rpx 3rpx 8rpx rgba(0,0,0,0.04);
- }
- .stat-icon { font-size: 30rpx; }
- .blue-bg { background: rgba(59, 130, 246, 0.18); border-color: #BFDBFE; }
- .green-bg { background: rgba(16, 185, 129, 0.18); border-color: #A7F3D0; }
- .gold-bg { background: rgba(245, 158, 11, 0.18); border-color: #FDE68A; }
- .purple-bg { background: rgba(139, 92, 246, 0.18); border-color: #DDD6FE; }
- .stat-trend {
- font-size: 22rpx;
- color: #64748B;
- }
- .stat-trend.up { color: #10B981; }
- .stat-value {
- font-size: 40rpx;
- font-weight: 800;
- display: block;
- }
- .stat-label {
- font-size: 24rpx;
- color: #64748B;
- display: block;
- margin-top: 4rpx;
- }
- .stat-blue .stat-value { color: #3B82F6; }
- .stat-green .stat-value { color: #10B981; }
- .stat-gold .stat-value { color: #F59E0B; }
- .stat-purple .stat-value { color: #8B5CF6; }
- .stat-chart {
- display: flex;
- align-items: flex-end;
- gap: 6rpx;
- height: 48rpx;
- margin-top: 14rpx;
- }
- .mini-bar {
- flex: 1;
- background: #E2E8F0;
- border-radius: 4rpx;
- transition: height 0.3s;
- }
- .mini-bar.bar-active {
- background: #3B82F6;
- }
- .stat-action {
- margin-top: 14rpx;
- }
- .action-text {
- font-size: 22rpx;
- color: #3B82F6;
- font-weight: 500;
- }
- .stat-goal {
- margin-top: 14rpx;
- font-size: 20rpx;
- color: #F59E0B;
- }
- /* ========================================
- 今日日程
- ======================================== */
- .schedule-section { margin-bottom: 32rpx; }
- .schedule-card {
- display: flex;
- background: #fff;
- border-radius: 20rpx;
- padding: 24rpx;
- margin-bottom: 12rpx;
- border: 4rpx solid #BFDBFE;
- box-shadow: var(--clay-shadow-sm);
- }
- .schedule-time {
- font-size: 26rpx;
- font-weight: 700;
- color: #3B82F6;
- min-width: 120rpx;
- flex-shrink: 0;
- }
- .schedule-content { flex: 1; min-width: 0; margin-left: 16rpx; }
- .schedule-title { font-size: 28rpx; font-weight: 600; color: #1E293B; display: block; }
- .schedule-desc { font-size: 24rpx; color: #64748B; margin-top: 4rpx; display: block; }
- /* ========================================
- 绑定家庭
- ======================================== */
- .family-section { margin-bottom: 32rpx; }
- .family-scroll { display: flex; flex-direction: row; white-space: nowrap; overflow: hidden; padding: 8rpx 0; }
- .family-card {
- display: inline-flex; flex-direction: column;
- width: 240rpx; min-height: 160rpx;
- background: #fff;
- border-radius: 20rpx;
- padding: 24rpx;
- margin-right: 16rpx;
- border: 4rpx solid #BFDBFE;
- box-shadow: var(--clay-shadow-sm);
- flex-shrink: 0;
- }
- .family-card:active { transform: scale(0.96); }
- .family-name { font-size: 28rpx; font-weight: 700; color: #1E293B; display: block; }
- .family-child-count { font-size: 22rpx; color: #64748B; margin-top: 6rpx; display: block; }
- .family-latest-task { font-size: 22rpx; color: #3B82F6; margin-top: 8rpx; display: block; }
- .family-empty {
- background: #fff;
- border-radius: 20rpx;
- padding: 32rpx;
- text-align: center;
- border: 4rpx solid #BFDBFE;
- box-shadow: var(--clay-shadow-sm);
- }
- .family-empty-text { font-size: 24rpx; color: #94A3B8; }
- /* ========================================
- 快捷操作 2x2
- ======================================== */
- .quick-actions-section { margin-bottom: 32rpx; }
- .quick-actions-grid { display: flex; flex-wrap: wrap; gap: 16rpx; }
- .quick-action-item {
- width: calc(50% - 8rpx);
- display: flex; flex-direction: column; align-items: center;
- background: #fff;
- border-radius: 20rpx;
- padding: 28rpx;
- border: 4rpx solid #BFDBFE;
- box-shadow: var(--clay-shadow-sm);
- transition: var(--clay-transition);
- }
- .quick-action-item:active { transform: scale(0.94); box-shadow: var(--clay-shadow-sm); }
- .quick-action-icon {
- width: 72rpx; height: 72rpx;
- border-radius: 20rpx;
- display: flex; align-items: center; justify-content: center;
- margin-bottom: 12rpx;
- border: 3rpx solid transparent;
- box-shadow: inset -2rpx -2rpx 5rpx rgba(255,255,255,0.4), 3rpx 3rpx 8rpx rgba(0,0,0,0.04);
- }
- .qa-emoji { font-size: 34rpx; }
- .qa-icon--assign { background: rgba(59,130,246,0.2); border-color: #BFDBFE; }
- .qa-icon--assessment { background: rgba(16,185,129,0.2); border-color: #A7F3D0; }
- .qa-icon--contact { background: rgba(245,158,11,0.2); border-color: #FDE68A; }
- .qa-icon--income { background: rgba(139,92,246,0.2); border-color: #DDD6FE; }
- .qa-label { font-size: 24rpx; font-weight: 600; color: #475569; }
- /* ========================================
- 数据趋势 - claymorphism
- ======================================== */
- .trend-section { margin-bottom: 32rpx; }
- .trend-chart {
- display: flex;
- justify-content: space-between;
- align-items: flex-end;
- background: #FFFFFF;
- border-radius: 24rpx;
- padding: 28rpx 24rpx;
- height: 220rpx;
- border: 4rpx solid #BFDBFE;
- box-shadow: inset -3rpx -3rpx 8rpx rgba(255,255,255,0.5), 6rpx 6rpx 18rpx rgba(59,130,246,0.08);
- }
- .trend-item {
- display: flex;
- flex-direction: column;
- align-items: center;
- flex: 1;
- }
- .trend-bar {
- width: 36rpx;
- background: linear-gradient(180deg, #93C5FD, #60A5FA);
- border-radius: 8rpx 8rpx 0 0;
- margin-bottom: 12rpx;
- transition: height 0.3s;
- }
- .trend-bar.trend-active {
- background: linear-gradient(180deg, #3B82F6, #2563EB);
- }
- .trend-day {
- font-size: 22rpx;
- color: #64748B;
- }
- /* ========================================
- 功能菜单 - claymorphism
- ======================================== */
- .menu-section { margin-bottom: 32rpx; }
- .menu-grid {
- display: flex;
- flex-wrap: wrap;
- background: #FFFFFF;
- border-radius: 24rpx;
- padding: 16rpx;
- border: 4rpx solid #BFDBFE;
- box-shadow: inset -3rpx -3rpx 8rpx rgba(255,255,255,0.5), 6rpx 6rpx 18rpx rgba(59,130,246,0.08);
- }
- .menu-item {
- width: 33.33%;
- display: flex;
- flex-direction: column;
- align-items: center;
- padding: 28rpx 0;
- position: relative;
- transition: var(--clay-transition);
- }
- .menu-item:active {
- transform: scale(0.93);
- }
- .menu-icon {
- width: 88rpx;
- height: 88rpx;
- border-radius: 24rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 38rpx;
- margin-bottom: 12rpx;
- border: 3rpx solid transparent;
- box-shadow: inset -2rpx -2rpx 5rpx rgba(255,255,255,0.4), 3rpx 3rpx 8rpx rgba(0,0,0,0.04);
- transition: var(--clay-transition);
- }
- .menu-item:active .menu-icon {
- box-shadow: inset 2rpx 2rpx 6rpx rgba(0,0,0,0.06), 1rpx 1rpx 3rpx rgba(0,0,0,0.03);
- }
- .mi-blue { background: rgba(59, 130, 246, 0.2); border-color: #BFDBFE; }
- .mi-gold { background: rgba(245, 158, 11, 0.2); border-color: #FDE68A; }
- .mi-purple { background: rgba(139, 92, 246, 0.2); border-color: #DDD6FE; }
- .mi-green { background: rgba(16, 185, 129, 0.2); border-color: #A7F3D0; }
- .mi-cyan { background: rgba(6, 182, 212, 0.2); border-color: #A5F3FC; }
- .mi-gray { background: rgba(100, 116, 139, 0.2); border-color: #CBD5E1; }
- .menu-label {
- font-size: 24rpx;
- color: #475569;
- font-weight: 500;
- }
- .menu-badge {
- position: absolute;
- top: 16rpx;
- right: 28rpx;
- background: #3B82F6;
- color: #FFFFFF;
- font-size: 20rpx;
- padding: 4rpx 12rpx;
- border-radius: 20rpx;
- border: 2rpx solid #60A5FA;
- }
- .msg-badge {
- position: absolute;
- top: 16rpx;
- right: 28rpx;
- background: #EF4444;
- color: #FFFFFF;
- font-size: 20rpx;
- min-width: 32rpx;
- text-align: center;
- padding: 4rpx 8rpx;
- border-radius: 20rpx;
- border: 2rpx solid #FCA5A5;
- }
- /* ========================================
- 快捷工具 - claymorphism
- ======================================== */
- .tools-section { margin-bottom: 48rpx; }
- .tools-row {
- display: flex;
- justify-content: space-between;
- background: #FFFFFF;
- border-radius: 24rpx;
- padding: 28rpx 16rpx;
- border: 4rpx solid #BFDBFE;
- box-shadow: inset -3rpx -3rpx 8rpx rgba(255,255,255,0.5), 6rpx 6rpx 18rpx rgba(59,130,246,0.08);
- }
- .tool-item {
- display: flex;
- flex-direction: column;
- align-items: center;
- flex: 1;
- transition: var(--clay-transition);
- }
- .tool-item:active {
- transform: scale(0.92);
- }
- .tool-icon-wrap {
- width: 72rpx;
- height: 72rpx;
- border-radius: 20rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- margin-bottom: 10rpx;
- border: 3rpx solid transparent;
- box-shadow: inset -2rpx -2rpx 5rpx rgba(255,255,255,0.4), 3rpx 3rpx 8rpx rgba(0,0,0,0.04);
- transition: var(--clay-transition);
- }
- .tool-item:active .tool-icon-wrap {
- box-shadow: inset 2rpx 2rpx 6rpx rgba(0,0,0,0.06), 1rpx 1rpx 3rpx rgba(0,0,0,0.03);
- }
- .tool-icon-text { font-size: 34rpx; }
- .tool-create { background: rgba(59, 130, 246, 0.2); border-color: #BFDBFE; }
- .tool-share { background: rgba(16, 185, 129, 0.2); border-color: #A7F3D0; }
- .tool-cal { background: rgba(245, 158, 11, 0.2); border-color: #FDE68A; }
- .tool-report { background: rgba(139, 92, 246, 0.2); border-color: #DDD6FE; }
- .tool-label {
- font-size: 22rpx;
- color: #475569;
- }
- </style>
|