解决Echarts+<el-tab-pane>的警告:Can‘t get DOM width or height

1 问题描述

环境:

  • Chrome 87
  • Element-Plus
  • Vue3.0.5
  • <el-tab>+<el-tab-pane>中使用Echarts

警告如下:

在这里插入图片描述

2 代码

<el-tabs type="border-card">
	<el-tab-pane label="xxx">
		<div id="main" style="width: 500px;height: 500px;">
		</div>
	</el-tab-pane>
</el-tabs>
export default {
    mounted() {
        var category = echarts.init(document.getElementById('main'))
        //...
	}
}

3 原因分析

原因是<el-tab-pane>,具体可以查看这里issue

在这里插入图片描述

Echarts警告的关键是clientWidthclienHeight,直接在代码中固定高宽时:

<div id="main" style="width: 500px;height: 500px;"></div>

控制台打印为clientHeight/clientWidth

console.log(document.getElementById('main').clientWidth)
console.log(document.getElementById('main').clientHeight)

两者均为0,原因在于<el-tab-pane>,将图表放到外面时并没有警告:

<el-tabs type="border-card">
	<div id="main" style="width: 500px;height: 500px;">
	</div>
	<el-tab-pane label="xxx">
	</el-tab-pane>
</el-tabs>

初始化Echarts时,<el-tab-pane>并没有让Echarts获取正确的clientHeight以及clientWidth,尝试过的解决方法是监听tab-click

<el-tabs type="border-card" @tab-click="xxx">
	<el-tab-pane label="xxx">
		<div id="main" style="width: 500px;height: 500px;">
		</div>
	</el-tab-pane>
</el-tabs>

但是这需要手动点击tab才能监听到,也就是如果设置了默认tab这是无法监听到的。

另一个尝试过的方案是手动设置width/height

<el-tabs type="border-card">
	<el-tab-pane label="xxx">
		<div id="main" ref="main" style="width: 500px;height: 500px;">
		</div>
	</el-tab-pane>
</el-tabs>
mounted(){
	this.$refs.main.style.width=500
	this.$refs.main.style.height=500
	var chart = echarts.init(document.getElementById('main'))
}

也是不行。

4 解决方案

使用Object.defineProperty设置clientWidth/clientHeight

mounted(){
	Object.defineProperty(document.getElementById('main'),'clientWidth',{get:function(){return 500;}})
	Object.defineProperty(document.getElementById('main'),'clientHeight',{get:function(){return 500;}})
	var chart = echarts.init(document.getElementById('main'))
}

同时也可以把div上的style去掉:

<div id="main"></div>

这样就不会出现警告了。

<template> <el-dialog :title="!dataForm.id ? &#39;新增电池信息&#39; : &#39;修改电池信息&#39;" :visible.sync="visible" width="90%" top="5vh" custom-class="battery-form-dialog" > <!-- 使用标签页布局 --> <el-tabs v-model="activeTab" type="card" tab-position="top"> <!-- 电池基本信息 --> <el-tab-pane label="基本信息" name="1"> <div class="form-grid"> <el-form-item label="电池ID" prop="batteryId"> <el-input v-model="dataForm.batteryId" disabled> <i slot="prefix" class="el-icon-files"></i> </el-input> </el-form-item> <el-form-item label="电压(V)" prop="batteryVoltage"> <el-input v-model="dataForm.batteryVoltage" type="number" disabled> <i slot="prefix" class="el-icon-data-line"></i> </el-input> </el-form-item> <el-form-item label="电流(A)" prop="batteryCurrent"> <el-input v-model="dataForm.batteryCurrent" type="number" disabled> <i slot="prefix" class="el-icon-sort"></i> </el-input> </el-form-item> <el-form-item label="SOC(%)" prop="batterySoc"> <el-input v-model="dataForm.batterySoc" type="number" min="0" max="100" disabled> <i slot="prefix" class="el-icon-pie-chart"></i> </el-input> </el-form-item> <el-form-item label="硬件版本" prop="batteryHardVersion"> <el-input v-model="dataForm.batteryHardVersion" disabled> <i slot="prefix" class="el-icon-cpu"></i> </el-input> </el-form-item> <el-form-item label="软件版本" prop="batterySoftVersion"> <el-input v-model="dataForm.batterySoftVersion" disabled> <i slot="prefix" class="el-icon-setting"></i> </el-input> </el-form-item> </div> </el-tab-pane> <!-- 电池状态信息 --> <el-tab-pane label="状态信息" name="2"> <div class="form-grid"> <el-form-item label="工作模式" prop="batteryWorkMode"> <el-select v-model="dataForm.batteryWorkMode" disabled> <el-option label="放电模式 (0x01)" value="1"></el-option> <el-option label="充电模式 (0x10)" value="16"></el-option> <el-option label="保护模式 (0x21)" value="33"></el-option> <el-option label="待机无输出模式 (0x30)" value="48"></el-option> <el-option label="待机预放电模式 (0x31)" value="49"></el-option> <el-option label="故障需返厂 (0xFF)" value="255"></el-option> </el-select> </el-form-item> <el-form-item label="电池类型" prop="batteryKind"> <el-select v-model="dataForm.batteryKind"> <el-option label="运营" value="0"></el-option> <el-option label="售后" value="1"></el-option> <el-option label="内测" value="2"></el-option> <el-option label="报废" value="3"></el-option> </el-select> </el-form-item> <el-form-item label="保护状态码" prop="batteryProtectCode"> <el-tooltip effect="dark" placement="top"> <div slot="content"> bit0: 放电低温 | bit1: 放电高温 | bit2: 充电高温<br> bit3: 充电低温 | bit4: 放电过流 | bit5: 放电欠压<br> bit6: 充电过流 | bit7: 充电过压 | bit8: 短路<br> bit9: 温差过大 | bit10: 压差过大 | bit11: 智能充电通信超时<br> bit12: IC保护 | bit13: 预放电失败 | bit14: BMS与Tracker通讯超时<br> bit15: Gsensor故障 | bit16~31: 保留 </div> <el-input v-model="dataForm.batteryProtectCode" disabled> <i slot="prefix" class="el-icon-warning"></i> </el-input> </el-tooltip> </el-form-item> <el-form-item label="错误状态码" prop="batteryErrorCode"> <el-tooltip effect="dark" placement="top"> <div slot="content"> 低8位故障状态码:<br> bit0: 保留 | bit1: 采样线故障 | bit2: 温度传感器损坏<br> bit3: IC损坏 | bit4: 充电MOS损坏 | bit5: 放电MOS损坏<br> bit6: 失衡 | bit7: 失效<br> 高8位工作状态:<br> bit8: G sensor损坏 | bit9: BMS与Tracker通讯故障 </div> <el-input v-model="dataForm.batteryErrorCode" disabled> <i slot="prefix" class="el-icon-warning-outline"></i> </el-input> </el-tooltip> </el-form-item> </div> </el-tab-pane> <!-- 温度电压信息 --> <el-tab-pane label="温度电压" name="3"> <div class="form-grid"> <el-form-item label="最高温度(℃)" prop="batteryTemperatureMax"> <el-input v-model="dataForm.batteryTemperatureMax" type="number" disabled> <i slot="prefix" class="el-icon-sunny"></i> </el-input> </el-form-item> <el-form-item label="最低温度(℃)" prop="batteryTemperatureMin"> <el-input v-model="dataForm.batteryTemperatureMin" type="number" disabled> <i slot="prefix" class="el-icon-cold-drink"></i> </el-input> </el-form-item> <el-form-item label="最高电压(V)" prop="batteryVoltageMax"> <el-input v-model="dataForm.batteryVoltageMax" type="number" disabled> <i slot="prefix" class="el-icon-top"></i> </el-input> </el-form-item> <el-form-item label="最低电压(V)" prop="batteryVoltageMin"> <el-input v-model="dataForm.batteryVoltageMin" type="number" disabled> <i slot="prefix" class="el-icon-bottom"></i> </el-input> </el-form-item> </div> </el-tab-pane> <!-- 设备信息 --> <el-tab-pane label="设备信息" name="4"> <div class="form-grid"> <el-form-item label="设备型号" prop="model"> <el-input v-model="dataForm.model" disabled> <i slot="prefix" class="el-icon-mobile"></i> </el-input> </el-form-item> <el-form-item label="制造商" prop="manufacture"> <el-input v-model="dataForm.manufacture" disabled> <i slot="prefix" class="el-icon-office-building"></i> </el-input> </el-form-item> <el-form-item label="IMEI" prop="imei"> <el-input v-model="dataForm.imei" disabled> <i slot="prefix" class="el-icon-phone"></i> </el-input> </el-form-item> <el-form-item label="IMSI" prop="imsi"> <el-input v-model="dataForm.imsi" disabled> <i slot="prefix" class="el-icon-sim-card"></i> </el-input> </el-form-item> <el-form-item label="ICCID" prop="iccid"> <el-input v-model="dataForm.iccid" disabled> <i slot="prefix" class="el-icon-credit-card"></i> </el-input> </el-form-item> </div> </el-tab-pane> <!-- GPS定位信息 --> <el-tab-pane label="GPS定位" name="5"> <div class="form-grid"> <el-form-item label="经度" prop="longitude"> <el-input v-model="dataForm.longitude" type="number" disabled> <i slot="prefix" class="el-icon-place"></i> </el-input> </el-form-item> <el-form-item label="经度方向" prop="longitudeDirection"> <el-select v-model="dataForm.longitudeDirection" disabled> <el-option label="东经" value="E"></el-option> <el-option label="西经" value="W"></el-option> </el-select> </el-form-item> <el-form-item label="纬度" prop="latitude"> <el-input v-model="dataForm.latitude" type="number" disabled> <i slot="prefix" class="el-icon-place"></i> </el-input> </el-form-item> <el-form-item label="纬度方向" prop="latitudeDirection"> <el-select v-model="dataForm.latitudeDirection" disabled> <el-option label="北纬" value="N"></el-option> <el-option label="南纬" value="S"></el-option> </el-select> </el-form-item> </div> </el-tab-pane> <!-- 业务信息 --> <el-tab-pane label="业务信息" name="6"> <div class="form-grid"> <el-form-item label="业务模式" prop="businessmode"> <el-select v-model="dataForm.businessmode" disabled> <el-option v-for="mode in businessModes" :key="mode.value" :label="mode.label" :value="mode.value"></el-option> </el-select> </el-form-item> <el-form-item label="处理状态" prop="handled"> <el-select v-model="dataForm.handled" disabled> <el-option label="已处理" :value="1"></el-option> <el-option label="待处理" :value="0"></el-option> </el-select> </el-form-item> <el-form-item label="执行方式" prop="todoNow"> <el-select v-model="dataForm.todoNow" disabled> <el-option label="立即执行" :value="1"></el-option> <el-option label="等待执行" :value="0"></el-option> </el-select> </el-form-item> <el-form-item label="需要回复" prop="needack"> <el-select v-model="dataForm.needack" disabled> <el-option label="是" :value="1"></el-option> <el-option label="否" :value="0"></el-option> </el-select> </el-form-item> <el-form-item label="消息类型" prop="flag"> <el-select v-model="dataForm.flag" disabled> <el-option label="设备主动请求或上报" :value="1"></el-option> <el-option label="平台主动推送或下指令" :value="2"></el-option> <el-option label="平台指令反馈的结果" :value="3"></el-option> </el-select> </el-form-item> </div> </el-tab-pane> <!-- 其他信息 --> <el-tab-pane label="其他信息" name="7"> <div class="form-grid"> <el-form-item label="原始数据" prop="payload"> <el-input v-model="dataForm.payload" type="textarea" :rows="4" disabled></el-input> </el-form-item> </div> </el-tab-pane> </el-tabs> <span slot="footer" class="dialog-footer"> <el-button @click="visible = false">取消</el-button> <el-button type="primary" @click="dataFormSubmit()">确定</el-button> </span> </el-dialog> </template> <script> export default { data() { return { visible: false, activeTab: &#39;1&#39;, dataForm: { id: 0, batteryId: &#39;&#39;, batteryVoltage: &#39;&#39;, batteryCurrent: &#39;&#39;, batterySoc: &#39;&#39;, batteryHardVersion: &#39;&#39;, batterySoftVersion: &#39;&#39;, batteryWorkMode: &#39;&#39;, batteryKind: "0", batteryProtectCode: &#39;&#39;, batteryErrorCode: &#39;&#39;, batteryTemperatureMax: &#39;&#39;, batteryTemperatureMin: &#39;&#39;, batteryVoltageMax: &#39;&#39;, batteryVoltageMin: &#39;&#39;, mosStatus: &#39;&#39;, mosTemp: &#39;&#39;, batteryCycleTimes: &#39;&#39;, steadyStatus: &#39;&#39;, cellVoltage: &#39;&#39;, model: &#39;&#39;, manufacture: &#39;&#39;, imei: &#39;&#39;, imsi: &#39;&#39;, iccid: &#39;&#39;, trackerHardwareVersion: &#39;&#39;, trackerSoftwareVersion: &#39;&#39;, csq: &#39;&#39;, networkType: &#39;&#39;, locationMode: &#39;&#39;, longitude: &#39;&#39;, longitudeDirection: &#39;&#39;, latitude: &#39;&#39;, latitudeDirection: &#39;&#39;, gpsSpeed: &#39;&#39;, gpsSignal: &#39;&#39;, satelliteNum: &#39;&#39;, accuracy: &#39;&#39;, flag: &#39;&#39;, clientId: &#39;&#39;, topic: &#39;&#39;, productKey: &#39;&#39;, handled: &#39;&#39;, todoNow: &#39;&#39;, needack: &#39;&#39;, businessmode: &#39;&#39;, uploadTime: &#39;&#39;, createTime: &#39;&#39;, updateTime: &#39;&#39;, payload: &#39;&#39; }, businessModes: [ { value: 1, label: "关机模式" }, { value: 2, label: "运营模式" }, { value: 3, label: "运输模式" }, { value: 4, label: "通讯充电模式" }, { value: 5, label: "盲充模式" }, { value: 6, label: "存储模式" }, { value: 7, label: "搜寻模式" }, { value: 8, label: "返厂模式" } ], /* dataRule: { batteryId: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], batteryVoltage: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], batteryCurrent: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], batterySoc: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], batteryHardVersion: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], batterySoftVersion: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], batteryWorkMode: [ { required: true, message: &#39;0x01(1):放电模式 0x10(16):充电模式 0x21(33):保护模式 0x30(48):待机无输出模式 0x31(49):待机预放电模式 0xFF(255):故障需返厂不能为空&#39;, trigger: &#39;blur&#39; } ], batteryProtectCode: [ { required: true, message: &#39;保护状态 bit16~bit 31 保留 bit15:Gsensor 故障 bit14:BMS 与 Tracker通讯超时 bit13: 预放电失败 bit12: IC保护 bit11: 智能充电通信超时 bit10:压差过大 bit9:温差过大 bit8:短路 bit7:充电过压 bit6:充电过流 bit5:放电欠压 bit4:放电过流 bit3:充电低温 bit2:充电高温 bit1:放电高温 bit0:放电低温不能为空&#39;, trigger: &#39;blur&#39; } ], batteryErrorCode: [ { required: true, message: &#39;转成2进制, 总共为16位,高8位为电池包工作状态,低8位为故障状态码 bit9BMS 与 Tracker通讯故障,bit8BMS 板 G sensor损坏,(8/9无效)bit7:失效,bit6:失衡,bit5:放电 MOS 损坏,bit4:充电 MOS 损坏,bit3IC 损坏,bit2:温度传感器损坏,bit1:采样线断线,虚焊等故障 保留,置 0,bit0:保留不能为空&#39;, trigger: &#39;blur&#39; } ], batteryTemperatureMax: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], batteryTemperatureMin: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], batteryVoltageMax: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], batteryVoltageMin: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], mosStatus: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], mosTemp: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], batteryCycleTimes: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], steadyStatus: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], cellVoltage: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], model: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], manufacture: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], imei: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], imsi: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], iccid: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], trackerHardwareVersion: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], trackerSoftwareVersion: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], csq: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], networkType: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], locationMode: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], longitude: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], longitudeDirection: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], latitude: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], latitudeDirection: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], gpsSpeed: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], gpsSignal: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], satelliteNum: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], accuracy: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], flag: [ { required: true, message: &#39;1:设备主动请求或上报 2:平台主动推送或下指令 3:平台指令反馈的结果不能为空&#39;, trigger: &#39;blur&#39; } ], clientId: [ { required: true, message: &#39;MQTT发布消息所需的clientId不能为空&#39;, trigger: &#39;blur&#39; } ], topic: [ { required: true, message: &#39;MQTT主题不能为空&#39;, trigger: &#39;blur&#39; } ], productKey: [ { required: true, message: &#39;主题名称中需要的productKey不能为空&#39;, trigger: &#39;blur&#39; } ], handled: [ { required: true, message: &#39;配置是否处理 1:已处理 0:待处理不能为空&#39;, trigger: &#39;blur&#39; } ], todoNow: [ { required: true, message: &#39;是否立即执行 0:等待执行 1:立即执行不能为空&#39;, trigger: &#39;blur&#39; } ], needack: [ { required: true, message: &#39;是否回复不能为空&#39;, trigger: &#39;blur&#39; } ], businessmode: [ { required: true, message: &#39;业务模式 1:关机模式 2:运营模式 3:运输模式 4:通讯充电模式 5:盲充模式 6:存储模式 7:搜寻模式 8:返厂模式不能为空&#39;, trigger: &#39;blur&#39; } ], uploadTime: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], createTime: [ { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } ], updateTime: [ { required: true, message: &#39;更新时间不能为空&#39;, trigger: &#39;blur&#39; } ], payload: [ { required: true, message: &#39;原始数据不能为空&#39;, trigger: &#39;blur&#39; } ] } */ } }, computed: { // 处理状态标签 handledLabel() { return this.dataForm.handled === 1 ? "已处理" : this.dataForm.handled === 0 ? "待处理" : ""; }, // 执行方式标签 todoNowLabel() { return this.dataForm.todoNow === 1 ? "立即执行" : this.dataForm.todoNow === 0 ? "等待执行" : ""; }, // 需要回复标签 needackLabel() { return this.dataForm.needack === 1 ? "是" : this.dataForm.needack === 0 ? "否" : ""; }, // 业务模式标签 businessModeLabel() { const mode = this.businessModes.find(m => m.value == this.dataForm.businessmode); return mode ? mode.label : ""; }, // 消息类型标签 flagLabel() { switch (this.dataForm.flag) { case 1: return "设备主动请求或上报"; case 2: return "平台主动推送或下指令"; case 3: return "平台指令反馈的结果"; default: return ""; } } }, methods: { init (id) { this.dataForm.id = id || 0 this.visible = true this.$nextTick(() => { this.$refs[&#39;dataForm&#39;].resetFields() if (this.dataForm.id) { this.$http({ url: this.$http.adornUrl(`/maya/mybatteryinfo/info/${this.dataForm.id}`), method: &#39;get&#39;, params: this.$http.adornParams() }).then(({data}) => { if (data && data.code === 0) { this.dataForm.batteryId = data.myBatteryInfo.batteryId this.dataForm.batteryVoltage = data.myBatteryInfo.batteryVoltage this.dataForm.batteryCurrent = data.myBatteryInfo.batteryCurrent this.dataForm.batterySoc = data.myBatteryInfo.batterySoc this.dataForm.batteryHardVersion = data.myBatteryInfo.batteryHardVersion this.dataForm.batterySoftVersion = data.myBatteryInfo.batterySoftVersion this.dataForm.batteryWorkMode = data.myBatteryInfo.batteryWorkMode this.dataForm.batteryKind = String(data.myBatteryInfo.batteryKind); this.dataForm.batteryProtectCode = data.myBatteryInfo.batteryProtectCode this.dataForm.batteryErrorCode = data.myBatteryInfo.batteryErrorCode this.dataForm.batteryTemperatureMax = data.myBatteryInfo.batteryTemperatureMax this.dataForm.batteryTemperatureMin = data.myBatteryInfo.batteryTemperatureMin this.dataForm.batteryVoltageMax = data.myBatteryInfo.batteryVoltageMax this.dataForm.batteryVoltageMin = data.myBatteryInfo.batteryVoltageMin this.dataForm.mosStatus = data.myBatteryInfo.mosStatus this.dataForm.mosTemp = data.myBatteryInfo.mosTemp this.dataForm.batteryCycleTimes = data.myBatteryInfo.batteryCycleTimes this.dataForm.steadyStatus = data.myBatteryInfo.steadyStatus this.dataForm.cellVoltage = data.myBatteryInfo.cellVoltage this.dataForm.model = data.myBatteryInfo.model this.dataForm.manufacture = data.myBatteryInfo.manufacture this.dataForm.imei = data.myBatteryInfo.imei this.dataForm.imsi = data.myBatteryInfo.imsi this.dataForm.iccid = data.myBatteryInfo.iccid this.dataForm.trackerHardwareVersion = data.myBatteryInfo.trackerHardwareVersion this.dataForm.trackerSoftwareVersion = data.myBatteryInfo.trackerSoftwareVersion this.dataForm.csq = data.myBatteryInfo.csq this.dataForm.networkType = data.myBatteryInfo.networkType this.dataForm.locationMode = data.myBatteryInfo.locationMode this.dataForm.longitude = data.myBatteryInfo.longitude this.dataForm.longitudeDirection = data.myBatteryInfo.longitudeDirection this.dataForm.latitude = data.myBatteryInfo.latitude this.dataForm.latitudeDirection = data.myBatteryInfo.latitudeDirection this.dataForm.gpsSpeed = data.myBatteryInfo.gpsSpeed this.dataForm.gpsSignal = data.myBatteryInfo.gpsSignal this.dataForm.satelliteNum = data.myBatteryInfo.satelliteNum this.dataForm.accuracy = data.myBatteryInfo.accuracy this.dataForm.flag = data.myBatteryInfo.flag this.dataForm.clientId = data.myBatteryInfo.clientId this.dataForm.topic = data.myBatteryInfo.topic this.dataForm.productKey = data.myBatteryInfo.productKey this.dataForm.handled = data.myBatteryInfo.handled this.dataForm.todoNow = data.myBatteryInfo.todoNow this.dataForm.needack = data.myBatteryInfo.needack this.dataForm.businessmode = data.myBatteryInfo.businessmode this.dataForm.uploadTime = data.myBatteryInfo.uploadTime this.dataForm.createTime = data.myBatteryInfo.createTime this.dataForm.updateTime = data.myBatteryInfo.updateTime this.dataForm.payload = data.myBatteryInfo.payload } }) } }) }, // 表单提交 dataFormSubmit () { this.$refs[&#39;dataForm&#39;].validate((valid) => { if (valid) { this.$http({ url: this.$http.adornUrl(`/maya/mybatteryinfo/${!this.dataForm.id ? &#39;save&#39; : &#39;update&#39;}`), method: &#39;post&#39;, data: this.$http.adornData({ &#39;id&#39;: this.dataForm.id || undefined, &#39;batteryId&#39;: this.dataForm.batteryId, &#39;batteryVoltage&#39;: this.dataForm.batteryVoltage, &#39;batteryCurrent&#39;: this.dataForm.batteryCurrent, &#39;batterySoc&#39;: this.dataForm.batterySoc, &#39;batteryHardVersion&#39;: this.dataForm.batteryHardVersion, &#39;batterySoftVersion&#39;: this.dataForm.batterySoftVersion, &#39;batteryWorkMode&#39;: this.dataForm.batteryWorkMode, &#39;batteryKind&#39;: Number(this.dataForm.batteryKind), &#39;batteryProtectCode&#39;: this.dataForm.batteryProtectCode, &#39;batteryErrorCode&#39;: this.dataForm.batteryErrorCode, &#39;batteryTemperatureMax&#39;: this.dataForm.batteryTemperatureMax, &#39;batteryTemperatureMin&#39;: this.dataForm.batteryTemperatureMin, &#39;batteryVoltageMax&#39;: this.dataForm.batteryVoltageMax, &#39;batteryVoltageMin&#39;: this.dataForm.batteryVoltageMin, &#39;mosStatus&#39;: this.dataForm.mosStatus, &#39;mosTemp&#39;: this.dataForm.mosTemp, &#39;batteryCycleTimes&#39;: this.dataForm.batteryCycleTimes, &#39;steadyStatus&#39;: this.dataForm.steadyStatus, &#39;cellVoltage&#39;: this.dataForm.cellVoltage, &#39;model&#39;: this.dataForm.model, &#39;manufacture&#39;: this.dataForm.manufacture, &#39;imei&#39;: this.dataForm.imei, &#39;imsi&#39;: this.dataForm.imsi, &#39;iccid&#39;: this.dataForm.iccid, &#39;trackerHardwareVersion&#39;: this.dataForm.trackerHardwareVersion, &#39;trackerSoftwareVersion&#39;: this.dataForm.trackerSoftwareVersion, &#39;csq&#39;: this.dataForm.csq, &#39;networkType&#39;: this.dataForm.networkType, &#39;locationMode&#39;: this.dataForm.locationMode, &#39;longitude&#39;: this.dataForm.longitude, &#39;longitudeDirection&#39;: this.dataForm.longitudeDirection, &#39;latitude&#39;: this.dataForm.latitude, &#39;latitudeDirection&#39;: this.dataForm.latitudeDirection, &#39;gpsSpeed&#39;: this.dataForm.gpsSpeed, &#39;gpsSignal&#39;: this.dataForm.gpsSignal, &#39;satelliteNum&#39;: this.dataForm.satelliteNum, &#39;accuracy&#39;: this.dataForm.accuracy, &#39;flag&#39;: this.dataForm.flag, &#39;clientId&#39;: this.dataForm.clientId, &#39;topic&#39;: this.dataForm.topic, &#39;productKey&#39;: this.dataForm.productKey, &#39;handled&#39;: this.dataForm.handled, &#39;todoNow&#39;: this.dataForm.todoNow, &#39;needack&#39;: this.dataForm.needack, &#39;businessmode&#39;: this.dataForm.businessmode, &#39;uploadTime&#39;: this.dataForm.uploadTime, &#39;createTime&#39;: this.dataForm.createTime, &#39;updateTime&#39;: this.dataForm.updateTime, &#39;payload&#39;: this.dataForm.payload }) }).then(({data}) => { if (data && data.code === 0) { this.$message({ message: &#39;操作成功&#39;, type: &#39;success&#39;, duration: 1500, onClose: () => { this.visible = false this.$emit(&#39;refreshDataList&#39;) } }) } else { this.$message.error(data.msg) } }) } }) } } } </script> <style> .battery-form-dialog { font-family: &#39;Segoe UI&#39;, &#39;PingFang SC&#39;, &#39;Microsoft YaHei&#39;, sans-serif; color: #1a1a1a; } /* 标签页样式优化 */ .battery-form-dialog .el-tabs__item { font-weight: 600 !important; font-size: 15px !important; padding: 0 20px !important; height: 40px; line-height: 40px; color: #555; } .battery-form-dialog .el-tabs__item.is-active { color: #1a73e8 !important; border-bottom: 3px solid #1a73e8 !important; } .battery-form-dialog .el-tabs__header { margin-bottom: 20px; } /* 网格布局 - 横向排列 */ .form-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px 30px; padding: 15px; } /* 表单标签优化 */ .battery-form-dialog .el-form-item__label { display: block; font-weight: 600 !important; color: #1a1a1a !important; font-size: 14px !important; padding-bottom: 6px !important; margin-bottom: 0 !important; letter-spacing: 0.5px; } /* 输入框优化 */ .battery-form-dialog .el-input__inner, .battery-form-dialog .el-textarea__inner, .battery-form-dialog .el-select .el-input__inner { font-size: 15px !important; color: #222 !important; font-weight: 500 !important; border: 1px solid #dcdfe6 !important; background-color: #f8fafc !important; height: 40px; line-height: 40px; border-radius: 4px; } /* 文本域样式 */ .battery-form-dialog .el-textarea__inner { min-height: 100px; line-height: 1.5; padding: 10px 15px; font-family: monospace; } /* 禁用状态优化 */ .battery-form-dialog .el-input.is-disabled .el-input__inner, .battery-form-dialog .el-textarea.is-disabled .el-textarea__inner, .battery-form-dialog .el-select.is-disabled .el-input__inner { color: #444 !important; background-color: #f0f4f8 !important; border-color: #e4e7ed !important; opacity: 1; } /* 图标颜色优化 */ .battery-form-dialog .el-input__prefix { color: #1a73e8 !important; font-size: 16px; display: flex; align-items: center; padding-left: 8px; } /* 按钮优化 */ .battery-form-dialog .el-button { font-weight: 600; padding: 10px 20px; border-radius: 4px; font-size: 14px; min-width: 100px; transition: all 0.3s; } .battery-form-dialog .el-button--default { border-color: #dcdfe6; } .battery-form-dialog .el-button--primary { background-color: #1a73e8; border-color: #1a73e8; } .battery-form-dialog .el-button--primary:hover { background-color: #0d62c9; border-color: #0d62c9; } /* 标题优化 */ .battery-form-dialog .el-dialog__title { font-size: 18px !important; font-weight: 700 !important; color: #1a1a1a !important; letter-spacing: 0.5px; } /* 提示工具样式 */ .battery-form-dialog .el-tooltip__popper { max-width: 400px; font-size: 13px; line-height: 1.6; background-color: #2c3e50; color: #ecf0f1; } .battery-form-dialog .el-tooltip__popper[x-placement^="top"] .popper__arrow { border-top-color: #2c3e50; } /* 错误提示样式 */ .battery-form-dialog .el-form-item__error { color: #f56c6c; font-size: 12px; padding-top: 4px; } /* 响应式调整 */ @media (max-width: 1200px) { .form-grid { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); } } @media (max-width: 992px) { .form-grid { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); } } @media (max-width: 768px) { .battery-form-dialog { width: 95% !important; } .form-grid { grid-template-columns: 1fr; } .battery-form-dialog .el-tabs__item { font-size: 13px !important; padding: 0 10px !important; } } </style>修复该页面,并给我完整胡代码
07-22
<script setup> import { ref, onMounted } from "vue" import { getCategoryFilterAPI } from "@/apis/category" import { useRoute } from "vue-router" import { getSubCategoryAPI } from "@/apis/category.js" import GoodsItem from "../Home/components/GoodsItem.vue" // 获取面包屑导航数据 const route = useRoute() const categoryData = ref({}) const getCategoryData = async () => { const res = await getCategoryFilterAPI(route.params.id) categoryData.value = res.result }; onMounted(() => { getCategoryData() }); //获取基础列表数据渲染 const goodList = ref([]) const reqData = ref({ categoryId: route.params.id, page: 1, pageSize: 20, sortField: &#39;publishTime&#39; }) const getGoodList = async () => { const res = await getSubCategoryAPI(reqData.value) console.log(res) goodList.value = res.result.items } onMounted(() => getGoodList()) // tab切换回调 const tabChange = () => { console.log(&#39;tab切换了&#39;, reqData.value.sortField) reqData.value.page = 1 getGoodList() } // 加载更多 const disabled = ref(false) const load = async () => { console.log(&#39;加载更多数据咯&#39;) // 获取下一页的数据 reqData.value.page++ const res = await getSubCategoryAPI(reqData.value) goodList.value = [...goodList.value, ...res.result.items] // 加载完毕 停止监听 if (res.result.items.length === 0) { disabled.value = true } } </script> <template> <div class="container"> <!-- 面包屑 --> <div class="bread-container"> <el-breadcrumb separator=">"> <el-breadcrumb-item :to="{ path: &#39;/&#39; }">首页</el-breadcrumb-item> <el-breadcrumb-item :to="{ path: `/category/${categoryData.parentId}` }" >{{ categoryData.parentName }} </el-breadcrumb-item> <el-breadcrumb-item>{{ categoryData.name }}</el-breadcrumb-item> </el-breadcrumb> </div> <div class="sub-container"> <el-tabs v-model="reqData.sortField" @tab-change="tabChange"> <el-tab-pane label="最新商品" name="publishTime"></el-tab-pane> <el-tab-pane label="最高人气" name="orderNum"></el-tab-pane> <el-tab-pane label="评论最多" name="evaluateNum"></el-tab-pane> </el-tabs> <div class="body" v-infinite-scroll="load" :infinite-scroll-disabled="disabled"> <!-- 商品列表--> <GoodsItem v-for="goods in goodList" :goods="goods" :key="goods.id" /> </div> </div> </div> </template> <style lang="scss" scoped> .bread-container { padding: 25px 0; color: #666; } .sub-container { padding: 20px 10px; background-color: #fff; // overflow-y: auto; .body { display: flex; flex-wrap: wrap; padding: 0 10px; // overflow-y: auto; } .goods-item { display: block; width: 220px; margin-right: 20px; padding: 20px 30px; text-align: center; img { width: 160px; height: 160px; } p { padding-top: 10px; } .name { font-size: 16px; } .desc { color: #999; height: 29px; } .price { color: $priceColor; font-size: 20px; } } .pagination-container { margin-top: 20px; display: flex; justify-content: center; } } </style> 为什么不会触发无限加载
09-30
<template> <el-dialog :title="!dataForm.id ? &#39;新增电池信息&#39; : &#39;修改电池信息&#39;" :close-on-click-modal="false" v-dialogDrag :visible.sync="visible" width="90%" top="5vh" custom-class="multi-column-dialog"> <el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()" label-width="120px" class="multi-column-form"> <!-- 使用栅格系统分三列 --> <el-row :gutter="30"> <!-- 第一列:电池基本信息 --> <el-col :span="8"> <div class="form-section"> <div class="section-header"> <i class="el-icon-folder"></i> <span>电池基本信息</span> </div> <el-form-item label="电池编号" prop="hwid"> <el-input v-model="dataForm.hwid" placeholder="电池编号" disabled></el-input> </el-form-item> <el-form-item label="电芯类型" prop="batteryCellId"> <el-select v-model="dataForm.batteryCellId" placeholder="选择电芯类型"> <el-option v-for="item in batteryCellIds" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </el-form-item> <el-form-item label="电池类型" prop="batteryKind"> <el-select v-model="dataForm.batteryKind" placeholder="选择电池类型"> <el-option v-for="item in batteryKinds" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </el-form-item> <el-form-item label="电芯封装" prop="batteryCellPackageId"> <el-select v-model="dataForm.batteryCellPackageId" placeholder="选择电芯封装"> <el-option v-for="item in batteryCellPackageIds" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </el-form-item> <el-form-item label="电池串数" prop="batteryBunchs"> <el-input v-model="dataForm.batteryBunchs" placeholder="电池串数"></el-input> </el-form-item> <el-form-item label="电池并数" prop="batteryUnions"> <el-input v-model="dataForm.batteryUnions" placeholder="电池并数"></el-input> </el-form-item> <el-form-item label="单体电压(V)" prop="singleBatteryVoltage"> <el-input v-model="dataForm.singleBatteryVoltage" placeholder="单体电压"></el-input> </el-form-item> <el-form-item label="额定总压(V)" prop="ratedTotalPressure"> <el-input v-model="dataForm.ratedTotalPressure" placeholder="额定总压"></el-input> </el-form-item> </div> </el-col> <!-- 第二列:电池规格参数 --> <el-col :span="8"> <div class="form-section"> <div class="section-header"> <i class="el-icon-s-data"></i> <span>规格参数</span> </div> <el-form-item label="额定电流(A)" prop="ratedCurrent"> <el-input v-model="dataForm.ratedCurrent" placeholder="额定电流"></el-input> </el-form-item> <el-form-item label="额定容量(Ah)" prop="ratedCapacity"> <el-input v-model="dataForm.ratedCapacity" placeholder="额定容量"></el-input> </el-form-item> <el-form-item label="额定能量(kWh)" prop="ratedEnergy"> <el-input v-model="dataForm.ratedEnergy" placeholder="额定能量"></el-input> </el-form-item> <el-form-item label="电池箱数" prop="batteryQuantity"> <el-input v-model="dataForm.batteryQuantity" placeholder="电池箱数"></el-input> </el-form-item> <el-form-item label="电池厂商" prop="batteryFirm"> <el-input v-model="dataForm.batteryFirm" placeholder="电池厂商"></el-input> </el-form-item> <el-form-item label="激活日期" prop="activationDate"> <el-date-picker v-model="dataForm.activationDate" type="date" placeholder="选择日期" disabled style="width: 100%"> </el-date-picker> </el-form-item> <el-form-item label="BMS编号" prop="bmsNum"> <el-input v-model="dataForm.bmsNum" placeholder="BMS编号"></el-input> </el-form-item> <el-form-item label="电芯编码" prop="batteryCellNum"> <el-input v-model="dataForm.batteryCellNum" placeholder="电芯编码"></el-input> </el-form-item> <el-form-item label="标称容量(Ah)" prop="nominalCapacity"> <el-input v-model="dataForm.nominalCapacity" placeholder="标称容量"></el-input> </el-form-item> </div> </el-col> <!-- 第三列:状态与位置信息 --> <el-col :span="8"> <div class="form-section"> <div class="section-header"> <i class="el-icon-location-information"></i> <span>状态与位置</span> </div> <el-form-item label="系统状态" prop="sysStatus"> <el-select v-model="dataForm.sysStatus" placeholder="系统状态"> <el-option v-for="item in sysStatuses" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </el-form-item> <el-form-item label="警报状态" prop="alarmStatus"> <el-select v-model="dataForm.alarmStatus" placeholder="报警状态"> <el-option v-for="item in alarmStatuses" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </el-form-item> <el-form-item label="所属项目" prop="projectId"> <el-select v-model="dataForm.projectId" placeholder="所属项目"> <el-option v-for="item in projectIds" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </el-form-item> <el-form-item label="地理位置" prop="cityId"> <div class="location-selectors"> <el-select v-model="dataForm.proviceId" placeholder="省份" @change="handleChange" style="margin-bottom: 10px"> <el-option v-for="item in provices" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> <el-select v-model="dataForm.cityId" placeholder="城市" @change="handleChange2" style="margin-bottom: 10px"> <el-option v-for="item in cities" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> <el-select v-model="dataForm.districtId" placeholder="区县"> <el-option v-for="item in districts" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </div> </el-form-item> <div class="section-header" style="margin-top: 20px"> <i class="el-icon-cpu"></i> <span>设备信息</span> </div> <el-form-item label="软件版本" prop="softVersion"> <el-input v-model="dataForm.softVersion" placeholder="软件版本"></el-input> </el-form-item> <el-form-item label="硬件版本" prop="hardwareVersion"> <el-input v-model="dataForm.hardwareVersion" placeholder="硬件版本"></el-input> </el-form-item> <el-form-item label="动力类型" prop="powerTypeId"> <el-select v-model="dataForm.powerTypeId" placeholder="选择动力类型"> <el-option v-for="item in powerTypeIds" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </el-form-item> <el-form-item label="二维码" prop="qrCode"> <el-input v-model="dataForm.qrCode" placeholder="二维码"></el-input> </el-form-item> </div> </el-col> </el-row> <!-- 底部:网络信息 --> <div class="form-section network-section"> <div class="section-header"> <i class="el-icon-connection"></i> <span>网络信息</span> </div> <el-row :gutter="20"> <el-col :span="6"> <el-form-item label="SCID" prop="scid"> <el-input v-model="dataForm.scid" placeholder="SCID"></el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="PLMN" prop="plmn"> <el-input v-model="dataForm.plmn" placeholder="PLMN"></el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="LAC" prop="lac"> <el-input v-model="dataForm.lac" placeholder="LAC"></el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="CID" prop="cid"> <el-input v-model="dataForm.cid" placeholder="CID"></el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="IMEI" prop="imei"> <el-input v-model="dataForm.imei" placeholder="IMEI"></el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="ICCID" prop="iccid"> <el-input v-model="dataForm.iccid" placeholder="ICCID"></el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="CCID" prop="ccid"> <el-input v-model="dataForm.ccid" placeholder="CCID"></el-input> </el-form-item> </el-col> </el-row> </div> </el-form> <span slot="footer" class="dialog-footer"> <el-button @click="visible = false">取消</el-button> <el-button type="primary" @click="dataFormSubmit()">确定</el-button> </span> </el-dialog> </template> <script> export default { data () { return { visible: false, dataForm: { id: 0, hwid: &#39;&#39;, batteryCellId: [], batteryKind: [], batteryCellPackageId: [], batteryBunchs: &#39;&#39;, batteryUnions: &#39;&#39;, singleBatteryVoltage: &#39;&#39;, ratedTotalPressure: &#39;&#39;, ratedCurrent: &#39;&#39;, ratedCapacity: &#39;&#39;, ratedEnergy: &#39;&#39;, batteryQuantity: &#39;&#39;, batteryFirm: &#39;&#39;, activationDate: &#39;&#39;, bmsNum: &#39;&#39;, batteryCellNum: &#39;&#39;, batteryChassisNum: &#39;&#39;, nominalCapacity: &#39;&#39;, sysStatus: &#39;&#39;, alarmStatus: &#39;&#39;, projectId: &#39;&#39;, cityId: &#39;&#39;, softVersion: &#39;&#39;, hardwareVersion: &#39;&#39;, powerTypeId: &#39;&#39;, qrCode: &#39;&#39;, scid: &#39;&#39;, plmn: &#39;&#39;, lac: &#39;&#39;, cid: &#39;&#39;, imei: &#39;&#39;, iccid: &#39;&#39;, ccid: &#39;&#39;, // sysStatus: [], // cityId: [], districtId:[], proviceId:[], // tempproviceId: &#39;&#39;, // softVersion: &#39;&#39;, // alarmStatus: [], // projectId: [], // powerTypeId: [] }, dataRule: { hwid: [ { required: true, message: &#39;电池编号不能为空&#39;, trigger: &#39;blur&#39; } ], batteryCellId: [ { required: true, message: &#39;电芯类型id不能为空&#39;, trigger: &#39;blur&#39; } ], batteryKind: [ { required: true, message: &#39;电池类型id不能为空&#39;, trigger: &#39;blur&#39; } ], batteryCellPackageId: [ { required: true, message: &#39;电芯封装id不能为空&#39;, trigger: &#39;blur&#39; } ], batteryBunchs: [ { required: true, message: &#39;电池串数不能为空&#39;, trigger: &#39;blur&#39; } ], batteryUnions: [ { required: true, message: &#39;电池并数不能为空&#39;, trigger: &#39;blur&#39; } ], singleBatteryVoltage: [ { required: true, message: &#39;单体电压不能为空&#39;, trigger: &#39;blur&#39; } ], ratedTotalPressure: [ { required: true, message: &#39;额定总压不能为空&#39;, trigger: &#39;blur&#39; } ], ratedCurrent: [ { required: true, message: &#39;额定电流不能为空&#39;, trigger: &#39;blur&#39; } ], ratedCapacity: [ { required: true, message: &#39;额定容量不能为空&#39;, trigger: &#39;blur&#39; } ], ratedEnergy: [ { required: true, message: &#39;额定能量不能为空&#39;, trigger: &#39;blur&#39; } ], batteryQuantity: [ { required: true, message: &#39;电池箱数不能为空&#39;, trigger: &#39;blur&#39; } ], batteryFirm: [ { required: true, message: &#39;电池厂商不能为空&#39;, trigger: &#39;blur&#39; } ], activationDate: [ { required: true, message: &#39;激活日期不能为空&#39;, trigger: &#39;blur&#39; } ], bmsNum: [ { required: true, message: &#39;BMS编号不能为空&#39;, trigger: &#39;blur&#39; } ], batteryCellNum: [ { required: true, message: &#39;电芯编码不能为空&#39;, trigger: &#39;blur&#39; } ], // batteryChassisNum: [ // { required: true, message: &#39;底盘编号不能为空&#39;, trigger: &#39;blur&#39; } // ], nominalCapacity: [ { required: true, message: &#39;标称容量不能为空&#39;, trigger: &#39;blur&#39; } ], capacity: [ { required: true, message: &#39;容量不能为空&#39;, trigger: &#39;blur&#39; } ], // createTime: [ // { required: true, message: &#39;不能为空&#39;, trigger: &#39;blur&#39; } // ], // updateTime: [ // { required: true, message: &#39;更新时间不能为空&#39;, trigger: &#39;blur&#39; } // ] sysStatus: [ { required: true, message: &#39;系统状态不能为空&#39;, trigger: &#39;blur&#39; } ], // alarmStatus: [ // { required: true, message: &#39;警报状态不能为空&#39;, trigger: &#39;blur&#39; } // ], // projectId: [ // { required: true, message: &#39;所属项目不能为空&#39;, trigger: &#39;blur&#39; } // ], // cityId: [ // { required: true, message: &#39;城市不能为空&#39;, trigger: &#39;blur&#39; } // ], softVersion: [ { required: true, message: &#39;软件版本不能为空&#39;, trigger: &#39;blur&#39; } ], // hardwareVersion: [ // { required: true, message: &#39;硬件版本不能为空&#39;, trigger: &#39;blur&#39; } // ], powerTypeId: [ { required: true, message: &#39;动力类型不能为空&#39;, trigger: &#39;blur&#39; } ], // qrCode: [ // { required: true, message: &#39;二维码不能为空&#39;, trigger: &#39;blur&#39; } // ], // scid: [ // { required: true, message: &#39;scid不能为空&#39;, trigger: &#39;blur&#39; } // ], // plmn: [ // { required: true, message: &#39;plmn不能为空&#39;, trigger: &#39;blur&#39; } // ], // lac: [ // { required: true, message: &#39;lac不能为空&#39;, trigger: &#39;blur&#39; } // ], // cid: [ // { required: true, message: &#39;cid不能为空&#39;, trigger: &#39;blur&#39; } // ], // imei: [ // { required: true, message: &#39;imei不能为空&#39;, trigger: &#39;blur&#39; } // ], // iccid: [ // { required: true, message: &#39;iccid不能为空&#39;, trigger: &#39;blur&#39; } // ], // ccid: [ // { required: true, message: &#39;ccid不能为空&#39;, trigger: &#39;blur&#39; } // ] }, batteryCellIds: [], batteryKinds:[{ value: 0, label: &#39;运营&#39; },{ value: 1, label: &#39;售后&#39; },{ value: 2, label: &#39;内测&#39; },{ value: 3, label: &#39;报废&#39; }], batteryCellPackageIds: [], provices: [{ value: &#39;选项1&#39;, label: &#39;黄金糕&#39; }, { value: &#39;选项2&#39;, label: &#39;双皮奶&#39;, disabled: true }, { value: &#39;选项3&#39;, label: &#39;蚵仔煎&#39; }, { value: &#39;选项4&#39;, label: &#39;龙须面&#39; }, { value: &#39;选项5&#39;, label: &#39;北京烤鸭&#39; }], value:&#39;&#39;, cities: [], districts: [], sysStatuses: [], powerTypeIds: [], projectIds:[], customIds:[], alarmStatuses:[] } }, methods: { init (id) { this.dataForm.id = id || 0 this.visible = true this.$nextTick(() => { this.$refs[&#39;dataForm&#39;].resetFields() if (this.dataForm.id) { this.$http({ url: this.$http.adornUrl(`/battery/bmsbatteryinfo/info/${this.dataForm.id}`), method: &#39;get&#39;, params: this.$http.adornParams() }).then(({data}) => { if (data && data.code === 0) { this.provices = data.data.provices this.cities = data.data.cities this.districts = data.data.districts this.sysStatuses = data.data.sysStatuses this.powerTypeIds = data.data.powers this.alarmStatuses = data.data.alarmStatuses this.projectIds = data.data.projectIds this.batteryCellIds = data.data.batteryCellIds this.batteryCellPackageIds = data.data.batteryCellPackageIds const socitem = data.data.bmsBatteryInfo // this.dataForm.batteryNum = data.bmsBatteryInfo.batteryNum this.dataForm.hwid = socitem.hwid this.dataForm.batteryCellId = socitem.batteryCellId this.dataForm.batteryKind = socitem.batteryKind this.dataForm.batteryCellPackageId = socitem.batteryCellPackageId this.dataForm.batteryBunchs = socitem.batteryBunchs this.dataForm.batteryUnions = socitem.batteryUnions this.dataForm.singleBatteryVoltage = socitem.singleBatteryVoltage this.dataForm.ratedTotalPressure = socitem.ratedTotalPressure this.dataForm.ratedCurrent = socitem.ratedCurrent this.dataForm.ratedCapacity = socitem.ratedCapacity this.dataForm.ratedEnergy = socitem.ratedEnergy this.dataForm.batteryQuantity = socitem.batteryQuantity this.dataForm.batteryFirm = socitem.batteryFirm this.dataForm.activationDate = socitem.activationDate this.dataForm.bmsNum = socitem.bmsNum this.dataForm.batteryCellNum = socitem.batteryCellNum // this.dataForm.batteryChassisNum = socitem.batteryChassisNum this.dataForm.nominalCapacity = socitem.nominalCapacity // this.dataForm.capacity = socitem.capacity this.dataForm.sysStatus = socitem.sysStatus this.dataForm.alarmStatus = socitem.alarmStatus this.dataForm.projectId = socitem.projectId this.dataForm.cityId = socitem.cityId this.dataForm.districtId = socitem.districtId this.dataForm.proviceId = socitem.proviceId this.dataForm.softVersion = socitem.softVersion this.dataForm.hardwareVersion = socitem.hardwareVersion this.dataForm.powerTypeId = socitem.powerTypeId this.dataForm.qrCode = socitem.qrCode this.dataForm.scid = socitem.scid this.dataForm.plmn = socitem.plmn this.dataForm.lac = socitem.lac this.dataForm.cid = socitem.cid this.dataForm.imei = socitem.imei this.dataForm.iccid = socitem.iccid this.dataForm.ccid = socitem.ccid this.dataForm.createTime = socitem.createTime this.dataForm.updateTime = socitem.updateTime } }) }else{ this.$http({ url: this.$http.adornUrl(`/battery/bmsbatteryinfo/getmenus`), method: &#39;get&#39;, params: this.$http.adornParams() }).then(({data}) => { if (data && data.code === 0) { this.provices = data.data.provices // this.cities = data.data.cities // this.districts = data.data.districts this.sysStatuses = data.data.sysStatuses this.powerTypeIds = data.data.powers this.alarmStatuses = data.data.alarmStatuses this.projectIds = data.data.projectIds this.batteryCellIds = data.data.batteryCellIds this.batteryCellPackageIds = data.data.batteryCellPackageIds } }) } }) }, mouseblur() { // alert("鼠标失去焦点,检查HWID是否重复"); }, handleChange(value) { // alert("鼠标"+value); this.dataForm.cityId = &#39;&#39; this.dataForm.districtId = &#39;&#39; this.getCities(value, 2) }, handleChange2(value) { // alert("鼠标===="+value); this.dataForm.districtId = &#39;&#39; this.getCities(value, 3) }, getCities(pid, level) { this.$http({ url: this.$http.adornUrl(&#39;/battery/bmsdistrictarea/getCitiesByPid&#39;), method: &#39;get&#39;, params: this.$http.adornParams({ &#39;level&#39;: level, &#39;pid&#39;: pid }) }).then(({data}) => { if (data && data.code === 0) { if(level==1){ this.provices = data.data } if(level==2){ this.cities = data.data } if(level==3){ this.districts = data.data } } else { this.provices = [] this.cities = [] this.districts = [] } }) }, // 表单提交 dataFormSubmit () { this.$refs[&#39;dataForm&#39;].validate((valid) => { if (valid) { this.$http({ url: this.$http.adornUrl(`/battery/bmsbatteryinfo/${!this.dataForm.id ? &#39;save&#39; : &#39;update&#39;}`), method: &#39;post&#39;, data: this.$http.adornData({ &#39;id&#39;: this.dataForm.id || undefined, &#39;hwid&#39;: this.dataForm.hwid, &#39;batteryCellId&#39;: this.dataForm.batteryCellId, &#39;batteryKind&#39;: this.dataForm.batteryKind, &#39;batteryCellPackageId&#39;: this.dataForm.batteryCellPackageId, &#39;batteryBunchs&#39;: this.dataForm.batteryBunchs, &#39;batteryUnions&#39;: this.dataForm.batteryUnions, &#39;singleBatteryVoltage&#39;: this.dataForm.singleBatteryVoltage, &#39;ratedTotalPressure&#39;: this.dataForm.ratedTotalPressure, &#39;ratedCurrent&#39;: this.dataForm.ratedCurrent, &#39;ratedCapacity&#39;: this.dataForm.ratedCapacity, &#39;ratedEnergy&#39;: this.dataForm.ratedEnergy, &#39;batteryQuantity&#39;: this.dataForm.batteryQuantity, &#39;batteryFirm&#39;: this.dataForm.batteryFirm, // &#39;activationDate&#39;: this.dataForm.activationDate, &#39;activateDateFormat&#39;: this.dataForm.activationDate, &#39;bmsNum&#39;: this.dataForm.bmsNum, &#39;batteryCellNum&#39;: this.dataForm.batteryCellNum, // &#39;batteryChassisNum&#39;: this.dataForm.batteryChassisNum, &#39;nominalCapacity&#39;: this.dataForm.nominalCapacity, // &#39;capacity&#39;: this.dataForm.capacity, &#39;sysStatus&#39;: this.dataForm.sysStatus, &#39;alarmStatus&#39;: this.dataForm.alarmStatus, &#39;projectId&#39;: this.dataForm.projectId, &#39;cityId&#39;: this.dataForm.cityId, &#39;districtId&#39;: this.dataForm.districtId, &#39;proviceId&#39;: this.dataForm.proviceId, &#39;softVersion&#39;: this.dataForm.softVersion, &#39;hardwareVersion&#39;: this.dataForm.hardwareVersion, &#39;powerTypeId&#39;: this.dataForm.powerTypeId, &#39;qrCode&#39;: this.dataForm.qrCode, &#39;scid&#39;: this.dataForm.scid, &#39;plmn&#39;: this.dataForm.plmn, &#39;lac&#39;: this.dataForm.lac, &#39;cid&#39;: this.dataForm.cid, &#39;imei&#39;: this.dataForm.imei, &#39;iccid&#39;: this.dataForm.iccid, &#39;ccid&#39;: this.dataForm.ccid, &#39;createTime&#39;: this.dataForm.createTime, &#39;updateTime&#39;: this.dataForm.updateTime }) }).then(({data}) => { if (data && data.code === 0) { this.$message({ message: &#39;操作成功&#39;, type: &#39;success&#39;, duration: 1500, onClose: () => { this.visible = false this.$emit(&#39;refreshDataList&#39;) } }) } else { this.$message.error(data.msg) } }) } }) } } } </script> <style scoped> /* 添加样式优化 */ .multi-column-dialog { max-width: 1400px; } .multi-column-form { max-height: 70vh; overflow-y: auto; padding: 10px 15px; } .form-section { background: #f8f9fc; border-radius: 8px; padding: 15px 20px; margin-bottom: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.05); border: 1px solid #ebeef5; } .section-header { display: flex; align-items: center; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid #ebeef5; color: #409EFF; font-weight: bold; } .section-header i { margin-right: 8px; font-size: 18px; } .network-section { margin-top: 20px; } .location-selectors { display: flex; flex-direction: column; } .el-form-item { margin-bottom: 18px; } .el-select, .el-input { width: 100%; } /* 响应式调整 */ @media (max-width: 1200px) { .el-col { width: 100% !important; } .multi-column-dialog { width: 95% !important; } } </style> 使用el-tab-pan优化
07-23
<template> <div class="app-container"> <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px" > <el-form-item label="Season No" prop="seasonNo" label-width="140"> <el-input v-model="queryParams.seasonNo" placeholder="please input" clearable @keyup.enter="handleQueryTest" /> </el-form-item> <el-form-item label="Colorwayid" prop="colorwayid" label-width="140"> <el-input v-model="queryParams.colorwayid" placeholder="please input" clearable @keyup.enter="handleQueryTest" /> </el-form-item> <el-form-item label="Model No" prop="modelNo" label-width="140"> <el-input v-model="queryParams.modelNo" placeholder="please input" clearable @keyup.enter="handleQueryTest" /> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQuery" >搜索</el-button > <el-button icon="Refresh" @click="resetQuery">重置</el-button> </el-form-item> <el-form-item> <el-button type="primary" plain @click="handleTest">新增</el-button> </el-form-item> </el-form> <el-table v-loading="loading" :data="qsList"> <el-table-column label="seasonNo" align="center" prop="seasonNo"> </el-table-column> <el-table-column label="stage" align="center" prop="stage"> </el-table-column> <el-table-column label="modelNo" align="center" prop="modelNo"> </el-table-column> <el-table-column label="colorwayid" align="center" prop="colorwayid"> </el-table-column> <el-table-column label="pattern" align="center" prop="pattern"> </el-table-column> <el-table-column label="firstsource" align="center" prop="firstsource"> </el-table-column> <el-table-column label="Operate" align="center" class-name="small-padding fixed-width" > <template #default="scope"> <el-tooltip content="Add" placement="top"> <el-button link type="primary" icon="Plus" @click="handleCreate(scope.row)" ></el-button> </el-tooltip> <el-tooltip content="Delete" placement="top"> <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" ></el-button> </el-tooltip> </template> </el-table-column> </el-table> <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" /> </div> <el-dialog title="ADD" v-model="testDialog" width="1600px" append-to-body> <div> <el-form :model="queryParams" ref="testRef" :inline="true" label-width="108px" > <el-form-item label="seasonNo" prop="seasonNo" label-width="140"> <el-input v-model="queryParams.seasonNo" placeholder="please input" clearable @keyup.enter="handleQueryTest" /> </el-form-item> <el-form-item label="colorwayid" prop="colorwayid" label-width="140"> <el-input v-model="queryParams.colorwayid" placeholder="please input" clearable @keyup.enter="handleQueryTest" /> </el-form-item> <el-form-item label="modelNo" prop="modelNo" label-width="140"> <el-input v-model="queryParams.modelNo" placeholder="please input" clearable @keyup.enter="handleQueryTest" /> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQueryTest" >Search</el-button > <el-button icon="Refresh" @click="resetQueryTest">Reset</el-button> </el-form-item> </el-form> <el-table v-loading="loading" :data="ptrList"> <el-table-column label="seasonNo" align="center" prop="seasonNo"> </el-table-column> <el-table-column label="stage" align="center" prop="stage"> </el-table-column> <el-table-column label="modelNo" align="center" prop="modelNo"> </el-table-column> <el-table-column label="Colorway Name" align="center" prop="colorwayid"> </el-table-column> <el-table-column label="pattern" align="center" prop="pattern"> </el-table-column> <el-table-column label="firstsource" align="center" prop="firstsource"> </el-table-column> <el-table-column label="Operate" align="center" class-name="small-padding fixed-width" > <template #default="scope"> <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" ></el-button> </template> </el-table-column> </el-table> <pagination v-show="totalTest > 0" :total="totalTest" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getTestList" /> </div> </el-dialog> <el-dialog title="创建" v-model="createDialog" width="1800px" append-to-body> <div> <el-tabs v-model="activeTab" type="card"> <el-tab-pane v-for="(item, index) in mainList" :key="index" :label="getTabLabel(item)" :name="index.toString()" > <!-- 每个标签页使用独立的表单和数据结构 --> <div v-if="currentTabData[index]"> <!-- 基本信息区域(只读) --> <el-card header="基本信息" style="margin-bottom: 15px"> <el-form :model="currentTabData[index].baseInfo" label-width="120px" :inline="true" > <el-form-item label="Dev Style Name"> <el-input v-model="currentTabData[index].baseInfo.modelNo" readonly style="width: 100px" class="readonly-input" /> <el-input v-model="currentTabData[index].baseInfo.modelName" readonly style="width: 150px" class="readonly-input" /> </el-form-item> <el-form-item label="Color Way Name" label-width="125"> <el-input v-model="currentTabData[index].baseInfo.colorwayid" readonly style="width: 100px" class="readonly-input" /> <el-input v-model="currentTabData[index].baseInfo.colorwayname" readonly style="width: 400px" class="readonly-input" /> <el-input v-model="currentTabData[index].baseInfo.bomid" readonly style="width: 100px" class="readonly-input" /> </el-form-item> <el-form-item label="Stage" label-width="60"> <el-input v-model="currentTabData[index].baseInfo.stage" readonly class="readonly-input" style="width: 120px" /> </el-form-item> <el-form-item label="DPA/STYLE" prop="prodCd" label-width="100"> <el-input v-model="currentTabData[index].baseInfo.prodCd" readonly class="readonly-input" /> </el-form-item> <el-form-item label="Season"> <el-input v-model="currentTabData[index].baseInfo.seasonNo" readonly class="readonly-input" style="width: 100px" /> </el-form-item> <el-form-item label="Version" prop="pfcVersion" label-width="80" > <el-input v-model="currentTabData[index].baseInfo.pfcVersion" readonly style="width: 120px" class="readonly-input" /> </el-form-item> <el-form-item label="Tool Code" prop="pattern" label-width="100" > <el-input v-model="currentTabData[index].baseInfo.pattern" readonly class="readonly-input" /> </el-form-item> <el-form-item label="PFC手册号" prop="pfcNo" label-width="100"> <el-input v-model="currentTabData[index].baseInfo.pfcNo" readonly style="width: 100px" class="readonly-input" /> </el-form-item> <el-form-item label="Page Number"> <el-input v-model="currentTabData[index].baseInfo.pageNumber" readonly class="readonly-input" style="width: 80px" /> <el-input v-model="currentTabData[index].baseInfo.stepno" readonly class="readonly-input" style="width: 80px" /> </el-form-item> <el-form-item label="鞋码类型" prop="sizeType" label-width="100" > <el-input v-model="currentTabData[index].baseInfo.sizeType" readonly class="readonly-input" /> </el-form-item> </el-form> <el-form :model="currentTabData[index].formData" :rules="getTabRules(index)" label-width="120px" > <el-row> <el-col :span="8"> <el-form-item label="STYLE NO" prop="styleNo"> <el-input v-model="currentTabData[index].formData.styleNo" placeholder="Please input" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="DPA" prop="dpa"> <el-input v-model="currentTabData[index].formData.dpa" placeholder="Please input" /> </el-form-item> </el-col> <el-col :span="4"> <el-form-item label="TD CODE" prop="tdCode"> <el-input v-model="currentTabData[index].formData.tdCode" placeholder="Please input" /> </el-form-item> </el-col> <el-col :span="4"> <el-form-item label="FACTORY" prop="factory"> <el-input v-model="currentTabData[index].formData.factory" placeholder="Please input" /> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="8"> <el-form-item label="LAB TEST" prop="labTest"> <el-input v-model="currentTabData[index].formData.labTest" placeholder="Please input" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="APPROVED BY" prop="approvedBy" label-width="130" > <el-input v-model="currentTabData[index].formData.approvedBy" placeholder="Please input" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="APPROVED DATE" prop="approvedDate" label-width="180" > <el-date-picker v-model="currentTabData[index].formData.approvedDate" type="date" placeholder="选择日期" style="width: 50%" /> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="16"> <el-form-item label="具体描述" prop="description"> <el-input v-model="currentTabData[index].formData.description" placeholder="Please input" type="textarea" :rows="2" /> </el-form-item> </el-col> </el-row> </el-form> </el-card> <!-- 可编辑的表单区域 --> <el-card header="编辑信息" style="margin-bottom: 15px"> <!-- 动态数据行区域(根据标签页类型显示不同的字段) --> <div style="margin-top: 20px"> <!-- 将模板选择器和列表标题放在同一行 --> <div style=" display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; " > <!-- 左侧:模板选择器 --> <div style="display: flex; align-items: center; flex: 1"> <span style=" font-weight: bold; margin-right: 10px; min-width: 50px; " >测试用例列表</span > <el-cascader v-model="currentTabData[index].selectedTemplate" :options="currentTabData[index].templateOptions" :props="getCascaderProps(index)" placeholder="请选择测试用例模板" clearable filterable style="width: 350px; margin-right: 10px" @change="handleTemplateSelect(index)" popper-class="custom-cascader" /> </div> </div> <el-table :data="currentTabData[index].dataRows" border v-loading="currentTabData[index].loading" > <!-- 根据页面类型动态显示列 --> <el-table-column v-for="column in getTableColumns(index)" :key="column.prop" :label="column.label" :prop="column.prop" :width="column.width" > <template #default="scope"> <el-input v-model="scope.row[column.prop]" size="small" /> </template> </el-table-column> <el-table-column label="Operate" width="80"> <template #default="scope"> <el-button link type="danger" size="small" @click="removeDataRow(index, scope.$index)" >delete</el-button > </template> </el-table-column> </el-table> </div> </el-card> <el-card header="鞋图上传" style="margin-bottom: 20px"> <el-upload v-model:file-list="currentTabData[index].fileList" :action="uploadUrl.url" list-type="picture-card" :multiple="true" :on-preview="(file) => handlePictureCardPreview(file, index)" :on-remove="(file) => handleRemove(file, index)" :on-success=" (response, file, fileList) => handleUploadSuccess(index, response, file, fileList) " :on-error="handleUploadError" :before-upload="(file) => beforeUpload(file, index)" :headers="uploadUrl.headers" :data="getUploadData(index)" :auto-upload="true" accept=".jpg,.jpeg,.png,.gif" > <el-icon><Plus /></el-icon> </el-upload> <el-dialog v-model="currentTabData[index].dialogVisible" style="width: 80%; max-width: 900px; height: 700px" > <img w-full :src="currentTabData[index].dialogImageUrl" alt="Preview Image" style=" max-width: 100%; max-height: 100%; display: block; margin: 0 auto; " /> </el-dialog> </el-card> </div> </el-tab-pane> </el-tabs> <!-- 底部操作按钮 --> <div style="text-align: center; margin-top: 20px"> <!-- <el-button type="primary" @click="handleSaveAll">保存所有</el-button> --> <el-button type="success" @click="handleSaveCurrent" >保存当前</el-button > <el-button @click="createDialog = false">取消</el-button> </div> </div> </el-dialog> </template> <script setup name="User"> import { ptrInfo, addQualityStand, qsInfo, getQsMain, getTemplateTree, saveQualityStandards, getSavedQualityStandards, uploadImages, getImages, deleteImage, delQualityStand, } from "@/api/quality/standard/quasd.js"; import { getSrc } from "@/utils/interceptSrc"; import { getToken } from "@/utils/auth"; const { proxy } = getCurrentInstance(); const qsList = ref([]); const ptrList = ref([]); const mainList = ref([]); const loading = ref(true); const showSearch = ref(true); const testDialog = ref(false); const createDialog = ref(false); const total = ref(0); const totalTest = ref(0); const activeTab = ref("0"); // 为每个标签页存储独立的数据 const currentTabData = ref({}); const data = reactive({ queryParams: { pageNum: 1, pageSize: 10, stage: null, modelNo: null, colorwayid: null, seasonNo: null, pfcNo: null, pattern: null, firstsource: null, pageNumber: null, stepno: null, pfcCaption: null, }, rules: { styleNo: [{ required: true, message: "STYLE NO不能为空", trigger: "blur" }], dpa: [{ required: true, message: "DPA不能为空", trigger: "blur" }], tdCode: [{ required: true, message: "TD CODE不能为空", trigger: "blur" }], factory: [{ required: true, message: "FACTORY不能为空", trigger: "blur" }], labTest: [{ required: true, message: "LAB TEST不能为空", trigger: "blur" }], approvedBy: [ { required: true, message: "APPROVED BY不能为空", trigger: "blur" }, ], approvedDate: [ { required: true, message: "APPROVED DATE不能为空", trigger: "blur" }, ], // 其他验证规则... }, }); const { queryParams, rules } = toRefs(data); // 在setup顶部定义上传配置 const uploadUrl = reactive({ headers: { Authorization: "Bearer " + getToken() }, url: process.env.VITE_APP_BASE_API + "/quality/standard/images/upload", }); // 初始化标签页数据 async function initTabData(tabIndex, sourceData) { currentTabData.value[tabIndex] = { baseInfo: { ...sourceData }, formData: { styleNo: "", dpa: "", tdCode: "", factory: "", labTest: "", approvedBy: "", approvedDate: "", description: "", }, dataRows: [], templateOptions: [], selectedTemplate: [], currentTemplateData: null, loading: false, // 添加加载状态 fileList: [], // 图片列表 dialogVisible: false, // 预览对话框显示状态 dialogImageUrl: "", // 预览图片URL }; // 加载模板数据 await loadTemplateOptions(tabIndex, sourceData.pageNumber); // 加载已保存的测试用例数据 await loadSavedDataRows(tabIndex, sourceData.pfcNo, sourceData.pageNumber); await loadImages(tabIndex, sourceData.pfcNo, sourceData.pageNumber); } // 新增:加载图片函数 async function loadImages(tabIndex, pfcNo, pageNumber) { try { const response = await getImages(pfcNo, pageNumber); const images = response.data || []; // 转换为el-upload需要的格式 currentTabData.value[tabIndex].fileList = images.map((image) => ({ uid: image.id, // 使用图片的唯一标识 name: image.originalName, url: getSrc(image.filePath), // 确保getSrc能正确生成图片URL status: "success", response: image, // 保留原始数据,删除时可能会用到 })); } catch (error) { console.error("加载图片失败:", error); proxy.$modal.msgError("加载图片失败"); } } // 获取上传参数(当前标签页的pfcNo和pageNumber) function getUploadData(tabIndex) { const baseInfo = currentTabData.value[tabIndex].baseInfo; return { pfcNo: baseInfo.pfcNo, pageNumber: baseInfo.pageNumber, }; } // 图片预览处理 function handlePictureCardPreview(file, tabIndex) { currentTabData.value[tabIndex].dialogImageUrl = file.url; currentTabData.value[tabIndex].dialogVisible = true; } // 新增:删除图片处理 async function handleRemove(file, tabIndex) { try { if (file.status == "success") { // 已上传的图片,调用删除接口 await deleteImage(file.response.id); proxy.$modal.msgSuccess("删除成功"); } // 从列表中移除 const index = currentTabData.value[tabIndex].fileList.findIndex( (item) => item.uid == file.uid ); if (index !== -1) { currentTabData.value[tabIndex].fileList.splice(index, 1); } } catch (error) { console.error("删除失败:", error); proxy.$modal.msgError("删除失败"); } } // 上传成功处理 function handleUploadSuccess(tabIndex, response, file, fileList) { if (response.code == 200) { proxy.$modal.msgSuccess(response.msg); // 更新文件列表(因为后端可能返回了新的URL等信息,但这里我们不需要额外处理,因为已经显示成功) // 如果需要,可以更新fileList中的某个文件信息,但通常不需要,因为我们的fileList已经绑定了 } else { proxy.$modal.msgError(response.msg || "上传失败"); // 标记为失败,以便显示错误 const index = currentTabData.value[tabIndex].fileList.findIndex( (item) => item.uid === file.uid ); if (index !== -1) { currentTabData.value[tabIndex].fileList[index].status = "fail"; currentTabData.value[tabIndex].fileList.splice(index, 1, { ...currentTabData.value[tabIndex].fileList[index], }); } } } // 上传失败处理 function handleUploadError(error, file, fileList) { console.error("上传失败:", error); proxy.$modal.msgError("上传失败"); } // 上传前验证 function beforeUpload(file, tabIndex) { const isImage = file.type.startsWith("image/"); const isLt5M = file.size / 1024 / 1024 < 10; if (!isImage) { proxy.$modal.msgError("只能上传图片文件!"); return false; } if (!isLt5M) { proxy.$modal.msgError("图片大小不能超过5MB!"); return false; } // 添加到文件列表(因为auto-upload为true,所以会自动上传) // 注意:我们使用v-model绑定fileList,所以不需要手动添加 return true; } // 修改 uploadImagesForTab 函数 async function uploadImagesForTab(tabIndex) { const currentTab = currentTabData.value[tabIndex]; const filesToUpload = currentTab.fileList.filter( (file) => !file.status || file.status !== "success" ); if (filesToUpload.length === 0) return; const formData = new FormData(); // 正确添加字段 - 注意参数名必须与后端@RequestParam一致 formData.append("pfcNo", currentTab.baseInfo.pfcNo); formData.append("pageNumber", currentTab.baseInfo.pageNumber); // 正确添加文件数组 - 使用相同的key &#39;files&#39; filesToUpload.forEach((file, index) => { formData.append("file", file.raw || file, file.name); // 第三个参数是文件名 }); try { const response = await uploadImages(formData); proxy.$modal.msgSuccess(response.msg || "图片上传成功"); // 更新已成功上传的文件状态 filesToUpload.forEach((file) => { const listFile = currentTab.fileList.find((f) => f.uid === file.uid); if (listFile) { listFile.status = "success"; } }); } catch (error) { console.error("图片上传失败:", error); proxy.$modal.msgError("图片上传失败: " + (error.message || "网络错误")); } } // 加载已保存的测试用例数据 async function loadSavedDataRows(tabIndex, pfcNo, pageNumber) { const currentTab = currentTabData.value[tabIndex]; try { currentTab.loading = true; const response = await getSavedQualityStandards(pfcNo, pageNumber); const savedData = response.data || []; if (savedData.length > 0) { const currentTab = currentTabData.value[tabIndex]; // 转换已保存数据为表格行格式 currentTab.dataRows = savedData.map((item) => { const row = { templateId: item.templateId, // 保存模板ID // 复制表单数据到当前标签页的表单中(只复制一次,取第一条数据) ...(currentTab.dataRows.length === 0 ? { // 这些字段会被表单数据覆盖,所以这里主要处理测试用例特定字段 } : {}), }; // 根据页面类型设置不同的字段 if (pageNumber == "P42" || pageNumber == "P124") { // P42/P124字段 row.bondTest = item.bondTest || ""; row.testItem = item.testItem || ""; row.pictureRef = item.pictureRef || ""; row.materialOne = item.materialOne || ""; row.materialTwo = item.materialTwo || ""; row.speed = item.speed || ""; row.minSpec = item.minSpec || ""; row.peSpec = item.peSpec || ""; } else if (pageNumber == "P43" || pageNumber == "P125") { // P43/P125字段 row.testMethod = item.testMethod || ""; row.testMethodName = item.testMethodName || ""; row.pictureRef = item.pictureRef || ""; row.flmc = item.flmc || ""; row.minSpec = item.minSpec || ""; if (pageNumber == "P43") { row.testParameter = item.testParameter || ""; } else if (pageNumber == "P125") { row.speed = item.speed || ""; } } // 设置可选字段 row.csan = item.csan || ""; row.pead = item.pead || ""; row.peSpec = item.peSpec || ""; return row; }); // 设置表单数据(取第一条数据的表单信息) if (savedData.length > 0) { const firstItem = savedData[0]; currentTab.formData = { styleNo: firstItem.styleNo || "", dpa: firstItem.dpa || "", tdCode: firstItem.tdCode || "", factory: firstItem.factory || "", labTest: firstItem.labTest || "", approvedBy: firstItem.approvedBy || "", approvedDate: firstItem.approvedDate || "", description: firstItem.description || "", }; } console.log(`标签页 ${tabIndex} 加载了 ${savedData.length} 条已保存数据`); } } catch (error) { console.error("加载已保存数据失败:", error); } finally { currentTab.loading = false; } } // 加载模板选项 async function loadTemplateOptions(tabIndex, pageNumber) { try { const response = await getTemplateTree(pageNumber); currentTabData.value[tabIndex].templateOptions = response.data || []; } catch (error) { console.error("加载模板数据失败:", error); proxy.$modal.msgError("加载测试用例模板失败"); } } // 获取级联选择器配置 function getCascaderProps(tabIndex) { const pageNumber = mainList.value[tabIndex]?.pageNumber; // 所有页面使用相同的配置 return { value: "value", label: "label", children: "children", checkStrictly: false, emitPath: true, expandTrigger: "hover", }; } // 处理模板选择 function handleTemplateSelect(tabIndex) { const currentTab = currentTabData.value[tabIndex]; const selectedValue = currentTab.selectedTemplate; const pageNumber = mainList.value[tabIndex]?.pageNumber; if (selectedValue && selectedValue.length > 0) { // 找到选中的模板数据 const templateData = findTemplateData( currentTab.templateOptions, selectedValue ); if (templateData && templateData.data) { currentTab.currentTemplateData = templateData.data; // 自动添加数据行 addDataRowFromTemplate(tabIndex); } else { // 如果不是叶子节点,不清空选择,让用户继续选择下级 if ( templateData && templateData.children && templateData.children.length > 0 ) { currentTab.currentTemplateData = null; } else { // 没有数据也没有子节点,清空选择 currentTab.selectedTemplate = []; currentTab.currentTemplateData = null; proxy.$modal.msgWarning("请选择有效的测试用例模板"); } } } else { currentTab.currentTemplateData = null; } } // 从模板添加数据行 function addDataRowFromTemplate(tabIndex) { const currentTab = currentTabData.value[tabIndex]; if (currentTab.currentTemplateData) { const columns = getTableColumns(tabIndex); const newRow = {}; // 初始化所有字段为空 columns.forEach((col) => { newRow[col.prop] = ""; }); // 用模板数据填充 fillRowWithTemplateData(newRow, currentTab.currentTemplateData, tabIndex); currentTab.dataRows.push(newRow); // 清空选择器 currentTab.selectedTemplate = []; currentTab.currentTemplateData = null; proxy.$modal.msgSuccess("已从模板添加测试用例"); } } // 在模板树中查找数据 function findTemplateData(options, path) { if (!options || !path || path.length == 0) return null; let currentLevel = options; let result = null; for (let i = 0; i < path.length; i++) { const currentValue = path[i]; const found = currentLevel.find((item) => item.value == currentValue); if (!found) return null; if (i == path.length - 1) { result = found; } else { currentLevel = found.children; } } return result; } // 修改原有的添加数据行方法 function addDataRow(tabIndex) { const currentTab = currentTabData.value[tabIndex]; const columns = getTableColumns(tabIndex); // 创建新行 const newRow = {}; columns.forEach((col) => { newRow[col.prop] = ""; }); currentTab.dataRows.push(newRow); proxy.$modal.msgSuccess("已添加空白的测试用例行"); } // 用模板数据填充行 function fillRowWithTemplateData(row, templateData, tabIndex) { const pageNumber = mainList.value[tabIndex]?.pageNumber; // 保存模板ID,用于后续保存操作 row.templateId = templateData.id; if (pageNumber == "P42" || pageNumber == "P124") { // P42/P124模板数据映射 const bondingData = templateData; // 映射所有字段 row.bondTest = bondingData.bondTest || ""; row.testItem = bondingData.testItem || ""; row.pictureRef = bondingData.pictureRef || ""; row.materialOne = bondingData.materialOne || ""; row.materialTwo = bondingData.materialTwo || ""; row.speed = bondingData.speed || ""; row.minSpec = bondingData.minSpec || ""; row.peSpec = bondingData.peSpec || ""; row.csan = bondingData.csan || ""; row.pead = bondingData.pead || ""; } else if (pageNumber == "P43") { // P43模板数据映射 const customData = templateData; row.testMethod = customData.testMethod || ""; row.testMethodName = customData.testMethodName || ""; row.pictureRef = customData.pictureRef || ""; row.flmc = customData.flmc || ""; row.testParameter = customData.testParameter || ""; // P43特有 row.minSpec = customData.minSpec || ""; row.peSpec = customData.peSpec || ""; row.csan = customData.csan || ""; row.pead = customData.pead || ""; } else if (pageNumber == "P125") { // P125模板数据映射 const customData = templateData; row.testMethod = customData.testMethod || ""; row.testMethodName = customData.testMethodName || ""; row.pictureRef = customData.pictureRef || ""; row.flmc = customData.flmc || ""; row.speed = customData.speed || ""; // P125特有 row.minSpec = customData.minSpec || ""; row.peSpec = customData.peSpec || ""; row.csan = customData.csan || ""; row.pead = customData.pead || ""; } } /** 查询【请填写功能名称】列表 */ function getList() { loading.value = true; qsInfo(queryParams.value).then((response) => { qsList.value = response.rows; total.value = response.total; loading.value = false; }); } function handleTest() { testDialog.value = true; getTestList(); } // 根据页面类型获取表格列配置 function getTableColumns(tabIndex) { const pageNumber = mainList.value[tabIndex]?.pageNumber; // 根据不同的pageNumber返回不同的列配置 switch (pageNumber) { case "P42": // Finished Shoe Bonding页面 return [ { prop: "bondTest", label: "BOND TEST", width: 120 }, { prop: "testItem", label: "TEST ITEM", width: 100 }, { prop: "pictureRef", label: "PICTURE REF.#", width: 130 }, { prop: "materialOne", label: "MATERIAL 1", width: 120 }, { prop: "materialTwo", label: "MATERIAL 2", width: 120 }, { prop: "speed", label: "Speed(mm/min)", width: 150 }, { prop: "minSpec", label: "Min.Spec(kgf/cm)", width: 150 }, { prop: "peSpec", label: "Product Exc.Spec", width: 150 }, { prop: "csan", label: "COMMENT SECTION Approver Name / Product Exception Detail...", width: 250, }, { prop: "pead", label: "Product Exception Approved Date", width: 150 }, ]; case "P43": // Finished Shoe Custom页面 return [ { prop: "testMethod", label: "Nike Test Method #", width: 120 }, { prop: "testMethodName", label: "Nike Test Method Name", width: 130 }, { prop: "pictureRef", label: "PICTURE REF.#", width: 100 }, { prop: "flmc", label: "FOCUSED LOCATION/MATERIAL/COLOR", width: 220 }, { prop: "testParameter", label: "Test Parameter", width: 120 }, // P43特有 { prop: "minSpec", label: "Min.Spec", width: 120 }, { prop: "peSpec", label: "Product Exc.Spec", width: 120 }, { prop: "csan", label: "COMMENT SECTION Approver Name / Product Exception Detail...", width: 250, }, { prop: "pead", label: "Product Exception Approved Date", width: 150 }, ]; case "P124": //Fuse & No Sew Upper return [ { prop: "bondTest", label: "Nike Test Method #", width: 120 }, { prop: "testItem", label: "TEST ITEM", width: 100 }, { prop: "pictureRef", label: "PICTURE REF.#", width: 100 }, { prop: "materialOne", label: "MATERIAL 1", width: 120 }, { prop: "materialTwo", label: "MATERIAL 2", width: 120 }, { prop: "speed", label: "Speed(mm/min)", width: 150 }, { prop: "minSpec", label: "Min.Spec(kgf/cm)", width: 150 }, { prop: "peSpec", label: "Product Exc.Spec", width: 150 }, { prop: "csan", label: "COMMENT SECTION Approver Name / Product Exception Detail...", width: 250, }, { prop: "pead", label: "Product Exception Approved Date", width: 150 }, ]; case "P125": // Sockliner页面 return [ { prop: "testMethod", label: "Nike Test Method #", width: 120 }, { prop: "testMethodName", label: "Nike Test Method Name", width: 130 }, { prop: "pictureRef", label: "PICTURE REF.#", width: 100 }, { prop: "flmc", label: "FOCUSED LOCATION/MATERIAL/COLOR", width: 220 }, { prop: "speed", label: "Speed(mm/min)", width: 150 }, // P125特有 { prop: "minSpec", label: "Min.Spec(kgf/cm)", width: 150 }, { prop: "peSpec", label: "Product Exc.Spec", width: 150 }, { prop: "csan", label: "COMMENT SECTION Approver Name / Product Exception Detail...", width: 250, }, { prop: "pead", label: "Product Exception Approved Date", width: 150 }, ]; default: return []; } } // 获取标签页显示名称 function getTabLabel(item) { return `${item.pfcCaption} (${item.pageNumber})`; } // 删除数据行 function removeDataRow(tabIndex, rowIndex) { currentTabData.value[tabIndex].dataRows.splice(rowIndex, 1); } // 获取对应标签页的验证规则 function getTabRules(tabIndex) { // 可以根据不同的标签页返回不同的验证规则 return data.rules; } function handleDelete(row) { proxy.$modal .confirm( &#39;确认删除该条记录吗?&#39; ) .then(function () { return delQualityStand(row.pfcNo); }) .then(() => { handleQuery(); proxy.$modal.msgSuccess("Delete Successfully"); }) .catch(() => {}); } async function handleCreate(row) { createDialog.value = true; try { const response = await getQsMain(row.pfcNo); mainList.value = response.data; // 为每个标签页初始化独立的数据 for (let index = 0; index < mainList.value.length; index++) { const item = mainList.value[index]; await initTabData(index, item); } // 设置默认激活第一个标签页 if (mainList.value.length > 0) { activeTab.value = "0"; } } catch (error) { console.error("加载数据失败:", error); proxy.$modal.msgError("加载数据失败"); } } // 保存当前标签页 async function handleSaveCurrent() { const currentIndex = parseInt(activeTab.value); const currentData = currentTabData.value[currentIndex]; const baseInfo = currentData.baseInfo; try { // 首先上传新添加的图片 await uploadImagesForTab(currentIndex); // 构建保存数据 const saveDataList = []; // 遍历当前标签页的所有测试用例 for (const dataRow of currentData.dataRows) { const saveData = { pageNumber: baseInfo.pageNumber, // 当前标签页的页码 pfcNo: baseInfo.pfcNo, // PFC手册号 templateId: dataRow.templateId, // 模板树第七层data的id // 其他表单数据 // styleNo: currentData.formData.styleNo, // dpa: currentData.formData.dpa, // tdCode: currentData.formData.tdCode, // factory: currentData.formData.factory, // labTest: currentData.formData.labTest, // approvedBy: currentData.formData.approvedBy, // approvedDate: currentData.formData.approvedDate, // description: currentData.formData.description }; // 添加测试用例数据 // const pageNumber = baseInfo.pageNumber; // if (pageNumber == &#39;P42&#39; || pageNumber == &#39;P124&#39;) { // // P42/P124字段 // saveData.testItem = dataRow.testItem || &#39;&#39;; // saveData.pictureRef = dataRow.pictureRef || &#39;&#39;; // saveData.materialOne = dataRow.materialOne || &#39;&#39;; // saveData.materialTwo = dataRow.materialTwo || &#39;&#39;; // saveData.speed = dataRow.speed || &#39;&#39;; // saveData.minSpec = dataRow.minSpec || &#39;&#39;; // saveData.bondTest = dataRow.bondTest || &#39;&#39;; // } else if (pageNumber == &#39;P43&#39; || pageNumber == &#39;P125&#39;) { // // P43/P125字段 // saveData.testMethod = dataRow.testMethod || &#39;&#39;; // saveData.testMethodName = dataRow.testMethodName || &#39;&#39;; // saveData.pictureRef = dataRow.pictureRef || &#39;&#39;; // saveData.flmc = dataRow.flmc || &#39;&#39;; // saveData.minSpec = dataRow.minSpec || &#39;&#39;; // if (pageNumber == &#39;P43&#39;) { // saveData.testParameter = dataRow.testParameter || &#39;&#39;; // } else if (pageNumber == &#39;P125&#39;) { // saveData.speed = dataRow.speed || &#39;&#39;; // } // } // 如果csan和pead不为空,也添加到保存数据中 if (dataRow.peSpec && dataRow.peSpec.trim() !== "") { saveData.peSpec = dataRow.peSpec; } if (dataRow.csan && dataRow.csan.trim() !== "") { saveData.csan = dataRow.csan; } if (dataRow.pead && dataRow.pead.trim() !== "") { saveData.pead = dataRow.pead; } saveDataList.push(saveData); } console.log("保存数据:", saveDataList); // 调用API保存数据 const response = await saveQualityStandards(saveDataList); proxy.$modal.msgSuccess( `保存 ${mainList.value[currentIndex].pfcCaption} 成功,共保存 ${saveDataList.length} 个测试用例` ); // 保存成功后重新加载数据,确保数据一致性 await loadSavedDataRows(currentIndex, baseInfo.pfcNo, baseInfo.pageNumber); } catch (error) { console.error("保存失败:", error); proxy.$modal.msgError("保存失败: " + (error.message || "未知错误")); } } // 监听弹窗关闭 watch(createDialog, (newVal) => { if (!newVal) { // 关闭弹窗时清理数据 currentTabData.value = {}; mainList.value = []; activeTab.value = "0"; } }); // 保存所有标签页 function handleSaveAll() { console.log("保存所有标签页数据:", currentTabData.value); // 遍历所有标签页数据并保存 Object.keys(currentTabData.value).forEach((index) => { const tabData = currentTabData.value[index]; console.log(`标签页 ${index} 数据:`, tabData); // 调用API保存每个标签页的数据 }); proxy.$modal.msgSuccess("所有数据保存成功"); createDialog.value = false; } function getTestList() { loading.value = true; ptrInfo(queryParams.value).then((response) => { ptrList.value = response.rows; totalTest.value = response.total; loading.value = false; }); } function handleAdd(row) { addQualityStand(row).then((response) => { proxy.$modal.msgSuccess("新增成功"); getList(); }); } /** 搜索按钮操作 */ function handleQuery() { queryParams.value.pageNum = 1; getList(); } function handleQueryTest() { queryParams.value.pageNum = 1; getTestList(); } /** 重置按钮操作 */ function resetQuery() { proxy.resetForm("queryRef"); handleQuery(); } function resetQueryTest() { proxy.resetForm("testRef"); handleQueryTest(); } getList(); </script> <style scoped> /* 为级联选择器添加样式,确保显示完整 */ :deep(.el-cascader) { width: 450px; /* 增加宽度以显示更长的路径 */ margin-right: 10px; } :deep(.el-cascader__dropdown) { max-height: 400px; /* 增加下拉框高度 */ } .readonly-input :deep(.el-input__inner) { background-color: #fff7e6; } /* 为级联选择器的标签添加更好的显示 */ :deep(.el-cascader-node__label) { font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 300px; } /* 模板选择区域样式 */ .template-selector { display: flex; align-items: center; margin-bottom: 15px; padding: 10px; background-color: #f8f9fa; border-radius: 4px; } .template-selector-label { font-weight: bold; margin-right: 10px; min-width: 120px; } .template-selector-hint { margin-left: 10px; color: #666; font-size: 12px; } /* 图片上传样式 */ :deep(.el-upload-list--picture-card .el-upload-list__item) { width: 100px; height: 100px; } :deep(.el-upload--picture-card) { width: 100px; height: 100px; line-height: 100px; } :deep(.el-upload-list--picture-card .el-upload-list__item-thumbnail) { object-fit: contain; } .upload-tip { margin-top: 10px; color: #909399; font-size: 12px; } </style> <style> /* 全局样式(不能加 scoped) */ .custom-cascader { max-height: 400px !important; /* 整体最大高度 */ overflow-y: auto !important; } .custom-cascader .el-cascader-menu { height: 400px !important; /* 每列高度 */ min-height: 300px !important; overflow-y: auto !important; } .custom-cascader .el-cascader-menu__wrap { max-height: 480px !important; /* 滚动区域高度 */ } </style>为什么级联选择器的下拉面板最多只能展示6个选择项
最新发布
10-17
我上面给的代码<template>为什么有两处新增按钮”查询“部分,渲染了两次,有什么区别,为什么这么做:<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 == &#39;task&#39;"> <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 == &#39;engineering&#39;?&#39;projectId&#39;:&#39;taskId&#39;" @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(&#39;查询&#39;)" 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(&#39;批量下载&#39;)" :loading="loading" v-on:click="downloadC()">批量下载</el-button> <el-button v-if="this.$menu.getMenuBus(&#39;导出&#39;)" v-on:click="exportDronePic()">导出</el-button> <el-button v-if="this.$menu.getMenuBus(&#39;数据统计&#39;)" 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: &#39;top-left&#39;, 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: &#39;&#39; }]" 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: &#39;&#39; }]" 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: &#39;&#39; }]" 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: &#39;&#39; }]" 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 &#39;@/api/common&#39; // import dataStatistics from &#39;./dataStatistics&#39; //隐藏 import { deletePic, downloadPic, exportDronePic, getPicFun, getSampleEngineerTree, getSampleTaskTree, getWorkCount } from &#39;@/api/dataManageMent&#39; import moment from "moment"; import { getMajorType, getSysDictionary } from "@/api/publicUrl"; import viewImg from "./viewImg"; import manuallyAnnotated from "./manuallyAnnotated"; import { requestParams, resetAddress } from &#39;@/api/url&#39; import { Loading } from &#39;element-ui&#39; 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:&#39;&#39;, handleEndTime:&#39;&#39;, isMark: "", //是否标注 isArc: "", //是否标注 picType: "", //图片类型 uploadtype: "", //数据来源 taskIds: "", //任务id projectIds: "", //工程id handleFlag: &#39;2&#39;, // handleUser: &#39;&#39;, // 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:&#39;&#39;,//任务搜索 engineeringSearch:&#39;&#39;,//工程搜索 scale: document.documentElement.clientWidth / 1920, // 新增:从子组件移入 // 新增数据统计表格的筛选条件 columnFilters: { handleUser: &#39;&#39;, towerNum: &#39;&#39;, markNum: &#39;&#39;, allNum: &#39;&#39; }, //新增:当前筛选条件 filters: {}, // 新增:字段设置的工具栏配置项 toolbarConfig: { custom: true, // 启用自定义列功能 customStorage: true, // 启用自定义列的本地存储 }, // 相关配置项 columnConfig: { drag: true, // 启用表头左右拖拽排序功能 resizable: true, // 启用拖拽列宽功能 }, columnDragConfig: { trigger: &#39;cell&#39;, 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 || &#39;&#39;; // } 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 = &#39;&#39; // }else{ // this.gcxxList = this.gcxxListAll // this.params.lineName = &#39;&#39; // } // } // _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(&#39;#&#39;,&#39;%23&#39;)) // // 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 = &#39;&#39; _this.taskSearch = &#39;&#39; 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:&#39;&#39;, majorType: _this.params.taskMajor?_this.params.taskMajor:&#39;0&#39;, voltageLevel: val?val.typeValue:&#39;&#39;, }).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: &#39;handleUser&#39;, towerNum: &#39;towerNum&#39;, markNum: &#39;markNum&#39;, allNum: &#39;allNum&#39; }; if (value || value == 0) { let displayValue = value; // 将筛选条件添加到 filterTags的el-tag标签中 this.filterTags.push({ label: column.title, value: Array.isArray(displayValue) ? displayValue.join(&#39;, &#39;) : 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: &#39;companyName&#39;, taskName: &#39;taskName&#39;, workDescribe: &#39;workDescribe&#39;, implementTypeName: &#39;implementType&#39;, taskTypeName: &#39;taskType&#39;, planStateName: &#39;planState&#39;, createUser: &#39;createUser&#39; }; // 清除对应的查询条件 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
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

氷泠

欢迎打赏,您的打赏是我前进的动

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值