Vue病历写回功能:实现多输入框内容插入与焦点管理🚀

本文将介绍如何实现一个高效、用户友好的病历写回功能,支持多输入框内容插入与焦点管理。该解决方案已在医疗系统中广泛应用,可大幅提升医生书写病历的效率。

实现效果如下

痛点分析与解决方案

医疗系统常见痛点

  • 🚫 焦点迷失:在多个输入区域(主诉、现病史、体格检查等)间切换时容易失去位置
  • 🔁 重复输入:常见症状描述和诊断结论需要反复输入
  • 效率低下:医疗工作者需要花费大量的时间去完成病例写回工作

我们的创新解决方案

  • 智能焦点追踪:自动记录当前和最后激活的输入框
  • 模板快速插入:一键插入预设模板内容
  • 🎯 光标精确定位:确保插入内容后光标位置正确
  • 💡 可视化状态:实时显示当前激活区域

核心实现代码解析

一、关键变量解析 🧠

js 复制代码
const activeInput: Ref<InputElement | null> = ref(null)       // 当前获得焦点的输入框
const lastActiveInput: Ref<InputElement | null> = ref(null)   // 最后获得焦点的输入框(用于恢复)
const registerEls: Ref<InputElement[]> = ref([])              // 所有注册的输入框实例

二. 核心方法解析 ✨

1. registerInput(el: InputElement)

  • 功能:注册输入框并绑定事件监听

  • 绑定事件

    • mousedown/focus → 触发 handleFocus 记录活跃输入框
    • blur → 触发 handleBlur 清除当前焦点
  • 存储 :将元素添加到注册列表 registerEls

2. insertContent(content: string)

  • 插入逻辑

    1. 优先使用 activeInput,若不存在则使用 lastActiveInput
    2. 若无有效输入框 → 显示警告提示
    3. 尝试获取焦点 → 计算光标位置
    4. 在光标处插入内容 → 更新光标位置
    5. 触发 input 事件通知Vue更新数据
  • 关键技术点

    js 复制代码
    // 在光标位置插入内容
    target.value = 
      target.value.slice(0, start) + 
      content + 
      target.value.slice(end)
    
    // 设置新光标位置
    target.setSelectionRange(newPos, newPos)
    
    // 触发数据绑定更新
    target.dispatchEvent(new Event('input', { bubbles: true }))

3. cleanup()

  • 资源清理

    • 移除所有注册元素的事件监听
    • 重置所有响应式变量
  • 使用场景:组件卸载时调用防止内存泄漏

4. 事件处理函数

js 复制代码
function handleFocus(e: Event) {
  const target = e.target as InputElement
  activeInput.value = target       // 更新当前焦点
  lastActiveInput.value = target   // 更新最后焦点备份
}

function handleBlur() {
  activeInput.value = null         // 清除当前焦点
}

三、工作流程 🔧

四、设计特点 🌟

  1. 双重焦点备份activeInput + lastActiveInput 确保即使输入框失焦也能定位
  2. 自动数据同步 :通过派发 input 事件触发Vue数据绑定更新
  3. 安全恢复机制 :插入前尝试 target.focus() 恢复焦点
  4. 内存管理:提供显式清理接口避免内存泄漏

五、使用场景示例

js 复制代码
<script setup lang="ts">
import { cleanup, insertContent, registerInput } from '../hooks/useWriteBackHistory'

const dialogVisible = ref(false)

function onCancel() {
  dialogVisible.value = false
  cleanup()
}

const content = ref('你很好,你很优秀,你是最棒的!')
function onload() {
  insertContent(content.value)
}
const formInline = reactive({
  user: '',
  region: '',
})
/**
 * @description 写回病历-注册
 * @param el
 */
function setInputRef(el: any) {
  if (el && el.$el) {
    registerInput(el.$el)
  }
}
</script>

<template>
  <el-dialog
    v-model="dialogVisible"
    title="Tips"
    width="800"
  >
    <el-form :inline="true" :model="formInline" class="demo-form-inline">
      <el-form-item label="主诉">
        <el-input :ref="setInputRef" v-model="formInline.user" placeholder="主诉" clearable type="textarea" />
      </el-form-item>

      <el-form-item label="诊断">
        <el-input :ref="setInputRef" v-model="formInline.user" placeholder="诊断" clearable type="textarea" />
      </el-form-item>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="onCancel">
          取消
        </el-button>
        <el-button type="primary" @click="onload">
          写回病例
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<style scoped lang="scss">

</style>

六、潜在问题及改进

  1. 移动端兼容性mousedown 事件在移动端可能需要替换为 touchstart
  2. 多实例冲突:全局变量在多个组件实例中使用时可能相互干扰
  3. 性能优化:大量输入框注册时考虑弱引用(WeakRef)管理
  4. 富文本支持:当前仅支持原生输入框,如需富文本编辑器需扩展

技术创造价值,代码改善生活 - 通过前端技术创新,我们可以为医疗行业带来真正的变革

欢迎在评论区交流你的想法和实践经验!

相关推荐
future14121 分钟前
项目开发日记
前端·学习·c#·游戏开发
汪子熙10 分钟前
CSS 中 td:last-child a 选择器详解
前端·javascript
北北~Simple24 分钟前
第一次搭建数据库
服务器·前端·javascript·数据库
GanGuaGua31 分钟前
Vue3常用指令
前端·javascript·vue.js
欧阳天风31 分钟前
录音实时上传
前端·javascript
江号软件分享35 分钟前
从DNS到防火墙:NetDisabler多策略断网方法详解
前端
灵犀学长44 分钟前
解锁HTML5页面生命周期API:前端开发的新视角
前端·html·html5
江号软件分享1 小时前
轻松解决Office版本冲突问题:卸载是关键
前端
致博软件F2BPM1 小时前
Element Plus和Ant Design Vue深度对比分析与选型指南
前端·javascript·vue.js
慧一居士2 小时前
flex 布局完整功能介绍和示例演示
前端