This commit is contained in:
dhr
2025-09-19 20:28:31 +08:00
parent b3a6918fef
commit aa443c3d62
12 changed files with 1539 additions and 572 deletions

View File

@ -5,7 +5,7 @@ VITE_APP_TITLE = 新能源场站智慧运维平台
VITE_APP_ENV = 'development'
# 开发环境
VITE_APP_BASE_API = 'http://192.168.110.180:18899'
VITE_APP_BASE_API = 'http://192.168.110.149:18899'
# 应用访问路径 例如使用前缀 /admin/
VITE_APP_CONTEXT_PATH = '/'

View File

@ -17,6 +17,8 @@
"MaybeRefOrGetter": true,
"PropType": true,
"Ref": true,
"Slot": true,
"Slots": true,
"VNode": true,
"WritableComputedRef": true,
"acceptHMRUpdate": true,
@ -35,6 +37,7 @@
"createInjectionState": true,
"createPinia": true,
"createReactiveFn": true,
"createRef": true,
"createReusableTemplate": true,
"createSharedComposable": true,
"createTemplatePromise": true,
@ -315,9 +318,6 @@
"watchThrottled": true,
"watchTriggerable": true,
"watchWithFilter": true,
"whenever": true,
"Slot": true,
"Slots": true,
"createRef": true
"whenever": true
}
}

View File

@ -0,0 +1,34 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
//查询列表
export const daibanlist = (query) => {
return request({
url: '/ops/matter/list',
method: 'get',
params: query
});
};
//新增待办事项
export const adddaiban = (data) => {
return request({
url: '/ops/matter',
method: 'post',
data: data
});
};
//修改待办事项
export const updatedaiban = (data) => {
return request({
url: '/ops/matter',
method: 'put',
data: data
});
};
//删除待办事项
export function deldaiban(ids) {
return request({
url: `/ops/matter/${ids}`, // 拼接ids作为路径参数
method: 'delete'
});
}

View File

@ -0,0 +1,63 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { ItemVO, ItemForm, ItemQuery } from '@/api/zhinengxunjian/inspection/item/types';
/**
* 查询运维-巡检-自定义巡检项列表
* @param query
* @returns {*}
*/
export const listItem = (query?: ItemQuery): AxiosPromise<ItemVO[]> => {
return request({
url: '/ops/item/list',
method: 'get',
params: query
});
};
/**
* 查询运维-巡检-自定义巡检项详细
* @param id
*/
export const getItem = (id: string | number): AxiosPromise<ItemVO> => {
return request({
url: '/ops/item/' + id,
method: 'get'
});
};
/**
* 新增运维-巡检-自定义巡检项
* @param data
*/
export const addItem = (data: ItemForm) => {
return request({
url: '/ops/item',
method: 'post',
data: data
});
};
/**
* 修改运维-巡检-自定义巡检项
* @param data
*/
export const updateItem = (data: ItemForm) => {
return request({
url: '/ops/item',
method: 'put',
data: data
});
};
/**
* 删除运维-巡检-自定义巡检项
* @param id
*/
export const delItem = (id: string | number | Array<string | number>) => {
return request({
url: '/ops/item/' + id,
method: 'delete'
});
};

View File

@ -0,0 +1,46 @@
export interface ItemVO {
/**
*
*/
id: string | number;
/**
* 自定义巡检项名称
*/
name: string;
/**
* 业务id巡检计划1
*/
type: string;
}
export interface ItemForm extends BaseEntity {
/**
* 自定义巡检项名称
*/
name?: string;
/**
* 业务id巡检计划1
*/
type?: string;
projectId?: number;
}
export interface ItemQuery extends PageQuery {
/**
* 自定义巡检项名称
*/
name?: string;
/**
* 业务id巡检计划1
*/
type?: string;
/**
* 日期范围参数
*/
params?: any;
}

View File

@ -0,0 +1,49 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
//查询列表
export const xunjianlist = (query) => {
return request({
url: '/ops/plan/list',
method: 'get',
params: query
});
};
//新增
export const addxunjian = (data) => {
return request({
url: '/ops/plan',
method: 'post',
data: data
});
};
//修改
export const updatexunjian = (data) => {
return request({
url: '/ops/plan',
method: 'put',
data: data
});
};
//删除
export const delxunjian = (ids) => {
return request({
url: `/ops/plan/${ids}`,
method: 'delete'
});
};
//查询人员
export const xunjianUserlist = (query) => {
return request({
url: '/ops/constructionUser/list',
method: 'get',
params: query
});
};
//查询巡检项
export const xunjianItemlist = (query) => {
return request({
url: '/ops/item/list',
method: 'get',
params: query
});
};

View File

@ -0,0 +1,225 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="自定义巡检项名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入自定义巡检项名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['inspection:item:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['inspection:item:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['inspection:item:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['inspection:item:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="itemList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="" align="center" prop="id" v-if="true" />
<el-table-column label="自定义巡检项名称" align="center" prop="name" />
<el-table-column label="业务id巡检计划1" align="center" prop="type" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['inspection:item:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['inspection:item:remove']"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改运维-巡检-自定义巡检项对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="650px" append-to-body>
<el-form ref="itemFormRef" :model="form" :rules="rules" label-width="135px">
<el-form-item label="自定义巡检项名称" prop="name">
<el-input v-model="form.name" placeholder="请输入自定义巡检项名称" />
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select v-model="form.type" placeholder="请选择类型">
<el-option label="巡检管理" value="1" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="Item" lang="ts">
import { listItem, getItem, delItem, addItem, updateItem } from '@/api/zhinengxunjian/inspection/item/index';
import { ItemVO, ItemQuery, ItemForm } from '@/api/zhinengxunjian/inspection/item/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const itemList = ref<ItemVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const itemFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: ItemForm = {
name: undefined,
type: '1',
projectId: 1
};
const data = reactive<PageData<ItemForm, ItemQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
name: undefined,
type: undefined,
params: {}
},
rules: {
name: [{ required: true, message: '自定义巡检项名称不能为空', trigger: 'blur' }],
type: [{ required: true, message: '业务id巡检计划1不能为空', trigger: 'change' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询运维-巡检-自定义巡检项列表 */
const getList = async () => {
loading.value = true;
const res = await listItem(queryParams.value);
itemList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
itemFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ItemVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加运维-巡检-自定义巡检项';
};
/** 修改按钮操作 */
const handleUpdate = async (row?: ItemVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getItem(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改运维-巡检-自定义巡检项';
};
/** 提交按钮 */
const submitForm = () => {
itemFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateItem(form.value).finally(() => (buttonLoading.value = false));
} else {
await addItem(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
/** 删除按钮操作 */
const handleDelete = async (row?: ItemVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除运维-巡检-自定义巡检项编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delItem(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'inspection/item/export',
{
...queryParams.value
},
`item_${new Date().getTime()}.xlsx`
);
};
onMounted(() => {
getList();
});
</script>

File diff suppressed because it is too large Load Diff

View File

@ -25,8 +25,6 @@
<div class="calendar-controls">
<!-- 月份选择器 -->
<el-date-picker v-model="currentDate" type="month" placeholder="选择月份" style="width: 120px; margin-right: 15px" />
<el-button type="primary">添加</el-button>
<el-button type="primary" @click="goToToday">今日</el-button>
<el-button type="text" icon="el-icon-plus"></el-button>
</div>
@ -39,7 +37,7 @@
<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>
<div class="event-description">{{ event.description }}</div>
<div class="event-describeValue">{{ event.describeValue }}</div>
</div>
</div>
</div>
@ -54,128 +52,48 @@
<el-button type="primary" size="small" icon="el-icon-plus" @click="openAddTaskDialog">添加</el-button>
</div>
<!-- 待办事项列表 -->
<!-- 待办事项列表 - 动态渲染 -->
<div class="todo-list">
<!-- 待办项1 - 常规维护 -->
<div class="todo-item">
<div class="todo-color-indicator normal"></div>
<el-checkbox class="todo-checkbox"></el-checkbox>
<div
v-for="item in todoListData"
:key="item.id"
class="todo-item"
:class="{ 'important': item.taskLevel === '重要', 'completed': item.status === 2 }"
>
<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>
<el-checkbox class="todo-checkbox" :checked="item.status === 2" @change="handleStatusChange(item, $event)"></el-checkbox>
<div class="todo-content">
<div class="todo-main">
<div class="todo-title">服务器例行检查</div>
<div class="todo-time">09:00-10:00 AM</div>
<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>
</div>
<div class="todo-description">检查所有生产服务器的CPU内存磁盘使用率确保正常运行</div>
<div class="todo-describeValue">{{ item.describeValue }}</div>
</div>
<div class="todo-actions">
<button class="action-btn edit-btn" @click="handleEdit">
<button class="action-btn edit-btn" @click="handleEdit(item.id)">
<img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" />
</button>
<button class="action-btn delete-btn" @click="handleDelete">
<button class="action-btn delete-btn" @click="handleDelete(item.id)">
<img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" />
</button>
</div>
</div>
<!-- 待办项2 - 重要 -->
<div class="todo-item important">
<div class="todo-color-indicator important"></div>
<el-checkbox class="todo-checkbox"></el-checkbox>
<div class="todo-content">
<div class="todo-main">
<div class="todo-title">数据库备份</div>
<div class="todo-time">14:00-15:00 PM</div>
</div>
<div class="todo-description">主要数据库全备份并验证备份文件完整性</div>
</div>
<div class="todo-actions">
<button class="action-btn edit-btn" @click="handleEdit">
<img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" />
</button>
<button class="action-btn delete-btn" @click="handleDelete">
<img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" />
</button>
</div>
</div>
<!-- 待办项3 - 紧急 -->
<div class="todo-item">
<div class="todo-color-indicator urgent"></div>
<el-checkbox class="todo-checkbox"></el-checkbox>
<div class="todo-content">
<div class="todo-main">
<div class="todo-title">网络设备固件更新</div>
<div class="todo-time">18:00-20:00 PM</div>
</div>
<div class="todo-description">更新核心交换机和防火墙固件需安排在业务低峰期</div>
</div>
<div class="todo-actions">
<button class="action-btn edit-btn" @click="handleEdit">
<img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" />
</button>
<button class="action-btn delete-btn" @click="handleDelete">
<img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" />
</button>
</div>
</div>
<!-- 待办项4 - 常规维护 -->
<div class="todo-item">
<div class="todo-color-indicator normal"></div>
<el-checkbox class="todo-checkbox"></el-checkbox>
<div class="todo-content">
<div class="todo-main">
<div class="todo-title">服务器例行检查</div>
<div class="todo-time">08:00-09:00 AM</div>
</div>
<div class="todo-description">检查所有生产服务器的CPU内存磁盘使用率确保正常运行</div>
</div>
<div class="todo-actions">
<button class="action-btn edit-btn" @click="handleEdit">
<img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" />
</button>
<button class="action-btn delete-btn" @click="handleDelete">
<img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" />
</button>
</div>
</div>
<div class="todo-item">
<div class="todo-color-indicator normal"></div>
<el-checkbox class="todo-checkbox"></el-checkbox>
<div class="todo-content">
<div class="todo-main">
<div class="todo-title">服务器例行检查</div>
<div class="todo-time">06:00-07:00 AM</div>
</div>
<div class="todo-description">检查所有生产服务器的CPU内存磁盘使用率确保正常运行</div>
</div>
<div class="todo-actions">
<button class="action-btn edit-btn" @click="handleEdit">
<img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" />
</button>
<button class="action-btn delete-btn" @click="handleDelete">
<img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" />
</button>
</div>
</div>
<div class="todo-item">
<div class="todo-color-indicator normal"></div>
<el-checkbox class="todo-checkbox"></el-checkbox>
<div class="todo-content">
<div class="todo-main">
<div class="todo-title">服务器例行检查</div>
<div class="todo-time">06:00-07:00 AM</div>
</div>
<div class="todo-description">检查所有生产服务器的CPU内存磁盘使用率确保正常运行</div>
</div>
<div class="todo-actions">
<button class="action-btn edit-btn" @click="handleEdit">
<img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" />
</button>
<button class="action-btn delete-btn" @click="handleDelete">
<img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" />
</button>
</div>
<!-- 无数据时显示 -->
<div v-if="todoListData.length === 0" class="empty-todo">
<p>暂无待办事项</p>
</div>
</div>
@ -192,8 +110,8 @@
<el-form-item label="任务名称" prop="name">
<el-input v-model="taskForm.name" placeholder="输入任务名称" class="form-input"></el-input>
</el-form-item>
<el-form-item label="任务描述" prop="description">
<el-input v-model="taskForm.description" placeholder="输入任务描述" class="form-input"></el-input>
<el-form-item label="任务描述" prop="describeValue">
<el-input v-model="taskForm.describeValue" placeholder="输入任务描述" class="form-input"></el-input>
</el-form-item>
<el-form-item label="时间" prop="timeRange">
<el-date-picker
@ -205,8 +123,8 @@
style="width: 100%"
/>
</el-form-item>
<el-form-item label="优先级" prop="priority">
<el-select v-model="taskForm.priority" placeholder="选择优先级" class="form-input">
<el-form-item label="优先级" prop="taskLevel">
<el-select v-model="taskForm.taskLevel" placeholder="选择优先级" class="form-input">
<el-option label="常规项" value="常规项"></el-option>
<el-option label="重要" value="重要"></el-option>
<el-option label="紧急" value="紧急"></el-option>
@ -214,12 +132,37 @@
</el-form-item>
<el-form-item label="任务类型" prop="taskType">
<el-select v-model="taskForm.taskType" placeholder="选择任务类型" class="form-input">
<el-option label="常规维护" value="常规维护"></el-option>
<el-option label="安全巡检" value="安全巡检"></el-option>
<el-option label="系统升级" value="系统升级"></el-option>
<el-option label="数据备份" value="数据备份"></el-option>
<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>
</el-select>
</el-form-item>
<!-- 新增工作时间段选择器 -->
<el-form-item label="工作时间段1" prop="workTimeRange1">
<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>
<el-form-item label="工作时间段2" prop="workTimeRange2">
<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>
</el-form>
<template #footer>
<el-button @click="closeDialog">取消</el-button>
@ -231,9 +174,10 @@
</template>
<script setup>
import { ref, computed, watch } from 'vue';
import { ref, computed, watch, onMounted } from 'vue';
import router from '@/router';
import TitleComponent from './TitleComponent.vue';
import { daibanlist, adddaiban, updatedaiban, deldaiban } from '@/api/zhinengxunjian/daiban/index';
// 默认显示当前月份
const currentDate = ref(new Date());
@ -244,46 +188,144 @@ const years = ref([]);
const selectedYear = ref(currentDate.value.getFullYear());
const selectedMonth = ref(currentDate.value.getMonth() + 1);
// 减少月份
const decreaseMonth = () => {
const date = new Date(currentDate.value);
date.setMonth(date.getMonth() - 1);
currentDate.value = date;
updateYearAndMonth();
};
// 增加月份
const increaseMonth = () => {
const date = new Date(currentDate.value);
date.setMonth(date.getMonth() + 1);
currentDate.value = date;
updateYearAndMonth();
};
// 回到今天
const goToToday = () => {
currentDate.value = new Date();
updateYearAndMonth();
};
// 日历事件数据 - 2025年9月的随机事件
const calendarEvents = ref([
// 服务维护事件
{ id: 1, date: '2025-09-11', title: '服务维护', description: '维护公司内部服务器', type: 'service' },
{ id: 2, date: '2025-09-28', title: '服务维护', description: '先所有旧服务器部署新内存', type: 'service' },
// 根据workTimeRange1和workTimeRange2生成taskTimeInfo字符串
const getTaskTimeInfoString = () => {
const timeInfoArray = [];
// 数据库管理事件
{ id: 3, date: '2025-09-21', title: '数据库管理', description: '定期执行数据库优化', type: 'database' },
{ id: 4, date: '2025-09-30', title: '数据库管理', description: '大型数据库备份策略', type: 'database' },
// 处理工作时间段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);
}
}
// 网络维护事件
{ id: 5, date: '2025-09-05', title: '网络维护', description: '网络设备例行检查', type: 'network' },
{ id: 6, date: '2025-09-15', title: '网络维护', description: '更新网络安全策略', type: 'network' },
// 处理工作时间段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);
}
}
// 系统升级事件
{ id: 7, date: '2025-09-18', title: '系统升级', description: '核心系统版本升级', type: 'upgrade' },
{ id: 8, date: '2025-09-25', title: '系统升级', description: '应用服务升级部署', type: 'upgrade' }
]);
// 合并多个时间段为一个字符串,用逗号分隔
return timeInfoArray.join(',');
};
// 待办事项数据 - 从接口获取
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';
};
// 获取指定日期的事件
const getDayEvents = (dateStr) => {
@ -315,18 +357,39 @@ watch(currentDate, (newDate) => {
// 初始化年份和月份
updateYearAndMonth();
// 组件挂载时获取数据
onMounted(() => {
fetchData();
});
// 弹窗相关状态管理
const dialogVisible = ref(false);
const taskForm = ref({
name: '',
description: '',
timeRange: '',
priority: '常规项',
taskType: '常规维护'
describeValue: '',
timeRange: null,
taskLevel: '常规项',
taskType: '1', // 默认值为1常规维护
workTimeRange1: null, // 工作时间段1
workTimeRange2: null // 工作时间段2
});
// 当前编辑的任务ID为null表示新建模式
const editingTaskId = ref(null);
// 打开添加任务弹窗
const openAddTaskDialog = () => {
// 重置表单为新建状态
editingTaskId.value = null;
taskForm.value = {
name: '',
describeValue: '',
timeRange: null,
taskLevel: '常规项',
taskType: '1',
workTimeRange1: null,
workTimeRange2: null
};
dialogVisible.value = true;
};
@ -336,30 +399,241 @@ const closeDialog = () => {
};
// 保存任务
const saveTask = () => {
// 这里可以添加表单验证和保存逻辑
console.log('保存任务:', taskForm.value);
// 重置表单
taskForm.value = {
name: '',
description: '',
timeRange: '',
priority: '常规项',
taskType: '常规维护'
};
// 关闭弹窗
closeDialog();
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 });
// 更新本地数据
const index = todoListData.value.findIndex((item) => item.id === editingTaskId.value);
if (index !== -1) {
todoListData.value[index] = {
...todoListData.value[index],
title: taskForm.value.name,
describeValue: taskForm.value.describeValue,
timeRange: formatTimeRange(taskForm.value.timeRange[0], taskForm.value.timeRange[1]),
originalTimeRange: taskForm.value.timeRange,
taskLevel: taskForm.value.taskLevel,
taskType: taskForm.value.taskType,
// 保留原有字段以便前端显示,添加类型检查
workTimeRange1: taskForm.value.workTimeRange1
? Array.isArray(taskForm.value.workTimeRange1)
? taskForm.value.workTimeRange1.join('-')
: taskForm.value.workTimeRange1
: '',
workTimeRange2: taskForm.value.workTimeRange2
? Array.isArray(taskForm.value.workTimeRange2)
? taskForm.value.workTimeRange2.join('-')
: taskForm.value.workTimeRange2
: ''
};
}
// 更新日历事件
const eventIndex = calendarEvents.value.findIndex((item) => item.id === editingTaskId.value);
if (eventIndex !== -1) {
calendarEvents.value[eventIndex] = {
...calendarEvents.value[eventIndex],
title: taskForm.value.name,
describeValue: taskForm.value.describeValue,
type: getEventType(taskForm.value.taskType)
};
}
ElMessage.success('任务更新成功');
} else {
// 新增操作
response = await adddaiban(apiData);
console.log('保存任务成功:', response);
// 获取当前日期
const currentDateStr = formatDate(new Date());
// 从接口响应中获取任务ID如果返回
const newId = response.data?.id || Date.now();
// 构建新任务对象添加到本地数据中
const newTask = {
id: newId,
title: taskForm.value.name,
describeValue: taskForm.value.describeValue,
timeRange: formatTimeRange(taskForm.value.timeRange[0], taskForm.value.timeRange[1]),
originalTimeRange: taskForm.value.timeRange,
taskLevel: taskForm.value.taskLevel,
taskType: taskForm.value.taskType,
// 保留原有字段以便前端显示,添加类型检查
workTimeRange1: taskForm.value.workTimeRange1
? Array.isArray(taskForm.value.workTimeRange1)
? taskForm.value.workTimeRange1.join('-')
: taskForm.value.workTimeRange1
: '',
workTimeRange2: taskForm.value.workTimeRange2
? Array.isArray(taskForm.value.workTimeRange2)
? taskForm.value.workTimeRange2.join('-')
: taskForm.value.workTimeRange2
: '',
date: currentDateStr
};
// 添加到待办列表
todoListData.value.unshift(newTask);
// 添加到日历事件
calendarEvents.value.push({
id: newId,
date: currentDateStr,
title: taskForm.value.name,
describeValue: taskForm.value.describeValue,
type: getEventType(taskForm.value.taskType)
});
ElMessage.success('任务添加成功');
}
// 重置表单
taskForm.value = {
name: '',
describeValue: '',
timeRange: null,
taskLevel: '常规项',
taskType: '1',
workTimeRange1: null,
workTimeRange2: null
};
// 重置编辑状态
editingTaskId.value = null;
// 关闭弹窗
closeDialog();
} catch (error) {
console.error('保存任务失败:', error);
ElMessage.error('保存任务失败,请重试');
}
};
// 处理状态变更
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;
}
};
// 编辑和删除处理函数
const handleEdit = () => {
console.log('执行编辑操作');
// 保留原有编辑逻辑
};
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;
const handleDelete = () => {
console.log('执行删除操作');
// 保留原有删除逻辑
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);
// 前端删除同步
todoListData.value = todoListData.value.filter((item) => item.id !== id);
calendarEvents.value = calendarEvents.value.filter((item) => item.id !== id);
ElMessage.success('任务已删除');
} catch (error) {
console.error('删除任务失败:', error);
ElMessage.error('删除任务失败,请重试');
}
})
.catch(() => {
ElMessage.info('已取消删除');
});
};
const handleInspection1 = () => {
@ -403,6 +677,16 @@ const handleInspection7 = () => {
padding: 2px;
}
/* 已完成任务的样式 */
.todo-color-indicator.completed {
background-color: #dcdfe6;
}
.todo-item.completed .todo-content {
color: #909399;
text-decoration: line-through;
}
.nav-tab {
padding: 12px 24px;
cursor: pointer;
@ -570,11 +854,6 @@ const handleInspection7 = () => {
overflow: hidden;
}
/* 重要任务的背景色 */
.todo-item.important {
background-color: #e6f7ff;
}
.todo-checkbox {
margin-top: 2px;
flex-shrink: 0;
@ -604,7 +883,7 @@ const handleInspection7 = () => {
color: #909399;
}
.todo-description {
.todo-describeValue {
font-size: 12px;
color: #606266;
line-height: 1.4;
@ -612,7 +891,7 @@ const handleInspection7 = () => {
.todo-actions {
position: absolute;
right: -80px;
right: -120px;
top: 0;
bottom: 0;
display: flex;
@ -653,7 +932,7 @@ const handleInspection7 = () => {
/* 内容区域平移以给按钮留出空间 */
.todo-item:hover .todo-content {
transform: translateX(-80px);
transform: translateX(-120px);
}
.action-icon {
@ -667,6 +946,18 @@ const handleInspection7 = () => {
gap: 12px;
}
/* 空状态样式 */
.empty-todo {
display: flex;
justify-content: center;
align-items: center;
height: 200px;
color: #909399;
font-size: 14px;
background-color: #fafafa;
border-radius: 4px;
}
.status-legend {
display: flex;
gap: 20px;
@ -809,7 +1100,7 @@ const handleInspection7 = () => {
text-overflow: ellipsis;
}
.event-description {
.event-describeValue {
font-size: 11px;
white-space: nowrap;
overflow: hidden;

View File

@ -795,36 +795,40 @@ const addEquipment = () => {
background-color: #f9fbfd;
min-height: 100vh;
}
/* 2. 顶部导航选项卡 */
.navigation-tabs {
display: flex;
margin-bottom: 20px;
background-color: #fff;
border-radius: 4px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
margin-bottom: 20px;
overflow: hidden;
padding: 2px;
}
.nav-tab {
padding: 12px 24px;
cursor: pointer;
transition: all 0.2s;
transition: all 0.3s ease;
border-radius: 4px;
font-size: 14px;
color: #6b7280;
color: #606266;
border-right: 1px solid #f0f0f0;
flex: 1;
text-align: center;
border-right: 1px solid #f0f0f0;
}
.nav-tab:last-child {
border-right: none;
}
.nav-tab:hover:not(.active) {
background-color: #f3f4f6;
.nav-tab:hover {
color: #409eff;
background-color: #ecf5ff;
}
.nav-tab.active {
background-color: #165dff;
background-color: #409eff;
color: #fff;
font-weight: 500;
box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3);
}
/* 3. 页面标题(与试验系统一致) */

View File

@ -807,35 +807,36 @@ const handleInspectionManagement3 = () => {
.progress-line {
flex: 1;
height: 2px;
background-color: #e5e7eb;
height: 0;
border-top: 2px dashed #e5e7eb;
margin: 10px 0;
}
.progress-step.active .step-number {
background-color: #165dff;
background-color: #10b981;
color: white;
}
.progress-step.active .step-name {
color: #165dff;
color: #10b981;
font-weight: 500;
}
.progress-line.active {
background-color: #165dff;
border-top-color: #10b981;
}
.progress-step.failed .step-number {
background-color: #dc2626;
background-color: red;
color: white;
}
.progress-step.failed .step-name {
color: #dc2626;
color: red;
}
.progress-line.failed {
background-color: #dc2626;
border-top-color: red;
}
/* 15. 试验结果样式 */

View File

@ -3,8 +3,8 @@
<div class="inspection-tasks">
<div class="navigation-tabs">
<div class="nav-tab" @click="handleInspection1">待办事项</div>
<div class="nav-tab active" @click="handleInspection2">巡检管理</div>
<div class="nav-tab" @click="handleInspection3">试验管理</div>
<div class="nav-tab" @click="handleInspection2">巡检管理</div>
<div class="nav-tab active" @click="handleInspection3">试验管理</div>
<div class="nav-tab" @click="handleInspection4">报修管理</div>
<div class="nav-tab" @click="handleInspection5">抢修管理</div>
<div class="nav-tab" @click="handleInspection6">工单管理</div>
@ -17,9 +17,9 @@
<!-- 选项卡 -->
<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>
<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>
@ -418,14 +418,14 @@ const handleView = (task) => {
};
const handleInspectionManagement1 = () => {
router.push('/rili/InspectionManagement');
router.push('/rili/shiyanguanli');
};
const handleInspectionManagement2 = () => {
router.push('/rili/xunjianrenwu');
router.push('/rili/shiyanrenwu');
};
const handleInspectionManagement3 = () => {
router.push('/rili/xunjianjihua');
router.push('/rili/shiyanjilu');
};
const handleInspection1 = () => {
router.push('/rili/rili');