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 @@
-
-
-
-
- 银城物业
- |
- 数字师傅
-
+
+
+
+ 银城物业
+ ·
+ 数字师傅
+
+
+
+
+
+
+ 手机号登录,一分钟上手
- 银城员工端
- 高效协同 · 贴心服务 · 让工作更简单
@@ -77,6 +80,8 @@
show-icon
/>
+
+ 登录即同意《服务协议》与《隐私政策》
@@ -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 }}
-
-
-
+ 2
{{ home?.review?.title }}
-
- 今日
- ·
- 线上复习
-
{{ home?.review?.desc }}
@@ -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