Files
FileCollect/原型/后台管理页面/task-management.html
T
2025-10-20 07:11:14 +08:00

1118 lines
34 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>任务管理 - 图片收集系统</title>
<!-- 引入Vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<!-- 引入Element UI CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/element-ui@2.15.8/lib/theme-chalk/index.css">
<!-- 引入Element UI JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/element-ui@2.15.8/lib/index.js"></script>
<!-- 引入Font Awesome -->
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- 引入ECharts -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js"></script>
<style>
body {
margin: 0;
padding: 0;
height: 100vh;
background-color: #f0f2f5;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
.container {
height: 100vh;
display: flex;
}
.sidebar {
width: 220px;
background-color: #001529;
color: white;
display: flex;
flex-direction: column;
}
.sidebar-header {
padding: 20px;
text-align: center;
border-bottom: 1px solid #1f2937;
}
.logo {
font-size: 20px;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
}
.logo-icon {
margin-right: 8px;
font-size: 22px;
}
.menu-item {
padding: 15px 20px;
cursor: pointer;
transition: background-color 0.3s;
display: flex;
align-items: center;
}
.menu-item:hover {
background-color: #1f2937;
}
.menu-item.active {
background-color: #1989fa;
}
.menu-icon {
margin-right: 10px;
font-size: 16px;
}
.main-content {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
.header {
background-color: white;
padding: 15px 20px;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.header-title {
font-size: 18px;
font-weight: 600;
color: #303133;
}
.header-actions {
display: flex;
align-items: center;
gap: 15px;
}
.user-info {
display: flex;
align-items: center;
}
.user-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background-color: #1989fa;
color: white;
display: flex;
align-items: center;
justify-content: center;
margin-right: 8px;
font-size: 14px;
}
.user-name {
color: #606266;
}
.content-wrapper {
flex: 1;
padding: 20px;
overflow-y: auto;
}
.card {
background-color: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
margin-bottom: 20px;
}
.search-section {
display: flex;
gap: 15px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.search-input {
width: 250px;
}
.select-wrapper {
width: 200px;
}
.table-wrapper {
overflow-x: auto;
}
.table-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.table-title {
font-size: 16px;
font-weight: 600;
color: #303133;
}
.btn-primary {
background-color: #1989fa;
border-color: #1989fa;
}
.btn-primary:hover {
background-color: #409eff;
border-color: #409eff;
}
.operation-buttons {
display: flex;
gap: 8px;
}
.el-button {
padding: 6px 12px;
font-size: 14px;
}
.dialog-form-item {
margin-bottom: 20px;
}
.dialog-form-label {
font-weight: 500;
color: #303133;
margin-bottom: 8px;
font-size: 14px;
}
.status-badge {
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
}
.status-pending {
background-color: #fdf6ec;
color: #e6a23c;
}
.status-active {
background-color: #f0f9eb;
color: #67c23a;
}
.status-completed {
background-color: #f0f2f5;
color: #909399;
}
.status-expired {
background-color: #fef0f0;
color: #f56c6c;
}
.priority-badge {
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
}
.priority-high {
background-color: #fef0f0;
color: #f56c6c;
}
.priority-medium {
background-color: #fdf6ec;
color: #e6a23c;
}
.priority-low {
background-color: #f0f9eb;
color: #67c23a;
}
.statistics-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-bottom: 20px;
}
.stat-card {
background-color: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
display: flex;
align-items: center;
}
.stat-icon {
width: 48px;
height: 48px;
border-radius: 50%;
background-color: #ecf5ff;
color: #1989fa;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
margin-right: 15px;
}
.stat-content {
flex: 1;
}
.stat-value {
font-size: 24px;
font-weight: 600;
color: #303133;
margin-bottom: 5px;
}
.stat-label {
font-size: 14px;
color: #909399;
}
.logout-btn {
cursor: pointer;
color: #606266;
transition: color 0.3s;
}
.logout-btn:hover {
color: #f56c6c;
}
.progress-bar {
margin-top: 5px;
}
.chart-container {
height: 300px;
width: 100%;
}
.chart-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-bottom: 20px;
}
.department-tag {
margin-right: 5px;
margin-bottom: 5px;
}
.tag-list {
margin-top: 10px;
display: flex;
flex-wrap: wrap;
}
.tag-item {
margin-right: 5px;
margin-bottom: 5px;
cursor: pointer;
}
.tag-item:hover {
opacity: 0.8;
}
.tag-item.active {
background-color: #1989fa;
color: white;
}
</style>
</head>
<body>
<div id="app">
<div class="container">
<!-- 侧边栏 -->
<div class="sidebar">
<div class="sidebar-header">
<div class="logo">
<i class="fa fa-tachometer logo-icon"></i>
<span>管理平台</span>
</div>
</div>
<div class="menu-item" @click="navigateTo('department')">
<i class="fa fa-building-o menu-icon"></i>
<span>部门管理</span>
</div>
<div class="menu-item" @click="navigateTo('user')">
<i class="fa fa-users menu-icon"></i>
<span>用户管理</span>
</div>
<div class="menu-item active" @click="navigateTo('task')">
<i class="fa fa-tasks menu-icon"></i>
<span>任务管理</span>
</div>
<div class="menu-item" @click="navigateTo('image')">
<i class="fa fa-picture-o menu-icon"></i>
<span>图片管理</span>
</div>
</div>
<!-- 主内容区 -->
<div class="main-content">
<!-- 顶部导航栏 -->
<div class="header">
<div class="header-title">任务管理</div>
<div class="header-actions">
<div class="user-info">
<div class="user-avatar"></div>
<span class="user-name">系统管理员</span>
</div>
<div class="logout-btn" @click="handleLogout">
<i class="fa fa-sign-out"></i> 退出
</div>
</div>
</div>
<!-- 内容区域 -->
<div class="content-wrapper">
<!-- 统计卡片 -->
<div class="statistics-cards">
<div class="stat-card">
<div class="stat-icon">
<i class="fa fa-list-alt"></i>
</div>
<div class="stat-content">
<div class="stat-value">{{ taskStats.total }}</div>
<div class="stat-label">总任务数</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon" style="background-color: #f0f9eb; color: #67c23a;">
<i class="fa fa-play-circle"></i>
</div>
<div class="stat-content">
<div class="stat-value">{{ taskStats.active }}</div>
<div class="stat-label">进行中任务</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon" style="background-color: #fef0f0; color: #f56c6c;">
<i class="fa fa-clock-o"></i>
</div>
<div class="stat-content">
<div class="stat-value">{{ taskStats.expired }}</div>
<div class="stat-label">已过期任务</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon" style="background-color: #e6f7ff; color: #1890ff;">
<i class="fa fa-check-circle"></i>
</div>
<div class="stat-content">
<div class="stat-value">{{ taskStats.completed }}</div>
<div class="stat-label">已完成任务</div>
</div>
</div>
</div>
<!-- 图表区域 -->
<div class="chart-row">
<div class="card">
<h3 style="margin-bottom: 20px; color: #303133;">任务状态分布</h3>
<div id="taskStatusChart" class="chart-container"></div>
</div>
<div class="card">
<h3 style="margin-bottom: 20px; color: #303133;">任务优先级分布</h3>
<div id="taskPriorityChart" class="chart-container"></div>
</div>
</div>
<!-- 搜索和操作区域 -->
<div class="card">
<div class="search-section">
<el-input
v-model="searchQuery"
placeholder="搜索任务名称或描述"
prefix-icon="el-icon-search"
class="search-input"
></el-input>
<el-select
v-model="statusFilter"
placeholder="选择状态"
class="select-wrapper"
clearable
>
<el-option label="待发布" value="pending"></el-option>
<el-option label="进行中" value="active"></el-option>
<el-option label="已完成" value="completed"></el-option>
<el-option label="已过期" value="expired"></el-option>
</el-select>
<el-select
v-model="priorityFilter"
placeholder="选择优先级"
class="select-wrapper"
clearable
>
<el-option label="高" value="high"></el-option>
<el-option label="中" value="medium"></el-option>
<el-option label="低" value="low"></el-option>
</el-select>
<el-button
type="primary"
class="btn-primary"
@click="addTask"
>
<i class="fa fa-plus"></i> 新增任务
</el-button>
</div>
</div>
<!-- 任务列表 -->
<div class="card">
<div class="table-header">
<div class="table-title">任务列表</div>
</div>
<div class="table-wrapper">
<el-table :data="filteredTasks" stripe style="width: 100%">
<el-table-column prop="id" label="任务ID" width="80"></el-table-column>
<el-table-column prop="title" label="任务名称" min-width="200">
<template slot-scope="scope">
<div style="font-weight: 500;">{{ scope.row.title }}</div>
<div style="color: #909399; font-size: 12px; margin-top: 2px;">{{ scope.row.description }}</div>
</template>
</el-table-column>
<el-table-column label="关联部门" min-width="150">
<template slot-scope="scope">
<el-tag
v-for="dept in scope.row.departments"
:key="dept.id"
size="small"
class="department-tag"
>
{{ dept.name }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="targetCount" label="目标数量" width="100"></el-table-column>
<el-table-column label="完成进度" min-width="150">
<template slot-scope="scope">
<div>
<div style="display: flex; justify-content: space-between;">
<span>{{ scope.row.uploadedCount }}</span>
<span>{{ scope.row.progress }}%</span>
</div>
<el-progress
:percentage="scope.row.progress"
:status="getProgressStatus(scope.row)"
class="progress-bar"
></el-progress>
</div>
</template>
</el-table-column>
<el-table-column prop="priority" label="优先级" width="100">
<template slot-scope="scope">
<span
class="priority-badge"
:class="{
'priority-high': scope.row.priority === 'high',
'priority-medium': scope.row.priority === 'medium',
'priority-low': scope.row.priority === 'low'
}"
>
{{ getPriorityText(scope.row.priority) }}
</span>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="100">
<template slot-scope="scope">
<span
class="status-badge"
:class="{
'status-pending': scope.row.status === 'pending',
'status-active': scope.row.status === 'active',
'status-completed': scope.row.status === 'completed',
'status-expired': scope.row.status === 'expired'
}"
>
{{ getStatusText(scope.row.status) }}
</span>
</template>
</el-table-column>
<el-table-column prop="deadline" label="截止日期" min-width="150">
<template slot-scope="scope">
<div :class="{ 'text-danger': isExpired(scope.row.deadline) }">
{{ formatDate(scope.row.deadline) }}
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="200" fixed="right">
<template slot-scope="scope">
<div class="operation-buttons">
<el-button
type="primary"
size="small"
@click="editTask(scope.row)"
>
编辑
</el-button>
<el-button
v-if="scope.row.status === 'pending'"
type="success"
size="small"
@click="publishTask(scope.row.id)"
>
发布
</el-button>
<el-button
v-if="scope.row.status === 'active'"
type="warning"
size="small"
@click="completeTask(scope.row.id)"
>
完成
</el-button>
<el-button
type="danger"
size="small"
@click="deleteTask(scope.row.id)"
>
删除
</el-button>
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</div>
</div>
<!-- 任务对话框 -->
<el-dialog
:title="dialogTitle"
:visible.sync="showDialog"
width="700px"
>
<div class="dialog-form-item">
<div class="dialog-form-label">任务名称</div>
<el-input
v-model="taskForm.title"
placeholder="请输入任务名称"
></el-input>
</div>
<div class="dialog-form-item">
<div class="dialog-form-label">任务描述</div>
<el-input
v-model="taskForm.description"
type="textarea"
rows="3"
placeholder="请输入任务描述"
></el-input>
</div>
<div class="dialog-form-item">
<div class="dialog-form-label">关联部门</div>
<el-select
v-model="taskForm.departmentIds"
multiple
placeholder="请选择关联部门"
>
<el-option
v-for="dept in departments"
:key="dept.id"
:label="dept.name"
:value="dept.id"
></el-option>
</el-select>
</div>
<div class="dialog-form-item">
<div class="dialog-form-label">目标数量</div>
<el-input-number
v-model="taskForm.targetCount"
:min="1"
:step="1"
placeholder="请输入目标数量"
></el-input-number>
</div>
<div class="dialog-form-item">
<div class="dialog-form-label">优先级</div>
<el-radio-group v-model="taskForm.priority">
<el-radio label="high"></el-radio>
<el-radio label="medium"></el-radio>
<el-radio label="low"></el-radio>
</el-radio-group>
</div>
<div class="dialog-form-item">
<div class="dialog-form-label">截止日期</div>
<el-date-picker
v-model="taskForm.deadline"
type="date"
placeholder="选择日期"
style="width: 100%;"
></el-date-picker>
</div>
<div slot="footer">
<el-button @click="showDialog = false">取消</el-button>
<el-button
type="primary"
@click="saveTask"
:loading="saving"
>
保存
</el-button>
</div>
</el-dialog>
</div>
<script>
new Vue({
el: '#app',
data() {
return {
searchQuery: '',
statusFilter: '',
priorityFilter: '',
showDialog: false,
dialogTitle: '新增任务',
saving: false,
departments: [
{ id: 1, name: '技术部' },
{ id: 2, name: '市场部' },
{ id: 3, name: '人力资源部' },
{ id: 4, name: '财务部' },
{ id: 5, name: '行政部' }
],
tasks: [
{
id: 1,
title: '产品包装图片采集',
description: '收集各类产品的包装图片,用于官网展示',
departmentIds: [1, 2],
departments: [
{ id: 1, name: '技术部' },
{ id: 2, name: '市场部' }
],
targetCount: 100,
uploadedCount: 78,
progress: 78,
priority: 'high',
status: 'active',
deadline: '2023-12-31'
},
{
id: 2,
title: '办公环境照片拍摄',
description: '拍摄新办公区域的环境照片',
departmentIds: [5],
departments: [
{ id: 5, name: '行政部' }
],
targetCount: 50,
uploadedCount: 32,
progress: 64,
priority: 'medium',
status: 'active',
deadline: '2023-12-15'
},
{
id: 3,
title: '活动现场照片收集',
description: '收集最近市场活动的现场照片',
departmentIds: [2],
departments: [
{ id: 2, name: '市场部' }
],
targetCount: 200,
uploadedCount: 200,
progress: 100,
priority: 'medium',
status: 'completed',
deadline: '2023-11-30'
},
{
id: 4,
title: '员工证件照更新',
description: '收集所有员工的最新证件照',
departmentIds: [3],
departments: [
{ id: 3, name: '人力资源部' }
],
targetCount: 150,
uploadedCount: 120,
progress: 80,
priority: 'low',
status: 'active',
deadline: '2024-01-15'
},
{
id: 5,
title: '财务凭证扫描',
description: '扫描并上传近期财务凭证',
departmentIds: [4],
departments: [
{ id: 4, name: '财务部' }
],
targetCount: 300,
uploadedCount: 180,
progress: 60,
priority: 'high',
status: 'pending',
deadline: '2024-01-10'
},
{
id: 6,
title: '设备库存盘点',
description: '拍摄所有IT设备的照片用于库存盘点',
departmentIds: [1],
departments: [
{ id: 1, name: '技术部' }
],
targetCount: 80,
uploadedCount: 40,
progress: 50,
priority: 'medium',
status: 'expired',
deadline: '2023-11-20'
}
],
taskForm: {
id: '',
title: '',
description: '',
departmentIds: [],
departments: [],
targetCount: 1,
uploadedCount: 0,
progress: 0,
priority: 'medium',
status: 'pending',
deadline: ''
},
taskStats: {
total: 6,
active: 3,
completed: 1,
expired: 1,
pending: 1
}
}
},
computed: {
filteredTasks() {
return this.tasks.filter(task => {
// 搜索任务名称或描述
const matchesSearch = !this.searchQuery ||
task.title.toLowerCase().includes(this.searchQuery.toLowerCase()) ||
task.description.toLowerCase().includes(this.searchQuery.toLowerCase());
// 状态筛选
const matchesStatus = !this.statusFilter ||
task.status === this.statusFilter;
// 优先级筛选
const matchesPriority = !this.priorityFilter ||
task.priority === this.priorityFilter;
return matchesSearch && matchesStatus && matchesPriority;
});
},
isNewTask() {
return !this.taskForm.id;
}
},
mounted() {
this.initCharts();
},
methods: {
// 初始化图表
initCharts() {
// 任务状态分布图表
const statusChart = echarts.init(document.getElementById('taskStatusChart'));
const statusOption = {
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left'
},
series: [
{
name: '任务状态',
type: 'pie',
radius: '50%',
data: [
{ value: this.taskStats.active, name: '进行中', itemStyle: { color: '#67c23a' } },
{ value: this.taskStats.completed, name: '已完成', itemStyle: { color: '#909399' } },
{ value: this.taskStats.expired, name: '已过期', itemStyle: { color: '#f56c6c' } },
{ value: this.taskStats.pending, name: '待发布', itemStyle: { color: '#e6a23c' } }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
statusChart.setOption(statusOption);
// 任务优先级分布图表
const priorityChart = echarts.init(document.getElementById('taskPriorityChart'));
const priorityOption = {
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left'
},
series: [
{
name: '任务优先级',
type: 'pie',
radius: '50%',
data: [
{ value: this.tasks.filter(t => t.priority === 'high').length, name: '高', itemStyle: { color: '#f56c6c' } },
{ value: this.tasks.filter(t => t.priority === 'medium').length, name: '中', itemStyle: { color: '#e6a23c' } },
{ value: this.tasks.filter(t => t.priority === 'low').length, name: '低', itemStyle: { color: '#67c23a' } }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
priorityChart.setOption(priorityOption);
// 监听窗口大小变化
window.addEventListener('resize', () => {
statusChart.resize();
priorityChart.resize();
});
},
// 导航到其他页面
navigateTo(page) {
let url = '';
switch (page) {
case 'department':
url = 'department-management.html';
break;
case 'user':
url = 'user-management.html';
break;
case 'task':
url = 'task-management.html';
break;
case 'image':
url = 'image-management.html';
break;
}
if (url && url !== window.location.pathname) {
window.location.href = url;
}
},
// 格式化日期
formatDate(dateStr) {
return dateStr;
},
// 判断是否过期
isExpired(dateStr) {
const today = new Date();
const deadline = new Date(dateStr);
return deadline < today;
},
// 获取优先级文本
getPriorityText(priority) {
const priorityMap = {
'high': '高',
'medium': '中',
'low': '低'
};
return priorityMap[priority] || '中';
},
// 获取状态文本
getStatusText(status) {
const statusMap = {
'pending': '待发布',
'active': '进行中',
'completed': '已完成',
'expired': '已过期'
};
return statusMap[status] || '待发布';
},
// 获取进度条状态
getProgressStatus(task) {
if (task.progress === 100) {
return 'success';
} else if (isExpired(task.deadline)) {
return 'exception';
} else {
return 'primary';
}
},
// 新增任务
addTask() {
this.dialogTitle = '新增任务';
this.taskForm = {
id: '',
title: '',
description: '',
departmentIds: [],
departments: [],
targetCount: 1,
uploadedCount: 0,
progress: 0,
priority: 'medium',
status: 'pending',
deadline: ''
};
this.showDialog = true;
},
// 编辑任务
editTask(task) {
this.dialogTitle = '编辑任务';
this.taskForm = { ...task };
// 将departments数组转换为departmentIds数组
this.taskForm.departmentIds = task.departments.map(d => d.id);
this.showDialog = true;
},
// 保存任务
saveTask() {
// 表单验证
if (!this.taskForm.title.trim()) {
this.$message.error('请输入任务名称');
return;
}
if (!this.taskForm.departmentIds || this.taskForm.departmentIds.length === 0) {
this.$message.error('请选择关联部门');
return;
}
if (!this.taskForm.deadline) {
this.$message.error('请选择截止日期');
return;
}
// 更新部门信息
const selectedDepartments = this.departments.filter(d =>
this.taskForm.departmentIds.includes(d.id)
);
this.taskForm.departments = selectedDepartments;
this.saving = true;
// 模拟保存操作
setTimeout(() => {
if (this.taskForm.id) {
// 编辑现有任务
const index = this.tasks.findIndex(t => t.id === this.taskForm.id);
if (index > -1) {
this.tasks[index] = { ...this.taskForm };
this.$message.success('任务信息已更新');
}
} else {
// 添加新任务
const newId = Math.max(...this.tasks.map(t => t.id), 0) + 1;
const newTask = {
...this.taskForm,
id: newId,
uploadedCount: 0,
progress: 0,
status: 'pending'
};
this.tasks.unshift(newTask);
// 更新统计数据
this.taskStats.total++;
this.taskStats.pending++;
this.$message.success('任务已创建');
}
this.saving = false;
this.showDialog = false;
this.initCharts(); // 重新初始化图表
}, 1000);
},
// 发布任务
publishTask(taskId) {
this.$confirm(`确定要发布该任务吗?发布后任务将变为进行中状态。`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const index = this.tasks.findIndex(t => t.id === taskId);
if (index > -1) {
this.tasks[index].status = 'active';
this.taskStats.pending--;
this.taskStats.active++;
this.$message.success('任务已发布');
this.initCharts(); // 重新初始化图表
}
}).catch(() => {
// 取消发布
});
},
// 完成任务
completeTask(taskId) {
this.$confirm(`确定要将该任务标记为已完成吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const index = this.tasks.findIndex(t => t.id === taskId);
if (index > -1) {
this.tasks[index].status = 'completed';
this.taskStats.active--;
this.taskStats.completed++;
this.$message.success('任务已完成');
this.initCharts(); // 重新初始化图表
}
}).catch(() => {
// 取消操作
});
},
// 删除任务
deleteTask(taskId) {
this.$confirm(`确定要删除该任务吗?删除后将无法恢复。`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
const index = this.tasks.findIndex(t => t.id === taskId);
if (index > -1) {
const task = this.tasks[index];
this.tasks.splice(index, 1);
// 更新统计数据
this.taskStats.total--;
if (task.status === 'pending') {
this.taskStats.pending--;
} else if (task.status === 'active') {
this.taskStats.active--;
} else if (task.status === 'completed') {
this.taskStats.completed--;
} else if (task.status === 'expired') {
this.taskStats.expired--;
}
this.$message.success('任务已删除');
this.initCharts(); // 重新初始化图表
}
}).catch(() => {
// 取消删除
});
},
// 处理退出登录
handleLogout() {
this.$confirm('确定要退出登录吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$message.success('退出成功');
setTimeout(() => {
window.location.href = 'admin-login.html';
}, 1000);
}).catch(() => {
// 取消退出
});
}
}
})
</script>
</body>
</html>