2025-09-17 15:53:38 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<div class="box-container">
|
|
|
|
|
|
<!-- 导航栏 -->
|
2025-09-26 20:32:14 +08:00
|
|
|
|
<!-- <div class="navigation-tabs">
|
2025-09-17 15:53:38 +08:00
|
|
|
|
<div class="nav-tab active" @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" @click="handleInspection7">运维组织</div>
|
2025-09-26 20:32:14 +08:00
|
|
|
|
</div> -->
|
2025-09-17 15:53:38 +08:00
|
|
|
|
<div class="main-content">
|
|
|
|
|
|
<!-- 左侧日历区域 -->
|
|
|
|
|
|
<div class="calendar-container">
|
|
|
|
|
|
<div class="calendar-header">
|
|
|
|
|
|
<div class="calendar-title">待办月视图</div>
|
|
|
|
|
|
<div class="calendar-controls">
|
|
|
|
|
|
<!-- 月份选择器 -->
|
|
|
|
|
|
<el-date-picker v-model="currentDate" type="month" placeholder="选择月份" style="width: 120px; margin-right: 15px" />
|
|
|
|
|
|
<el-button type="primary" @click="goToToday">今日</el-button>
|
|
|
|
|
|
<el-button type="text" icon="el-icon-plus"></el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<!-- 使用 Element Plus 的日历组件 -->
|
|
|
|
|
|
<el-calendar v-model="currentDate">
|
|
|
|
|
|
<template #date-cell="{ date, data }">
|
|
|
|
|
|
<div class="custom-date-cell" :class="getCellClass(data.day)">
|
|
|
|
|
|
<div class="date-day">{{ data.day.split('-').slice(2).join('-') }}</div>
|
|
|
|
|
|
<div class="date-events">
|
|
|
|
|
|
<div v-for="event in getDayEvents(data.day)" :key="event.id" class="event-item" :class="'event-' + event.type">
|
|
|
|
|
|
<div class="event-title">{{ event.title }}</div>
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<div class="event-describeValue">{{ event.describeValue }}</div>
|
2025-09-17 15:53:38 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-calendar>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 右侧表单区域 -->
|
|
|
|
|
|
<div class="form-container">
|
|
|
|
|
|
<div class="form-header">
|
|
|
|
|
|
<h2>今日待办</h2>
|
2025-09-23 20:36:47 +08:00
|
|
|
|
<el-button type="primary" icon="Plus" @click="openAddTaskDialog">添加</el-button>
|
2025-09-17 15:53:38 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<!-- 待办事项列表 - 动态渲染 -->
|
2025-09-17 15:53:38 +08:00
|
|
|
|
<div class="todo-list">
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<div
|
|
|
|
|
|
v-for="item in todoListData"
|
|
|
|
|
|
:key="item.id"
|
|
|
|
|
|
class="todo-item"
|
|
|
|
|
|
:class="{ 'important': item.taskLevel === '重要', 'completed': item.status === 2 }"
|
|
|
|
|
|
>
|
2025-09-26 20:32:14 +08:00
|
|
|
|
<el-checkbox class="todo-checkbox" :checked="item.status === 2" @change="handleStatusChange(item, $event)"></el-checkbox>
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<div
|
|
|
|
|
|
class="todo-color-indicator"
|
|
|
|
|
|
:class="{
|
|
|
|
|
|
normal: item.taskLevel === '常规项' && item.status !== 2,
|
|
|
|
|
|
important: item.taskLevel === '重要' && item.status !== 2,
|
|
|
|
|
|
urgent: item.taskLevel === '紧急' && item.status !== 2,
|
|
|
|
|
|
completed: item.status === 2
|
|
|
|
|
|
}"
|
|
|
|
|
|
></div>
|
2025-09-17 15:53:38 +08:00
|
|
|
|
<div class="todo-content">
|
|
|
|
|
|
<div class="todo-main">
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<div class="todo-title">{{ item.title }}</div>
|
|
|
|
|
|
<div v-if="item.workTimeRange1 || item.workTimeRange2" class="todo-time">
|
|
|
|
|
|
{{ item.workTimeRange1 }}
|
|
|
|
|
|
<span v-if="item.workTimeRange1 && item.workTimeRange2">——</span>
|
|
|
|
|
|
{{ item.workTimeRange2 }}
|
|
|
|
|
|
</div>
|
2025-09-17 15:53:38 +08:00
|
|
|
|
</div>
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<div class="todo-describeValue">{{ item.describeValue }}</div>
|
2025-09-17 15:53:38 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="todo-actions">
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<button class="action-btn edit-btn" @click="handleEdit(item.id)">
|
2025-09-18 19:56:24 +08:00
|
|
|
|
<img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" />
|
|
|
|
|
|
</button>
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<button class="action-btn delete-btn" @click="handleDelete(item.id)">
|
2025-09-18 19:56:24 +08:00
|
|
|
|
<img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" />
|
|
|
|
|
|
</button>
|
2025-09-17 15:53:38 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<!-- 无数据时显示 -->
|
|
|
|
|
|
<div v-if="todoListData.length === 0" class="empty-todo">
|
|
|
|
|
|
<p>暂无待办事项</p>
|
2025-09-17 15:53:38 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 状态图例 - 标签形式 -->
|
|
|
|
|
|
<div class="status-legend">
|
|
|
|
|
|
<span class="status-tag normal"><span class="color-block"></span>常规维护</span>
|
|
|
|
|
|
<span class="status-tag important"><span class="color-block"></span>重要</span>
|
|
|
|
|
|
<span class="status-tag urgent"><span class="color-block"></span>紧急</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-09-22 15:42:13 +08:00
|
|
|
|
<el-dialog
|
|
|
|
|
|
v-model="dialogVisible"
|
|
|
|
|
|
:title="editingTaskId ? '编辑任务' : '新增任务'"
|
|
|
|
|
|
width="480px"
|
|
|
|
|
|
class="custom-dialog"
|
|
|
|
|
|
:before-close="closeDialog"
|
|
|
|
|
|
>
|
2025-09-17 15:53:38 +08:00
|
|
|
|
<el-form :model="taskForm" label-width="80px" class="task-form">
|
|
|
|
|
|
<el-form-item label="任务名称" prop="name">
|
|
|
|
|
|
<el-input v-model="taskForm.name" placeholder="输入任务名称" class="form-input"></el-input>
|
|
|
|
|
|
</el-form-item>
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<el-form-item label="任务描述" prop="describeValue">
|
|
|
|
|
|
<el-input v-model="taskForm.describeValue" placeholder="输入任务描述" class="form-input"></el-input>
|
2025-09-17 15:53:38 +08:00
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="时间" prop="timeRange">
|
|
|
|
|
|
<el-date-picker
|
|
|
|
|
|
v-model="taskForm.timeRange"
|
|
|
|
|
|
type="datetimerange"
|
|
|
|
|
|
start-placeholder="开始时间"
|
|
|
|
|
|
end-placeholder="结束时间"
|
2025-09-22 15:42:13 +08:00
|
|
|
|
:disabled-date="() => false"
|
2025-09-17 15:53:38 +08:00
|
|
|
|
class="form-input"
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</el-form-item>
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<el-form-item label="优先级" prop="taskLevel">
|
|
|
|
|
|
<el-select v-model="taskForm.taskLevel" placeholder="选择优先级" class="form-input">
|
2025-09-17 15:53:38 +08:00
|
|
|
|
<el-option label="常规项" value="常规项"></el-option>
|
|
|
|
|
|
<el-option label="重要" value="重要"></el-option>
|
|
|
|
|
|
<el-option label="紧急" value="紧急"></el-option>
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="任务类型" prop="taskType">
|
|
|
|
|
|
<el-select v-model="taskForm.taskType" placeholder="选择任务类型" class="form-input">
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<el-option label="常规维护" value="1"></el-option>
|
|
|
|
|
|
<el-option label="安全巡检" value="2"></el-option>
|
|
|
|
|
|
<el-option label="系统升级" value="3"></el-option>
|
|
|
|
|
|
<el-option label="数据备份" value="4"></el-option>
|
2025-09-17 15:53:38 +08:00
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<!-- 新增:工作时间段选择器 -->
|
2025-09-22 15:42:13 +08:00
|
|
|
|
<el-form-item label="开始时间" prop="workTimeRange1">
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<el-time-picker
|
|
|
|
|
|
v-model="taskForm.workTimeRange1"
|
|
|
|
|
|
type="timerange"
|
|
|
|
|
|
start-placeholder="开始时间"
|
|
|
|
|
|
end-placeholder="结束时间"
|
|
|
|
|
|
format="HH:mm"
|
|
|
|
|
|
value-format="HH:mm"
|
|
|
|
|
|
class="form-input"
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</el-form-item>
|
2025-09-22 15:42:13 +08:00
|
|
|
|
<el-form-item label="结束时间" prop="workTimeRange2">
|
2025-09-19 20:28:31 +08:00
|
|
|
|
<el-time-picker
|
|
|
|
|
|
v-model="taskForm.workTimeRange2"
|
|
|
|
|
|
type="timerange"
|
|
|
|
|
|
start-placeholder="开始时间"
|
|
|
|
|
|
end-placeholder="结束时间"
|
|
|
|
|
|
format="HH:mm"
|
|
|
|
|
|
value-format="HH:mm"
|
|
|
|
|
|
class="form-input"
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</el-form-item>
|
2025-09-17 15:53:38 +08:00
|
|
|
|
</el-form>
|
|
|
|
|
|
<template #footer>
|
|
|
|
|
|
<el-button @click="closeDialog">取消</el-button>
|
|
|
|
|
|
<el-button type="primary" @click="saveTask">保存任务</el-button>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
2025-09-19 20:28:31 +08:00
|
|
|
|
import { ref, computed, watch, onMounted } from 'vue';
|
2025-09-17 15:53:38 +08:00
|
|
|
|
import router from '@/router';
|
2025-09-19 20:28:31 +08:00
|
|
|
|
import { daibanlist, adddaiban, updatedaiban, deldaiban } from '@/api/zhinengxunjian/daiban/index';
|
2025-09-17 15:53:38 +08:00
|
|
|
|
|
|
|
|
|
|
// 默认显示当前月份
|
|
|
|
|
|
const currentDate = ref(new Date());
|
|
|
|
|
|
|
|
|
|
|
|
// 为了保持兼容性,保留这些变量
|
|
|
|
|
|
const targetYear = 2025;
|
|
|
|
|
|
const years = ref([]);
|
|
|
|
|
|
const selectedYear = ref(currentDate.value.getFullYear());
|
|
|
|
|
|
const selectedMonth = ref(currentDate.value.getMonth() + 1);
|
|
|
|
|
|
|
|
|
|
|
|
// 回到今天
|
|
|
|
|
|
const goToToday = () => {
|
|
|
|
|
|
currentDate.value = new Date();
|
|
|
|
|
|
updateYearAndMonth();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
// 根据workTimeRange1和workTimeRange2生成taskTimeInfo字符串
|
|
|
|
|
|
const getTaskTimeInfoString = () => {
|
|
|
|
|
|
const timeInfoArray = [];
|
|
|
|
|
|
|
|
|
|
|
|
// 处理工作时间段1 - 更宽松的类型处理
|
|
|
|
|
|
if (taskForm.value.workTimeRange1) {
|
|
|
|
|
|
if (Array.isArray(taskForm.value.workTimeRange1)) {
|
|
|
|
|
|
// 如果是数组,直接拼接
|
|
|
|
|
|
timeInfoArray.push(taskForm.value.workTimeRange1.join('-'));
|
|
|
|
|
|
} else if (typeof taskForm.value.workTimeRange1 === 'string') {
|
|
|
|
|
|
// 如果已经是字符串,直接使用
|
|
|
|
|
|
timeInfoArray.push(taskForm.value.workTimeRange1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-17 15:53:38 +08:00
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
// 处理工作时间段2 - 更宽松的类型处理
|
|
|
|
|
|
if (taskForm.value.workTimeRange2) {
|
|
|
|
|
|
if (Array.isArray(taskForm.value.workTimeRange2)) {
|
|
|
|
|
|
// 如果是数组,直接拼接
|
|
|
|
|
|
timeInfoArray.push(taskForm.value.workTimeRange2.join('-'));
|
|
|
|
|
|
} else if (typeof taskForm.value.workTimeRange2 === 'string') {
|
|
|
|
|
|
// 如果已经是字符串,直接使用
|
|
|
|
|
|
timeInfoArray.push(taskForm.value.workTimeRange2);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-17 15:53:38 +08:00
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
// 合并多个时间段为一个字符串,用逗号分隔
|
|
|
|
|
|
return timeInfoArray.join(',');
|
|
|
|
|
|
};
|
2025-09-17 15:53:38 +08:00
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
// 待办事项数据 - 从接口获取
|
|
|
|
|
|
const todoListData = ref([]);
|
|
|
|
|
|
const calendarEvents = ref([]);
|
|
|
|
|
|
|
|
|
|
|
|
// 格式化日期为YYYY-MM-DD格式
|
|
|
|
|
|
const formatDate = (date) => {
|
|
|
|
|
|
if (!date) return '';
|
|
|
|
|
|
const d = new Date(date);
|
|
|
|
|
|
const year = d.getFullYear();
|
|
|
|
|
|
const month = String(d.getMonth() + 1).padStart(2, '0');
|
|
|
|
|
|
const day = String(d.getDate()).padStart(2, '0');
|
|
|
|
|
|
return `${year}-${month}-${day}`;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 格式化时间范围
|
|
|
|
|
|
const formatTimeRange = (startTime, endTime) => {
|
|
|
|
|
|
if (!startTime || !endTime) return '';
|
|
|
|
|
|
const start = new Date(startTime);
|
|
|
|
|
|
const end = new Date(endTime);
|
|
|
|
|
|
const formatHourMinute = (date) => {
|
|
|
|
|
|
const hours = String(date.getHours()).padStart(2, '0');
|
|
|
|
|
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
|
|
|
|
return `${hours}:${minutes}`;
|
|
|
|
|
|
};
|
|
|
|
|
|
return `${formatHourMinute(start)}-${formatHourMinute(end)}`;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 从接口获取数据并处理 - 根据实际返回格式修正版
|
|
|
|
|
|
const fetchData = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const response = await daibanlist();
|
|
|
|
|
|
console.log('接口原始返回:', response); // 打印原始响应,便于调试
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化数据数组
|
|
|
|
|
|
let data = [];
|
|
|
|
|
|
|
|
|
|
|
|
// 根据实际返回格式提取数据,数据在response.rows中
|
|
|
|
|
|
if (response && Array.isArray(response.rows)) {
|
|
|
|
|
|
data = response.rows;
|
|
|
|
|
|
} else if (response.data && Array.isArray(response.data.rows)) {
|
|
|
|
|
|
// 兼容可能的嵌套结构
|
|
|
|
|
|
data = response.data.rows;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.warn('接口返回格式不符合预期,使用空数组', response);
|
|
|
|
|
|
data = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理待办列表数据
|
|
|
|
|
|
todoListData.value = data.map((item) => ({
|
|
|
|
|
|
id: item.id,
|
|
|
|
|
|
title: item.taskName,
|
|
|
|
|
|
describeValue: item.describeValue,
|
|
|
|
|
|
timeRange: formatTimeRange(item.taskBeginTime, item.taskEndTime),
|
|
|
|
|
|
// 保存原始时间用于编辑
|
|
|
|
|
|
originalTimeRange: [new Date(item.taskBeginTime), new Date(item.taskEndTime)],
|
|
|
|
|
|
taskLevel: item.taskLevel === '1' ? '常规项' : item.taskLevel === '2' ? '紧急' : '重要',
|
|
|
|
|
|
// 注意:根据返回数据调整了taskLevel映射,原代码可能颠倒了重要和紧急
|
|
|
|
|
|
taskType: item.taskType,
|
|
|
|
|
|
// 从taskTimeInfo获取时间段数据,格式为"17:00,20:00"
|
|
|
|
|
|
workTimeRange1: item.taskTimeInfo ? item.taskTimeInfo.split(',')[0] || '' : '',
|
|
|
|
|
|
workTimeRange2: item.taskTimeInfo && item.taskTimeInfo.split(',').length > 1 ? item.taskTimeInfo.split(',')[1] : '',
|
|
|
|
|
|
date: formatDate(item.taskBeginTime),
|
|
|
|
|
|
status: item.status || 1 // 添加状态字段,默认1表示未完成
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
// 确保每个项目都有status字段
|
|
|
|
|
|
todoListData.value.forEach((item) => {
|
|
|
|
|
|
if (item.status === undefined) {
|
|
|
|
|
|
item.status = 1; // 默认未完成
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 处理日历事件数据
|
|
|
|
|
|
calendarEvents.value = data.map((item) => ({
|
|
|
|
|
|
id: item.id,
|
|
|
|
|
|
date: formatDate(item.taskBeginTime),
|
|
|
|
|
|
title: item.taskName,
|
|
|
|
|
|
describeValue: item.describeValue,
|
|
|
|
|
|
type: getEventType(item.taskType),
|
|
|
|
|
|
status: item.status // 添加状态信息
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
console.log('数据处理完成,共', data.length, '条记录');
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取待办数据失败:', error);
|
|
|
|
|
|
// 出错时确保数据是数组,避免页面报错
|
|
|
|
|
|
todoListData.value = [];
|
|
|
|
|
|
calendarEvents.value = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 根据任务类型获取事件类型
|
|
|
|
|
|
const getEventType = (taskType) => {
|
|
|
|
|
|
// 任务类型映射: 1-常规维护, 2-安全巡检, 3-系统升级, 4-数据备份
|
|
|
|
|
|
const typeMap = {
|
|
|
|
|
|
'1': 'service', // 常规维护对应service
|
|
|
|
|
|
'2': 'database', // 安全巡检对应database
|
|
|
|
|
|
'3': 'upgrade', // 系统升级对应upgrade
|
|
|
|
|
|
'4': 'network' // 数据备份对应network
|
|
|
|
|
|
};
|
|
|
|
|
|
return typeMap[taskType] || 'service';
|
|
|
|
|
|
};
|
2025-09-17 15:53:38 +08:00
|
|
|
|
|
|
|
|
|
|
// 获取指定日期的事件
|
|
|
|
|
|
const getDayEvents = (dateStr) => {
|
|
|
|
|
|
return calendarEvents.value.filter((event) => event.date === dateStr);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 根据事件类型获取单元格样式
|
|
|
|
|
|
const getCellClass = (date) => {
|
|
|
|
|
|
const events = getDayEvents(date);
|
|
|
|
|
|
if (events.length > 0) {
|
|
|
|
|
|
const eventType = events[0].type;
|
|
|
|
|
|
return `date-cell-${eventType}`;
|
|
|
|
|
|
}
|
|
|
|
|
|
return '';
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 更新年份和月份选择器的值
|
|
|
|
|
|
const updateYearAndMonth = () => {
|
|
|
|
|
|
selectedYear.value = currentDate.value.getFullYear();
|
|
|
|
|
|
selectedMonth.value = currentDate.value.getMonth() + 1;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 监听日期变化,更新年份和月份
|
|
|
|
|
|
watch(currentDate, (newDate) => {
|
|
|
|
|
|
selectedYear.value = newDate.getFullYear();
|
|
|
|
|
|
selectedMonth.value = newDate.getMonth() + 1;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化年份和月份
|
|
|
|
|
|
updateYearAndMonth();
|
|
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
// 组件挂载时获取数据
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
fetchData();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-09-17 15:53:38 +08:00
|
|
|
|
// 弹窗相关状态管理
|
|
|
|
|
|
const dialogVisible = ref(false);
|
|
|
|
|
|
const taskForm = ref({
|
|
|
|
|
|
name: '',
|
2025-09-19 20:28:31 +08:00
|
|
|
|
describeValue: '',
|
|
|
|
|
|
timeRange: null,
|
|
|
|
|
|
taskLevel: '常规项',
|
|
|
|
|
|
taskType: '1', // 默认值为1(常规维护)
|
|
|
|
|
|
workTimeRange1: null, // 工作时间段1
|
|
|
|
|
|
workTimeRange2: null // 工作时间段2
|
2025-09-17 15:53:38 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
// 当前编辑的任务ID,为null表示新建模式
|
|
|
|
|
|
const editingTaskId = ref(null);
|
|
|
|
|
|
|
2025-09-17 15:53:38 +08:00
|
|
|
|
// 打开添加任务弹窗
|
|
|
|
|
|
const openAddTaskDialog = () => {
|
2025-09-19 20:28:31 +08:00
|
|
|
|
// 重置表单为新建状态
|
|
|
|
|
|
editingTaskId.value = null;
|
|
|
|
|
|
taskForm.value = {
|
|
|
|
|
|
name: '',
|
|
|
|
|
|
describeValue: '',
|
|
|
|
|
|
timeRange: null,
|
|
|
|
|
|
taskLevel: '常规项',
|
|
|
|
|
|
taskType: '1',
|
|
|
|
|
|
workTimeRange1: null,
|
|
|
|
|
|
workTimeRange2: null
|
|
|
|
|
|
};
|
2025-09-17 15:53:38 +08:00
|
|
|
|
dialogVisible.value = true;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 关闭弹窗
|
|
|
|
|
|
const closeDialog = () => {
|
|
|
|
|
|
dialogVisible.value = false;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 保存任务
|
2025-09-19 20:28:31 +08:00
|
|
|
|
const saveTask = async () => {
|
|
|
|
|
|
// 表单验证
|
|
|
|
|
|
if (!taskForm.value.name || !taskForm.value.describeValue || !taskForm.value.timeRange) {
|
|
|
|
|
|
// 使用Element Plus的消息提示
|
|
|
|
|
|
ElMessage.warning('请填写必要的任务信息');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证工作时间段
|
|
|
|
|
|
if (!taskForm.value.workTimeRange1 && !taskForm.value.workTimeRange2) {
|
|
|
|
|
|
ElMessage.warning('请至少填写一个工作时间段');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 构建接口所需的数据结构
|
|
|
|
|
|
const apiData = {
|
|
|
|
|
|
createDept: 0, // 根据实际情况设置
|
|
|
|
|
|
createBy: 0, // 根据实际情况设置
|
|
|
|
|
|
createTime: new Date().toISOString(),
|
|
|
|
|
|
updateBy: 0, // 根据实际情况设置
|
|
|
|
|
|
updateTime: new Date().toISOString(),
|
|
|
|
|
|
params: {
|
|
|
|
|
|
property1: 'string',
|
|
|
|
|
|
property2: 'string'
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
projectId: 0, // 根据实际情况设置
|
|
|
|
|
|
taskName: taskForm.value.name,
|
|
|
|
|
|
describeValue: taskForm.value.describeValue,
|
|
|
|
|
|
taskBeginTime: taskForm.value.timeRange[0].toISOString(),
|
|
|
|
|
|
taskEndTime: taskForm.value.timeRange[1].toISOString(),
|
|
|
|
|
|
// 使用taskTimeInfo替代workTimeRange1和workTimeRange2,通过字符串拼接开始和结束时间
|
|
|
|
|
|
taskTimeInfo: getTaskTimeInfoString(),
|
|
|
|
|
|
taskLevel: taskForm.value.taskLevel === '常规项' ? '1' : taskForm.value.taskLevel === '重要' ? '3' : '2',
|
|
|
|
|
|
taskType: taskForm.value.taskType
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let response;
|
|
|
|
|
|
// 判断是新增还是编辑
|
|
|
|
|
|
if (editingTaskId.value) {
|
|
|
|
|
|
// 编辑操作 - 修改参数传递方式,将id合并到apiData中
|
|
|
|
|
|
response = await updatedaiban({ ...apiData, id: editingTaskId.value });
|
|
|
|
|
|
ElMessage.success('任务更新成功');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 新增操作
|
|
|
|
|
|
response = await adddaiban(apiData);
|
|
|
|
|
|
console.log('保存任务成功:', response);
|
|
|
|
|
|
ElMessage.success('任务添加成功');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-22 15:42:13 +08:00
|
|
|
|
// 重新从接口获取最新数据,确保列表数据与后端保持一致
|
|
|
|
|
|
await fetchData();
|
|
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
// 重置表单
|
|
|
|
|
|
taskForm.value = {
|
|
|
|
|
|
name: '',
|
|
|
|
|
|
describeValue: '',
|
|
|
|
|
|
timeRange: null,
|
|
|
|
|
|
taskLevel: '常规项',
|
|
|
|
|
|
taskType: '1',
|
|
|
|
|
|
workTimeRange1: null,
|
|
|
|
|
|
workTimeRange2: null
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 重置编辑状态
|
|
|
|
|
|
editingTaskId.value = null;
|
|
|
|
|
|
|
|
|
|
|
|
// 关闭弹窗
|
|
|
|
|
|
closeDialog();
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('保存任务失败:', error);
|
|
|
|
|
|
ElMessage.error('保存任务失败,请重试');
|
|
|
|
|
|
}
|
2025-09-17 15:53:38 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
// 处理状态变更
|
|
|
|
|
|
const handleStatusChange = async (item, checked) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 更新本地状态
|
|
|
|
|
|
item.status = checked ? 2 : 1;
|
|
|
|
|
|
|
|
|
|
|
|
// 直接更新相关的日历事件以反映状态变化
|
|
|
|
|
|
const calendarEvent = calendarEvents.value.find((event) => event.id === item.id);
|
|
|
|
|
|
if (calendarEvent) {
|
|
|
|
|
|
calendarEvent.status = item.status;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 这里可以添加API调用,更新后端状态
|
|
|
|
|
|
// await updateTaskStatus(item.id, item.status);
|
|
|
|
|
|
|
|
|
|
|
|
console.log('任务状态已更新:', item.id, '状态:', item.status);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('更新任务状态失败:', error);
|
|
|
|
|
|
ElMessage.error('更新任务状态失败,请重试');
|
|
|
|
|
|
// 恢复原始状态
|
|
|
|
|
|
item.status = checked ? 1 : 2;
|
|
|
|
|
|
}
|
2025-09-18 19:56:24 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
// 编辑和删除处理函数
|
|
|
|
|
|
const handleEdit = (id) => {
|
|
|
|
|
|
console.log('执行编辑操作:', id);
|
|
|
|
|
|
// 找到对应的数据项
|
|
|
|
|
|
const item = todoListData.value.find((item) => item.id === id);
|
|
|
|
|
|
if (item) {
|
|
|
|
|
|
// 存储编辑的任务ID
|
|
|
|
|
|
editingTaskId.value = id;
|
|
|
|
|
|
// 填充表单数据,使用原始时间范围
|
|
|
|
|
|
// 处理工作时间段格式:如果是字符串格式(如"HH:mm-HH:mm"),则转换为数组格式
|
|
|
|
|
|
let workTimeRange1 = item.workTimeRange1;
|
|
|
|
|
|
let workTimeRange2 = item.workTimeRange2;
|
|
|
|
|
|
|
|
|
|
|
|
if (typeof workTimeRange1 === 'string' && workTimeRange1.includes('-')) {
|
|
|
|
|
|
workTimeRange1 = workTimeRange1.split('-');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (typeof workTimeRange2 === 'string' && workTimeRange2.includes('-')) {
|
|
|
|
|
|
workTimeRange2 = workTimeRange2.split('-');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
taskForm.value = {
|
|
|
|
|
|
name: item.title,
|
|
|
|
|
|
describeValue: item.describeValue,
|
|
|
|
|
|
timeRange: item.originalTimeRange, // 使用保存的原始时间对象
|
|
|
|
|
|
taskLevel: item.taskLevel,
|
|
|
|
|
|
taskType: item.taskType,
|
|
|
|
|
|
workTimeRange1: workTimeRange1,
|
|
|
|
|
|
workTimeRange2: workTimeRange2
|
|
|
|
|
|
};
|
|
|
|
|
|
// 打开弹窗
|
|
|
|
|
|
dialogVisible.value = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
const handleDelete = (id) => {
|
|
|
|
|
|
console.log('执行删除操作:', id);
|
|
|
|
|
|
ElMessageBox.confirm('确定要删除这个任务吗?', '删除确认', {
|
|
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
|
type: 'warning'
|
|
|
|
|
|
})
|
|
|
|
|
|
.then(async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 对于单个ID,直接作为路径参数传递
|
|
|
|
|
|
// 接口要求格式: /ops/matter/{ids},这里ids是单个ID
|
|
|
|
|
|
await deldaiban(id);
|
|
|
|
|
|
|
2025-09-22 15:42:13 +08:00
|
|
|
|
// 删除成功后重新获取最新数据
|
|
|
|
|
|
await fetchData();
|
2025-09-19 20:28:31 +08:00
|
|
|
|
ElMessage.success('任务已删除');
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('删除任务失败:', error);
|
|
|
|
|
|
ElMessage.error('删除任务失败,请重试');
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(() => {
|
|
|
|
|
|
ElMessage.info('已取消删除');
|
|
|
|
|
|
});
|
2025-09-18 19:56:24 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-17 15:53:38 +08:00
|
|
|
|
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');
|
|
|
|
|
|
};
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.box-container {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
background-color: #f5f7fa;
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
/* 已完成任务的样式 */
|
|
|
|
|
|
.todo-color-indicator.completed {
|
|
|
|
|
|
background-color: #dcdfe6;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.todo-item.completed .todo-content {
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
text-decoration: line-through;
|
|
|
|
|
|
}
|
2025-09-26 20:32:14 +08:00
|
|
|
|
/* 导航栏样式 */
|
|
|
|
|
|
.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;
|
|
|
|
|
|
}
|
2025-09-17 15:53:38 +08:00
|
|
|
|
.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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header {
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header h1 {
|
|
|
|
|
|
font-size: 24px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header p {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #606266;
|
|
|
|
|
|
margin: 5px 0 0 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.main-content {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 20px;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 日历区域样式 */
|
|
|
|
|
|
.calendar-container {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 自定义弹窗样式 */
|
|
|
|
|
|
.custom-dialog {
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-dialog .el-dialog__header {
|
|
|
|
|
|
background-color: #f5f7fa;
|
|
|
|
|
|
border-bottom: 1px solid #e4e7ed;
|
|
|
|
|
|
padding: 15px 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-dialog .el-dialog__title {
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.custom-dialog .el-dialog__body {
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 确保所有输入框长度相等 */
|
|
|
|
|
|
.task-form .form-input {
|
|
|
|
|
|
height: 30px;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 时间选择器样式调整 */
|
|
|
|
|
|
.task-form .el-date-editor {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 30px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.calendar-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.calendar-title {
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.calendar-controls {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.el-select {
|
|
|
|
|
|
margin-right: 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.form-container {
|
|
|
|
|
|
flex: 0 0 360px; /* 调整宽度以匹配设计图,更贴合右侧区域宽度 */
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
padding: 20px 20px 80px 20px; /* 增加底部内边距,为固定标签留出空间 */
|
|
|
|
|
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
position: relative; /* 设置为相对定位,使内部绝对定位元素相对于此容器定位 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
padding-bottom: 10px;
|
|
|
|
|
|
border-bottom: 1px solid #f0f0f0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-header h2 {
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.todo-list {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
max-height: 480px;
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.todo-item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
padding: 12px 12px 12px 20px;
|
|
|
|
|
|
background-color: #fafafa;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.todo-checkbox {
|
|
|
|
|
|
margin-top: 2px;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.todo-content {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.todo-main {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.todo-title {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.todo-time {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
.todo-describeValue {
|
2025-09-17 15:53:38 +08:00
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #606266;
|
|
|
|
|
|
line-height: 1.4;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.todo-actions {
|
|
|
|
|
|
position: absolute;
|
2025-09-19 20:28:31 +08:00
|
|
|
|
right: -120px;
|
2025-09-17 15:53:38 +08:00
|
|
|
|
top: 0;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
display: flex;
|
2025-09-18 19:56:24 +08:00
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
padding: 0 12px;
|
|
|
|
|
|
background-color: inherit;
|
2025-09-17 15:53:38 +08:00
|
|
|
|
opacity: 0;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-18 19:56:24 +08:00
|
|
|
|
.action-btn {
|
|
|
|
|
|
width: 36px;
|
|
|
|
|
|
height: 36px;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
transition: all 0.2s ease;
|
2025-09-17 15:53:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-18 19:56:24 +08:00
|
|
|
|
.action-btn:hover {
|
|
|
|
|
|
background-color: #f5f7fa;
|
|
|
|
|
|
transform: translateY(-1px);
|
|
|
|
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
|
2025-09-17 15:53:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-18 19:56:24 +08:00
|
|
|
|
/* 悬停显示操作按钮 */
|
2025-09-17 15:53:38 +08:00
|
|
|
|
.todo-item:hover .todo-actions {
|
2025-09-26 20:32:14 +08:00
|
|
|
|
background: linear-gradient(to right, rgba(173, 216, 230, 0), rgb(64, 158, 255));
|
2025-09-17 15:53:38 +08:00
|
|
|
|
right: 0;
|
2025-09-26 20:32:14 +08:00
|
|
|
|
opacity: 0.8;
|
2025-09-17 15:53:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 20:32:14 +08:00
|
|
|
|
/* 取消内容区域平移效果 */
|
2025-09-18 19:56:24 +08:00
|
|
|
|
.todo-item:hover .todo-content {
|
2025-09-26 20:32:14 +08:00
|
|
|
|
transform: none;
|
2025-09-18 19:56:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.action-icon {
|
|
|
|
|
|
width: 16px;
|
|
|
|
|
|
height: 16px;
|
|
|
|
|
|
object-fit: contain;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 调整按钮间距 */
|
|
|
|
|
|
.todo-actions {
|
|
|
|
|
|
gap: 12px;
|
2025-09-17 15:53:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
/* 空状态样式 */
|
|
|
|
|
|
.empty-todo {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
height: 200px;
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
background-color: #fafafa;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-17 15:53:38 +08:00
|
|
|
|
.status-legend {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 20px;
|
|
|
|
|
|
padding: 15px 0;
|
|
|
|
|
|
border-top: 1px solid #ebeef5;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.status-tag {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 5px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.status-tag .color-block {
|
|
|
|
|
|
width: 12px;
|
|
|
|
|
|
height: 12px;
|
|
|
|
|
|
border-radius: 2px;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.status-tag.normal .color-block {
|
|
|
|
|
|
background-color: #52c41a;
|
|
|
|
|
|
}
|
|
|
|
|
|
.status-tag.important .color-block {
|
|
|
|
|
|
background-color: #faad14;
|
|
|
|
|
|
}
|
|
|
|
|
|
.status-tag.urgent .color-block {
|
|
|
|
|
|
background-color: #ff4d4f;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.todo-color-indicator {
|
|
|
|
|
|
width: 8px;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
border-radius: 0 4px 4px 0;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.todo-color-indicator.normal {
|
|
|
|
|
|
background-color: #52c41a;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.todo-color-indicator.important {
|
|
|
|
|
|
background-color: #faad14;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.todo-color-indicator.urgent {
|
|
|
|
|
|
background-color: #ff4d4f;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 20:32:14 +08:00
|
|
|
|
:deep(.custom-date-cell) {
|
2025-09-17 15:53:38 +08:00
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
padding: 5px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
box-sizing: border-box; /* 确保内边距不撑大元素 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 系统升级事件样式 */
|
|
|
|
|
|
.event-upgrade {
|
|
|
|
|
|
background-color: #fff1f0;
|
|
|
|
|
|
color: #f5222d;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 日期单元格背景色 - 按事件类型 */
|
|
|
|
|
|
.date-cell-service {
|
|
|
|
|
|
background-color: #e6f7ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.date-cell-database {
|
|
|
|
|
|
background-color: #f0f9ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.date-cell-network {
|
|
|
|
|
|
background-color: #fffbe6;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.date-cell-upgrade {
|
|
|
|
|
|
background-color: #fff1f0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 日历样式优化 */
|
|
|
|
|
|
.el-calendar {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.el-calendar-table {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 穿透作用域,强制设置日历单元格为正方形 */
|
2025-09-26 20:32:14 +08:00
|
|
|
|
:deep(.el-calendar-table td) {
|
2025-09-17 15:53:38 +08:00
|
|
|
|
padding: 2px;
|
|
|
|
|
|
vertical-align: top;
|
|
|
|
|
|
width: 120px; /* 强制宽度 */
|
|
|
|
|
|
height: 120px; /* 强制高度(与宽度一致) */
|
|
|
|
|
|
}
|
2025-09-26 20:32:14 +08:00
|
|
|
|
:deep(.el-calendar-day) {
|
2025-09-17 15:53:38 +08:00
|
|
|
|
padding: 0; /* 移除默认内边距 */
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.date-day {
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
margin-bottom: 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.date-events {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.event-item {
|
|
|
|
|
|
padding: 3px;
|
|
|
|
|
|
margin-bottom: 2px;
|
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.event-title {
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-19 20:28:31 +08:00
|
|
|
|
.event-describeValue {
|
2025-09-17 15:53:38 +08:00
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 服务维护事件样式 */
|
|
|
|
|
|
.event-service {
|
|
|
|
|
|
background-color: #e6f7ff;
|
|
|
|
|
|
color: #1890ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 数据库管理事件样式 */
|
|
|
|
|
|
.event-database {
|
|
|
|
|
|
background-color: #f0f9ff;
|
|
|
|
|
|
color: #36cfc9;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 网络维护事件样式 */
|
|
|
|
|
|
.event-network {
|
|
|
|
|
|
background-color: #fffbe6;
|
|
|
|
|
|
color: #faad14;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 系统升级事件样式 */
|
|
|
|
|
|
.event-upgrade {
|
|
|
|
|
|
background-color: #fff1f0;
|
|
|
|
|
|
color: #f5222d;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|