feat(fe): AI 独立成页(打字机)+ 修快速记录 6 处问题 + 导航栏去接缝

AI 从底部弹层改成独立页面 pages/ai/ai:
- 整屏聊天,输入框固定在底部,不再是「问题都打不完」的小格子
- 回复逐字吐出(30ms/2 字),点一下可跳过
- 会话 session 从 sheet 改为 chat,历史拉 50 条
- 组件里对应的 ai 分支和 aiMessages/aiInput/sendAI 一并删掉,
  避免两套实现并存

快速记录九个入口逐个排查,修掉 6 处:
1. 疫苗/驱虫的默认日期写死成 2026-07-21 / 2026-07-15,早已是过去的
   日期 —— 改成打开时按今天 +30 / +90 天算
2. 异常观察没选症状时,optIdx 返回 0 会被当成选了「呕吐」,等于替
   用户瞎填 —— 加 optPicked 判断,没选就提示
3. 体重为空时会静默存成「上次的体重」,凭空造一条假数据 —— 改为必填校验
4. 消费金额为空会存成 ¥0 —— 必填校验
5. 用药药品名为空 —— 必填校验
6. 照片弹层里「模拟上传预览」是没删掉的假文案

顺带清理:保存按钮上的 data-text / data-icon 从来没被读过(onSave 只用
buildRecord 的返回值),是纯误导的死属性,删掉。我上一条 commit 把它们
说成「写库值」是说错了 —— 真正写库的是 buildRecord 里的 icon 字段,那部分
仍然没动。

导航栏原来是一整条半透明色块,底边和页面渐变硬碰硬,屏幕上横着一道接缝。
改成上实下虚的渐变,并用同一条 mask 把毛玻璃一起淡出(只淡背景不淡 blur
的话,接缝会从色差变成糊边)。返回键做成圆形,和右上角胶囊视觉对称。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-07-29 11:10:41 +08:00
parent cab8b9ee28
commit 35fc57e8de
16 changed files with 281 additions and 97 deletions
+43
View File
@@ -0,0 +1,43 @@
/* 整页聊天:上面滚动区自适应,下面输入区固定,中间不留空 */
.chat-scroll{flex:1;min-height:0}
.chat-body{padding:var(--sp-3) var(--pad-x) var(--sp-5)}
.chat-bottom{height:1rpx}
.row{display:flex;align-items:flex-start;gap:var(--sp-2);margin-bottom:var(--sp-4)}
.row-user{justify-content:flex-end}
.ai-avatar{
width:60rpx;height:60rpx;border-radius:var(--r-sm);flex:none;margin-top:4rpx;
display:flex;align-items:center;justify-content:center;
background:var(--cta);color:#fff;
}
.bubble{
max-width:76%;border-radius:var(--r-md);padding:var(--sp-3) var(--sp-4);
font-size:var(--fs-md);line-height:1.62;word-break:break-word;
}
.bubble-ai{background:#fff;box-shadow:var(--sd-1);border-top-left-radius:var(--r-xs)}
.bubble-user{background:var(--primary-soft);color:var(--primary-ink);border-top-right-radius:var(--r-xs)}
/* 打字光标 */
.caret{color:var(--primary);animation:blink .9s steps(1) infinite}
@keyframes blink{50%{opacity:0}}
/* 底部输入区 */
.dock{
flex:none;background:rgba(255,255,255,.94);
backdrop-filter:blur(28rpx);-webkit-backdrop-filter:blur(28rpx);
border-top:1rpx solid var(--line);
padding:var(--sp-3) var(--pad-x) calc(var(--sp-3) + env(safe-area-inset-bottom));
}
.presets{white-space:nowrap;margin-bottom:var(--sp-3)}
.preset{
display:inline-block;height:var(--h-sm);line-height:var(--h-sm);padding:0 var(--sp-4);
margin-right:var(--sp-2);border-radius:var(--r-full);border:1rpx solid var(--line);
background:#fff;color:var(--text-2);font-size:var(--fs-sm);
}
.input-row{display:flex;align-items:center;gap:var(--sp-3)}
.input-row .input{flex:1;background:var(--surface-2)}
.send{
width:88rpx;height:88rpx;border-radius:var(--r-md);flex:none;
display:flex;align-items:center;justify-content:center;
background:var(--line);color:#fff;transition:.16s ease;
}
.send.on{background:var(--cta)}