<template>
  <div class="dashboard-page">
    <!-- 顶部导航条 -->
    <div class="dash-header">
      <div class="header-left">
        <el-tag size="large" :type="roleTagType">{{ roleLabel }}驾驶舱</el-tag>
        <el-radio-group v-model="periodType" size="small" @change="onPeriodChange">
          <el-radio-button value="month">本月</el-radio-button>
          <el-radio-button value="quarter">本季</el-radio-button>
          <el-radio-button value="year">本年</el-radio-button>
          <el-radio-button value="custom">自定义</el-radio-button>
        </el-radio-group>
        <el-date-picker
          v-if="periodType === 'custom'"
          v-model="customStart"
          type="date"
          placeholder="开始日期"
          value-format="YYYY-MM-DD"
          size="small"
          style="width:140px"
          @change="onCustomRangeChange"
        />
        <span v-if="periodType === 'custom'" style="color:#999;">至</span>
        <el-date-picker
          v-if="periodType === 'custom'"
          v-model="customEnd"
          type="date"
          placeholder="结束日期"
          value-format="YYYY-MM-DD"
          size="small"
          style="width:140px"
          @change="onCustomRangeChange"
        />
      </div>
      <div class="header-right">
        <span v-if="dataRange" class="data-range">📅 {{ dataRange }}</span>
        <el-button text size="small" @click="showSidebar = !showSidebar; if(showSidebar) refreshAnalysis()">
          {{ showSidebar ? '收起AI' : '🤖 AI分析' }}
        </el-button>
      </div>
    </div>

    <!-- ====== CEO视图 ====== -->
    <template v-if="userRole === 'ceo'">
      <!-- 摘要卡片行 -->
      <div class="summary-row">
        <div class="stat-card blue" @click="$router.push('/kpis')" style="cursor:pointer;"><div class="stat-val">{{ summary.kpi_total }}</div><div class="stat-label">KPI总数</div><div class="stat-sub click-hint">点击查看详情</div></div>
        <div class="stat-card red" @click="$router.push('/alerts')" style="cursor:pointer;"><div class="stat-val">{{ redAlerts }}</div><div class="stat-label">紧急异常</div><div class="stat-sub">待处理 {{ alerts.length }} 条</div></div>
        <div class="stat-card green" @click="$router.push('/kpis')" style="cursor:pointer;"><div class="stat-val">{{ greenKpis }}</div><div class="stat-label">正常</div></div>
        <div class="stat-card yellow" @click="$router.push('/alerts')" style="cursor:pointer;"><div class="stat-val">{{ yellowKpis }}</div><div class="stat-label">预警中</div></div>
        <div class="stat-card" :class="syncCardClass" @click="$router.push('/data')" style="cursor:pointer;">
          <div class="stat-val" style="font-size:14px;line-height:1.4;">{{ syncStatusText }}</div>
          <div class="stat-label">数据同步</div>
          <div class="stat-sub">{{ syncTimeText }}</div>
        </div>
      </div>

      <!-- 主内容区：双栏 -->
      <div class="ceo-main">
        <!-- 左栏 -->
        <div class="ceo-left">
          <!-- 异常高亮区 -->
          <div v-if="alerts.length > 0" class="alert-spotlight">
            <div class="spotlight-title">🔴 需要关注的异常</div>
            <div class="spotlight-list">
              <div v-for="a in alerts" :key="a.id" class="spotlight-item"
                   :class="'level-' + a.alert_level"
                   @click="$router.push('/alerts')">
                <span class="spotlight-badge">{{ a.alert_level === 'red' ? '紧急' : '预警' }}</span>
                <span class="spotlight-msg">{{ a.alert_message }}</span>
                <el-icon><ArrowRight /></el-icon>
              </div>
            </div>
          </div>

          <!-- KPI矩阵 — 四维度网格 -->
          <div class="matrix-grid">
            <div v-for="dim in kpiByDim" :key="dim.name" class="dim-card">
              <div class="dim-head" :style="{ background: dim.color }">
                <span class="dim-icon">{{ dim.icon }}</span>
                <span class="dim-name">{{ dim.name }}</span>
                <span class="dim-count">{{ dim.kpis.length }}</span>
              </div>
              <div class="dim-body">
                <div v-for="k in dim.kpis" :key="k.id" class="kpi-row" @click="showKPIDetail(k)">
                  <div class="kpi-row-top">
                    <span class="kpi-row-name">{{ k.kpi_name }}</span>
                    <span class="kpi-row-badge" :style="{ color: alertColor(k.alert_level) }">{{ alertIcon(k.alert_level) }}</span>
                  </div>
                  <div class="kpi-row-btm">
                    <span class="kpi-row-val">{{ fmtValue(k.actual_value, k.kpi_name) }}</span>
                    <span class="kpi-row-target">/ {{ k.target_value ?? '-' }}</span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <!-- 右栏 -->
        <div class="ceo-right">
          <!-- 预测卡片 -->
          <div v-if="predictions.length > 0" class="right-card">
            <div class="right-card-title">🔮 下月预测</div>
            <div class="pred-list">
              <div v-for="p in predictions" :key="p.kpi_id" class="pred-row" :class="'trend-' + p.trend"
                   @click="$router.push('/predict')" style="cursor:pointer;">
                <div class="pred-row-top">
                  <span class="pred-name">{{ p.kpi_name }}</span>
                  <span class="pred-arrow">{{ {up:'↑',down:'↓',stable:'→'}[p.trend] }}</span>
                </div>
                <div class="pred-row-val">
                  <span class="pred-cur">{{ fmtValue(p.last_value, p.kpi_code) }}</span>
                  <span class="pred-sep">→</span>
                  <span class="pred-fut" :style="{ color: p.trend === 'down' ? '#f56c6c' : '#67c23a' }">
                    {{ fmtValue(p.predicted_value, p.kpi_code) }}
                  </span>
                </div>
                <div class="pred-row-info">
                  <span class="pred-conf" :class="p.confidence">{{ {high:'高',medium:'中',low:'低'}[p.confidence] }}置信</span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </template>

    <!-- ====== 业务视图 ====== -->
    <template v-if="userRole === 'business'">
      <div class="summary-row">
        <div class="stat-card blue"><div class="stat-val">{{ myKpis.length }}</div><div class="stat-label">我的KPI</div></div>
        <div class="stat-card red"><div class="stat-val">{{ myKpis.filter((k:any)=>k.alert_level==='red').length }}</div><div class="stat-label">需关注</div></div>
      </div>
      <div v-if="myKpis.length === 0" class="empty-state">暂无关联到你的KPI</div>
      <div v-else class="kpi-card-grid">
        <div v-for="k in myKpis" :key="k.id" class="kpi-card-item" @click="showKPIDetail(k)">
          <div class="card-item-head">
            <span class="item-name">{{ k.kpi_name }}</span>
            <el-tag size="small" :type="alertType(k.alert_level)">{{ alertIcon(k.alert_level) }}</el-tag>
          </div>
          <div class="card-item-val" :style="{ color: alertColor(k.alert_level) }">
            {{ fmtValue(k.actual_value, k.kpi_name) }}
            <span class="item-unit">{{ k.unit }}</span>
          </div>
          <div class="card-item-target">目标 {{ k.target_value ?? '-' }}</div>
          <div class="card-item-trend" v-if="k.trend && k.trend.length >= 2">
            <span v-for="(t, i) in k.trend.slice(-3)" :key="i" class="tdot" :style="{ background: trendColor(t.value, k) }"></span>
            <span class="trend-hint">近3月</span>
          </div>
        </div>
      </div>
    </template>

    <!-- ====== 财务视图 ====== -->
    <template v-if="userRole === 'finance'">
      <div class="summary-row">
        <div class="stat-card blue" @click="$router.push('/deviations')" style="cursor:pointer;"><div class="stat-val">{{ finSummary.total_sales ? fmtValue(finSummary.total_sales, 'SALES_TOTAL') : '-' }}</div><div class="stat-label">本月销售额</div></div>
        <div class="stat-card" :class="(finSummary.gross_profit_rate ?? 0) < 0 ? 'red' : 'green'" @click="$router.push('/deviations')" style="cursor:pointer;">
          <div class="stat-val">{{ finSummary.gross_profit_rate != null ? finSummary.gross_profit_rate.toFixed(1) + '%' : '-' }}</div>
          <div class="stat-label">毛利率</div>
        </div>
        <div class="stat-card yellow" @click="$router.push('/deviations')" style="cursor:pointer;"><div class="stat-val">{{ finSummary.receivable_turnover != null ? finSummary.receivable_turnover.toFixed(2) : '-' }}</div><div class="stat-label">应收周转率</div></div>
      </div>
      <div class="kpi-card-grid">
        <div v-for="k in finKpis" :key="k.id" class="kpi-card-item wide" @click="showKPIDetail(k)">
          <div class="card-item-head">
            <span class="item-name">{{ k.kpi_name }}</span>
            <el-tag size="small" :type="alertType(k.alert_level)">{{ alertIcon(k.alert_level) }}</el-tag>
          </div>
          <div class="card-item-val" :style="{ color: alertColor(k.alert_level) }">
            {{ k.actual_value != null ? fmtValue(k.actual_value, k.kpi_code) : '-' }}
            <span class="item-unit">{{ k.unit }}</span>
          </div>
          <div class="trend-bars" v-if="k.trend && k.trend.length >= 2">
            <div v-for="(t, i) in k.trend" :key="i" class="tbar-wrap" :title="t.period + ': ' + (t.value ?? '-')">
              <div class="tbar" :style="{ height: barHeight(t.value, k.trend) + '%' }"></div>
              <div class="tbar-label">{{ t.period.slice(-2) }}</div>
            </div>
          </div>
        </div>
      </div>
    </template>

    <!-- ====== IT视图 ====== -->
    <template v-if="userRole === 'it'">
      <div class="summary-row">
        <div class="stat-card blue"><div class="stat-val">{{ summary.kpi_total }}</div><div class="stat-label">活跃KPI</div></div>
        <div class="stat-card green"><div class="stat-val">{{ enabledChannels }}</div><div class="stat-label">通知渠道</div></div>
        <div class="stat-card gray"><div class="stat-val">{{ erpStatus }}</div><div class="stat-label">ERP同步</div></div>
      </div>
      <el-card shadow="never" class="sys-card">
        <template #header><span>⚙️ 系统概览</span></template>
        <el-descriptions :column="3" border size="small">
          <el-descriptions-item label="后端服务">{{ backendStatus }}</el-descriptions-item>
          <el-descriptions-item label="数据库">{{ dbStatus }}</el-descriptions-item>
          <el-descriptions-item label="ERP网关">{{ erpGatewayStatus }}</el-descriptions-item>
          <el-descriptions-item label="定时任务">每日1:00</el-descriptions-item>
          <el-descriptions-item label="预警推送">企微应用</el-descriptions-item>
          <el-descriptions-item label="Redis">{{ redisStatus }}</el-descriptions-item>
        </el-descriptions>
      </el-card>
    </template>

    <!-- AI分析浮窗 -->
    <div v-if="showSidebar" class="ai-panel">
      <div class="ai-head"><span>🤖 AI 分析</span><el-button text size="small" @click="showSidebar = false">✕</el-button></div>
      <div class="ai-body">
        <div v-if="aiLoading" class="ai-loading"><el-icon class="is-loading" :size="20"><Loading /></el-icon><p>分析中...</p></div>
        <div v-else-if="aiAnalysis" class="ai-content" v-html="renderMd(aiAnalysis)"></div>
        <el-empty v-else description="暂无分析" />
      </div>
      <div class="ai-foot"><el-button size="small" type="primary" @click="refreshAnalysis" :loading="aiLoading">刷新</el-button></div>
    </div>

    <!-- KPI详情弹窗 -->
    <el-dialog v-model="showDetail" :title="selectedKPI?.kpi_name" width="500px">
      <div v-if="selectedKPI">
        <div class="dlg-summary">
          <el-tag :type="alertType(selectedKPI.alert_level)" size="large">
            {{ periodType === 'month' ? '本月' : periodType }}值: {{ fmtValue(selectedKPI.actual_value, selectedKPI.kpi_name) }}
          </el-tag>
          <span>目标: {{ selectedKPI.target_value }} | {{ selectedKPI.responsible_dept || '' }}</span>
        </div>
        <div class="kpi-bar large" v-if="selectedKPI.target_value && selectedKPI.actual_value">
          <div class="bar-fill" :style="{ width: Math.min(100, selectedKPI.actual_value/selectedKPI.target_value*100)+'%', background: alertColor(selectedKPI.alert_level) }"></div>
        </div>
        <el-divider />
        <div v-if="selectedKPIDetail" class="analysis-content" v-html="renderMd(selectedKPIDetail)"></div>
        <el-button v-else type="primary" plain @click="loadKPIAnalysis" :loading="loadingDetail">AI分析此KPI</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { Loading, ArrowRight } from '@element-plus/icons-vue'
import { dashboardApi, alertApi } from '../api/index'
import axios from 'axios'

const router = useRouter()

const userStr = localStorage.getItem('cma_user') || '{}'
const user = JSON.parse(userStr)
const userRole = ref(user.role || 'ceo')

const roleTagType = computed(() => ({ ceo: 'danger', finance: 'warning', business: 'primary', it: 'info' }[userRole.value] || ''))
const roleLabel = computed(() => ({ ceo: '总经理', finance: '财务部', business: '业务部', it: 'IT部' }[userRole.value] || userRole.value))

const periodType = ref('month')
const customStart = ref('')
const customEnd = ref('')
const dataRange = ref('')
const showSidebar = ref(false)
const showDetail = ref(false)
const selectedKPI = ref<any>(null)
const selectedKPIDetail = ref('')
const loadingDetail = ref(false)
const predictions = ref<any[]>([])
const kpis = ref<any[]>([])
const alerts = ref<any[]>([])
const summary = ref({ kpi_total: 0, alert_count: 0, sync_status: { status: 'unknown', last_sync: null, detail: '' } })

// 同步状态卡片样式和文字
const syncCardClass = computed(() => {
  const s = summary.value.sync_status?.status
  if (s === 'success') return 'green'
  if (s === 'failed') return 'red'
  return 'blue'
})
const syncStatusText = computed(() => {
  const s = summary.value.sync_status?.status
  if (s === 'success') return '✅ 同步正常'
  if (s === 'failed') return '❌ 同步失败'
  return '⏳ 待同步'
})
const syncTimeText = computed(() => {
  const raw = summary.value.sync_status?.last_sync || ''
  // 从日志行提取时间 2026-05-27 01:00:02
  const m = raw.match(/(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2})/)
  if (m) return m[1]
  return raw.substring(0, 20) || '--'
})
const redAlerts = computed(() => alerts.value.filter((a: any) => a.alert_level === 'red').length)
const greenKpis = computed(() => kpis.value.filter((k: any) => k.alert_level === 'green' || k.alert_level === 'none').length)
const yellowKpis = computed(() => kpis.value.filter((k: any) => k.alert_level === 'yellow' || k.alert_level === 'red').length)
const myKpis = ref<any[]>([])
const finKpis = ref<any[]>([])
const finSummary = ref<any>({})
const enabledChannels = ref(0)
const aiAnalysis = ref('')
const aiLoading = ref(false)

const aiApi = axios.create({ baseURL: '/api/cma', timeout: 30000 })
aiApi.interceptors.request.use((config: any) => {
  const token = localStorage.getItem('cma_token')
  if (token) config.headers.Authorization = `Bearer ${token}`
  return config
})

const dimConfig: Record<string, { icon: string; color: string; name: string }> = {
  finance: { icon: '💰', color: '#409eff', name: '财务维度' },
  customer: { icon: '👥', color: '#67c23a', name: '客户维度' },
  process: { icon: '⚙️', color: '#e6a23c', name: '内部流程' },
  learning: { icon: '📚', color: '#f56c6c', name: '学习成长' },
}

const kpiByDim = computed(() => {
  const dims: Record<string, any[]> = {}
  kpis.value.forEach((k: any) => {
    const d = k.dimension || 'other'
    if (!dims[d]) dims[d] = []
    dims[d].push(k)
  })
  return Object.entries(dims).map(([key, kpis]) => ({
    name: dimConfig[key]?.name || key,
    icon: dimConfig[key]?.icon || '📊',
    color: dimConfig[key]?.color || '#909399',
    kpis,
  }))
})

function fmtValue(v: any, tag?: string): string {
  if (v == null) return '-'
  const n = Number(v)
  if (isNaN(n)) return String(v)
  if (tag === 'SALES_TOTAL') return '¥' + (n / 10000).toFixed(0) + '万'
  if (tag && (tag.includes('率') || tag.includes('RATE') || tag.includes('ratio') || tag.includes('RATIO'))) return n.toFixed(1) + '%'
  if (Math.abs(n) >= 10000) return (n / 10000).toFixed(1) + '万'
  if (Number.isInteger(n)) return n.toLocaleString()
  return n.toFixed(2)
}
function alertType(level: string): string {
  return level === 'red' ? 'danger' : level === 'yellow' ? 'warning' : level === 'green' ? 'success' : 'info'
}
function alertIcon(level: string): string {
  return level === 'red' ? '🔴' : level === 'yellow' ? '🟡' : level === 'green' ? '🟢' : '⚪'
}
function alertColor(level: string): string {
  return level === 'red' ? '#f56c6c' : level === 'yellow' ? '#e6a23c' : level === 'green' ? '#67c23a' : '#909399'
}
function trendColor(v: any, kpi: any): string {
  if (v == null) return '#ddd'
  if (kpi.threshold_red) {
    const threshold = parseFloat(kpi.threshold_red.replace(/[<>=]/g, ''))
    return v < threshold ? '#f56c6c' : '#67c23a'
  }
  return '#909399'
}
function barHeight(v: any, trend: any[]): number {
  if (v == null || trend.length === 0) return 0
  const values = trend.filter(t => t.value != null).map(t => Math.abs(t.value))
  if (values.length === 0) return 0
  return Math.max(...values) > 0 ? (Math.abs(v) / Math.max(...values)) * 80 : 0
}
function renderMd(text: string): string {
  if (!text) return ''
  return text.replace(/### (.+)/g, '<h4 style="margin:12px 0 6px">$1</h4>').replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>').replace(/\n/g, '<br>')
}

function showKPIDetail(k: any) {
  selectedKPI.value = k
  selectedKPIDetail.value = ''
  showDetail.value = true
}

async function loadKPIAnalysis() {
  if (!selectedKPI.value?.id) return
  loadingDetail.value = true
  try {
    const r: any = await aiApi.post('/ai/kpi-analysis', { kpi_id: selectedKPI.value.id, period: periodType.value })
    selectedKPIDetail.value = r.data || r.analysis || '暂无分析结果'
  } catch { selectedKPIDetail.value = 'AI分析请求失败' }
  loadingDetail.value = false
}

async function refreshAnalysis() {
  aiLoading.value = true
  try {
    const r: any = await aiApi.post('/ai/dashboard-analysis', { role: userRole.value, period: periodType.value })
    aiAnalysis.value = r.data || r.analysis || '暂无分析'
  } catch { aiAnalysis.value = 'AI分析暂时不可用' }
  aiLoading.value = false
}

// 构建请求参数
function getPeriodParams(): any {
  if (periodType.value === 'custom' && customStart.value && customEnd.value) {
    return { period: 'custom', start_date: customStart.value, end_date: customEnd.value }
  }
  return { period: periodType.value }
}

function onPeriodChange(val: string) {
  if (val !== 'custom') loadData()
}

function onCustomRangeChange(val: any) {
  if (customStart.value && customEnd.value) loadData()
}

async function loadData() {
  try {
    const params = getPeriodParams()
    if (userRole.value === 'ceo') {
      const [kpiRes, alertRes, sumRes, predRes] = await Promise.all([
        dashboardApi.kpis({ role: 'ceo', ...params }),
        alertApi.list({ limit: 10 }),
        dashboardApi.summary({ role: 'ceo', ...params }),
        dashboardApi.predict({}).catch(() => ({ data: [] })),
      ])
      kpis.value = (kpiRes as any).data || []
      alerts.value = (alertRes as any).data?.filter((a: any) => a.status === 'pending') || []
      summary.value = { kpi_total: (sumRes as any).kpi_total || 0, alert_count: (sumRes as any).alert_count || 0 }
      predictions.value = (predRes as any)?.predictions || []
      dataRange.value = (kpiRes as any).range?.start + ' ~ ' + (kpiRes as any).range?.end
    } else if (userRole.value === 'business') {
      const r: any = await dashboardApi.myKpis?.(params)
      myKpis.value = (r as any)?.data || []
      dataRange.value = (r as any)?.period || ''
    } else if (userRole.value === 'finance') {
      const r: any = await dashboardApi.financeAnalysis?.(params)
      finKpis.value = (r as any)?.kpis || []
      finSummary.value = (r as any)?.summary || {}
      dataRange.value = (r as any)?.period || ''
    } else if (userRole.value === 'it') {
      const channelRes = await axios.get('/api/cma/notifications/channels').then(r => r.data)
      enabledChannels.value = channelRes.data?.filter((c: any) => c.enabled).length || 0
    }
  } catch (e) { console.error('加载数据失败:', e) }
}

onMounted(() => { loadData() })
</script>

<style scoped>
/* ========== 布局 ========== */
.dashboard-page { max-width: 1400px; margin: 0 auto; position: relative; }

/* 顶部导航 */
.dash-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:20px; padding:12px 20px; background:#fff; border-radius:10px; box-shadow:0 1px 3px rgba(0,0,0,0.05); }
.header-left, .header-right { display:flex; align-items:center; gap:12px; }
.data-range { color:#999; font-size:13px; }

/* ========== 摘要卡片行 ========== */
.summary-row { display:grid; grid-template-columns:repeat(auto-fit, minmax(150px, 1fr)); gap:14px; margin-bottom:20px; }
.stat-card { background:#fff; border-radius:10px; padding:16px 20px; box-shadow:0 1px 3px rgba(0,0,0,0.05); border-top:3px solid #ccc; transition:transform .15s; cursor:default; }
.stat-card:hover { transform:translateY(-1px); box-shadow:0 3px 10px rgba(0,0,0,0.08); }
.stat-card.blue { border-top-color:#409eff; }
.stat-card.red { border-top-color:#f56c6c; }
.stat-card.green { border-top-color:#67c23a; }
.stat-card.yellow { border-top-color:#e6a23c; }
.stat-card.gray { border-top-color:#909399; }
.stat-val { font-size:28px; font-weight:700; color:#1a1a2e; letter-spacing:-1px; }
.stat-label { font-size:13px; color:#888; margin-top:2px; }
.stat-sub { font-size:11px; color:#bbb; margin-top:1px; }
.click-hint { font-size:10px; color:#d0d0d0; }

/* ========== CEO双栏 ========== */
.ceo-main { display:flex; gap:20px; align-items:flex-start; }
.ceo-left { flex:2; min-width:0; }
.ceo-right { flex:1; min-width:260px; max-width:340px; position:sticky; top:80px; }

/* 异常高亮区 */
.alert-spotlight { background:linear-gradient(135deg, #fff5f5 0%, #fff 100%); border:1px solid #fde2e2; border-radius:10px; padding:16px; margin-bottom:20px; }
.spotlight-title { font-size:15px; font-weight:600; margin-bottom:10px; color:#c0392b; }
.spotlight-list { display:flex; flex-direction:column; gap:6px; }
.spotlight-item { display:flex; align-items:center; gap:10px; padding:10px 12px; border-radius:8px; cursor:pointer; transition:background .15s; font-size:13px; }
.spotlight-item:hover { background:rgba(245,108,108,0.08); }
.spotlight-item.level-red { border-left:3px solid #f56c6c; }
.spotlight-item.level-yellow { border-left:3px solid #e6a23c; }
.spotlight-badge { font-size:11px; font-weight:600; padding:2px 8px; border-radius:4px; white-space:nowrap; }
.spotlight-item.level-red .spotlight-badge { background:#fef0f0; color:#f56c6c; }
.spotlight-item.level-yellow .spotlight-badge { background:#fdf6ec; color:#e6a23c; }
.spotlight-msg { flex:1; color:#333; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.spotlight-item .el-icon { color:#ccc; flex-shrink:0; }

/* KPI矩阵 */
.matrix-grid { display:grid; grid-template-columns:repeat(2, 1fr); gap:14px; }
.dim-card { background:#fff; border-radius:10px; overflow:hidden; box-shadow:0 1px 3px rgba(0,0,0,0.05); }
.dim-head { display:flex; align-items:center; gap:6px; padding:10px 14px; color:#fff; font-weight:600; font-size:13px; }
.dim-icon { font-size:16px; }
.dim-count { margin-left:auto; font-size:11px; opacity:.7; }
.dim-body { padding:6px 0; }
.kpi-row { padding:10px 14px; cursor:pointer; transition:background .12s; border-bottom:1px solid #f8f8f8; }
.kpi-row:last-child { border-bottom:none; }
.kpi-row:hover { background:#f8faff; }
.kpi-row-top { display:flex; justify-content:space-between; align-items:center; margin-bottom:4px; }
.kpi-row-name { font-size:13px; color:#333; }
.kpi-row-badge { font-size:12px; }
.kpi-row-btm { display:flex; align-items:baseline; gap:4px; }
.kpi-row-val { font-size:18px; font-weight:700; color:#1a1a2e; }
.kpi-row-target { font-size:12px; color:#aaa; }

/* 右侧预测 */
.right-card { background:#fff; border-radius:10px; padding:16px; box-shadow:0 1px 3px rgba(0,0,0,0.05); border:1px solid #f0f0f0; }
.right-card-title { font-size:15px; font-weight:600; margin-bottom:14px; }
.pred-list { display:flex; flex-direction:column; gap:12px; }
.pred-row { padding:12px; border-radius:8px; border:1px solid #f0f0f0; transition:border-color .15s; }
.pred-row:hover { border-color:#d0d0d0; }
.pred-row.trend-down { border-left:3px solid #f56c6c; }
.pred-row.trend-up { border-left:3px solid #67c23a; }
.pred-row.trend-stable { border-left:3px solid #909399; }
.pred-row-top { display:flex; justify-content:space-between; margin-bottom:6px; }
.pred-name { font-size:13px; font-weight:500; color:#333; }
.pred-arrow { font-size:14px; font-weight:700; color:#999; }
.pred-row.trend-down .pred-arrow { color:#f56c6c; }
.pred-row.trend-up .pred-arrow { color:#67c23a; }
.pred-row-val { display:flex; align-items:center; gap:6px; margin-bottom:4px; }
.pred-cur { font-size:16px; font-weight:600; color:#555; }
.pred-sep { color:#ccc; font-size:12px; }
.pred-fut { font-size:18px; font-weight:700; }
.pred-row-info { font-size:11px; }
.pred-conf { padding:1px 6px; border-radius:3px; }
.pred-conf.high { background:#f0f9eb; color:#67c23a; }
.pred-conf.medium { background:#fdf6ec; color:#e6a23c; }
.pred-conf.low { background:#f4f4f5; color:#909399; }

/* ========== 业务/财务KPI卡片 ========== */
.kpi-card-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(240px, 1fr)); gap:14px; }
.kpi-card-item { background:#fff; border-radius:10px; padding:16px; box-shadow:0 1px 3px rgba(0,0,0,0.05); cursor:pointer; transition:all .15s; border:1px solid transparent; }
.kpi-card-item:hover { border-color:#409eff; box-shadow:0 3px 12px rgba(64,158,255,0.12); }
.kpi-card-item.wide { grid-column:span 2; }
.card-item-head { display:flex; justify-content:space-between; align-items:center; margin-bottom:8px; }
.item-name { font-size:14px; font-weight:500; color:#333; }
.card-item-val { font-size:26px; font-weight:700; margin-bottom:4px; }
.item-unit { font-size:13px; color:#999; font-weight:400; margin-left:4px; }
.card-item-target { font-size:12px; color:#aaa; margin-bottom:6px; }
.card-item-trend { display:flex; align-items:center; gap:4px; }
.tdot { width:8px; height:8px; border-radius:50%; display:inline-block; }
.trend-hint { font-size:10px; color:#ccc; margin-left:2px; }

/* 财务趋势柱 */
.trend-bars { display:flex; gap:6px; align-items:flex-end; height:40px; margin-top:8px; }
.tbar-wrap { display:flex; flex-direction:column; align-items:center; flex:1; }
.tbar { width:100%; background:#409eff; border-radius:2px 2px 0 0; min-height:3px; transition:height .3s; }
.tbar-label { font-size:9px; color:#bbb; margin-top:3px; }

/* 系统卡片 */
.sys-card { margin-top:16px; }

/* AI面板 */
.ai-panel { position:fixed; top:80px; right:20px; width:340px; max-height:calc(100vh - 100px); background:#fff; border-radius:10px; box-shadow:0 4px 20px rgba(0,0,0,0.12); display:flex; flex-direction:column; z-index:200; }
.ai-head { display:flex; justify-content:space-between; align-items:center; padding:14px 16px; border-bottom:1px solid #f0f0f0; font-weight:600; }
.ai-body { flex:1; overflow-y:auto; padding:14px 16px; font-size:13px; line-height:1.6; }
.ai-foot { padding:10px 16px; border-top:1px solid #f0f0f0; }
.ai-loading { text-align:center; padding:30px 0; color:#999; }

/* KPI详情弹窗 */
.dlg-summary { display:flex; justify-content:space-between; align-items:center; margin-bottom:12px; }
.kpi-bar.large { height:10px; background:#f0f0f0; border-radius:5px; overflow:hidden; }
.bar-fill { height:100%; border-radius:5px; transition:width .5s; }
.analysis-content { font-size:13px; line-height:1.7; }
.analysis-content h4 { margin:12px 0 6px; color:#409eff; }

/* 空状态 */
.empty-state { text-align:center; padding:60px 0; color:#aaa; font-size:14px; }

/* 响应式 */
@media screen and (max-width: 1024px) {
  .ceo-main { flex-direction:column; }
  .ceo-right { max-width:100%; position:static; }
  .matrix-grid { grid-template-columns:1fr; }
}
@media screen and (max-width: 768px) {
  .summary-row { grid-template-columns:repeat(2, 1fr); }
  .kpi-card-grid { grid-template-columns:1fr; }
  .kpi-card-item.wide { grid-column:span 1; }
  .dash-header { flex-direction:column; align-items:flex-start; gap:8px; }
  .ai-panel { width:calc(100vw - 40px); right:20px; }
}
</style>
