# medication-record **Repository Path**: MengXY/medication-record ## Basic Information - **Project Name**: medication-record - **Description**: 纯前端本地用药记录工具 - **Primary Language**: HTML/CSS - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2015-05-07 - **Last Updated**: 2026-05-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

Medication Record

用药记录 (Medication Record)

Pad 横屏用药记录工具 · 本地存储 · 无需登录 · 开箱即用

MIT License Vue 3.5 Vant 4 TypeScript IndexedDB

## 介绍 一款面向家庭的 Pad 横屏用药记录工具。数据完全存储在浏览器本地,无法多设备同步访问,开箱即用。 **核心场景**:将 Pad 放在家中固定位置(如客厅、餐桌),家人经过时即可随手记录用药情况。适合家里有老人、慢性病患者需要长期服药,多个家庭成员需分别记录各自的用药。 - 每天吃了没、吃了多少次、什么时间吃的,一目了然。 - 退出浏览器或关闭 Pad,数据不会丢失。 - 更换设备需通过浏览器导出/导入 IndexedDB 数据。 ## 功能特性 - **👨‍👩‍👧‍👦 多用户支持** — 家庭每个成员可创建独立的用药人,互不干扰,顶部栏可快速切换 - **💊 药品管理** — 添加、编辑、软删除药品卡片,支持丰富的服用周期配置 - **📅 日历视图** — 在日历上查看每天各药品的服用状态(黄点待服、绿点已服) - **✅ 记录勾选** — 点击当天用药记录的勾选框标记已服用,记录精确到分钟的实际服药时间 - **📊 历史追溯** — 已勾选的服药记录永久保存,切换日期可查看历史用药情况 - **🔄 软删除机制** — 删除药品后,历史服药记录依然保留可查 - **🎨 颜色标识** — 每种药品可设置独立颜色,在日历和卡片中快速区分 - **📟 Pad 横屏适配** — 布局针对 Pad 横屏优化,药品卡片横向滚动 + 大尺寸日历一览无余 - **🔒 纯本地存储** — 数据仅保存在当前浏览器 IndexedDB 中,不经过任何服务器,无法多设备同步访问 ## 服用周期类型 | 周期 | 每日次数 | 说明 | |------|---------|------| | 每天1次 | 1 | 每日服用一次 | | 每天2次 | 2 | 早晚各一次 | | 每天3次 | 3 | 早中晚各一次 | | 每2天1次 | 1 | 间隔一天服用 | | 每3天1次 | 1 | 间隔两天服用 | | 每周1次 | 1 | 每周固定一天 | | 每月1次 | 1 | 每月固定日期 | ## 技术栈 | 类别 | 技术 | 用途 | |------|------|------| | 框架 | [Vue 3](https://vuejs.org/) + [Composition API](https://vuejs.org/guide/composition-api-setup) | 响应式 UI | | 语言 | [TypeScript](https://www.typescriptlang.org/) | 类型安全 | | 构建 | [Vite](https://vitejs.dev/) | 极速开发构建 | | 路由 | [Vue Router](https://router.vuejs.org/) | 页面导航 | | 状态管理 | [Pinia](https://pinia.vuejs.org/) | 全局状态 | | UI 组件 | [Vant 4](https://vant-ui.github.io/) | 移动端组件库 | | 数据持久化 | [IndexedDB](https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API) (idb) | 浏览器本地存储 | | 部署 | Nginx + SSH2 | 生产环境部署 | ## 项目结构 ``` medication-record/ ├── src/ │ ├── components/ # 组件 │ │ ├── HomeHeader.vue # 顶部导航栏(用户切换 + 添加用户) │ │ ├── MedicationCard.vue # 药品卡片(横向滚动) │ │ ├── CalendarDay.vue # 日历日期格子 │ │ ├── AddMedicationModal.vue # 添加/编辑药品弹窗 │ │ ├── EditMedicationModal.vue# 编辑药品弹窗(含删除) │ │ ├── MedicationRecordModal.vue # 用药记录弹窗(勾选服药) │ │ └── MedicationCalendar.vue # 完整日历页(补录功能) │ ├── views/ # 页面 │ │ ├── HomeView.vue # 首页(药品卡片 + 日历) │ │ ├── CreateUserView.vue # 首次创建用药人 │ │ └── UserManagementView.vue # 用药人管理 │ ├── stores/ │ │ └── app.ts # Pinia 全局状态 │ ├── utils/ │ │ └── db.ts # IndexedDB 数据模型与工具函数 │ ├── router/ │ │ └── index.ts # 路由配置 │ ├── App.vue # 根组件 │ └── main.ts # 入口文件 ├── deploy.cjs # 一键部署脚本 ├── deploy.config.example.cjs # 部署配置文件示例(复制为 deploy.config.cjs 使用) ├── package.json └── vite.config.ts ``` ## 数据模型 所有数据存储在浏览器 **IndexedDB** 中,数据库名 `medication-record-db`,包含三个对象仓库: ### Users(用药人) | 字段 | 类型 | 说明 | |------|------|------| | id | string | 主键 | | name | string | 用药人姓名 | | createdAt | number | 创建时间戳 | ### Medications(药品) | 字段 | 类型 | 说明 | |------|------|------| | id | string | 主键 | | userId | string | 所属用药人 ID | | name | string | 药品名称 | | startTime | number | 开始服用日期 | | cycleType | enum | 服用周期类型 | | color | string | 标识颜色 | | deleted? | true | 软删除标记 | | createdAt | number | 创建时间戳 | ### Records(服药记录) | 字段 | 类型 | 说明 | |------|------|------| | id | string | 主键 | | medicationId | string | 药品 ID | | date | number | 服药日期(当天 00:00 时间戳) | | times | number[] | 已服用的次数索引,如 [0, 1] | | actualTimes | Record | timeIndex → 实际服用时间戳映射 | | createdAt | number | 创建时间戳 | ## 核心实现思路 ### 服药周期计算 通过 `shouldTakeMedication()` 函数计算某药品在某天是否需要服用。核心算法是计算目标日期与开始日期之间的天数差,再根据周期类型取模判断: ```typescript const diffDays = Math.floor((targetDate - startDate) / (1000 * 60 * 60 * 24)); switch (medication.cycleType) { case 'daily_1': // 每天 → 总是返回 true case 'every_2_days': // 每2天 → diffDays % 2 === 0 case 'every_3_days': // 每3天 → diffDays % 3 === 0 case 'weekly': // 每周 → diffDays % 7 === 0 case 'monthly': // 每月 → targetDate.getDate() === startDate.getDate() } ``` ### 服药记录勾选 在 `toggleRecord()` 中,勾选/取消勾选的核心逻辑: 1. 查找该药品当天的已有记录 2. **勾选**:将 timeIndex 加入 times 数组,并记录当前时间戳到 actualTimes 3. **取消**:从 times 数组移除 timeIndex,删除对应 actualTimes;若 times 为空则删除整条记录 ### 软删除 删除药品时并非真实从数据库移除,而是将 `deleted` 标记为 `true`: - 首页药品滚动列表**过滤掉** deleted 的药品 - 日历**仅显示**已有实际服药记录的已删除药品日期 - 新增同名药品时,若存在软删除记录则**合并更新**,恢复所有历史服药数据 ## 快速开始 ### 环境要求 - Node.js >= 20.19.0 或 >= 22.12.0 ### 安装与运行 ```bash # 克隆项目 git clone cd medication-record # 安装依赖 npm install # 本地开发(热更新) npm run dev # 生产构建 npm run build # 预览构建产物 npm run preview ``` ### 使用流程 ``` 1. 首次访问 → 输入姓名创建用药人 2. 首页点击 "+" 添加药品 → 填写药品名称、开始日期、服用周期、颜色 3. 在日历上点击某天的日期 → 弹出当天用药记录弹窗 4. 点击勾选框 → 标记该次药已服用,记录实际服药时间 5. 如需再次取消勾选 → 再次点击即可取消 6. 顶部栏可切换不同用药人 7. 点击导航栏 "+" 按钮添加新用药人 ``` ## 部署 ### 一键部署脚本 ```bash # 安装部署依赖 npm install ssh2-sftp-client # 方式一:使用配置文件(推荐) # 复制示例配置文件,填入实际服务器信息 cp deploy.config.example.cjs deploy.config.cjs # 编辑 deploy.config.cjs,填入服务器地址、用户名、密码 # 然后直接运行: node deploy.cjs # 方式二:交互式输入 node deploy.cjs ``` > 配置优先级:`deploy.config.cjs` > 环境变量 (`DEPLOY_HOST` / `DEPLOY_USER` / `DEPLOY_PASS`) > 交互式输入 > > `deploy.config.cjs` 已在 `.gitignore` 中,不会被提交到 Git,避免凭证泄露 ### 手动部署 ```bash # 构建 npm run build # 将 dist/ 目录上传到服务器 /www/web/medication-record/ ``` ### 在线地址 [https://medication.esugar.cn](https://medication.esugar.cn) ## 数据安全与存储 - **纯本地存储** — 所有数据存储在浏览器本地 IndexedDB,不上传任何服务器 - **单设备使用** — 数据与浏览器绑定,无法多设备同步访问(设计初衷即为固定设备使用) - **数据持久性** — 关闭浏览器或重启 Pad,数据不丢失 - **浏览器数据清除** — 若清除浏览器数据(Cookie / 缓存 / IndexedDB),数据将被删除,请提前做好备份 - **更换设备** — 旧数据在新设备上不可见,需自行通过浏览器开发者工具导出 IndexedDB 数据 ## License [MIT](LICENSE) Copyright (c) 2026