合并
This commit is contained in:
@ -34,7 +34,7 @@
|
|||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"diagram-js": "12.3.0",
|
"diagram-js": "12.3.0",
|
||||||
"didi": "9.0.2",
|
"didi": "9.0.2",
|
||||||
"echarts": "5.5.0",
|
"echarts": "^5.5.0",
|
||||||
"echarts-gl": "^2.0.9",
|
"echarts-gl": "^2.0.9",
|
||||||
"element-plus": "2.8.8",
|
"element-plus": "2.8.8",
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
|
@ -106,6 +106,6 @@ export const getFootNote = (data) => {
|
|||||||
return request({
|
return request({
|
||||||
url: 'gps/equipmentSon/getList',
|
url: 'gps/equipmentSon/getList',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
data: data
|
params: data
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -122,6 +122,11 @@ export interface EquipmentQuery extends PageQuery {
|
|||||||
*/
|
*/
|
||||||
type?: string | number;
|
type?: string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 展示用户/设备数据:1=用户数据,0=设备数据
|
||||||
|
*/
|
||||||
|
gpsType?: string | number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户id
|
* 用户id
|
||||||
*/
|
*/
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col>
|
<el-col>
|
||||||
<div style="color: rgba(0, 30, 59, 1);;font-family: 'Alibaba-PuHuiTi-Bold';margin: 10px 0 0 0;"
|
<div
|
||||||
:style="{ fontSize: fontLevelMap[props.fontLevel] }">
|
style="color: rgba(0, 30, 59, 1); font-family: 'Alibaba-PuHuiTi-Bold'; margin: 10px 0 0 0"
|
||||||
|
:style="{ fontSize: fontLevelMap[props.fontLevel] }"
|
||||||
|
>
|
||||||
{{ props.title }}
|
{{ props.title }}
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col>
|
<el-col>
|
||||||
<p style="color: rgba(154, 154, 154, 1);font-size: 14px;">
|
<p style="color: rgba(154, 154, 154, 1); font-size: 14px">
|
||||||
{{ props.subtitle }}
|
{{ props.subtitle }}
|
||||||
</p>
|
</p>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
@ -22,9 +23,9 @@ const props = defineProps({
|
|||||||
type: Number,
|
type: Number,
|
||||||
default: 1
|
default: 1
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
const fontLevelMap = {
|
const fontLevelMap = {
|
||||||
1: "24px",
|
1: '24px',
|
||||||
2: "18px"
|
2: '18px'
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
756
src/views/dhr_demo/InspectionManagement.vue
Normal file
756
src/views/dhr_demo/InspectionManagement.vue
Normal file
@ -0,0 +1,756 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="operation-inspection">
|
||||||
|
<div class="navigation-tabs">
|
||||||
|
<div class="nav-tab" @click="handleInspection1">待办事项</div>
|
||||||
|
<div class="nav-tab active" @click="handleInspection2">巡检管理</div>
|
||||||
|
<div class="nav-tab">试验管理</div>
|
||||||
|
<div class="nav-tab">报修管理</div>
|
||||||
|
<div class="nav-tab">抢修管理</div>
|
||||||
|
<div class="nav-tab">工单管理</div>
|
||||||
|
</div>
|
||||||
|
<TitleComponent title="运维巡检管理" subtitle="制定巡检计划,安排巡检任务,跟进巡检记录"></TitleComponent>
|
||||||
|
|
||||||
|
<!-- 选项卡和按钮组合 -->
|
||||||
|
<div class="tabs-wrapper">
|
||||||
|
<div style="display: flex; align-items: center; gap: 10px">
|
||||||
|
<el-button type="primary" @click="handleInspectionManagement1">巡检计划</el-button>
|
||||||
|
<el-button type="primary" @click="handleInspectionManagement2">巡检任务</el-button>
|
||||||
|
<el-button type="primary" @click="handleInspectionManagement3">巡检记录</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 筛选栏 -->
|
||||||
|
<div class="filter-bar">
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select v-model="planType" placeholder="计划类型" clearable>
|
||||||
|
<el-option label="全部类型" value="all"></el-option>
|
||||||
|
<el-option label="每日巡检" value="daily"></el-option>
|
||||||
|
<el-option label="每周巡检" value="weekly"></el-option>
|
||||||
|
<el-option label="每月巡检" value="monthly"></el-option>
|
||||||
|
<el-option label="每季度巡检" value="quarterly"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select v-model="status" placeholder="全部状态" clearable>
|
||||||
|
<el-option label="全部状态" value="all"></el-option>
|
||||||
|
<el-option label="启用中" value="enabled"></el-option>
|
||||||
|
<el-option label="已停用" value="disabled"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select v-model="inspectionObject" placeholder="巡检对象" clearable>
|
||||||
|
<el-option label="全部对象" value="all"></el-option>
|
||||||
|
<el-option label="服务器" value="server"></el-option>
|
||||||
|
<el-option label="网络设备" value="network"></el-option>
|
||||||
|
<el-option label="应用系统" value="application"></el-option>
|
||||||
|
<el-option label="基础设施" value="infrastructure"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-actions">
|
||||||
|
<el-button type="primary" class="search-btn">搜索</el-button>
|
||||||
|
<el-button type="primary" icon="el-icon-plus" class="create-btn" @click="handleCreate">手动创建计划</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 表格 -->
|
||||||
|
<div class="table-wrapper">
|
||||||
|
<el-table :data="pagedTableData" stripe style="width: 100%" highlight-current-row class="custom-table">
|
||||||
|
<el-table-column align="center" prop="name" label="计划名称" style="width: 14.2%"></el-table-column>
|
||||||
|
<el-table-column align="center" prop="type" label="类型" style="width: 14.2%"></el-table-column>
|
||||||
|
<el-table-column align="center" prop="object" label="巡检对象" style="width: 14.2%"></el-table-column>
|
||||||
|
<el-table-column align="center" prop="frequency" label="频率" style="width: 14.2%"></el-table-column>
|
||||||
|
<el-table-column align="center" prop="status" label="状态" style="width: 14.2%">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="scope.row.status === 'enabled' ? 'success' : 'info'" class="status-tag">
|
||||||
|
{{ scope.row.status === 'enabled' ? '启用中' : '已停用' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" prop="responsible" label="负责人" style="width: 14.2%"></el-table-column>
|
||||||
|
<el-table-column align="center" label="操作" style="width: 14.2%" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button type="text" @click="handleEdit(scope.row)" size="small" class="action-btn">编辑</el-button>
|
||||||
|
<el-button type="text" @click="handleDetail(scope.row)" size="small" class="action-btn">详情</el-button>
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
:disabled="scope.row.status === 'disabled'"
|
||||||
|
@click="handleEnable(scope.row)"
|
||||||
|
size="small"
|
||||||
|
class="action-btn"
|
||||||
|
:class="{ 'text-success': scope.row.status === 'disabled' }"
|
||||||
|
>
|
||||||
|
{{ scope.row.status === 'enabled' ? '停用' : '启用' }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<!-- 分页区域 -->
|
||||||
|
<div class="pagination-section">
|
||||||
|
<div class="pagination-info">
|
||||||
|
显示第{{ (currentPage - 1) * pageSize + 1 }}到{{ Math.min(currentPage * pageSize, total) }}条,共有{{ total }}条记录
|
||||||
|
</div>
|
||||||
|
<div class="pagination-controls">
|
||||||
|
<el-pagination
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
:current-page="currentPage"
|
||||||
|
:page-sizes="[10, 20, 30, 40]"
|
||||||
|
:page-size="pageSize"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="total"
|
||||||
|
background
|
||||||
|
>
|
||||||
|
</el-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 创建计划弹窗 -->
|
||||||
|
<el-dialog v-model="dialogVisible" title="新建巡检计划" width="700px" class="create-plan-dialog" center :show-close="true">
|
||||||
|
<el-form :model="createForm" :rules="createFormRules" ref="createFormRef" label-width="150px" class="custom-form">
|
||||||
|
<el-form-item label="计划名称*" prop="planName" class="form-item-large">
|
||||||
|
<el-input v-model="createForm.planName" placeholder="请输入计划名称" class="custom-input" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<el-form-item label="计划类型*" prop="planType" class="form-item-half">
|
||||||
|
<el-select v-model="createForm.planType" placeholder="请选择计划类型" class="custom-select">
|
||||||
|
<el-option label="每日巡检" value="daily" />
|
||||||
|
<el-option label="每周巡检" value="weekly" />
|
||||||
|
<el-option label="每月巡检" value="monthly" />
|
||||||
|
<el-option label="每季度巡检" value="quarterly" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="巡检对象类型*" prop="objectType" class="form-item-half">
|
||||||
|
<el-select v-model="createForm.objectType" placeholder="请选择对象类型" class="custom-select">
|
||||||
|
<el-option label="服务器" value="server" />
|
||||||
|
<el-option label="网络设备" value="network" />
|
||||||
|
<el-option label="应用系统" value="application" />
|
||||||
|
<el-option label="基础设施" value="infrastructure" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<el-form-item label="开始日期*" prop="startDate" class="form-item-half">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="createForm.startDate"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择日期"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
class="custom-date-picker"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="结束日期*" prop="endDate" class="form-item-half">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="createForm.endDate"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择日期"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
class="custom-date-picker"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
<el-form-item label="巡检频率*" class="form-item-large">
|
||||||
|
<div style="display: flex; align-items: center; gap: 20px">
|
||||||
|
<el-radio-group v-model="createForm.frequencyType" class="frequency-radio-group">
|
||||||
|
<el-radio label="daily">每天</el-radio>
|
||||||
|
<el-radio label="weekly">每周</el-radio>
|
||||||
|
<el-radio label="monthly">每月</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
|
||||||
|
<!-- 每周选择框 - 变小并排在单选框后面 -->
|
||||||
|
<el-select
|
||||||
|
v-if="createForm.frequencyType === 'weekly'"
|
||||||
|
v-model="createForm.weekday"
|
||||||
|
placeholder="选择周几"
|
||||||
|
class="custom-select-small"
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
<el-option label="周一" value="1" />
|
||||||
|
<el-option label="周二" value="2" />
|
||||||
|
<el-option label="周三" value="3" />
|
||||||
|
<el-option label="周四" value="4" />
|
||||||
|
<el-option label="周五" value="5" />
|
||||||
|
<el-option label="周六" value="6" />
|
||||||
|
<el-option label="周日" value="0" />
|
||||||
|
</el-select>
|
||||||
|
|
||||||
|
<!-- 每月选择框 - 变小并排在单选框后面 -->
|
||||||
|
<el-select
|
||||||
|
v-if="createForm.frequencyType === 'monthly'"
|
||||||
|
v-model="createForm.monthday"
|
||||||
|
placeholder="选择几号"
|
||||||
|
class="custom-select-small"
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
<template v-for="day in 31" :key="day">
|
||||||
|
<el-option :label="day + '号'" :value="day" />
|
||||||
|
</template>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<div class="form-row" s>
|
||||||
|
<el-form-item label="计划开始时间*" prop="startTime" class="form-item-half">
|
||||||
|
<el-time-picker v-model="createForm.startTime" placeholder="选择时间" format="HH:mm" value-format="HH:mm" class="custom-time-picker" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="预计时长(分钟)" class="form-item-half">
|
||||||
|
<el-input v-model.number="createForm.estimatedDuration" class="custom-input" />
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-form-item label="负责人*" prop="responsiblePerson" class="form-item-large">
|
||||||
|
<el-select v-model="createForm.responsiblePerson" placeholder="请选择负责人" class="custom-select">
|
||||||
|
<el-option label="张明" value="zhangming" />
|
||||||
|
<el-option label="李华" value="lihua" />
|
||||||
|
<el-option label="王强" value="wangqiang" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="巡检项*" class="form-item-large">
|
||||||
|
<el-checkbox-group v-model="createForm.inspectionItems" style="border: 0.1 solid black; padding: 5px">
|
||||||
|
<el-checkbox label="CPU使用率检查" />
|
||||||
|
<el-checkbox label="内存使用情况" />
|
||||||
|
<el-checkbox label="磁盘空间检查" />
|
||||||
|
<el-checkbox label="网络连接状态" />
|
||||||
|
<el-checkbox label="系统日志检查" />
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="备注说明" prop="remarks" class="form-item-large">
|
||||||
|
<el-input v-model="createForm.remarks" type="textarea" placeholder="请输入备注" rows="3" class="custom-textarea" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="cancelCreatePlan">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submitCreatePlan">新增任务</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// 表单引用
|
||||||
|
const createFormRef = ref(null);
|
||||||
|
import { ref, computed, reactive } from 'vue';
|
||||||
|
import router from '@/router';
|
||||||
|
import TitleComponent from '@/views/demo/components/TitleComponent.vue';
|
||||||
|
|
||||||
|
// 激活的选项卡
|
||||||
|
const activeTab = ref('plan');
|
||||||
|
// 计划类型
|
||||||
|
const planType = ref('all');
|
||||||
|
// 状态
|
||||||
|
const status = ref('all');
|
||||||
|
// 巡检对象
|
||||||
|
const inspectionObject = ref('all');
|
||||||
|
// 原始表格数据
|
||||||
|
const rawTableData = ref([
|
||||||
|
{
|
||||||
|
name: '生产服务器每日巡检 2025-05-14',
|
||||||
|
type: '每日巡检',
|
||||||
|
object: '服务器',
|
||||||
|
frequency: '每天8:30',
|
||||||
|
status: 'enabled',
|
||||||
|
responsible: '张明'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '网络设备安全巡检 2025-04-15',
|
||||||
|
type: '每周巡检',
|
||||||
|
object: '网络设备',
|
||||||
|
frequency: '每天10:30',
|
||||||
|
status: 'enabled',
|
||||||
|
responsible: '张明'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '数据库性能巡检 2025-03-03',
|
||||||
|
type: '每月巡检',
|
||||||
|
object: '应用系统',
|
||||||
|
frequency: '每月1日14:00',
|
||||||
|
status: 'disabled',
|
||||||
|
responsible: '张明'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '机房环境季度检查',
|
||||||
|
type: '每季度巡检',
|
||||||
|
object: '基础设备',
|
||||||
|
frequency: '每季度第一个月5号',
|
||||||
|
status: 'enabled',
|
||||||
|
responsible: '张明'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '生产服务器每日巡检 2025-05-14',
|
||||||
|
type: '每日巡检',
|
||||||
|
object: '服务器',
|
||||||
|
frequency: '每天8:30',
|
||||||
|
status: 'enabled',
|
||||||
|
responsible: '张明'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '生产服务器每日巡检 2025-05-14',
|
||||||
|
type: '每日巡检',
|
||||||
|
object: '服务器',
|
||||||
|
frequency: '每天8:30',
|
||||||
|
status: 'enabled',
|
||||||
|
responsible: '张明'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '生产服务器每日巡检 2025-05-14',
|
||||||
|
type: '每日巡检',
|
||||||
|
object: '服务器',
|
||||||
|
frequency: '每天8:30',
|
||||||
|
status: 'enabled',
|
||||||
|
responsible: '张明'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '生产服务器每日巡检 2025-05-14',
|
||||||
|
type: '每日巡检',
|
||||||
|
object: '服务器',
|
||||||
|
frequency: '每天8:30',
|
||||||
|
status: 'enabled',
|
||||||
|
responsible: '张明'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '生产服务器每日巡检 2025-05-14',
|
||||||
|
type: '每日巡检',
|
||||||
|
object: '服务器',
|
||||||
|
frequency: '每天8:30',
|
||||||
|
status: 'enabled',
|
||||||
|
responsible: '张明'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '生产服务器每日巡检 2025-05-14',
|
||||||
|
type: '每日巡检',
|
||||||
|
object: '服务器',
|
||||||
|
frequency: '每天8:30',
|
||||||
|
status: 'enabled',
|
||||||
|
responsible: '张明'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '生产服务器每日巡检 2025-05-14',
|
||||||
|
type: '每日巡检',
|
||||||
|
object: '服务器',
|
||||||
|
frequency: '每天8:30',
|
||||||
|
status: 'enabled',
|
||||||
|
responsible: '张明'
|
||||||
|
},
|
||||||
|
// 增加更多数据用于测试分页
|
||||||
|
{
|
||||||
|
name: '应用系统安全检查',
|
||||||
|
type: '每周巡检',
|
||||||
|
object: '应用系统',
|
||||||
|
frequency: '每周五16:00',
|
||||||
|
status: 'enabled',
|
||||||
|
responsible: '李华'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '网络带宽监控',
|
||||||
|
type: '每日巡检',
|
||||||
|
object: '网络设备',
|
||||||
|
frequency: '每天12:00',
|
||||||
|
status: 'enabled',
|
||||||
|
responsible: '王强'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
// 当前页码
|
||||||
|
const currentPage = ref(1);
|
||||||
|
// 每页条数 - 与分页控件默认值保持一致
|
||||||
|
const pageSize = ref(10);
|
||||||
|
// 总条数 - 从原始数据计算得出
|
||||||
|
const total = ref(rawTableData.value.length);
|
||||||
|
|
||||||
|
// 计算属性:根据当前页码和每页条数获取分页后的数据
|
||||||
|
const pagedTableData = computed(() => {
|
||||||
|
const startIndex = (currentPage.value - 1) * pageSize.value;
|
||||||
|
const endIndex = startIndex + pageSize.value;
|
||||||
|
return rawTableData.value.slice(startIndex, endIndex);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 每页条数改变
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
pageSize.value = val;
|
||||||
|
currentPage.value = 1; // 重置到第一页
|
||||||
|
};
|
||||||
|
|
||||||
|
// 当前页码改变
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
currentPage.value = val;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
const handleEdit = (row) => {
|
||||||
|
console.log('编辑', row);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 详情
|
||||||
|
const handleDetail = (row) => {
|
||||||
|
console.log('详情', row);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 启用/停用
|
||||||
|
const handleEnable = (row) => {
|
||||||
|
row.status = row.status === 'enabled' ? 'disabled' : 'enabled';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选项卡切换
|
||||||
|
const handleTabChange = (newTab, oldTab) => {
|
||||||
|
// 可以在这里添加选项卡切换时的逻辑
|
||||||
|
console.log('选项卡切换:', newTab, oldTab);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 创建计划弹窗相关
|
||||||
|
const dialogVisible = ref(false);
|
||||||
|
const createForm = reactive({
|
||||||
|
planName: '',
|
||||||
|
planType: '',
|
||||||
|
objectType: '',
|
||||||
|
startDate: '',
|
||||||
|
endDate: '',
|
||||||
|
frequencyType: 'daily',
|
||||||
|
frequencyValue: '',
|
||||||
|
weekday: '', // 存储周几
|
||||||
|
monthday: '', // 存储几号
|
||||||
|
startTime: '',
|
||||||
|
estimatedDuration: 60,
|
||||||
|
responsiblePerson: '',
|
||||||
|
inspectionItems: [],
|
||||||
|
remarks: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 创建计划表单验证规则
|
||||||
|
const createFormRules = computed(() => ({
|
||||||
|
planName: [{ required: true, message: '请输入计划名称', trigger: 'blur' }],
|
||||||
|
planType: [{ required: true, message: '请选择计划类型', trigger: 'change' }],
|
||||||
|
objectType: [{ required: true, message: '请选择对象类型', trigger: 'change' }],
|
||||||
|
startDate: [{ required: true, message: '请选择开始日期', trigger: 'change' }],
|
||||||
|
endDate: [{ required: true, message: '请选择结束日期', trigger: 'change' }],
|
||||||
|
startTime: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
|
||||||
|
responsiblePerson: [{ required: true, message: '请选择负责人', trigger: 'change' }],
|
||||||
|
weekday: createForm.frequencyType === 'weekly' ? [{ required: true, message: '请选择周几', trigger: 'change' }] : [],
|
||||||
|
monthday: createForm.frequencyType === 'monthly' ? [{ required: true, message: '请选择几号', trigger: 'change' }] : []
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 打开创建计划弹窗
|
||||||
|
const handleCreate = () => {
|
||||||
|
dialogVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提交创建计划
|
||||||
|
const submitCreatePlan = () => {
|
||||||
|
console.log('提交创建计划:', createForm);
|
||||||
|
// 这里可以添加实际的创建计划逻辑
|
||||||
|
dialogVisible.value = false;
|
||||||
|
// 重置表单
|
||||||
|
Object.keys(createForm).forEach((key) => {
|
||||||
|
if (Array.isArray(createForm[key])) {
|
||||||
|
createForm[key] = [];
|
||||||
|
} else if (key === 'estimatedDuration') {
|
||||||
|
createForm[key] = 60;
|
||||||
|
} else if (key === 'frequencyType') {
|
||||||
|
createForm[key] = 'daily';
|
||||||
|
} else {
|
||||||
|
createForm[key] = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消创建计划
|
||||||
|
const cancelCreatePlan = () => {
|
||||||
|
dialogVisible.value = false;
|
||||||
|
// 重置表单
|
||||||
|
Object.keys(createForm).forEach((key) => {
|
||||||
|
if (Array.isArray(createForm[key])) {
|
||||||
|
createForm[key] = [];
|
||||||
|
} else if (key === 'estimatedDuration') {
|
||||||
|
createForm[key] = 60;
|
||||||
|
} else if (key === 'frequencyType') {
|
||||||
|
createForm[key] = 'daily';
|
||||||
|
} else {
|
||||||
|
createForm[key] = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleInspection1 = () => {
|
||||||
|
router.push('/rili/rili');
|
||||||
|
};
|
||||||
|
const handleInspection2 = () => {
|
||||||
|
router.push('/rili/InspectionManagement');
|
||||||
|
};
|
||||||
|
const handleInspectionManagement1 = () => {
|
||||||
|
router.push('/rili/InspectionManagement');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInspectionManagement2 = () => {
|
||||||
|
router.push('/rili/xunjianrenwu');
|
||||||
|
};
|
||||||
|
const handleInspectionManagement3 = () => {
|
||||||
|
router.push('/rili/xunjianjihua');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 样式保持不变 */
|
||||||
|
.operation-inspection {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 标题区域样式 */
|
||||||
|
.title-section {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-subtitle {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #909399;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选项卡样式 */
|
||||||
|
.tabs-wrapper {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-tabs {
|
||||||
|
border-bottom: none;
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-tabs .el-tabs__header {
|
||||||
|
margin: 0 -20px 0 -20px;
|
||||||
|
padding: 0 20px;
|
||||||
|
border-bottom: 1px solid #e4e7ed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-tabs .el-tabs__nav-wrap::after {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-tabs .el-tabs__item {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
padding: 12px 20px;
|
||||||
|
margin-right: 20px;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-tabs .el-tabs__item.is-active {
|
||||||
|
color: #409eff;
|
||||||
|
border-bottom-color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-tabs .el-tabs__item:hover {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 筛选栏样式 */
|
||||||
|
.filter-bar {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-bar .el-select {
|
||||||
|
width: 150px;
|
||||||
|
height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-actions {
|
||||||
|
margin-left: auto;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-btn,
|
||||||
|
.create-btn {
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表格样式 */
|
||||||
|
.table-wrapper {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-table {
|
||||||
|
border: 1px solid #ebeef5;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-table th {
|
||||||
|
background-color: #fafafa;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #606266;
|
||||||
|
text-align: left;
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-table td {
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-table tr:hover {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-table tr.current-row {
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag {
|
||||||
|
padding: 4px 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
color: #409eff;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn:hover {
|
||||||
|
color: #66b1ff;
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 分页区域样式 */
|
||||||
|
.pagination-section {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 16px 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-info {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-controls .el-pagination {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-controls .el-pagination__sizes {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-controls .el-pagination button {
|
||||||
|
min-width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-controls .el-pagination .el-pager li {
|
||||||
|
min-width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-controls .el-pagination .el-pager li.active {
|
||||||
|
background-color: #409eff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
/* 导航栏样式 */
|
||||||
|
.navigation-tabs {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab {
|
||||||
|
padding: 12px 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
border-right: 1px solid #f0f0f0;
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab:hover {
|
||||||
|
color: #409eff;
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab.active {
|
||||||
|
background-color: #409eff;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab {
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
/* 响应式设计 */
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.filter-bar {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-actions {
|
||||||
|
margin-left: 0;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
700
src/views/dhr_demo/index.vue
Normal file
700
src/views/dhr_demo/index.vue
Normal file
@ -0,0 +1,700 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<!-- 导航栏 -->
|
||||||
|
<div class="navigation-tabs">
|
||||||
|
<div class="nav-tab active" @click="handleInspection1">待办事项</div>
|
||||||
|
<div class="nav-tab" @click="handleInspection2">巡检管理</div>
|
||||||
|
<div class="nav-tab">试验管理</div>
|
||||||
|
<div class="nav-tab">报修管理</div>
|
||||||
|
<div class="nav-tab">抢修管理</div>
|
||||||
|
<div class="nav-tab">工单管理</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 标题栏 -->
|
||||||
|
<div class="header">
|
||||||
|
<TitleComponent title="运维待办事项" subtitle="管理每日、每周等的运维工作任务"></TitleComponent>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="main-content">
|
||||||
|
<!-- 左侧日历区域 -->
|
||||||
|
<div class="calendar-container">
|
||||||
|
<div class="calendar-header">
|
||||||
|
<div class="calendar-title">待办月视图</div>
|
||||||
|
<div class="calendar-controls">
|
||||||
|
<!-- 年份月份选择 -->
|
||||||
|
<el-select v-model="selectedYear" placeholder="选择年份" size="small" style="width: 80px; margin-right: 5px">
|
||||||
|
<el-option v-for="year in years" :key="year" :label="year.toString()" :value="year"></el-option>
|
||||||
|
</el-select>
|
||||||
|
<el-select v-model="selectedMonth" placeholder="选择月份" size="small" style="width: 80px; margin-right: 10px">
|
||||||
|
<el-option v-for="month in 12" :key="month" :label="month.toString()" :value="month"></el-option>
|
||||||
|
</el-select>
|
||||||
|
<!-- 月份切换按钮 -->
|
||||||
|
<el-button type="text" icon="el-icon-arrow-left" @click="decreaseMonth"></el-button>
|
||||||
|
<el-button type="text" icon="el-icon-arrow-right" @click="increaseMonth"></el-button>
|
||||||
|
<el-button type="primary" size="small">添加</el-button>
|
||||||
|
<el-button type="primary" size="small" @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>
|
||||||
|
<div class="event-description">{{ event.description }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-calendar>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右侧表单区域 -->
|
||||||
|
<div class="form-container">
|
||||||
|
<div class="form-header">
|
||||||
|
<h2>今日待办</h2>
|
||||||
|
<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 class="todo-content">
|
||||||
|
<div class="todo-main">
|
||||||
|
<div class="todo-title">服务器例行检查</div>
|
||||||
|
<div class="todo-time">09:00-10:00 AM</div>
|
||||||
|
</div>
|
||||||
|
<div class="todo-description">检查所有生产服务器的CPU、内存、磁盘使用率,确保正常运行</div>
|
||||||
|
</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">
|
||||||
|
<el-button type="text" icon="el-icon-edit"></el-button>
|
||||||
|
<el-button type="text" icon="el-icon-delete"></el-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>
|
||||||
|
|
||||||
|
<!-- 待办项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>
|
||||||
|
|
||||||
|
<!-- 待办项5 - 常规维护 -->
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 状态图例 - 标签形式 -->
|
||||||
|
<div class="status-legend">
|
||||||
|
<span class="status-tag normal">常规维护</span>
|
||||||
|
<span class="status-tag important">重要</span>
|
||||||
|
<span class="status-tag urgent">紧急</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-dialog v-model="dialogVisible" title="新增任务" width="480px" class="custom-dialog" :before-close="closeDialog">
|
||||||
|
<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>
|
||||||
|
<el-form-item label="任务描述" prop="description">
|
||||||
|
<el-input v-model="taskForm.description" placeholder="输入任务描述" class="form-input"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="时间" prop="timeRange">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="taskForm.timeRange"
|
||||||
|
type="datetimerange"
|
||||||
|
start-placeholder="开始时间"
|
||||||
|
end-placeholder="结束时间"
|
||||||
|
class="form-input"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="优先级" prop="priority">
|
||||||
|
<el-select v-model="taskForm.priority" placeholder="选择优先级" class="form-input">
|
||||||
|
<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">
|
||||||
|
<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-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="closeDialog">取消</el-button>
|
||||||
|
<el-button type="primary" @click="saveTask">保存任务</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch } from 'vue';
|
||||||
|
import router from '@/router';
|
||||||
|
import TitleComponent from '../demo/components/TitleComponent.vue';
|
||||||
|
|
||||||
|
// 生成年份选项,生成2020-2029年的年份范围
|
||||||
|
const targetYear = 2025;
|
||||||
|
const years = ref(Array.from({ length: 10 }, (_, index) => 2020 + index));
|
||||||
|
const selectedYear = ref(targetYear);
|
||||||
|
const selectedMonth = ref(9);
|
||||||
|
|
||||||
|
// 默认显示2025年9月
|
||||||
|
const currentDate = ref(new Date(targetYear, 8, 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' },
|
||||||
|
|
||||||
|
// 数据库管理事件
|
||||||
|
{ id: 3, date: '2025-09-21', title: '数据库管理', description: '定期执行数据库优化', type: 'database' },
|
||||||
|
{ id: 4, date: '2025-09-30', title: '数据库管理', description: '大型数据库备份策略', type: 'database' },
|
||||||
|
|
||||||
|
// 网络维护事件
|
||||||
|
{ id: 5, date: '2025-09-05', title: '网络维护', description: '网络设备例行检查', type: 'network' },
|
||||||
|
{ id: 6, date: '2025-09-15', title: '网络维护', description: '更新网络安全策略', type: 'network' },
|
||||||
|
|
||||||
|
// 系统升级事件
|
||||||
|
{ id: 7, date: '2025-09-18', title: '系统升级', description: '核心系统版本升级', type: 'upgrade' },
|
||||||
|
{ id: 8, date: '2025-09-25', title: '系统升级', description: '应用服务升级部署', type: 'upgrade' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 获取指定日期的事件
|
||||||
|
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([selectedYear, selectedMonth], ([newYear, newMonth]) => {
|
||||||
|
const date = new Date(currentDate.value);
|
||||||
|
date.setFullYear(newYear);
|
||||||
|
date.setMonth(newMonth - 1);
|
||||||
|
currentDate.value = date;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化年份和月份选择器
|
||||||
|
updateYearAndMonth();
|
||||||
|
|
||||||
|
// 弹窗相关状态管理
|
||||||
|
const dialogVisible = ref(false);
|
||||||
|
const taskForm = ref({
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
timeRange: '',
|
||||||
|
priority: '常规项',
|
||||||
|
taskType: '常规维护'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 打开添加任务弹窗
|
||||||
|
const openAddTaskDialog = () => {
|
||||||
|
dialogVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const closeDialog = () => {
|
||||||
|
dialogVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存任务
|
||||||
|
const saveTask = () => {
|
||||||
|
// 这里可以添加表单验证和保存逻辑
|
||||||
|
console.log('保存任务:', taskForm.value);
|
||||||
|
// 重置表单
|
||||||
|
taskForm.value = {
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
timeRange: '',
|
||||||
|
priority: '常规项',
|
||||||
|
taskType: '常规维护'
|
||||||
|
};
|
||||||
|
// 关闭弹窗
|
||||||
|
closeDialog();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInspection1 = () => {
|
||||||
|
router.push('/rili/rili');
|
||||||
|
};
|
||||||
|
const handleInspection2 = () => {
|
||||||
|
router.push('/rili/InspectionManagement');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.container {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 导航栏样式 */
|
||||||
|
.navigation-tabs {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab {
|
||||||
|
padding: 12px 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
border-right: 1px solid #f0f0f0;
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab:hover {
|
||||||
|
color: #409eff;
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab.active {
|
||||||
|
background-color: #409eff;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab {
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 日历区域样式 */
|
||||||
|
.calendar-container {
|
||||||
|
flex: 1;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 自定义弹窗样式 */
|
||||||
|
.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 {
|
||||||
|
width: 400px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.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: 400px;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 重要任务的背景色 */
|
||||||
|
.todo-item.important {
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-checkbox {
|
||||||
|
margin-top: 2px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-content {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-description {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #606266;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-actions {
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
bottom: 10px;
|
||||||
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-actions .el-button {
|
||||||
|
padding: 4px 8px;
|
||||||
|
min-width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 状态图例 - 标签形式 */
|
||||||
|
.status-legend {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
padding-top: 15px;
|
||||||
|
border-top: 1px solid #ebeef5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 16px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag.normal {
|
||||||
|
background-color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag.important {
|
||||||
|
background-color: #faad14;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag.urgent {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 自定义日历单元格样式 */
|
||||||
|
.custom-date-cell {
|
||||||
|
padding: 5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 系统升级事件样式 */
|
||||||
|
.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%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-calendar-table td {
|
||||||
|
padding: 2px;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-calendar-day {
|
||||||
|
height: 120px;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-description {
|
||||||
|
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>
|
672
src/views/dhr_demo/xunjianjihua.vue
Normal file
672
src/views/dhr_demo/xunjianjihua.vue
Normal file
@ -0,0 +1,672 @@
|
|||||||
|
<template>
|
||||||
|
<div class="operation-inspection">
|
||||||
|
<div class="navigation-tabs">
|
||||||
|
<div class="nav-tab" @click="handleInspection1">待办事项</div>
|
||||||
|
<div class="nav-tab active" @click="handleInspection2">巡检管理</div>
|
||||||
|
<div class="nav-tab">试验管理</div>
|
||||||
|
<div class="nav-tab">报修管理</div>
|
||||||
|
<div class="nav-tab">抢修管理</div>
|
||||||
|
<div class="nav-tab">工单管理</div>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; align-items: center; gap: 1200px">
|
||||||
|
<TitleComponent title="运维巡检管理" subtitle="制定巡检计划,安排巡检任务,跟进巡检记录"></TitleComponent>
|
||||||
|
<div style="display: flex; align-items: center; gap: 10px">
|
||||||
|
<el-button type="primary" class="export-btn">筛选</el-button>
|
||||||
|
<el-button type="primary" class="create-btn">导入数据</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 选项卡和按钮组合 -->
|
||||||
|
<div class="tabs-wrapper">
|
||||||
|
<div style="display: flex; align-items: center; gap: 10px">
|
||||||
|
<el-button type="primary" @click="handleInspectionManagement1">巡检计划</el-button>
|
||||||
|
<el-button type="primary" @click="handleInspectionManagement2">巡检任务</el-button>
|
||||||
|
<el-button type="primary" @click="handleInspectionManagement3">巡检记录</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 筛选栏 -->
|
||||||
|
<div class="filter-bar">
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select v-model="filterStatus" placeholder="状态" clearable>
|
||||||
|
<el-option label="全部状态" value="all"></el-option>
|
||||||
|
<el-option label="正常" value="normal"></el-option>
|
||||||
|
<el-option label="需关注" value="attention"></el-option>
|
||||||
|
<el-option label="有问题" value="problem"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select v-model="filterType" placeholder="巡检类型" clearable>
|
||||||
|
<el-option label="全部类型" value="all"></el-option>
|
||||||
|
<el-option label="数据库" value="database"></el-option>
|
||||||
|
<el-option label="服务器" value="server"></el-option>
|
||||||
|
<el-option label="网络设备" value="network"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="dateRange"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
></el-date-picker>
|
||||||
|
</div>
|
||||||
|
<div class="filter-actions">
|
||||||
|
<el-button type="primary" class="search-btn">搜索</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 主内容区 -->
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6" style="grid-auto-rows: 1fr">
|
||||||
|
<!-- 左侧和中间内容区 -->
|
||||||
|
<div class="lg:col-span-2 space-y-6">
|
||||||
|
<!-- 巡检记录与报告卡片 -->
|
||||||
|
<div class="content-card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2 class="card-title">巡检记录与报告</h2>
|
||||||
|
<div class="flex space-x-2">
|
||||||
|
<button
|
||||||
|
class="px-3 py-1 text-sm rounded-md hover:bg-gray-200 transition"
|
||||||
|
:class="{ 'bg-gray-100 text-gray-700': timeRange === 'month', 'bg-white text-gray-500': timeRange !== 'month' }"
|
||||||
|
@click="handleTimeRangeChange('month')"
|
||||||
|
>
|
||||||
|
月
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="px-3 py-1 text-sm rounded-md hover:bg-gray-100 transition"
|
||||||
|
:class="{ 'bg-gray-100 text-gray-700': timeRange === 'week', 'bg-white text-gray-500': timeRange !== 'week' }"
|
||||||
|
@click="handleTimeRangeChange('week')"
|
||||||
|
>
|
||||||
|
周
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="px-3 py-1 text-sm rounded-md hover:bg-gray-100 transition"
|
||||||
|
:class="{ 'bg-gray-100 text-gray-700': timeRange === 'day', 'bg-white text-gray-500': timeRange !== 'day' }"
|
||||||
|
@click="handleTimeRangeChange('day')"
|
||||||
|
>
|
||||||
|
日
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据卡片 -->
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||||
|
<div class="stat-card">
|
||||||
|
<p class="stat-label">本月完成巡检</p>
|
||||||
|
<p class="stat-value">42</p>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<p class="stat-label">发现问题数</p>
|
||||||
|
<p class="stat-value">7</p>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<p class="stat-label">已解决问题</p>
|
||||||
|
<p class="stat-value">5</p>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<p class="stat-label">平均完成时间</p>
|
||||||
|
<p class="stat-value">45分钟</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="divider"></div>
|
||||||
|
|
||||||
|
<!-- 图表区域 -->
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 py-4">
|
||||||
|
<!-- 饼图 - 本月巡检完成情况 -->
|
||||||
|
<div class="md:col-span-1">
|
||||||
|
<p class="chart-title">本月完成巡检</p>
|
||||||
|
<div class="relative w-32 h-32 mx-auto">
|
||||||
|
<!-- 饼图使用SVG绘制 - 显示本月巡检完成情况 -->
|
||||||
|
<svg class="w-full h-full" viewBox="0 0 100 100">
|
||||||
|
<!-- 背景圆环 -->
|
||||||
|
<circle cx="50" cy="50" r="45" fill="none" stroke="#f3f4f6" stroke-width="10" />
|
||||||
|
<!-- 已完成部分 (72%) -->
|
||||||
|
<circle
|
||||||
|
cx="50"
|
||||||
|
cy="50"
|
||||||
|
r="45"
|
||||||
|
fill="none"
|
||||||
|
stroke="#10b981"
|
||||||
|
stroke-width="10"
|
||||||
|
stroke-dasharray="282.74"
|
||||||
|
stroke-dashoffset="113.1"
|
||||||
|
transform="rotate(-90 50 50)"
|
||||||
|
/>
|
||||||
|
<!-- 未完成部分 (28%) -->
|
||||||
|
<circle
|
||||||
|
cx="50"
|
||||||
|
cy="50"
|
||||||
|
r="45"
|
||||||
|
fill="none"
|
||||||
|
stroke="#f97316"
|
||||||
|
stroke-width="10"
|
||||||
|
stroke-dasharray="113.1"
|
||||||
|
stroke-dashoffset="0"
|
||||||
|
transform="rotate(-90 50 50)"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<!-- 饼图中心显示 -->
|
||||||
|
<div class="absolute inset-0 flex flex-col items-center justify-center">
|
||||||
|
<p class="text-sm text-gray-500">已解决问题</p>
|
||||||
|
<p class="text-lg font-bold text-gray-800">72%</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 饼图图例 -->
|
||||||
|
<div class="mt-3 flex justify-center space-x-4">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="w-3 h-3 rounded-full bg-green-500 mr-1"></div>
|
||||||
|
<span class="text-xs text-gray-600">已解决</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="w-3 h-3 rounded-full bg-orange-500 mr-1"></div>
|
||||||
|
<span class="text-xs text-gray-600">未解决</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 进度条 -->
|
||||||
|
<div class="md:col-span-2 flex flex-col justify-center">
|
||||||
|
<div class="space-y-4">
|
||||||
|
<div>
|
||||||
|
<div class="flex justify-between text-sm mb-1">
|
||||||
|
<span class="text-gray-600">完成率</span>
|
||||||
|
<span class="font-medium text-gray-800">68%</span>
|
||||||
|
</div>
|
||||||
|
<div class="w-full bg-gray-200 rounded-full h-2">
|
||||||
|
<div class="bg-red-500 h-2 rounded-full" style="width: 68%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="flex justify-between text-sm mb-1">
|
||||||
|
<span class="text-gray-600">解决率</span>
|
||||||
|
<span class="font-medium text-gray-800">72%</span>
|
||||||
|
</div>
|
||||||
|
<div class="w-full bg-gray-200 rounded-full h-2">
|
||||||
|
<div class="bg-green-500 h-2 rounded-full" style="width: 72%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="flex justify-between text-sm mb-1">
|
||||||
|
<span class="text-gray-600">及时率</span>
|
||||||
|
<span class="font-medium text-gray-800">60%</span>
|
||||||
|
</div>
|
||||||
|
<div class="w-full bg-gray-200 rounded-full h-2">
|
||||||
|
<div class="bg-gray-500 h-2 rounded-full" style="width: 60%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="divider"></div>
|
||||||
|
|
||||||
|
<!-- 发现问题种类 -->
|
||||||
|
<div class="py-4">
|
||||||
|
<h3 class="section-title">发现问题种类</h3>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<div>
|
||||||
|
<div class="flex justify-between text-sm mb-1">
|
||||||
|
<span class="text-gray-600">温度异常率</span>
|
||||||
|
<span class="text-gray-500">85%</span>
|
||||||
|
</div>
|
||||||
|
<div class="w-full bg-gray-200 rounded-full h-2">
|
||||||
|
<div class="bg-blue-500 h-2 rounded-full" style="width: 85%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="flex justify-between text-sm mb-1">
|
||||||
|
<span class="text-gray-600">内存使用率</span>
|
||||||
|
<span class="text-gray-500">62%</span>
|
||||||
|
</div>
|
||||||
|
<div class="w-full bg-gray-200 rounded-full h-2">
|
||||||
|
<div class="bg-blue-500 h-2 rounded-full" style="width: 62%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="flex justify-between text-sm mb-1">
|
||||||
|
<span class="text-gray-600">CPU负载</span>
|
||||||
|
<span class="text-gray-500">45%</span>
|
||||||
|
</div>
|
||||||
|
<div class="w-full bg-gray-200 rounded-full h-2">
|
||||||
|
<div class="bg-blue-500 h-2 rounded-full" style="width: 45%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="flex justify-between text-sm mb-1">
|
||||||
|
<span class="text-gray-600">响应时间</span>
|
||||||
|
<span class="text-gray-500">30%</span>
|
||||||
|
</div>
|
||||||
|
<div class="w-full bg-gray-200 rounded-full h-2">
|
||||||
|
<div class="bg-blue-500 h-2 rounded-full" style="width: 30%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="flex justify-between text-sm mb-1">
|
||||||
|
<span class="text-gray-600">磁盘空间状态</span>
|
||||||
|
<span class="text-gray-500">15%</span>
|
||||||
|
</div>
|
||||||
|
<div class="w-full bg-gray-200 rounded-full h-2">
|
||||||
|
<div class="bg-blue-500 h-2 rounded-full" style="width: 15%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右侧最近巡检结果 -->
|
||||||
|
<div class="lg:col-span-1" style="display: flex; flex-direction: column; height: 100%">
|
||||||
|
<div class="content-card" style="flex: 1; display: flex; flex-direction: column">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2 class="card-title">最近巡检结果</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 巡检结果列表 -->
|
||||||
|
<div class="card-body" style="flex: 1; overflow-y: auto">
|
||||||
|
<div class="inspection-results space-y-4">
|
||||||
|
<!-- 结果1:正常 -->
|
||||||
|
<div class="inspection-card bg-white border border-gray-200 rounded-lg p-4 shadow-sm">
|
||||||
|
<div class="flex justify-between items-start mb-4">
|
||||||
|
<h3 class="text-lg font-medium text-gray-800">数据库性能巡检</h3>
|
||||||
|
<span class="status-tag status-normal px-3 py-1 text-xs">正常</span>
|
||||||
|
</div>
|
||||||
|
<p class="text-sm text-gray-500 mb-3">2025-06-15 14:00-16:45 张明</p>
|
||||||
|
|
||||||
|
<div class="flex justify-between items-center mb-4">
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<i class="fas fa-check-circle text-green-500 text-lg mb-1"></i>
|
||||||
|
<span class="text-xs text-gray-600 mb-1">系统连接量</span>
|
||||||
|
<span class="text-sm font-medium">128<500</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<i class="fas fa-check-circle text-green-500 text-lg mb-1"></i>
|
||||||
|
<span class="text-xs text-gray-600 mb-1">查询响应时间</span>
|
||||||
|
<span class="text-sm font-medium">平均0.3S</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<i class="fas fa-check-circle text-green-500 text-lg mb-1"></i>
|
||||||
|
<span class="text-xs text-gray-600 mb-1">表空间使用率</span>
|
||||||
|
<span class="text-sm font-medium">75%</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<i class="fas fa-check-circle text-green-500 text-lg mb-1"></i>
|
||||||
|
<span class="text-xs text-gray-600 mb-1">日志文件</span>
|
||||||
|
<span class="text-sm font-medium">正常轮转</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-end gap-2">
|
||||||
|
<el-button size="small" class="text-sm border-gray-300 text-gray-600">查看详情</el-button>
|
||||||
|
<el-button type="primary" size="small" class="text-sm">生成报告</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 结果2:需关注 -->
|
||||||
|
<div class="inspection-card bg-white border border-gray-200 rounded-lg p-4 shadow-sm">
|
||||||
|
<div class="flex justify-between items-start mb-4">
|
||||||
|
<h3 class="text-lg font-medium text-gray-800">生产服务器日常巡检</h3>
|
||||||
|
<span class="status-tag status-attention px-3 py-1 text-xs">需关注</span>
|
||||||
|
</div>
|
||||||
|
<p class="text-sm text-gray-500 mb-3">2025-06-15 14:00-16:45 张明</p>
|
||||||
|
|
||||||
|
<div class="flex justify-between items-center mb-4">
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<i class="fas fa-check-circle text-green-500 text-lg mb-1"></i>
|
||||||
|
<span class="text-xs text-gray-600 mb-1">CPU使用率</span>
|
||||||
|
<span class="text-sm font-medium">平均35%,峰值59%</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<i class="fas fa-exclamation-circle text-yellow-500 text-lg mb-1"></i>
|
||||||
|
<span class="text-xs text-gray-600 mb-1">内存使用率</span>
|
||||||
|
<span class="text-sm font-medium">85%</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<i class="fas fa-check-circle text-green-500 text-lg mb-1"></i>
|
||||||
|
<span class="text-xs text-gray-600 mb-1">磁盘空间</span>
|
||||||
|
<span class="text-sm font-medium">62%</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<i class="fas fa-check-circle text-green-500 text-lg mb-1"></i>
|
||||||
|
<span class="text-xs text-gray-600 mb-1">服务状态</span>
|
||||||
|
<span class="text-sm font-medium">正常运行</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-yellow-50 border border-yellow-200 rounded-md p-3 mb-4">
|
||||||
|
<div class="flex items-start">
|
||||||
|
<i class="fas fa-info-circle text-yellow-500 mt-0.5 mr-2"></i>
|
||||||
|
<p class="text-xs text-yellow-800">已创建问题单 #PRB-2023061501,计划于今晚进行内存扩容</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-end gap-2">
|
||||||
|
<el-button size="small" class="text-sm border-gray-300 text-gray-600">查看详情</el-button>
|
||||||
|
<el-button type="primary" size="small" class="text-sm">生成报告</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 结果3:有问题 -->
|
||||||
|
<div class="inspection-card bg-white border border-gray-200 rounded-lg p-4 shadow-sm">
|
||||||
|
<div class="flex justify-between items-start mb-4">
|
||||||
|
<h3 class="text-lg font-medium text-gray-800">网络设备安全巡检</h3>
|
||||||
|
<span class="status-tag status-problem px-3 py-1 text-xs">有问题</span>
|
||||||
|
</div>
|
||||||
|
<p class="text-sm text-gray-500 mb-3">2025-06-14 10:00-11:30 李华</p>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-2 gap-2 mb-4">
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<i class="fas fa-times-circle text-red-500 text-lg mb-1"></i>
|
||||||
|
<span class="text-xs text-gray-600 mb-1">防火墙规则</span>
|
||||||
|
<span class="text-sm font-medium">部分规则异常</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<i class="fas fa-exclamation-circle text-yellow-500 text-lg mb-1"></i>
|
||||||
|
<span class="text-xs text-gray-600 mb-1">安全补丁</span>
|
||||||
|
<span class="text-sm font-medium">需更新</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<i class="fas fa-check-circle text-green-500 text-lg mb-1"></i>
|
||||||
|
<span class="text-xs text-gray-600 mb-1">访问控制</span>
|
||||||
|
<span class="text-sm font-medium">正常</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<i class="fas fa-check-circle text-green-500 text-lg mb-1"></i>
|
||||||
|
<span class="text-xs text-gray-600 mb-1">流量监控</span>
|
||||||
|
<span class="text-sm font-medium">正常</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-end gap-2">
|
||||||
|
<el-button size="small" class="text-sm border-gray-300 text-gray-600">查看详情</el-button>
|
||||||
|
<el-button type="primary" size="small" class="text-sm">生成报告</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import router from '@/router';
|
||||||
|
import TitleComponent from '@/views/demo/components/TitleComponent.vue';
|
||||||
|
|
||||||
|
// 筛选条件
|
||||||
|
const filterStatus = ref('all');
|
||||||
|
const filterType = ref('all');
|
||||||
|
const dateRange = ref([]);
|
||||||
|
|
||||||
|
// 时间范围选择
|
||||||
|
const timeRange = ref('month'); // 默认选中"月"
|
||||||
|
|
||||||
|
// 时间范围切换函数
|
||||||
|
const handleTimeRangeChange = (range) => {
|
||||||
|
timeRange.value = range;
|
||||||
|
// 在实际应用中,这里应该根据选择的时间范围重新获取数据
|
||||||
|
console.log(`切换到${range}视图`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 导航方法
|
||||||
|
const handleInspection1 = () => {
|
||||||
|
router.push('/rili/rili');
|
||||||
|
};
|
||||||
|
const handleInspection2 = () => {
|
||||||
|
router.push('/rili/InspectionManagement');
|
||||||
|
};
|
||||||
|
const handleInspectionManagement1 = () => {
|
||||||
|
router.push('/rili/InspectionManagement');
|
||||||
|
};
|
||||||
|
const handleInspectionManagement2 = () => {
|
||||||
|
router.push('/rili/xunjianrenwu');
|
||||||
|
};
|
||||||
|
const handleInspectionManagement3 = () => {
|
||||||
|
router.push('/rili/xunjianjihua');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 主容器样式 */
|
||||||
|
.operation-inspection {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 导航栏样式 */
|
||||||
|
.navigation-tabs {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab {
|
||||||
|
padding: 12px 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
border-right: 1px solid #f0f0f0;
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab:hover {
|
||||||
|
color: #409eff;
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab.active {
|
||||||
|
background-color: #409eff;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab {
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选项卡样式 */
|
||||||
|
.tabs-wrapper {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 筛选栏样式 */
|
||||||
|
.filter-bar {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-bar .el-select,
|
||||||
|
.filter-bar .el-date-picker {
|
||||||
|
width: 150px;
|
||||||
|
height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-actions {
|
||||||
|
margin-left: auto;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-btn,
|
||||||
|
.export-btn,
|
||||||
|
.create-btn {
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 内容卡片样式 */
|
||||||
|
.content-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
padding: 20px;
|
||||||
|
border-bottom: 1px solid #e4e7ed;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-body {
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 统计卡片样式 */
|
||||||
|
.stat-card {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 分隔线 */
|
||||||
|
.divider {
|
||||||
|
height: 1px;
|
||||||
|
background-color: #e4e7ed;
|
||||||
|
margin: 16px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 图表标题 */
|
||||||
|
.chart-title {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 区域标题 */
|
||||||
|
.section-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
margin: 0 0 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 记录列表样式 */
|
||||||
|
.record-list {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-item {
|
||||||
|
padding: 16px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-time,
|
||||||
|
.record-type {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
margin: 4px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 状态标签 */
|
||||||
|
.status-tag {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-normal {
|
||||||
|
background-color: #f0f9eb;
|
||||||
|
color: #52c41a;
|
||||||
|
border: 1px solid #e1f3d8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-attention {
|
||||||
|
background-color: #fffbe6;
|
||||||
|
color: #faad14;
|
||||||
|
border: 1px solid #fff1b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-problem {
|
||||||
|
background-color: #fff2f0;
|
||||||
|
color: #f5222d;
|
||||||
|
border: 1px solid #ffe3e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 操作按钮 */
|
||||||
|
.action-btn {
|
||||||
|
color: #409eff;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn:hover {
|
||||||
|
color: #66b1ff;
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 响应式设计 */
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.filter-bar {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-actions {
|
||||||
|
margin-left: 0;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
892
src/views/dhr_demo/xunjianrenwu.vue
Normal file
892
src/views/dhr_demo/xunjianrenwu.vue
Normal file
@ -0,0 +1,892 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<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">试验管理</div>
|
||||||
|
<div class="nav-tab">报修管理</div>
|
||||||
|
<div class="nav-tab">抢修管理</div>
|
||||||
|
<div class="nav-tab">工单管理</div>
|
||||||
|
</div>
|
||||||
|
<!-- 页面标题 -->
|
||||||
|
<TitleComponent title="运维巡检管理" subtitle="制定巡检计划,安排巡检任务,跟进巡检记录"></TitleComponent>
|
||||||
|
|
||||||
|
<!-- 选项卡 -->
|
||||||
|
<div class="tabs-wrapper">
|
||||||
|
<div style="display: flex; align-items: center; gap: 10px">
|
||||||
|
<el-button type="primary" @click="handleInspectionManagement1">巡检计划</el-button>
|
||||||
|
<el-button type="primary" @click="handleInspectionManagement2">巡检任务</el-button>
|
||||||
|
<el-button type="primary" @click="handleInspectionManagement3">巡检记录</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 筛选栏 -->
|
||||||
|
<div class="filter-bar">
|
||||||
|
<div class="filter-container">
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select v-model="taskStatus" placeholder="任务状态">
|
||||||
|
<el-option label="待执行" value="pending"></el-option>
|
||||||
|
<el-option label="执行中" value="executing"></el-option>
|
||||||
|
<el-option label="已延期" value="delayed"></el-option>
|
||||||
|
<el-option label="已完成" value="completed"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select v-model="planType" placeholder="全部计划">
|
||||||
|
<el-option label="每日巡检计划" value="daily"></el-option>
|
||||||
|
<el-option label="每周巡检计划" value="weekly"></el-option>
|
||||||
|
<el-option label="每月巡检计划" value="monthly"></el-option>
|
||||||
|
<el-option label="每季度巡检计划" value="quarterly"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select v-model="executor" placeholder="执行人">
|
||||||
|
<el-option label="全部人员" value="all"></el-option>
|
||||||
|
<el-option label="张明" value="zhangming"></el-option>
|
||||||
|
<el-option label="李华" value="lihua"></el-option>
|
||||||
|
<el-option label="王强" value="wangqiang"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-actions">
|
||||||
|
<el-button type="primary" class="search-btn" @click="handleSearch"> <i class="el-icon-search mr-1"></i>搜索 </el-button>
|
||||||
|
<el-button type="primary" icon="el-icon-plus" class="create-btn" @click="handleCreateTask"> 手动创建任务 </el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 任务卡片列表 -->
|
||||||
|
<div class="task-cards">
|
||||||
|
<div class="task-card" v-for="(task, index) in pagedTasks" :key="index">
|
||||||
|
<div class="task-header">
|
||||||
|
<div class="task-title">
|
||||||
|
{{ task.title }}
|
||||||
|
</div>
|
||||||
|
<div class="task-status" :class="task.statusClass">
|
||||||
|
{{ task.statusText }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="task-details">
|
||||||
|
<div class="detail-item">
|
||||||
|
<span class="detail-label">计划时间</span>
|
||||||
|
<span class="detail-value">{{ task.planTime }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item">
|
||||||
|
<span class="detail-label">巡检对象</span>
|
||||||
|
<span class="detail-value">{{ task.target }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item">
|
||||||
|
<span class="detail-label">执行人</span>
|
||||||
|
<span class="detail-value">{{ task.executor }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="detail-item">
|
||||||
|
<span class="detail-label">关联计划</span>
|
||||||
|
<span class="detail-value">{{ task.relatedPlan }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 特定状态的额外信息 -->
|
||||||
|
<div v-if="task.status === 'delayed'" class="delay-reason">
|
||||||
|
<span class="detail-label">延期原因</span>
|
||||||
|
<span class="detail-value">{{ task.delayReason }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="task.status === 'executing'" class="progress-container">
|
||||||
|
<span class="detail-label">完成进度</span>
|
||||||
|
<div class="progress-bar">
|
||||||
|
<el-progress :percentage="task.progress" stroke-width="6" :stroke-color="task.progressColor"></el-progress>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="task.status === 'completed'" class="task-result">
|
||||||
|
<span class="detail-label">结果</span>
|
||||||
|
<span class="detail-value" :class="task.resultClass">{{ task.result }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="task-actions">
|
||||||
|
<el-button type="text" size="small" class="action-btn view-btn" @click="handleView(task)"> 详情 </el-button>
|
||||||
|
<el-button type="primary" size="small" :class="task.actionClass" @click="handleAction(task)">
|
||||||
|
{{ task.actionText }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 分页区域 -->
|
||||||
|
<div class="pagination-section">
|
||||||
|
<div class="pagination-controls">
|
||||||
|
<el-pagination
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
:current-page="currentPage"
|
||||||
|
:page-sizes="[8, 12, 16, 20]"
|
||||||
|
:page-size="pageSize"
|
||||||
|
layout="prev, pager, next, jumper"
|
||||||
|
:total="total"
|
||||||
|
background
|
||||||
|
>
|
||||||
|
</el-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 添加新任务弹窗 -->
|
||||||
|
<el-dialog v-model="createTaskDialogVisible" title="添加新任务" width="500px" :before-close="handleCancelCreateTask">
|
||||||
|
<el-form ref="createTaskFormRef" :model="createTaskForm" :rules="createTaskRules" label-width="80px">
|
||||||
|
<el-form-item label="任务名称" prop="taskName">
|
||||||
|
<el-input v-model="createTaskForm.taskName" placeholder="输入任务名称" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="巡检对象" prop="inspectionTarget">
|
||||||
|
<el-input v-model="createTaskForm.inspectionTarget" placeholder="输入巡检内容" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="时间" prop="timeRange">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="createTaskForm.timeRange"
|
||||||
|
type="datetimerange"
|
||||||
|
start-placeholder="开始时间"
|
||||||
|
end-placeholder="结束时间"
|
||||||
|
format="YYYY-MM-DD HH:mm"
|
||||||
|
value-format="YYYY-MM-DD HH:mm"
|
||||||
|
placeholder="选择时间范围"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="关联计划">
|
||||||
|
<el-select v-model="createTaskForm.relatedPlan" placeholder="选择关联计划">
|
||||||
|
<el-option label="全部计划" value="all" />
|
||||||
|
<el-option label="每日巡检计划" value="daily" />
|
||||||
|
<el-option label="每周巡检计划" value="weekly" />
|
||||||
|
<el-option label="每月巡检计划" value="monthly" />
|
||||||
|
<el-option label="每季度巡检计划" value="quarterly" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="执行人">
|
||||||
|
<el-select v-model="createTaskForm.executor" placeholder="选择执行人">
|
||||||
|
<el-option label="全部人员" value="all" />
|
||||||
|
<el-option label="张明" value="zhangming" />
|
||||||
|
<el-option label="李华" value="lihua" />
|
||||||
|
<el-option label="王强" value="wangqiang" />
|
||||||
|
<el-option label="赵伟" value="zhaowei" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="handleCancelCreateTask">取消</el-button>
|
||||||
|
<el-button type="primary" @click="handleSaveTask">保存任务</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed } from 'vue';
|
||||||
|
import router from '@/router';
|
||||||
|
import TitleComponent from '@/views/demo/components/TitleComponent.vue';
|
||||||
|
|
||||||
|
// 激活的选项卡
|
||||||
|
const activeTab = ref('task');
|
||||||
|
|
||||||
|
// 筛选条件
|
||||||
|
const taskStatus = ref('');
|
||||||
|
const planType = ref('');
|
||||||
|
const executor = ref('');
|
||||||
|
|
||||||
|
// 任务数据
|
||||||
|
const tasks = ref([
|
||||||
|
{
|
||||||
|
title: '生产服务器日常巡检',
|
||||||
|
status: 'pending',
|
||||||
|
statusText: '待执行',
|
||||||
|
statusClass: 'status-pending',
|
||||||
|
planTime: '2025-06-16 08:30',
|
||||||
|
target: '生产服务器集群(12台)',
|
||||||
|
executor: '张明',
|
||||||
|
relatedPlan: '每日巡检计划',
|
||||||
|
actionText: '开始执行',
|
||||||
|
actionClass: 'start-btn'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '机房环境检查',
|
||||||
|
status: 'delayed',
|
||||||
|
statusText: '已延期',
|
||||||
|
statusClass: 'status-delayed',
|
||||||
|
planTime: '2025-06-16 08:30',
|
||||||
|
target: '机房温度、湿度、电源',
|
||||||
|
executor: '李华',
|
||||||
|
relatedPlan: '每周巡检计划',
|
||||||
|
delayReason: '设备维修处理中',
|
||||||
|
actionText: '重新安排',
|
||||||
|
actionClass: 'reschedule-btn'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '网络设备安全巡检',
|
||||||
|
status: 'executing',
|
||||||
|
statusText: '执行中',
|
||||||
|
statusClass: 'status-executing',
|
||||||
|
planTime: '2025-06-16 09:30',
|
||||||
|
target: '核心交换机、防火墙',
|
||||||
|
executor: '王强',
|
||||||
|
relatedPlan: '每周巡检计划',
|
||||||
|
progress: 60,
|
||||||
|
progressColor: '#FF7D00',
|
||||||
|
actionText: '完成',
|
||||||
|
actionClass: 'complete-btn'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '数据库性能巡检',
|
||||||
|
status: 'completed',
|
||||||
|
statusText: '已完成',
|
||||||
|
statusClass: 'status-completed',
|
||||||
|
planTime: '2025-06-16 10:30',
|
||||||
|
target: '生产数据库集群(2组)',
|
||||||
|
executor: '赵伟',
|
||||||
|
relatedPlan: '每月巡检计划',
|
||||||
|
result: '正常',
|
||||||
|
resultClass: 'result-normal',
|
||||||
|
actionText: '查看报告',
|
||||||
|
actionClass: 'report-btn'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '生产服务器日常巡检',
|
||||||
|
status: 'pending',
|
||||||
|
statusText: '待执行',
|
||||||
|
statusClass: 'status-pending',
|
||||||
|
planTime: '2025-06-16 13:30',
|
||||||
|
target: '生产服务器集群(12台)',
|
||||||
|
executor: '张明',
|
||||||
|
relatedPlan: '每日巡检计划',
|
||||||
|
actionText: '开始执行',
|
||||||
|
actionClass: 'start-btn'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '机房环境检查',
|
||||||
|
status: 'delayed',
|
||||||
|
statusText: '已延期',
|
||||||
|
statusClass: 'status-delayed',
|
||||||
|
planTime: '2025-06-16 14:00',
|
||||||
|
target: '机房温度、湿度、电源',
|
||||||
|
executor: '李华',
|
||||||
|
relatedPlan: '每周巡检计划',
|
||||||
|
delayReason: '设备维修处理中',
|
||||||
|
actionText: '重新安排',
|
||||||
|
actionClass: 'reschedule-btn'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '网络设备安全巡检',
|
||||||
|
status: 'executing',
|
||||||
|
statusText: '执行中',
|
||||||
|
statusClass: 'status-executing',
|
||||||
|
planTime: '2025-06-16 15:00',
|
||||||
|
target: '核心交换机、防火墙',
|
||||||
|
executor: '王强',
|
||||||
|
relatedPlan: '每周巡检计划',
|
||||||
|
progress: 35,
|
||||||
|
progressColor: '#FF7D00',
|
||||||
|
actionText: '完成',
|
||||||
|
actionClass: 'complete-btn'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '数据库性能巡检',
|
||||||
|
status: 'completed',
|
||||||
|
statusText: '已完成',
|
||||||
|
statusClass: 'status-completed',
|
||||||
|
planTime: '2025-06-16 16:00',
|
||||||
|
target: '生产数据库集群(2组)',
|
||||||
|
executor: '赵伟',
|
||||||
|
relatedPlan: '每月巡检计划',
|
||||||
|
result: '正常',
|
||||||
|
resultClass: 'result-normal',
|
||||||
|
actionText: '查看报告',
|
||||||
|
actionClass: 'report-btn'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 分页相关
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const pageSize = ref(8);
|
||||||
|
const total = ref(tasks.value.length);
|
||||||
|
|
||||||
|
// 状态排序映射
|
||||||
|
const statusOrder = {
|
||||||
|
pending: 0, // 待完成
|
||||||
|
delayed: 1, // 已延期
|
||||||
|
executing: 2, // 执行中
|
||||||
|
completed: 3 // 已完成
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页处理后的数据(含排序)
|
||||||
|
const pagedTasks = computed(() => {
|
||||||
|
// 先按状态排序
|
||||||
|
const sortedTasks = [...tasks.value].sort((a, b) => {
|
||||||
|
return statusOrder[a.status] - statusOrder[b.status];
|
||||||
|
});
|
||||||
|
|
||||||
|
// 再进行分页
|
||||||
|
const startIndex = (currentPage.value - 1) * pageSize.value;
|
||||||
|
const endIndex = startIndex + pageSize.value;
|
||||||
|
return sortedTasks.slice(startIndex, endIndex);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 搜索处理
|
||||||
|
const handleSearch = () => {
|
||||||
|
currentPage.value = 1; // 重置到第一页
|
||||||
|
// 实际应用中这里会根据筛选条件过滤数据
|
||||||
|
};
|
||||||
|
|
||||||
|
// 创建任务弹窗相关
|
||||||
|
const createTaskDialogVisible = ref(false);
|
||||||
|
const createTaskForm = ref({
|
||||||
|
taskName: '',
|
||||||
|
inspectionTarget: '',
|
||||||
|
timeRange: [],
|
||||||
|
relatedPlan: 'all',
|
||||||
|
executor: 'all'
|
||||||
|
});
|
||||||
|
|
||||||
|
const createTaskRules = {
|
||||||
|
taskName: [{ required: true, message: '请输入任务名称', trigger: 'blur' }],
|
||||||
|
inspectionTarget: [{ required: true, message: '请输入巡检对象', trigger: 'blur' }],
|
||||||
|
timeRange: [{ required: true, message: '请选择时间范围', trigger: 'change' }]
|
||||||
|
};
|
||||||
|
|
||||||
|
// 创建任务
|
||||||
|
const handleCreateTask = () => {
|
||||||
|
createTaskDialogVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存任务
|
||||||
|
const handleSaveTask = () => {
|
||||||
|
// 模拟保存任务逻辑
|
||||||
|
console.log('保存任务:', createTaskForm.value);
|
||||||
|
// 关闭弹窗
|
||||||
|
createTaskDialogVisible.value = false;
|
||||||
|
// 重置表单
|
||||||
|
createTaskForm.value = {
|
||||||
|
taskName: '',
|
||||||
|
inspectionTarget: '',
|
||||||
|
timeRange: [],
|
||||||
|
relatedPlan: 'all',
|
||||||
|
executor: 'all'
|
||||||
|
};
|
||||||
|
// 这里可以添加成功提示和刷新任务列表的逻辑
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消创建任务
|
||||||
|
const handleCancelCreateTask = () => {
|
||||||
|
createTaskDialogVisible.value = false;
|
||||||
|
// 重置表单
|
||||||
|
createTaskForm.value = {
|
||||||
|
taskName: '',
|
||||||
|
inspectionTarget: '',
|
||||||
|
timeRange: [],
|
||||||
|
relatedPlan: 'all',
|
||||||
|
executor: 'all'
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页事件
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
pageSize.value = val;
|
||||||
|
currentPage.value = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
currentPage.value = val;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 查看任务详情
|
||||||
|
const handleView = (task) => {
|
||||||
|
console.log('查看任务详情:', task);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInspectionManagement1 = () => {
|
||||||
|
router.push('/rili/InspectionManagement');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInspectionManagement2 = () => {
|
||||||
|
router.push('/rili/xunjianrenwu');
|
||||||
|
};
|
||||||
|
const handleInspectionManagement3 = () => {
|
||||||
|
router.push('/rili/xunjianjihua');
|
||||||
|
};
|
||||||
|
const handleInspection1 = () => {
|
||||||
|
router.push('/rili/rili');
|
||||||
|
};
|
||||||
|
const handleInspection2 = () => {
|
||||||
|
router.push('/rili/InspectionManagement');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.inspection-tasks {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选项卡样式 */
|
||||||
|
.tabs-wrapper {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-tabs {
|
||||||
|
border-bottom: none;
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-tabs .el-tabs__header {
|
||||||
|
margin: 0 -20px 0 -20px;
|
||||||
|
padding: 0 20px;
|
||||||
|
border-bottom: 1px solid #e4e7ed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-tabs .el-tabs__nav-wrap::after {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-tabs .el-tabs__item {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
padding: 12px 20px;
|
||||||
|
margin-right: 20px;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-tabs .el-tabs__item.is-active {
|
||||||
|
color: #409eff;
|
||||||
|
border-bottom-color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-tabs .el-tabs__item:hover {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
/* 筛选栏样式 */
|
||||||
|
.filter-bar {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
|
||||||
|
padding: 16px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-bar .el-select {
|
||||||
|
width: 180px;
|
||||||
|
height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-bar .el-select .el-input__inner {
|
||||||
|
border-radius: 4px;
|
||||||
|
border-color: #dcdfe6;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-bar .el-select .el-input__inner:focus {
|
||||||
|
border-color: #165dff;
|
||||||
|
box-shadow: 0 0 0 2px rgba(22, 93, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-actions {
|
||||||
|
margin-left: auto;
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-btn {
|
||||||
|
background-color: #f2f3f5;
|
||||||
|
color: #303133;
|
||||||
|
border-color: #f2f3f5;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-btn:hover {
|
||||||
|
background-color: #e5e6eb;
|
||||||
|
color: #303133;
|
||||||
|
border-color: #e5e6eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.create-btn {
|
||||||
|
background-color: #165dff;
|
||||||
|
border-color: #165dff;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.create-btn:hover {
|
||||||
|
background-color: #0e42d2;
|
||||||
|
border-color: #0e42d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 任务卡片样式 */
|
||||||
|
.task-cards {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
|
||||||
|
padding: 16px 16px 60px 16px; /* 底部留出更多空间给按钮 */
|
||||||
|
transition: box-shadow 0.2s ease;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: 280px; /* 确保有足够高度显示所有内容 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 12px;
|
||||||
|
border-top: 1px solid #f0f2f5;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 16px;
|
||||||
|
right: 16px;
|
||||||
|
left: 16px;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 12px 0 0 0;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-card::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-card.status-pending::before {
|
||||||
|
background-color: #1677ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-card.status-delayed::before {
|
||||||
|
background-color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-card.status-executing::before {
|
||||||
|
background-color: #fa8c16;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-card.status-completed::before {
|
||||||
|
background-color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-card:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
border-bottom: 1px solid #f0f2f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #1d2129;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-status {
|
||||||
|
padding: 4px 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 待执行状态 - 蓝色 */
|
||||||
|
.status-pending {
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
color: #1677ff;
|
||||||
|
border-color: #91d5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 已延期状态 - 红色 */
|
||||||
|
.status-delayed {
|
||||||
|
background-color: #fff2f0;
|
||||||
|
color: #ff4d4f;
|
||||||
|
border-color: #ffccc7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 执行中状态 - 黄色 */
|
||||||
|
.status-executing {
|
||||||
|
background-color: #fffbe6;
|
||||||
|
color: #fa8c16;
|
||||||
|
border-color: #ffe58f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 已完成状态 - 绿色 */
|
||||||
|
.status-completed {
|
||||||
|
background-color: #f6ffed;
|
||||||
|
color: #52c41a;
|
||||||
|
border-color: #b7eb8f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-details {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-label {
|
||||||
|
flex: 0 0 80px;
|
||||||
|
color: #86909c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-value {
|
||||||
|
flex: 1;
|
||||||
|
color: #4e5969;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delay-reason {
|
||||||
|
display: flex;
|
||||||
|
margin: 10px 0;
|
||||||
|
font-size: 13px;
|
||||||
|
padding-top: 8px;
|
||||||
|
border-top: 1px dashed #f0f2f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin: 10px 0;
|
||||||
|
padding-top: 8px;
|
||||||
|
border-top: 1px dashed #f0f2f5;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
flex: 1;
|
||||||
|
padding-left: 80px;
|
||||||
|
margin-top: 4px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-text {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #86909c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-result {
|
||||||
|
display: flex;
|
||||||
|
margin: 10px 0;
|
||||||
|
font-size: 13px;
|
||||||
|
padding-top: 8px;
|
||||||
|
border-top: 1px dashed #f0f2f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-normal {
|
||||||
|
color: #00b42a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-abnormal {
|
||||||
|
color: #f53f3f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 12px;
|
||||||
|
border-top: 1px solid #f0f2f5;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 16px;
|
||||||
|
right: 16px;
|
||||||
|
left: 16px;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 12px 0 0 0;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-btn {
|
||||||
|
color: #165dff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-btn:hover {
|
||||||
|
color: #0e42d2;
|
||||||
|
background-color: #e8f3ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.start-btn {
|
||||||
|
background-color: #165dff;
|
||||||
|
border-color: #165dff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.start-btn:hover {
|
||||||
|
background-color: #0e42d2;
|
||||||
|
border-color: #0e42d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reschedule-btn {
|
||||||
|
background-color: #ff7d00;
|
||||||
|
border-color: #ff7d00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reschedule-btn:hover {
|
||||||
|
background-color: #e86a00;
|
||||||
|
border-color: #e86a00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.complete-btn {
|
||||||
|
background-color: #00b42a;
|
||||||
|
border-color: #00b42a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.complete-btn:hover {
|
||||||
|
background-color: #008718;
|
||||||
|
border-color: #008718;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-btn {
|
||||||
|
background-color: #86909c;
|
||||||
|
border-color: #86909c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-btn:hover {
|
||||||
|
background-color: #6b7785;
|
||||||
|
border-color: #6b7785;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 分页区域样式 */
|
||||||
|
.pagination-section {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-controls .el-pagination {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-controls .el-pagination button,
|
||||||
|
.pagination-controls .el-pagination .el-pager li {
|
||||||
|
min-width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
line-height: 36px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-controls .el-pagination .el-pager li.active {
|
||||||
|
background-color: #165dff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 响应式设计 */
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.task-cards {
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.inspection-tasks {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-container {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-actions {
|
||||||
|
margin-left: 0;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-bar .el-select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-cards {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 导航栏样式 */
|
||||||
|
.navigation-tabs {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab {
|
||||||
|
padding: 12px 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
border-right: 1px solid #f0f0f0;
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab:hover {
|
||||||
|
color: #409eff;
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab.active {
|
||||||
|
background-color: #409eff;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab {
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="leftPage">
|
<div class="leftPage">
|
||||||
<div class="topPage">
|
<div class="topPage">
|
||||||
<Title style="font-size: 22px" title="企业关键指标" />
|
<Title title="企业关键指标" />
|
||||||
<div class="indicators">
|
<div class="indicators">
|
||||||
<div class="indicator-card" v-for="indicator in indicators" :key="indicator.id">
|
<div class="indicator-card" v-for="indicator in indicators" :key="indicator.id">
|
||||||
<div style="display: flex; align-items: baseline; gap: 4px; margin-bottom: 5px">
|
<div style="display: flex; align-items: baseline; gap: 4px; margin-bottom: 5px">
|
||||||
@ -17,7 +17,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="endPage">
|
<div class="endPage">
|
||||||
<Title style="font-size: 22px" title="人员情况" />
|
<Title title="人员情况" />
|
||||||
<!-- 人员总览区域 -->
|
<!-- 人员总览区域 -->
|
||||||
<div class="people_overview">
|
<div class="people_overview">
|
||||||
<div class="people_overview_content">
|
<div class="people_overview_content">
|
||||||
@ -80,7 +80,7 @@
|
|||||||
|
|
||||||
<!-- 项目出勤率柱状图 -->
|
<!-- 项目出勤率柱状图 -->
|
||||||
<div class="project_attendance_chart">
|
<div class="project_attendance_chart">
|
||||||
<Title style="font-size: 22px" title="项目出勤率统计" />
|
<Title title="项目出勤率统计" />
|
||||||
|
|
||||||
<div class="chart_content" ref="attendanceChartRef"></div>
|
<div class="chart_content" ref="attendanceChartRef"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -108,31 +108,31 @@ const mapChartRef = ref<HTMLDivElement | null>(null);
|
|||||||
const indicators = ref([
|
const indicators = ref([
|
||||||
{
|
{
|
||||||
id: '1',
|
id: '1',
|
||||||
name: '在建项目',
|
name: '光伏项目',
|
||||||
value: '28',
|
value: '28',
|
||||||
unit: '个',
|
unit: '个',
|
||||||
iconPath: '/assets/demo/beUnder.png'
|
iconPath: '/assets/demo/beUnder.png'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '2',
|
id: '2',
|
||||||
name: '合同总额',
|
name: '风电项目',
|
||||||
value: '288.88',
|
value: '288.88',
|
||||||
unit: '亿元',
|
unit: '个',
|
||||||
iconPath: '/assets/demo/contract.png'
|
iconPath: '/src/assets/images/contract.png'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '3',
|
id: '3',
|
||||||
name: '总容量',
|
name: '光伏系统总容量',
|
||||||
value: '158.88',
|
value: '158.88',
|
||||||
unit: '个',
|
unit: 'MW',
|
||||||
iconPath: '/assets/demo/totalCapacity.png'
|
iconPath: '/src/assets/images/totalCapacity.png'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '4',
|
id: '4',
|
||||||
name: '今日施工',
|
name: '风电项目总容量',
|
||||||
value: '18',
|
value: '18',
|
||||||
unit: '个',
|
unit: 'MW',
|
||||||
iconPath: '/assets/demo/todayConstruction.png'
|
iconPath: '/src/assets/images/todayConstruction.png'
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -255,7 +255,7 @@ const scrollToProject = (index: number) => {
|
|||||||
// 计算滚动条应该移动到的位置
|
// 计算滚动条应该移动到的位置
|
||||||
// 确保当前项目居中显示
|
// 确保当前项目居中显示
|
||||||
const totalProjects = projectAttendanceData.value.length;
|
const totalProjects = projectAttendanceData.value.length;
|
||||||
const visiblePercentage = 15; // 与dataZoom的end值保持一致
|
const visiblePercentage = 20; // 与dataZoom的end值保持一致
|
||||||
const itemPercentage = 100 / totalProjects; // 每个项目所占总宽度的百分比
|
const itemPercentage = 100 / totalProjects; // 每个项目所占总宽度的百分比
|
||||||
|
|
||||||
// 计算新的start值,使当前项目尽量居中显示
|
// 计算新的start值,使当前项目尽量居中显示
|
||||||
@ -273,28 +273,6 @@ const scrollToProject = (index: number) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 开始自动滚动
|
|
||||||
*/
|
|
||||||
const startScroll = () => {
|
|
||||||
if (scrollInterval.value) return;
|
|
||||||
|
|
||||||
scrollInterval.value = window.setInterval(() => {
|
|
||||||
currentScrollIndex.value++;
|
|
||||||
scrollToProject(currentScrollIndex.value);
|
|
||||||
}, scrollSpeed);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 停止自动滚动
|
|
||||||
*/
|
|
||||||
const stopScroll = () => {
|
|
||||||
if (scrollInterval.value) {
|
|
||||||
clearInterval(scrollInterval.value);
|
|
||||||
scrollInterval.value = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取项目出勤率统计数据 - 保持项目出勤率图表功能
|
* 获取项目出勤率统计数据 - 保持项目出勤率图表功能
|
||||||
*/
|
*/
|
||||||
@ -367,10 +345,10 @@ const getKeyIndexData = async () => {
|
|||||||
const { data, code } = res;
|
const { data, code } = res;
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
// 更新指标数据,使用接口返回的指定字段
|
// 更新指标数据,使用接口返回的指定字段
|
||||||
indicators.value[0].value = data.ongoingProject || 0;
|
indicators.value[0].value = data.photovoltaicCount || 0;
|
||||||
indicators.value[1].value = data.totalContractAmount || 0;
|
indicators.value[1].value = data.windElectricityCount || 0;
|
||||||
indicators.value[2].value = data.totalCapacity || 0;
|
indicators.value[2].value = data.photovoltaicTotalCapacity || 0;
|
||||||
indicators.value[3].value = data.todayProject || 0;
|
indicators.value[3].value = data.windElectricityTotalCapacity || 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -593,17 +571,9 @@ const initAttendanceChart = () => {
|
|||||||
|
|
||||||
attendanceChart.setOption(option);
|
attendanceChart.setOption(option);
|
||||||
|
|
||||||
// 添加鼠标悬浮事件监听
|
// 移除自动滚动功能,保留其他事件监听
|
||||||
if (attendanceChartRef.value) {
|
if (attendanceChartRef.value) {
|
||||||
// 鼠标进入图表区域时停止滚动
|
// 保留其他可能需要的事件监听器
|
||||||
attendanceChartRef.value.addEventListener('mouseenter', () => {
|
|
||||||
stopScroll();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 鼠标离开图表区域时重新开始滚动
|
|
||||||
attendanceChartRef.value.addEventListener('mouseleave', () => {
|
|
||||||
startScroll();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加窗口大小变化时的图表更新
|
// 添加窗口大小变化时的图表更新
|
||||||
@ -619,11 +589,7 @@ const initAttendanceChart = () => {
|
|||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
window.removeEventListener('resize', handleResize);
|
window.removeEventListener('resize', handleResize);
|
||||||
|
|
||||||
// 移除鼠标事件监听
|
// 移除鼠标事件监听(已在上面移除添加的事件监听)
|
||||||
if (attendanceChartRef.value) {
|
|
||||||
attendanceChartRef.value.removeEventListener('mouseenter', stopScroll);
|
|
||||||
attendanceChartRef.value.removeEventListener('mouseleave', startScroll);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -652,9 +618,6 @@ onMounted(async () => {
|
|||||||
|
|
||||||
// 再初始化图表
|
// 再初始化图表
|
||||||
initAttendanceChart();
|
initAttendanceChart();
|
||||||
|
|
||||||
// 图表初始化后自动开始滚动
|
|
||||||
startScroll();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
@ -667,9 +630,6 @@ onUnmounted(() => {
|
|||||||
attendanceChart.dispose();
|
attendanceChart.dispose();
|
||||||
attendanceChart = null;
|
attendanceChart = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清理滚动计时器
|
|
||||||
stopScroll();
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -879,10 +839,8 @@ onUnmounted(() => {
|
|||||||
text-shadow: 0px 1.24px 6.21px rgba(0, 200, 83, 0.5);
|
text-shadow: 0px 1.24px 6.21px rgba(0, 200, 83, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 点阵地图样式 */
|
|
||||||
.people_map {
|
.people_map {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 120px;
|
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
background: rgba(10, 24, 45, 0.5);
|
background: rgba(10, 24, 45, 0.5);
|
||||||
border: 1px solid rgba(29, 214, 255, 0.1);
|
border: 1px solid rgba(29, 214, 255, 0.1);
|
||||||
|
@ -71,15 +71,17 @@ let data = [
|
|||||||
const getTrajectoryData = async () => {
|
const getTrajectoryData = async () => {
|
||||||
try {
|
try {
|
||||||
// 从URL参数中获取clientId、projectId和userId
|
// 从URL参数中获取clientId、projectId和userId
|
||||||
const { clientId, projectId, userId } = route.query;
|
const { clientId, projectId, userId, gpsType } = route.query;
|
||||||
|
|
||||||
if (!clientId || !projectId || !userId) {
|
if (!projectId || !userId || !gpsType) {
|
||||||
ElMessage.warning('缺少必要参数,请检查传入的参数');
|
ElMessage.warning('缺少必要参数,请检查传入的参数');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const res = await getFootNote({ clientId, projectId, userId });
|
// 确保gpsType转换为数字类型,以便正确传递给后端
|
||||||
|
const gpsTypeNum = parseInt(gpsType, 10);
|
||||||
|
const res = await getFootNote({ clientId, projectId, userId, gpsType: gpsTypeNum });
|
||||||
|
|
||||||
if (res && res.code === 200 && res.data && res.data.length > 0) {
|
if (res && res.code === 200 && res.data && res.data.length > 0) {
|
||||||
data = res.data;
|
data = res.data;
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
<el-card shadow="never">
|
<el-card shadow="never">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="20" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['gps:equipment:edit']"
|
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['gps:equipment:edit']"
|
||||||
>修改</el-button
|
>修改</el-button
|
||||||
@ -39,7 +39,12 @@
|
|||||||
>
|
>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="2">
|
<el-col :span="2">
|
||||||
<el-button type="primary" plain @click="handleViewAll">{{ viewAllButtonText }}</el-button>
|
<el-button type="primary" plain @click="toggleGpsType">
|
||||||
|
{{ currentGpsType === 0 ? '显示用户数据' : '显示设备数据' }}
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="2">
|
||||||
|
<el-button type="primary" v-if="queryParams.gpsType !== 1" plain @click="handleViewAll">{{ viewAllButtonText }}</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
@ -102,7 +107,7 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
icon="Location"
|
icon="Location"
|
||||||
v-hasPermi="['gps:equipmentSon:getList']"
|
v-hasPermi="['gps:equipmentSon:getList']"
|
||||||
@click="handleGoToEmptyPage(scope.row.userId, scope.row.projectId, scope.row.clientId)"
|
@click="handleGoToEmptyPage(scope.row.userId, scope.row.projectId, scope.row.clientId, scope.row.gpsType)"
|
||||||
:disabled="!scope.row.userId || !scope.row.projectId"
|
:disabled="!scope.row.userId || !scope.row.projectId"
|
||||||
></el-button>
|
></el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
@ -189,7 +194,7 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
icon="Location"
|
icon="Location"
|
||||||
v-hasPermi="['gps:equipmentSon:getList']"
|
v-hasPermi="['gps:equipmentSon:getList']"
|
||||||
@click="handleGoToEmptyPage(scope.row.userId, scope.row.projectId, currentHistoryClientId)"
|
@click="handleGoToEmptyPage(scope.row.userId, scope.row.projectId, currentHistoryClientId, currentGpsType)"
|
||||||
></el-button>
|
></el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
@ -301,6 +306,9 @@ const initFormData: EquipmentForm = {
|
|||||||
remark: undefined
|
remark: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 当前GPS类型 (0:设备数据, 1:用户数据)
|
||||||
|
const currentGpsType = ref(0);
|
||||||
|
|
||||||
// 页面数据
|
// 页面数据
|
||||||
const data = reactive<PageData<EquipmentForm, EquipmentQuery>>({
|
const data = reactive<PageData<EquipmentForm, EquipmentQuery>>({
|
||||||
form: { ...initFormData },
|
form: { ...initFormData },
|
||||||
@ -317,6 +325,7 @@ const data = reactive<PageData<EquipmentForm, EquipmentQuery>>({
|
|||||||
creationTime: undefined,
|
creationTime: undefined,
|
||||||
lastAccessedTime: undefined,
|
lastAccessedTime: undefined,
|
||||||
registered: undefined,
|
registered: undefined,
|
||||||
|
gpsType: 0, // 默认显示设备数据
|
||||||
params: {}
|
params: {}
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
@ -385,6 +394,15 @@ const formatDateTime = (timestamp: any): string => {
|
|||||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** 切换GPS数据类型 */
|
||||||
|
const toggleGpsType = () => {
|
||||||
|
currentGpsType.value = currentGpsType.value === 0 ? 1 : 0;
|
||||||
|
queryParams.value.gpsType = currentGpsType.value;
|
||||||
|
queryParams.value.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
proxy?.$modal.msgSuccess(`已切换到${currentGpsType.value === 0 ? '设备数据' : '用户数据'}模式`);
|
||||||
|
};
|
||||||
|
|
||||||
/** 获取设备列表 */
|
/** 获取设备列表 */
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
@ -397,6 +415,9 @@ const getList = async () => {
|
|||||||
queryParams.value.projectId = undefined;
|
queryParams.value.projectId = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 确保gpsType参数正确设置
|
||||||
|
queryParams.value.gpsType = currentGpsType.value;
|
||||||
|
|
||||||
const res = await listEquipment(queryParams.value);
|
const res = await listEquipment(queryParams.value);
|
||||||
equipmentList.value = res.rows as ExtendedEquipmentVO[];
|
equipmentList.value = res.rows as ExtendedEquipmentVO[];
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
@ -490,16 +511,24 @@ const handleViewAll = () => {
|
|||||||
getList();
|
getList();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleGoToEmptyPage = (userId: any, projectId: any, clientId: any) => {
|
const handleGoToEmptyPage = (userId: any, projectId: any, clientId: any, gpsType: number) => {
|
||||||
console.log('userId:', userId, 'projectId:', projectId, 'clientId:', clientId);
|
console.log('userId:', userId, 'projectId:', projectId, 'clientId:', clientId, 'gpsType:', gpsType);
|
||||||
|
|
||||||
|
const queryParams: any = {
|
||||||
|
userId: userId,
|
||||||
|
projectId: projectId,
|
||||||
|
gpsType: gpsType,
|
||||||
|
clientId: clientId
|
||||||
|
};
|
||||||
|
|
||||||
|
// 当gpsType为0时传入clientId,为1时不传入
|
||||||
|
if (gpsType === 1 && clientId) {
|
||||||
|
queryParams.clientId = '';
|
||||||
|
}
|
||||||
|
|
||||||
router.push({
|
router.push({
|
||||||
path: './equipmentGPS',
|
path: './equipmentGPS',
|
||||||
query: {
|
query: queryParams
|
||||||
userId: userId,
|
|
||||||
projectId: projectId,
|
|
||||||
clientId: clientId
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
ID<template>
|
<template>
|
||||||
<div class="large-screen">
|
<div class="large-screen">
|
||||||
<Header />
|
<Header />
|
||||||
<div class="nav">
|
<div class="nav">
|
||||||
@ -21,7 +21,6 @@ import leftPage from './components/leftPage.vue';
|
|||||||
import centerPage from './components/centerPage.vue';
|
import centerPage from './components/centerPage.vue';
|
||||||
import rightPage from './components/rightPage.vue';
|
import rightPage from './components/rightPage.vue';
|
||||||
// import '@/assets/styles/element.scss';
|
// import '@/assets/styles/element.scss';
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
@ -101,10 +101,10 @@
|
|||||||
|
|
||||||
<el-table-column label="操作" align="center" fixed="right" width="200">
|
<el-table-column label="操作" align="center" fixed="right" width="200">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<!-- 查看子项按钮 -->
|
<!-- 查看流转台账按钮 -->
|
||||||
<el-tooltip content="查看子项" placement="top">
|
<el-tooltip content="查看流转台账" placement="top">
|
||||||
<el-button link type="primary" @click="handleViewSons(scope.row)" v-hasPermi="['land:landTransferLedger:childrenList']">
|
<el-button link type="primary" @click="handleViewSons(scope.row)" v-hasPermi="['land:landTransferLedger:childrenList']">
|
||||||
查看子项
|
查看流转台账
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip content="删除" placement="top">
|
<el-tooltip content="删除" placement="top">
|
||||||
@ -162,7 +162,7 @@
|
|||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button type="primary" plain icon="Plus" @click="handleAddSon" v-hasPermi="['land:landTransferLedger:childrenAdd']">
|
<el-button type="primary" plain icon="Plus" @click="handleAddSon" v-hasPermi="['land:landTransferLedger:childrenAdd']">
|
||||||
新增子项
|
新增流转台账
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -397,9 +397,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button v-hasPermi="['land:landTransferLedger:addSon']" :loading="sonButtonLoading" type="primary" @click="submitSonForm"
|
<el-button :loading="sonButtonLoading" type="primary" @click="submitSonForm">确 定</el-button>
|
||||||
>确 定</el-button
|
|
||||||
>
|
|
||||||
<el-button @click="cancelSonForm">取 消</el-button>
|
<el-button @click="cancelSonForm">取 消</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -1026,7 +1024,7 @@ const handleAdd = () => {
|
|||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 查看子项按钮操作(打开子项弹窗时) */
|
/** 新增流转台账按钮操作(打开子项弹窗时) */
|
||||||
const handleViewSons = async (row: LandTransferLedgerVO) => {
|
const handleViewSons = async (row: LandTransferLedgerVO) => {
|
||||||
if (!row?.id) return;
|
if (!row?.id) return;
|
||||||
|
|
||||||
@ -1093,7 +1091,7 @@ const handleAddSon = async () => {
|
|||||||
await getListRoad();
|
await getListRoad();
|
||||||
|
|
||||||
// 5. 打开弹窗
|
// 5. 打开弹窗
|
||||||
sonFormDialog.title = '添加子项(继承父项数据)';
|
sonFormDialog.title = '新增流转台账';
|
||||||
sonFormDialog.visible = true;
|
sonFormDialog.visible = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,13 +2,18 @@
|
|||||||
<div class="leftPage">
|
<div class="leftPage">
|
||||||
<div class="topPage">
|
<div class="topPage">
|
||||||
<Title title="项目公告" />
|
<Title title="项目公告" />
|
||||||
<div class="content" ref="contentRef" id="event_scroll" @mouseenter="pauseScroll" @mouseleave="resumeScroll">
|
<div
|
||||||
<div class="content_item" v-for="item in news" :key="item.id" @click="showNewsDetail(item)">
|
class="content"
|
||||||
<img src="@/assets/projectLarge/round.svg" alt="">
|
ref="contentRef"
|
||||||
|
id="event_scroll"
|
||||||
|
@mouseenter.native="autoScrollTable(true, false)"
|
||||||
|
@mouseleave.native="autoScrollTable(false, true)"
|
||||||
|
>
|
||||||
|
<div class="content_item" v-for="item in news" :key="item.id">
|
||||||
|
<img src="@/assets/projectLarge/round.svg" alt="" />
|
||||||
<div class="ellipsis">
|
<div class="ellipsis">
|
||||||
{{ item.title }}
|
{{ item.title }}
|
||||||
<span style="color: rgba(138, 149, 165, 1);">{{ item.id === newId ? '关闭' :
|
<span @click="showNewsDetail(item)" style="color: rgba(138, 149, 165, 1)">{{ item.id === newId ? '关闭' : '查看' }}</span>
|
||||||
'查看' }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -18,40 +23,40 @@
|
|||||||
<!-- <div class="detail_title">{{ newDetail.title }}</div> -->
|
<!-- <div class="detail_title">{{ newDetail.title }}</div> -->
|
||||||
<div class="detail_content" v-html="newDetail.content"></div>
|
<div class="detail_content" v-html="newDetail.content"></div>
|
||||||
<div class="close" @click="newId = ''">
|
<div class="close" @click="newId = ''">
|
||||||
<CircleClose style="width: 1.2em; height: 1.2em;" />
|
<CircleClose style="width: 1.2em; height: 1.2em" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="endPage">
|
<div class="endPage">
|
||||||
<Title title="人员情况" />
|
<Title title="人员情况" />
|
||||||
<div class="map">
|
<div class="map">
|
||||||
<img src="@/assets/projectLarge/map.svg" alt="">
|
<img src="@/assets/projectLarge/map.svg" alt="" />
|
||||||
<!-- <div ref="mapChartRef"></div> -->
|
<!-- <div ref="mapChartRef"></div> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="attendance_tag">
|
<div class="attendance_tag">
|
||||||
<div class="tag_item">
|
<div class="tag_item">
|
||||||
<img src="@/assets/projectLarge/people.svg" alt="">
|
<img src="@/assets/projectLarge/people.svg" alt="" />
|
||||||
<div class="tag_title">出勤人</div>
|
<div class="tag_title">出勤人</div>
|
||||||
<div class="tag_info">
|
<div class="tag_info">
|
||||||
{{ attendanceCount }}
|
{{ attendanceCount }}
|
||||||
<span style="font-size: 14px;">人</span>
|
<span style="font-size: 14px">人</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tag_item">
|
<div class="tag_item">
|
||||||
<img src="@/assets/projectLarge/people.svg" alt="">
|
<img src="@/assets/projectLarge/people.svg" alt="" />
|
||||||
<div class="tag_title">在岗人</div>
|
<div class="tag_title">在岗人</div>
|
||||||
<div class="tag_info">
|
<div class="tag_info">
|
||||||
{{ peopleCount }}
|
{{ peopleCount }}
|
||||||
<span style="font-size: 14px;">人</span>
|
<span style="font-size: 14px">人</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tag_item">
|
<div class="tag_item">
|
||||||
<img src="@/assets/projectLarge/people.svg" alt="">
|
<img src="@/assets/projectLarge/people.svg" alt="" />
|
||||||
<div class="tag_title">出勤率</div>
|
<div class="tag_title">出勤率</div>
|
||||||
<div class="tag_info">
|
<div class="tag_info">
|
||||||
{{ attendanceRate }}
|
{{ attendanceRate }}
|
||||||
<span style="font-size: 14px;">%</span>
|
<span style="font-size: 14px">%</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -65,8 +70,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-for="item in teamAttendanceList" :key="item.id" class="attendance_item">
|
<div v-for="item in teamAttendanceList" :key="item.id" class="attendance_item">
|
||||||
<div class="attendance_item_title">{{ item.teamName }}</div>
|
<div class="attendance_item_title">{{ item.teamName }}</div>
|
||||||
<div class="attendance_item_number">{{ item.attendanceNumber }} <span class="subfont">人/{{ item.allNumber
|
<div class="attendance_item_number">
|
||||||
}}</span></div>
|
{{ item.attendanceNumber }} <span class="subfont">人/{{ item.allNumber }}</span>
|
||||||
|
</div>
|
||||||
<div class="attendance_item_rate">{{ item.attendanceRate }} %</div>
|
<div class="attendance_item_rate">{{ item.attendanceRate }} %</div>
|
||||||
<div class="attendance_item_date subfont">{{ item.attendanceTime }}</div>
|
<div class="attendance_item_date subfont">{{ item.attendanceTime }}</div>
|
||||||
</div>
|
</div>
|
||||||
@ -76,71 +82,80 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue"
|
import { ref } from 'vue';
|
||||||
import Title from './title.vue'
|
import Title from './title.vue';
|
||||||
import { getScreenNews, getScreenPeople } from '@/api/projectScreen';
|
import { getScreenNews, getScreenPeople } from '@/api/projectScreen/index';
|
||||||
|
import { mapOption } from './optionList';
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
projectId: {
|
projectId: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
|
let mapChart = null;
|
||||||
|
const mapChartRef = ref<HTMLDivElement | null>(null);
|
||||||
const contentRef = ref<HTMLDivElement | null>(null);
|
const contentRef = ref<HTMLDivElement | null>(null);
|
||||||
const news = ref([])
|
const news = ref([]);
|
||||||
const newDetail = ref({
|
const newDetail = ref({
|
||||||
title: '',
|
title: '',
|
||||||
content: ''
|
content: ''
|
||||||
})
|
});
|
||||||
const newId = ref('')
|
const newId = ref('');
|
||||||
const attendanceCount = ref(0)
|
const attendanceCount = ref(0);
|
||||||
const attendanceRate = ref(0)
|
const attendanceRate = ref(0);
|
||||||
const peopleCount = ref(0)
|
const peopleCount = ref(0);
|
||||||
const teamAttendanceList = ref([
|
const teamAttendanceList = ref([{ id: '', teamName: '', attendanceNumber: 0, allNumber: 0, attendanceRate: 0, attendanceTime: '' }]);
|
||||||
{ id: "", teamName: "", attendanceNumber: 0, allNumber: 0, attendanceRate: 0, attendanceTime: "" },
|
|
||||||
])
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示新闻详情
|
* 显示新闻详情
|
||||||
*/
|
*/
|
||||||
const showNewsDetail = (item: any) => {
|
const showNewsDetail = (item: any) => {
|
||||||
if (newId.value === item.id) {
|
if (newId.value === item.id) {
|
||||||
newId.value = ''
|
newId.value = '';
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
newDetail.value = item
|
newDetail.value = item;
|
||||||
newId.value = item.id
|
newId.value = item.id;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取项目人员出勤数据
|
* 获取项目人员出勤数据
|
||||||
*/
|
*/
|
||||||
const getPeopleData = async () => {
|
const getPeopleData = async () => {
|
||||||
const res = await getScreenPeople(props.projectId);
|
const res = await getScreenPeople(props.projectId);
|
||||||
const { data, code } = res
|
const { data, code } = res;
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
attendanceCount.value = data.attendanceCount
|
attendanceCount.value = data.attendanceCount;
|
||||||
attendanceRate.value = data.attendanceRate
|
attendanceRate.value = data.attendanceRate;
|
||||||
peopleCount.value = data.peopleCount
|
peopleCount.value = data.peopleCount;
|
||||||
teamAttendanceList.value = data.teamAttendanceList
|
teamAttendanceList.value = data.teamAttendanceList;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取项目新闻数据
|
* 获取项目新闻数据
|
||||||
*/
|
*/
|
||||||
const getNewsData = async () => {
|
const getNewsData = async () => {
|
||||||
const res = await getScreenNews(props.projectId);
|
const res = await getScreenNews(props.projectId);
|
||||||
const { data, code } = res
|
const { data, code } = res;
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
news.value = data
|
news.value = data;
|
||||||
requestAnimationFrame((timestamp) => autoScrollTable(timestamp));
|
autoScrollTable(5);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
var lastTime = 0;
|
var lastTime = 0;
|
||||||
var scrolltimerTable = null
|
const state = reactive({
|
||||||
|
events: [],
|
||||||
|
outputList: [],
|
||||||
|
detialInfoShow: false,
|
||||||
|
notShowPro: [{ id: 37 }, { id: 44 }, { id: 48 }], //模块内容区域不展示的项目(中煤科工 广东户用光伏项目 兴隆光伏)
|
||||||
|
scrolltimerTable: null,
|
||||||
|
flagPause: true //滚动继续滚动
|
||||||
|
});
|
||||||
|
|
||||||
const autoScrollTable = (time: number) => {
|
const autoScrollTable = (time: number) => {
|
||||||
const divData = document.getElementById('event_scroll');
|
const divData = document.getElementById('event_scroll');
|
||||||
@ -175,13 +190,14 @@ const resumeScroll = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getPeopleData()
|
// nextTick(() => {
|
||||||
getNewsData()
|
// initMapChart();
|
||||||
})
|
// });
|
||||||
|
getPeopleData();
|
||||||
onUnmounted(() => {
|
getNewsData();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
@ -35,7 +35,9 @@
|
|||||||
<el-button type="warning" plain icon="Upload" @click="handleImport" v-hasPermi="['supplierInput:supplierInput:import']">导入</el-button>
|
<el-button type="warning" plain icon="Upload" @click="handleImport" v-hasPermi="['supplierInput:supplierInput:import']">导入</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['supplierInput:supplierInput:export']">导出模板</el-button>
|
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['supplierInput:supplierInput:export']"
|
||||||
|
>导出模板</el-button
|
||||||
|
>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -703,7 +705,7 @@ const handleExport = () => {
|
|||||||
try {
|
try {
|
||||||
// 创建a标签并直接下载public目录下的静态文件
|
// 创建a标签并直接下载public目录下的静态文件
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
link.href = '/assets/files/供应商导入模板.xlsx'; // 使用public目录下现有的Excel文件作为模板
|
link.href = '/xx.xlsx';
|
||||||
link.download = '供应商导入模板.xlsx';
|
link.download = '供应商导入模板.xlsx';
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
@ -746,7 +748,7 @@ const handleImport = () => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
// 调用导入接口
|
// 调用导入接口
|
||||||
const res = await leadingIn(formData, queryParams.value.projectId);
|
const res = await leadingIn(formData, queryParams.value.projectId);
|
||||||
console.log("111111111111",queryParams.value.projectId);
|
console.log('111111111111', queryParams.value.projectId);
|
||||||
|
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
proxy?.$modal.msgSuccess('导入成功');
|
proxy?.$modal.msgSuccess('导入成功');
|
||||||
|
Reference in New Issue
Block a user