feat: 列宽拖拽 + 筛选栏 + 截图导出 + UI优化
- 新增 v-column-resize 指令,11 张表格均支持拖拽调整列宽 - 工作计划/商机跟单/要客拜访新增筛选栏(客户经理 + 状态) - 汇总栏 chip 可点击筛选,支持重置与计数 - 新增截图导出功能(dom-to-image-more,像素级文字渲染) - 截图范围从标题开始,自动隐藏操作按钮,5px白边 - 截图时页面闪烁动画反馈 - 全局 CSS 完善(列宽手柄、截图模式、捕获动画) - 仪表盘 UI 细节优化 + 亮灯表标签调整 - 登录页 UI 改进 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import { useRouter } from 'vue-router'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { dashboardApi } from '@/api/dashboard'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import api from '@/api/index'
|
||||
|
||||
const router = useRouter()
|
||||
const auth = useAuthStore()
|
||||
@@ -58,6 +59,23 @@ function goWeeklyReport(managerId?: string) {
|
||||
else router.push('/weekly-report')
|
||||
}
|
||||
|
||||
function getRefDate(): string {
|
||||
const d = new Date()
|
||||
d.setDate(d.getDate() + weekOffset.value * 7)
|
||||
return d.toISOString().slice(0, 10)
|
||||
}
|
||||
|
||||
async function handleExport() {
|
||||
try {
|
||||
const res = await api.get('/export/weekly-report', { params: { reference_date: getRefDate() }, responseType: 'blob' })
|
||||
const url = URL.createObjectURL(res.data)
|
||||
const a = document.createElement('a')
|
||||
a.href = url; a.download = 'weekly_report.xlsx'; a.click()
|
||||
URL.revokeObjectURL(url)
|
||||
ElMessage.success('导出成功')
|
||||
} catch (e: any) { ElMessage.error('导出失败') }
|
||||
}
|
||||
|
||||
function rowState(p: any): 'full' | 'catching' | 'missing' {
|
||||
if (p.has_reported_today && p.completed) return 'full'
|
||||
if (p.has_reported_today && !p.completed) return 'catching'
|
||||
@@ -67,15 +85,36 @@ function rowState(p: any): 'full' | 'catching' | 'missing' {
|
||||
|
||||
<template>
|
||||
<div class="dashboard" v-loading="loading">
|
||||
<!-- ═══ Editorial Page Header ═══ -->
|
||||
<!-- ═══ Page Header ═══ -->
|
||||
<div class="page-head">
|
||||
<h2 class="page-title">仪表盘</h2>
|
||||
<div class="week-nav">
|
||||
<button class="week-nav-btn" @click="changeWeek(-1)" title="上一周">◀</button>
|
||||
<span class="week-label">{{ stats.week_start }} — {{ stats.week_end }}</span>
|
||||
<button class="week-nav-btn" @click="changeWeek(1)" :disabled="weekOffset >= 0" title="下一周">▶</button>
|
||||
<button v-if="isHistoricalWeek" class="week-nav-reset" @click="goCurrentWeek">回到本周</button>
|
||||
<el-tag v-if="isHistoricalWeek" type="info" size="small" style="margin-left:8px">📦 历史归档 · 只读</el-tag>
|
||||
<div class="page-head-row">
|
||||
<div>
|
||||
<h2 class="page-title">仪表盘</h2>
|
||||
<div class="week-nav">
|
||||
<button class="week-nav-btn" @click="changeWeek(-1)" title="上一周">◀</button>
|
||||
<span class="week-label">{{ stats.week_start }} — {{ stats.week_end }}</span>
|
||||
<button class="week-nav-btn" @click="changeWeek(1)" :disabled="weekOffset >= 0" title="下一周">▶</button>
|
||||
<button v-if="isHistoricalWeek" class="week-nav-reset" @click="goCurrentWeek">回到本周</button>
|
||||
<el-tag v-if="isHistoricalWeek" type="info" size="small" style="margin-left:8px">📦 历史归档 · 只读</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-head-actions">
|
||||
<el-button type="primary" @click="goWeeklyReport()">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:4px">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||
<polyline points="14 2 14 8 20 8"></polyline>
|
||||
</svg>
|
||||
本周周报详情
|
||||
</el-button>
|
||||
<el-button type="success" v-if="auth.isDirector" @click="handleExport">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:4px">
|
||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
||||
<polyline points="7 10 12 15 17 10"></polyline>
|
||||
<line x1="12" y1="15" x2="12" y2="3"></line>
|
||||
</svg>
|
||||
导出 Excel
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-rule"></div>
|
||||
</div>
|
||||
@@ -133,34 +172,6 @@ function rowState(p: any): 'full' | 'catching' | 'missing' {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══ Quick Actions ═══ -->
|
||||
<div class="actions">
|
||||
<el-button type="primary" @click="goWeeklyReport">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:4px">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||
<polyline points="14 2 14 8 20 8"></polyline>
|
||||
</svg>
|
||||
本周周报详情
|
||||
</el-button>
|
||||
<el-button type="success" v-if="auth.isDirector" @click="router.push('/weekly-report')">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:4px">
|
||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
||||
<polyline points="7 10 12 15 17 10"></polyline>
|
||||
<line x1="12" y1="15" x2="12" y2="3"></line>
|
||||
</svg>
|
||||
导出 Excel
|
||||
</el-button>
|
||||
<el-button plain @click="router.push('/customers')">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:4px">
|
||||
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
|
||||
<circle cx="9" cy="7" r="4"></circle>
|
||||
<path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
|
||||
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
|
||||
</svg>
|
||||
客户管理
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- ═══ Reporting Progress ═══ -->
|
||||
<el-card class="progress-card">
|
||||
<template #header>
|
||||
@@ -174,6 +185,7 @@ function rowState(p: any): 'full' | 'catching' | 'missing' {
|
||||
</div>
|
||||
</template>
|
||||
<div v-if="progress.length === 0" class="empty">暂无数据</div>
|
||||
<div class="progress-grid">
|
||||
<div
|
||||
v-for="p in progress"
|
||||
:key="p.manager_id"
|
||||
@@ -201,13 +213,16 @@ function rowState(p: any): 'full' | 'catching' | 'missing' {
|
||||
:stroke-width="12"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* ═══ Page Header ═══ */
|
||||
.page-head { margin-bottom: 24px; }
|
||||
.page-head { margin-bottom: 20px; }
|
||||
.page-head-row { display: flex; justify-content: space-between; align-items: center; }
|
||||
.page-head-actions { display: flex; gap: 8px; flex-shrink: 0; }
|
||||
.page-title {
|
||||
margin: 0;
|
||||
font-family: var(--font-heading);
|
||||
@@ -264,8 +279,12 @@ function rowState(p: any): 'full' | 'catching' | 'missing' {
|
||||
font-size: 12px; color: var(--warm-gray); letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
/* ═══ Actions ═══ */
|
||||
.actions { display: flex; gap: 10px; margin-bottom: 24px; }
|
||||
/* ═══ Progress Grid — responsive 2-column ═══ */
|
||||
.progress-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
|
||||
gap: 8px 24px;
|
||||
}
|
||||
|
||||
/* ═══ Progress ═══ */
|
||||
.progress-card { margin-top: 4px; }
|
||||
|
||||
Reference in New Issue
Block a user