2025-09-17 15:53:38 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<div class="execution-records">
|
|
|
|
|
|
<!-- 顶部导航栏 -->
|
|
|
|
|
|
<div class="navigation-tabs">
|
|
|
|
|
|
<div class="nav-tab" @click="handleInspection1">待办事项</div>
|
|
|
|
|
|
<div class="nav-tab" @click="handleInspection2">巡检管理</div>
|
|
|
|
|
|
<div class="nav-tab" @click="handleInspection3">试验管理</div>
|
|
|
|
|
|
<div class="nav-tab" @click="handleInspection4">报修管理</div>
|
|
|
|
|
|
<div class="nav-tab" @click="handleInspection5">抢修管理</div>
|
|
|
|
|
|
<div class="nav-tab" @click="handleInspection6">工单管理</div>
|
|
|
|
|
|
<div class="nav-tab active" @click="handleInspection7">运维组织</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 页面标题 -->
|
|
|
|
|
|
<TitleComponent title="运维组织模块" subtitle="实时监控人员状态、车辆状态和班组状态"></TitleComponent>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 选项卡 -->
|
|
|
|
|
|
<div class="tabs-wrapper">
|
|
|
|
|
|
<div style="display: flex; align-items: center; gap: 10px">
|
|
|
|
|
|
<el-button type="primary" @click="handleInspectionManagement1">人员状态</el-button>
|
|
|
|
|
|
<el-button type="primary" @click="handleInspectionManagement2">车辆状态</el-button>
|
|
|
|
|
|
<el-button type="primary" @click="handleInspectionManagement3">班组状态</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 搜索和筛选区 -->
|
|
|
|
|
|
<div class="search-filter">
|
|
|
|
|
|
<div class="search-container">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="searchKeyword"
|
|
|
|
|
|
placeholder="搜索班组名称或编号"
|
|
|
|
|
|
class="search-input"
|
|
|
|
|
|
suffix-icon="el-icon-search"
|
|
|
|
|
|
@keyup.enter="handleSearch"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
<el-button type="primary" class="new-team-btn" @click="handleCreateTeam"> <i class="el-icon-plus"></i> 新增班组 </el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 班组卡片和图表区域 -->
|
|
|
|
|
|
<div class="team-cards-section">
|
|
|
|
|
|
<div class="team-cards-container">
|
|
|
|
|
|
<!-- 班组卡片 -->
|
|
|
|
|
|
<div v-for="team in filteredTeams" :key="team.id" class="team-card">
|
|
|
|
|
|
<div class="team-header">
|
|
|
|
|
|
<div class="team-name">
|
|
|
|
|
|
{{ team.name }}
|
|
|
|
|
|
<el-tag :type="getTeamStatusType(team.status)" class="team-status-tag">
|
|
|
|
|
|
{{ team.status }}
|
|
|
|
|
|
</el-tag>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="team-region">负责区域: {{ team.region }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="team-details">
|
|
|
|
|
|
<div class="team-leader">组长: {{ team.leader }}</div>
|
|
|
|
|
|
<div class="team-members">
|
|
|
|
|
|
成员数: {{ team.memberCount }}人
|
|
|
|
|
|
<div class="member-avatars">
|
|
|
|
|
|
<el-avatar v-for="i in Math.min(5, team.memberCount)" :key="i" size="small" class="avatar-small">{{
|
|
|
|
|
|
String.fromCharCode(64 + i)
|
|
|
|
|
|
}}</el-avatar>
|
|
|
|
|
|
<span v-if="team.memberCount > 5" class="avatar-more">+{{ team.memberCount - 5 }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="team-tasks">
|
|
|
|
|
|
<div class="task-label">当前任务数:</div>
|
|
|
|
|
|
<div class="task-progress">
|
|
|
|
|
|
<div class="progress-bar" :style="{ width: team.taskProgress }"></div>
|
|
|
|
|
|
<div class="progress-text">{{ team.currentTasks }}/{{ team.totalTasks }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="team-completion">
|
|
|
|
|
|
<div class="completion-label">今日完成率:</div>
|
|
|
|
|
|
<div class="completion-bar">
|
|
|
|
|
|
<div class="completion-fill" :style="{ width: team.completionRate }" :class="getCompletionClass(team.completionRate)"></div>
|
|
|
|
|
|
<div class="completion-text">{{ team.completionRate }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="team-actions">
|
|
|
|
|
|
<el-button type="text" @click="handleViewTeamDetails(team)" class="action-btn">查看详情</el-button>
|
|
|
|
|
|
<el-button type="text" @click="handleAssignTasks(team)" class="action-btn assign-btn" v-if="team.status === '正常运行'">
|
|
|
|
|
|
分配任务
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
<el-button type="text" @click="handleSupport(team)" class="action-btn support-btn" v-if="team.status === '人员紧张'">
|
|
|
|
|
|
支援请求
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 图表卡片 -->
|
|
|
|
|
|
<div class="chart-card-container">
|
|
|
|
|
|
<div class="chart-card">
|
|
|
|
|
|
<div class="chart-header">
|
2025-09-17 20:03:00 +08:00
|
|
|
|
<h3>班组每周任务情况</h3>
|
2025-09-17 15:53:38 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="chart-content">
|
2025-09-17 20:03:00 +08:00
|
|
|
|
<!-- 环形图容器 -->
|
2025-09-17 15:53:38 +08:00
|
|
|
|
<div id="teamChart" class="chart-container"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 班组任务完成情况表格 -->
|
|
|
|
|
|
<div class="table-wrapper">
|
2025-09-17 20:03:00 +08:00
|
|
|
|
<div class="table-header-title">
|
|
|
|
|
|
<h2>班组任务完成情况</h2>
|
|
|
|
|
|
</div>
|
2025-09-17 15:53:38 +08:00
|
|
|
|
<el-table :data="pagedTableData" stripe style="width: 100%" highlight-current-row class="custom-table">
|
|
|
|
|
|
<el-table-column align="center" prop="name" label="班组名称" min-width="120"></el-table-column>
|
|
|
|
|
|
<el-table-column align="center" prop="leader" label="组长" min-width="100"></el-table-column>
|
|
|
|
|
|
<el-table-column align="center" prop="memberCount" label="成员数" min-width="100"></el-table-column>
|
|
|
|
|
|
<el-table-column align="center" prop="region" label="负责区域" min-width="150"></el-table-column>
|
|
|
|
|
|
<el-table-column align="center" prop="currentTasks" label="当前任务" min-width="100"></el-table-column>
|
|
|
|
|
|
<el-table-column align="center" prop="unfinishedTasks" label="未完成" min-width="100"></el-table-column>
|
|
|
|
|
|
<el-table-column align="center" prop="completionRate" label="完成率" min-width="120">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<div class="completion-bar">
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="completion-progress"
|
|
|
|
|
|
:style="{ width: scope.row.completionRate }"
|
|
|
|
|
|
:class="getCompletionClass(scope.row.completionRate)"
|
|
|
|
|
|
></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column align="center" prop="status" label="状态" min-width="100">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<el-tag :type="getTeamStatusType(scope.row.status)" class="status-tag">
|
|
|
|
|
|
{{ scope.row.status }}
|
|
|
|
|
|
</el-tag>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column align="center" label="操作" min-width="180" fixed="right">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<el-button type="text" @click="handleViewTeamDetails(scope.row)" size="small" class="action-btn">详情</el-button>
|
|
|
|
|
|
<el-button type="text" @click="handleManageTeam(scope.row)" size="small" class="action-btn manage-btn"> 管理 </el-button>
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
@click="handleSupport(scope.row)"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
class="action-btn support-btn"
|
|
|
|
|
|
v-if="scope.row.status === '人员紧张'"
|
|
|
|
|
|
>
|
|
|
|
|
|
支援
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 分页区域 -->
|
|
|
|
|
|
<div class="pagination-section">
|
|
|
|
|
|
<div class="pagination-info">
|
|
|
|
|
|
显示第{{ (currentPage - 1) * pageSize + 1 }}到{{ Math.min(currentPage * pageSize, total) }}条,共{{ total }}条记录
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="pagination-controls">
|
|
|
|
|
|
<el-pagination
|
|
|
|
|
|
@size-change="handleSizeChange"
|
|
|
|
|
|
@current-change="handleCurrentChange"
|
|
|
|
|
|
:current-page="currentPage"
|
|
|
|
|
|
:page-sizes="[10, 20, 30, 40]"
|
|
|
|
|
|
:page-size="pageSize"
|
|
|
|
|
|
layout="prev, pager, next, jumper"
|
|
|
|
|
|
:total="total"
|
|
|
|
|
|
background
|
|
|
|
|
|
>
|
|
|
|
|
|
</el-pagination>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue';
|
|
|
|
|
|
import router from '@/router';
|
|
|
|
|
|
import TitleComponent from './TitleComponent.vue';
|
|
|
|
|
|
import * as echarts from 'echarts'; // 导入ECharts
|
2025-09-17 20:03:00 +08:00
|
|
|
|
import renwuImage from '@/assets/images/renwu.png';
|
2025-09-17 15:53:38 +08:00
|
|
|
|
|
|
|
|
|
|
// 搜索条件
|
|
|
|
|
|
const searchKeyword = ref('');
|
|
|
|
|
|
|
|
|
|
|
|
// 班组数据
|
|
|
|
|
|
const rawTeamData = ref([
|
|
|
|
|
|
{
|
|
|
|
|
|
id: 1,
|
|
|
|
|
|
name: '第一运维组',
|
|
|
|
|
|
leader: '张工',
|
|
|
|
|
|
memberCount: 12,
|
|
|
|
|
|
region: '东区、南区',
|
|
|
|
|
|
currentTasks: 5,
|
|
|
|
|
|
totalTasks: 23,
|
|
|
|
|
|
unfinishedTasks: 18,
|
|
|
|
|
|
completionRate: '85%',
|
|
|
|
|
|
taskProgress: '22%',
|
|
|
|
|
|
status: '正常运行'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
id: 2,
|
|
|
|
|
|
name: '第二运维组',
|
|
|
|
|
|
leader: '李工',
|
|
|
|
|
|
memberCount: 10,
|
|
|
|
|
|
region: '西区、北区',
|
|
|
|
|
|
currentTasks: 7,
|
|
|
|
|
|
totalTasks: 22,
|
|
|
|
|
|
unfinishedTasks: 15,
|
|
|
|
|
|
completionRate: '65%',
|
|
|
|
|
|
taskProgress: '32%',
|
|
|
|
|
|
status: '正常运行'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
id: 3,
|
|
|
|
|
|
name: '第三运维组',
|
|
|
|
|
|
leader: '赵工',
|
|
|
|
|
|
memberCount: 14,
|
|
|
|
|
|
region: '市中心区域',
|
|
|
|
|
|
currentTasks: 12,
|
|
|
|
|
|
totalTasks: 24,
|
|
|
|
|
|
unfinishedTasks: 12,
|
|
|
|
|
|
completionRate: '45%',
|
|
|
|
|
|
taskProgress: '50%',
|
|
|
|
|
|
status: '人员紧张'
|
|
|
|
|
|
}
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
2025-09-17 20:03:00 +08:00
|
|
|
|
// 提取任务数据用于图表展示
|
|
|
|
|
|
const teamChartData = computed(() => {
|
|
|
|
|
|
return rawTeamData.value.map((team) => ({
|
|
|
|
|
|
name: team.name,
|
|
|
|
|
|
value: team.currentTasks, // 使用当前任务数
|
|
|
|
|
|
teamId: team.id
|
|
|
|
|
|
}));
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 计算总任务数
|
|
|
|
|
|
const totalTasks = computed(() => {
|
|
|
|
|
|
return teamChartData.value.reduce((sum, item) => sum + item.value, 0);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-09-17 15:53:38 +08:00
|
|
|
|
// 分页相关
|
|
|
|
|
|
const currentPage = ref(1);
|
|
|
|
|
|
const pageSize = ref(10);
|
|
|
|
|
|
const total = ref(rawTeamData.value.length);
|
|
|
|
|
|
|
|
|
|
|
|
// 筛选后的班组数据
|
|
|
|
|
|
const filteredTeams = computed(() => {
|
|
|
|
|
|
let teams = [...rawTeamData.value];
|
|
|
|
|
|
|
|
|
|
|
|
if (searchKeyword.value) {
|
|
|
|
|
|
const keyword = searchKeyword.value.toLowerCase();
|
|
|
|
|
|
teams = teams.filter(
|
|
|
|
|
|
(team) =>
|
|
|
|
|
|
team.name.toLowerCase().includes(keyword) || team.region.toLowerCase().includes(keyword) || team.leader.toLowerCase().includes(keyword)
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return teams;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 分页处理后的数据
|
|
|
|
|
|
const pagedTableData = computed(() => {
|
|
|
|
|
|
// 更新总条数
|
|
|
|
|
|
total.value = filteredTeams.value.length;
|
|
|
|
|
|
|
|
|
|
|
|
// 分页处理
|
|
|
|
|
|
const startIndex = (currentPage.value - 1) * pageSize.value;
|
|
|
|
|
|
const endIndex = startIndex + pageSize.value;
|
|
|
|
|
|
return filteredTeams.value.slice(startIndex, endIndex);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 获取班组状态标签样式
|
|
|
|
|
|
const getTeamStatusType = (status) => {
|
|
|
|
|
|
const statusMap = {
|
|
|
|
|
|
'正常运行': 'success',
|
|
|
|
|
|
'人员紧张': 'warning'
|
|
|
|
|
|
};
|
|
|
|
|
|
return statusMap[status] || 'default';
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 获取完成度样式
|
|
|
|
|
|
const getCompletionClass = (completion) => {
|
|
|
|
|
|
const percentage = parseInt(completion);
|
|
|
|
|
|
if (percentage >= 80) return 'high';
|
|
|
|
|
|
if (percentage >= 60) return 'medium';
|
|
|
|
|
|
return 'low';
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 搜索处理
|
|
|
|
|
|
const handleSearch = () => {
|
|
|
|
|
|
currentPage.value = 1; // 重置到第一页
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 分页事件
|
|
|
|
|
|
const handleSizeChange = (val) => {
|
|
|
|
|
|
pageSize.value = val;
|
|
|
|
|
|
currentPage.value = 1;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleCurrentChange = (val) => {
|
|
|
|
|
|
currentPage.value = val;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 操作按钮事件
|
|
|
|
|
|
const handleViewTeamDetails = (team) => {
|
|
|
|
|
|
console.log('查看班组详情:', team);
|
|
|
|
|
|
// 实际应用中这里会跳转到详情页
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleAssignTasks = (team) => {
|
|
|
|
|
|
console.log('分配任务给班组:', team);
|
|
|
|
|
|
// 实际应用中这里会打开任务分配表单
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleManageTeam = (team) => {
|
|
|
|
|
|
console.log('管理班组:', team);
|
|
|
|
|
|
// 实际应用中这里会打开班组管理页面
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleSupport = (team) => {
|
|
|
|
|
|
console.log('请求支援:', team);
|
|
|
|
|
|
// 实际应用中这里会打开支援请求表单
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleCreateTeam = () => {
|
|
|
|
|
|
console.log('创建新班组');
|
|
|
|
|
|
// 实际应用中这里会打开新建班组表单
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 导航路由跳转
|
|
|
|
|
|
const handleInspection1 = () => {
|
|
|
|
|
|
router.push('/rili/rili');
|
|
|
|
|
|
};
|
|
|
|
|
|
const handleInspection2 = () => {
|
|
|
|
|
|
router.push('/rili/InspectionManagement');
|
|
|
|
|
|
};
|
|
|
|
|
|
const handleInspection3 = () => {
|
|
|
|
|
|
router.push('/rili/shiyanguanli');
|
|
|
|
|
|
};
|
|
|
|
|
|
const handleInspection4 = () => {
|
|
|
|
|
|
router.push('/rili/baoxiuguanli');
|
|
|
|
|
|
};
|
|
|
|
|
|
const handleInspection5 = () => {
|
|
|
|
|
|
router.push('/rili/qiangxiuguanli');
|
|
|
|
|
|
};
|
|
|
|
|
|
const handleInspection6 = () => {
|
|
|
|
|
|
router.push('/rili/gongdanliebiao');
|
|
|
|
|
|
};
|
|
|
|
|
|
const handleInspection7 = () => {
|
|
|
|
|
|
router.push('/rili/renyuanzhuangtai');
|
|
|
|
|
|
};
|
|
|
|
|
|
const handleInspectionManagement1 = () => {
|
|
|
|
|
|
router.push('/rili/renyuanzhuangtai');
|
|
|
|
|
|
};
|
|
|
|
|
|
const handleInspectionManagement2 = () => {
|
|
|
|
|
|
router.push('/rili/cheliangzhuangtai');
|
|
|
|
|
|
};
|
|
|
|
|
|
const handleInspectionManagement3 = () => {
|
|
|
|
|
|
router.push('/rili/banzhuzhuangtai');
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// ECharts实例
|
|
|
|
|
|
let chartInstance = null;
|
|
|
|
|
|
|
2025-09-17 20:03:00 +08:00
|
|
|
|
// 初始化ECharts图表 - 修改为环形图样式
|
2025-09-17 15:53:38 +08:00
|
|
|
|
const initChart = () => {
|
|
|
|
|
|
// 使用nextTick确保DOM已完全渲染
|
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
|
// 获取DOM元素
|
|
|
|
|
|
const chartDom = document.getElementById('teamChart');
|
|
|
|
|
|
if (!chartDom) {
|
|
|
|
|
|
console.error('图表容器元素未找到');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 销毁已存在的图表实例
|
|
|
|
|
|
if (chartInstance) {
|
|
|
|
|
|
chartInstance.dispose();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建新的图表实例
|
|
|
|
|
|
chartInstance = echarts.init(chartDom);
|
|
|
|
|
|
|
|
|
|
|
|
// 准备图表数据
|
2025-09-17 20:03:00 +08:00
|
|
|
|
const allData = teamChartData.value;
|
|
|
|
|
|
|
|
|
|
|
|
// 定义颜色方案
|
|
|
|
|
|
const teamColors = [
|
|
|
|
|
|
'#1890ff', // 第一运维组 - 蓝色
|
|
|
|
|
|
'#faad14', // 第二运维组 - 黄色
|
|
|
|
|
|
'#722ed1' // 第三运维组 - 紫色
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
// 准备图表配置项
|
2025-09-17 15:53:38 +08:00
|
|
|
|
const option = {
|
2025-09-17 20:03:00 +08:00
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
|
|
|
|
|
|
|
|
// 提示框 - 显示详细数据
|
2025-09-17 15:53:38 +08:00
|
|
|
|
tooltip: {
|
|
|
|
|
|
trigger: 'item',
|
2025-09-17 20:03:00 +08:00
|
|
|
|
formatter: '{a} <br/>{b}: {c} 项',
|
2025-09-17 15:53:38 +08:00
|
|
|
|
backgroundColor: 'rgba(255, 255, 255, 0.95)',
|
|
|
|
|
|
borderColor: '#e8e8e8',
|
2025-09-17 20:03:00 +08:00
|
|
|
|
borderWidth: 1,
|
2025-09-17 15:53:38 +08:00
|
|
|
|
textStyle: {
|
2025-09-17 20:03:00 +08:00
|
|
|
|
color: '#333',
|
|
|
|
|
|
fontSize: 14
|
2025-09-17 15:53:38 +08:00
|
|
|
|
},
|
|
|
|
|
|
padding: 12,
|
|
|
|
|
|
borderRadius: 8,
|
|
|
|
|
|
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)'
|
|
|
|
|
|
},
|
2025-09-17 20:03:00 +08:00
|
|
|
|
|
|
|
|
|
|
// 图例 - 在底部横向排列
|
2025-09-17 15:53:38 +08:00
|
|
|
|
legend: {
|
2025-09-17 20:03:00 +08:00
|
|
|
|
orient: 'horizontal',
|
|
|
|
|
|
bottom: 10,
|
|
|
|
|
|
left: 'center',
|
2025-09-17 15:53:38 +08:00
|
|
|
|
itemWidth: 14,
|
|
|
|
|
|
itemHeight: 14,
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
|
color: '#666'
|
|
|
|
|
|
},
|
2025-09-17 20:03:00 +08:00
|
|
|
|
itemGap: 20,
|
|
|
|
|
|
// 当数据过多时启用分页
|
|
|
|
|
|
pageShow: allData.length > 6,
|
|
|
|
|
|
pageFormatter: '{current}/{total}'
|
2025-09-17 15:53:38 +08:00
|
|
|
|
},
|
2025-09-17 20:03:00 +08:00
|
|
|
|
|
|
|
|
|
|
// 系列数据 - 环形图
|
2025-09-17 15:53:38 +08:00
|
|
|
|
series: [
|
|
|
|
|
|
{
|
2025-09-17 20:03:00 +08:00
|
|
|
|
name: '每周任务',
|
2025-09-17 15:53:38 +08:00
|
|
|
|
type: 'pie',
|
2025-09-17 20:03:00 +08:00
|
|
|
|
radius: ['50%', '70%'], // 调整内半径和外半径,使环形更宽
|
|
|
|
|
|
center: ['50%', '50%'], // 调整中心位置
|
2025-09-17 15:53:38 +08:00
|
|
|
|
avoidLabelOverlap: false,
|
2025-09-17 20:03:00 +08:00
|
|
|
|
|
|
|
|
|
|
// 扇区样式
|
2025-09-17 15:53:38 +08:00
|
|
|
|
itemStyle: {
|
2025-09-17 20:03:00 +08:00
|
|
|
|
borderRadius: 2,
|
2025-09-17 15:53:38 +08:00
|
|
|
|
borderColor: '#fff',
|
|
|
|
|
|
borderWidth: 2,
|
2025-09-17 20:03:00 +08:00
|
|
|
|
color: function (params) {
|
|
|
|
|
|
return teamColors[params.dataIndex % teamColors.length];
|
|
|
|
|
|
}
|
2025-09-17 15:53:38 +08:00
|
|
|
|
},
|
2025-09-17 20:03:00 +08:00
|
|
|
|
|
|
|
|
|
|
// 扇区标签 - 不显示外部标签
|
2025-09-17 15:53:38 +08:00
|
|
|
|
label: {
|
2025-09-17 20:03:00 +08:00
|
|
|
|
show: false
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 标签连接线 - 隐藏
|
|
|
|
|
|
labelLine: {
|
|
|
|
|
|
show: false
|
2025-09-17 15:53:38 +08:00
|
|
|
|
},
|
2025-09-17 20:03:00 +08:00
|
|
|
|
|
|
|
|
|
|
// 中心文本 - 使用富文本自定义样式
|
2025-09-17 15:53:38 +08:00
|
|
|
|
emphasis: {
|
|
|
|
|
|
scale: true,
|
2025-09-17 20:03:00 +08:00
|
|
|
|
scaleSize: 5,
|
2025-09-17 15:53:38 +08:00
|
|
|
|
label: {
|
2025-09-17 20:03:00 +08:00
|
|
|
|
show: false
|
2025-09-17 15:53:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-09-17 20:03:00 +08:00
|
|
|
|
|
|
|
|
|
|
// 动画效果
|
2025-09-17 15:53:38 +08:00
|
|
|
|
animationType: 'scale',
|
|
|
|
|
|
animationEasing: 'elasticOut',
|
2025-09-17 20:03:00 +08:00
|
|
|
|
animationDuration: 1500,
|
2025-09-17 15:53:38 +08:00
|
|
|
|
animationDelay: function (idx) {
|
2025-09-17 20:03:00 +08:00
|
|
|
|
return idx * 150;
|
2025-09-17 15:53:38 +08:00
|
|
|
|
},
|
2025-09-17 20:03:00 +08:00
|
|
|
|
|
|
|
|
|
|
// 任务数据
|
|
|
|
|
|
data: allData
|
2025-09-17 15:53:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 设置图表配置项
|
|
|
|
|
|
chartInstance.setOption(option);
|
|
|
|
|
|
|
2025-09-17 20:03:00 +08:00
|
|
|
|
// 添加中心圆形白色背景和图片 - 使用ECharts的graphic组件
|
|
|
|
|
|
chartInstance.setOption({
|
|
|
|
|
|
graphic: {
|
|
|
|
|
|
elements: [
|
|
|
|
|
|
// 圆形白色背景
|
|
|
|
|
|
{
|
|
|
|
|
|
type: 'circle',
|
|
|
|
|
|
z: 90,
|
|
|
|
|
|
left: 'center',
|
|
|
|
|
|
top: 'center',
|
|
|
|
|
|
shape: {
|
|
|
|
|
|
r: 35 // 圆形半径
|
|
|
|
|
|
},
|
|
|
|
|
|
style: {
|
|
|
|
|
|
fill: '#ffffff',
|
|
|
|
|
|
stroke: '#f0f0f0',
|
|
|
|
|
|
lineWidth: 2
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
// 中心图片 - 使用本地图片renwu.png
|
|
|
|
|
|
{
|
|
|
|
|
|
type: 'image',
|
|
|
|
|
|
z: 100,
|
|
|
|
|
|
left: 'center',
|
|
|
|
|
|
top: 'center',
|
|
|
|
|
|
style: {
|
|
|
|
|
|
image: renwuImage,
|
|
|
|
|
|
width: 30,
|
|
|
|
|
|
height: 30
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-09-17 15:53:38 +08:00
|
|
|
|
// 处理窗口大小变化
|
|
|
|
|
|
const handleResize = () => {
|
|
|
|
|
|
chartInstance.resize();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
window.addEventListener('resize', handleResize);
|
|
|
|
|
|
|
|
|
|
|
|
// 组件卸载时移除事件监听
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
|
window.removeEventListener('resize', handleResize);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 组件挂载时初始化图表
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
initChart();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 组件卸载时销毁图表实例
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
|
if (chartInstance) {
|
|
|
|
|
|
chartInstance.dispose();
|
|
|
|
|
|
chartInstance = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
2025-09-17 20:03:00 +08:00
|
|
|
|
/* 样式保持不变 */
|
2025-09-17 15:53:38 +08:00
|
|
|
|
.execution-records {
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
background-color: #f5f7fa;
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 选项卡样式 */
|
|
|
|
|
|
.tabs-wrapper {
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 搜索和筛选区样式 */
|
|
|
|
|
|
.search-filter {
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.search-container {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 16px 24px;
|
|
|
|
|
|
border-bottom: 1px solid #f0f0f0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.search-input {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
max-width: 500px;
|
|
|
|
|
|
height: 36px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.new-team-btn {
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
margin-left: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 班组卡片区域样式 */
|
|
|
|
|
|
.team-cards-section {
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
|
|
|
|
|
|
padding: 24px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-cards-container {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
|
|
|
|
|
|
gap: 24px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-card {
|
|
|
|
|
|
border: 1px solid #f0f0f0;
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
padding: 24px;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04);
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-card::before {
|
|
|
|
|
|
content: '';
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
width: 4px;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
background: linear-gradient(180deg, #1890ff 0%, #40a9ff 100%);
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
transition: opacity 0.3s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-card:nth-child(2)::before {
|
|
|
|
|
|
background: linear-gradient(180deg, #faad14 0%, #ffc53d 100%);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-card:nth-child(3)::before {
|
|
|
|
|
|
background: linear-gradient(180deg, #ff4d4f 0%, #ff7a45 100%);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-card:hover {
|
|
|
|
|
|
transform: translateY(-5px);
|
|
|
|
|
|
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
|
|
|
|
|
|
border-color: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-card:hover::before {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 图表卡片容器样式 */
|
|
|
|
|
|
.chart-card-container {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: stretch;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 图表卡片样式 */
|
|
|
|
|
|
.chart-card {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
border: 1px solid #f0f0f0;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.04);
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chart-header {
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
padding-bottom: 12px;
|
|
|
|
|
|
border-bottom: 1px dashed #f0f0f0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chart-header h3 {
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chart-content {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
2025-09-17 20:03:00 +08:00
|
|
|
|
position: relative;
|
2025-09-17 15:53:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-17 20:03:00 +08:00
|
|
|
|
/* 图表容器样式 */
|
2025-09-17 15:53:38 +08:00
|
|
|
|
.chart-container {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
2025-09-17 20:03:00 +08:00
|
|
|
|
min-height: 320px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 新增任务数标签样式 */
|
|
|
|
|
|
.task-count-label {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
bottom: 40px;
|
|
|
|
|
|
right: 40px;
|
|
|
|
|
|
background-color: #722ed1;
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
padding: 6px 12px;
|
|
|
|
|
|
border-radius: 16px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(114, 46, 209, 0.3);
|
2025-09-17 15:53:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-header {
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
padding-bottom: 12px;
|
|
|
|
|
|
border-bottom: 1px dashed #f0f0f0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-name {
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-region {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #606266;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-details {
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-leader,
|
|
|
|
|
|
.team-members {
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 成员头像展示 */
|
|
|
|
|
|
.member-avatars {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
|
gap: -8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.avatar-small {
|
|
|
|
|
|
width: 24px;
|
|
|
|
|
|
height: 24px;
|
|
|
|
|
|
line-height: 24px;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
border: 2px solid #fff;
|
|
|
|
|
|
background-color: #e6f7ff;
|
|
|
|
|
|
color: #1890ff;
|
|
|
|
|
|
margin-left: -8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.avatar-small:nth-child(2) {
|
|
|
|
|
|
background-color: #fff7e6;
|
|
|
|
|
|
color: #fa8c16;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.avatar-small:nth-child(3) {
|
|
|
|
|
|
background-color: #fff1f0;
|
|
|
|
|
|
color: #ff4d4f;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.avatar-small:nth-child(4) {
|
|
|
|
|
|
background-color: #f6ffed;
|
|
|
|
|
|
color: #52c41a;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.avatar-small:nth-child(5) {
|
|
|
|
|
|
background-color: #f0f2f5;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.avatar-more {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #999;
|
|
|
|
|
|
margin-left: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-tasks,
|
|
|
|
|
|
.team-completion {
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-label,
|
|
|
|
|
|
.completion-label {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #606266;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-progress,
|
|
|
|
|
|
.completion-bar {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 10px;
|
|
|
|
|
|
background-color: #f0f2f5;
|
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.progress-bar,
|
|
|
|
|
|
.completion-fill {
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
|
transition: width 0.3s ease;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.progress-bar {
|
|
|
|
|
|
background: linear-gradient(90deg, #fa8c16 0%, #ffc53d 100%);
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(250, 140, 22, 0.3);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.progress-bar::after,
|
|
|
|
|
|
.completion-fill::after {
|
|
|
|
|
|
content: '';
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0) 100%);
|
|
|
|
|
|
animation: shimmer 2s infinite;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes shimmer {
|
|
|
|
|
|
0% {
|
|
|
|
|
|
transform: translateX(-100%);
|
|
|
|
|
|
}
|
|
|
|
|
|
100% {
|
|
|
|
|
|
transform: translateX(100%);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.progress-text,
|
|
|
|
|
|
.completion-text {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
right: 6px;
|
|
|
|
|
|
top: 50%;
|
|
|
|
|
|
transform: translateY(-50%);
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #606266;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.completion-fill.high {
|
|
|
|
|
|
background: linear-gradient(90deg, #52c41a 0%, #73d13d 100%);
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(82, 196, 26, 0.3);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.completion-fill.medium {
|
|
|
|
|
|
background: linear-gradient(90deg, #faad14 0%, #ffc53d 100%);
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(250, 173, 20, 0.3);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.completion-fill.low {
|
|
|
|
|
|
background: linear-gradient(90deg, #ff4d4f 0%, #ff7a45 100%);
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(255, 77, 79, 0.3);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-actions {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
padding-top: 16px;
|
|
|
|
|
|
border-top: 1px dashed #f0f0f0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-17 20:03:00 +08:00
|
|
|
|
/* 表格标题样式 */
|
|
|
|
|
|
.table-header-title {
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
padding: 16px 24px;
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.table-header-title h2 {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-17 15:53:38 +08:00
|
|
|
|
/* 表格样式优化 */
|
|
|
|
|
|
.table-wrapper {
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-table {
|
|
|
|
|
|
border-collapse: collapse;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-table th {
|
|
|
|
|
|
background-color: #fafafa;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
padding: 12px 8px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
border-bottom: 2px solid #f0f0f0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-table td {
|
|
|
|
|
|
padding: 12px 8px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
border-bottom: 1px solid #f5f7fa;
|
|
|
|
|
|
color: #606266;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
transition: background-color 0.2s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-table tr:hover td {
|
|
|
|
|
|
background-color: #f8f9ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-table tr.current-row td {
|
|
|
|
|
|
background-color: #e6f7ff !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 状态标签样式 */
|
|
|
|
|
|
.status-tag,
|
|
|
|
|
|
.team-status-tag {
|
|
|
|
|
|
padding: 4px 12px;
|
|
|
|
|
|
border-radius: 16px;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-status-tag:hover {
|
|
|
|
|
|
transform: scale(1.05);
|
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 完成度样式优化 */
|
|
|
|
|
|
.completion-bar {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 8px;
|
|
|
|
|
|
background-color: #f0f2f5;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.completion-progress {
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
transition: width 0.3s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.completion-progress.high {
|
|
|
|
|
|
background-color: #52c41a;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.completion-progress.medium {
|
|
|
|
|
|
background-color: #faad14;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.completion-progress.low {
|
|
|
|
|
|
background-color: #fa8c16;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 操作按钮样式优化 */
|
|
|
|
|
|
.action-btn {
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
padding: 4px 10px;
|
|
|
|
|
|
margin: 0 3px;
|
|
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.action-btn:hover {
|
|
|
|
|
|
background-color: #f8f9ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.assign-btn {
|
|
|
|
|
|
color: #1890ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.assign-btn:hover {
|
|
|
|
|
|
color: #094ab2;
|
|
|
|
|
|
background-color: #e6f7ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.manage-btn {
|
|
|
|
|
|
color: #1890ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.manage-btn:hover {
|
|
|
|
|
|
color: #094ab2;
|
|
|
|
|
|
background-color: #e6f7ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.support-btn {
|
|
|
|
|
|
color: #ff4d4f;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.support-btn:hover {
|
|
|
|
|
|
color: #cf1322;
|
|
|
|
|
|
background-color: #fff2f0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 分页区域样式 */
|
|
|
|
|
|
.pagination-section {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
padding: 16px 24px;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pagination-info {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #606266;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pagination-controls .el-pagination {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pagination-controls .el-pagination button,
|
|
|
|
|
|
.pagination-controls .el-pagination .el-pager li {
|
|
|
|
|
|
min-width: 36px;
|
|
|
|
|
|
height: 36px;
|
|
|
|
|
|
line-height: 36px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pagination-controls .el-pagination .el-pager li.active {
|
|
|
|
|
|
background-color: #165dff;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 导航栏样式 */
|
|
|
|
|
|
.navigation-tabs {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
|
|
|
|
|
padding: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-tab {
|
|
|
|
|
|
padding: 12px 24px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #606266;
|
|
|
|
|
|
border-right: 1px solid #f0f0f0;
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-tab:last-child {
|
|
|
|
|
|
border-right: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-tab:hover {
|
|
|
|
|
|
color: #409eff;
|
|
|
|
|
|
background-color: #ecf5ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-tab.active {
|
|
|
|
|
|
background-color: #409eff;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-tab {
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
user-select: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 响应式设计 */
|
|
|
|
|
|
@media (max-width: 1200px) {
|
|
|
|
|
|
.team-cards-container {
|
|
|
|
|
|
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
|
.execution-records {
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.navigation-tabs {
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-tab {
|
|
|
|
|
|
flex: 1 0 33%;
|
|
|
|
|
|
padding: 10px 0;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.team-cards-container {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pagination-section {
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 响应式调整图表大小 */
|
|
|
|
|
|
.chart-container {
|
2025-09-17 20:03:00 +08:00
|
|
|
|
min-height: 280px;
|
2025-09-17 15:53:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|