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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user