diff --git a/mobile-uni/src/pages/auth/login/index.vue b/mobile-uni/src/pages/auth/login/index.vue index bb6b516e..7572468e 100644 --- a/mobile-uni/src/pages/auth/login/index.vue +++ b/mobile-uni/src/pages/auth/login/index.vue @@ -1,17 +1,20 @@ @@ -213,7 +218,7 @@ onShow(() => { .login-shell { min-height: 100vh; - padding: 72px 24px 36px; + padding: 36px 24px 28px; overflow: hidden; } @@ -240,24 +245,19 @@ onShow(() => { left: -72px; } -.login-head { - position: relative; - max-width: 720px; - margin: 0 auto 32px; -} - .brand-lockup { display: flex; align-items: center; - gap: 12px; - margin-bottom: 28px; + justify-content: center; + gap: 10px; + max-width: 720px; + margin: 0 auto 22px; } .login-logo { - width: 48px; - height: 48px; + width: 34px; + height: 34px; flex: none; - transform: translateX(6px) scale(1.4); } .brand-copy { @@ -286,21 +286,49 @@ onShow(() => { color: #e60012; } -.login-head .page-title { - display: block; - color: #252931; - font-size: 34px; - font-weight: 800; - line-height: 1.16; - letter-spacing: 1px; +.mentor-block { + display: flex; + align-items: flex-start; + gap: 12px; + max-width: 720px; + margin: 0 auto 18px; + padding: 0 6px; } -.login-head .page-subtitle { - display: block; - margin-top: 12px; - color: #6d7078; - font-size: 15px; - line-height: 1.6; +.mentor-image { + width: 128px; + height: 130px; + flex: none; +} + +.mentor-bubble { + position: relative; + margin-top: 20px; + padding: 12px 16px; + border: 1px solid rgba(225, 227, 232, 0.9); + border-radius: 14px; + background: #ffffff; + box-shadow: 0 6px 16px rgba(29, 31, 35, 0.08); +} + +.mentor-bubble::before { + position: absolute; + top: 22px; + left: -6px; + width: 10px; + height: 10px; + border-bottom: 1px solid rgba(225, 227, 232, 0.9); + border-left: 1px solid rgba(225, 227, 232, 0.9); + background: #ffffff; + content: ''; + transform: rotate(45deg); +} + +.mentor-bubble-text { + color: #25282d; + font-size: 16px; + font-weight: 600; + line-height: 1.5; } .login-card { @@ -310,7 +338,7 @@ onShow(() => { gap: 18px; max-width: 720px; margin: 0 auto; - padding: 36px 20px 36px; + padding: 28px 20px 28px; border: 1px solid rgba(225, 227, 232, 0.95); border-top: 4px solid #e60012; border-radius: 18px; @@ -470,6 +498,16 @@ onShow(() => { border-radius: 10px; } +.agreement { + display: block; + max-width: 720px; + margin: 16px auto 0; + color: #a4a8b0; + font-size: 12px; + line-height: 1.5; + text-align: center; +} + @media (max-width: 375px) { .login-shell { padding-right: 32px; @@ -482,8 +520,9 @@ onShow(() => { font-size: 17px; } - .login-head .page-title { - font-size: 32px; + .mentor-image { + width: 112px; + height: 114px; } .code-row { diff --git a/mobile-uni/src/pages/user/sop/index.vue b/mobile-uni/src/pages/user/sop/index.vue index 2bbb9e0c..e2f0690e 100644 --- a/mobile-uni/src/pages/user/sop/index.vue +++ b/mobile-uni/src/pages/user/sop/index.vue @@ -17,7 +17,7 @@ - 师 + 你好,我是老师傅。工作里的 SOP、话术、流程直接问我,答案都带引用依据;也可以按住下面的按钮说话。 @@ -37,14 +37,14 @@ - 师 + 师傅思考中… - 师 + - 师 + 登录后才能查询 SOP、生成总结卡并反馈答案。 @@ -2066,7 +2066,8 @@ onUnload(() => { } .master-avatar { - background: #e70014; + overflow: hidden; + background: #f3f4f6; color: #ffffff; } diff --git a/mobile-uni/src/pages/user/today/index.vue b/mobile-uni/src/pages/user/today/index.vue index a9d0f056..36f403b2 100644 --- a/mobile-uni/src/pages/user/today/index.vue +++ b/mobile-uni/src/pages/user/today/index.vue @@ -13,63 +13,59 @@ {{ message }} - + + + {{ positionProfile.value }} {{ positionProfile.heroTitle }} 有问题,随时问老师傅 - {{ mentorBubbleText }} - + {{ mentorBubbleText }} - + - - - - - - + + + {{ voiceTitle }} + {{ voiceSub }} + - - - - + + + @@ -95,19 +91,9 @@ - - - + 1 - - {{ primaryAssignmentSourceLabel }} - - {{ primaryScheduleTitle }} - - {{ primaryScheduleTime }} - · - {{ primarySchedulePlace }} - + {{ primaryDisplayTitle }} {{ primaryScheduleDesc }} @@ -133,23 +112,44 @@ - - + + + + + 常用功能 + + + + + + + - @@ -162,6 +162,7 @@ import { getMobileHome } from '@/services/home'; import { getPracticeAssignments } from '@/services/practice'; import { getSelectedPositionProfile, isLoggedIn, rememberLoginRedirect } from '@/services/auth'; import { resetPageScroll } from '@/services/navigation'; +import { chooseSpeechAudio, transcribeSpeechBlob, transcribeSpeechFile } from '@/services/speech'; import { stripInternalCodes } from '@/services/text'; import { ensureEmployeePosition } from '@/services/position'; import { createPageRequestScope, currentAccountKey } from '@/services/request-scope'; @@ -224,9 +225,11 @@ const primaryAssignmentSourceLabel = computed(() => primaryAssignment.value ? assignmentSourceLabel(primaryAssignment.value.source) : '' ); -const primaryAssignmentSourceClass = computed(() => - primaryAssignment.value?.source || 'manual' -); +const primaryDisplayTitle = computed(() => { + const label = primaryAssignmentSourceLabel.value; + const title = primaryScheduleTitle.value; + return label && title ? `${label}:${title}` : title; +}); const primaryScheduleDesc = computed(() => { const item = primaryAssignment.value; @@ -237,18 +240,6 @@ const primaryScheduleDesc = computed(() => { return home.value?.primary?.desc || '进入练习页查看今日任务'; }); -const primaryScheduleTime = computed(() => { - const item = primaryAssignment.value; - if (item?.source === 'daily') return '今日'; - return '09:30-11:30'; -}); - -const primarySchedulePlace = computed(() => { - const item = primaryAssignment.value; - if (item?.source === 'daily') return '线上答题'; - return '线上学习'; -}); - const tipBody = computed(() => { const tip = positionProfile.value.tip || ''; return tip.replace(/^今日小贴士[::]\s*/, '').replace(/^小贴士[::]\s*/, '') || tip; @@ -304,8 +295,138 @@ const loadHome = async () => { } }; -const goSop = () => { - uni.switchTab({ url: '/pages/user/sop/index' }); +const recording = ref(false); +const cancelling = ref(false); +const transcribing = ref(false); +let recorder: MediaRecorder | null = null; +let recordStream: MediaStream | null = null; +let holdGeneration = 0; +let discardRecording = false; +let holdStartY = 0; + +const voiceTitle = computed(() => { + if (transcribing.value) return '正在识别'; + if (recording.value) return cancelling.value ? '松开取消' : '松开发送'; + return '按住说话'; +}); + +const voiceSub = computed(() => { + if (transcribing.value) return '老师傅正在听…'; + if (recording.value) return '上滑取消'; + return '松开发送,上滑取消'; +}); + +const supportsRecording = () => + typeof navigator !== 'undefined' + && Boolean(navigator.mediaDevices?.getUserMedia) + && typeof MediaRecorder !== 'undefined'; + +const stopRecordTracks = () => { + recordStream?.getTracks().forEach((track) => track.stop()); + recordStream = null; +}; + +const startHold = async (event?: TouchEvent | MouseEvent) => { + if (recording.value || transcribing.value) return; + if (!loggedIn.value) { + goLogin(); + return; + } + if (!supportsRecording()) { + void pickAudioFallback(); + return; + } + const generation = ++holdGeneration; + discardRecording = false; + cancelling.value = false; + if (event && 'touches' in event && event.touches[0]) { + holdStartY = event.touches[0].clientY; + } + try { + const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true }); + if (generation !== holdGeneration) { + mediaStream.getTracks().forEach((track) => track.stop()); + return; + } + recordStream = mediaStream; + const mediaRecorder = new MediaRecorder(mediaStream); + const chunks: Blob[] = []; + recorder = mediaRecorder; + mediaRecorder.ondataavailable = (e) => { + if (e.data?.size) chunks.push(e.data); + }; + mediaRecorder.onstop = () => { + recording.value = false; + recorder = null; + stopRecordTracks(); + if (discardRecording) return; + const blob = new Blob(chunks, { type: mediaRecorder.mimeType || 'audio/webm' }); + if (blob.size) void handleVoiceBlob(blob); + }; + mediaRecorder.start(); + recording.value = true; + } catch { + stopRecordTracks(); + if (generation === holdGeneration) void pickAudioFallback(); + } +}; + +const moveHold = (event: TouchEvent) => { + if (!recording.value) return; + const y = event.touches[0]?.clientY ?? holdStartY; + cancelling.value = holdStartY - y > 60; +}; + +const endHold = () => { + if (!recording.value) return; + discardRecording = cancelling.value; + if (recorder && recorder.state !== 'inactive') recorder.stop(); +}; + +const cancelHold = () => { + if (!recording.value) return; + discardRecording = true; + if (recorder && recorder.state !== 'inactive') recorder.stop(); +}; + +const handleVoiceBlob = async (blob: Blob) => { + transcribing.value = true; + message.value = ''; + try { + const result = await transcribeSpeechBlob(blob, 'today-ask.webm'); + const text = result.text?.trim(); + if (text) ask(text); + else message.value = '没听清,请再说一次'; + } catch (error) { + message.value = error instanceof Error ? error.message : '语音识别失败,请重试'; + } finally { + transcribing.value = false; + } +}; + +const pickAudioFallback = async () => { + try { + const file = await chooseSpeechAudio(); + transcribing.value = true; + const result = await transcribeSpeechFile(file); + const text = result.text?.trim(); + if (text) ask(text); + else message.value = '没听清,请再说一次'; + } catch (error) { + if (error instanceof Error && error.message !== '未选择音频') { + message.value = error.message; + } + } finally { + transcribing.value = false; + } +}; + +const openLearning = () => { + uni.navigateTo({ url: '/pages/user/learning/index' }); +}; + +const openReport = () => { + uni.navigateTo({ url: '/pages/user/report/index' }); }; const ask = (query: string) => { @@ -358,10 +479,14 @@ onShow(() => { }); onHide(() => { + holdGeneration += 1; + cancelHold(); requests.invalidate(); }); onUnload(() => { + holdGeneration += 1; + cancelHold(); requests.invalidate(); }); @@ -373,57 +498,6 @@ onUnload(() => { background: #f7f7f7; } -.question-board-card { - display: flex; - width: 100%; - gap: 12px; - align-items: center; - margin-top: 16px; - padding: 16px; - color: var(--ink); - text-align: left; -} - -.question-board-icon { - display: flex; - flex: 0 0 44px; - width: 44px; - height: 44px; - align-items: center; - justify-content: center; - border-radius: 14px; - background: #fff0f1; - color: var(--brand); - font-weight: 900; -} - -.question-board-copy { - min-width: 0; - flex: 1; -} - -.question-board-title, -.question-board-desc { - display: block; -} - -.question-board-title { - font-size: 17px; - font-weight: 900; -} - -.question-board-desc { - margin-top: 4px; - color: var(--muted); - font-size: 13px; - line-height: 1.5; -} - -.question-board-arrow { - color: var(--muted); - font-size: 28px; -} - .brand-bar { display: flex; align-items: center; @@ -482,27 +556,39 @@ onUnload(() => { font-size: 13px; } -.mentor-hero { +.hero-immersive { position: relative; - display: flex; - min-height: 196px; - align-items: flex-start; - justify-content: space-between; - margin-top: 2px; - padding: 0; - border-radius: 20px; - background: #ffffff; + min-height: 216px; + margin: 2px -16px 0; overflow: hidden; } +.hero-bg { + position: absolute; + inset: 0; + width: 100%; + height: 100%; +} + +.hero-scrim { + position: absolute; + inset: 0; + background: linear-gradient( + 90deg, + rgba(255, 255, 255, 0.92) 0%, + rgba(255, 255, 255, 0.62) 34%, + rgba(255, 255, 255, 0) 64% + ); +} + .hero-copy { position: relative; z-index: 2; display: flex; - width: 52%; - max-width: 52%; + width: 54%; + max-width: 54%; flex-direction: column; - padding: 22px 0 0 20px; + padding: 26px 0 0 24px; } .hero-role, @@ -516,43 +602,36 @@ onUnload(() => { .hero-sub { margin-top: 2px; - color: #8a8d93; + color: #4b5058; font-size: 14px; white-space: nowrap; line-height: 1.4; } -.hero-tip { - margin-top: 7px; - color: var(--employee-primary); - font-size: 13px; - line-height: 1.4; - white-space: nowrap; -} - -.mentor-stage { - position: relative; +.hero-stage { + position: absolute; + right: 0; + bottom: 0; z-index: 1; - width: 178px; - height: 196px; - flex: none; + width: 190px; + height: 216px; } .mentor-image { position: absolute; - right: 4px; - bottom: 4px; - width: 140px; - height: 140px; - filter: drop-shadow(0 10px 16px rgba(20, 24, 32, 0.12)); + right: 10px; + bottom: 0; + width: 126px; + height: 210px; + filter: drop-shadow(0 10px 16px rgba(20, 24, 32, 0.18)); } .mentor-bubble { position: absolute; - top: 10px; - right: 84px; + top: 16px; + right: 118px; z-index: 3; - width: 112px; + max-width: 150px; padding: 10px 12px; border-radius: 18px; background: #ffffff; @@ -578,151 +657,73 @@ onUnload(() => { line-height: 1.45; } -.ask-card { +.voice-card { position: relative; z-index: 4; - margin-top: 10px; - padding: 12px 14px 10px; - border: 0; - border-radius: 20px; + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + margin: -48px 4px 0; + padding: 22px 16px 16px; + border-radius: 22px; background: #ffffff; - box-shadow: 0 10px 28px rgba(24, 28, 36, 0.06); + box-shadow: 0 14px 34px rgba(24, 28, 36, 0.1); } -.voice-panel { +.voice-mic { display: flex; - align-items: center; - min-height: 82px; - gap: 10px; -} - -.voice-primary, -.voice-secondary { - display: flex; - min-width: 0; - align-items: center; - margin: 0; - border: 0; - border-radius: 0; - background: transparent; - box-shadow: none; - text-align: left; -} - -.voice-primary::after, -.voice-secondary::after { - border: 0; -} - -.voice-primary { - flex: 1.45; - min-height: 70px; - gap: 10px; - padding: 0; -} - -.voice-secondary { - flex: 1; - gap: 10px; - min-height: 70px; - padding: 0; -} - -.voice-divider { - display: none; -} - -.voice-emblem { - display: flex; - width: 64px; - height: 64px; - flex: none; + width: 96px; + height: 96px; align-items: center; justify-content: center; + margin: 0; + padding: 0; + border: 0; border-radius: 50%; background: var(--employee-primary); - box-shadow: none; -} - -.voice-mark { - color: #ffffff; - font-size: 24px; - font-weight: 900; + box-shadow: 0 10px 24px rgba(230, 0, 18, 0.28); line-height: 1; } -.voice-copy { - display: flex; - min-width: 0; - flex-direction: column; - gap: 4px; +.voice-mic::after { + border: 0; +} + +.voice-mic.recording { + background: var(--brand-pressed); + box-shadow: 0 6px 16px rgba(184, 0, 15, 0.3); + transform: scale(0.95); +} + +.voice-mic.cancelling { + background: #6b7280; + box-shadow: 0 6px 16px rgba(107, 114, 128, 0.3); } .voice-title { - color: #1a1a1a; - font-size: 18px; + color: var(--employee-primary); + font-size: 20px; font-weight: 800; line-height: 1.2; - white-space: nowrap; } -.voice-primary .voice-title { - color: #1a1a1a; -} - -.secondary-title { - font-size: 18px; -} - -.voice-desc { +.voice-sub { color: #9a9da3; - font-size: 12px; + font-size: 13px; font-weight: 500; line-height: 1.3; - white-space: nowrap; -} - -.voice-primary .voice-desc { - color: #9a9da3; -} - -.secondary-copy { - max-width: 108px; -} - -.secondary-copy .voice-desc { - width: 96px; - white-space: normal; - line-height: 1.45; -} - -.keyboard-mark { - display: flex; - width: 64px; - height: 64px; - flex: none; - align-items: center; - justify-content: center; - border-radius: 16px; - background: #f3f4f6; -} - -.keyboard-icon { - color: #6b7280; - line-height: 1; } .mentor-chips { - margin-top: 4px; - padding-top: 8px; - border-top: 1px solid #f0f1f3; + margin-top: 14px; } .chip-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; - padding: 0 10px; + padding: 0 2px; } .chip { @@ -872,22 +873,18 @@ onUnload(() => { background: #fafafa; } -.schedule-icon-wrap { +.schedule-num { display: flex; - width: 52px; - height: 52px; + width: 30px; + height: 30px; flex: none; align-items: center; justify-content: center; border-radius: 50%; - background: var(--employee-primary-soft); -} - -.review-icon { - background: #fff7eb; -} - -.schedule-icon { + background: var(--employee-primary); + color: #ffffff; + font-size: 16px; + font-weight: 800; line-height: 1; } @@ -906,46 +903,6 @@ onUnload(() => { line-height: 1.25; } -.schedule-source { - display: inline-flex; - width: fit-content; - padding: 3px 8px; - border-radius: 999px; - background: #edf3ff; - color: #2f6bff; - font-size: 12px; - font-weight: 800; - line-height: 1.3; -} - -.schedule-source.retry { - background: #fff1f2; - color: #d51b2b; -} - -.schedule-source.camp { - background: #fff7eb; - color: #b86b00; -} - -.schedule-source.daily { - background: #eef8f2; - color: #258652; -} - -.schedule-meta { - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 4px; - color: #9a9da3; - font-size: 14px; -} - -.meta-dot { - color: #c5c7cb; -} - .schedule-desc { color: #8a8d93; font-size: 14px; @@ -954,121 +911,86 @@ onUnload(() => { .schedule-action { display: flex; - width: 86px; + width: auto; + min-width: 88px; min-height: 52px; flex: none; align-items: center; justify-content: center; + padding: 0 10px; border-radius: 12px; background: var(--employee-primary); box-shadow: 0 8px 16px rgba(230, 0, 18, 0.18); color: #ffffff; - font-size: 18px; + font-size: 17px; font-weight: 800; + line-height: 1.2; + white-space: nowrap; } .review-action { - background: #d98200; - box-shadow: 0 8px 16px rgba(217, 130, 0, 0.16); -} - -.map-grid { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 10px; -} - -.map-tile { - display: flex; - min-height: 70px; - align-items: center; - gap: 10px; - padding: 10px 8px; - border: 1px solid #e2e4e8; - border-radius: 14px; - background: #ffffff; - text-align: left; - overflow: hidden; -} - -.map-tile.ask, -.map-tile.practice, -.map-tile.learn, -.map-tile.report { - color: #25282d; + border: 1.5px solid var(--employee-primary); background: #ffffff; box-shadow: none; + color: var(--employee-primary); } -.map-tile.ask, -.map-symbol.ask { --map-accent: #e60012; } -.map-tile.practice, -.map-symbol.practice { --map-accent: #16a052; } -.map-tile.learn, -.map-symbol.learn { --map-accent: #f28b00; } -.map-tile.report, -.map-symbol.report { --map-accent: #526075; } +.tools-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 10px; +} -.map-symbol { +.tool-cell { display: flex; - width: 44px; - height: 44px; - flex: none; + flex-direction: column; + align-items: flex-start; + gap: 8px; + margin: 0; + padding: 12px; + border: 0; + border-radius: 16px; + background: #fafafa; + box-shadow: none; + text-align: left; + line-height: 1.3; +} + +.tool-cell::after { + border: 0; +} + +.tool-icon { + display: flex; + width: 40px; + height: 40px; align-items: center; justify-content: center; - border-radius: 50%; - background: var(--map-accent); - color: #ffffff; - font-size: 24px; + border-radius: 12px; + background: var(--employee-primary-soft); + color: var(--employee-primary); + font-size: 18px; font-weight: 900; } -.map-symbol.ask { - background: var(--map-accent); - box-shadow: none; -} - -.map-symbol.practice { - background: var(--map-accent); - box-shadow: none; -} - -.map-symbol.learn { - background: var(--map-accent); - box-shadow: none; -} - -.map-symbol.report { - background: var(--map-accent); - box-shadow: none; -} - -.map-copy { +.tool-copy { display: flex; min-width: 0; - flex: 1; flex-direction: column; gap: 2px; } -.map-title { - color: #25282d; - font-size: 16px; +.tool-name { + color: #1a1a1a; + font-size: 15px; font-weight: 800; line-height: 1.2; } -.map-desc { - color: #8a8d93; - font-size: 12px; - line-height: 1.35; - white-space: pre-line; -} - -.map-arrow { - color: #9da1a8; - font-size: 18px; - flex: none; +.tool-sub { + color: #9a9da3; + font-size: 11px; + line-height: 1.3; } .tip-card { @@ -1128,32 +1050,24 @@ onUnload(() => { font-size: 28px; } - .mentor-stage { - width: 140px; - height: 150px; + .hero-stage { + width: 150px; + height: 190px; } .mentor-image { - width: 128px; - height: 150px; + width: 104px; + height: 174px; } .mentor-bubble { - right: 92px; - width: 96px; + right: 88px; + max-width: 120px; padding: 8px 10px; } .voice-title { - font-size: 16px; - } - - .secondary-title { - font-size: 14px; - } - - .voice-desc { - font-size: 12px; + font-size: 18px; } .chip-text { @@ -1169,8 +1083,8 @@ onUnload(() => { } } -:global(html[data-aihr-font-size='extra-large'] .mentor-hero) { - min-height: 270px; +:global(html[data-aihr-font-size='extra-large'] .hero-immersive) { + min-height: 300px; } :global(html[data-aihr-font-size='extra-large'] .hero-copy) { @@ -1179,17 +1093,9 @@ onUnload(() => { padding-right: 18px; } -:global(html[data-aihr-font-size='extra-large'] .hero-tip) { - max-width: 160px; - white-space: normal; -} - -:global(html[data-aihr-font-size='extra-large'] .mentor-stage) { - position: absolute; - right: 0; - bottom: 0; - width: 154px; - height: 154px; +:global(html[data-aihr-font-size='extra-large'] .hero-stage) { + width: 150px; + height: 170px; } :global(html[data-aihr-font-size='extra-large'] .mentor-bubble) { @@ -1198,38 +1104,12 @@ onUnload(() => { :global(html[data-aihr-font-size='extra-large'] .mentor-image) { right: 0; - bottom: 0; - width: 144px; - height: 154px; -} - -:global(html[data-aihr-font-size='extra-large'] .voice-panel) { - flex-direction: column; - align-items: stretch; - gap: 0; -} - -:global(html[data-aihr-font-size='extra-large'] .voice-primary), -:global(html[data-aihr-font-size='extra-large'] .voice-secondary) { - width: 100%; - flex: none; -} - -:global(html[data-aihr-font-size='extra-large'] .voice-secondary) { - padding-top: 10px; - border-top: 1px solid #f0f1f3; -} - -:global(html[data-aihr-font-size='extra-large'] .secondary-copy) { - max-width: none; -} - -:global(html[data-aihr-font-size='extra-large'] .secondary-copy .voice-desc) { - width: auto; + width: 104px; + height: 170px; } :global(html[data-aihr-font-size='extra-large'] .chip-row), -:global(html[data-aihr-font-size='extra-large'] .map-grid) { +:global(html[data-aihr-font-size='extra-large'] .tools-grid) { grid-template-columns: 1fr; } @@ -1255,7 +1135,7 @@ onUnload(() => { } :global(html[data-aihr-font-size='extra-large'] .schedule-copy) { - flex-basis: calc(100% - 64px); + flex-basis: calc(100% - 46px); } :global(html[data-aihr-font-size='extra-large'] .tip-card) { diff --git a/mobile-uni/src/services/speech.ts b/mobile-uni/src/services/speech.ts index acce534e..7f7b5ad7 100644 --- a/mobile-uni/src/services/speech.ts +++ b/mobile-uni/src/services/speech.ts @@ -151,7 +151,7 @@ export const createSpeechPlaybackController = ( const utterance = new window.SpeechSynthesisUtterance(value.slice(0, 600)); utterance.lang = 'zh-CN'; utterance.rate = profile?.speed || 0.95; - utterance.pitch = profile?.role === 'mentor' ? 0.85 : profile?.role === 'customer' ? 1.05 : 1; + utterance.pitch = profile?.role === 'mentor' ? 1.06 : profile?.role === 'customer' ? 1.05 : 1; utterance.onend = () => { if (currentGeneration === generation && activeKey === key) stop(); }; diff --git a/mobile-uni/src/static/community-hero-bg.webp b/mobile-uni/src/static/community-hero-bg.webp new file mode 100644 index 00000000..cc80621b Binary files /dev/null and b/mobile-uni/src/static/community-hero-bg.webp differ diff --git a/mobile-uni/src/static/mentor-female-avatar.png b/mobile-uni/src/static/mentor-female-avatar.png new file mode 100644 index 00000000..fdf76267 Binary files /dev/null and b/mobile-uni/src/static/mentor-female-avatar.png differ diff --git a/mobile-uni/src/static/mentor-female-bust.png b/mobile-uni/src/static/mentor-female-bust.png new file mode 100644 index 00000000..fc9c9875 Binary files /dev/null and b/mobile-uni/src/static/mentor-female-bust.png differ diff --git a/mobile-uni/src/static/mentor-female.png b/mobile-uni/src/static/mentor-female.png new file mode 100644 index 00000000..a110ed19 Binary files /dev/null and b/mobile-uni/src/static/mentor-female.png differ