- Database schema with 31 tables for 4-card system - LLM API integration (Gemini, DeepSeek, OpenAI) - Error handling system with modal component - Connection test UI for LLM services - Environment configuration files - Complete database documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1772 lines
57 KiB
HTML
1772 lines
57 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-TW">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>績效管理系統 - 四卡循環 v1.1</title>
|
||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@300;400;500;600;700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||
<style>
|
||
:root {
|
||
--primary: #1e40af;
|
||
--primary-light: #3b82f6;
|
||
--primary-50: #eff6ff;
|
||
--success: #059669;
|
||
--success-light: #10b981;
|
||
--success-50: #ecfdf5;
|
||
--warning: #f59e0b;
|
||
--warning-50: #fffbeb;
|
||
--danger: #dc2626;
|
||
--danger-50: #fef2f2;
|
||
--purple: #7c3aed;
|
||
--purple-50: #f5f3ff;
|
||
--slate-50: #f8fafc;
|
||
--slate-100: #f1f5f9;
|
||
--slate-200: #e2e8f0;
|
||
--slate-300: #cbd5e1;
|
||
--slate-400: #94a3b8;
|
||
--slate-500: #64748b;
|
||
--slate-600: #475569;
|
||
--slate-700: #334155;
|
||
--slate-800: #1e293b;
|
||
--slate-900: #0f172a;
|
||
}
|
||
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family: 'Noto Sans TC', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
||
background: var(--slate-50);
|
||
color: var(--slate-800);
|
||
line-height: 1.6;
|
||
}
|
||
|
||
/* Header */
|
||
.header {
|
||
background: linear-gradient(135deg, var(--slate-900), var(--slate-800));
|
||
color: white;
|
||
padding: 0.875rem 1.5rem;
|
||
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 100;
|
||
}
|
||
|
||
.header-content {
|
||
max-width: 1440px;
|
||
margin: 0 auto;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.logo-section {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 1rem;
|
||
}
|
||
|
||
.logo-icon {
|
||
width: 42px;
|
||
height: 42px;
|
||
background: linear-gradient(135deg, #60a5fa, #3b82f6);
|
||
border-radius: 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 1.25rem;
|
||
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
|
||
}
|
||
|
||
.logo-text h1 {
|
||
font-size: 1.125rem;
|
||
font-weight: 700;
|
||
letter-spacing: -0.5px;
|
||
}
|
||
|
||
.logo-text p {
|
||
font-size: 0.65rem;
|
||
color: var(--slate-400);
|
||
}
|
||
|
||
.header-actions {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
}
|
||
|
||
.lang-switch {
|
||
display: flex;
|
||
background: var(--slate-700);
|
||
border-radius: 8px;
|
||
padding: 2px;
|
||
font-size: 0.75rem;
|
||
}
|
||
|
||
.lang-btn {
|
||
padding: 0.375rem 0.75rem;
|
||
border: none;
|
||
background: transparent;
|
||
color: var(--slate-400);
|
||
cursor: pointer;
|
||
border-radius: 6px;
|
||
transition: all 0.2s;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.lang-btn.active {
|
||
background: var(--primary);
|
||
color: white;
|
||
}
|
||
|
||
.notification-btn {
|
||
position: relative;
|
||
padding: 0.5rem;
|
||
background: transparent;
|
||
border: none;
|
||
color: white;
|
||
cursor: pointer;
|
||
border-radius: 8px;
|
||
transition: background 0.2s;
|
||
}
|
||
|
||
.notification-btn:hover {
|
||
background: var(--slate-700);
|
||
}
|
||
|
||
.notification-badge {
|
||
position: absolute;
|
||
top: 4px;
|
||
right: 4px;
|
||
width: 8px;
|
||
height: 8px;
|
||
background: #ef4444;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.user-profile {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.625rem;
|
||
padding-left: 0.75rem;
|
||
border-left: 1px solid var(--slate-700);
|
||
}
|
||
|
||
.user-avatar {
|
||
width: 34px;
|
||
height: 34px;
|
||
background: linear-gradient(135deg, #fbbf24, #f97316);
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-weight: 700;
|
||
font-size: 0.8rem;
|
||
}
|
||
|
||
.user-info .name {
|
||
font-weight: 600;
|
||
font-size: 0.8rem;
|
||
}
|
||
|
||
.user-info .role {
|
||
font-size: 0.65rem;
|
||
color: var(--slate-400);
|
||
}
|
||
|
||
/* Main Container */
|
||
.main-container {
|
||
max-width: 1440px;
|
||
margin: 0 auto;
|
||
padding: 1.5rem;
|
||
}
|
||
|
||
/* Period Selector */
|
||
.period-bar {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 1.25rem;
|
||
}
|
||
|
||
.period-selector {
|
||
display: flex;
|
||
gap: 0.5rem;
|
||
}
|
||
|
||
.period-btn {
|
||
padding: 0.5rem 1rem;
|
||
border: 1px solid var(--slate-300);
|
||
background: white;
|
||
border-radius: 8px;
|
||
font-size: 0.8rem;
|
||
font-weight: 500;
|
||
color: var(--slate-600);
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
}
|
||
|
||
.period-btn:hover {
|
||
border-color: var(--primary-light);
|
||
color: var(--primary);
|
||
}
|
||
|
||
.period-btn.active {
|
||
background: var(--primary);
|
||
border-color: var(--primary);
|
||
color: white;
|
||
}
|
||
|
||
.period-info {
|
||
font-size: 0.8rem;
|
||
color: var(--slate-500);
|
||
}
|
||
|
||
.period-info strong {
|
||
color: var(--slate-700);
|
||
}
|
||
|
||
/* Progress Stepper */
|
||
.stepper-container {
|
||
background: white;
|
||
border-radius: 16px;
|
||
padding: 1.25rem 1.5rem;
|
||
margin-bottom: 1.5rem;
|
||
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
|
||
border: 1px solid var(--slate-200);
|
||
}
|
||
|
||
.stepper-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 1.25rem;
|
||
}
|
||
|
||
.stepper-header h2 {
|
||
font-size: 0.8rem;
|
||
font-weight: 600;
|
||
color: var(--slate-600);
|
||
}
|
||
|
||
.stepper-header span {
|
||
font-size: 0.75rem;
|
||
color: var(--slate-500);
|
||
}
|
||
|
||
.stepper {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
position: relative;
|
||
padding: 0 3rem;
|
||
}
|
||
|
||
.stepper::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 22px;
|
||
left: 100px;
|
||
right: 100px;
|
||
height: 3px;
|
||
background: var(--slate-200);
|
||
border-radius: 2px;
|
||
}
|
||
|
||
.stepper::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 22px;
|
||
left: 100px;
|
||
width: calc(50% - 50px);
|
||
height: 3px;
|
||
background: linear-gradient(90deg, var(--success), var(--success-light));
|
||
border-radius: 2px;
|
||
}
|
||
|
||
.step {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
position: relative;
|
||
z-index: 1;
|
||
cursor: pointer;
|
||
transition: transform 0.2s;
|
||
}
|
||
|
||
.step:hover {
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
.step-icon {
|
||
width: 46px;
|
||
height: 46px;
|
||
border-radius: 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 1.25rem;
|
||
margin-bottom: 0.625rem;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.step.completed .step-icon {
|
||
background: linear-gradient(135deg, var(--success), var(--success-light));
|
||
box-shadow: 0 4px 12px rgba(5, 150, 105, 0.35);
|
||
color: white;
|
||
}
|
||
|
||
.step.active .step-icon {
|
||
background: linear-gradient(135deg, var(--primary), var(--primary-light));
|
||
box-shadow: 0 4px 12px rgba(30, 64, 175, 0.35), 0 0 0 3px rgba(59, 130, 246, 0.2);
|
||
color: white;
|
||
}
|
||
|
||
.step.pending .step-icon {
|
||
background: var(--slate-200);
|
||
color: var(--slate-400);
|
||
}
|
||
|
||
.step-title {
|
||
font-size: 0.825rem;
|
||
font-weight: 600;
|
||
color: var(--slate-700);
|
||
margin-bottom: 0.125rem;
|
||
}
|
||
|
||
.step.active .step-title {
|
||
color: var(--primary);
|
||
}
|
||
|
||
.step-subtitle {
|
||
font-size: 0.65rem;
|
||
color: var(--slate-400);
|
||
margin-bottom: 0.375rem;
|
||
}
|
||
|
||
.step-status {
|
||
font-size: 0.65rem;
|
||
padding: 0.2rem 0.625rem;
|
||
border-radius: 20px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.step.completed .step-status {
|
||
background: #d1fae5;
|
||
color: #065f46;
|
||
}
|
||
|
||
.step.active .step-status {
|
||
background: #dbeafe;
|
||
color: #1e40af;
|
||
}
|
||
|
||
.step.pending .step-status {
|
||
background: var(--slate-100);
|
||
color: var(--slate-500);
|
||
}
|
||
|
||
/* Content Grid */
|
||
.content-grid {
|
||
display: grid;
|
||
grid-template-columns: 240px 1fr 300px;
|
||
gap: 1.5rem;
|
||
}
|
||
|
||
/* Sidebar */
|
||
.sidebar {
|
||
position: sticky;
|
||
top: 80px;
|
||
height: fit-content;
|
||
}
|
||
|
||
.sidebar-card {
|
||
background: white;
|
||
border-radius: 16px;
|
||
overflow: hidden;
|
||
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
|
||
border: 1px solid var(--slate-200);
|
||
}
|
||
|
||
.sidebar-header {
|
||
background: linear-gradient(135deg, var(--slate-800), var(--slate-700));
|
||
color: white;
|
||
padding: 0.875rem 1rem;
|
||
font-weight: 600;
|
||
font-size: 0.85rem;
|
||
}
|
||
|
||
.sidebar-nav {
|
||
padding: 0.375rem;
|
||
}
|
||
|
||
.nav-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.625rem;
|
||
padding: 0.75rem 0.875rem;
|
||
border-radius: 10px;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
margin-bottom: 0.125rem;
|
||
border: none;
|
||
background: transparent;
|
||
width: 100%;
|
||
text-align: left;
|
||
font-size: 0.8rem;
|
||
font-weight: 500;
|
||
color: var(--slate-600);
|
||
}
|
||
|
||
.nav-item:hover {
|
||
background: var(--slate-50);
|
||
}
|
||
|
||
.nav-item.active {
|
||
background: var(--primary-50);
|
||
color: var(--primary);
|
||
}
|
||
|
||
.nav-icon {
|
||
width: 32px;
|
||
height: 32px;
|
||
border-radius: 8px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: var(--slate-100);
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.nav-item.active .nav-icon {
|
||
background: #dbeafe;
|
||
}
|
||
|
||
.nav-check {
|
||
margin-left: auto;
|
||
color: var(--success);
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.sidebar-divider {
|
||
height: 1px;
|
||
background: var(--slate-200);
|
||
margin: 0.5rem;
|
||
}
|
||
|
||
/* Main Panel */
|
||
.main-panel {
|
||
background: white;
|
||
border-radius: 16px;
|
||
overflow: hidden;
|
||
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
|
||
border: 1px solid var(--slate-200);
|
||
}
|
||
|
||
.panel-header {
|
||
padding: 1.25rem 1.5rem;
|
||
background: linear-gradient(135deg, var(--slate-50), white);
|
||
border-bottom: 1px solid var(--slate-200);
|
||
}
|
||
|
||
.panel-header-content {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.panel-title-section {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.875rem;
|
||
}
|
||
|
||
.panel-icon {
|
||
width: 46px;
|
||
height: 46px;
|
||
background: var(--primary-50);
|
||
border-radius: 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 1.375rem;
|
||
}
|
||
|
||
.panel-title h2 {
|
||
font-size: 1.2rem;
|
||
font-weight: 700;
|
||
color: var(--slate-800);
|
||
}
|
||
|
||
.panel-title p {
|
||
font-size: 0.75rem;
|
||
color: var(--slate-500);
|
||
}
|
||
|
||
.panel-meta {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 1.5rem;
|
||
}
|
||
|
||
.meta-item {
|
||
text-align: center;
|
||
}
|
||
|
||
.meta-item .label {
|
||
font-size: 0.7rem;
|
||
color: var(--slate-500);
|
||
}
|
||
|
||
.meta-item .value {
|
||
font-size: 1.5rem;
|
||
font-weight: 700;
|
||
color: var(--primary);
|
||
}
|
||
|
||
.progress-ring {
|
||
width: 50px;
|
||
height: 50px;
|
||
}
|
||
|
||
/* Tabs */
|
||
.tabs {
|
||
display: flex;
|
||
padding: 0 1.25rem;
|
||
border-bottom: 1px solid var(--slate-200);
|
||
background: white;
|
||
overflow-x: auto;
|
||
}
|
||
|
||
.tab {
|
||
padding: 0.875rem 1.25rem;
|
||
font-size: 0.8rem;
|
||
font-weight: 500;
|
||
color: var(--slate-500);
|
||
cursor: pointer;
|
||
position: relative;
|
||
transition: color 0.2s;
|
||
border: none;
|
||
background: transparent;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.tab:hover {
|
||
color: var(--slate-700);
|
||
}
|
||
|
||
.tab.active {
|
||
color: var(--primary);
|
||
}
|
||
|
||
.tab.active::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 2px;
|
||
background: var(--primary);
|
||
border-radius: 1px;
|
||
}
|
||
|
||
/* Content Area */
|
||
.content-area {
|
||
padding: 1.25rem;
|
||
max-height: 600px;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
/* Section */
|
||
.section {
|
||
margin-bottom: 1.5rem;
|
||
}
|
||
|
||
.section-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 0.875rem;
|
||
}
|
||
|
||
.section-title {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
font-size: 1rem;
|
||
font-weight: 600;
|
||
color: var(--slate-800);
|
||
}
|
||
|
||
.section-badge {
|
||
font-size: 0.7rem;
|
||
background: var(--slate-100);
|
||
color: var(--slate-500);
|
||
padding: 0.3rem 0.75rem;
|
||
border-radius: 20px;
|
||
}
|
||
|
||
/* KRA Card */
|
||
.kra-card {
|
||
background: linear-gradient(135deg, var(--slate-50), white);
|
||
border: 1px solid var(--slate-200);
|
||
border-radius: 12px;
|
||
padding: 1.25rem;
|
||
margin-bottom: 0.875rem;
|
||
transition: box-shadow 0.3s;
|
||
}
|
||
|
||
.kra-card:hover {
|
||
box-shadow: 0 6px 20px rgba(0,0,0,0.06);
|
||
}
|
||
|
||
.kra-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
margin-bottom: 0.875rem;
|
||
}
|
||
|
||
.kra-badge {
|
||
font-size: 0.65rem;
|
||
font-weight: 600;
|
||
background: var(--primary-50);
|
||
color: var(--primary);
|
||
padding: 0.3rem 0.625rem;
|
||
border-radius: 5px;
|
||
}
|
||
|
||
.kra-title {
|
||
font-size: 0.925rem;
|
||
font-weight: 600;
|
||
margin-top: 0.375rem;
|
||
color: var(--slate-800);
|
||
}
|
||
|
||
.kra-weight {
|
||
font-size: 0.7rem;
|
||
color: var(--slate-500);
|
||
margin-top: 0.25rem;
|
||
}
|
||
|
||
.kra-status {
|
||
font-size: 0.75rem;
|
||
font-weight: 600;
|
||
color: var(--success);
|
||
}
|
||
|
||
.kra-output {
|
||
background: white;
|
||
border: 1px solid var(--slate-200);
|
||
border-radius: 8px;
|
||
padding: 0.875rem;
|
||
margin-bottom: 0.875rem;
|
||
}
|
||
|
||
.kra-output .label {
|
||
font-size: 0.7rem;
|
||
color: var(--slate-500);
|
||
margin-bottom: 0.25rem;
|
||
}
|
||
|
||
.kra-output .value {
|
||
font-size: 0.825rem;
|
||
color: var(--slate-700);
|
||
}
|
||
|
||
/* Dual Rating */
|
||
.rating-section {
|
||
background: var(--slate-50);
|
||
border-radius: 8px;
|
||
padding: 0.875rem;
|
||
}
|
||
|
||
.rating-row {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 1rem;
|
||
}
|
||
|
||
.rating-item {
|
||
background: white;
|
||
border-radius: 8px;
|
||
padding: 0.75rem;
|
||
border: 1px solid var(--slate-200);
|
||
}
|
||
|
||
.rating-item .header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 0.5rem;
|
||
}
|
||
|
||
.rating-item .type {
|
||
font-size: 0.7rem;
|
||
font-weight: 600;
|
||
padding: 0.2rem 0.5rem;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.rating-item .type.self {
|
||
background: var(--warning-50);
|
||
color: #b45309;
|
||
}
|
||
|
||
.rating-item .type.manager {
|
||
background: var(--success-50);
|
||
color: #047857;
|
||
}
|
||
|
||
.rating-item .percentage {
|
||
font-size: 1rem;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.rating-item .percentage.self {
|
||
color: var(--warning);
|
||
}
|
||
|
||
.rating-item .percentage.manager {
|
||
color: var(--success);
|
||
}
|
||
|
||
.progress-track {
|
||
height: 8px;
|
||
background: var(--slate-200);
|
||
border-radius: 4px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.progress-track .fill {
|
||
height: 100%;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.progress-track .fill.amber {
|
||
background: linear-gradient(90deg, #fbbf24, #f59e0b);
|
||
}
|
||
|
||
.progress-track .fill.green {
|
||
background: linear-gradient(90deg, #34d399, #10b981);
|
||
}
|
||
|
||
/* Add Button */
|
||
.add-btn {
|
||
width: 100%;
|
||
padding: 0.875rem;
|
||
border: 2px dashed var(--slate-300);
|
||
border-radius: 10px;
|
||
background: transparent;
|
||
color: var(--slate-500);
|
||
font-size: 0.825rem;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
}
|
||
|
||
.add-btn:hover {
|
||
border-color: var(--primary-light);
|
||
color: var(--primary);
|
||
background: var(--primary-50);
|
||
}
|
||
|
||
/* Competency Section */
|
||
.competency-card {
|
||
background: linear-gradient(135deg, var(--purple-50), white);
|
||
border: 1px solid #ddd6fe;
|
||
border-radius: 12px;
|
||
padding: 1.25rem;
|
||
}
|
||
|
||
.competency-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
margin-bottom: 0.75rem;
|
||
}
|
||
|
||
.competency-source {
|
||
font-size: 0.65rem;
|
||
background: #ede9fe;
|
||
color: #6d28d9;
|
||
padding: 0.2rem 0.5rem;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.competency-title {
|
||
font-size: 0.925rem;
|
||
font-weight: 600;
|
||
color: var(--slate-800);
|
||
margin-bottom: 0.375rem;
|
||
}
|
||
|
||
.competency-desc {
|
||
font-size: 0.8rem;
|
||
color: var(--slate-500);
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.level-section {
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.level-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 0.625rem;
|
||
}
|
||
|
||
.level-label {
|
||
font-size: 0.75rem;
|
||
font-weight: 500;
|
||
color: var(--slate-600);
|
||
}
|
||
|
||
.level-buttons {
|
||
display: flex;
|
||
gap: 0.375rem;
|
||
}
|
||
|
||
.level-btn {
|
||
flex: 1;
|
||
padding: 0.5rem 0.25rem;
|
||
border-radius: 8px;
|
||
font-size: 0.65rem;
|
||
font-weight: 500;
|
||
border: none;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
background: var(--slate-100);
|
||
color: var(--slate-600);
|
||
}
|
||
|
||
.level-btn:hover {
|
||
background: var(--slate-200);
|
||
}
|
||
|
||
.level-btn.active {
|
||
background: linear-gradient(135deg, var(--purple), #8b5cf6);
|
||
color: white;
|
||
box-shadow: 0 3px 10px rgba(124, 58, 237, 0.3);
|
||
}
|
||
|
||
.level-btn.manager-active {
|
||
background: linear-gradient(135deg, var(--success), var(--success-light));
|
||
color: white;
|
||
box-shadow: 0 3px 10px rgba(5, 150, 105, 0.3);
|
||
}
|
||
|
||
.sbi-card {
|
||
background: white;
|
||
border: 1px solid var(--slate-200);
|
||
border-radius: 10px;
|
||
padding: 1rem;
|
||
}
|
||
|
||
.sbi-card .label {
|
||
font-size: 0.75rem;
|
||
color: var(--slate-500);
|
||
margin-bottom: 0.625rem;
|
||
}
|
||
|
||
.sbi-item {
|
||
font-size: 0.8rem;
|
||
margin-bottom: 0.375rem;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.sbi-item .tag {
|
||
font-weight: 600;
|
||
}
|
||
|
||
.sbi-item .tag.situation { color: var(--primary); }
|
||
.sbi-item .tag.behavior { color: var(--success); }
|
||
.sbi-item .tag.impact { color: var(--purple); }
|
||
|
||
/* Footer */
|
||
.panel-footer {
|
||
padding: 0.875rem 1.25rem;
|
||
background: var(--slate-50);
|
||
border-top: 1px solid var(--slate-200);
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.btn {
|
||
padding: 0.625rem 1.25rem;
|
||
border-radius: 8px;
|
||
font-size: 0.8rem;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
border: none;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.375rem;
|
||
}
|
||
|
||
.btn-ghost {
|
||
background: transparent;
|
||
color: var(--slate-600);
|
||
}
|
||
|
||
.btn-ghost:hover {
|
||
background: var(--slate-200);
|
||
}
|
||
|
||
.btn-secondary {
|
||
background: var(--slate-200);
|
||
color: var(--slate-700);
|
||
}
|
||
|
||
.btn-secondary:hover {
|
||
background: var(--slate-300);
|
||
}
|
||
|
||
.btn-primary {
|
||
background: linear-gradient(135deg, var(--primary), var(--primary-light));
|
||
color: white;
|
||
box-shadow: 0 3px 10px rgba(30, 64, 175, 0.3);
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
transform: translateY(-1px);
|
||
box-shadow: 0 5px 14px rgba(30, 64, 175, 0.35);
|
||
}
|
||
|
||
.btn-group {
|
||
display: flex;
|
||
gap: 0.625rem;
|
||
}
|
||
|
||
/* Right Panel - Dashboard */
|
||
.right-panel {
|
||
position: sticky;
|
||
top: 80px;
|
||
height: fit-content;
|
||
}
|
||
|
||
.dashboard-card {
|
||
background: white;
|
||
border-radius: 16px;
|
||
overflow: hidden;
|
||
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
|
||
border: 1px solid var(--slate-200);
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.dashboard-header {
|
||
padding: 0.875rem 1rem;
|
||
border-bottom: 1px solid var(--slate-200);
|
||
font-weight: 600;
|
||
font-size: 0.85rem;
|
||
color: var(--slate-700);
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
}
|
||
|
||
.dashboard-content {
|
||
padding: 1rem;
|
||
}
|
||
|
||
/* Distribution Chart */
|
||
.distribution-chart {
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.dist-row {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 0.625rem;
|
||
}
|
||
|
||
.dist-label {
|
||
width: 36px;
|
||
font-size: 0.75rem;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.dist-label.a-plus { color: #059669; }
|
||
.dist-label.a { color: #10b981; }
|
||
.dist-label.b-plus { color: #3b82f6; }
|
||
.dist-label.b { color: #f59e0b; }
|
||
.dist-label.c { color: #ef4444; }
|
||
|
||
.dist-bar-container {
|
||
flex: 1;
|
||
height: 20px;
|
||
background: var(--slate-100);
|
||
border-radius: 4px;
|
||
overflow: hidden;
|
||
margin: 0 0.5rem;
|
||
position: relative;
|
||
}
|
||
|
||
.dist-bar {
|
||
height: 100%;
|
||
border-radius: 4px;
|
||
transition: width 0.5s ease;
|
||
}
|
||
|
||
.dist-bar.a-plus { background: linear-gradient(90deg, #059669, #10b981); }
|
||
.dist-bar.a { background: linear-gradient(90deg, #10b981, #34d399); }
|
||
.dist-bar.b-plus { background: linear-gradient(90deg, #3b82f6, #60a5fa); }
|
||
.dist-bar.b { background: linear-gradient(90deg, #f59e0b, #fbbf24); }
|
||
.dist-bar.c { background: linear-gradient(90deg, #ef4444, #f87171); }
|
||
|
||
.dist-suggest {
|
||
position: absolute;
|
||
right: 0;
|
||
top: 0;
|
||
bottom: 0;
|
||
border-left: 2px dashed var(--slate-400);
|
||
}
|
||
|
||
.dist-value {
|
||
width: 40px;
|
||
font-size: 0.75rem;
|
||
text-align: right;
|
||
color: var(--slate-600);
|
||
}
|
||
|
||
.suggest-note {
|
||
font-size: 0.7rem;
|
||
color: var(--slate-500);
|
||
text-align: center;
|
||
margin-top: 0.5rem;
|
||
}
|
||
|
||
/* Quick Stats */
|
||
.quick-stats {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 0.625rem;
|
||
}
|
||
|
||
.stat-item {
|
||
background: var(--slate-50);
|
||
border-radius: 10px;
|
||
padding: 0.875rem;
|
||
text-align: center;
|
||
}
|
||
|
||
.stat-value {
|
||
font-size: 1.375rem;
|
||
font-weight: 700;
|
||
color: var(--slate-800);
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: 0.7rem;
|
||
color: var(--slate-500);
|
||
margin-top: 0.25rem;
|
||
}
|
||
|
||
/* Approval Queue */
|
||
.approval-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
padding: 0.75rem;
|
||
background: var(--slate-50);
|
||
border-radius: 8px;
|
||
margin-bottom: 0.5rem;
|
||
}
|
||
|
||
.approval-avatar {
|
||
width: 32px;
|
||
height: 32px;
|
||
border-radius: 50%;
|
||
background: var(--primary-50);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 0.75rem;
|
||
font-weight: 600;
|
||
color: var(--primary);
|
||
}
|
||
|
||
.approval-info {
|
||
flex: 1;
|
||
}
|
||
|
||
.approval-name {
|
||
font-size: 0.8rem;
|
||
font-weight: 600;
|
||
color: var(--slate-700);
|
||
}
|
||
|
||
.approval-type {
|
||
font-size: 0.7rem;
|
||
color: var(--slate-500);
|
||
}
|
||
|
||
.approval-action {
|
||
font-size: 0.7rem;
|
||
color: var(--primary);
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* Data Flow */
|
||
.data-flow {
|
||
background: white;
|
||
border-radius: 16px;
|
||
padding: 1.5rem;
|
||
margin-top: 1.5rem;
|
||
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
|
||
border: 1px solid var(--slate-200);
|
||
}
|
||
|
||
.flow-title {
|
||
font-size: 0.9rem;
|
||
font-weight: 600;
|
||
color: var(--slate-700);
|
||
margin-bottom: 1rem;
|
||
text-align: center;
|
||
}
|
||
|
||
.flow-cards {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 0.375rem;
|
||
}
|
||
|
||
.flow-card {
|
||
background: linear-gradient(135deg, var(--slate-50), white);
|
||
border: 2px solid var(--slate-200);
|
||
border-radius: 10px;
|
||
padding: 0.75rem 1rem;
|
||
text-align: center;
|
||
transition: all 0.3s;
|
||
flex: 1;
|
||
max-width: 140px;
|
||
}
|
||
|
||
.flow-card:hover {
|
||
border-color: var(--primary-light);
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
.flow-card .icon {
|
||
font-size: 1.25rem;
|
||
margin-bottom: 0.375rem;
|
||
}
|
||
|
||
.flow-card .name {
|
||
font-weight: 600;
|
||
font-size: 0.8rem;
|
||
color: var(--slate-700);
|
||
}
|
||
|
||
.flow-card .desc {
|
||
font-size: 0.65rem;
|
||
color: var(--slate-500);
|
||
}
|
||
|
||
.flow-arrow {
|
||
font-size: 1.125rem;
|
||
color: var(--slate-400);
|
||
}
|
||
|
||
.flow-note {
|
||
text-align: center;
|
||
margin-top: 0.75rem;
|
||
font-size: 0.7rem;
|
||
color: var(--slate-500);
|
||
}
|
||
|
||
/* Responsive */
|
||
@media (max-width: 1280px) {
|
||
.content-grid {
|
||
grid-template-columns: 220px 1fr;
|
||
}
|
||
.right-panel {
|
||
display: none;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 1024px) {
|
||
.content-grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
.sidebar {
|
||
display: none;
|
||
}
|
||
.stepper {
|
||
padding: 0;
|
||
}
|
||
.stepper::before,
|
||
.stepper::after {
|
||
display: none;
|
||
}
|
||
.step-subtitle {
|
||
display: none;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 640px) {
|
||
.panel-header-content {
|
||
flex-direction: column;
|
||
gap: 1rem;
|
||
}
|
||
.rating-row {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
.level-buttons {
|
||
flex-wrap: wrap;
|
||
}
|
||
.level-btn {
|
||
flex: 1 1 45%;
|
||
}
|
||
.period-bar {
|
||
flex-direction: column;
|
||
gap: 0.75rem;
|
||
align-items: flex-start;
|
||
}
|
||
.flow-cards {
|
||
flex-direction: column;
|
||
}
|
||
.flow-arrow {
|
||
transform: rotate(90deg);
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<!-- Header -->
|
||
<header class="header">
|
||
<div class="header-content">
|
||
<div class="logo-section">
|
||
<div class="logo-icon">🏆</div>
|
||
<div class="logo-text">
|
||
<h1>績效管理系統</h1>
|
||
<p>Performance Management System</p>
|
||
</div>
|
||
</div>
|
||
<div class="header-actions">
|
||
<div class="lang-switch">
|
||
<button class="lang-btn active" onclick="switchLang('zh')">繁中</button>
|
||
<button class="lang-btn" onclick="switchLang('en')">EN</button>
|
||
</div>
|
||
<button class="notification-btn">
|
||
<div class="notification-badge"></div>
|
||
<svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"/>
|
||
</svg>
|
||
</button>
|
||
<div class="user-profile">
|
||
<div class="user-avatar">王</div>
|
||
<div class="user-info">
|
||
<div class="name">王小明</div>
|
||
<div class="role">產品部 PM</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Main Container -->
|
||
<div class="main-container">
|
||
<!-- Period Selector -->
|
||
<div class="period-bar">
|
||
<div class="period-selector">
|
||
<button class="period-btn" onclick="setPeriod('q1')">Q1 季度</button>
|
||
<button class="period-btn" onclick="setPeriod('q2')">Q2 季度</button>
|
||
<button class="period-btn" onclick="setPeriod('q3')">Q3 季度</button>
|
||
<button class="period-btn active" onclick="setPeriod('annual')">年度完整</button>
|
||
</div>
|
||
<div class="period-info">
|
||
評核期間:<strong>2024/01/01 - 2024/12/31</strong>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Progress Stepper -->
|
||
<div class="stepper-container">
|
||
<div class="stepper-header">
|
||
<h2>📋 2024 年度績效評核流程 - 單向連動</h2>
|
||
<span>整體進度:65%</span>
|
||
</div>
|
||
<div class="stepper">
|
||
<div class="step completed">
|
||
<div class="step-icon">👤</div>
|
||
<div class="step-title">角色卡</div>
|
||
<div class="step-subtitle">Role Card</div>
|
||
<div class="step-status">已完成</div>
|
||
</div>
|
||
<div class="step completed">
|
||
<div class="step-icon">🎯</div>
|
||
<div class="step-title">能力卡</div>
|
||
<div class="step-subtitle">Competency</div>
|
||
<div class="step-status">已完成</div>
|
||
</div>
|
||
<div class="step active">
|
||
<div class="step-icon">📊</div>
|
||
<div class="step-title">績效卡</div>
|
||
<div class="step-subtitle">Performance</div>
|
||
<div class="step-status">進行中</div>
|
||
</div>
|
||
<div class="step pending">
|
||
<div class="step-icon">🌱</div>
|
||
<div class="step-title">成長卡</div>
|
||
<div class="step-subtitle">Growth</div>
|
||
<div class="step-status">待開始</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Content Grid -->
|
||
<div class="content-grid">
|
||
<!-- Sidebar -->
|
||
<aside class="sidebar">
|
||
<div class="sidebar-card">
|
||
<div class="sidebar-header">📁 快速導航</div>
|
||
<nav class="sidebar-nav">
|
||
<button class="nav-item">
|
||
<div class="nav-icon">👤</div>
|
||
<span>角色卡</span>
|
||
<span class="nav-check">✓</span>
|
||
</button>
|
||
<button class="nav-item">
|
||
<div class="nav-icon">🎯</div>
|
||
<span>能力卡</span>
|
||
<span class="nav-check">✓</span>
|
||
</button>
|
||
<button class="nav-item active">
|
||
<div class="nav-icon">📊</div>
|
||
<span>績效卡</span>
|
||
</button>
|
||
<button class="nav-item">
|
||
<div class="nav-icon">🌱</div>
|
||
<span>成長卡</span>
|
||
</button>
|
||
<div class="sidebar-divider"></div>
|
||
<button class="nav-item">
|
||
<div class="nav-icon">📈</div>
|
||
<span>儀表板</span>
|
||
</button>
|
||
<button class="nav-item">
|
||
<div class="nav-icon">📅</div>
|
||
<span>歷史快照</span>
|
||
</button>
|
||
</nav>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- Main Panel -->
|
||
<main class="main-panel">
|
||
<div class="panel-header">
|
||
<div class="panel-header-content">
|
||
<div class="panel-title-section">
|
||
<div class="panel-icon">📊</div>
|
||
<div class="panel-title">
|
||
<h2>績效卡 - 2024年度完整評核</h2>
|
||
<p>Performance Review Form - Annual</p>
|
||
</div>
|
||
</div>
|
||
<div class="panel-meta">
|
||
<div class="meta-item">
|
||
<div class="label">目標佔比</div>
|
||
<div class="value">70%</div>
|
||
</div>
|
||
<div class="meta-item">
|
||
<div class="label">行為佔比</div>
|
||
<div class="value">30%</div>
|
||
</div>
|
||
<div class="meta-item">
|
||
<div class="label">完成度</div>
|
||
<div class="value">65%</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tabs -->
|
||
<div class="tabs">
|
||
<button class="tab">基本資訊</button>
|
||
<button class="tab active">目標成果</button>
|
||
<button class="tab">行為評估</button>
|
||
<button class="tab">綜合評價</button>
|
||
<button class="tab">主管回饋</button>
|
||
</div>
|
||
|
||
<!-- Content -->
|
||
<div class="content-area">
|
||
<!-- Section 1: Goals & Outcomes -->
|
||
<div class="section">
|
||
<div class="section-header">
|
||
<h3 class="section-title">
|
||
🎯 一、目標與成果 (Goals & Outcomes)
|
||
</h3>
|
||
<span class="section-badge">佔比: 70%</span>
|
||
</div>
|
||
|
||
<!-- KRA Card 1 -->
|
||
<div class="kra-card">
|
||
<div class="kra-header">
|
||
<div>
|
||
<span class="kra-badge">KRA 1</span>
|
||
<h4 class="kra-title">產品上市時程</h4>
|
||
<p class="kra-weight">權重:40%</p>
|
||
</div>
|
||
<span class="kra-status">✓ 已達成</span>
|
||
</div>
|
||
<div class="kra-output">
|
||
<div class="label">具體產出</div>
|
||
<div class="value">Q1 完成 MVP 開發,Q2 Beta 測試上線,獲得 500+ 測試用戶回饋</div>
|
||
</div>
|
||
<div class="rating-section">
|
||
<div class="rating-row">
|
||
<div class="rating-item">
|
||
<div class="header">
|
||
<span class="type self">👤 自評</span>
|
||
<span class="percentage self">80%</span>
|
||
</div>
|
||
<div class="progress-track">
|
||
<div class="fill amber" style="width: 80%"></div>
|
||
</div>
|
||
</div>
|
||
<div class="rating-item">
|
||
<div class="header">
|
||
<span class="type manager">👔 主管評</span>
|
||
<span class="percentage manager">85%</span>
|
||
</div>
|
||
<div class="progress-track">
|
||
<div class="fill green" style="width: 85%"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- KRA Card 2 -->
|
||
<div class="kra-card">
|
||
<div class="kra-header">
|
||
<div>
|
||
<span class="kra-badge">KRA 2</span>
|
||
<h4 class="kra-title">客戶滿意度提升</h4>
|
||
<p class="kra-weight">權重:30%</p>
|
||
</div>
|
||
<span class="kra-status">✓ 超額達成</span>
|
||
</div>
|
||
<div class="kra-output">
|
||
<div class="label">具體產出</div>
|
||
<div class="value">NPS 從 32 提升至 48(目標 45),客戶續約率達 92%</div>
|
||
</div>
|
||
<div class="rating-section">
|
||
<div class="rating-row">
|
||
<div class="rating-item">
|
||
<div class="header">
|
||
<span class="type self">👤 自評</span>
|
||
<span class="percentage self">100%</span>
|
||
</div>
|
||
<div class="progress-track">
|
||
<div class="fill green" style="width: 100%"></div>
|
||
</div>
|
||
</div>
|
||
<div class="rating-item">
|
||
<div class="header">
|
||
<span class="type manager">👔 主管評</span>
|
||
<span class="percentage manager">100%</span>
|
||
</div>
|
||
<div class="progress-track">
|
||
<div class="fill green" style="width: 100%"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<button class="add-btn">+ 新增 KRA(從角色卡連動)</button>
|
||
</div>
|
||
|
||
<!-- Section 2: Behavior Assessment -->
|
||
<div class="section">
|
||
<div class="section-header">
|
||
<h3 class="section-title">
|
||
👥 二、行為與能力評估 (Behavior Assessment)
|
||
</h3>
|
||
<span class="section-badge">佔比: 30%</span>
|
||
</div>
|
||
|
||
<div class="competency-card">
|
||
<div class="competency-header">
|
||
<div>
|
||
<span class="competency-source">📚 職能字典</span>
|
||
<h4 class="competency-title">管理職能:橫向整合力</h4>
|
||
</div>
|
||
</div>
|
||
<p class="competency-desc">整合跨部門資源,建立有效協作關係,達成共同目標</p>
|
||
|
||
<!-- Self Assessment -->
|
||
<div class="level-section">
|
||
<div class="level-header">
|
||
<span class="level-label">👤 自評等級</span>
|
||
</div>
|
||
<div class="level-buttons">
|
||
<button class="level-btn">L1<br>初學新手</button>
|
||
<button class="level-btn">L2<br>基礎應用</button>
|
||
<button class="level-btn active">L3<br>獨立勝任</button>
|
||
<button class="level-btn">L4<br>精通深化</button>
|
||
<button class="level-btn">L5<br>專家引領</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Manager Assessment -->
|
||
<div class="level-section">
|
||
<div class="level-header">
|
||
<span class="level-label">👔 主管評等級</span>
|
||
</div>
|
||
<div class="level-buttons">
|
||
<button class="level-btn">L1<br>初學新手</button>
|
||
<button class="level-btn">L2<br>基礎應用</button>
|
||
<button class="level-btn">L3<br>獨立勝任</button>
|
||
<button class="level-btn manager-active">L4<br>精通深化</button>
|
||
<button class="level-btn">L5<br>專家引領</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="sbi-card">
|
||
<div class="label">📝 評估舉例 (SBI 格式)</div>
|
||
<p class="sbi-item"><span class="tag situation">【情境 Situation】</span> 跨部門產品發布專案中</p>
|
||
<p class="sbi-item"><span class="tag behavior">【行為 Behavior】</span> 主動召開週會,建立共享進度看板,協調資源分配</p>
|
||
<p class="sbi-item"><span class="tag impact">【影響 Impact】</span> 專案準時上線,團隊協作效率提升 30%</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Footer -->
|
||
<div class="panel-footer">
|
||
<button class="btn btn-ghost">💾 暫存草稿</button>
|
||
<div class="btn-group">
|
||
<button class="btn btn-secondary">← 上一步</button>
|
||
<button class="btn btn-primary">送出審批 (主管) →</button>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- Right Panel - Dashboard -->
|
||
<aside class="right-panel">
|
||
<!-- Distribution Card -->
|
||
<div class="dashboard-card">
|
||
<div class="dashboard-header">
|
||
📊 績效等級分佈(建議)
|
||
</div>
|
||
<div class="dashboard-content">
|
||
<div class="distribution-chart">
|
||
<div class="dist-row">
|
||
<span class="dist-label a-plus">A+</span>
|
||
<div class="dist-bar-container">
|
||
<div class="dist-bar a-plus" style="width: 8%"></div>
|
||
<div class="dist-suggest" style="right: 90%"></div>
|
||
</div>
|
||
<span class="dist-value">8%</span>
|
||
</div>
|
||
<div class="dist-row">
|
||
<span class="dist-label a">A</span>
|
||
<div class="dist-bar-container">
|
||
<div class="dist-bar a" style="width: 22%"></div>
|
||
<div class="dist-suggest" style="right: 75%"></div>
|
||
</div>
|
||
<span class="dist-value">22%</span>
|
||
</div>
|
||
<div class="dist-row">
|
||
<span class="dist-label b-plus">B+</span>
|
||
<div class="dist-bar-container">
|
||
<div class="dist-bar b-plus" style="width: 38%"></div>
|
||
<div class="dist-suggest" style="right: 60%"></div>
|
||
</div>
|
||
<span class="dist-value">38%</span>
|
||
</div>
|
||
<div class="dist-row">
|
||
<span class="dist-label b">B</span>
|
||
<div class="dist-bar-container">
|
||
<div class="dist-bar b" style="width: 24%"></div>
|
||
<div class="dist-suggest" style="right: 75%"></div>
|
||
</div>
|
||
<span class="dist-value">24%</span>
|
||
</div>
|
||
<div class="dist-row">
|
||
<span class="dist-label c">C</span>
|
||
<div class="dist-bar-container">
|
||
<div class="dist-bar c" style="width: 8%"></div>
|
||
<div class="dist-suggest" style="right: 90%"></div>
|
||
</div>
|
||
<span class="dist-value">8%</span>
|
||
</div>
|
||
</div>
|
||
<p class="suggest-note">虛線為建議分佈,不強制執行</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Quick Stats -->
|
||
<div class="dashboard-card">
|
||
<div class="dashboard-header">
|
||
📈 快速統計
|
||
</div>
|
||
<div class="dashboard-content">
|
||
<div class="quick-stats">
|
||
<div class="stat-item">
|
||
<div class="stat-value">87%</div>
|
||
<div class="stat-label">目標達成率</div>
|
||
</div>
|
||
<div class="stat-item">
|
||
<div class="stat-value">L3.5</div>
|
||
<div class="stat-label">能力平均</div>
|
||
</div>
|
||
<div class="stat-item">
|
||
<div class="stat-value">3</div>
|
||
<div class="stat-label">KRA 項目</div>
|
||
</div>
|
||
<div class="stat-item">
|
||
<div class="stat-value">5</div>
|
||
<div class="stat-label">職能項目</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Approval Queue -->
|
||
<div class="dashboard-card">
|
||
<div class="dashboard-header">
|
||
✅ 待審批清單
|
||
</div>
|
||
<div class="dashboard-content">
|
||
<div class="approval-item">
|
||
<div class="approval-avatar">李</div>
|
||
<div class="approval-info">
|
||
<div class="approval-name">李小華</div>
|
||
<div class="approval-type">績效卡 - 年度</div>
|
||
</div>
|
||
<span class="approval-action">審批 →</span>
|
||
</div>
|
||
<div class="approval-item">
|
||
<div class="approval-avatar">張</div>
|
||
<div class="approval-info">
|
||
<div class="approval-name">張大明</div>
|
||
<div class="approval-type">成長卡 - IDP</div>
|
||
</div>
|
||
<span class="approval-action">審批 →</span>
|
||
</div>
|
||
<div class="approval-item">
|
||
<div class="approval-avatar">陳</div>
|
||
<div class="approval-info">
|
||
<div class="approval-name">陳小美</div>
|
||
<div class="approval-type">角色卡 - 變更</div>
|
||
</div>
|
||
<span class="approval-action">審批 →</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
</div>
|
||
|
||
<!-- Data Flow Diagram -->
|
||
<div class="data-flow">
|
||
<h3 class="flow-title">🔄 四卡單向連動資料流</h3>
|
||
<div class="flow-cards">
|
||
<div class="flow-card">
|
||
<div class="icon">👤</div>
|
||
<div class="name">角色卡</div>
|
||
<div class="desc">職責・KRA/KPI</div>
|
||
</div>
|
||
<div class="flow-arrow">→</div>
|
||
<div class="flow-card">
|
||
<div class="icon">🎯</div>
|
||
<div class="name">能力卡</div>
|
||
<div class="desc">技能・熟練度</div>
|
||
</div>
|
||
<div class="flow-arrow">→</div>
|
||
<div class="flow-card">
|
||
<div class="icon">📊</div>
|
||
<div class="name">績效卡</div>
|
||
<div class="desc">達成・評分</div>
|
||
</div>
|
||
<div class="flow-arrow">→</div>
|
||
<div class="flow-card">
|
||
<div class="icon">🌱</div>
|
||
<div class="name">成長卡</div>
|
||
<div class="desc">IDP・追蹤</div>
|
||
</div>
|
||
</div>
|
||
<p class="flow-note">↺ 基本資訊自動帶入連動 | 週期保留快照歸檔</p>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// Language Switch
|
||
function switchLang(lang) {
|
||
document.querySelectorAll('.lang-btn').forEach(btn => {
|
||
btn.classList.remove('active');
|
||
});
|
||
event.target.classList.add('active');
|
||
|
||
if (lang === 'en') {
|
||
alert('English version coming in Phase 2!');
|
||
}
|
||
}
|
||
|
||
// Period Switch
|
||
function setPeriod(period) {
|
||
document.querySelectorAll('.period-btn').forEach(btn => {
|
||
btn.classList.remove('active');
|
||
});
|
||
event.target.classList.add('active');
|
||
|
||
const periodInfo = document.querySelector('.period-info strong');
|
||
if (period === 'annual') {
|
||
periodInfo.textContent = '2024/01/01 - 2024/12/31';
|
||
} else if (period === 'q1') {
|
||
periodInfo.textContent = '2024/01/01 - 2024/03/31';
|
||
} else if (period === 'q2') {
|
||
periodInfo.textContent = '2024/04/01 - 2024/06/30';
|
||
} else if (period === 'q3') {
|
||
periodInfo.textContent = '2024/07/01 - 2024/09/30';
|
||
}
|
||
}
|
||
|
||
// Tab switching
|
||
document.querySelectorAll('.tab').forEach(tab => {
|
||
tab.addEventListener('click', function() {
|
||
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
|
||
this.classList.add('active');
|
||
});
|
||
});
|
||
|
||
// Level button selection
|
||
document.querySelectorAll('.level-section').forEach(section => {
|
||
section.querySelectorAll('.level-btn').forEach(btn => {
|
||
btn.addEventListener('click', function() {
|
||
const buttons = section.querySelectorAll('.level-btn');
|
||
const isManager = section.querySelector('.level-label').textContent.includes('主管');
|
||
|
||
buttons.forEach(b => {
|
||
b.classList.remove('active', 'manager-active');
|
||
});
|
||
|
||
if (isManager) {
|
||
this.classList.add('manager-active');
|
||
} else {
|
||
this.classList.add('active');
|
||
}
|
||
});
|
||
});
|
||
});
|
||
|
||
// Nav item selection
|
||
document.querySelectorAll('.nav-item').forEach(item => {
|
||
item.addEventListener('click', function() {
|
||
document.querySelectorAll('.nav-item').forEach(i => i.classList.remove('active'));
|
||
this.classList.add('active');
|
||
});
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|