fix: 多角色业务链路测试发现并修复 3 类问题
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

1. 角色权限修复(CRITICAL):
   - operator 角色权限为空(迁移 name/code 不匹配 + 软删除冲突)
   - doctor 角色权限被误清(API assign_permissions 失败导致全部软删除)
   - nurse 缺 devices 权限 + doctor/nurse 缺 appointment 权限
   - 新增 3 个迁移 000130-000132 修复所有角色权限

2. 趋势指标映射修复(HIGH):
   - 前端 blood_pressure_systolic → systolic_bp_morning
   - 前端 blood_sugar_fasting → blood_sugar
   - 同步修复首页、健康页、趋势页的 indicator 参数

3. 咨询页错误处理优化(MEDIUM):
   - 403/401 时显示空列表而非"加载失败"错误提示
This commit is contained in:
iven
2026-05-08 22:00:43 +08:00
parent 81c174a902
commit 28dafa9bea
8 changed files with 376 additions and 77 deletions

View File

@@ -80,9 +80,9 @@ export default function Health() {
setTrendLoading(true);
try {
const indicatorMap: Record<VitalType, string> = {
blood_pressure: 'blood_pressure_systolic',
blood_pressure: 'systolic_bp_morning',
heart_rate: 'heart_rate',
blood_sugar: 'blood_sugar_fasting',
blood_sugar: 'blood_sugar',
weight: 'weight',
};
const points = await fetchTrend(indicatorMap[type], '7d');
@@ -194,6 +194,13 @@ export default function Health() {
};
const maxTrendValue = Math.max(...trendData.map((d) => d.value), 1);
const getThresholdValue = (type: VitalType, th: HealthThreshold[]): number | null => {
if (type === 'blood_pressure') return findThreshold(th, 'systolic_bp', 'high')?.threshold_value ?? 140;
if (type === 'heart_rate') return findThreshold(th, 'heart_rate', 'high')?.threshold_value ?? 100;
if (type === 'blood_sugar') return findThreshold(th, 'blood_sugar_fasting', 'high')?.threshold_value ?? 6.1;
return null;
};
const dayLabels = ['日', '一', '二', '三', '四', '五', '六'];
return (
@@ -351,12 +358,20 @@ export default function Health() {
) : (
<View className='trend-chart'>
<View className='trend-bars'>
{/* 阈值标线 */}
{getThresholdValue(activeTab, thresholds) && (() => {
const tv = getThresholdValue(activeTab, thresholds)!;
const pct = Math.min(95, (tv / maxTrendValue) * 100);
return (
<View className='trend-threshold-line' style={`bottom:${12 + pct * 1.08}px;`}>
<Text className='trend-threshold-label'>{tv}</Text>
</View>
);
})()}
{trendData.map((point, i) => {
const heightPct = Math.max(8, (point.value / maxTrendValue) * 100);
const isAbnormal = activeTab === 'blood_pressure' ? point.value > 140
: activeTab === 'heart_rate' ? (point.value > 100 || point.value < 60)
: activeTab === 'blood_sugar' ? point.value > 6.1
: false;
const tv = getThresholdValue(activeTab, thresholds);
const isAbnormal = tv ? point.value >= tv : false;
const dayOfWeek = new Date(point.date).getDay();
return (
<View className='trend-bar-col' key={i}>