fix(mobile): supervisor dashboard color semantics and polish

- workbench metrics: red only when value > 0 (was always red, even zeros)
- stable alert renders as calm green strip, not a clickable pink alarm card
- quick-entry header: drop duplicated member count
- header subtitle shows today's date
- team: low-risk member cards use neutral grey left bar (was red for all)
- team: 'normal' risk count is green (was red)
- team: difficulty sort chips flex-centered
This commit is contained in:
2026-07-20 09:39:28 +08:00
parent 260b7f851e
commit 875a1cfd2a
2 changed files with 49 additions and 15 deletions
+40 -14
View File
@@ -3,7 +3,7 @@
<view class="page-head">
<view>
<text class="page-title">主管工作台</text>
<text class="page-subtitle">住宅项目 · 今日训练与带教</text>
<text class="page-subtitle">住宅项目 · 今天 {{ todayLabel }}</text>
</view>
<button v-if="loggedIn && !accessDenied" class="ghost-button refresh-button" :disabled="loading" @click="loadPage">
{{ loading ? '刷新中' : '刷新' }}
@@ -40,7 +40,7 @@
v-for="item in supervisorMetrics"
:key="item.key"
class="metric-item"
:class="{ primary: item.primary, danger: item.key === 'lowScores' || item.key === 'alerts' }"
:class="{ attention: item.value > 0 && (item.primary || item.key === 'lowScores' || item.key === 'alerts') }"
>
<text class="metric-value">{{ item.value }}</text>
<text class="metric-label">{{ item.title }}</text>
@@ -54,9 +54,9 @@
<text class="panel-title">连续低分预警</text>
<text class="muted">{{ actionableAlerts.length }} 条</text>
</view>
<view v-if="alerts.length" class="alert-list">
<view v-if="actionableAlerts.length" class="alert-list">
<button
v-for="item in alerts"
v-for="item in actionableAlerts"
:key="`${item.type}-${item.title}`"
class="alert-row"
:class="item.severity"
@@ -69,6 +69,10 @@
<text class="alert-arrow">›</text>
</button>
</view>
<view v-else-if="stableAlert" class="stable-strip">
<text class="stable-title">{{ stableAlert.title }}</text>
<text class="stable-desc">{{ stableAlert.desc }}</text>
</view>
<view v-else class="empty compact-empty">暂无团队预警</view>
</view>
@@ -96,7 +100,6 @@
<view class="panel task-panel">
<view class="section-head">
<text class="panel-title">快捷入口</text>
<text class="muted">{{ teamCount }} 人</text>
</view>
<view class="task-list">
<button class="task-row" @click="openPage('/pages/supervisor/team/index')">
@@ -177,6 +180,10 @@ const pendingAssignmentCount = computed(() =>
supervisorMetrics.value.find((item) => item.key === 'pendingAssignments')?.value || 0);
const pendingPreview = computed(() => pendingReviews.value.slice(0, 3));
const actionableAlerts = computed(() => actionablePracticeAlerts(alerts.value));
const stableAlert = computed(() => alerts.value.find((item) => item.type === 'stable'));
const weekNames = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
const now = new Date();
const todayLabel = `${now.getMonth() + 1}月${now.getDate()}日 ${weekNames[now.getDay()]}`;
const clearData = () => {
pendingReviews.value = [];
@@ -336,15 +343,15 @@ onUnload(invalidateRequests);
background: #f8fbff;
}
.metric-item.primary {
.metric-item.attention {
background: #eef4ff;
}
.metric-item.primary .metric-value {
.metric-item.attention .metric-value {
color: var(--employee-primary);
}
.metric-item.primary .metric-label {
.metric-item.attention .metric-label {
color: var(--employee-primary);
}
@@ -532,15 +539,12 @@ onUnload(invalidateRequests);
box-shadow: 0 4px 14px rgba(24, 28, 36, 0.03);
}
.metric-item.primary,
.metric-item.danger {
.metric-item.attention {
background: #ffffff;
}
.metric-item.primary .metric-value,
.metric-item.primary .metric-label,
.metric-item.danger .metric-value,
.metric-item.danger .metric-label {
.metric-item.attention .metric-value,
.metric-item.attention .metric-label {
color: #e60012;
}
@@ -611,6 +615,28 @@ onUnload(invalidateRequests);
color: #e60012;
}
.stable-strip {
margin-top: 10px;
padding: 14px 16px;
border-radius: 14px;
background: #f0fdf4;
}
.stable-title {
display: block;
color: #15803d;
font-size: 14px;
font-weight: 800;
}
.stable-desc {
display: block;
margin-top: 4px;
color: #4b5563;
font-size: 12px;
line-height: 1.45;
}
.preview-row {
padding: 14px 0;
border-width: 0 0 1px;
@@ -436,7 +436,7 @@ onUnload(invalidateRequests);
}
.risk-item.low .risk-value {
color: var(--employee-primary);
color: #16a34a;
}
.mistake-panel {
@@ -451,12 +451,16 @@ onUnload(invalidateRequests);
}
.difficulty-sort button {
display: flex;
align-items: center;
justify-content: center;
min-height: 34px;
padding: 0 10px;
border: 1px solid #d7e0eb;
background: #ffffff;
color: var(--employee-muted);
font-size: 12px;
line-height: 1;
}
.difficulty-sort button.active {
@@ -561,6 +565,10 @@ onUnload(invalidateRequests);
border-left-color: #f59e0b;
}
.team-row.low {
border-left-color: #d7dde5;
}
.team-main {
min-width: 0;
flex: 1;