更新功能

This commit is contained in:
Your Name
2026-05-26 18:05:48 +08:00
parent 5b233fb0ab
commit 0dd9cdcba9
8 changed files with 4703 additions and 10 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
import App from './App' import App from './App'
var baseUrl ='https://admin.zhenyangtang.com.cn/'; var baseUrl ='https://css.zhenyangtang.com.cn/';
// #ifndef VUE3 // #ifndef VUE3
import Vue from 'vue' import Vue from 'vue'
import './uni.promisify.adaptor' import './uni.promisify.adaptor'
+7 -1
View File
@@ -57,7 +57,13 @@
"optimization" : { "optimization" : {
"subPackages" : true "subPackages" : true
}, },
"usingComponents" : true "usingComponents" : true,
"plugins" : {
"WechatSI" : {
"version" : "0.3.5",
"provider" : "wx069ba97219f66d99"
}
}
}, },
"mp-alipay" : { "mp-alipay" : {
"usingComponents" : true "usingComponents" : true
+15
View File
@@ -126,6 +126,21 @@
} }
} }
] ]
},
{
"root": "tongji",
"pages": [
{
"path": "pages/index",
"style": {
"navigationBarTitleText": "日常记录",
"navigationBarBackgroundColor": "#0ea5a4",
"navigationBarTextStyle": "white",
"backgroundColor": "#f1f5f9",
"enablePullDownRefresh": true
}
}
]
} }
], ],
"tabBar": { "tabBar": {
+70
View File
@@ -53,6 +53,18 @@
<text class="time-value">{{ card.create_time || '-' }}</text> <text class="time-value">{{ card.create_time || '-' }}</text>
</view> </view>
</view> </view>
<!-- 快捷入口 -->
<view class="card-actions">
<view class="card-action-btn primary" @click.stop="viewDailyRecord(card)">
<text class="card-action-icon">📈</text>
<text class="card-action-text">日常记录</text>
</view>
<view class="card-action-btn" @click.stop="viewCardDetail(card)">
<text class="card-action-icon">📝</text>
<text class="card-action-text">查看 / 编辑</text>
</view>
</view>
</view> </view>
<!-- 空状态 --> <!-- 空状态 -->
@@ -138,6 +150,16 @@ const viewCardDetail = (card) => {
}) })
} }
// 查看日常记录(血糖血压 / 饮食 / 运动 / 跟踪备注 + 波浪图)
const viewDailyRecord = (card) => {
const url = `/tongji/pages/index?diagnosis_id=${card.id}` +
`&patient_id=${card.patient_id || ''}` +
`&patient_name=${encodeURIComponent(card.patient_name || '')}` +
`&age=${card.age || ''}` +
`&gender=${card.gender || ''}`
uni.navigateTo({ url })
}
// 新建就诊卡(patient_id 创建后自动生成,仅需登录) // 新建就诊卡(patient_id 创建后自动生成,仅需登录)
const createCard = () => { const createCard = () => {
const token = uni.getStorageSync('token') const token = uni.getStorageSync('token')
@@ -310,6 +332,54 @@ const formatDate = (timestamp) => {
border-top: 4rpx solid #e8eaed; border-top: 4rpx solid #e8eaed;
} }
.card-actions {
display: flex;
gap: 20rpx;
margin-top: 28rpx;
padding-top: 28rpx;
border-top: 4rpx solid #e8eaed;
}
.card-action-btn {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 12rpx;
padding: 24rpx 12rpx;
background: #f6faff;
border-radius: 20rpx;
border: 2rpx solid #d6e6fb;
min-height: 80rpx;
transition: all 0.2s;
&:active {
transform: scale(0.98);
opacity: 0.85;
}
&.primary {
background: linear-gradient(135deg, #1890ff, #0ea5a4);
border-color: transparent;
.card-action-icon,
.card-action-text {
color: #ffffff;
}
}
}
.card-action-icon {
font-size: 36rpx;
color: #1890ff;
}
.card-action-text {
font-size: 30rpx;
color: #1890ff;
font-weight: 500;
}
.time-info { .time-info {
display: flex; display: flex;
align-items: center; align-items: center;
File diff suppressed because it is too large Load Diff
@@ -23,6 +23,10 @@
</div> </div>
<div v-if="canEditDailyRecord" class="daily-matrix__toolbar-right"> <div v-if="canEditDailyRecord" class="daily-matrix__toolbar-right">
<span v-if="hasPatientSelfRecord" class="daily-matrix__legend">
<span class="daily-matrix__cell-patient">自录</span>
<span class="daily-matrix__legend-text">= 患者在小程序自录</span>
</span>
<el-button type="primary" @click="openQuickAdd('blood')">+血糖</el-button> <el-button type="primary" @click="openQuickAdd('blood')">+血糖</el-button>
<el-button @click="openQuickAdd('diet')">+饮食</el-button> <el-button @click="openQuickAdd('diet')">+饮食</el-button>
<el-button @click="openQuickAdd('exercise')">+运动</el-button> <el-button @click="openQuickAdd('exercise')">+运动</el-button>
@@ -30,6 +34,10 @@
<el-button @click="fetchTracking">刷新</el-button> <el-button @click="fetchTracking">刷新</el-button>
</div> </div>
<div v-else class="daily-matrix__toolbar-right"> <div v-else class="daily-matrix__toolbar-right">
<span v-if="hasPatientSelfRecord" class="daily-matrix__legend">
<span class="daily-matrix__cell-patient">自录</span>
<span class="daily-matrix__legend-text">= 患者在小程序自录</span>
</span>
<el-button @click="fetchTracking">刷新</el-button> <el-button @click="fetchTracking">刷新</el-button>
</div> </div>
</div> </div>
@@ -57,7 +65,8 @@
:class="{ :class="{
'is-clickable': isCellClickable(row.key, date), 'is-clickable': isCellClickable(row.key, date),
'is-empty': !getCell(row.key, date).hasRecord, 'is-empty': !getCell(row.key, date).hasRecord,
'is-high': getCell(row.key, date).isHigh 'is-high': getCell(row.key, date).isHigh,
'is-patient-self': getCell(row.key, date).isPatientSelf && getCell(row.key, date).hasRecord
}" }"
@click="handleCellClick(row.key, date)" @click="handleCellClick(row.key, date)"
> >
@@ -82,6 +91,14 @@
<template v-else-if="getCell(row.key, date).value"> <template v-else-if="getCell(row.key, date).value">
<span>{{ getCell(row.key, date).value }}</span> <span>{{ getCell(row.key, date).value }}</span>
<span v-if="getCell(row.key, date).isHigh" class="daily-matrix__cell-up"></span> <span v-if="getCell(row.key, date).isHigh" class="daily-matrix__cell-up"></span>
<el-tooltip
v-if="getCell(row.key, date).isPatientSelf"
content="患者在小程序自录的数据"
placement="top"
:show-after="120"
>
<span class="daily-matrix__cell-patient">自录</span>
</el-tooltip>
</template> </template>
<template v-else></template> <template v-else></template>
</div> </div>
@@ -345,6 +362,10 @@ interface BloodRecord {
western_medicine?: string western_medicine?: string
insulin?: string insulin?: string
remark?: string remark?: string
/** 来源:0-医生录入 1-患者自录(小程序日常记录页) */
source?: number
/** 合并后该日是否含有「患者自录」记录 */
has_patient_self?: boolean
[key: string]: any [key: string]: any
} }
@@ -558,6 +579,10 @@ const visibleDates = computed(() => {
return dates return dates
}) })
const hasPatientSelfRecord = computed(() => {
return bloodRecords.value.some((r) => Number((r as any).source) === 1)
})
const bloodByDate = computed(() => { const bloodByDate = computed(() => {
const map = new Map<string, BloodRecord>() const map = new Map<string, BloodRecord>()
for (const record of bloodRecords.value) { for (const record of bloodRecords.value) {
@@ -570,7 +595,8 @@ const bloodByDate = computed(() => {
patient_id: record.patient_id, patient_id: record.patient_id,
record_date: date, record_date: date,
record_time: record.record_time || '', record_time: record.record_time || '',
record_date_ts: record.record_date_ts record_date_ts: record.record_date_ts,
has_patient_self: false
}) })
} }
const merged = map.get(date)! const merged = map.get(date)!
@@ -594,6 +620,10 @@ const bloodByDate = computed(() => {
;(merged as any)[field] = record[field] ;(merged as any)[field] = record[field]
} }
} }
// 当天有任意 source=1 的记录则标记为患者自录
if (Number(record.source) === 1) {
merged.has_patient_self = true
}
} }
return map return map
}) })
@@ -723,35 +753,40 @@ function parseTrendNumber(value: unknown): number | null {
return parsed return parsed
} }
function getCell(metric: string, date: string): { value: string; isHigh: boolean; hasRecord: boolean } { function getCell(metric: string, date: string): { value: string; isHigh: boolean; hasRecord: boolean; isPatientSelf?: boolean } {
const blood = bloodByDate.value.get(date) const blood = bloodByDate.value.get(date)
const diet = dietByDate.value.get(date) const diet = dietByDate.value.get(date)
const exercise = exerciseByDate.value.get(date) const exercise = exerciseByDate.value.get(date)
const tracking = trackingByDate.value.get(date) const tracking = trackingByDate.value.get(date)
const isPatientSelf = !!blood?.has_patient_self
switch (metric) { switch (metric) {
case 'fasting': case 'fasting':
return { return {
value: blood?.fasting_blood_sugar != null && blood.fasting_blood_sugar !== '' ? String(blood.fasting_blood_sugar) : '', value: blood?.fasting_blood_sugar != null && blood.fasting_blood_sugar !== '' ? String(blood.fasting_blood_sugar) : '',
isHigh: isHighFastingBloodSugar(blood?.fasting_blood_sugar, props.age), isHigh: isHighFastingBloodSugar(blood?.fasting_blood_sugar, props.age),
hasRecord: !!blood && blood.fasting_blood_sugar != null && blood.fasting_blood_sugar !== '' hasRecord: !!blood && blood.fasting_blood_sugar != null && blood.fasting_blood_sugar !== '',
isPatientSelf
} }
case 'postprandial': case 'postprandial':
return { return {
value: blood?.postprandial_blood_sugar != null && blood.postprandial_blood_sugar !== '' ? String(blood.postprandial_blood_sugar) : '', value: blood?.postprandial_blood_sugar != null && blood.postprandial_blood_sugar !== '' ? String(blood.postprandial_blood_sugar) : '',
isHigh: isHighPostprandialBloodSugar(blood?.postprandial_blood_sugar, props.age), isHigh: isHighPostprandialBloodSugar(blood?.postprandial_blood_sugar, props.age),
hasRecord: !!blood && blood.postprandial_blood_sugar != null && blood.postprandial_blood_sugar !== '' hasRecord: !!blood && blood.postprandial_blood_sugar != null && blood.postprandial_blood_sugar !== '',
isPatientSelf
} }
case 'other': case 'other':
return { return {
value: blood?.other_blood_sugar != null && blood.other_blood_sugar !== '' ? String(blood.other_blood_sugar) : '', value: blood?.other_blood_sugar != null && blood.other_blood_sugar !== '' ? String(blood.other_blood_sugar) : '',
isHigh: isHighOtherBloodSugar(blood?.other_blood_sugar, props.age), isHigh: isHighOtherBloodSugar(blood?.other_blood_sugar, props.age),
hasRecord: !!blood && blood.other_blood_sugar != null && blood.other_blood_sugar !== '' hasRecord: !!blood && blood.other_blood_sugar != null && blood.other_blood_sugar !== '',
isPatientSelf
} }
case 'bp': case 'bp':
return { return {
value: blood && (blood.systolic_pressure || blood.diastolic_pressure) ? formatBp(blood) : '', value: blood && (blood.systolic_pressure || blood.diastolic_pressure) ? formatBp(blood) : '',
isHigh: isHighBloodPressure(blood), isHigh: isHighBloodPressure(blood),
hasRecord: !!blood && !!(blood.systolic_pressure || blood.diastolic_pressure) hasRecord: !!blood && !!(blood.systolic_pressure || blood.diastolic_pressure),
isPatientSelf
} }
case 'western': case 'western':
return { return {
@@ -1115,6 +1150,12 @@ defineExpose({ refresh: fetchTracking })
color: #dc2626; color: #dc2626;
font-weight: 700; font-weight: 700;
} }
&.is-patient-self {
position: relative;
background: linear-gradient(180deg, rgba(139, 92, 246, 0.04) 0%, rgba(139, 92, 246, 0.10) 100%);
border-radius: 4px;
}
} }
&__cell-up { &__cell-up {
@@ -1122,6 +1163,38 @@ defineExpose({ refresh: fetchTracking })
font-size: 13px; font-size: 13px;
} }
&__cell-patient {
display: inline-block;
margin-left: 4px;
padding: 1px 6px;
font-size: 11px;
font-weight: 600;
color: #6d28d9;
background: #ede9fe;
border: 1px solid #ddd6fe;
border-radius: 999px;
line-height: 1.2;
letter-spacing: 0.5px;
white-space: nowrap;
}
&__legend {
display: inline-flex;
align-items: center;
gap: 6px;
margin-right: 12px;
padding: 2px 10px 2px 6px;
background: #f8f6ff;
border: 1px dashed #ddd6fe;
border-radius: 999px;
}
&__legend-text {
font-size: 12px;
color: #6d28d9;
font-weight: 500;
}
&__todo { &__todo {
margin-top: 16px; margin-top: 16px;
} }
+299 -1
View File
@@ -15,7 +15,10 @@
namespace app\api\controller; namespace app\api\controller;
use app\adminapi\logic\tcm\DiagnosisLogic; use app\adminapi\logic\tcm\DiagnosisLogic;
use app\adminapi\logic\tcm\TrackingNoteLogic;
use app\adminapi\logic\ConfigLogic; use app\adminapi\logic\ConfigLogic;
use app\common\model\tcm\Diagnosis;
use app\common\model\tcm\BloodRecord;
/** /**
* 中医诊断控制器(供小程序调用) * 中医诊断控制器(供小程序调用)
@@ -28,7 +31,7 @@ class TcmController extends BaseApiController
* @notes 不需要登录的方法 * @notes 不需要登录的方法
* @var array * @var array
*/ */
public array $notNeedLogin = ['getPatientSignature', 'diagnosisDetail', 'getDict', 'confirmDiagnosis', 'getCardList', 'getOrderByNo', 'patientHangupVideo']; public array $notNeedLogin = ['getPatientSignature', 'diagnosisDetail', 'getDict', 'confirmDiagnosis', 'getCardList', 'getOrderByNo', 'patientHangupVideo', 'dailyTrackingWindow', 'dailyTrackingNotes'];
/** /**
* @notes 获取患者签名(供小程序调用) * @notes 获取患者签名(供小程序调用)
@@ -332,6 +335,301 @@ class TcmController extends BaseApiController
} }
} }
/**
* @notes 日常记录窗口数据(血糖血压 / 饮食 / 运动)—— 患者端
*
* 路由:GET /api/tcm/dailyTrackingWindow?diagnosis_id=:id&patient_id=:pid&start_date=&end_date=
* 说明:供小程序「日常记录」页面拉取一段时间内的跟踪数据,复用后台 fetchTrackingWindow。
*
* @return \think\response\Json
*/
public function dailyTrackingWindow()
{
$diagnosisId = (int) $this->request->get('diagnosis_id', 0);
$patientId = (int) $this->request->get('patient_id', 0);
$startDate = (string) $this->request->get('start_date', '');
$endDate = (string) $this->request->get('end_date', '');
if ($diagnosisId <= 0) {
return $this->fail('诊单ID不能为空');
}
try {
// 患者端越权校验:诊单必须存在;如传入 patient_id 则须与诊单匹配
$diagnosis = Diagnosis::where('id', $diagnosisId)->find();
if (!$diagnosis) {
return $this->fail('诊单不存在');
}
if ($patientId > 0 && (int) $diagnosis['patient_id'] !== $patientId) {
return $this->fail('无权查看该诊单的日常记录');
}
$data = DiagnosisLogic::fetchTrackingWindow($diagnosisId, $startDate, $endDate);
// 把诊断的基础信息一并返回,便于小程序展示头部摘要
$data['diagnosis'] = [
'id' => (int) $diagnosis['id'],
'patient_id' => (int) $diagnosis['patient_id'],
'patient_name' => (string) ($diagnosis['patient_name'] ?? ''),
'age' => (int) ($diagnosis['age'] ?? 0),
'gender' => (int) ($diagnosis['gender'] ?? 0),
];
return $this->data($data);
} catch (\Exception $e) {
return $this->fail($e->getMessage());
}
}
/**
* @notes 日常记录-跟踪备注列表(患者端)
*
* 路由:GET /api/tcm/dailyTrackingNotes?diagnosis_id=:id&patient_id=:pid
*
* @return \think\response\Json
*/
public function dailyTrackingNotes()
{
$diagnosisId = (int) $this->request->get('diagnosis_id', 0);
$patientId = (int) $this->request->get('patient_id', 0);
if ($diagnosisId <= 0) {
return $this->fail('诊单ID不能为空');
}
try {
$diagnosis = Diagnosis::where('id', $diagnosisId)->find();
if (!$diagnosis) {
return $this->fail('诊单不存在');
}
if ($patientId > 0 && (int) $diagnosis['patient_id'] !== $patientId) {
return $this->fail('无权查看该诊单的跟踪备注');
}
$notes = TrackingNoteLogic::getByDiagnosis($diagnosisId);
return $this->data($notes);
} catch (\Exception $e) {
return $this->fail($e->getMessage());
}
}
/**
* @notes 校验当前登录患者是否拥有指定诊单(通过 diagnosis_view_records 关联)
* @param int $diagnosisId
* @return array{ok:bool,diagnosis?:\app\common\model\tcm\Diagnosis,error?:string}
*/
private function ensurePatientOwnsDiagnosis(int $diagnosisId): array
{
if (!$this->userId) {
return ['ok' => false, 'error' => '请先登录'];
}
if ($diagnosisId <= 0) {
return ['ok' => false, 'error' => '诊单ID不能为空'];
}
$diagnosis = Diagnosis::where('id', $diagnosisId)->find();
if (!$diagnosis) {
return ['ok' => false, 'error' => '诊单不存在'];
}
// 通过 diagnosis_view_records 校验当前小程序用户与该诊单的归属关系
// 该表是「就诊卡列表」的来源(参考 DiagnosisLogic::getCardList
$owned = \think\facade\Db::name('diagnosis_view_records')
->where('user_id', $this->userId)
->where('diagnosis_id', $diagnosisId)
->where('delete_time', null)
->find();
if (!$owned) {
return ['ok' => false, 'error' => '无权操作该诊单'];
}
return ['ok' => true, 'diagnosis' => $diagnosis];
}
/**
* @notes 日常记录-获取今日已录入的血糖血压记录(患者端)
*
* 路由:GET /api/tcm/dailyTodayBloodRecord?diagnosis_id=:id
*
* 用于「日常记录」页打开「录入今日」表单时预填数据;只返回 source=1 的当天记录。
*
* @return \think\response\Json
*/
public function dailyTodayBloodRecord()
{
$diagnosisId = (int) $this->request->get('diagnosis_id', 0);
$check = $this->ensurePatientOwnsDiagnosis($diagnosisId);
if (!$check['ok']) {
return $this->fail($check['error']);
}
try {
$todayStart = strtotime(date('Y-m-d 00:00:00'));
$todayEnd = strtotime(date('Y-m-d 23:59:59'));
$record = BloodRecord::where('diagnosis_id', $diagnosisId)
->where('source', 1)
->where('record_date', '>=', $todayStart)
->where('record_date', '<=', $todayEnd)
->order('id', 'desc')
->find();
if (!$record) {
return $this->data(['record' => null, 'today' => date('Y-m-d')]);
}
$data = $record->toArray();
$data['record_date'] = date('Y-m-d', (int) $data['record_date']);
return $this->data(['record' => $data, 'today' => date('Y-m-d')]);
} catch (\Exception $e) {
return $this->fail($e->getMessage());
}
}
/**
* @notes 日常记录-保存今日的血糖血压记录(患者端)
*
* 路由:POST /api/tcm/dailySaveBloodRecord
* 必填:diagnosis_id
* 可选数值:fasting_blood_sugar, postprandial_blood_sugar, other_blood_sugar,
* systolic_pressure, diastolic_pressure
* 可选字符串:remark
*
* 语义:同一天同一诊单只有一条 source=1 的记录;存在则 update,不存在则 create。
* 日期强制为「今天」;任何 record_date 入参被忽略,避免补录历史。
*
* @return \think\response\Json
*/
public function dailySaveBloodRecord()
{
$diagnosisId = (int) $this->request->post('diagnosis_id', 0);
$check = $this->ensurePatientOwnsDiagnosis($diagnosisId);
if (!$check['ok']) {
return $this->fail($check['error']);
}
$diagnosis = $check['diagnosis'];
// 解析并校验数值字段;空字符串当 null 处理
$parseDecimal = function ($v) {
if ($v === null || $v === '' || $v === '0' || $v === 0) return null;
if (!is_numeric($v)) return null;
$f = (float) $v;
return $f > 0 ? $f : null;
};
$parseInt = function ($v) {
if ($v === null || $v === '') return null;
if (!is_numeric($v)) return null;
$i = (int) $v;
return $i > 0 ? $i : null;
};
$fasting = $parseDecimal($this->request->post('fasting_blood_sugar'));
$postprandial = $parseDecimal($this->request->post('postprandial_blood_sugar'));
$other = $parseDecimal($this->request->post('other_blood_sugar'));
$systolic = $parseInt($this->request->post('systolic_pressure'));
$diastolic = $parseInt($this->request->post('diastolic_pressure'));
$remark = trim((string) $this->request->post('remark', ''));
// 至少要填一个有效字段
if ($fasting === null && $postprandial === null && $other === null &&
$systolic === null && $diastolic === null && $remark === '') {
return $this->fail('请至少填写一项血糖或血压数据');
}
// 边界校验,避免误录天文数字
if ($fasting !== null && ($fasting < 0.1 || $fasting > 50)) return $this->fail('空腹血糖数值异常');
if ($postprandial !== null && ($postprandial < 0.1 || $postprandial > 50)) return $this->fail('餐后血糖数值异常');
if ($other !== null && ($other < 0.1 || $other > 50)) return $this->fail('其他血糖数值异常');
if ($systolic !== null && ($systolic < 40 || $systolic > 300)) return $this->fail('收缩压数值异常');
if ($diastolic !== null && ($diastolic < 20 || $diastolic > 200)) return $this->fail('舒张压数值异常');
try {
$todayStart = strtotime(date('Y-m-d 00:00:00'));
$todayEnd = strtotime(date('Y-m-d 23:59:59'));
$existing = BloodRecord::where('diagnosis_id', $diagnosisId)
->where('source', 1)
->where('record_date', '>=', $todayStart)
->where('record_date', '<=', $todayEnd)
->order('id', 'desc')
->find();
$payload = [
'diagnosis_id' => $diagnosisId,
'patient_id' => (int) $diagnosis['patient_id'],
'record_date' => $todayStart,
'record_time' => date('H:i'),
'fasting_blood_sugar' => $fasting,
'postprandial_blood_sugar' => $postprandial,
'other_blood_sugar' => $other,
'systolic_pressure' => $systolic,
'diastolic_pressure' => $diastolic,
'remark' => $remark,
'source' => 1,
];
if ($existing) {
$payload['id'] = $existing['id'];
BloodRecord::update($payload);
return $this->success('已更新今日记录', ['id' => $existing['id']]);
}
$created = BloodRecord::create($payload);
return $this->success('录入成功', ['id' => $created->id]);
} catch (\Exception $e) {
return $this->fail($e->getMessage());
}
}
/**
* @notes 日常记录-删除今日的血糖血压记录(患者端)
*
* 路由:POST /api/tcm/dailyDeleteBloodRecord
* 必填:diagnosis_id, id
*
* 只允许删除当前用户拥有的诊单 + 当天 + source=1 的记录;其他情况一律拒绝。
*
* @return \think\response\Json
*/
public function dailyDeleteBloodRecord()
{
$diagnosisId = (int) $this->request->post('diagnosis_id', 0);
$recordId = (int) $this->request->post('id', 0);
$check = $this->ensurePatientOwnsDiagnosis($diagnosisId);
if (!$check['ok']) {
return $this->fail($check['error']);
}
if ($recordId <= 0) {
return $this->fail('记录ID不能为空');
}
try {
$todayStart = strtotime(date('Y-m-d 00:00:00'));
$todayEnd = strtotime(date('Y-m-d 23:59:59'));
$record = BloodRecord::where('id', $recordId)
->where('diagnosis_id', $diagnosisId)
->where('source', 1)
->find();
if (!$record) {
return $this->fail('记录不存在或无权删除');
}
$ts = (int) $record['record_date'];
if ($ts < $todayStart || $ts > $todayEnd) {
return $this->fail('只能删除当天的记录');
}
BloodRecord::destroy($recordId);
return $this->success('已删除');
} catch (\Exception $e) {
return $this->fail($e->getMessage());
}
}
/** /**
* @notes 根据订单号获取订单详情(供小程序支付页调用) * @notes 根据订单号获取订单详情(供小程序支付页调用)
* @return \think\response\Json * @return \think\response\Json
@@ -0,0 +1,11 @@
-- 为「血糖血压记录表」增加来源字段
-- 0 = 医生 / 助理在管理后台录入(历史数据默认 0)
-- 1 = 患者在小程序「日常记录」页自录
-- 该字段用于:1) 后台 DailyMatrix 上展示「患者自录」徽章;2) 限制患者只能编辑/删除自己当天的记录
ALTER TABLE `zyt_tcm_blood_record`
ADD COLUMN `source` tinyint(1) NOT NULL DEFAULT 0 COMMENT '来源:0-医生录入 1-患者自录' AFTER `remark`;
-- 加索引方便按来源过滤
ALTER TABLE `zyt_tcm_blood_record`
ADD KEY `idx_source` (`source`);