OfficeSystem/components/ContentDashboard.vue

357 lines
7.4 KiB
Vue
Raw Normal View History

2025-11-05 10:16:17 +08:00
<template>
<scroll-view class="dashboard-scroll" scroll-y>
<!-- 任务概览 -->
<view class="task-overview">
<view class="task-card" v-for="item in taskStats" :key="item.label">
<text class="task-count">{{ item.count }}</text>
<text class="task-label">{{ item.label }}</text>
</view>
</view>
<!-- 逾期任务详情 -->
<view class="overdue-section" v-if="overdueTasks.length > 0">
<view class="overdue-card" v-for="task in overdueTasks" :key="task.id">
<view class="overdue-badge">逾期</view>
<view class="overdue-content">
<text class="overdue-date">{{ task.date }}</text>
<text class="overdue-project">所属项目: {{ task.project }}</text>
<text class="overdue-desc">{{ task.description }}</text>
<text class="overdue-owner">负责人: {{ task.owner }}</text>
<text class="overdue-time">发布时间: {{ task.releaseTime }}</text>
</view>
<view class="overdue-action">
<button class="handle-btn" @click="handleOverdueTask(task)">立即处理</button>
</view>
</view>
<view class="carousel-dots">
<view class="dot" :class="{ active: true }"></view>
<view class="dot"></view>
<view class="dot"></view>
</view>
</view>
<!-- 公告事项 -->
<view class="announcement-section">
<view class="section-header">
<text class="section-icon">📢</text>
<text class="section-title">公告事项</text>
</view>
<view class="announcement-item" v-for="announcement in announcements" :key="announcement.id" @click="viewAnnouncement(announcement)">
<view class="announcement-content">
<text class="announcement-title">{{ announcement.title }}</text>
<text class="announcement-desc">{{ announcement.description }}</text>
<text class="announcement-time">{{ announcement.time }}</text>
</view>
<text class="arrow"></text>
</view>
</view>
<!-- 项目状态 -->
<view class="project-status-section">
<view class="section-header">
<text class="section-icon">💎</text>
<text class="section-title">项目状态</text>
</view>
<view class="status-grid">
<view class="status-card" v-for="status in projectStatus" :key="status.label">
<text class="status-count">{{ status.count }}</text>
<text class="status-label">{{ status.label }}</text>
</view>
</view>
</view>
<!-- 客户状态 -->
<view class="customer-status-section">
<view class="section-header">
<text class="section-icon">👤</text>
<text class="section-title">客户状态</text>
</view>
<view class="status-grid">
<view class="status-card" v-for="status in customerStatus" :key="status.label">
<text class="status-count">{{ status.count }}</text>
<text class="status-label">{{ status.label }}</text>
</view>
</view>
</view>
</scroll-view>
</template>
<script setup>
import { ref } from 'vue';
// 任务统计
const taskStats = ref([
{ label: '完成任务', count: 78 },
{ label: '待完成任务', count: 28 },
{ label: '即将预期', count: 8 },
{ label: '逾期任务', count: 1 }
]);
// 逾期任务
const overdueTasks = ref([
{
id: 1,
date: '2025-10-15',
project: '创特项目管理系统',
description: '项目内容项目内容项目内容项目内容项目内容项目...',
owner: '张珊珊、李志',
releaseTime: '2025-03-21'
}
]);
// 公告事项
const announcements = ref([
{
id: 1,
title: '·国庆放假通知',
description: '国庆放假安排1号至6号,前后不调休...',
time: '2025-09-26 16:54:46'
}
]);
// 项目状态
const projectStatus = ref([
{ label: '运行中', count: 1 },
{ label: '运维中', count: 1 },
{ label: '即将到期', count: 1 },
{ label: '开发超期', count: 1 }
]);
// 客户状态
const customerStatus = ref([
{ label: '今日新增', count: 1 },
{ label: '今日已跟进', count: 1 },
{ label: '今日待跟进', count: 1 },
{ label: '即将跟进', count: 1 }
]);
// 处理逾期任务
const handleOverdueTask = (task) => {
console.log('处理逾期任务:', task);
uni.showToast({
title: '跳转到任务处理',
icon: 'none'
});
};
// 查看公告
const viewAnnouncement = (announcement) => {
console.log('查看公告:', announcement);
uni.showToast({
title: '查看公告详情',
icon: 'none'
});
};
</script>
<style lang="scss" scoped>
.dashboard-scroll {
2025-11-05 11:04:47 +08:00
2025-11-05 10:16:17 +08:00
}
.task-overview {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
gap: 12px;
}
.task-card {
flex: 1;
background: #fff;
border-radius: 8px;
padding: 16px;
display: flex;
flex-direction: column;
align-items: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.task-count {
font-size: 24px;
font-weight: 600;
color: #333;
margin-bottom: 8px;
}
.task-label {
font-size: 12px;
color: #666;
}
.overdue-section {
margin-bottom: 20px;
}
.overdue-card {
background: #ffe6e6;
border-radius: 8px;
padding: 16px;
margin-bottom: 12px;
display: flex;
align-items: flex-start;
position: relative;
}
.overdue-badge {
position: absolute;
left: 0;
top: 0;
background: #ff4444;
color: #fff;
font-size: 12px;
padding: 4px 8px;
border-radius: 4px 0 0 0;
}
.overdue-content {
flex: 1;
margin-left: 60px;
display: flex;
flex-direction: column;
gap: 8px;
}
.overdue-date {
font-size: 14px;
color: #333;
font-weight: 500;
}
.overdue-project,
.overdue-desc,
.overdue-owner,
.overdue-time {
font-size: 12px;
color: #666;
line-height: 1.5;
}
.overdue-action {
margin-left: 12px;
}
.handle-btn {
background: #ff4444;
color: #fff;
border: none;
border-radius: 4px;
padding: 8px 16px;
font-size: 12px;
}
.carousel-dots {
display: flex;
justify-content: center;
gap: 8px;
margin-top: 8px;
}
.dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: #ddd;
}
.dot.active {
background: #2885ff;
}
.announcement-section,
.project-status-section,
.customer-status-section {
2025-11-05 11:04:47 +08:00
2025-11-05 10:16:17 +08:00
}
.section-header {
display: flex;
align-items: center;
margin-bottom: 12px;
gap: 8px;
}
.section-icon {
font-size: 18px;
}
.section-title {
font-size: 16px;
font-weight: 600;
color: #333;
}
.announcement-item {
background: #fff;
border-radius: 8px;
padding: 16px;
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.announcement-content {
flex: 1;
display: flex;
flex-direction: column;
gap: 8px;
}
.announcement-title {
font-size: 14px;
font-weight: 500;
color: #333;
}
.announcement-desc {
font-size: 12px;
color: #666;
line-height: 1.5;
}
.announcement-time {
font-size: 12px;
color: #999;
}
.arrow {
font-size: 20px;
color: #999;
margin-left: 12px;
}
.status-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
}
.status-card {
background: #fff;
border-radius: 8px;
padding: 16px;
display: flex;
flex-direction: column;
align-items: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.status-count {
font-size: 20px;
font-weight: 600;
color: #333;
margin-bottom: 8px;
}
.status-label {
font-size: 12px;
color: #666;
text-align: center;
}
</style>