|
|
@@ -1,15 +1,34 @@
|
|
|
<template>
|
|
|
- <div class="page">
|
|
|
- <div class="page-hero">
|
|
|
+ <div class="app-page period-workbench">
|
|
|
+ <div class="app-page-header page-hero">
|
|
|
<div class="hero-info">
|
|
|
- <h2>考核周期</h2>
|
|
|
- <p>管理考核节奏,推动 OKR 对齐</p>
|
|
|
+ <h2 class="app-page-title">考核周期</h2>
|
|
|
+ <p class="app-page-subtitle">管理考核节奏,推动 OKR 对齐</p>
|
|
|
</div>
|
|
|
<el-button v-if="auth.isAdmin" type="primary" size="large" @click="showCreate = true" round>
|
|
|
创建新周期
|
|
|
</el-button>
|
|
|
</div>
|
|
|
|
|
|
+ <div class="period-metrics metric-row" v-if="periods.length">
|
|
|
+ <div class="metric-card">
|
|
|
+ <span class="metric-card__label">进行中</span>
|
|
|
+ <strong>{{ active.length }}</strong>
|
|
|
+ </div>
|
|
|
+ <div class="metric-card">
|
|
|
+ <span class="metric-card__label">OKR 对齐</span>
|
|
|
+ <strong>{{ okrAlign.length }}</strong>
|
|
|
+ </div>
|
|
|
+ <div class="metric-card">
|
|
|
+ <span class="metric-card__label">考评中</span>
|
|
|
+ <strong>{{ assessing.length }}</strong>
|
|
|
+ </div>
|
|
|
+ <div class="metric-card">
|
|
|
+ <span class="metric-card__label">已归档</span>
|
|
|
+ <strong>{{ archived.length }}</strong>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<div v-if="periods.length === 0" class="empty-state">
|
|
|
<el-empty description="暂无考核周期">
|
|
|
<template #extra>
|
|
|
@@ -234,6 +253,7 @@ const upcoming = computed(() => periods.value.filter(p => p.status !== 'ARCHIVED
|
|
|
|
|
|
// Sub-groups within 进行中
|
|
|
const executing = computed(() => active.value.filter(p => p.status === 'EXECUTING' || p.status === 'ASSESSING'))
|
|
|
+const assessing = computed(() => active.value.filter(p => p.status === 'ASSESSING'))
|
|
|
const okrAlign = computed(() => active.value.filter(p => p.status === 'OKR_ALIGN'))
|
|
|
const drafts = computed(() => active.value.filter(p => p.status === 'DRAFT'))
|
|
|
|
|
|
@@ -321,11 +341,10 @@ function statusGuide(p) {
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
-.page { width: 100%; max-width: 960px; }
|
|
|
-.page-hero { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 24px; }
|
|
|
-.hero-info h2 { font-size: 28px; font-weight: 700; color: #1a1a2e; margin: 0; }
|
|
|
-.hero-info p { font-size: 14px; color: #888; margin: 4px 0 0; }
|
|
|
-.empty-state { display: flex; align-items: center; justify-content: center; min-height: 300px; background: #fff; border-radius: 12px; }
|
|
|
+.period-workbench { max-width: 960px; }
|
|
|
+.page-hero { margin-bottom: 18px; }
|
|
|
+.period-metrics { margin-bottom: 18px; }
|
|
|
+.empty-state { min-height: 300px; }
|
|
|
.empty-hint { font-size: 13px; color: #bbb; }
|
|
|
|
|
|
/* Tabs */
|
|
|
@@ -339,7 +358,7 @@ function statusGuide(p) {
|
|
|
/* Category */
|
|
|
.category { margin-bottom: 32px; }
|
|
|
.cat-head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
|
|
|
-.cat-badge { padding: 5px 16px; border-radius: 16px; font-size: 14px; font-weight: 700; color: #fff; }
|
|
|
+.cat-badge { padding: 5px 16px; border-radius: 8px; font-size: 14px; font-weight: 700; color: #fff; }
|
|
|
.cat-badge.active { background: #2b1f99; }
|
|
|
.cat-badge.upcoming { background: #909399; }
|
|
|
.cat-badge.archived { background: #b0b4ba; }
|