# T3 · 诊单列表「未服务天数」 > 来源:~/.claude/plans/6-7-fluffy-sunset.md(T3 节)— 拆分版 > 范围:本 PR 仅完成 **后端字段 + 前端列**;「查看」按钮 + 行双击留到 T1+T2 上线时一并加(避免在 readonly 路由不存在的窗口期产生 404)。 ## 用户故事 二中心医助每天开诊单列表时,要一眼看出「这个患者多少天没打卡血糖」,便于优先回访。**口径**:未服务天数 = 当天 − 该患者最近一条血糖记录日期(天,向下取整)。以血糖(`zyt_tcm_blood_record.record_date` MAX)为唯一锚点,不混合其它打卡表。 ## 后端改动 文件:`server/app/adminapi/lists/tcm/DiagnosisLists.php` 在 `lists()` 末尾(拼装完所有其它字段之后): ```php $diagIds = array_filter(array_unique(array_column($lists, 'id'))); $maxRows = []; if (!empty($diagIds)) { $maxRows = BloodRecord::whereIn('diagnosis_id', $diagIds) ->whereNull('delete_time') ->group('diagnosis_id') ->column('MAX(record_date)', 'diagnosis_id'); } $now = time(); foreach ($lists as &$item) { $last = (int) ($maxRows[(int) $item['id']] ?? 0); $item['last_blood_record_at'] = $last > 0 ? date('Y-m-d', $last) : null; $item['unserved_days'] = $last > 0 ? max(0, (int) floor(($now - $last) / 86400)) : null; } ``` 字段语义: - `last_blood_record_at`:`Y-m-d` 字符串,无打卡 → `null` - `unserved_days`:整数,无打卡 → `null` ## 前端改动 文件:`admin/src/views/tcm/diagnosis/index.vue` 在「开方」列后、「视频旁观」列前,新增列: ```html ``` 颜色规则(计划原文): - `null/undefined` → 灰 - `>=7` → 红 - `3-6` → 橙 - `<=2` → 绿 ```ts const unservedDaysClass = (n: unknown) => { if (n === null || n === undefined) return 'unserved-muted' const num = Number(n) if (!Number.isFinite(num)) return 'unserved-muted' if (num >= 7) return 'unserved-red' if (num >= 3) return 'unserved-orange' return 'unserved-green' } ``` CSS 加 4 个 class(红 #dc2626 / 橙 #ea580c / 绿 #16a34a / 灰 #94a3b8)。 ## 不做(边界) - 不加「查看」按钮(依赖 T1 readonly 页) - 不加 `@row-dblclick`(同上) - 不加 `?sort=unserved_days&order=desc` 排序白名单(这是计划原文的可选项;当前没有用户反馈需要排序,先简化) - 不动 `count()` 函数(仅展示字段,不影响过滤/分页) ## 验收 1. 在诊单列表里能看到「未服务天数」列 2. 没有任何血糖打卡的诊单 → 显示 `—`(灰) 3. 7 天前打过卡 → 红色(如 9) 4. 3-6 天前打过卡 → 橙色 5. ≤ 2 天打过卡 → 绿色 6. 列表分页 / 搜索 / Tab 切换不受影响 7. 性能:单页面查询多一次 `WHERE IN + GROUP BY` 走 `idx_diagnosis_id`,N+1 不会出现