踩坑记21 div 固定宽高比 padding-bottom | style scoped 时 :deep(.el-input__inner:focus) | javaScript 八进制

本文探讨了三个前端开发中的常见问题:如何使用CSS保持div元素的固定宽高比,通过相对单位实现字体随视口缩放,以及在Vue中解决 scoped 样式穿透el-input组件的问题。解决方案包括利用padding-bottom属性,使用vw单位,以及掌握:deep()深度选择器的正确用法。

2021.9.7

坑67(div、css、固定宽高比 :目标是使div元素在缩放时宽高比固定。因为 垂直方向上的内外边距使用百分比做单位时,是基于包含块的宽度来计算的。所以使用 padding-bottom实现宽高比固定的元素块。
实现:divBox实现固定宽高比,divContent则为其中内容,实现内容定位。
.divBox {
  /* 相对位置,定位基于该元素原先位置 */
  position: relative;
  /* 宽:高=4:3 */
  width: 40%;
  height: 0;
  padding-bottom: 30%;
}
.divContent {
  /* 绝对位置,定位基于父元素位置 */
  position: absolute;
  /* 充满父元素 */
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
坑68(font-size、css、缩放 :目标是使字体大小随视口大小缩放。使用相对长度单位即可。例如,1vw=1%视口宽度。具体使用需依据情况选择合适单位。
坑69(el-input、 el-input__inner:focus 、scoped、css :目标是改变el-input处于focus状态时的border颜色。检查页面元素发现是在.el-input__inner:focus中变更的。于是直接更改,代码如下:(style非scoped时可成功)
.el-input__inner:focus {
  border-color: #FF9505 !important;
}
但是毫无效果,检查页面元素可以看到该样式甚至没有被添加到元素中,也就是说选择器没有成功选到对应元素。
排查发现是因为 style使用了scoped,限制了样式渗透。需要使用深度选择器,这里使用了::v-deep(使用>>>和/deep/的话,均会标红),代码如下:
<style scoped>
::v-deep .el-input__inner:focus {
  border-color: #FF9505 !important;
}
</style>
可以成功达到效果,但提示编译器会提示如下:
[@vue/compiler-sfc] ::v-deep usage as a combinator has been deprecated. Use :deep(<inner-selector>) instead.
表示::v-deep用法已被弃用,请使用 :deep(内部选择器)代替。
于是最终代码如下:
<style scoped>
:deep(.el-input__inner:focus)  {
  border-color: #FF9505 !important;
}
</style>
Scoped CSS | Vue Loader (vuejs.org)   深度作用选择器
坑70(error、javaScript、 八进制 :运行时报错如下。
Octal literals are not allowed in strict mode.
表示 严格模式下不允许八进制字面量。这里不允许的写法是指 旧版的以0为前缀的八进制写法。所以Number不能有01、001、000.1这样不合日常数字的写法。而 新版的八进制写法是以0o为前缀,在javaScript中可以使用,例如0o77,对应十进制的63。
解决报错:将代码中的id=01,改为id=1。如果需要01,可以改用字符串。

by 莫得感情踩坑机(限定)

<template> <view class="detail-container"> <text>这是详情页</text> </view> </template> <script> export default { setup() { // 可以在这里添加逻辑 } } </script> <style> .detail-container { display: flex; justify-content: center; align-items: center; height: 100vh; } </style>这个是我的详情页代码,现在我想要顶部有一个索引板块,板块里有输入框问卷标题:(cWjTitle)、输入框被测评人(dcId)、输入框人员部门(dcDept)、下拉选择框人员状态(state),代码逻辑和接口参照以下代码:<template> <div class="detail-container"> <!-- 索引板块卡片 --> <el-card class="index-card"> <!-- 表单区域 --> <el-form :model="formData" label-position="top" ref="indexForm" class="mobile-form" > <!-- 问卷标题 --> <el-form-item label="问卷标题:" prop="dcWjTitle"> <el-input v-model="formData.dcWjTitle" placeholder="请输入问卷标题" clearable :prefix-icon="Document" /> </el-form-item> <div class="form-row"> <!-- 被测评人 --> <el-form-item label="被测评人:" prop="dcId" class="inline-form-item"> <el-select v-model="formData.dcId" multiple filterable remote reserve-keyword clearable placeholder="请选择被测评人" :remote-method="searchBdr" :loading="bdrLoading" @focus="handleBdrFocus" > <el-option v-for="item in bdrOptions" :key="item.dcId" :label="item.dcName" :value="item.dcId" /> </el-select> </el-form-item> <!-- 人员部门 --> <el-form-item label="人员部门:" prop="dcDept" class="inline-form-item"> <el-input v-model="formData.dcDept" placeholder="请输入人员部门" clearable :prefix-icon="OfficeBuilding" /> </el-form-item> </div> <!-- 提交状态 --> <el-form-item label="提交状态:" prop="state"> <el-select v-model="formData.state" placeholder="请选择提交状态" clearable class="mobile-select" > <el-option label="已提交" :value="1" /> <el-option label="未提交" :value="0" /> </el-select> </el-form-item> <!-- 新增:按钮区域 --> <el-form-item class="button-group"> <el-button type="primary" @click="handleSearch" class="action-button" :icon="Search" > 搜索 </el-button> <el-button @click="handleReset" class="action-button" :icon="Refresh" > 重置 </el-button> </el-form-item> </el-form> </el-card> <!-- 数据显示板块 --> <el-card class="data-card"> <template #header> <div class="card-header"> <el-button type="primary" size="small" :icon="Refresh" @click="fetchData" > 刷新数据 </el-button> </div> </template> <!-- 数据加载 --> <div v-loading="loading" class="card-container"> <div v-for="(item, index) in tableData" :key="item.dcWjId" class="data-card-item" > <!-- 顶部:序号和问卷标题 --> <div class="card-header-section"> <!-- <div class="card-id">序号{{ item.dcWjId }}</div> --> <div class="card-title">{{ item.dcWjTitle }}</div> </div> <!-- 中间:其他数据 --> <div class="card-body-section"> <div class="card-row"> <span class="card-label">被测评人:</span> <span class="card-value">{{ item.dcName }}</span> </div> <div class="card-row"> <span class="card-label">部门:</span> <span class="card-value">{{ item.dcDept }}</span> </div> <div class="card-row"> <span class="card-label">创建间:</span> <span class="card-value">{{ item.createTime }}</span> </div> <div class="card-row"> <span class="card-label">提交间:</span> <span class="card-value">{{ item.updateTime || '-' }}</span> </div> </div> <!-- 底部:状态、得分和操作按钮 --> <div class="card-footer-section"> <div class="status-container"> <el-tag :type="item.state === '1' ? 'success' : 'info'"> {{ item.state === '1' ? '已提交' : '未提交' }} </el-tag> <div class="score">总分: {{ item.score || '0' }}</div> </div> <el-button size="small" type="primary" @click="handleView(item)" class="action-btn" > 编辑/查看 </el-button> </div> </div> <!-- 空数据提示 --> <el-empty v-if="tableData.length === 0" description="暂无数据" /> </div> <!-- 分页控件 --> <div class="pagination-container"> <el-pagination v-model:current-page="pagination.current" v-model:page-size="pagination.size" :page-sizes="[5, 10, 20, 50]" layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" @size-change="handleSizeChange" @current-change="handlePageChange" /> </div> </el-card> </div> </template> <script setup> // 确保正确导入所有 Vue 函数 import { ref, reactive, onMounted, onUnmounted } from 'vue'; import axios from 'axios'; import { Document, User, OfficeBuilding, Search, Refresh } from '@element-plus/icons-vue'; import { ElMessage } from 'element-plus'; import { useRouter } from 'vue-router'; const router = useRouter(); // 环境变量管理API地址 const API_BASE = import.meta.env.VITE_API_BASE || 'http://172.26.26.43/dev-api'; const API_URL = `${API_BASE}/wjdc/wj/listTx`; const BDR_API_URL = `${API_BASE}/wjdc/wj/getBdrList`; // 被测评人相关数据 const bdrOptions = ref([]); // 被测评人选项列表 const bdrLoading = ref(false); // 加载状态 const bdrCache = ref([]); // 缓存所有被测评人数据 // 表单数据 const formData = reactive({ dcWjTitle: '', dcId: [], dcDept: '', state: null }); // 表格数据 const tableData = ref([]); const loading = ref(false); // 分页配置 const pagination = reactive({ current: 1, size: 10, total: 0 }); // 表单引用 const indexForm = ref(null); // 请求取消令牌 let cancelTokenSource = axios.CancelToken.source(); // 处理被测评人输入框获取焦点 const handleBdrFocus = () => { if (bdrCache.value.length === 0) { fetchBdrList(''); } }; // 获取被测评人列表 const fetchBdrList = async (keyword = '') => { const token = getAuthToken(); if (!token) return; bdrLoading.value = true; try { const response = await axios.get(BDR_API_URL, { headers: { 'Authorization': `Bearer ${token}` } }); // 判断返回的数据是否是数组 if (Array.isArray(response.data)) { // 缓存所有数据 bdrCache.value = response.data; // 根据关键字过滤 if (keyword) { const searchTerm = keyword.toLowerCase(); bdrOptions.value = bdrCache.value.filter(item => item.dcName && item.dcName.toLowerCase().includes(searchTerm) ).slice(0, 10); // 最多显示10条 } else { // 未输入关键字显示前10条 bdrOptions.value = bdrCache.value.slice(0, 10); } } else { // 如果不是数组,则按照原有格式处理(假设有code和data) if (response.data && response.data.code === 200) { bdrCache.value = response.data.data || []; // 同样的过滤逻辑 if (keyword) { const searchTerm = keyword.toLowerCase(); bdrOptions.value = bdrCache.value.filter(item => item.dcName.toLowerCase().includes(searchTerm) ).slice(0, 10); } else { bdrOptions.value = bdrCache.value.slice(0, 10); } } else { const msg = response.data?.msg || '返回数据格式不正确'; ElMessage.error('获取被测评人列表失败: ' + msg); } } } catch (error) { console.error('获取被测评人列表失败:', error); ElMessage.error('获取被测评人列表失败'); } finally { bdrLoading.value = false; } }; // 搜索被测评人(防抖) let searchBdrTimer = null; const searchBdr = (query) => { if (searchBdrTimer) clearTimeout(searchBdrTimer); searchBdrTimer = setTimeout(() => { if (bdrCache.value.length === 0) { fetchBdrList(query); } else { // 本地过滤 if (query) { const searchTerm = query.toLowerCase(); bdrOptions.value = bdrCache.value.filter(item => item.dcName.toLowerCase().includes(searchTerm) ).slice(0, 10); } else { bdrOptions.value = bdrCache.value.slice(0, 10); } } }, 300); }; // 获取认证令牌 const getAuthToken = () => { const token = localStorage.getItem('token'); if (!token) { ElMessage.warning('请先登录'); router.push('/login'); return null; } return token; }; // 搜索按钮处理函数 - 防抖 let searchTimer = null; const handleSearch = () => { // 检查被测评人选择数量 if (formData.dcId.length > 1) { ElMessage.warning({ message: '当前只能搜索一个被测人员', duration: 3000 }); return; } if (searchTimer) clearTimeout(searchTimer); searchTimer = setTimeout(() => { pagination.current = 1; fetchData(); }, 300); }; // 重置按钮处理函数 const handleReset = () => { if (indexForm.value) { indexForm.value.resetFields(); // 确保重置后 dcId 是空数组 formData.dcId = []; } handleSearch(); }; // 编辑/查看 const handleView = (row) => { router.push({ name: 'Operation', // 路由名称 params: { id: row.dcWjId // 传递问卷ID作为参数 } }); }; // 分页大小改变 const handleSizeChange = (size) => { pagination.size = size; fetchData(); }; // 页码改变 const handlePageChange = (page) => { pagination.current = page; fetchData(); }; // 获取数据 const fetchData = async () => { // 获取认证令牌 const token = getAuthToken(); if (!token) return; // 取消之前的请求 if (cancelTokenSource) { cancelTokenSource.cancel('请求被取消'); } cancelTokenSource = axios.CancelToken.source(); loading.value = true; try { // 构造请求参数 const params = { pageNum: pagination.current, pageSize: pagination.size, ...formData, // 安全处理:确保 dcId 是数组再 join dcId: Array.isArray(formData.dcId) ? formData.dcId.join(',') : '' // 将数组转换为逗号分隔的字符串 }; // 调用API - 添加认证头 const response = await axios.get(API_URL, { params, cancelToken: cancelTokenSource.token, headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` } }); // 处理响应数据 const { data } = response; if (data && data.code === 200) { // 修改点:直接使用 data.rows 和 data.total tableData.value = data.rows || []; pagination.total = data.total || 0; // 空数据提示 if (tableData.value.length === 0) { ElMessage.info('没有找到匹配的数据'); } } else { const errorMsg = data?.msg || '未知错误'; console.error('API返回错误:', errorMsg); ElMessage.error(`请求失败: ${errorMsg}`); tableData.value = []; pagination.total = 0; } } catch (error) { // 处理认证失败 if (error.response && error.response.status === 401) { ElMessage.error('认证过期,请重新登录'); localStorage.removeItem('token'); router.push('/login'); return; } // 忽略取消请求的错误 if (!axios.isCancel(error)) { console.error('获取数据失败:', error); const errorMsg = error.response?.data?.message || '网络请求失败'; ElMessage.error(`请求失败: ${errorMsg}`); tableData.value = []; pagination.total = 0; } } finally { loading.value = false; } }; // 页面加载获取初始数据 onMounted(() => { fetchData(); }); // 组件卸载取消所有请求 onUnmounted(() => { if (cancelTokenSource) { cancelTokenSource.cancel('组件卸载,取消请求'); } }); </script> <style scoped> .form-row { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 16px; } .inline-form-item { flex: 1; min-width: 250px; } .inline-form-item :deep(.el-form-item__label) { float: left; width: auto; padding-right: 12px; line-height: 32px; } .inline-form-item :deep(.el-form-item__content) { display: flex; flex: 1; } /* 移动端响应式 */ @media (max-width: 768px) { .form-row { flex-direction: column; gap: 16px; } .inline-form-item { min-width: 100%; } .inline-form-item :deep(.el-form-item__label) { float: none; width: 100%; padding-right: 0; padding-bottom: 8px; } } /* 卡片容器样式 */ .card-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); gap: 16px; } /* 单个卡片样式 */ .data-card-item { background: #fff; border-radius: 12px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); padding: 16px; display: flex; flex-direction: column; transition: all 0.3s ease; border: 1px solid #ebeef5; } .data-card-item:hover { transform: translateY(-4px); box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12); } /* 卡片头部(序号+标题) */ .card-header-section { padding-bottom: 12px; border-bottom: 1px solid #f0f2f5; margin-bottom: 12px; } .card-id { font-size: 14px; color: #909399; margin-bottom: 4px; } .card-title { font-size: 16px; font-weight: 600; color: #303133; line-height: 1.4; word-break: break-word; } /* 卡片主体(其他信息) */ .card-body-section { flex: 1; margin-bottom: 12px; } .card-row { display: flex; margin-bottom: 8px; font-size: 14px; } .card-label { color: #606266; min-width: 70px; text-align: right; } .card-value { color: #303133; flex: 1; word-break: break-word; } /* 卡片底部(状态+按钮) */ .card-footer-section { display: flex; justify-content: space-between; align-items: center; padding-top: 12px; border-top: 1px solid #f0f2f5; } .status-container { display: flex; align-items: center; gap: 8px; } .score { font-size: 14px; color: #e6a23c; font-weight: 500; } .action-btn { flex-shrink: 0; } /* 移动端响应式 */ @media (max-width: 768px) { .card-container { grid-template-columns: 1fr; } .card-row { flex-direction: column; margin-bottom: 12px; } .card-label { text-align: left; margin-bottom: 4px; font-weight: 500; } .card-footer-section { flex-direction: column; align-items: stretch; gap: 12px; } .status-container { justify-content: space-between; } } /* 添加选择器样式 */ :deep(.el-select) .el-input__inner { height: auto !important; min-height: 44px; padding: 5px 15px; } /* 标签样式 */ :deep(.el-tag) { margin: 2px 6px 2px 0; } /* 下拉菜单样式 */ :deep(.el-select-dropdown) { max-height: 300px; overflow-y: auto; } .index-card { border-radius: 12px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); } .card-header { font-size: 18px; font-weight: 600; color: #1a1a1a; } .mobile-form { :deep(.el-form-item__label) { font-weight: 500; margin-bottom: 6px; } :deep(.el-input__inner) { height: 44px; border-radius: 8px; } } .mobile-select { width: 100%; :deep(.el-input__inner) { height: 44px; } } /* 按钮区域样式 */ .button-group { display: flex; gap: 12px; margin-top: 16px; } .action-button { flex: 1; height: 46px; font-size: 16px; border-radius: 8px; } /* 移动端响应式调整 */ @media (max-width: 480px) { .button-group { flex-direction: column; gap: 10px; } .action-button { width: 100%; } } </style> 但是样式布局要适用于手机端,注意这个是要写到移动端,uniapp+Vue3的项目里。
07-18
同样的解释对下面代码,尽可能详细且解释语法:<template> <div class="body"> <div class="annotation_Table"> <div class="contentBox"> <el-tabs v-model="activeName" @tab-click="handleClick"> <el-tab-pane label="任务" name="task"></el-tab-pane> <el-tab-pane label="工程" name="engineering"></el-tab-pane> </el-tabs> </div> <div> <div class="treeSelect" v-if="activeName == 'task'"> <el-input size="small" placeholder="请输入内容" suffix-icon="el-icon-search" v-model="taskSearch"> </el-input> </div> <div class="treeSelect" v-else> <el-input size="small" placeholder="请输入内容" suffix-icon="el-icon-search" v-model="engineeringSearch"> </el-input> </div> <!-- <el-tree--> <!-- :data="tree_data"--> <!-- show-checkbox--> <!-- node-key="id"--> <!-- @check="check"--> <!-- :default-expand-all="true"--> <!-- :props="defaultProps"--> <!-- @node-click="handleNodeClick"--> <!-- >--> <!-- </el-tree>--> <!-- 修改:树节点:default-expand-all="true"展开改为false闭合 --> <el-tree class="treeLine" :data="tree_data" show-checkbox :node-key="activeName == 'engineering'?'projectId':'taskId'" @check="check" :default-expand-all="false" :props="defaultProps" @node-click="handleNodeClick" ref="treeRefImg" :highlight-current="true" filterable :key="treeKey" :filter-node-method="filterNode"> </el-tree> </div> </div> <div class="image_lazy_right body-tabel"> <div class="top-form" style="position: relative" @keyup.enter="getPicFun()"> <div class="select-box"> <label>专业</label> <el-select @change="taskMajorChange" filterable placeholder="专业" clearable v-model="params.taskMajor"> <el-option v-for="item in MajorList" :key="item.majorType" :label="item.majorTypeName" :value="item.majorType"></el-option> </el-select> </div> <div class="select-box"> <label>电压等级</label> <el-select @change="dydjListChange" filterable placeholder="电压等级" clearable v-model="params.dydj"> <el-option v-for="item in dydjList" :key="item.typeValue" :label="item.typeName" :value="item.typeValue"></el-option> </el-select> </div> <div class="select-box"> <label>工程名称</label> <el-select class="selectCss" clearable filterable @change="gcxxListChange" v-model="params.lineName" placeholder="工程名称"> <el-option v-for="item in gcxxList" :key="item.basicId" :label="item.basicName" :value="item.basicId"></el-option> </el-select> </div> <div class="select-box"> <label>杆塔/间隔名称</label> <!-- 新增@change="handleGtbhChange"杆塔和工程树联动 --> <el-select multiple collapse-tags class="selectCss selectCssList" clearable filterable v-model="gtbhList" placeholder="杆塔/间隔名称" @change="handleGtbhChange"> <el-option v-for="item in gcgtList" :key="item.keyId" :label="item.towerName" :value="item.keyId"></el-option> </el-select> </div> <div class="date-picker-box"> <label>上传间</label> <el-date-picker v-model="timeValue" type="daterange" value-format="yyyy-MM-dd" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker> </div> <div class="date-picker-box"> <label>处理间</label> <el-date-picker v-model="timeValue1" type="daterange" value-format="yyyy-MM-dd" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker> </div> <div class="select-box"> <label>是否有问题</label> <el-select class="selectCss" clearable filterable v-model="params.isMark" placeholder="是否有问题"> <el-option label="否" value="0"></el-option> <el-option label="是" value="1"></el-option> </el-select> </div> <div class="select-box"> <label>图片类型</label> <el-select class="selectCss" clearable filterable v-model="params.picType" placeholder="图片类型"> <el-option label="可见光巡检照片" value="1"></el-option> <el-option label="红外巡检照片" value="2"></el-option> </el-select> </div> <div class="select-box"> <label>数据来源</label> <el-select class="selectCss" clearable filterable v-model="params.uploadtype" placeholder="数据来源"> <el-option label="app上传" value="1"></el-option> <el-option label="离线上传" value="2"></el-option> </el-select> </div> <div class="select-box"> <label>是否归档</label> <el-select class="selectCss" clearable filterable v-model="params.isArc" placeholder="是否归档"> <el-option label="否" value="0"></el-option> <el-option label="是" value="1"></el-option> </el-select> </div> <div class="select-box"> <label>处理状态</label> <el-select class="selectCss" clearable filterable v-model="params.handleFlag" placeholder="处理状态"> <el-option label="已处理" value="1"></el-option> <el-option label="未处理" value="2"></el-option> </el-select> </div> <div class="input-box"> <label>处理人</label> <el-input v-model="params.handleUser" placeholder="处理人"></el-input> </div> <!-- <div class="select-box">--> <!-- <label>有无问题</label>--> <!-- <el-select--> <!-- class="selectCss"--> <!-- clearable--> <!-- filterable--> <!-- v-model="params.handleFlag"--> <!-- placeholder="有无问题"--> <!-- >--> <!-- <el-option label="有" value="1"></el-option>--> <!-- <el-option label="无" value="2"></el-option>--> <!-- </el-select>--> <!-- </div>--> <div class="button-box"> <el-button v-if="this.$menu.getMenuBus('查询')" v-on:click="getPicFun">查询</el-button> </div> <div class="button-box" style="position: absolute;right: 0px;bottom: -1px;"> <el-button v-if="this.$menu.getMenuBus('批量下载')" :loading="loading" v-on:click="downloadC()">批量下载</el-button> <el-button v-if="this.$menu.getMenuBus('导出')" v-on:click="exportDronePic()">导出</el-button> <el-button v-if="this.$menu.getMenuBus('数据统计')" v-on:click="getWorkCount()">数据统计</el-button> </div> </div> <div class="demo-image__lazy"> <div class="imgBox"> <div class="imgList" v-for="(item,index) in tableData"> <el-image v-on:click="viewimg(item,index)" :key="item.sourceUrl" :src="getImgUrl(item)"> </el-image> <!-- :preview-src-list="srcList"--> <!-- :initial-index="listIndex"--> <div class="typeNeme">{{ item.taskType }}</div> <div class="typeGD">{{ item.isArcName }}</div> <div class="isWenTi">{{ item.handleName }} 发现 {{ item.defectNum?item.defectNum:0 }} 个问题</div> <div class="imgText"> <li style="cursor: pointer;" v-on:click="modifyTest(item)"><span style="border-bottom: 1px solid #ffffff">{{ item.picName ? item.picName : "" }}</span></li> <!-- <li>--> <!-- <span>名称:</span--> <!-- >{{--> <!-- (item.lineName ? item.lineName : "") +--> <!-- "-" +--> <!-- (item.towerName ? item.towerName : "")--> <!-- }}--> <!-- </li>--> <li><span>采集间:</span>{{ parseTime(item.photoTime) }}</li> <li class="imgTextLi" v-on:click="modifyTest(item)">标注 >></li> </div> </div> </div> </div> <div class="pageBox"> 共 {{ total }} 条数据 <el-pagination background :current-page.sync="page.pageNum" layout="prev, pager, next, jumper, sizes" :total="total" @size-change="handleSizeChange" @current-change="handleCurrentChange"> </el-pagination> </div> </div> <manually-annotated ref="examineInitMap" @getPicFun="getPicFun" @pre="pre" @next="next" v-if="dialogUploadObj.isShow" :dialogUploadObj="dialogUploadObj" :AnnotatedRow="AnnotatedRow" :imageObj="imageObj"></manually-annotated> <view-img @closeImgBox="closeImgBox" v-if="view.isShow" :view="view"></view-img> <!-- 隐藏原本代码 --> <!-- <data-statistics v-if="dataStatisticsObj.isShow" :dataStatisticsObj="dataStatisticsObj"></data-statistics> --> <el-dialog title="数据统计" :visible.sync="dataStatisticsObj.isShow" :modal-append-to-body="false" :append-to-body="false" :close-on-click-modal="false" top="12vh" width="70%" class="dialogBox data-statistics-dialog" custom-class="data-statistics-dialog"> <!-- 新增:查询按钮 --> <div class="button-box"> <el-button v-on:click="getWorkCount">查询</el-button> </div> <!-- 新增:任务名称、工程名称、处理间三个筛选 --> <div class="top-form"> <div class="input-box"> <label>任务名称</label> <el-input placeholder="请输入任务名称" v-model="params.taskName" clearable></el-input> </div> <div class="select-box"> <label>工程名称</label> <el-select class="selectCss" clearable filterable v-model="params.lineName" placeholder="工程名称"> <el-option v-for="item in gcxxList" :key="item.basicId" :label="item.basicName" :value="item.basicId"></el-option> </el-select> </div> <div class="date-picker-box"> <label>处理间</label> <el-date-picker v-model="timeValue1" type="daterange" value-format="yyyy-MM-dd" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker> </div> </div> <div class="button-box" style="margin-bottom: 5px; height: 30px;"> <el-row :gutter="3"> <el-col v-for="(tag, index) in filterTags" :key="index" :span="1.5"> <el-tag color="#0C53CF" closable @close="removeFilterTag(index)"> {{ tag.label }}: {{ tag.value }} </el-tag> </el-col> </el-row> </div> <div class="body-tabel"> <div class="body-tabels"> <!-- 新增:auto-resize自动调整大小 --> <vxe-table :data="dataStatisticsObj.tableData" style="width: 100%; height: 100%" border ref="table" :filter-config="{ remote: true }" @filter-change="handleFilterChange" :custom-config="{ placement: 'top-left', storage: true }" :column-config="columnConfig, columnDragConfig" :toolbar-config="toolbarConfig" auto-resize > <vxe-column title="序号" type="seq" align="center" :width="80 * scale"></vxe-column> <vxe-column field="handleUser" align="center" title="标注人员" show-header-overflow show-overflow="title" show-footer-overflow :filters="[{ data: '' }]" sortable> <template #filter="{ column }"> <FuzzySearch ref="fuzzySearch" type="input" @reset="handleReset" @filter="(value) => handleColumnFilter(column, value)" label="标注人员" @changeTab="changeTab" /> </template> </vxe-column> <vxe-column field="towerNum" align="center" title="杆塔数量" show-header-overflow show-overflow="title" show-footer-overflow :filters="[{ data: '' }]" sortable> <template #filter="{ column }"> <FuzzySearch ref="fuzzySearch" type="input" @reset="handleReset" @filter="(value) => handleColumnFilter(column, value)" label="杆塔数量" @changeTab="changeTab" /> </template> </vxe-column> <vxe-column field="markNum" align="center" title="缺陷数据" show-header-overflow show-overflow="title" show-footer-overflow :filters="[{ data: '' }]" sortable> <template #filter="{ column }"> <FuzzySearch ref="fuzzySearch" type="input" @reset="handleReset" @filter="(value) => handleColumnFilter(column, value)" label="缺陷标注" @changeTab="changeTab" /> </template> </vxe-column> <vxe-column field="allNum" align="center" title="处理数据" show-header-overflow show-overflow="title" show-footer-overflow :filters="[{ data: '' }]" sortable> <template #filter="{ column }"> <FuzzySearch ref="fuzzySearch" type="input" @reset="handleReset" @filter="(value) => handleColumnFilter(column, value)" label="处理数据" @changeTab="changeTab" /> </template> </vxe-column> </vxe-table> <!-- 新增分页 --> <!-- 添加分页 --> <div class="pageBox"> 共 {{ dataStatisticsObj.total }} 条数据 <el-pagination background :page-sizes="[10, 20, 50, 100]" :page-size="dataStatisticsObj.page.pageSize" :total="dataStatisticsObj.total" :current-page="dataStatisticsObj.page.pageNum" layout="prev, pager, next, jumper, sizes" @current-change="handleCurrentChangeStats" @size-change="handleSizeChangeStats" > </el-pagination> </div> </div> </div> </el-dialog> </div> </template> <script> import { getProject, getProjectTower, } from "@/api/jobManagement/jobManagementUrl"; import { getCommonReadFile } from '@/api/common' // import dataStatistics from './dataStatistics' //隐藏 import { deletePic, downloadPic, exportDronePic, getPicFun, getSampleEngineerTree, getSampleTaskTree, getWorkCount } from '@/api/dataManageMent' import moment from "moment"; import { getMajorType, getSysDictionary } from "@/api/publicUrl"; import viewImg from "./viewImg"; import manuallyAnnotated from "./manuallyAnnotated"; import { requestParams, resetAddress } from '@/api/url' import { Loading } from 'element-ui' import FuzzySearch from "@/views/FuzzySearch.vue" export default { name: "annotationTable", components: { viewImg, manuallyAnnotated, // dataStatistics, //隐藏 FuzzySearch }, data() { return { view: { isShow: false, obj: {}, }, activeName: "task", treeKey: 0, loading: false, tree_data: [], listIndex: 0, srcList: [], defaultProps: { children: "child", label: "title", }, uro: require("../../../../../assets/images/operation/example.jpg"), gtbhList:[], params: { gtbh: "", //杆塔id companyId: "", //单位id lineName: "", //线路id dydj: "", //电压等级 taskMajor: "", //专业 startTime: "", //开始间 endTime: "", //结束间 handleStartTime:'', handleEndTime:'', isMark: "", //是否标注 isArc: "", //是否标注 picType: "", //图片类型 uploadtype: "", //数据来源 taskIds: "", //任务id projectIds: "", //工程id handleFlag: '2', // handleUser: '', // taskName: "", // 新增任务名称参数 }, AnnotatedRow: {}, timeValue: [], timeValue1: [], tableData: [], imageObj: {}, MajorList: [], dydjList: [], gcxxList: [],//左侧工程树与右侧工程名称下拉框联动(左侧树有选中节点下拉框显示选中的内容,如果没有选中的显示初始化查询的所有工程名称) gcxxListAll: [],//初始化查询的所有工程名称 gcgtList: [], page: { pageNum: 1, pageSize: 10, }, total: 0, upDialogObj: { isShow: false, title: "上传", width: "50%", top: "11vh", "modal-append-to-body": false, "close-on-click-modal": false, "append-to-body": false, }, dataStatisticsObj:{ isShow: false, tableData: [], // 新增:以下 total: 0, page: { pageNum: 1, pageSize: 10 }, }, dialogUploadObj: { isShow: false, title: "图像标注", width: "99%", // width: "96%", // top: "11vh", top: "1vh", "modal-append-to-body": false, "close-on-click-modal": false, "append-to-body": true, }, taskSearch:'',//任务搜索 engineeringSearch:'',//工程搜索 scale: document.documentElement.clientWidth / 1920, // 新增:从子组件移入 // 新增数据统计表格的筛选条件 columnFilters: { handleUser: '', towerNum: '', markNum: '', allNum: '' }, //新增:当前筛选条件 filters: {}, // 新增:字段设置的工具栏配置项 toolbarConfig: { custom: true, // 启用自定义列功能 customStorage: true, // 启用自定义列的本地存储 }, // 相关配置项 columnConfig: { drag: true, // 启用表头左右拖拽排序功能 resizable: true, // 启用拖拽列宽功能 }, columnDragConfig: { trigger: 'cell', showIcon: false, showGuidesStatus: true }, filterTags: [], // 新增:tag标签用于存储筛选条件的标签 }; }, watch: { taskSearch(val) { this.$refs.treeRefImg.filter(val); }, engineeringSearch(val) { this.$refs.treeRefImg.filter(val); }, // 新增: dataStatisticsObj: { handler(newVal) { // 从子组件移入的watch }, deep: true, immediate: true } }, mounted() { this.getPicFun(); this.getMajorType(); this.getSysDictionary(0); this.handleClick(); this.getProject() // 新增:连接vxe-toolbar和vxe-table const $table = this.$refs.table; const $toolbar = this.$refs.toolbarRef; if ($table && $toolbar) { $table.connect($toolbar); } }, methods: { filterNode(value, data) { if (!value) return true; if(!data.title) return true; return data.title.indexOf(value) !== -1; }, handleNodeClick(val){ var _this = this; _this.params.projectIds = ""; _this.params.taskIds = ""; _this.params.lineName = ""; var data = this.$refs.treeRefImg.getCheckedNodes(); var Index = data.findIndex((item) => { return item == val; }); if(Index== -1){ data.push(val) }else { data.splice(Index, 1) } if (_this.activeName == "task") { data.forEach((res) => { if(res.taskId){ _this.params.taskIds += res.taskId + ","; } }); } else { if(data.length > 0){ let arr = [] data.forEach((res) => { if(res.projectId){ if(res.projectId) _this.params.projectIds += res.projectId + ","; } arr.push({basicld:res.projectId,basicName:res.projectName}) }); this.gcxxList = arr }else{ _this.gcxxList = _this.gcxxListAll; } } _this.getPicFun(); this.$refs.treeRefImg.setCheckedNodes(data); }, // handleNodeClick(data){ // var _this = this; // _this.params.projectIds = ""; // _this.params.taskIds = ""; // if (_this.activeName == "task") { // _this.params.taskIds = data.taskId || ''; // } else { // _this.params.projectIds += data.projectId || ""; // } // _this.getPicFun(); // // }, // 隐藏原代码 // check(val, node) { // var _this = this; // _this.params.projectIds = ""; // _this.params.taskIds = ""; // if (_this.activeName == "task") { // node.checkedNodes.forEach((res) => { // _this.params.taskIds += res.taskId + ","; // }); // } else { // if(node.checkedNodes && node.checkedNodes.length > 0){ // let arr = [] // node.checkedNodes.forEach((res) => { // _this.params.projectIds += res.projectId + ","; // arr.push({basicld:res.projectId,basicName:res.projectName}) // }); // this.gcxxList = arr // this.params.lineName = '' // }else{ // this.gcxxList = this.gcxxListAll // this.params.lineName = '' // } // } // _this.getPicFun(); // }, // 修改以上代码 // 修改check方法,处理树节点选中的联动 check(val, node) {debugger var _this = this; _this.params.projectIds = ""; _this.params.taskIds = ""; _this.params.lineName = ""; // 清空工程名称选择 _this.gtbhList = []; // 清空杆塔选择 if (_this.activeName == "task") { node.checkedNodes.forEach((res) => { _this.params.taskIds += res.taskId + ","; }); } else { // 工程树逻辑 let projectIds = []; let projectNames = []; let arr = [] node.checkedNodes.forEach((res) => { if (res.projectId) { projectIds.push(res.projectId); projectNames.push(res.projectName); _this.params.projectIds += res.projectId + ","; } arr.push({basicld:res.projectId,basicName:res.projectName}) }); this.gcxxList = arr // 更新工程名称下拉框选项 if (projectIds.length > 0) { // 新增:如果选中了工程节点,则只显示选中的工程 // _this.gcxxList = projectIds.map((id, index) => ({ // basicId: id, // basicName: projectNames[index] // })); // 自动查询第一个选中工程的杆塔数据 if (projectIds[0]) { this.getProjectTower(projectIds[0]); } } else { // 新增:如果没有选中任何工程节点,则显示所有工程 _this.gcxxList = _this.gcxxListAll; } } _this.getPicFun(); }, getImgUrl(obj) { // url = requestParams.dronePic+url obj.fileType = obj.fileType ? obj.fileType : 0; var URL= obj.sourceThumbUrl?obj.sourceThumbUrl:obj.sourceUrl var url = requestParams.ImgPathOss + "/uavMap/data/readFile?filePath=" + URL + "&fileType=" + obj.fileType; // console.log(url.replaceAll('#','%23')) // // getCommonReadFile({fileType:obj.fileType,filePath:obj.urlPath,ossPath:obj.urlPath}).then(res=>{ // let url1 = window.URL.createObjectURL(res); // console.log(url1) // }) return resetAddress(url); // return url1.toString(); }, handleClick() { var _this = this; _this.engineeringSearch = '' _this.taskSearch = '' this.gcxxList = this.gcxxListAll if (_this.activeName == "task") { getSampleTaskTree().then((res) => { _this.tree_data = res.data; }); } else { getSampleEngineerTree().then((res) => { _this.tree_data = res.data; }); } _this.treeKey+=1 }, pre() { if (this.page.pageNum == 1) { } else { this.page.pageNum--; this.getPicFun(); } }, next(type) { if(type){ this.page.pageNum = 1; }else{ this.page.pageNum = this.page.pageNum += 1; } this.getPicFun(); }, closeImgBox() { this.view.isShow = false; }, viewimg(row,index) { // this.listIndex = index+1 var Index = this.tableData.findIndex((item) => { return item.keyId == row.keyId; }); this.view.listIndex = Index; this.view.obj = row; this.view.obj.urlPath = row.sourceUrl this.view.isShow = true; }, modifyTest(row) { this.AnnotatedRow = row; this.dialogUploadObj.isShow = true; }, taskMajorChange(val) { // this.MajorList.filter((item, index) => { // return item.majorType == val; // }); }, dydjListChange(val) { let arr = this.dydjList.filter((item, index) => { return item.typeValue == val; }); this.getProject(arr[0]); }, getProject(val) { var _this = this; getProject({ voltageName: val?val.typeName:'', majorType: _this.params.taskMajor?_this.params.taskMajor:'0', voltageLevel: val?val.typeValue:'', }).then((res) => { _this.gcxxListAll = res.data; _this.gcxxList = res.data; }); }, // 原代码隐藏 // gcxxListChange(val) { // this.getProjectTower(val); // // var list = this.gcxxList.filter(item => { // // return item.basicId == val // // }); // }, // 修改以上代码 修改工程名称变化处理方法 gcxxListChange(val) { if (val) { this.getProjectTower(val); } else { this.gcgtList = []; // 清空杆塔列表 this.gtbhList = []; // 清空杆塔选择 } this.getPicFun(); }, // 新增:杆塔选择变化处理方法 handleGtbhChange(val) { this.getPicFun(); }, // 隐藏原代码 // getProjectTower(val) { // var _this = this; // getProjectTower({ keyId: val, majorType: _this.params.taskMajor }).then( // (res) => { // _this.gcgtList = res.data; // } // ); // }, // 新增:修改以上代码:获取杆塔数据方法 getProjectTower(val) { var _this = this; getProjectTower({ keyId: val, majorType: _this.params.taskMajor }).then((res) => { _this.gcgtList = res.data; // 可优化:自动选中第一个杆塔(可选) // if (res.data.length > 0) { // _this.gtbhList = [res.data[0].keyId]; // } }).catch(() => { _this.gcgtList = []; }); }, downloadC(row) { let that = this; let str = "", type = ".zip"; let parmas = {}; that.params.startTime = that.timeValue ? that.timeValue[0] : ""; that.params.endTime = that.timeValue ? that.timeValue[1] : ""; that.params.handleStartTime = that.timeValue1 ? that.timeValue1[0] : ""; that.params.handleEndTime = that.timeValue1 ? that.timeValue1[1] : ""; that.params.gtbh = that.gtbhList.join(",") that.loading = true downloadPic({ ...that.params }).then((data) => { if (!data) { return; } let time = new Date(); let url = window.URL.createObjectURL(new Blob([data])); let link = window.document.createElement("a"); link.style.display = "none"; link.href = url; link.setAttribute("download", moment(time).format("YYYYMMDD") + type); document.body.appendChild(link); link.click(); //释放内存 window.URL.revokeObjectURL(link.href); that.loading = false }).catch(e=>{ that.loading = false }); return; if (row) { str += row.keyId + ","; str = str.slice(0, str.length - 1); parmas = { keyId: str, type: 1, }; type = ".zip"; that.params.startTime = that.timeValue ? that.timeValue[0] : ""; that.params.endTime = that.timeValue ? that.timeValue[1] : ""; that.params.handleStartTime = that.timeValue1 ? that.timeValue1[0] : ""; that.params.handleEndTime = that.timeValue1 ? that.timeValue1[1] : ""; downloadPic({ ...that.params }).then((data) => { if (!data) { return; } let time = new Date(); let url = window.URL.createObjectURL(new Blob([data])); let link = window.document.createElement("a"); link.style.display = "none"; link.href = url; link.setAttribute("download", moment(time).format("YYYYMMDD") + type); document.body.appendChild(link); link.click(); //释放内存 window.URL.revokeObjectURL(link.href); }); } }, deletePic(val) { var _this = this; deletePic({ keyId: val.keyId, fileUrl: val.sourceUrl }).then((res) => { if (res.code == 200) { _this.$message({ message: "删除成功", type: "success", }); } else { _this.$message({ message: "删除失败", type: "error", }); } _this.getPicFun(); }); }, getFile(row) { // debugger let url = process.env.VUE_APP_BASE_API + "/uavMap/data/readFile?filePath=" + row.filePath + "&fileType=" + row.fileType; window.open(resetAddress(url)); }, getSysDictionary(sum) { var _this = this; getSysDictionary({ parentId: sum }).then((res) => { if (sum == 0) { _this.dydjList = res.data; } }); }, getMajorType() { var _this = this; getMajorType({}).then((res) => { _this.MajorList = res.data; }); }, getPicFun() { let instance = Loading.service({ text: "正在查询数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", }); var _this = this; _this.params.startTime = _this.timeValue ? _this.timeValue[0] : ""; _this.params.endTime = _this.timeValue ? _this.timeValue[1] : ""; _this.params.handleStartTime = _this.timeValue1 ? _this.timeValue1[0] : ""; _this.params.handleEndTime = _this.timeValue1 ? _this.timeValue1[1] : ""; _this.params.gtbh = _this.gtbhList.join(",") $(".v-modal").remove(); getPicFun({ ..._this.page, ..._this.params }).then((res) => { _this.tableData = res.data.rows; _this.view.srcList = []; _this.tableData.forEach((item,index)=>{ var url = requestParams.ImgPathOss +"/uavMap/data/readFile?filePath="+item.sourceUrl+"&fileType="+item.fileType; _this.view.srcList.push(resetAddress(url)) }) // _this.tableData = _this.tableData.concat(res.data.rows); _this.total = res.data.total; _this.imageObj = res.data; _this.imageObj["pageNum"] = _this.page.pageNum; _this.srcList = [] // _this.tableData.forEach(obj=>{ // getCommonReadFile({fileType:obj.fileType,filePath:obj.sourceUrl,ossPath:obj.sourceUrl}).then(res=>{ // let url1 = window.URL.createObjectURL(res); // _this.srcList.push(url1) // console.log(_this.srcList) // }) // }) instance.close(); _this.$refs.examineInitMap.preCG(_this.tableData); }).catch(e=>{ instance.close(); }); }, // 新增分页选择器大小 handleSizeChange(val) { this.page.pageSize = val; //更新每页显示条数 this.getPicFun(); //重新获取数据 }, handleCurrentChange(val) { this.page.pageNum = val; this.getPicFun(); }, // 新增分页 handleCurrentChangeStats(val) { this.dataStatisticsObj.page.pageNum = val; this.getWorkCount(); }, // 数据统计表格的每页条数变化 handleSizeChangeStats(val) { this.dataStatisticsObj.page.pageSize = val; this.getWorkCount(); }, getWorkCount(){ var _this = this; // 设置处理间参数 // _this.params.handleStartTime = _this.timeValue1 ? _this.timeValue1[0] : ""; // _this.params.handleEndTime = _this.timeValue1 ? _this.timeValue1[1] : ""; // 合并表单查询条件和列筛选条件 let queryParams = { ...this.params, ...this.columnFilters, pageNum: this.dataStatisticsObj.page.pageNum, pageSize: this.dataStatisticsObj.page.pageSize, }; // 暂隐藏不可删除 _this.params.startTime = _this.timeValue ? _this.timeValue[0] : ""; _this.params.endTime = _this.timeValue ? _this.timeValue[1] : ""; _this.params.handleStartTime = _this.timeValue1 ? _this.timeValue1[0] : ""; _this.params.handleEndTime = _this.timeValue1 ? _this.timeValue1[1] : ""; _this.params.gtbh = _this.gtbhList.join(",") _this.dataStatisticsObj.isShow = true getWorkCount(queryParams).then(res =>{ _this.dataStatisticsObj.tableData = res.data.rows || res.data; // 根据后端返回结构调整, _this.dataStatisticsObj.total = res.data.total || res.data.length; // 根据后端返回结构调整; }) }, exportDronePic() { var _this = this; _this.params.startTime = _this.timeValue ? _this.timeValue[0] : ""; _this.params.endTime = _this.timeValue ? _this.timeValue[1] : ""; _this.params.handleStartTime = _this.timeValue1 ? _this.timeValue1[0] : ""; _this.params.handleEndTime = _this.timeValue1 ? _this.timeValue1[1] : ""; _this.params.gtbh = _this.gtbhList.join(",") exportDronePic({ ..._this.params }).then((data) => { let time = new Date(); let url = window.URL.createObjectURL(new Blob([data])); let link = window.document.createElement("a"); link.style.display = "none"; link.href = url; link.setAttribute( "download", "样本库列表" + this.parseTime(new Date(), "{y}{m}{d}{h}{i}{s}") + ".xlsx" ); document.body.appendChild(link); link.click(); //释放内存 window.URL.revokeObjectURL(link.href); }); }, // 数据统计表格的列筛选 handleColumnFilter(column, value) { // 清除每个重复展示的筛选条件 this.filterTags = this.filterTags.filter(tag => tag.prop !== column.property); // 映射列字段到查询字段 const fieldMap = { handleUser: 'handleUser', towerNum: 'towerNum', markNum: 'markNum', allNum: 'allNum' }; if (value || value == 0) { let displayValue = value; // 将筛选条件添加到 filterTags的el-tag标签中 this.filterTags.push({ label: column.title, value: Array.isArray(displayValue) ? displayValue.join(', ') : displayValue, prop: column.property, }); // 更新对应的查询字段 const queryField = fieldMap[column.property] || column.property; this.columnFilters[column.property] = value; this.params[queryField] = value; } else { // 清除筛选条件 const queryField = fieldMap[column.property] || column.property; delete this.columnFilters[column.property]; } this.handleFilterChange({ filters: this.filters }); }, // 移除数据统计表格的筛选标签 removeFilterTag(index) { const removedTag = this.filterTags.splice(index, 1)[0]; // 映射列字段到查询字段 const fieldMap = { companyName: 'companyName', taskName: 'taskName', workDescribe: 'workDescribe', implementTypeName: 'implementType', taskTypeName: 'taskType', planStateName: 'planState', createUser: 'createUser' }; // 清除对应的查询条件 const queryField = fieldMap[removedTag.prop] || removedTag.prop; delete this.params[queryField]; delete this.columnFilters[removedTag.prop]; this.getWorkCount(); }, // 筛选变化事件 handleFilterChange({ column }) {}, // 重置筛选条件 handleReset() { this.filters = {}; this.getWorkCount(); }, changeTab() { this.$nextTick(() => { this.$refs.table.closeFilter(); this.$refs.table.clearFilter(); }); } }, }; </script> <style lang="scss" scoped> .pageBox { display: flex; justify-content: flex-end; align-items: center; color: rgba($color: #fff, $alpha: 0.6); margin-top: 16px; letter-spacing: 1px; ::v-deep .el-pagination { .el-pager li, .btn-prev, .btn-next { width: 34px; height: 34px; color: #fff; font-size: 16px; background: rgba($color: #0045c0, $alpha: 0.2); border: 1px solid rgba($color: #005cff, $alpha: 0.9); line-height: 34px; padding: 0; } .el-pager li.active { background: #005cff; } .el-pagination__jump { color: rgba($color: #fff, $alpha: 0.6); margin-left: 20px; .el-pagination__editor { margin: 0 5px; .el-input__inner { background: rgba($color: #0045c0, $alpha: 0.4); height: 34px; color: #fff; border: 0; } } } .el-pagination__sizes { color: #ffffff !important; .el-input__inner { height: 34px; font-size: 16px; background: rgba($color: #0045c0, $alpha: 0.2); border: 1px solid rgba($color: #005cff, $alpha: 0.9); color: #ffffff !important; } } } } // 新增:引入定义好的样式文件 @import "@/assets/styles/vxeClass.scss"; .body { width: calc(100% - 60px); height: calc(100% - 190px); position: fixed; left: 20px; top: 150px; display: flex; //flex-direction: column; flex-direction: initial; .annotation_Table { width: 20%; height: 100%; //background: #f0f8ff21; .contentBox { width: 100%; flex: 1; //margin-top: 20px; margin-bottom: 20px; ::v-deep .el-tabs { .el-tabs__header { margin: 0; } .el-tabs__nav { width: 100%; display: flex; .el-tabs__item { flex: 1; height: 32px; padding: 0; display: flex; justify-content: center; align-items: center; font-size: 14px; color: #fff; letter-spacing: 1px; background: rgba($color: #000c23, $alpha: 0.3); } .is-active { background: rgba($color: #469bff, $alpha: 0.4); } } .el-tabs__nav-wrap::after { height: 4px; background: rgba($color: #469bff, $alpha: 0.4); } .el-tabs__active-bar { height: 4px; background: #469bff; } ::v-deep .el-tabs__active-bar { width: 200px !important; transform: translateX(0); } } } ::v-deep .el-tree { background: transparent; color: #fff; overflow: auto; height: 586px; //原本675px flex: 1; .el-icon-caret-right:before { //display: none; } >.el-tree-node { min-width: 100%; display: inline-block; } //.el-tree-node__expand-icon { // width: 14px; // height: 14px; // background: url("../../../../../../assets/images/operation/add.png") no-repeat; // background-size: 100% 100%; // // margin-left: -25px; //} .custom-tree-node { margin-left: 14px; } //.el-tree-node__expand-icon.expanded { // transform: rotateY(0); // background: url("../../../../../../assets/images/operation/reduce.png") // no-repeat; // background-size: 100% 100%; //} .el-tree-node__expand-icon.is-leaf { //display: none; } .el-tree-node__content { // margin-left: 42px; } .el-tree-node__content:hover { background: rgba($color: #469bff, $alpha: 0.3); } .el-tree-node:focus>.el-tree-node__content { background: rgba($color: #469bff, $alpha: 0.8); } } ::v-deep .el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content { background: rgba($color: #469bff, $alpha: 0.8); } } .image_lazy_right { width: 80%; height: 100%; //background: rgba(0, 137, 255, 0.13); .date-picker-box { width: 360px; } .select-box { width: 360px; } .input-box { width: 360px; } .demo-image__lazy { display: flex; height: 65%; overflow-y: auto; } .imgBox { display: flex; flex-wrap: wrap; .imgList { position: relative; width: 275px; margin: 0px 10px 0px 10px; overflow: hidden; .el-image { width: 100%; height: 165px; } } .typeNeme { position: absolute; top: 0px; background: #ffb802c7; padding: 2px 25px 2px 10px; border-bottom-right-radius: 19px; color: white; font-size: 13px; } .isWenTi { position: absolute; top: 145px; background: #000000a6; padding: 2px 15px 2px 10px; /* border-bottom-right-radius: 19px; */ color: white; font-size: 13px; } .typeGD { position: absolute; top: 12px; right: -27px; background: #00a3ff; padding: 2px 32px; -webkit-transform: rotate(45deg); transform: rotate(45deg); color: #ffffff; font-size: 13px; } .imgText { color: #ffffff; position: relative; margin-bottom: 10px; font-size: 12px; .imgTextLi { position: absolute; right: 10px; bottom: 0px; color: #00a3ff; cursor: pointer; } } } } .btn { width: 80px; height: 28px; cursor: pointer; display: flex; align-items: center; justify-content: center; } .audit { color: #07ffe1; background: rgba(0, 92, 255, 0.08); border-radius: 2px 2px 2px 2px; border: 1px solid; border-image: linear-gradient(180deg, rgba(7, 255, 225, 0.8), rgba(7, 255, 225, 0.24)) 1 1; margin-right: 8px; img { width: 14px; height: 14px; margin-right: 4px; } } .delete { color: #ff4e02; background: rgba(0, 92, 255, 0.08); border-radius: 2px 2px 2px 2px; border: 1px solid; border-image: linear-gradient(180deg, rgba(255, 78, 2, 0.8), rgba(255, 78, 2, 0.24)) 1 1; img { width: 14px; height: 14px; margin-right: 4px; } } .examine { color: #469bff; background: rgba(0, 92, 255, 0.08); border-radius: 2px 2px 2px 2px; border: 1px solid; border-image: linear-gradient(180deg, rgba(0, 92, 255, 0.8), rgba(0, 92, 255, 0.24)) 1 1; margin-right: 8px; img { width: 14px; height: 14px; margin-right: 4px; } } .downloadC { color: #e6a23c; background: rgba(0, 92, 255, 0.08); border-radius: 2px 2px 2px 2px; border: 1px solid; border-image: linear-gradient(180deg, rgba(236, 162, 60, 0.8), rgba(236, 162, 60, 0.24)) 1 1; margin-right: 8px; img { width: 14px; height: 14px; margin-right: 4px; } } // 新增:从子组件移入的样式 //修改后的样式 .data-statistics-dialog { ::v-deep .el-dialog { height: 70vh !important; // 使用视口高度单位 display: flex; flex-direction: column; .el-dialog__body { flex: 1; padding: 20px; overflow: hidden; display: flex; flex-direction: column; } } .body-tabel { flex: 1; display: flex; flex-direction: column; overflow: hidden; .body-tabels { flex: 1; overflow: hidden; overflow-y: auto; display: flex; flex-direction: column; .vxe-table { flex: 1; display: flex; flex-direction: column; overflow: hidden; overflow-y: auto; .vxe-table--body-wrapper { flex: 1; overflow: auto; } } } } } } </style>
最新发布
09-09
帮我解释这段代码的每一行功能,尽可能详细,每行代码实现了什么作用,用了什么语法,就在我原有代码上注释,不要举例或省略:<template> <div class="body"> <div class="annotation_Table"> <div class="contentBox"> <el-tabs v-model="activeName" @tab-click="handleClick"> <el-tab-pane label="任务" name="task"></el-tab-pane> <el-tab-pane label="工程" name="engineering"></el-tab-pane> </el-tabs> </div> <div> <div class="treeSelect" v-if="activeName == 'task'"> <el-input size="small" placeholder="请输入内容" suffix-icon="el-icon-search" v-model="taskSearch"> </el-input> </div> <div class="treeSelect" v-else> <el-input size="small" placeholder="请输入内容" suffix-icon="el-icon-search" v-model="engineeringSearch"> </el-input> </div> <!-- 修改:树节点:default-expand-all="true"展开改为false闭合 --> <el-tree class="treeLine" :data="tree_data" show-checkbox :node-key="activeName == 'engineering'?'projectId':'taskId'" @check="check" :default-expand-all="false" :props="defaultProps" @node-click="handleNodeClick" ref="treeRefImg" :highlight-current="true" filterable :key="treeKey" :filter-node-method="filterNode"> </el-tree> </div> </div> <div class="image_lazy_right body-tabel"> <!-- 以下是form表单区域 --> <div class="top-form" style="position: relative" @keyup.enter="getPicFun()"> <div class="select-box"> <label>专业</label> <el-select @change="taskMajorChange" filterable placeholder="专业" clearable v-model="params.taskMajor"> <el-option v-for="item in MajorList" :key="item.majorType" :label="item.majorTypeName" :value="item.majorType"></el-option> </el-select> </div> <div class="select-box"> <label>电压等级</label> <el-select @change="dydjListChange" filterable placeholder="电压等级" clearable v-model="params.dydj"> <el-option v-for="item in dydjList" :key="item.typeValue" :label="item.typeName" :value="item.typeValue"></el-option> </el-select> </div> <div class="select-box"> <label>工程名称</label> <!-- 原本 lineName改为 lineId --> <el-select class="selectCss" clearable filterable @change="gcxxListChange" v-model="params.lineId" placeholder="工程名称"> <el-option v-for="item in gcxxList" :key="item.basicId" :label="item.basicName" :value="item.basicId"></el-option> </el-select> </div> <div class="select-box"> <label>杆塔/间隔名称</label> <el-select multiple collapse-tags class="selectCss selectCssList" clearable filterable v-model="gtbhList" placeholder="杆塔/间隔名称" @change="handleGtbhChange"> <el-option v-for="item in gcgtList" :key="item.keyId" :label="item.towerName" :value="item.keyId"></el-option> </el-select> </div> <div class="date-picker-box"> <label>上传间</label> <!-- 原本 timeValue 换成 startTime --> <el-date-picker v-model="startTime" type="daterange" value-format="yyyy-MM-dd" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker> </div> <div class="date-picker-box"> <label>处理间</label> <!-- 原本 timeValue1 换成 dealStartTime --> <el-date-picker v-model="dealStartTime" type="daterange" value-format="yyyy-MM-dd" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"> </el-date-picker> </div> <!--隐藏 --> <!-- <div class="select-box"> <label>是否有问题</label> <el-select class="selectCss" clearable filterable v-model="params.isMark" placeholder="是否有问题"> <el-option label="否" value="0"></el-option> <el-option label="是" value="1"></el-option> </el-select> </div> --> <div class="select-box"> <label>图片类型</label> <el-select class="selectCss" clearable filterable v-model="params.picType" placeholder="图片类型"> <el-option label="可见光巡检照片" value="1"></el-option> <el-option label="红外巡检照片" value="2"></el-option> </el-select> </div> <!--隐藏 --> <!-- <div class="select-box"> <label>数据来源</label> <el-select class="selectCss" clearable filterable v-model="params.uploadtype" placeholder="数据来源"> <el-option label="app上传" value="1"></el-option> <el-option label="离线上传" value="2"></el-option> </el-select> </div> <div class="select-box"> <label>是否归档</label> <el-select class="selectCss" clearable filterable v-model="params.isArc" placeholder="是否归档"> <el-option label="否" value="0"></el-option> <el-option label="是" value="1"></el-option> </el-select> </div> --> <div class="input-box"> <label>确认人</label> <el-input v-model="params.confirmUserName" placeholder="处理人"></el-input> </div> <!-- <div class="select-box"> <label>处理状态</label> <el-select class="selectCss" clearable filterable v-model="params.status" placeholder="处理状态"> <el-option label="未处理" value="0"></el-option> <el-option label="已归档" value="1"></el-option> <el-option label="未消缺" value="2"></el-option> </el-select> </div> --> <div class="input-box"> <label>处理人</label> <!-- 原本 handleUser 换成 reportUserName --> <el-input v-model="params.reportUserName" placeholder="处理人"></el-input> </div> <div class="button-box"> <el-button v-if="this.$menu.getMenuBus('查询')" v-on:click="getPicFun">查询</el-button> </div> <div class="button-box" style="position: absolute;right: 0px;bottom: -1px;"> <!-- 新增:批量确认和批量上报 --> <!-- <el-button v-on:click="batchConfirmation"> </el-button> <el-button v-on:click="batchReporting">批量上报</el-button> --> <el-button v-if="this.$menu.getMenuBus('批量下载')" :loading="loading" v-on:click="downloadC()">批量下载</el-button> <el-button v-if="this.$menu.getMenuBus('导出')" v-on:click="exportDronePic()">导出</el-button> <!-- 新增:样式切换模块 --> <el-tooltip class="item" effect="dark" content="列表模式" placement="top-start"> <img class="liebiao" @click="tableType = 'table'" src="../../../../../assets/images/operation/列表模式2.png" alt="" /> </el-tooltip> <el-tooltip class="item" effect="dark" content="宫格模式" placement="top-start"> <img class="gongge" @click="tableType = 'imgTable'" src="../../../../../assets/images/operation/6宫格.png" alt="" /> </el-tooltip> </div> </div> <!-- 宫格模式 --> <div class="demo-image__lazy"> <div class="imgBox" v-if="tableType == 'imgTable'"> <div class="imgList" v-for="(item,index) in tableData"> <el-image v-on:click="viewimg(item,index)" :key="item.sourceUrl" :src="getImgUrl(item)"> </el-image> <div class="typeNeme">{{ item.flightType }}</div> <div class="typeGD">{{ item.statusName }}</div> <div class="isWenTi">{{ item.handleName }} 发现 1 个问题</div> <div class="imgText"> <li style="cursor: pointer;" v-on:click="modifyTest(item)"><span style="border-bottom: 1px solid #ffffff">{{ item.picName ? item.picName : "" }}</span></li> <!-- 隐藏不删除 --> <!-- <li> <span>名称:</span >{{ (item.lineName ? item.lineName : "") + "-" + (item.towerName ? item.towerName : "") }} </li> --> <li><span>采集间:</span>{{ parseTime(item.gatherTime) }}</li> <li class="imgTextLi" v-on:click="modifyTest(item)">消缺 >></li> </div> </div> </div> <!-- 表格模式 --> <div v-else class="body-tabel" style="overflow: hidden"> <!-- 新增:@selection-change="handleSelectionChange" --> <el-table :data="tableData" style="width: 100%" height="90%" border @selection-change="handleSelectionChange" > <!-- 新增 --> <el-table-column type="selection" width="55" align="center"></el-table-column> <el-table-column label="序号" type="index" align="center" :width="80*scale"> </el-table-column> <el-table-column prop="voltageName" align="center" label="电压等级"> </el-table-column> <el-table-column prop="lineName" align="center" label="工程名称"> </el-table-column> <el-table-column prop="towerName" align="center" label="杆塔名称"> </el-table-column> <el-table-column prop="partName" align="center" label="缺陷部位"> </el-table-column> <el-table-column prop="defectName" align="center" label="缺陷类型"> </el-table-column> <el-table-column prop="defectLeve" align="center" label="缺陷等级"> </el-table-column> <el-table-column prop="reportUserName" align="center" label="上报人"> </el-table-column> <el-table-column prop="createTime" align="center" label="上报间"> <template slot-scope="scope"> <span>{{ parseTime(scope.row.insertTime) }}</span> </template> </el-table-column> <el-table-column prop="createUserName" align="center" label="上传人"> </el-table-column> <el-table-column prop="updateDate" align="center" label="更改间"> <template slot-scope="scope"> <span>{{ parseTime(scope.row.updateDate) }}</span> </template> </el-table-column> <!--隐藏 --> <!-- <el-table-column prop="updateUserName" align="center" label="更改人"> </el-table-column> --> <el-table-column label="操作" align="center" :width="140*scale"> <template slot-scope="scope"> <div class="btn1 audit" v-on:click="modifyTest(scope.row)"> 消缺 </div> </template> </el-table-column> </el-table> </div> </div> <div class="pageBox"> 共 {{ total }} 条数据 <el-pagination background :current-page.sync="page.pageNum" layout="prev, pager, next, jumper, sizes" :total="total" @size-change="handleSizeChange" @current-change="handleCurrentChange"> </el-pagination> </div> </div> <!-- 相关组件 --> <defectDetailing ref="examineInitMap" @getPicFun="getPicFun" @pre="pre" @next="next" v-if="dialogUploadObj.isShow" :dialogUploadObj="dialogUploadObj" :AnnotatedRow="AnnotatedRow" :imageObj="imageObj" :parentData="currentRowData" > </defectDetailing> <viewImging @closeImgBox="closeImgBox" v-if="view.isShow" :view="view"></viewImging> </div> </template> <script> import { getProject, getProjectTower, } from "@/api/jobManagement/jobManagementUrl"; import { deletePic, // downloadPic, //原本获取下载图片接口 // exportDronePic, //原本导出 // getPicFun, //原本获取表格和图片数据 getSampleEngineerTree, getSampleTaskTree, } from '@/api/dataManageMent' import moment from "moment"; import { getMajorType, getSysDictionary } from "@/api/publicUrl"; import viewImging from "./details/viewImging.vue"; import defectDetailing from "./details/defectDetailing.vue"; import { requestParams, resetAddress } from '@/api/url' import { Loading } from 'element-ui' import { getDefectSolve, //获取表格和图片列表等数据 updateDefectSolve, //批量确认和上报 downloadSolvePic, //批量下载 exportSolveDefect, //导出 } from '@/api/dataManageMent/elimination'; //新增:相关接口 export default { name: "annotationTable", components: { viewImging, defectDetailing }, data() { return { view: { isShow: false, obj: {}, }, tableType: "imgTable", //切换样式展示 activeName: "task", checkeds:[], treeKey: 0, loading: false, tree_data: [], listIndex: 0, srcList: [], defaultProps: { children: "child", label: "title", }, uro: require("../../../../../assets/images/operation/example.jpg"), gtbhList:[], params: { gtbh: "", //杆塔id companyId: "", //单位id lineId: "", //线路id 原本 lineName改为 lineId dydj: "", //电压等级 taskMajor: "", //专业 startTime: "", //开始间 endTime: "", //结束间 handleStartTime:'', handleEndTime:'', isMark: "", //是否标注 isArc: "", //是否标注 picType: "", //图片类型 uploadtype: "", //数据来源 taskIds: "", //任务id projectIds: "", //工程id status: '2', // 原本是handleFlag: '2'换成 status reportUserName: '', // 处理人 修改:handleUser 换成 reportUserName taskName: "", // 新增任务名称参数 confirmUserName: "", //新增:确认人传参查询 }, AnnotatedRow: {}, startTime: [], //原本 timeValue 换成 startTime dealStartTime: [], //原本 timeValue1 换成 dealStartTime tableData: [], imageObj: {}, MajorList: [], dydjList: [], gcxxList: [],//左侧工程树与右侧工程名称下拉框联动(左侧树有选中节点下拉框显示选中的内容,如果没有选中的显示初始化查询的所有工程名称) gcxxListAll: [],//初始化查询的所有工程名称 gcgtList: [], page: { pageNum: 1, pageSize: 10, }, total: 0, upDialogObj: { isShow: false, title: "上传", width: "50%", top: "11vh", "modal-append-to-body": false, "close-on-click-modal": false, "append-to-body": false, }, dataStatisticsObj:{ isShow: false, tableData: [], // 新增:以下 total: 0, page: { pageNum: 1, pageSize: 10 }, }, dialogUploadObj: { isShow: false, title: "图像标注", width: "99%", // width: "96%", // top: "11vh", top: "1vh", "modal-append-to-body": false, "close-on-click-modal": false, "append-to-body": true, }, taskSearch:'',//任务搜索 engineeringSearch:'',//工程搜索 scale: document.documentElement.clientWidth / 1920, // 新增:从子组件移入 multipleSelection: [], // 新增:表格存储选中的行 currentRowData: {} // 新增:用于存储当前行的完整数据 }; }, watch: { taskSearch(val) { this.$refs.treeRefImg.filter(val); }, engineeringSearch(val) { this.$refs.treeRefImg.filter(val); }, // 新增: dataStatisticsObj: { handler(newVal) { // 从子组件移入的watch }, deep: true, immediate: true } }, mounted() { this.getPicFun(); this.getMajorType(); this.getSysDictionary(0); this.handleClick(); this.getProject() }, methods: { filterNode(value, data) { if (!value) return true; if(!data.title) return true; return data.title.indexOf(value) !== -1; }, handleNodeClick(val){ var _this = this; _this.params.projectIds = ""; _this.params.taskIds = ""; _this.params.lineId = ""; // 原本 lineName改为 lineId var data = this.$refs.treeRefImg.getCheckedNodes(); var Index = data.findIndex((item) => { return item == val; }); if(Index== -1){ data.push(val) }else { data.splice(Index, 1) } if (_this.activeName == "task") { data.forEach((res) => { if(res.taskId){ _this.params.taskIds += res.taskId + ","; } }); } else { if(data.length > 0){ let arr = [] data.forEach((res) => { if(res.projectId){ if(res.projectId) _this.params.projectIds += res.projectId + ","; } arr.push({basicld:res.projectId,basicName:res.projectName}) }); this.gcxxList = arr }else{ _this.gcxxList = _this.gcxxListAll; } } _this.getPicFun(); this.$refs.treeRefImg.setCheckedNodes(data); }, // 修改以上代码 // 修改check方法,处理树节点选中的联动 check(val, node) { // debugger var _this = this; _this.params.projectIds = ""; _this.params.taskIds = ""; _this.params.lineId = ""; // 清空工程名称选择 原本 lineName改为 lineId _this.gtbhList = []; // 清空杆塔选择 if (_this.activeName == "task") { node.checkedNodes.forEach((res) => { _this.params.taskIds += res.taskId + ","; }); } else { // 工程树逻辑 let projectIds = []; let projectNames = []; let arr = [] node.checkedNodes.forEach((res) => { if (res.projectId) { projectIds.push(res.projectId); projectNames.push(res.projectName); _this.params.projectIds += res.projectId + ","; } arr.push({basicld:res.projectId,basicName:res.projectName}) }); this.gcxxList = arr // 更新工程名称下拉框选项 if (projectIds.length > 0) { // 新增:如果选中了工程节点,则只显示选中的工程 // _this.gcxxList = projectIds.map((id, index) => ({ // basicId: id, // basicName: projectNames[index] // })); // 自动查询第一个选中工程的杆塔数据 if (projectIds[0]) { this.getProjectTower(projectIds[0]); } } else { // 新增:如果没有选中任何工程节点,则显示所有工程 _this.gcxxList = _this.gcxxListAll; } } _this.getPicFun(); }, getImgUrl(obj) { // url = requestParams.dronePic+url obj.fileType = obj.fileType ? obj.fileType : 0; var URL= obj.defectPath?obj.defectPath:'' var url = requestParams.ImgPathOss + "/uavMap/data/readFile?filePath=" + URL + "&fileType=" + obj.fileType; return resetAddress(url); }, handleClick() { var _this = this; _this.engineeringSearch = '' _this.taskSearch = '' this.gcxxList = this.gcxxListAll if (_this.activeName == "task") { getSampleTaskTree().then((res) => { _this.tree_data = res.data; }); } else { getSampleEngineerTree().then((res) => { _this.tree_data = res.data; }); } _this.treeKey+=1 }, pre() { if (this.page.pageNum == 1) { } else { this.page.pageNum--; this.getPicFun(); } }, next(type) { if(type){ this.page.pageNum = 1; }else{ this.page.pageNum = this.page.pageNum += 1; } this.getPicFun(); }, closeImgBox() { this.view.isShow = false; }, viewimg(row,index) { // this.listIndex = index+1 var Index = this.tableData.findIndex((item) => { return item.keyId == row.keyId; }); this.view.listIndex = Index; this.view.obj = row; this.view.obj.urlPath = row.defectPath this.view.isShow = true; }, modifyTest(row) { this.AnnotatedRow = row; this.currentRowData = row; // 新增:保存当前行的完整数据,在子组件展示 this.dialogUploadObj.isShow = true; }, taskMajorChange(val) { // this.MajorList.filter((item, index) => { // return item.majorType == val; // }); }, dydjListChange(val) { let arr = this.dydjList.filter((item, index) => { return item.typeValue == val; }); this.getProject(arr[0]); }, getProject(val) { var _this = this; getProject({ voltageName: val?val.typeName:'', majorType: _this.params.taskMajor?_this.params.taskMajor:'0', voltageLevel: val?val.typeValue:'', }).then((res) => { _this.gcxxListAll = res.data; _this.gcxxList = res.data; }); }, // 修改以上代码 修改工程名称变化处理方法 gcxxListChange(val) { if (val) { this.getProjectTower(val); } else { this.gcgtList = []; // 清空杆塔列表 this.gtbhList = []; // 清空杆塔选择 } this.getPicFun(); }, // 新增:杆塔选择变化处理方法 handleGtbhChange(val) { this.getPicFun(); }, // 新增:修改以上代码:获取杆塔数据方法 getProjectTower(val) { var _this = this; getProjectTower({ keyId: val, majorType: _this.params.taskMajor }).then((res) => { _this.gcgtList = res.data; // 可优化:自动选中第一个杆塔(可选) // if (res.data.length > 0) { // _this.gtbhList = [res.data[0].keyId]; // } }).catch(() => { _this.gcgtList = []; }); }, downloadC() { // (row) let that = this; // let str = "", // type = ".zip"; // let parmas = {}; that.params.startTime = that.startTime ? that.startTime[0] : ""; //原本 timeValue 换成 startTime that.params.endTime = that.startTime ? that.startTime[1] : ""; //原本 timeValue 换成 startTime that.params.handleStartTime = that.dealStartTime ? that.dealStartTime[0] : ""; //原本 timeValue1 换成 dealStartTime that.params.handleEndTime = that.dealStartTime ? that.dealStartTime[1] : ""; //原本 timeValue1 换成 dealStartTime that.params.gtbh = that.gtbhList.join(","); // 新增:如果有选中的行,则只下载选中的行 if (that.multipleSelection.length > 0) { const taskIds = [...new Set(that.multipleSelection.map(item => item.taskId))].join(","); const projectIds = [...new Set(that.multipleSelection.map(item => item.projectId))].join(","); const gtbh = [...new Set(that.multipleSelection.map(item => item.gtbh))].join(","); that.params = { ...that.params, taskIds, projectIds, gtbh }; }; that.loading = true; // 原本 downloadPic 换成 downloadSolvePic downloadSolvePic(that.params).then((data) => { if (!data) { that.loading = false; //新增 return; } // let time = new Date(); //暂隐藏 let url = window.URL.createObjectURL(new Blob([data])); let link = window.document.createElement("a"); // link.style.display = "none"; //暂隐藏 link.href = url; link.setAttribute("download", `消缺样本_${moment().format("YYYYMMDD")}.zip`); document.body.appendChild(link); link.click(); //释放内存 document.body.removeChild(link); window.URL.revokeObjectURL(link.href); that.loading = false }).catch(e=>{ that.loading = false; console.error("下载失败:", error); }); }, deletePic(val) { var _this = this; deletePic({ keyId: val.keyId, fileUrl: val.sourceUrl }).then((res) => { if (res.code == 200) { _this.$message({ message: "删除成功", type: "success", }); } else { _this.$message({ message: "删除失败", type: "error", }); } _this.getPicFun(); }); }, getFile(row) { // debugger let url = process.env.VUE_APP_BASE_API + "/uavMap/data/readFile?filePath=" + row.filePath + "&fileType=" + row.fileType; window.open(resetAddress(url)); }, getSysDictionary(sum) { var _this = this; getSysDictionary({ parentId: sum }).then((res) => { if (sum == 0) { _this.dydjList = res.data; } }); }, getMajorType() { var _this = this; getMajorType({}).then((res) => { _this.MajorList = res.data; }); }, // 获取列表和图片模式的数据 getPicFun() { let instance = Loading.service({ text: "正在查询数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", }); var _this = this; _this.params.startTime = _this.startTime ? _this.startTime[0] : ""; //原本 timeValue 换成 startTime _this.params.endTime = _this.startTime ? _this.startTime[1] : ""; //原本 timeValue 换成 startTime _this.params.handleStartTime = _this.dealStartTime ? _this.dealStartTime[0] : ""; //原本 timeValue1 换成 dealStartTime _this.params.handleEndTime = _this.dealStartTime ? _this.dealStartTime[1] : ""; //原本 timeValue1 换成 dealStartTime _this.params.gtbh = _this.gtbhList.join(",") $(".v-modal").remove(); // 原本 getPicFun 换成 getDefectSolve getDefectSolve({ ..._this.page, ..._this.params }).then((res) => { _this.tableData = res.data.rows; _this.view.srcList = []; _this.tableData.forEach((item,index)=>{ var url = requestParams.ImgPathOss +"/uavMap/data/readFile?filePath="+item.defectPath+"&fileType="+item.fileType; _this.view.srcList.push(resetAddress(url)) }) _this.total = res.data.total; _this.imageObj = res.data; _this.imageObj["pageNum"] = _this.page.pageNum; _this.srcList = [] instance.close(); _this.$refs.examineInitMap.preCG(_this.tableData); }).catch(e=>{ instance.close(); }); }, // 新增分页选择器大小 handleSizeChange(val) { this.page.pageSize = val; //更新每页显示条数 this.getPicFun(); //重新获取数据 }, handleCurrentChange(val) { this.page.pageNum = val; this.getPicFun(); }, // 导出 exportDronePic() { var _this = this; _this.params.startTime = _this.startTime ? _this.startTime[0] : ""; //原本 timeValue 换成 startTime _this.params.endTime = _this.startTime ? _this.startTime[1] : ""; //原本 timeValue 换成 startTime _this.params.handleStartTime = _this.dealStartTime ? _this.dealStartTime[0] : ""; //原本 timeValue1 换成 dealStartTime _this.params.handleEndTime = _this.dealStartTime ? _this.dealStartTime[1] : ""; //原本 timeValue1 换成 dealStartTime _this.params.gtbh = _this.gtbhList.join(","); // 新增以下 // 如果有选中的行,则只导出选中的行 if (_this.multipleSelection.length > 0) { const taskIds = [...new Set(_this.multipleSelection.map(item => item.taskId))].join(","); const projectIds = [...new Set(_this.multipleSelection.map(item => item.projectId))].join(","); const gtbh = [...new Set(_this.multipleSelection.map(item => item.gtbh))].join(","); _this.params = { ..._this.params, taskIds, projectIds, gtbh }; } // 显示加载中 const loadingInstance = Loading.service({ text: '正在生成导出文件,请稍候...', spinner: 'el-icon-loading', background: 'rgba(0, 0, 0, 0.7)' }); // 原本 exportDronePic 换成 exportSolveDefect exportSolveDefect(_this.params) .then((data) => { if (!data) { loadingInstance.close(); _this.$message.warning('没有可导出的数据'); return; } // 创建下载链接 const url = window.URL.createObjectURL(new Blob([data])); const link = document.createElement('a'); link.href = url; // 设置下载文件名 const fileName = `消缺样本_${moment().format('YYYYMMDD_HHmmss')}.xlsx`; link.setAttribute('download', fileName); // 触发下载 document.body.appendChild(link); link.click(); // 清理资源 document.body.removeChild(link); window.URL.revokeObjectURL(url); _this.$message.success('导出成功'); }) .catch((error) => { console.error('导出失败:', error); _this.$message.error('导出失败: ' + (error.message || '服务器错误')); }) .finally(() => { loadingInstance.close(); }); }, tabImg(){ console.log(this.tableType) }, // 处理表格选择变化 handleSelectionChange(val) { this.multipleSelection = val; }, // 新增:批量确认和批量上报 batchConfirmation() { this.batchUpdateStatus('1'); }, batchReporting() { this.batchUpdateStatus('2'); }, // 通用批量确认和上报 batchUpdateStatus(status) { let keyIds = '' if(this.tableType == 'imgTable'){ if (this.checkeds.length === 0) { this.$message.warning('请至少选择一条数据'); return; } keyIds = this.checkeds.join(','); }else{ if (this.multipleSelection.length === 0) { this.$message.warning('请至少选择一条数据'); return; } keyIds = this.multipleSelection.map(row => row.keyId).join(','); } updateDefectSolve({ keyIds: keyIds, status: status }).then(response => { if (response.code === 200) { this.$message.success('操作成功'); this.getPicFun(); } else { this.$message.error(response.msg || '操作失败'); } }).catch(error => { this.$message.error('请求失败: ' + error.message); }); }, }, }; </script> <style lang="scss" scoped> .body { width: calc(100% - 60px); height: calc(100% - 190px); position: fixed; left: 20px; top: 150px; display: flex; //flex-direction: column; flex-direction: initial; .annotation_Table { width: 20%; height: 100%; //background: #f0f8ff21; .contentBox { width: 100%; flex: 1; //margin-top: 20px; margin-bottom: 20px; ::v-deep .el-tabs { .el-tabs__header { margin: 0; } .el-tabs__nav { width: 100%; display: flex; .el-tabs__item { flex: 1; height: 32px; padding: 0; display: flex; justify-content: center; align-items: center; font-size: 14px; color: #fff; letter-spacing: 1px; background: rgba($color: #000c23, $alpha: 0.3); } .is-active { background: rgba($color: #469bff, $alpha: 0.4); } } .el-tabs__nav-wrap::after { height: 4px; background: rgba($color: #469bff, $alpha: 0.4); } .el-tabs__active-bar { height: 4px; background: #469bff; } ::v-deep .el-tabs__active-bar { width: 200px !important; transform: translateX(0); } } } ::v-deep .el-tree { background: transparent; color: #fff; overflow: auto; height: 586px; //原本675px flex: 1; .el-icon-caret-right:before { //display: none; } >.el-tree-node { min-width: 100%; display: inline-block; } //.el-tree-node__expand-icon { // width: 14px; // height: 14px; // background: url("../../../../../../assets/images/operation/add.png") no-repeat; // background-size: 100% 100%; // // margin-left: -25px; //} .custom-tree-node { margin-left: 14px; } //.el-tree-node__expand-icon.expanded { // transform: rotateY(0); // background: url("../../../../../../assets/images/operation/reduce.png") // no-repeat; // background-size: 100% 100%; //} .el-tree-node__expand-icon.is-leaf { //display: none; } .el-tree-node__content { // margin-left: 42px; } .el-tree-node__content:hover { background: rgba($color: #469bff, $alpha: 0.3); } .el-tree-node:focus>.el-tree-node__content { background: rgba($color: #469bff, $alpha: 0.8); } } ::v-deep .el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content { background: rgba($color: #469bff, $alpha: 0.8); } } .image_lazy_right { width: 80%; height: 100%; //background: rgba(0, 137, 255, 0.13); .date-picker-box { width: 360px; } .select-box { width: 360px; } .input-box { width: 360px; } .demo-image__lazy { display: flex; height: 65%; overflow-y: auto; } .imgBox { display: flex; flex-wrap: wrap; .imgList { position: relative; width: 275px; margin: 0px 10px 0px 10px; overflow: hidden; .el-image { width: 100%; height: 165px; } } .typeNeme { position: absolute; top: 0px; background: #ffb802c7; padding: 2px 25px 2px 10px; border-bottom-right-radius: 19px; color: white; font-size: 13px; } .isWenTi { position: absolute; top: 145px; background: #000000a6; padding: 2px 15px 2px 10px; /* border-bottom-right-radius: 19px; */ color: white; font-size: 13px; } .typeGD { position: absolute; top: 12px; right: -27px; background: #00a3ff; padding: 2px 32px; -webkit-transform: rotate(45deg); transform: rotate(45deg); color: #ffffff; font-size: 13px; } .imgText { color: #ffffff; position: relative; margin-bottom: 10px; font-size: 12px; .imgTextLi { position: absolute; right: 10px; bottom: 0px; color: #00a3ff; cursor: pointer; } } .el-checkbox-group{ display: flex; flex-wrap: wrap; align-content: flex-start; } ::v-deep.el-checkbox{ position: absolute; top: 25px; left: 0; .el-checkbox__label{ display: none; } .el-checkbox__inner{ background: #003799; border: 1px solid #469BFF66; // 新增:选择框长宽 width: 32px; height: 32px; } .el-checkbox__label{ color: white; } // 新增:修改样式 .el-checkbox__inner::after { height: 16px; left: 12.8px; top: 3.2px; } } } } .audit { color: #07ffe1; background: rgba(0, 92, 255, 0.08); border-radius: 2px 2px 2px 2px; border: 1px solid; border-image: linear-gradient(180deg, rgba(7, 255, 225, 0.8), rgba(7, 255, 225, 0.24)) 1 1; margin-right: 8px; img { width: 14px; height: 14px; margin-right: 4px; } } .downloadC { color: #e6a23c; background: rgba(0, 92, 255, 0.08); border-radius: 2px 2px 2px 2px; border: 1px solid; border-image: linear-gradient(180deg, rgba(236, 162, 60, 0.8), rgba(236, 162, 60, 0.24)) 1 1; margin-right: 8px; img { width: 14px; height: 14px; margin-right: 4px; } } .button-box { display: flex; align-items: center; img { margin-left: 10px; cursor: pointer; } .liebiao { width: 26px; } .gongge { width: 26px; } } } </style>
09-09
<template> <div class="detail-container"> <!-- 索引板块卡片 --> <el-card class="index-card"> <!-- 表单区域 --> <el-form :model="formData" label-position="top" ref="indexForm" class="mobile-form" > <!-- 问卷标题 --> <el-form-item label="问卷标题:" prop="dcWjTitle"> <el-input v-model="formData.dcWjTitle" placeholder="请输入问卷标题" clearable :prefix-icon="Document" /> </el-form-item> <!-- 被测评人 --> <el-form-item label="被测评人:" prop="dcId"> <el-input v-model="formData.dcId" placeholder="请输入被测评人" clearable :prefix-icon="User" /> </el-form-item> <!-- 人员部门 --> <el-form-item label="人员部门:" prop="dcDept"> <el-input v-model="formData.dcDept" placeholder="请输入人员部门" clearable :prefix-icon="OfficeBuilding" /> </el-form-item> <!-- 提交状态 --> <el-form-item label="提交状态:" prop="state"> <el-select v-model="formData.state" placeholder="请选择提交状态" clearable class="mobile-select" > <el-option label="已提交" :value="1" /> <el-option label="未提交" :value="0" /> </el-select> </el-form-item> <!-- 新增:按钮区域 --> <el-form-item class="button-group"> <el-button type="primary" @click="handleSearch" class="action-button" :icon="Search" > 搜索 </el-button> <el-button @click="handleReset" class="action-button" :icon="Refresh" > 重置 </el-button> </el-form-item> </el-form> </el-card> <!-- 数据显示板块 --> <el-card class="data-card"> <!-- 刷新数据 --> <template #header> <div class="card-header"> <el-button type="primary" size="small" :icon="Refresh" @click="fetchData" > 刷新数据 </el-button> </div> </template> <!-- 数据表格 --> <el-table :data="tableData" v-loading="loading" element-loading-text="数据加载中..." stripe style="width: 100%" class="mobile-table" > <el-table-column prop="id" label="ID" width="80" /> <el-table-column prop="dcWjTitle" label="问卷标题" min-width="150" /> <el-table-column prop="dcName" label="被测评人" width="120" /> <el-table-column prop="dcDept" label="部门" width="120" /> <el-table-column prop="state" label="提交状态" width="100"> <template #default="scope"> <el-tag :type="scope.row.state === '1' ? 'success' : 'info'"> {{ scope.row.state === '1' ? '已提交' : '未提交' }} </el-tag> </template> </el-table-column> <el-table-column prop="score" label="总分" width="120" /> <el-table-column prop="createTime" label="创建间" width="180" /> <el-table-column label="操作" width="120" fixed="right"> <template #default="scope"> <el-button size="small" type="primary" @click="handleView(scope.row)" > 查看 </el-button> </template> </el-table-column> </el-table> <!-- 分页控件 --> <div class="pagination-container"> <el-pagination v-model:current-page="pagination.current" v-model:page-size="pagination.size" :page-sizes="[5, 10, 20, 50]" layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" @size-change="handleSizeChange" @current-change="handlePageChange" /> </div> </el-card> </div> </template> <script setup> // 确保正确导入所有 Vue 函数 import { ref, reactive, onMounted, onUnmounted } from 'vue'; import axios from 'axios'; import { Document, User, OfficeBuilding, Search, Refresh } from '@element-plus/icons-vue'; import { ElMessage } from 'element-plus'; import { useRouter } from 'vue-router'; const router = useRouter(); // 环境变量管理API地址 const API_BASE = import.meta.env.VITE_API_BASE || 'http://172.26.26.43/dev-api'; const API_URL = `${API_BASE}/wjdc/wj/listTx`; // 表单数据 const formData = reactive({ dcWjTitle: '', dcId: '', dcDept: '', state: null }); // 表格数据 const tableData = ref([]); const loading = ref(false); // 分页配置 const pagination = reactive({ current: 1, size: 10, total: 0 }); // 表单引用 const indexForm = ref(null); // 请求取消令牌 let cancelTokenSource = axios.CancelToken.source(); // 获取认证令牌 const getAuthToken = () => { const token = localStorage.getItem('token'); if (!token) { ElMessage.warning('请先登录'); router.push('/login'); return null; } return token; }; // 搜索按钮处理函数 - 添加防抖 let searchTimer = null; const handleSearch = () => { if (searchTimer) clearTimeout(searchTimer); searchTimer = setTimeout(() => { pagination.current = 1; fetchData(); }, 300); }; // 重置按钮处理函数 const handleReset = () => { if (indexForm.value) { indexForm.value.resetFields(); } handleSearch(); }; // 查看详情 const handleView = (row) => { console.log('查看详情:', row); // 这里可以实现查看详情的逻辑 }; // 分页大小改变 const handleSizeChange = (size) => { pagination.size = size; fetchData(); }; // 页码改变 const handlePageChange = (page) => { pagination.current = page; fetchData(); }; // 获取数据 const fetchData = async () => { // 获取认证令牌 const token = getAuthToken(); if (!token) return; // 取消之前的请求 if (cancelTokenSource) { cancelTokenSource.cancel('请求被取消'); } cancelTokenSource = axios.CancelToken.source(); loading.value = true; try { // 构造请求参数 const params = { pageNum: pagination.current, pageSize: pagination.size, ...formData }; // 调用API - 添加认证头 const response = await axios.get(API_URL, { params, cancelToken: cancelTokenSource.token, headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` } }); // 处理响应数据 const { data } = response; if (data && data.code === 200) { // 修改点:直接使用 data.rows 和 data.total tableData.value = data.rows || []; pagination.total = data.total || 0; // 空数据提示 if (tableData.value.length === 0) { ElMessage.info('没有找到匹配的数据'); } } else { const errorMsg = data?.msg || '未知错误'; console.error('API返回错误:', errorMsg); ElMessage.error(`请求失败: ${errorMsg}`); tableData.value = []; pagination.total = 0; } } catch (error) { // 处理认证失败 if (error.response && error.response.status === 401) { ElMessage.error('认证过期,请重新登录'); localStorage.removeItem('token'); router.push('/login'); return; } // 忽略取消请求的错误 if (!axios.isCancel(error)) { console.error('获取数据失败:', error); const errorMsg = error.response?.data?.message || '网络请求失败'; ElMessage.error(`请求失败: ${errorMsg}`); tableData.value = []; pagination.total = 0; } } finally { loading.value = false; } }; // 页面加载获取初始数据 onMounted(() => { fetchData(); }); // 组件卸载取消所有请求 onUnmounted(() => { if (cancelTokenSource) { cancelTokenSource.cancel('组件卸载,取消请求'); } }); </script> <style scoped> /* 移动端适配样式 */ .detail-container { padding: 12px; } .index-card { border-radius: 12px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); } .card-header { font-size: 18px; font-weight: 600; color: #1a1a1a; } .mobile-form { :deep(.el-form-item__label) { font-weight: 500; margin-bottom: 6px; } :deep(.el-input__inner) { height: 44px; border-radius: 8px; } } .mobile-select { width: 100%; :deep(.el-input__inner) { height: 44px; } } /* 按钮区域样式 */ .button-group { display: flex; gap: 12px; margin-top: 16px; } .action-button { flex: 1; height: 46px; font-size: 16px; border-radius: 8px; } /* 移动端响应式调整 */ @media (max-width: 480px) { .button-group { flex-direction: column; gap: 10px; } .action-button { width: 100%; } } </style> 我想索引板块的被测评人搜索框有如下效果,在点击空白输入框还未输入调用接口:http://172.26.26.43/dev-api/wjdc/wj/getBdrList ,响应的数据格式:[{"dcId":14,"dcName":"张三"},{"dcId":15,"dcName":"李四"},{"dcId":16,"dcName":"王五"}] ,显示返回的名称dcName前10个,然后可以输入关键字带出含有该字的名字,如输入张,显示张三,张兰。选择张三就把张三添加到搜索框里,支持多选
07-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值