2026-09-23.md 4.5 KB

2026-09-23

登录页「记住密码」多账号下拉选择(已完成)

  • 需求:登录页勾选记住密码后,把企业名+账号+密码存本地;之后企业名/账号均可下拉选择(同时支持手输新值)
  • 实现:
    • src/hooks/web/useCache.ts:新增 CACHE_KEY.SavedAccounts = 'savedAccounts'
    • src/utils/auth.ts:新增 SavedAccountType + getSavedAccounts / addSavedAccount / removeSavedAccount,密码复用 encrypt/decrypt(RSA)加密存 localStorage(web-storage-cache,有效期 365 天,上限 20 条,同 tenantName+username 去重覆盖并置顶)
    • src/views/Login/components/LoginForm.vue:
    • 企业名、账号两个 el-input 改为 el-select(filterable + allow-create + default-first-option,仍可手输新值)
    • 账号下拉项显示 账号(企业名),右侧删除图标可单条移除
    • 选企业名 → 自动带出该企业下最近记住的账号+密码;选账号 → 自动带出企业名+密码(优先匹配当前企业名)
    • 登录成功:勾选记住 → addSavedAccount;未勾选 → 从列表移除该账号
    • src/locales/zh-CN.ts / en.ts:新增 login.rememberPassword(记住密码)
  • 已跑 vue-tsc --noEmit,改动文件无类型报错

⚠️ 补做:真正生效的登录页是 src/views/Login/Login.vue(不是 components/LoginForm.vue)

  • 事由:在 components/LoginForm.vue 改完后用户截图反馈「没看到新功能」
  • 根因:本项目真实登录路由渲染的是 views/Login/Login.vue 的自定义手写表单(原生 <input> + .inputM/.inputS 样式 + 「使用谷歌浏览器」页脚); components/LoginForm.vue / MobileForm / QrCodeForm / RegisterForm 在 Login.vue 里全是注释掉的(<LoginForm ... /> 注释),改了不生效
  • 排查手法:用户截图里的特征文案(账号登录 / 使用谷歌浏览器 / 欢迎来到颐年)→ 在项目里 Grep,直接定位真正的组件
  • 教训:改登录页前先确认实际挂载的组件;本项目多个 Login 入口并存,别默认 LoginForm.vue
  • Login.vue 侧实现:企业名/账号输入框 @focus/@input 弹自绘 .account-dropdown 面板(失焦 150ms 延时关闭,选项用 @mousedown.prevent 以免 blur 早于 click); 密码框下新增「记住密码」el-checkbox(登录按钮 marginTop 由 40px 收为 12px,卡片 500px 高度不变);登录成功分支同样 addSavedAccount / removeSavedAccount
  • 共用同一套 src/utils/auth.ts 的 SavedAccounts 存储(跨两个登录页互通)

🐛 上述功能上线后两个 BUG 的修复(务必记住这两个坑)

  1. 密码被清空 / 回填后是乱码
    • 根因:src/utils/auth.ts 的 setLoginForm() 原地改写传入对象(loginForm.password = encrypt(...))。 handleLogin 里先 setLoginForm(loginData.loginForm) 再 addSavedAccount(...) → 存进去的是「密文再加密」→ 读时解不开 → 密码空
    • 修法:① setLoginForm 改为 { ...loginForm, password: encrypt(...) } 不再改原对象; ② SavedAccounts 的增删改统一基于原始密文列表 getSavedAccountsRaw(),禁止「先全解密再全加密」(会把解密失败的条目永久写成空); ③ 解密结果仍像密文(≥40 位 base64)时再解一层,自动修复历史二次加密数据
  2. 自绘下拉面板自动关闭
    • 根因:面板 position:absolute 在 overflow:auto 滚动容器内会撑出滚动条→重排→input 失焦→blur 关闭;且原本用 blur+150ms 延时关闭太脆
    • 修法:面板 Teleport to="body" + position:fixed + 输入框 getBoundingClientRect() 定位; 关闭只判 document.mousedown 是否落在面板/输入框外,完全不依赖 focus/blur;scroll/resize 只重新定位
  3. 选中空的记住密码不再覆盖用户已输入的内容(if (matched.password) 守卫)
  4. vue-tsc --noEmit 已过

交互约定

  • 回填策略:选企业名 → 带出该企业最近记住的账号+密码;选账号 → 带出企业名+密码;两者都加非空守卫

后续微调(同日)

  • 登录下拉改为打开即展示全部记住的企业名/账号,不再按输入内容过滤(用户明确要求)
  • 临时医嘱单打印页 short-doctor-order/Print.vue:字体全部改黑色(标题/字段标签/表头),红色仅保留线条(标题双红线、表格边框); 长期医嘱单 Print.vue 本就是黑色;execute-doctor-order 无红色字体