diff --git a/docs/HANDOVER_FEATURE.md b/docs/HANDOVER_FEATURE.md new file mode 100644 index 0000000..154ba0b --- /dev/null +++ b/docs/HANDOVER_FEATURE.md @@ -0,0 +1,427 @@ +# 护工端交接班流程功能文档 + +## 📋 功能概述 + +护工端交接班流程是一个完整的工作交接解决方案,帮助护工在下班时系统地记录工作内容、传递重要信息给下一班护工,确保老人护理工作的连续性和质量。 + +## 🎨 设计特点 + +- **高保真原型设计**:完全按照产品设计文档实现,包含详细的视觉规范 +- **微交互动画**:丰富的动画效果提升用户体验 +- **响应式适配**:支持不同尺寸屏幕,包括横屏模式 +- **无障碍设计**:遵循无障碍设计规范,支持语音操作 + +## 🗂️ 项目结构 + +``` +src/ +├── pages/ +│ └── handover/ # 交接班功能目录 +│ ├── index.vue # 入口页面(下班提醒) +│ ├── previous-notes.vue # 查看上一班留言 +│ ├── work-summary.vue # 填写本班工作总结 +│ ├── next-shift-notes.vue # 填写下一班注意事项 +│ ├── waiting-confirm.vue # 等待接班人确认 +│ ├── complete.vue # 交接完成 +│ └── components/ # 共享组件 +│ ├── progress-indicator.vue # 进度指示器 +│ ├── elder-card.vue # 老人信息卡片 +│ ├── shift-end-reminder.vue # 下班提醒弹窗 +│ └── remind-colleague-modal.vue # 催促接班人弹窗 +│ +├── store/ +│ └── modules/ +│ └── handover.js # 交接班状态管理 +│ +├── api/ +│ └── modules/ +│ └── handover.js # 交接班 API 接口 +│ +└── styles/ + ├── handover-design.scss # 设计系统变量 + └── handover-animations.scss # 动画效果样式 +``` + +## 🎯 功能流程 + +### 1. 下班提醒(第1屏) + +**触发时机**:当前时间接近班次结束时间前15分钟 + +**功能**: +- 自动弹出提醒弹窗 +- 显示下班时间 +- 提供"开始交接班"和"稍后再说"选项 +- 稍后再说后15分钟再次提醒 + +**组件**:`shift-end-reminder.vue` + +### 2. 查看上一班留言(第2屏) + +**路由**:`/handover/previous-notes` + +**功能**: +- 显示上一班护工的基本信息 +- 展示重点关注老人列表(按紧急程度分类) + - 🔴 危险红:紧急/异常情况 + - 🟡 警告橙:需要关注的情况 + - 🔵 蓝色:一般提醒 +- 显示待完成任务列表 +- 支持点击卡片查看详细信息 + +**数据结构**: +```javascript +{ + caregiver: '李小花', + timeRange: '06:00-14:00', + focusElders: [ + { + id: 1, + room: '101房', + name: '张淑华奶奶', + level: 'danger', // 'danger' | 'warning' | 'normal' + issue: '血压异常', + description: '详细描述...', + reminder: '提醒事项...' + } + ], + todos: [ + { + id: 1, + content: '101房 17:00 测量血压', + note: '未完成,请接手处理' + } + ] +} +``` + +### 3. 填写本班工作总结(第3屏) + +**路由**:`/handover/work-summary` + +**功能**: +- 展示本班工作统计数据 + - 总任务数、护理任务、用餐任务、监测任务 + - 任务完成率 +- 填写重点工作记录 + - 支持文本输入 + - 支持语音输入(长按语音按钮) + - 字数限制:500字 +- 快捷标签功能 + - 预设标签:血压正常、食欲改善、情绪稳定等 + - 支持自定义标签 + - 点击标签自动插入到文本框 +- 照片记录 + - 最多上传9张照片 + - 支持拍照和从相册选择 + - 可删除已上传的照片 + +**验证**: +- 必须填写工作记录(至少1个字符)才能进入下一步 + +### 4. 填写下一班注意事项(第4屏) + +**路由**:`/handover/next-shift-notes` + +**功能**: +- 选择需要特别关注的老人 + - 勾选老人后展开详细信息 + - 可添加提醒事项 + - 支持添加其他老人 +- 填写补充说明 + - 支持文本和语音输入 + - 字数限制:500字 +- 显示接班人信息 + - 姓名、班次、时间、电话 + - 在线状态显示 +- 提交交接班记录 + +**验证**: +- 必须至少勾选一位需要关注的老人 +- 接班人必须在线才能提交 + +### 5. 等待接班人确认(第5屏) + +**路由**:`/handover/waiting-confirm` + +**功能**: +- 显示等待状态 + - 沙漏旋转动画 + - 进度转圈动画 +- 显示接班人信息和在线状态 +- 展示已发送的通知 + - 微信通知 + - 短信提醒 + - APP推送 +- 显示预计等待时间 +- 提供催促功能 + - 点击"催一下"按钮 + - 30秒内不可重复催促 + - 超过5分钟未确认显示"联系管理员" + +**自动流程**: +- 3秒后(演示用)自动跳转到完成页面 +- 实际应该等待接班人确认后跳转 + +### 6. 交接完成(第6屏) + +**路由**:`/handover/complete` + +**功能**: +- 显示完成状态(✅ 动画) +- 展示今日工作统计 + - 工作时长 + - 完成任务数和完成率 + - 服务评价 + - 今日亮点 +- 展示今日收益预览 + - 基础工时费 + - 绩效奖金 + - 服务提成 + - 预计总收入 + - 发放日期提示 +- 操作按钮 + - 查看详细报告 + - 确定下班(打卡) + - 分享今日工作 + +### 7. 催促接班人弹窗(第7屏) + +**组件**:`remind-colleague-modal.vue` + +**触发时机**: +- 在等待确认页面点击"催一下" +- 等待超过3分钟自动弹出 + +**功能**: +- 提供多种催促方式 + - 📱 发送微信消息 + - 📞 直接拨打电话 + - 👔 联系管理员 +- 再等等选项 + +## 🎨 设计系统 + +### 颜色系统 + +```scss +// 主色调 +$handover-primary: #3B82F6; // 主蓝色 +$handover-primary-dark: #2563EB; // 深蓝色 +$handover-primary-deep: #1E40AF; // 更深蓝色 + +// 辅助色 +$handover-success: #10B981; // 成功绿 +$handover-warning: #F59E0B; // 警告橙 +$handover-danger: #EF4444; // 危险红 + +// 中性色 +$handover-gray-900 ~ $handover-gray-50 // 灰度阶梯 +``` + +### 字体系统 + +```scss +// 字号 +$handover-font-size-2xl: 24px; // 超大标题 +$handover-font-size-xl: 20px; // 大标题 +$handover-font-size-lg: 18px; // 页面标题 +$handover-font-size-md: 16px; // 章节标题 +$handover-font-size-base: 14px; // 正文 +$handover-font-size-sm: 13px; // 辅助信息 +$handover-font-size-xs: 12px; // 小字 + +// 字重 +$handover-font-weight-regular: 400; +$handover-font-weight-medium: 500; +$handover-font-weight-semibold: 600; +$handover-font-weight-bold: 700; +``` + +### 间距系统 + +```scss +$handover-spacing-2xs: 4px; +$handover-spacing-xs: 8px; +$handover-spacing-sm: 12px; +$handover-spacing-md: 16px; +$handover-spacing-lg: 20px; +$handover-spacing-xl: 24px; +$handover-spacing-2xl: 32px; +``` + +## 🔧 状态管理 + +### Pinia Store + +**位置**:`src/store/modules/handover.js` + +**State**: +```javascript +{ + currentShift: {}, // 当前班次信息 + previousNotes: {}, // 上一班留言 + workSummary: {}, // 本班工作总结 + nextShiftNotes: {}, // 下一班注意事项 + successor: {}, // 接班人信息 + handoverStatus: {}, // 交接班状态 + reminderSettings: {} // 提醒设置 +} +``` + +**Getters**: +- `canStartHandover`:是否可以开始交接班 +- `shouldShowReminder`:是否需要显示下班提醒 +- `focusElderCount`:重点关注老人数量 +- `todoCount`:待完成任务数量 +- `handoverProgress`:交接班进度百分比 + +**Actions**: +- `initHandover()`:初始化交接班数据 +- `loadPreviousNotes()`:加载上一班留言 +- `updateWorkSummary(data)`:更新工作总结 +- `updateNextShiftNotes(data)`:更新下一班注意事项 +- `submitHandover()`:提交交接班记录 +- `confirmHandover()`:接班人确认 +- `resetHandover()`:重置交接班状态 + +## 🌐 API 接口 + +**位置**:`src/api/modules/handover.js` + +### 接口列表 + +| 接口名称 | 方法 | 路径 | 说明 | +|---------|------|------|------| +| getCurrentShift | GET | /handover/current-shift | 获取当前班次信息 | +| getPreviousNotes | GET | /handover/previous-notes | 获取上一班留言 | +| getFocusElders | GET | /handover/focus-elders | 获取重点关注老人列表 | +| getTodoList | GET | /handover/todos | 获取待完成任务列表 | +| getWorkStatistics | GET | /handover/work-statistics | 获取本班工作统计 | +| saveWorkSummary | POST | /handover/work-summary | 保存工作总结 | +| uploadPhoto | POST | /handover/upload-photo | 上传照片 | +| getSuccessorInfo | GET | /handover/successor | 获取接班人信息 | +| saveNextShiftNotes | POST | /handover/next-shift-notes | 保存下一班注意事项 | +| submitHandover | POST | /handover/submit | 提交交接班记录 | +| checkSuccessorOnline | GET | /handover/check-online/:id | 检查接班人是否在线 | +| remindSuccessor | POST | /handover/remind-successor | 催促接班人确认 | +| getHandoverHistory | GET | /handover/history | 获取交接班历史记录 | +| getTodayReport | GET | /handover/today-report | 获取今日工作统计报告 | +| getTodayEarnings | GET | /handover/today-earnings | 获取今日收益预览 | +| confirmClockOut | POST | /handover/clock-out | 确认下班打卡 | + +## 🎭 动画效果 + +**位置**:`src/styles/handover-animations.scss` + +### 可用动画类 + +- **页面转场**:`.page-enter`, `.page-exit` +- **按钮反馈**:`.button-press` +- **加载状态**:`.loading-spin`, `.skeleton`, `.pulse` +- **淡入淡出**:`.fade-in`, `.fade-out`, `.fade-in-up`, `.fade-in-down` +- **缩放动画**:`.scale-in`, `.scale-pop` +- **抖动动画**:`.shake` +- **弹跳动画**:`.bounce` +- **滑动动画**:`.slide-in-left`, `.slide-in-right` +- **特殊动画**:`.bell-ring`, `.hourglass-rotate`, `.breathe` + +### 使用示例 + +```vue + + 内容 + +``` + +## 🚀 开发指南 + +### 1. 安装依赖 + +```bash +pnpm install +``` + +### 2. 运行开发服务器 + +```bash +# H5 +pnpm dev:h5 + +# 微信小程序 +pnpm dev:mp-weixin + +# App +pnpm dev:app +``` + +### 3. 访问交接班功能 + +在应用中导航到 `/handover` 路径,或者在首页添加入口按钮。 + +### 4. 模拟数据 + +目前使用的是模拟数据,可以在以下位置修改: + +- **Store**:`src/store/modules/handover.js` 中的 `loadPreviousNotes()` 方法 +- **页面组件**:各个页面的 `ref` 数据 + +### 5. 对接后端 API + +1. 修改 `src/api/request.js` 配置 API 基础URL +2. 实现 `src/api/modules/handover.js` 中的接口 +3. 在 Store 的 actions 中调用 API 接口 +4. 处理错误和加载状态 + +## 📱 响应式适配 + +### 屏幕尺寸 + +- **小屏手机** (≤375px):缩小间距和字号 +- **标准手机** (375-414px):标准尺寸 +- **大屏手机** (≥414px):适当增加间距 +- **平板** (≥768px):采用两栏布局 + +### 横屏适配 + +横屏时: +- 导航栏高度缩小至48px +- 内容区域采用左右分栏 +- 左侧:老人列表(40%) +- 右侧:详细信息(60%) + +## ♿ 无障碍设计 + +- **文字可读性**:最小字号12px,行高至少1.5倍 +- **色彩对比度**:正文对比度 ≥ 4.5:1 +- **触控区域**:按钮最小尺寸 44×44px +- **语音操作**:支持语音输入作为备选方案 + +## 🐛 已知问题 + +1. **语音输入功能**:目前是模拟实现,需要集成实际的语音识别服务 +2. **照片上传**:需要配置实际的文件上传服务器 +3. **推送通知**:需要集成推送服务(如极光推送、uni-push等) +4. **实时在线状态**:需要 WebSocket 或轮询实现 + +## 🔮 后续优化 + +1. **离线支持**:添加离线数据缓存 +2. **数据同步**:实现离线数据同步机制 +3. **更多语言**:支持多语言国际化 +4. **主题切换**:支持暗色模式 +5. **性能优化**:图片懒加载、虚拟列表等 +6. **测试覆盖**:添加单元测试和 E2E 测试 + +## 📄 许可证 + +MIT License + +## 👥 贡献者 + +- Claude (AI Assistant) +- [您的团队成员] + +## 📞 联系方式 + +如有问题或建议,请联系项目负责人。 diff --git a/src/api/modules/handover.js b/src/api/modules/handover.js new file mode 100644 index 0000000..8167e0c --- /dev/null +++ b/src/api/modules/handover.js @@ -0,0 +1,254 @@ +/** + * 交接班相关 API 接口 + */ +import request from '../request' + +/** + * 获取当前班次信息 + */ +export function getCurrentShift() { + return request({ + url: '/handover/current-shift', + method: 'GET' + }) +} + +/** + * 获取上一班留言 + */ +export function getPreviousNotes() { + return request({ + url: '/handover/previous-notes', + method: 'GET' + }) +} + +/** + * 获取重点关注老人列表 + */ +export function getFocusElders() { + return request({ + url: '/handover/focus-elders', + method: 'GET' + }) +} + +/** + * 获取待完成任务列表 + */ +export function getTodoList() { + return request({ + url: '/handover/todos', + method: 'GET' + }) +} + +/** + * 获取本班工作统计 + */ +export function getWorkStatistics() { + return request({ + url: '/handover/work-statistics', + method: 'GET' + }) +} + +/** + * 保存工作总结 + * @param {Object} data - 工作总结数据 + * @param {String} data.workRecord - 工作记录文本 + * @param {Array} data.selectedTags - 选中的标签 + * @param {Array} data.photos - 照片列表 + */ +export function saveWorkSummary(data) { + return request({ + url: '/handover/work-summary', + method: 'POST', + data + }) +} + +/** + * 上传照片 + * @param {File} file - 照片文件 + */ +export function uploadPhoto(file) { + const formData = new FormData() + formData.append('file', file) + + return request({ + url: '/handover/upload-photo', + method: 'POST', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** + * 获取接班人信息 + */ +export function getSuccessorInfo() { + return request({ + url: '/handover/successor', + method: 'GET' + }) +} + +/** + * 保存下一班注意事项 + * @param {Object} data - 注意事项数据 + * @param {Array} data.focusElders - 重点关注老人列表 + * @param {String} data.supplementNote - 补充说明 + * @param {Array} data.attachments - 附件列表 + */ +export function saveNextShiftNotes(data) { + return request({ + url: '/handover/next-shift-notes', + method: 'POST', + data + }) +} + +/** + * 提交交接班记录 + * @param {Object} data - 交接班完整数据 + */ +export function submitHandover(data) { + return request({ + url: '/handover/submit', + method: 'POST', + data + }) +} + +/** + * 检查接班人是否在线 + * @param {String} successorId - 接班人ID + */ +export function checkSuccessorOnline(successorId) { + return request({ + url: `/handover/check-online/${successorId}`, + method: 'GET' + }) +} + +/** + * 催促接班人确认 + * @param {String} successorId - 接班人ID + * @param {String} method - 催促方式: 'wechat', 'sms', 'phone', 'admin' + */ +export function remindSuccessor(successorId, method) { + return request({ + url: '/handover/remind-successor', + method: 'POST', + data: { + successorId, + method + } + }) +} + +/** + * 获取交接班历史记录 + * @param {Object} params - 查询参数 + * @param {Number} params.page - 页码 + * @param {Number} params.pageSize - 每页数量 + * @param {String} params.startDate - 开始日期 + * @param {String} params.endDate - 结束日期 + */ +export function getHandoverHistory(params) { + return request({ + url: '/handover/history', + method: 'GET', + params + }) +} + +/** + * 获取交接班详情 + * @param {String} handoverId - 交接班记录ID + */ +export function getHandoverDetail(handoverId) { + return request({ + url: `/handover/detail/${handoverId}`, + method: 'GET' + }) +} + +/** + * 获取今日工作统计报告 + */ +export function getTodayReport() { + return request({ + url: '/handover/today-report', + method: 'GET' + }) +} + +/** + * 获取今日收益预览 + */ +export function getTodayEarnings() { + return request({ + url: '/handover/today-earnings', + method: 'GET' + }) +} + +/** + * 确认下班打卡 + */ +export function confirmClockOut() { + return request({ + url: '/handover/clock-out', + method: 'POST' + }) +} + +/** + * 获取快捷标签列表 + */ +export function getQuickTags() { + return request({ + url: '/handover/quick-tags', + method: 'GET' + }) +} + +/** + * 添加自定义标签 + * @param {String} tagName - 标签名称 + */ +export function addCustomTag(tagName) { + return request({ + url: '/handover/custom-tag', + method: 'POST', + data: { + tagName + } + }) +} + +export default { + getCurrentShift, + getPreviousNotes, + getFocusElders, + getTodoList, + getWorkStatistics, + saveWorkSummary, + uploadPhoto, + getSuccessorInfo, + saveNextShiftNotes, + submitHandover, + checkSuccessorOnline, + remindSuccessor, + getHandoverHistory, + getHandoverDetail, + getTodayReport, + getTodayEarnings, + confirmClockOut, + getQuickTags, + addCustomTag +} diff --git a/src/pages.json b/src/pages.json index 52d1e3a..e8724ba 100644 --- a/src/pages.json +++ b/src/pages.json @@ -93,6 +93,65 @@ } } ] + }, + { + "root": "pages/handover", + "pages": [ + { + "path": "index", + "aliasPath": "/handover", + "name": "handover", + "style": { + "navigationStyle": "custom", + "navigationBarTitleText": "交接班" + } + }, + { + "path": "previous-notes", + "aliasPath": "/handover/previous-notes", + "name": "handover-previous-notes", + "style": { + "navigationStyle": "custom", + "navigationBarTitleText": "查看上一班留言" + } + }, + { + "path": "work-summary", + "aliasPath": "/handover/work-summary", + "name": "handover-work-summary", + "style": { + "navigationStyle": "custom", + "navigationBarTitleText": "本班工作总结" + } + }, + { + "path": "next-shift-notes", + "aliasPath": "/handover/next-shift-notes", + "name": "handover-next-shift-notes", + "style": { + "navigationStyle": "custom", + "navigationBarTitleText": "下一班注意事项" + } + }, + { + "path": "waiting-confirm", + "aliasPath": "/handover/waiting-confirm", + "name": "handover-waiting-confirm", + "style": { + "navigationStyle": "custom", + "navigationBarTitleText": "等待确认" + } + }, + { + "path": "complete", + "aliasPath": "/handover/complete", + "name": "handover-complete", + "style": { + "navigationStyle": "custom", + "navigationBarTitleText": "交接完成" + } + } + ] } ], "tabBar": { diff --git a/src/pages/handover/complete.vue b/src/pages/handover/complete.vue new file mode 100644 index 0000000..0b7e9b9 --- /dev/null +++ b/src/pages/handover/complete.vue @@ -0,0 +1,457 @@ + + + + + diff --git a/src/pages/handover/components/elder-card.vue b/src/pages/handover/components/elder-card.vue new file mode 100644 index 0000000..4dd7324 --- /dev/null +++ b/src/pages/handover/components/elder-card.vue @@ -0,0 +1,164 @@ + + + + + diff --git a/src/pages/handover/components/progress-indicator.vue b/src/pages/handover/components/progress-indicator.vue new file mode 100644 index 0000000..4812e0d --- /dev/null +++ b/src/pages/handover/components/progress-indicator.vue @@ -0,0 +1,126 @@ + + + + + diff --git a/src/pages/handover/components/remind-colleague-modal.vue b/src/pages/handover/components/remind-colleague-modal.vue new file mode 100644 index 0000000..46f46e9 --- /dev/null +++ b/src/pages/handover/components/remind-colleague-modal.vue @@ -0,0 +1,203 @@ + + + + + diff --git a/src/pages/handover/components/shift-end-reminder.vue b/src/pages/handover/components/shift-end-reminder.vue new file mode 100644 index 0000000..d70777d --- /dev/null +++ b/src/pages/handover/components/shift-end-reminder.vue @@ -0,0 +1,180 @@ + + + + + diff --git a/src/pages/handover/index.vue b/src/pages/handover/index.vue new file mode 100644 index 0000000..88ac562 --- /dev/null +++ b/src/pages/handover/index.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/src/pages/handover/next-shift-notes.vue b/src/pages/handover/next-shift-notes.vue new file mode 100644 index 0000000..d4e7208 --- /dev/null +++ b/src/pages/handover/next-shift-notes.vue @@ -0,0 +1,635 @@ +