feat: AI评估、个人中心、开始训练页面

This commit is contained in:
王天骄
2026-06-08 16:39:10 +08:00
parent 23550c3828
commit 2bfd15ba5e
50 changed files with 4038 additions and 981 deletions
@@ -0,0 +1,998 @@
<template>
<view class="learning-page">
<view class="learning-shell">
<view class="assistant-header">
<view class="header-left">
<button class="icon-button" aria-label="返回" @click="emit('go-home')">
<view class="history-icon"></view>
</button>
<text class="page-title">AI 学习助手</text>
</view>
<view class="header-actions">
<button class="director-chip" @click="modalVisible = true">
<image class="director-thumb" src="/static/config-doctor.png" mode="aspectFill"></image>
<text>咨询王主任</text>
</button>
<button class="icon-button muted" aria-label="更多" @click="showToast('更多功能即将开放')">
<view class="more-icon"></view>
</button>
</view>
</view>
<scroll-view class="chat-canvas" scroll-y :scroll-top="scrollTop">
<view class="time-row">
<text>今天 10:42 AM</text>
</view>
<view
v-for="message in messages"
:key="message.id"
class="message-block"
:class="`message-${message.role}`"
>
<view v-if="message.role === 'user'" class="user-bubble">
<text>{{ message.content }}</text>
</view>
<view v-else class="assistant-message">
<view class="assistant-meta">
<view class="robot-badge">
<view class="robot-icon"></view>
</view>
<text>AI 临床助理</text>
</view>
<view v-if="message.variant === 'acs-pathway'" class="assistant-card">
<text class="response-intro">急性冠脉综合征ACS临床路径</text>
<view class="pathway-card">
<view
v-for="step in pathwaySteps"
:key="step.title"
class="pathway-step"
>
<text class="step-index">{{ step.index }}</text>
<view class="step-copy">
<text class="step-title">{{ step.title }}</text>
<text class="step-desc">{{ step.description }}</text>
</view>
</view>
</view>
<view class="evidence-box">
<view class="evidence-heading">
<view class="verified-icon"></view>
<text>循证来源</text>
</view>
<text class="evidence-item">[1] 2023 AHA/ACC ACS 管理指南</text>
<text class="evidence-item">[2] 临床诊疗常规心血管分册</text>
</view>
</view>
<view v-else class="assistant-card simple-card">
<text>{{ message.content }}</text>
</view>
</view>
</view>
<view class="typing-row" :class="{ visible: typingVisible }">
<view class="typing-dots">
<view class="dot dot-one"></view>
<view class="dot dot-two"></view>
<view class="dot dot-three"></view>
</view>
<text>正在思考中...</text>
</view>
</scroll-view>
<view class="input-panel">
<scroll-view class="quick-actions" scroll-x>
<view class="quick-row">
<button
v-for="action in quickActions"
:key="action"
class="quick-chip"
@click="useQuickAction(action)"
>
{{ action }}
</button>
</view>
</scroll-view>
<view class="composer">
<textarea
class="message-input"
v-model="draft"
auto-height
maxlength="500"
placeholder="请输入您的问题..."
placeholder-class="input-placeholder"
@confirm="handleSend"
></textarea>
<view class="composer-actions">
<button class="attach-button" aria-label="附件" @click="showToast('附件上传即将开放')">
<view class="attach-icon"></view>
</button>
<button class="send-button" aria-label="发送" @click="handleSend">
<view class="send-icon"></view>
</button>
</view>
</view>
<text class="disclaimer">AI 生成内容仅供临床参考最终医疗决策请咨询资深医师</text>
</view>
<view v-if="modalVisible" class="modal-mask" @click="modalVisible = false">
<view class="wang-modal" @click.stop>
<view class="modal-header">
<view class="modal-doctor">
<image class="modal-avatar" src="/static/config-doctor.png" mode="aspectFill"></image>
<view class="modal-title-group">
<text class="modal-title">王主任</text>
<text class="modal-subtitle">临床教育首席专家</text>
</view>
</view>
<button class="icon-button muted" aria-label="关闭" @click="modalVisible = false">
<view class="close-icon"></view>
</button>
</view>
<view class="modal-body">
<view class="quote-card">
<text>对于 ACS 患者请务必牢记时间就是心肌虽然 AI 提供了标准的临床路径但结合患者个体化风险特征的临床判断仍是您最关键的工具</text>
</view>
<view class="mentor-grid">
<button class="mentor-card" @click="showToast('已选择查房带教')">
<view class="school-small-icon"></view>
<text>查房带教</text>
</button>
<button class="mentor-card" @click="showToast('已选择疑难会诊')">
<view class="notes-small-icon"></view>
<text>疑难会诊</text>
</button>
</view>
<button class="guidance-button" @click="showToast('一对一指导即将开始')">
开始一对一指导
</button>
</view>
</view>
</view>
<view class="toast" :class="{ visible: toastVisible }">{{ toastMessage }}</view>
</view>
</view>
</template>
<script setup lang="ts">
import { nextTick, onMounted, onUnmounted, ref } from 'vue'
type AssistantMessage = {
id: string
role: 'user' | 'assistant'
content: string
variant?: 'acs-pathway' | 'simple'
}
const emit = defineEmits<{
(event: 'go-home'): void
(event: 'open-settings'): void
(event: 'open-profile'): void
}>()
const quickActions = ['更新指南', '风险评估量表', '药理学详情', '病例研讨']
const pathwaySteps = [
{ index: '1', title: '早期识别', description: '10分钟内完成12导联心电图。' },
{ index: '2', title: '药物干预', description: '阿司匹林、氯吡格雷。' },
{ index: '3', title: '再灌注策略', description: 'STEMI需紧急PCI。' }
]
const messages = ref<AssistantMessage[]>([
{
id: 'sample-user',
role: 'user',
content: '你能解释一下急性冠脉综合征(ACS)的最新临床路径吗?'
},
{
id: 'sample-ai',
role: 'assistant',
content: '',
variant: 'acs-pathway'
}
])
const draft = ref('')
const modalVisible = ref(false)
const typingVisible = ref(false)
const toastMessage = ref('')
const toastVisible = ref(false)
const scrollTop = ref(0)
let typingTimer: ReturnType<typeof setTimeout> | null = null
let pulseTimer: ReturnType<typeof setInterval> | null = null
let toastTimer: ReturnType<typeof setTimeout> | null = null
function useQuickAction(action: string) {
const prompts: Record<string, string> = {
更新指南: '请帮我梳理 ACS 最新指南中需要重点关注的更新。',
风险评估量表: '请列出 ACS 常用风险评估量表及适用场景。',
药理学详情: '请说明 ACS 常用抗血小板药物的适应证和注意事项。',
病例研讨: '请用病例研讨形式带我复盘一例胸痛患者。'
}
draft.value = prompts[action] || action
}
function handleSend() {
const value = draft.value.trim()
if (!value) {
showToast('请输入问题')
return
}
messages.value.push({
id: `user-${Date.now()}`,
role: 'user',
content: value
})
draft.value = ''
typingVisible.value = true
scrollToBottom()
if (typingTimer) clearTimeout(typingTimer)
typingTimer = setTimeout(() => {
typingVisible.value = false
messages.value.push({
id: `assistant-${Date.now()}`,
role: 'assistant',
variant: 'simple',
content: '已收到。我会结合医院知识库、临床路径和指南证据,为你整理成可用于带教复盘的要点。'
})
scrollToBottom()
}, 900)
}
function scrollToBottom() {
nextTick(() => {
scrollTop.value += 1000
})
}
function showToast(message: string) {
if (toastTimer) clearTimeout(toastTimer)
toastMessage.value = message
toastVisible.value = true
uni.showToast({
title: message,
icon: 'none'
})
toastTimer = setTimeout(() => {
toastVisible.value = false
}, 1800)
}
onMounted(() => {
pulseTimer = setInterval(() => {
if (typingVisible.value) return
typingVisible.value = true
setTimeout(() => {
typingVisible.value = false
}, 2400)
}, 12000)
})
onUnmounted(() => {
if (typingTimer) clearTimeout(typingTimer)
if (pulseTimer) clearInterval(pulseTimer)
if (toastTimer) clearTimeout(toastTimer)
})
</script>
<style>
page {
min-height: 100%;
background: #f2f3fb;
}
.learning-page {
min-height: 100vh;
background: #f2f3fb;
color: #191c21;
font-family: Inter, -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
-webkit-tap-highlight-color: transparent;
}
.learning-shell {
position: relative;
min-height: 100vh;
background: #ffffff;
overflow: hidden;
display: flex;
flex-direction: column;
}
.assistant-header {
position: relative;
z-index: 10;
box-sizing: border-box;
height: 56px;
padding: 0 16px;
border-bottom: 1px solid #c2c6d4;
background: #ffffff;
display: flex;
align-items: center;
justify-content: space-between;
flex: 0 0 auto;
}
.header-left,
.header-actions,
.director-chip,
.assistant-meta,
.evidence-heading,
.composer-actions,
.modal-doctor {
display: flex;
align-items: center;
}
.header-left,
.header-actions {
gap: 12px;
}
.page-title {
color: #191c21;
font-size: 18px;
line-height: 28px;
font-weight: 600;
letter-spacing: 0;
}
.icon-button,
.director-chip,
.quick-chip,
.attach-button,
.send-button,
.mentor-card,
.guidance-button {
padding: 0;
border: 0;
background: transparent;
}
.icon-button::after,
.director-chip::after,
.quick-chip::after,
.attach-button::after,
.send-button::after,
.mentor-card::after,
.guidance-button::after {
border: 0;
}
.icon-button {
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
}
.icon-button:active {
background: rgba(25, 28, 33, 0.05);
}
.director-chip {
box-sizing: border-box;
min-height: 32px;
padding: 4px 8px;
border: 1px solid #c2c6d4;
border-radius: 12px;
background: #f2f3fb;
gap: 8px;
color: #00478d;
font-size: 12px;
line-height: 16px;
font-weight: 600;
}
.director-thumb {
width: 20px;
height: 20px;
border-radius: 50%;
flex: 0 0 auto;
}
.history-icon,
.more-icon,
.robot-icon,
.verified-icon,
.attach-icon,
.send-icon,
.close-icon,
.school-small-icon,
.notes-small-icon {
background: #424752;
-webkit-mask-position: center;
-webkit-mask-repeat: no-repeat;
-webkit-mask-size: contain;
mask-position: center;
mask-repeat: no-repeat;
mask-size: contain;
}
.history-icon {
width: 24px;
height: 24px;
-webkit-mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M13%203a9%209%200%201%201-8.95%2010H2l3-3%203%203H6.07A7%207%200%201%200%208.1%208.05L6.68%206.63A8.96%208.96%200%200%201%2013%203zm-1%205h1.5v5l4%202-.75%201.23L12%2013.75V8z'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M13%203a9%209%200%201%201-8.95%2010H2l3-3%203%203H6.07A7%207%200%201%200%208.1%208.05L6.68%206.63A8.96%208.96%200%200%201%2013%203zm-1%205h1.5v5l4%202-.75%201.23L12%2013.75V8z'/%3E%3C/svg%3E");
}
.more-icon {
width: 24px;
height: 24px;
-webkit-mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M12%208a2%202%200%201%200%200-4%202%202%200%200%200%200%204zm0%202a2%202%200%201%200%200%204%202%202%200%200%200%200-4zm0%206a2%202%200%201%200%200%204%202%202%200%200%200%200-4z'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M12%208a2%202%200%201%200%200-4%202%202%200%200%200%200%204zm0%202a2%202%200%201%200%200%204%202%202%200%200%200%200-4zm0%206a2%202%200%201%200%200%204%202%202%200%200%200%200-4z'/%3E%3C/svg%3E");
}
.chat-canvas {
box-sizing: border-box;
flex: 1 1 auto;
min-height: 0;
padding: 16px;
background: #ffffff;
}
.time-row {
display: flex;
justify-content: center;
margin-bottom: 32px;
}
.time-row text {
padding: 4px 16px;
border-radius: 12px;
background: #f2f3fb;
color: #727783;
font-size: 12px;
line-height: 16px;
font-weight: 500;
letter-spacing: 0;
}
.message-block {
margin-bottom: 16px;
}
.message-user {
display: flex;
justify-content: flex-end;
}
.user-bubble {
box-sizing: border-box;
max-width: 85%;
padding: 12px 16px;
border-radius: 8px 8px 0 8px;
background: #00478d;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
color: #ffffff;
font-size: 16px;
line-height: 24px;
}
.assistant-message {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.assistant-meta {
gap: 8px;
color: #00478d;
font-size: 14px;
line-height: 20px;
font-weight: 600;
}
.robot-badge {
width: 28px;
height: 28px;
border-radius: 8px;
background: #00478d;
display: flex;
align-items: center;
justify-content: center;
}
.robot-icon {
width: 18px;
height: 18px;
background: #ffffff;
-webkit-mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M12%202a2%202%200%200%201%201%203.73V7h4a3%203%200%200%201%203%203v7a3%203%200%200%201-3%203H7a3%203%200%200%201-3-3v-7a3%203%200%200%201%203-3h4V5.73A2%202%200%200%201%2012%202zM7%2010a1%201%200%200%200-1%201v6a1%201%200%200%200%201%201h10a1%201%200%200%200%201-1v-6a1%201%200%200%200-1-1H7zm2.5%203.5a1.5%201.5%200%201%201%200-3%201.5%201.5%200%200%201%200%203zm5%200a1.5%201.5%200%201%201%200-3%201.5%201.5%200%200%201%200%203z'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M12%202a2%202%200%200%201%201%203.73V7h4a3%203%200%200%201%203%203v7a3%203%200%200%201-3%203H7a3%203%200%200%201-3-3v-7a3%203%200%200%201%203-3h4V5.73A2%202%200%200%201%2012%202zM7%2010a1%201%200%200%200-1%201v6a1%201%200%200%200%201%201h10a1%201%200%200%200%201-1v-6a1%201%200%200%200-1-1H7zm2.5%203.5a1.5%201.5%200%201%201%200-3%201.5%201.5%200%200%201%200%203zm5%200a1.5%201.5%200%201%201%200-3%201.5%201.5%200%200%201%200%203z'/%3E%3C/svg%3E");
}
.assistant-card {
box-sizing: border-box;
max-width: 90%;
padding: 16px;
border: 1px solid #c2c6d4;
border-radius: 0 8px 8px 8px;
background: #ffffff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
display: flex;
flex-direction: column;
gap: 12px;
}
.response-intro,
.simple-card {
color: #191c21;
font-size: 16px;
line-height: 24px;
}
.pathway-card {
box-sizing: border-box;
padding: 16px;
border: 1px solid rgba(194, 198, 212, 0.3);
border-radius: 8px;
background: #f2f3fb;
display: flex;
flex-direction: column;
gap: 16px;
}
.pathway-step {
display: flex;
align-items: flex-start;
gap: 12px;
}
.step-index {
width: 20px;
height: 20px;
border-radius: 50%;
background: #00478d;
color: #ffffff;
font-size: 10px;
line-height: 20px;
text-align: center;
font-weight: 600;
flex: 0 0 auto;
margin-top: 2px;
}
.step-copy {
display: flex;
flex-direction: column;
gap: 2px;
}
.step-title {
color: #00478d;
font-size: 14px;
line-height: 20px;
font-weight: 600;
}
.step-desc {
color: #424752;
font-size: 14px;
line-height: 20px;
}
.evidence-box {
padding-top: 16px;
border-top: 1px solid #c2c6d4;
display: flex;
flex-direction: column;
gap: 4px;
}
.evidence-heading {
gap: 8px;
margin-bottom: 4px;
color: #006970;
font-size: 12px;
line-height: 16px;
font-weight: 700;
letter-spacing: 0;
}
.verified-icon {
width: 16px;
height: 16px;
background: #006970;
-webkit-mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M12%202l2.39%202.42%203.37-.49.6%203.35%203.02%201.57-1.55%203.03%201.55%203.03-3.02%201.57-.6%203.35-3.37-.49L12%2022l-2.39-2.42-3.37.49-.6-3.35-3.02-1.57%201.55-3.03-1.55-3.03%203.02-1.57.6-3.35%203.37.49L12%202zm-1.1%2013.2l5.66-5.66-1.42-1.42-4.24%204.24-2.12-2.12-1.42%201.42%203.54%203.54z'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M12%202l2.39%202.42%203.37-.49.6%203.35%203.02%201.57-1.55%203.03%201.55%203.03-3.02%201.57-.6%203.35-3.37-.49L12%2022l-2.39-2.42-3.37.49-.6-3.35-3.02-1.57%201.55-3.03-1.55-3.03%203.02-1.57.6-3.35%203.37.49L12%202zm-1.1%2013.2l5.66-5.66-1.42-1.42-4.24%204.24-2.12-2.12-1.42%201.42%203.54%203.54z'/%3E%3C/svg%3E");
}
.evidence-item {
color: #424752;
font-size: 13px;
line-height: 20px;
font-style: italic;
}
.typing-row {
display: flex;
align-items: center;
gap: 8px;
color: #727783;
font-size: 12px;
line-height: 16px;
font-style: italic;
opacity: 0;
transition: opacity 0.3s ease;
}
.typing-row.visible {
opacity: 1;
}
.typing-dots {
display: flex;
gap: 4px;
}
.dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: #727783;
animation: typing-bounce 1s ease-in-out infinite;
}
.dot-two {
animation-delay: 0.12s;
}
.dot-three {
animation-delay: 0.24s;
}
.input-panel {
box-sizing: border-box;
padding: 12px 16px 16px;
border-top: 1px solid #c2c6d4;
background: #ffffff;
flex: 0 0 auto;
}
.quick-actions {
width: 100%;
margin-bottom: 12px;
white-space: nowrap;
}
.quick-row {
display: flex;
gap: 8px;
padding-bottom: 4px;
}
.quick-chip {
box-sizing: border-box;
min-height: 32px;
padding: 6px 16px;
border: 1px solid #c2c6d4;
border-radius: 12px;
background: #ecedf6;
color: #424752;
font-size: 12px;
line-height: 16px;
font-weight: 500;
letter-spacing: 0;
white-space: nowrap;
}
.quick-chip:active {
background: #e7e8f0;
}
.composer {
box-sizing: border-box;
padding: 8px;
border: 1px solid #c2c6d4;
border-radius: 8px;
background: #f2f3fb;
display: flex;
align-items: flex-end;
gap: 8px;
}
.composer:focus-within {
border-color: #00478d;
}
.message-input {
flex: 1;
min-height: 44px;
max-height: 128px;
padding: 8px 0;
border: 0;
background: transparent;
color: #191c21;
font-size: 16px;
line-height: 24px;
}
.input-placeholder {
color: #727783;
}
.composer-actions {
gap: 4px;
flex: 0 0 auto;
margin-bottom: 4px;
}
.attach-button,
.send-button {
width: 40px;
height: 40px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
}
.attach-icon {
width: 22px;
height: 22px;
background: #727783;
-webkit-mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M16.5%206.5v9a4.5%204.5%200%200%201-9%200v-10a3%203%200%200%201%206%200v9a1.5%201.5%200%200%201-3%200v-8h2v8a.5.5%200%200%200%201%200v-9a2%202%200%200%200-4%200v10a2.5%202.5%200%200%200%205%200v-9h2z'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M16.5%206.5v9a4.5%204.5%200%200%201-9%200v-10a3%203%200%200%201%206%200v9a1.5%201.5%200%200%201-3%200v-8h2v8a.5.5%200%200%200%201%200v-9a2%202%200%200%200-4%200v10a2.5%202.5%200%200%200%205%200v-9h2z'/%3E%3C/svg%3E");
}
.send-button {
background: #00478d;
}
.send-button:active {
transform: scale(0.95);
}
.send-icon {
width: 20px;
height: 20px;
background: #ffffff;
-webkit-mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M2%2021l21-9L2%203v7l15%202-15%202v7z'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M2%2021l21-9L2%203v7l15%202-15%202v7z'/%3E%3C/svg%3E");
}
.disclaimer {
display: block;
margin-top: 8px;
text-align: center;
color: #727783;
font-size: 11px;
line-height: 16px;
}
.modal-mask {
position: absolute;
inset: 0;
z-index: 60;
background: rgba(0, 0, 0, 0.2);
backdrop-filter: blur(2px);
-webkit-backdrop-filter: blur(2px);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.wang-modal {
width: 100%;
max-width: 340px;
border: 1px solid #c2c6d4;
border-radius: 8px;
background: #ffffff;
box-shadow: 0 18px 48px rgba(25, 28, 33, 0.2);
overflow: hidden;
animation: fade-in 0.2s ease-out forwards;
}
.modal-header {
box-sizing: border-box;
padding: 24px;
border-bottom: 1px solid #c2c6d4;
background: #ffffff;
display: flex;
align-items: center;
justify-content: space-between;
}
.modal-doctor {
gap: 16px;
}
.modal-avatar {
width: 56px;
height: 56px;
border: 2px solid #00478d;
border-radius: 50%;
}
.modal-title-group {
display: flex;
flex-direction: column;
gap: 2px;
}
.modal-title {
color: #191c21;
font-size: 20px;
line-height: 28px;
font-weight: 600;
}
.modal-subtitle {
color: #727783;
font-size: 14px;
line-height: 20px;
}
.close-icon {
width: 22px;
height: 22px;
-webkit-mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M18.3%205.71L12%2012l6.3%206.29-1.41%201.41L10.59%2013.41%204.29%2019.7%202.88%2018.29%209.17%2012%202.88%205.71%204.29%204.3l6.3%206.29%206.3-6.29%201.41%201.41z'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M18.3%205.71L12%2012l6.3%206.29-1.41%201.41L10.59%2013.41%204.29%2019.7%202.88%2018.29%209.17%2012%202.88%205.71%204.29%204.3l6.3%206.29%206.3-6.29%201.41%201.41z'/%3E%3C/svg%3E");
}
.modal-body {
padding: 24px;
display: flex;
flex-direction: column;
gap: 16px;
}
.quote-card {
padding: 16px;
border: 1px solid rgba(0, 71, 141, 0.1);
border-radius: 8px;
background: rgba(0, 94, 184, 0.06);
text-align: center;
color: #191c21;
font-size: 16px;
line-height: 24px;
font-style: italic;
}
.mentor-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
.mentor-card {
box-sizing: border-box;
min-height: 96px;
padding: 16px;
border: 1px solid rgba(194, 198, 212, 0.3);
border-radius: 8px;
background: #f2f3fb;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8px;
color: #191c21;
font-size: 14px;
line-height: 20px;
font-weight: 600;
}
.school-small-icon,
.notes-small-icon {
width: 24px;
height: 24px;
background: #00478d;
}
.school-small-icon {
-webkit-mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M12%203L1%209l11%206%209-4.91V17h2V9L12%203zm0%2014L5%2013.18V17l7%204%207-4v-3.82L12%2017z'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M12%203L1%209l11%206%209-4.91V17h2V9L12%203zm0%2014L5%2013.18V17l7%204%207-4v-3.82L12%2017z'/%3E%3C/svg%3E");
}
.notes-small-icon {
-webkit-mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M6%202h9l5%205v15H6a2%202%200%200%201-2-2V4a2%202%200%200%201%202-2zm8%201.5V8h4.5L14%203.5zM8%2011v2h8v-2H8zm0%204v2h8v-2H8zm0%204h5v-2H8v2z'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M6%202h9l5%205v15H6a2%202%200%200%201-2-2V4a2%202%200%200%201%202-2zm8%201.5V8h4.5L14%203.5zM8%2011v2h8v-2H8zm0%204v2h8v-2H8zm0%204h5v-2H8v2z'/%3E%3C/svg%3E");
}
.guidance-button {
width: 100%;
min-height: 44px;
border-radius: 8px;
background: #00478d;
color: #ffffff;
font-size: 14px;
line-height: 20px;
font-weight: 600;
}
.guidance-button:active {
transform: scale(0.98);
}
.toast {
position: absolute;
left: 50%;
bottom: 96px;
z-index: 100;
max-width: 300px;
padding: 10px 18px;
border-radius: 12px;
background: #2e3037;
color: #eff0f8;
font-size: 14px;
line-height: 20px;
font-weight: 600;
text-align: center;
pointer-events: none;
opacity: 0;
transform: translate(-50%, 16px);
transition: opacity 0.3s ease, transform 0.3s ease;
}
.toast.visible {
opacity: 1;
transform: translate(-50%, 0);
}
@keyframes typing-bounce {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-4px);
}
}
@keyframes fade-in {
from {
opacity: 0;
transform: scale(0.95);
}
to {
opacity: 1;
transform: scale(1);
}
}
@media (min-width: 768px) {
.learning-page {
display: flex;
justify-content: center;
background: #d8dae2;
}
.learning-shell {
width: 390px;
min-height: 100vh;
box-shadow: 0 24px 64px rgba(25, 28, 33, 0.18);
}
}
@media (max-height: 760px) {
.chat-canvas {
padding: 12px 16px;
}
.time-row {
margin-bottom: 20px;
}
.input-panel {
padding-bottom: 12px;
}
}
</style>