Browse Source

fix: 优化升级包管理页面样式,增加设备状态中的历史日志 tab(还需完善)

yanglzh 7 months ago
parent
commit
0d128ece4c

+ 2 - 0
.windsurfrules

@@ -0,0 +1,2 @@
+1. 中文回答
+2. vue3 element-plus

+ 328 - 152
src/views/iot/device/instance/component/chart.vue

@@ -1,180 +1,356 @@
 <template>
-	<div class="system-edit-dic-container">
-		<el-dialog v-model="isShowDialog" :title="data.name + `(${data.key})`" width="850px">
-			<!-- 这里是 echarts 线图 -->
-			<div id="lineChart" ref="chartRef" class="chart-container"></div>
-		</el-dialog>
-	</div>
+  <div class="system-edit-dic-container">
+    <el-dialog v-model="isShowDialog" :title="data.name + `(${data.key})`" width="850px">
+      <!-- 添加 tab 切换 -->
+      <el-tabs v-model="activeTab">
+        <el-tab-pane label="趋势图" name="trend">
+          <!-- 这里是 echarts 线图 -->
+          <div id="lineChart" ref="chartRef" class="chart-container"></div>
+        </el-tab-pane>
+        <el-tab-pane label="历史日志" name="history">
+          <!-- 历史日志数据表格 -->
+          <div class="history-container">
+            <div class="date-picker-container">
+              <el-date-picker v-model="historyDateRange" type="datetimerange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" @change="fetchHistoryData" />
+              <el-button type="primary" @click="exportData">导出</el-button>
+            </div>
+            <el-table :data="historyData" border style="width: 100%" v-loading="historyLoading">
+              <el-table-column prop="dataTime" label="时间" align="center" />
+              <el-table-column prop="dataValue" label="属性值" align="center" />
+              <el-table-column prop="unit" label="数据单位" align="center">
+                <template #default>{{ data.unit }}</template>
+              </el-table-column>
+            </el-table>
+            <div class="pagination-container">
+              <el-pagination
+                v-model:current-page="currentPage"
+                v-model:page-size="pageSize"
+                :page-sizes="[10, 20, 50, 100]"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="totalItems"
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+              />
+            </div>
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+    </el-dialog>
+  </div>
 </template>
 
 <script lang="ts" setup>
-import { ref, onMounted, watch, nextTick } from 'vue'
-import api from '/@/api/device'
-import * as echarts from 'echarts'
+import { ref, reactive, watch, nextTick } from "vue";
+import api from "/@/api/device";
+import * as echarts from "echarts";
+import dayjs from "dayjs";
+import { ElMessage } from "element-plus";
 
-const data = ref({ name: '', key: '' })
-const loading = ref(false)
-const isShowDialog = ref(false)
-const chartRef = ref<HTMLElement | null>(null)
-let chartInstance: echarts.ECharts | null = null
-const lineData = ref([])
+const data = ref({ name: "", key: "", unit: "" });
+const loading = ref(false);
+const isShowDialog = ref(false);
+const chartRef = ref<HTMLElement | null>(null);
+let chartInstance: echarts.ECharts | null = null;
+const lineData = ref([]);
+
+// 新增 Tab 相关状态
+const activeTab = ref("trend");
+const historyData = ref([]);
+const historyLoading = ref(false);
+const historyDateRange = ref([dayjs().subtract(1, "hour").format("YYYY-MM-DD HH:mm:ss"), dayjs().format("YYYY-MM-DD HH:mm:ss")]);
+const currentPage = ref(1);
+const pageSize = ref(10);
+const totalItems = ref(0);
+
+const params = reactive({
+  productKey: "",
+  deviceKey: "",
+  properties: "",
+  dateRange: [dayjs().subtract(1, "hour").format("YYYY-MM-DD HH:mm:ss"), dayjs().format("YYYY-MM-DD HH:mm:ss")],
+});
 
 // 初始化图表
 const initChart = () => {
-	if (chartRef.value) {
-		// 如果已有实例先销毁
-		if (chartInstance) {
-			chartInstance.dispose()
-		}
-		// 创建图表实例
-		chartInstance = echarts.init(chartRef.value)
-		// 设置加载状态
-		if (loading.value) {
-			chartInstance.showLoading()
-		} else {
-			chartInstance.hideLoading()
-		}
-		// 更新图表
-		updateChart()
-	}
-}
+  if (chartRef.value) {
+    // 如果已有实例先销毁
+    if (chartInstance) {
+      chartInstance.dispose();
+    }
+    // 创建图表实例
+    chartInstance = echarts.init(chartRef.value);
+    // 设置加载状态
+    if (loading.value) {
+      chartInstance.showLoading();
+    } else {
+      chartInstance.hideLoading();
+    }
+    // 更新图表
+    updateChart();
+  }
+};
 
 // 更新图表数据
 const updateChart = () => {
-	if (!chartInstance) return
-
-	// 从 lineData 中提取数据
-	const xData = lineData.value.map((item: any) => item.ts?.slice(10)).reverse()
-	const yData = lineData.value.map((item: any) => item.value).reverse()
-
-	// 配置图表选项
-	const option = {
-		tooltip: {
-			trigger: 'axis',
-			formatter: '{b}<br />{a}: {c}',
-		},
-		grid: {
-			top: 15,
-			left: 40,
-			right: 30,
-			bottom: 50, // 增加底部空间,为 dataZoom 留出位置
-			containLabel: true,
-		},
-		dataZoom: [
-			{
-				type: 'slider', // 滑动条型数据区域缩放组件
-				show: true,
-				start: 0,
-				end: 100,
-				height: 20,
-				bottom: 10,
-				borderColor: 'transparent',
-				backgroundColor: '#f5f5f5',
-				fillerColor: 'rgba(167, 183, 204, 0.4)',
-				handleIcon:
-					'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
-				handleSize: '80%',
-				handleStyle: {
-					color: '#fff',
-					shadowBlur: 3,
-					shadowColor: 'rgba(0, 0, 0, 0.6)',
-					shadowOffsetX: 2,
-					shadowOffsetY: 2,
-				},
-			},
-			{
-				type: 'inside', // 内置型数据区域缩放组件,允许鼠标滚轮或触摸板缩放
-				start: 0,
-				end: 100,
-			},
-		],
-		xAxis: {
-			type: 'category',
-			data: xData,
-			axisLabel: {
-				rotate: 0,
-			},
-		},
-		yAxis: {
-			type: 'value',
-		},
-		series: [
-			{
-				name: '数值',
-				type: 'line',
-				data: yData,
-				smooth: true,
-				lineStyle: {
-					width: 2,
-				},
-				symbolSize: 4,
-			},
-		],
-	}
-
-	// 设置图表配置
-	chartInstance.setOption(option)
-}
+  if (!chartInstance) return;
+
+  // 从 lineData 中提取数据
+  const xData = lineData.value.map((item: any) => item.ts?.slice(10)).reverse();
+  const yData = lineData.value.map((item: any) => item.value).reverse();
+
+  // 配置图表选项
+  const option = {
+    tooltip: {
+      trigger: "axis",
+      formatter: "{b}<br />{a}: {c}",
+    },
+    grid: {
+      top: 15,
+      left: 40,
+      right: 30,
+      bottom: 50, // 增加底部空间,为 dataZoom 留出位置
+      containLabel: true,
+    },
+    dataZoom: [
+      {
+        type: "slider", // 滑动条型数据区域缩放组件
+        show: true,
+        start: 0,
+        end: 100,
+        height: 20,
+        bottom: 10,
+        borderColor: "transparent",
+        backgroundColor: "#f5f5f5",
+        fillerColor: "rgba(167, 183, 204, 0.4)",
+        handleIcon: "M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z",
+        handleSize: "80%",
+        handleStyle: {
+          color: "#fff",
+          shadowBlur: 3,
+          shadowColor: "rgba(0, 0, 0, 0.6)",
+          shadowOffsetX: 2,
+          shadowOffsetY: 2,
+        },
+      },
+      {
+        type: "inside", // 内置型数据区域缩放组件,允许鼠标滚轮或触摸板缩放
+        start: 0,
+        end: 100,
+      },
+    ],
+    xAxis: {
+      type: "category",
+      data: xData,
+      axisLabel: {
+        rotate: 0,
+      },
+    },
+    yAxis: {
+      type: "value",
+      splitLine: {
+        show: true,
+        lineStyle: {
+          color: "rgba(88,88,88,0.5)",
+        },
+      },
+    },
+    series: [
+      {
+        name: "数值",
+        type: "line",
+        data: yData,
+        smooth: true,
+        lineStyle: {
+          width: 2,
+        },
+        symbolSize: 4,
+      },
+    ],
+  };
+
+  // 设置图表配置
+  chartInstance.setOption(option);
+};
+
+// 获取历史数据
+const fetchHistoryData = () => {
+  if (!params.deviceKey || !params.properties) return;
+
+  historyLoading.value = true;
+
+  const historyParams = {
+    productKey: params.productKey,
+    deviceKey: params.deviceKey,
+    properties: params.properties,
+    dateRange: historyDateRange.value,
+    page: currentPage.value,
+    pageSize: pageSize.value,
+  };
+
+  api.analysis
+    .deviceIndicatorTrend(historyParams)
+    .then((res: any) => {
+      historyData.value = res;
+      totalItems.value = res.length;
+    })
+    .catch((error) => {
+      console.error("获取历史数据失败:", error);
+      ElMessage.error("获取历史数据失败");
+    })
+    .finally(() => {
+      historyLoading.value = false;
+    });
+};
+
+// 处理分页大小变化
+const handleSizeChange = (size: number) => {
+  pageSize.value = size;
+  fetchHistoryData();
+};
+
+// 处理页码变化
+const handleCurrentChange = (page: number) => {
+  currentPage.value = page;
+  fetchHistoryData();
+};
+
+// 导出数据
+const exportData = () => {
+  if (historyData.value.length === 0) {
+    ElMessage.warning("没有数据可导出");
+    return;
+  }
+
+  // 创建CSV内容
+  let csvContent = "时间,属性值";
+  if (data.value.unit) {
+    csvContent += ",数据单位";
+  }
+  csvContent += "\n";
+
+  historyData.value.forEach((item: any) => {
+    csvContent += `${item.ts},${item.value}`;
+    if (data.value.unit) {
+      csvContent += `,${data.value.unit}`;
+    }
+    csvContent += "\n";
+  });
+
+  // 创建Blob对象
+  const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
+  const url = URL.createObjectURL(blob);
+
+  // 创建下载链接
+  const link = document.createElement("a");
+  link.setAttribute("href", url);
+  link.setAttribute("download", `${data.value.name}_历史数据_${dayjs().format("YYYYMMDD_HHmmss")}.csv`);
+  link.style.visibility = "hidden";
+  document.body.appendChild(link);
+  link.click();
+  document.body.removeChild(link);
+};
 
 // 监听数据变化,更新图表
 watch(
-	() => lineData.value,
-	() => {
-		nextTick(() => {
-			updateChart()
-		})
-	},
-	{ deep: true }
-)
+  () => lineData.value,
+  () => {
+    nextTick(() => {
+      updateChart();
+    });
+  },
+  { deep: true }
+);
 
 // 监听 loading 状态变化
 watch(
-	() => loading.value,
-	(newVal) => {
-		if (chartInstance) {
-			if (newVal) {
-				chartInstance.showLoading()
-			} else {
-				chartInstance.hideLoading()
-			}
-		}
-	}
-)
+  () => loading.value,
+  (newVal) => {
+    if (chartInstance) {
+      if (newVal) {
+        chartInstance.showLoading();
+      } else {
+        chartInstance.hideLoading();
+      }
+    }
+  }
+);
 
 // 监听弹窗显示状态
 watch(
-	() => isShowDialog.value,
-	(val) => {
-		if (val) {
-			nextTick(() => {
-				initChart()
-			})
-		}
-	}
-)
+  () => isShowDialog.value,
+  (val) => {
+    if (val) {
+      nextTick(() => {
+        initChart();
+        // 重置分页
+        currentPage.value = 1;
+        // 如果是历史日志标签页,加载历史数据
+        if (activeTab.value === "history") {
+          fetchHistoryData();
+        }
+      });
+    }
+  }
+);
+
+// 监听标签页切换
+watch(
+  () => activeTab.value,
+  (val) => {
+    if (val === "history" && isShowDialog.value) {
+      fetchHistoryData();
+    } else if (val === "trend" && isShowDialog.value) {
+      nextTick(() => {
+        initChart();
+      });
+    }
+  }
+);
 
 // 打开弹窗
-const openDialog = (row: any, deviceKey: string) => {
-	data.value = row
-	isShowDialog.value = true
-	loading.value = true
-	api.instance
-		.getLogDetail({
-			deviceKey: deviceKey,
-			propertyKey: row.key,
-			pageSize: 100,
-		})
-		.then((res: any) => {
-			lineData.value = res.List
-		})
-		.finally(() => (loading.value = false))
-}
+const openDialog = (row: any, deviceKey: string, productKey: string) => {
+  params.productKey = productKey;
+  params.deviceKey = deviceKey;
+  params.properties = row.key;
 
-defineExpose({ openDialog })
+  // 重置日期范围
+  historyDateRange.value = [dayjs().subtract(1, "hour").format("YYYY-MM-DD HH:mm:ss"), dayjs().format("YYYY-MM-DD HH:mm:ss")];
+  console.log(row);
+  data.value = row;
+  isShowDialog.value = true;
+  loading.value = true;
+  api.instance
+    .getLogDetail({
+      deviceKey: deviceKey,
+      propertyKey: row.key,
+      pageSize: 100,
+    })
+    .then((res: any) => {
+      lineData.value = res.List;
+    })
+    .finally(() => (loading.value = false));
+};
+
+defineExpose({ openDialog });
 </script>
 <style scoped>
 .chart-container {
-	width: 100%;
-	height: 400px;
+  width: 100%;
+  height: 400px;
+}
+
+.history-container {
+  width: 100%;
+}
+
+.date-picker-container {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 15px;
+}
+
+.pagination-container {
+  margin-top: 15px;
+  display: flex;
+  justify-content: flex-end;
 }
 </style>

+ 245 - 241
src/views/iot/device/instance/detail.vue

@@ -1,24 +1,24 @@
 <template>
   <div class="page bg page-full">
     <div class="content">
-      <div class="cont_box" style="align-items: center;">
+      <div class="cont_box" style="align-items: center">
         <div class="title">设备:{{ detail.name }}</div>
-        <el-tag v-if="areaData.status === 0" type="info" style="margin-left: 20px;">未启用</el-tag>
-        <el-tag v-else-if="areaData.status === 1" type="danger" style="margin-left: 20px;">离线</el-tag>
-        <el-tag v-else-if="areaData.status === 2" type="success" style="margin-left: 20px;">在线</el-tag>
+        <el-tag v-if="areaData.status === 0" type="info" style="margin-left: 20px">未启用</el-tag>
+        <el-tag v-else-if="areaData.status === 1" type="danger" style="margin-left: 20px">离线</el-tag>
+        <el-tag v-else-if="areaData.status === 2" type="success" style="margin-left: 20px">在线</el-tag>
       </div>
     </div>
 
     <div class="content-box page-full-part page-full">
       <el-tabs v-model="activeName" @tab-click="handleClick">
         <el-tab-pane label="运行状态" name="3">
-          <div style=" display: flex;flex-wrap: wrap;">
+          <div style="display: flex; flex-wrap: wrap">
             <div class="ant-card">
               <div class="ant-card-body">
                 <div class="cardflex">
                   <div>设备状态</div>
-                  <div @click="getrunData()" style="cursor: pointer;">
-                    <el-icon style="font-size: 18px;">
+                  <div @click="getrunData()" style="cursor: pointer">
+                    <el-icon style="font-size: 18px">
                       <ele-Refresh />
                     </el-icon>
                   </div>
@@ -28,8 +28,8 @@
                 <div class="statusname" v-if="areaData.status == 1">离线</div>
                 <div class="statusname" v-if="areaData.status == 2">在线</div>
                 <div class="cardflex comtest">
-                  <div> 数据时间</div>
-                  <div>{{ areaData.lastOnlineTime || '未启用' }}</div>
+                  <div>数据时间</div>
+                  <div>{{ areaData.lastOnlineTime || "未启用" }}</div>
                 </div>
               </div>
             </div>
@@ -38,28 +38,26 @@
               <div class="ant-card-body">
                 <div class="cardflex">
                   <div>{{ item.name }}</div>
-                  <div style="cursor: pointer;">
-                    <el-icon style="font-size: 18px;" @click="getrunData()">
+                  <div style="cursor: pointer">
+                    <el-icon style="font-size: 18px" @click="getrunData()">
                       <ele-Refresh />
                     </el-icon>
-                    <el-icon style="font-size: 18px;margin-left: 10px;" @click="onOpenListDetail(item)">
+                    <el-icon style="font-size: 18px; margin-left: 10px" @click="onOpenListDetail(item)">
                       <ele-Expand />
                     </el-icon>
-                    <el-icon style="font-size: 18px;margin-left: 10px;" @click="onOpenChartDetail(item)">
+                    <el-icon style="font-size: 18px; margin-left: 10px" @click="onOpenChartDetail(item)">
                       <ele-DataLine />
                     </el-icon>
                   </div>
                 </div>
 
                 <div class="statusname" v-if="item.type != 'object'">
-
                   {{ getValueText(item.key, item.value) }}
                   <!-- {{ item.value }}{{ item.unit }} -->
-
                 </div>
                 <div v-else>
                   <div class="oblist" v-for="(vare, name) in item.value">
-                    <div> {{ getStatusText(name, vare) }}</div>
+                    <div>{{ getStatusText(name, vare) }}</div>
                     <!-- <div class="name">{{ name }}:</div>
                     <div class="name">{{ vare }}</div> -->
                   </div>
@@ -89,14 +87,13 @@
               <copy :text="prodetail.key"></copy>
             </el-descriptions-item>
             <el-descriptions-item label="产品名称">
-              <router-link :to="'/iotmanager/device/product/detail/' + prodetail.key" class="link-type">{{
-                detail.productName }} </router-link>
+              <router-link :to="'/iotmanager/device/product/detail/' + prodetail.key" class="link-type">{{ detail.productName }} </router-link>
             </el-descriptions-item>
             <el-descriptions-item label="链接协议">{{ prodetail.transportProtocol }}</el-descriptions-item>
             <el-descriptions-item label="设备类型">{{ prodetail.deviceType }}</el-descriptions-item>
             <el-descriptions-item label="固件版本">{{ detail.version }}</el-descriptions-item>
             <el-descriptions-item label="注册时间">{{ detail.registryTime }}</el-descriptions-item>
-            <el-descriptions-item label="最后上线时间">{{ detail.lastOnlineTime || '' }}</el-descriptions-item>
+            <el-descriptions-item label="最后上线时间">{{ detail.lastOnlineTime || "" }}</el-descriptions-item>
             <el-descriptions-item label="详细地址">{{ detail.address }}</el-descriptions-item>
             <el-descriptions-item label="说明">{{ detail.desc }}</el-descriptions-item>
             <el-descriptions-item :label="item.name" v-for="(item, index) in detail.tags" :key="index">{{ item.value }}</el-descriptions-item>
@@ -109,13 +106,14 @@
             </div>
             </el-descriptions-item> -->
           </el-descriptions>
-          <div class="flex" style="margin-top: 20px;">
-            <el-input type="number" style="width: 380px;margin-right: 20px;" v-model.number="detail.onlineTimeout">
+          <div class="flex" style="margin-top: 20px">
+            <el-input type="number" style="width: 380px; margin-right: 20px" v-model.number="detail.onlineTimeout">
               <template #prepend>设备超时时间</template>
               <template #append>秒</template>
             </el-input>
             <el-button type="primary" @click="onlineTimeoutUpdate">
-              <el-icon style="font-size: 18px;"><ele-Refresh /></el-icon>更新</el-button>
+              <el-icon style="font-size: 18px"><ele-Refresh /></el-icon>更新</el-button
+            >
           </div>
         </el-tab-pane>
         <el-tab-pane label="物模型" name="2">
@@ -219,7 +217,6 @@
                 </div>
               </div>
 
-
               <el-table style="width: 100%" :data="tableData.data" v-loading="tableLoading" v-if="activetab == 'tab'">
                 <el-table-column label="属性标识" align="center" prop="key" />
                 <el-table-column label="属性名称" prop="name" show-overflow-tooltip />
@@ -292,7 +289,7 @@
         </el-tab-pane>
         <el-tab-pane label="Topic列表" name="topic">
           SagooMqtt协议 ,涉及的topic如下:
-          <el-table style="width: 100%;margin-top: 20px;" :data="topicData" border>
+          <el-table style="width: 100%; margin-top: 20px" :data="topicData" border>
             <el-table-column label="描述" prop="info" width="250" />
             <el-table-column label="类型" prop="type" width="80" align="center" />
             <el-table-column label="Topic类" prop="url">
@@ -341,7 +338,6 @@
             </el-table>
             <pagination v-show="deviceTableData.total > 0" :total="deviceTableData.total" v-model:page="deviceTableData.param.pageNum" v-model:limit="deviceTableData.param.pageSize" @pagination="getDeviceTableData" />
           </div>
-
         </el-tab-pane>
         <el-tab-pane label="设备档案" name="7" v-if="deviceAssetData">
           <el-form label-width="110px">
@@ -399,27 +395,27 @@
   </div>
 </template>
 <script lang="ts">
-import { toRefs, reactive, onMounted, ref, defineComponent, nextTick, onUnmounted } from 'vue';
-import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
-import functionCom from './component/function.vue';
-import 'vue3-json-viewer/dist/index.css';
-import EditDic from './component/edit.vue';
-import EditAttr from '../product/component/editAttr.vue';
-import EditFun from '../product/component/editFun.vue';
-import EditEvent from '../product/component/editEvent.vue';
-import EditTab from '../product/component/editTab.vue';
-import devantd from '/@/components/devantd/index.vue';
-import ListDic from './component/list.vue';
-import ChartDic from './component/chart.vue';
-import SubDevice from './component/subDevice.vue';
-import setAttr from './component/setAttr.vue';
-import SubDeviceMutipleBind from './component/subDeviceMutipleBind.vue';
-import api from '/@/api/device';
-import datahub from '/@/api/datahub';
+import { toRefs, reactive, onMounted, ref, defineComponent, nextTick, onUnmounted } from "vue";
+import { ElMessageBox, ElMessage, FormInstance } from "element-plus";
+import functionCom from "./component/function.vue";
+import "vue3-json-viewer/dist/index.css";
+import EditDic from "./component/edit.vue";
+import EditAttr from "../product/component/editAttr.vue";
+import EditFun from "../product/component/editFun.vue";
+import EditEvent from "../product/component/editEvent.vue";
+import EditTab from "../product/component/editTab.vue";
+import devantd from "/@/components/devantd/index.vue";
+import ListDic from "./component/list.vue";
+import ChartDic from "./component/chart.vue";
+import SubDevice from "./component/subDevice.vue";
+import setAttr from "./component/setAttr.vue";
+import SubDeviceMutipleBind from "./component/subDeviceMutipleBind.vue";
+import api from "/@/api/device";
+import datahub from "/@/api/datahub";
 import FromData from "/@/views/iot/property/dossier/component/from.vue";
 import EditAssetRef from "/@/views/iot/property/dossier/edit.vue";
 
-import { useRoute } from 'vue-router';
+import { useRoute } from "vue-router";
 
 interface TableDataState {
   isShowDialog: boolean;
@@ -442,14 +438,16 @@ interface TableDataState {
     data: [];
     total: number;
     loading: boolean;
-    param: {
-      pageNum: number;
-      pageSize: number;
-      name: string;
-      deviceType: string;
-      status: string;
-      dateRange: string[];
-    } | any;
+    param:
+      | {
+          pageNum: number;
+          pageSize: number;
+          name: string;
+          deviceType: string;
+          status: string;
+          dateRange: string[];
+        }
+      | any;
   };
   logtableData: {
     data: [];
@@ -459,24 +457,23 @@ interface TableDataState {
   };
 }
 export default defineComponent({
-  name: 'deviceEditPro',
+  name: "deviceEditPro",
   components: { EditAssetRef, FromData, SubDeviceMutipleBind, SubDevice, EditDic, EditAttr, EditFun, EditEvent, EditTab, devantd, ListDic, functionCom, setAttr, ChartDic },
 
   props: {
-    deviceKey: String
+    deviceKey: String,
   },
   setup(props, context) {
+    let timer: any;
 
-    let timer: any
-
-    onUnmounted(() => clearInterval(timer))
+    onUnmounted(() => clearInterval(timer));
 
     const logqueryRef = ref();
 
-    const topicData = ref<any[]>([])
+    const topicData = ref<any[]>([]);
 
     // 属性列表,查询保留小数位使用
-    const propertyMap = new Map()
+    const propertyMap = new Map();
 
     const array_list = ref([]);
     const tableLoading = ref(false);
@@ -498,18 +495,18 @@ export default defineComponent({
     const state = reactive<TableDataState>({
       certificate: [],
       phone: [],
-      intro: '',
+      intro: "",
       deviceKeyList: [],
       areaData: [],
       isShowDialog: false,
       dialogVisible: false,
       logTypeData: [],
-      jsonData: '',
-      activeName: '3', // 分类数据
-      activetab: 'attr', // 分类数据
+      jsonData: "",
+      activeName: "3", // 分类数据
+      activetab: "attr", // 分类数据
       detail: {},
       prodetail: [],
-      productKey: '',
+      productKey: "",
       developer_status: 0,
       deviceTableData: {
         data: [],
@@ -517,7 +514,7 @@ export default defineComponent({
         loading: false,
         param: {
           pageNum: 1,
-          gatewayKey: '',
+          gatewayKey: "",
           pageSize: 20,
           dateRange: [],
         },
@@ -528,9 +525,9 @@ export default defineComponent({
         loading: false,
         param: {
           pageNum: 1,
-          productKey: '',
+          productKey: "",
           pageSize: 20,
-          status: '',
+          status: "",
           dateRange: [],
         },
       },
@@ -540,21 +537,21 @@ export default defineComponent({
         loading: false,
         param: {
           pageNum: 1,
-          productKey: '',
+          productKey: "",
           pageSize: 20,
-          status: '',
+          status: "",
           dateRange: [],
         },
       },
     });
 
     onMounted(() => {
-      initData()
+      initData();
     });
 
     function initData() {
       // 如果是嵌入的就是子设备,看子设备详情,否则看页面参数
-      const deviceKey = props.deviceKey || route.params?.id
+      const deviceKey = props.deviceKey || route.params?.id;
       api.instance.detail(deviceKey).then((res: any) => {
         state.detail = res.data;
         state.developer_status = res.data.status;
@@ -564,10 +561,10 @@ export default defineComponent({
           state.prodetail = res.data;
         });
 
-        const { phone, certificate, intro } = JSON.parse(res.data.extensionInfo || '{}')
+        const { phone, certificate, intro } = JSON.parse(res.data.extensionInfo || "{}");
         state.phone = phone || [];
         state.certificate = certificate || [];
-        state.intro = intro
+        state.intro = intro;
 
         //加载全部属性
         datahub.node.getpropertyList({ productKey: state.detail.productKey }).then((re: any) => {
@@ -575,52 +572,53 @@ export default defineComponent({
           re.forEach((item: any) => propertyMap.set(item.key, item?.valueType));
         });
 
-
-        const deviceType = res.data?.product?.deviceType
-
-        topicData.value = deviceType === '网关' ? [
-          {
-            url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/property/pack/post`,
-            info: '网关批量上传事件和属性(网关发起)',
-            type: '请求',
-          },
-          {
-            url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/property/pack/post_reply`,
-            info: '网关批量上传事件和属性(网关发起)',
-            type: '响应',
-          }
-        ] : [
-
-          {
-            url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/property/post`,
-            info: '设备上报属性(设备端发起)',
-            type: '请求',
-          },
-          {
-            url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/property/post_reply`,
-            info: '设备上报属性(设备端发起)',
-            type: '响应',
-          },
-          {
-            url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/${'${eventIdentifier}'}/post`,
-            info: '设备上报事件(设备端发起)',
-            type: '请求',
-          },
-          {
-            url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/${'${eventIdentifier}'}/post_reply`,
-            info: '设备上报事件(设备端发起)',
-            type: '响应',
-          }
-        ]
+        const deviceType = res.data?.product?.deviceType;
+
+        topicData.value =
+          deviceType === "网关"
+            ? [
+                {
+                  url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/property/pack/post`,
+                  info: "网关批量上传事件和属性(网关发起)",
+                  type: "请求",
+                },
+                {
+                  url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/property/pack/post_reply`,
+                  info: "网关批量上传事件和属性(网关发起)",
+                  type: "响应",
+                },
+              ]
+            : [
+                {
+                  url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/property/post`,
+                  info: "设备上报属性(设备端发起)",
+                  type: "请求",
+                },
+                {
+                  url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/property/post_reply`,
+                  info: "设备上报属性(设备端发起)",
+                  type: "响应",
+                },
+                {
+                  url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/${"${eventIdentifier}"}/post`,
+                  info: "设备上报事件(设备端发起)",
+                  type: "请求",
+                },
+                {
+                  url: `/sys/${res.data.productKey}/${deviceKey}/thing/event/${"${eventIdentifier}"}/post_reply`,
+                  info: "设备上报事件(设备端发起)",
+                  type: "响应",
+                },
+              ];
 
         // 加载对应设备档案 (企业版功能)
-        sessionStorage.isEnterprise && getDeviceAssetMetadata()
+        sessionStorage.isEnterprise && getDeviceAssetMetadata();
 
         getrunData();
 
-        timer = setInterval(getrunData, 3000)
+        timer = setInterval(getrunData, 3000);
 
-        getDeviceTableData()
+        getDeviceTableData();
       });
     }
 
@@ -634,56 +632,58 @@ export default defineComponent({
           const newArray = (resde?.data || []).map((obj: any) => {
             const { name, value, ...rest } = obj;
             const newObj = { name, value, ...rest };
-            newObj[name] = value ? value : '';
+            newObj[name] = value ? value : "";
             return newObj;
           });
-          dataList.value = newArray
+          dataList.value = newArray;
 
           for (const item of dataList.value) {
             item.pattern = false;
-            if (item.types == 'input' || item.types == 'textarea') {
+            if (item.types == "input" || item.types == "textarea") {
               if (urlRegex.test(item.value)) {
                 item.pattern = true;
               }
             }
             // 根据属性返回键获取对应档案对应的内容
-            deviceAssetMetadata.value[item.name] = item.value ? item.value : ''
+            deviceAssetMetadata.value[item.name] = item.value ? item.value : "";
           }
         });
       });
-    }
+    };
 
     const mutipleUnbind = () => {
-      let msg = '是否进行批量解绑?';
+      let msg = "是否进行批量解绑?";
       if (state.deviceKeyList.length === 0) {
-        ElMessage.error('请选择要批量解绑的数据。');
+        ElMessage.error("请选择要批量解绑的数据。");
         return;
       }
-      ElMessageBox.confirm(msg, '提示', {
-        confirmButtonText: '确认',
-        cancelButtonText: '取消',
-        type: 'warning',
+      ElMessageBox.confirm(msg, "提示", {
+        confirmButtonText: "确认",
+        cancelButtonText: "取消",
+        type: "warning",
       })
         .then(() => {
-          api.device.mutipleUnbind({
-            "gatewayKey": state.deviceTableData.param.gatewayKey,
-            "subKeys": state.deviceKeyList
-          }).then(() => {
-            ElMessage.success('解绑成功');
-            // typeList();
-            getDeviceTableData();
-          });
+          api.device
+            .mutipleUnbind({
+              gatewayKey: state.deviceTableData.param.gatewayKey,
+              subKeys: state.deviceKeyList,
+            })
+            .then(() => {
+              ElMessage.success("解绑成功");
+              // typeList();
+              getDeviceTableData();
+            });
         })
-        .catch(() => { });
-    }
+        .catch(() => {});
+    };
 
     const getDeviceTableData = () => {
-      state.deviceTableData.data = []
+      state.deviceTableData.data = [];
       state.deviceTableData.param.gatewayKey = state.detail.key;
       api.device.getList(state.deviceTableData.param).then((res: any) => {
         state.deviceTableData.data = res.list;
         state.deviceTableData.total = res.Total;
-      })
+      });
     };
 
     // 多选框选中数据
@@ -693,23 +693,21 @@ export default defineComponent({
 
     // 打开修改产品弹窗
     const onOpenDetail = (row: any) => {
-      subDeviceRef.value.openDialog(row)
+      subDeviceRef.value.openDialog(row);
     };
 
-
     // 删除子设备
     const deleteSubDevice = (row: any) => {
-      ElMessageBox.confirm(`此操作将永久删除该子设备:${row.name}, 是否继续?`, '提示', {
-        confirmButtonText: '删除',
-        cancelButtonText: '取消',
-        type: 'warning',
+      ElMessageBox.confirm(`此操作将永久删除该子设备:${row.name}, 是否继续?`, "提示", {
+        confirmButtonText: "删除",
+        cancelButtonText: "取消",
+        type: "warning",
       }).then(() => {
         api.product.deleteSubDevice(row.id).then(() => {
-          ElMessage.success('删除成功');
+          ElMessage.success("删除成功");
           getDeviceTableData();
         });
       });
-
     };
 
     const onLogDetail = (row: any) => {
@@ -721,7 +719,6 @@ export default defineComponent({
       mutipleBindRef.value.openDialog(state.deviceTableData.param.gatewayKey);
     };
 
-
     //编辑属性
     const onEditAttr = (row: any) => {
       editAttrRef.value.openDialog(row, state.productKey);
@@ -768,7 +765,7 @@ export default defineComponent({
 
     //查看日志图形
     const onOpenChartDetail = (row: any) => {
-      chartDicRef.value.openDialog(row, state.detail.key);
+      chartDicRef.value.openDialog(row, state.detail.key, state.productKey);
     };
 
     // 打开修改产品弹窗
@@ -778,7 +775,7 @@ export default defineComponent({
 
     // 打开修改设备档案弹窗
     const onOpenEditAsset = () => {
-      editAssetRef.value.open(deviceAssetData.value, state.detail.product)
+      editAssetRef.value.open(deviceAssetData.value, state.detail.product);
     };
 
     // 删除产品
@@ -786,109 +783,121 @@ export default defineComponent({
       let msg = `此操作将永久删除该数据,是否继续?`;
 
       if (key.length === 0) {
-        ElMessage.error('请选择要删除的数据。');
+        ElMessage.error("请选择要删除的数据。");
         return;
       }
-      ElMessageBox.confirm(msg, '提示', {
-        confirmButtonText: '确认',
-        cancelButtonText: '取消',
-        type: 'warning',
+      ElMessageBox.confirm(msg, "提示", {
+        confirmButtonText: "确认",
+        cancelButtonText: "取消",
+        type: "warning",
       })
         .then(() => {
-          if (type == 'attr') {
+          if (type == "attr") {
             api.model.propertydel(state.productKey, key).then(() => {
-              ElMessage.success('删除成功');
+              ElMessage.success("删除成功");
               getproperty();
             });
           }
-          if (type == 'fun') {
+          if (type == "fun") {
             api.model.functiondel(state.productKey, key).then(() => {
-              ElMessage.success('删除成功');
+              ElMessage.success("删除成功");
               getfunction();
             });
           }
-          if (type == 'event') {
+          if (type == "event") {
             api.model.eventdel(state.productKey, key).then(() => {
-              ElMessage.success('删除成功');
+              ElMessage.success("删除成功");
               getevent();
             });
           }
-          if (type == 'tab') {
+          if (type == "tab") {
             api.model.tagdel(state.productKey, key).then(() => {
-              ElMessage.success('删除成功');
+              ElMessage.success("删除成功");
               gettab();
             });
           }
         })
-        .catch(() => { });
+        .catch(() => {});
     };
 
     //根据不同类型获取列表
     const getList = () => {
       switch (state.activetab) {
-        case 'attr':
+        case "attr":
           getproperty();
           break;
-        case 'fun':
+        case "fun":
           getfunction();
           break;
-        case 'event':
+        case "event":
           getevent();
           break;
-        case 'tab':
+        case "tab":
           gettab();
           break;
       }
     };
 
     const getproperty = () => {
-      state.tableData.data = []
-      tableLoading.value = true
-      api.model.property(state.tableData.param).then((res: any) => {
-        state.tableData.data = res.Data;
-        state.tableData.total = res.Total;
-      }).finally(() => tableLoading.value = false)
+      state.tableData.data = [];
+      tableLoading.value = true;
+      api.model
+        .property(state.tableData.param)
+        .then((res: any) => {
+          state.tableData.data = res.Data;
+          state.tableData.total = res.Total;
+        })
+        .finally(() => (tableLoading.value = false));
     };
 
     const getfunction = () => {
-      state.tableData.data = []
-      tableLoading.value = true
-      api.model.function(state.tableData.param).then((res: any) => {
-        state.tableData.data = res.Data;
-        state.tableData.total = res.Total;
-      }).finally(() => tableLoading.value = false)
+      state.tableData.data = [];
+      tableLoading.value = true;
+      api.model
+        .function(state.tableData.param)
+        .then((res: any) => {
+          state.tableData.data = res.Data;
+          state.tableData.total = res.Total;
+        })
+        .finally(() => (tableLoading.value = false));
     };
     const getevent = () => {
-      state.tableData.data = []
-      tableLoading.value = true
-      api.model.event(state.tableData.param).then((res: any) => {
-        state.tableData.data = res.Data;
-        state.tableData.total = res.Total;
-      }).finally(() => tableLoading.value = false)
+      state.tableData.data = [];
+      tableLoading.value = true;
+      api.model
+        .event(state.tableData.param)
+        .then((res: any) => {
+          state.tableData.data = res.Data;
+          state.tableData.total = res.Total;
+        })
+        .finally(() => (tableLoading.value = false));
     };
 
     const gettab = () => {
-      state.tableData.data = []
-      tableLoading.value = true
-      api.model.tag(state.tableData.param).then((res: any) => {
-        state.tableData.data = res.Data;
-        state.tableData.total = res.Total;
-      }).finally(() => tableLoading.value = false)
+      state.tableData.data = [];
+      tableLoading.value = true;
+      api.model
+        .tag(state.tableData.param)
+        .then((res: any) => {
+          state.tableData.data = res.Data;
+          state.tableData.total = res.Total;
+        })
+        .finally(() => (tableLoading.value = false));
     };
 
     const wuhandleClick = (tab: any) => {
       state.activetab = tab.props.name;
       switch (tab.props.name) {
-        case 'attr':
+        case "attr":
           getproperty();
           break;
-        case 'fun':
+        case "fun":
           getfunction();
           break;
-        case 'event':
+        case "event":
           getevent();
           break;
-        case 'tab':
+        case "tab":
           gettab();
           break;
       }
@@ -909,22 +918,22 @@ export default defineComponent({
     };
 
     const getValueText = (key: String, value: String) => {
-      const item = propertyMap.get(key)
+      const item = propertyMap.get(key);
 
-      if (!item) return value
+      if (!item) return value;
 
       if (item.type === "enum") {
         const option = item.elements.find((element: any) => element.value === value);
         if (option) {
           return option.text;
         }
-      } else if (['float', 'double'].includes(item?.type) && item?.decimals) {
+      } else if (["float", "double"].includes(item?.type) && item?.decimals) {
         //  根据属性确定保留小数位数
-        return Number(value).toFixed(item.decimals)
+        return Number(value).toFixed(item.decimals);
       } else {
         return value;
       }
-    }
+    };
     const getStatusText = (name: any, value: string) => {
       let data = array_list.value as any;
       for (let i = 0; i < data.length; i++) {
@@ -952,25 +961,22 @@ export default defineComponent({
               return `${field.name}: ${element.text}`;
             }
           } else {
-
             return `${field.name}: ${value}`;
           }
         }
       }
 
-      return name + ':' + value;
-    }
+      return name + ":" + value;
+    };
 
     const getrunData = () => {
-
       api.instance.getrun_status({ deviceKey: state.detail.key }).then((res: any) => {
-        state.areaData = res
+        state.areaData = res;
         let properties = state.areaData.properties || [];
 
         var temp = new Array();
 
         properties.forEach(function (item: any, index: number) {
-
           let datalist = item.list || [];
           temp[index] = [];
           var temps = new Array();
@@ -980,17 +986,16 @@ export default defineComponent({
               temps.push(a);
             }
           });
-          if (item.type == 'object') {
+          if (item.type == "object") {
             item.value = JSON.parse(item.value);
           }
 
-          temp[index]['name'] = item.name
-          temp[index]['key'] = item.key
-          temp[index]['type'] = item.type
-          temp[index]['unit'] = item.unit
-          temp[index]['value'] = item.value
-          temp[index]['list'] = temps
-
+          temp[index]["name"] = item.name;
+          temp[index]["key"] = item.key;
+          temp[index]["type"] = item.type;
+          temp[index]["unit"] = item.unit;
+          temp[index]["value"] = item.value;
+          temp[index]["list"] = temps;
         });
         state.areaData.properties = temp;
       });
@@ -1019,25 +1024,25 @@ export default defineComponent({
     const CkOption = () => {
       if (state.developer_status == 2) {
         api.instance.devoffline({ id: state.detail.id }).then((res: any) => {
-          ElMessage.success('操作成功');
+          ElMessage.success("操作成功");
           state.developer_status = 1;
         });
       } else {
         api.instance.devonline({ id: state.detail.id }).then((res: any) => {
-          ElMessage.success('操作成功');
+          ElMessage.success("操作成功");
           state.developer_status = 2;
         });
       }
     };
     const onlineTimeoutUpdate = () => {
-      if (!state.detail.onlineTimeout) return ElMessage('请先输入设备超时时间')
+      if (!state.detail.onlineTimeout) return ElMessage("请先输入设备超时时间");
       api.device.updateOnlineTimeout({ deviceKey: state.detail.key, onlineTimeout: state.detail.onlineTimeout }).then(() => {
-        ElMessage.success('设置成功')
-      })
-    }
+        ElMessage.success("设置成功");
+      });
+    };
     const setAttr = (row: any) => {
-      setAttrRef.value.show(row)
-    }
+      setAttrRef.value.show(row);
+    };
 
     return {
       topicData,
@@ -1101,35 +1106,35 @@ export default defineComponent({
 });
 </script>
 <style scoped lang="scss">
-.capsule-wrapper{
+.capsule-wrapper {
   display: flex;
   align-items: center;
-  .capsule{
+  .capsule {
     display: flex;
     flex-direction: row;
     align-items: center;
     border: 1px solid var(--el-color-primary);
     border-radius: 20px;
     font-size: 12px;
-    .label{
-        height: 24px;
-        display: flex;
-        align-items: center;
-        border-top-left-radius: 20px;
-        border-bottom-left-radius: 20px;
-        background-color: var(--el-color-primary);
-        padding: 0px 10px;
-        text-indent: 2px;
-        color: var(--el-color-white) !important;
+    .label {
+      height: 24px;
+      display: flex;
+      align-items: center;
+      border-top-left-radius: 20px;
+      border-bottom-left-radius: 20px;
+      background-color: var(--el-color-primary);
+      padding: 0px 10px;
+      text-indent: 2px;
+      color: var(--el-color-white) !important;
     }
-    .value{
-        height: 24px;
-        display: flex;
-        align-items: center;
-        border-top-right-radius: 20px;
-        border-bottom-right-radius: 20px;
-        text-indent: -2px;
-        padding: 0px 10px;
+    .value {
+      height: 24px;
+      display: flex;
+      align-items: center;
+      border-top-right-radius: 20px;
+      border-bottom-right-radius: 20px;
+      text-indent: -2px;
+      padding: 0px 10px;
     }
   }
 }
@@ -1196,7 +1201,6 @@ export default defineComponent({
   display: flex;
   padding: 10px;
   justify-content: space-between;
-
 }
 
 .content-box .pro-box .protitle {
@@ -1251,7 +1255,7 @@ tr {
 
   line-height: 1.5;
   list-style: none;
-  font-feature-settings: 'tnum';
+  font-feature-settings: "tnum";
   position: relative;
   border-radius: 2px;
   transition: all 0.3s;

+ 33 - 35
src/views/iot/ota-update/update/component/batch.vue

@@ -17,7 +17,7 @@
           </el-icon>
           重置
         </el-button>
-        <el-button type="primary" v-auth="'add'" @click="onOpenAdd()">
+        <el-button type="primary" @click="onOpenAdd()">
           <el-icon>
             <ele-FolderAdd />
           </el-icon>
@@ -26,7 +26,7 @@
       </el-form-item>
     </el-form>
     <el-table :data="tableData.data" style="width: 100%" v-loading="tableData.loading">
-      <el-table-column prop="id" label="ID" width="100" />
+      <el-table-column prop="id" label="ID" width="100" align="center" />
       <el-table-column prop="name" label="名称" />
       <!--        <el-table-column prop="waitVersion" label="待升级版本号" width="120" />-->
       <el-table-column label="类型" prop="types" width="120" align="center">
@@ -41,35 +41,32 @@
           <el-tag type="info" size="small" v-else>否</el-tag>
         </template>
       </el-table-column>
-      <el-table-column prop="method" label="协议方式" show-overflow-tooltip>
+      <el-table-column prop="method" label="协议方式" show-overflow-tooltip align="center">
         <template #default="scope">
           <el-tag size="small" v-if="scope.row.method == 1">http</el-tag>
           <el-tag size="small" v-if="scope.row.method == 2">https</el-tag>
           <el-tag size="small" v-if="scope.row.method == 3">mqtt</el-tag>
         </template>
       </el-table-column>
-      <el-table-column prop="stratege" label="升级方式" show-overflow-tooltip>
+      <el-table-column prop="stratege" label="升级方式" show-overflow-tooltip align="center">
         <template #default="scope">
           <el-tag size="small" v-if="scope.row.stratege == 1">静态升级 </el-tag>
           <el-tag size="small" v-if="scope.row.stratege == 2">动态升级</el-tag>
         </template>
       </el-table-column>
 
-      <el-table-column prop="push" label="主动推送" show-overflow-tooltip>
+      <el-table-column prop="push" label="主动推送" show-overflow-tooltip align="center">
         <template #default="scope">
           <el-tag size="small" v-if="scope.row.push == 1">是 </el-tag>
           <el-tag size="small" v-if="scope.row.push == 2">否</el-tag>
         </template>
       </el-table-column>
-      <el-table-column prop="createdAt" label="创建时间" min-width="100" align="center" />
-      <el-table-column label="操作" width="200" align="center">
+      <el-table-column prop="createdAt" label="创建时间" width="160" align="center" />
+      <el-table-column label="操作" width="120" align="center">
         <template #default="scope">
-          <!--            <router-link :to="'/iotmanager/operation/ota/update/device/' + scope.row.id" class="link-type" style="padding-right: 12px;font-size: 12px;color: #409eff;">-->
-          <!--              <span>查看</span>-->
-          <!--            </router-link>-->
           <el-button size="small" text type="primary" @click="getDeviceList(scope.row)">查看</el-button>
-          <!--            <el-button size="small" text type="warning" v-auth="'edit'" @click="CheckUpdate(scope.row)">编辑</el-button>-->
-          <!--            <el-button size="small" text type="danger" v-auth="'del'" @click="del(scope.row)">删除</el-button>-->
+          <!-- <el-button size="small" text type="warning" @click="CheckUpdate(scope.row)">编辑</el-button> -->
+          <el-button size="small" text type="danger" @click="onRowDel(scope.row)">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -80,11 +77,11 @@
 </template>
 
 <script lang="ts">
-import api from '/@/api/ota';
-import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
-import { ElMessageBox, ElMessage } from 'element-plus'
-import CheckConfig from '/@/views/iot/ota-update/update/component/check.vue';
-import DeviceList from '/@/views/iot/ota-update/update/component/deviceList.vue';
+import api from "/@/api/ota";
+import { toRefs, reactive, onMounted, ref, defineComponent } from "vue";
+import { ElMessageBox, ElMessage } from "element-plus";
+import CheckConfig from "/@/views/iot/ota-update/update/component/check.vue";
+import DeviceList from "/@/views/iot/ota-update/update/component/deviceList.vue";
 
 // 定义接口来定义对象的类型
 interface TableDataRow {
@@ -117,14 +114,14 @@ export default defineComponent({
   props: {
     detail: {
       type: Object,
-      default: ''
-    }
+      default: "",
+    },
   },
   setup(props) {
     const deviceRef = ref();
     const checkRef = ref();
     const queryRef = ref();
-    const tabDataList = ref([{ dictLabel: '全部', dictValue: '' }]);
+    const tabDataList = ref([{ dictLabel: "全部", dictValue: "" }]);
     const state = reactive<TableDataState>({
       ids: [],
       tableData: {
@@ -136,7 +133,7 @@ export default defineComponent({
           dateRange: [],
           pageNum: 1,
           pageSize: 20,
-          keyWord: '',
+          keyWord: "",
           devOtaFirmwareId: 0,
         },
       },
@@ -151,7 +148,7 @@ export default defineComponent({
       if (row.active === 1) active = 0;
       if (row.active === 0) active = 1;
       api.batch.stop({ id: row.id, active: active }).then((res: any) => {
-        ElMessage.success('操作成功');
+        ElMessage.success("操作成功");
         batchList();
       });
     };
@@ -160,7 +157,7 @@ export default defineComponent({
       batchList();
     };
     const getList = (pageNum?: number) => {
-      typeof pageNum === 'number' && (state.tableData.param.pageNum = pageNum)
+      typeof pageNum === "number" && (state.tableData.param.pageNum = pageNum);
       state.tableData.loading = true;
       state.tableData.param.devOtaFirmwareId = props.detail.id;
       api.batch
@@ -178,7 +175,7 @@ export default defineComponent({
     };
     // 删除模块
     const onRowDel = (row?: TableDataRow) => {
-      let msg = '你确定要删除所选数据?';
+      let msg = "你确定要删除所选数据?";
       let ids: number[] = [];
       if (row) {
         msg = `此操作将永久删除:“${row.name}”,是否继续?`;
@@ -187,20 +184,21 @@ export default defineComponent({
         ids = state.ids;
       }
       if (ids.length === 0) {
-        ElMessage.error('请选择要删除的数据。');
+        ElMessage.error("请选择要删除的数据。");
         return;
       }
-      ElMessageBox.confirm(msg, '提示', {
-        confirmButtonText: '确认',
-        cancelButtonText: '取消',
-        type: 'warning',
-      }).then(() => {
-        api.batch.del(ids).then(() => {
-          ElMessage.success('删除成功');
-          getList();
-        });
+      ElMessageBox.confirm(msg, "提示", {
+        confirmButtonText: "确认",
+        cancelButtonText: "取消",
+        type: "warning",
       })
-        .catch(() => { });
+        .then(() => {
+          api.batch.del(ids).then(() => {
+            ElMessage.success("删除成功");
+            getList();
+          });
+        })
+        .catch(() => {});
     };
     /** 重置按钮操作 */
     const resetQuery = () => {

+ 37 - 39
src/views/iot/ota-update/update/component/check.vue

@@ -22,18 +22,17 @@
         </el-form-item>
 
         <el-form-item label="所属设备" prop="devices" v-if="deviceShow">
-
           <!-- 回显已选设备 -->
           <template v-if="deviceNameShow">
-            <el-tag v-for="item in deviceNameList" style="margin-right: 10px;">{{ item }}</el-tag>
+            <el-tag v-for="item in deviceNameList" style="margin-right: 10px">{{ item }}</el-tag>
           </template>
 
-          <el-button type="primary" @click="onOpenDevice()" style="margin-left: 5px; margin-top: 10px;">选择设备</el-button>
+          <el-button type="primary" @click="onOpenDevice()" style="margin-left: 5px; margin-top: 10px">选择设备</el-button>
         </el-form-item>
 
         <el-form-item label="升级方式" prop="stratege">
           <el-radio-group v-model="ruleForm.stratege">
-            <el-radio label="1" disabled>静态升级</el-radio>
+            <el-radio label="1">静态升级</el-radio>
             <el-radio label="2">动态升级</el-radio>
           </el-radio-group>
         </el-form-item>
@@ -48,7 +47,7 @@
       <template #footer>
         <span class="dialog-footer">
           <el-button @click="onCancel">取 消</el-button>
-          <el-button type="primary" @click="onSubmit">{{ ruleForm.id !== 0 ? '修 改' : '添 加' }}</el-button>
+          <el-button type="primary" @click="onSubmit">{{ ruleForm.id !== 0 ? "修 改" : "添 加" }}</el-button>
         </span>
       </template>
     </el-dialog>
@@ -59,9 +58,9 @@
 </template>
 
 <script lang="ts">
-import { reactive, toRefs, defineComponent, onMounted, ref, unref } from 'vue';
-import { ElMessage } from 'element-plus';
-import api from '/@/api/ota';
+import { reactive, toRefs, defineComponent, onMounted, ref, unref } from "vue";
+import { ElMessage } from "element-plus";
+import api from "/@/api/ota";
 import rule from "/@/api/rule";
 import DeviceBind from "/@/views/iot/ota-update/update/component/deviceBind.vue";
 
@@ -74,7 +73,7 @@ interface RuleFormState {
   stratege: string;
   devOtaFirmwareId: number;
   push: string;
-  pushDisabled: boolean,
+  pushDisabled: boolean;
   types: string;
   productKey: string;
 }
@@ -89,12 +88,12 @@ interface UpdateState {
 }
 
 export default defineComponent({
-  name: 'otaEditUpdateData',
+  name: "otaEditUpdateData",
   components: { DeviceBind },
   computed: {
     rule() {
-      return rule
-    }
+      return rule;
+    },
   },
   setup(prop, { emit }) {
     const deviceRef = ref();
@@ -103,25 +102,25 @@ export default defineComponent({
       isShowDialog: false,
       ruleForm: {
         id: 0,
-        name: '',
-        waitVersion: '',
-        method: '1',
+        name: "",
+        waitVersion: "",
+        method: "1",
         devices: [],
-        stratege: '2',
+        stratege: "2",
         devOtaFirmwareId: 0,
-        push: '2',
+        push: "2",
         pushDisabled: true,
         types: "1",
-        productKey: '',
+        productKey: "",
       },
       productData: [],
       rules: {
-        name: [{ required: true, message: '批次名称不能为空', trigger: 'blur' }],
-        method: [{ required: true, message: '协议方式不能为空', trigger: 'blur' }],
-        stratege: [{ required: true, message: '升级方式不能为空', trigger: 'blur' }],
-        push: [{ required: true, message: '推送方式不能为空', trigger: 'blur' }],
-        types: [{ required: true, message: '类型不能为空', trigger: 'blur' }],
-        devices: [{ required: true, message: '所属设备不能为空', trigger: 'blue' }],
+        name: [{ required: true, message: "批次名称不能为空", trigger: "blur" }],
+        method: [{ required: true, message: "协议方式不能为空", trigger: "blur" }],
+        stratege: [{ required: true, message: "升级方式不能为空", trigger: "blur" }],
+        push: [{ required: true, message: "推送方式不能为空", trigger: "blur" }],
+        types: [{ required: true, message: "类型不能为空", trigger: "blur" }],
+        devices: [{ required: true, message: "所属设备不能为空", trigger: "blue" }],
       },
       deviceShow: false, // 所属设备是否显示
       deviceNameShow: false, // 回显设备名称状态
@@ -144,16 +143,16 @@ export default defineComponent({
     const getMethod = () => {
       // 如果是http、https协议则主动推送为否
       // if (state.ruleForm.method === '1') {
-      state.ruleForm.push = '2';
+      state.ruleForm.push = "2";
       state.ruleForm.pushDisabled = true;
       // }
       // if (state.ruleForm.method === '2') {
       //   state.ruleForm.push = '2';
       //   state.ruleForm.pushDisabled = true;
       // }
-      if (state.ruleForm.method === '3') {
+      if (state.ruleForm.method === "3") {
         state.ruleForm.pushDisabled = false;
-        state.ruleForm.push = '1';
+        state.ruleForm.push = "1";
       }
     };
     // 打开弹窗
@@ -174,16 +173,16 @@ export default defineComponent({
     const resetForm = () => {
       state.ruleForm = {
         id: 0,
-        name: '',
-        waitVersion: '',
-        method: '1',
+        name: "",
+        waitVersion: "",
+        method: "1",
         devices: [],
-        stratege: '2',
+        stratege: "2",
         devOtaFirmwareId: 0,
-        push: '2',
+        push: "2",
         pushDisabled: true,
         types: "1",
-        productKey: '',
+        productKey: "",
       };
     };
     // 关闭弹窗
@@ -206,16 +205,16 @@ export default defineComponent({
           if (state.ruleForm.id !== 0) {
             //修改
             api.batch.edit(state.ruleForm).then(() => {
-              ElMessage.success('升级包修改成功');
+              ElMessage.success("升级包修改成功");
               closeDialog(); // 关闭弹窗
-              emit('getList');
+              emit("getList");
             });
           } else {
             //添加
             api.batch.add(state.ruleForm).then(() => {
-              ElMessage.success('升级包添加成功');
+              ElMessage.success("升级包添加成功");
               closeDialog(); // 关闭弹窗
-              emit('getList');
+              emit("getList");
             });
           }
         }
@@ -246,11 +245,10 @@ export default defineComponent({
     };
   },
 });
-
 </script>
 
 <style lang="scss" scoped>
 .width100 {
   width: 100%;
 }
-</style>
+</style>

+ 63 - 63
src/views/iot/ota-update/update/component/device.vue

@@ -1,48 +1,46 @@
 <template>
   <div>
-	<el-card shadow="nover">
-		<div class="search">
-			<el-form inline ref="queryRef">
-				<el-form-item label="设备名称:" prop="name">
-					<el-input v-model="tableData.param.deviceName" placeholder="请输入设备名称" clearable style="width: 240px" @submit.prevent />
-				</el-form-item>
+    <el-card shadow="nover">
+      <div class="search">
+        <el-form inline ref="queryRef">
+          <el-form-item label="设备名称:" prop="name">
+            <el-input v-model="tableData.param.deviceName" placeholder="请输入设备名称" clearable style="width: 240px" @submit.prevent />
+          </el-form-item>
 
-				<el-form-item>
-
-					<el-button type="primary" class="ml10" @click="getDetail">
-						<el-icon>
-							<ele-Search />
-						</el-icon>
-						查询
-					</el-button>
-				</el-form-item>
-
-			</el-form>
-		</div>
-		<el-table :data="tableData.data" style="width: 100%" row-key="id" v-loading="tableData.loading">
-			<el-table-column prop="id" label="ID" width="100" show-overflow-tooltip></el-table-column>
-			<el-table-column prop="deviceName" label="设备名称" show-overflow-tooltip></el-table-column>
-			<el-table-column prop="status" label="状态" show-overflow-tooltip>
-				<template #default="scope">
-					<el-tag size="small" v-if="scope.row.status == 0">待推送</el-tag>
-					<el-tag size="small" v-if="scope.row.status == 1">已推送</el-tag>
-					<el-tag size="small" v-if="scope.row.status == 2">升级中</el-tag>
-					<el-tag size="small" v-if="scope.row.status == 3">升级成功</el-tag>
-					<el-tag size="small" v-if="scope.row.status == 4">升级失败</el-tag>
-					<el-tag size="small" v-if="scope.row.status == 5">已取消</el-tag>
-				</template>
-			</el-table-column>
-			<el-table-column prop="step" label="升级进度" show-overflow-tooltip></el-table-column>
-			<el-table-column prop="fail" label="失败原因" width="100" align="center">
-				<template #default="scope">
-					<el-tag size="small" v-if="scope.row.fail == -1">升级失败</el-tag>
-					<el-tag size="small" v-if="scope.row.fail == -2">下载失败</el-tag>
-					<el-tag size="small" v-if="scope.row.fail == -3">校验失败</el-tag>
-					<el-tag size="small" v-if="scope.row.fail == -4">烧写失败</el-tag>
-				</template>
-			</el-table-column>
-			<el-table-column prop="createdAt" label="时间" min-width="100" align="center"></el-table-column>
-			<!-- <el-table-column label="操作" width="200" align="center">
+          <el-form-item>
+            <el-button type="primary" class="ml10" @click="getDetail">
+              <el-icon>
+                <ele-Search />
+              </el-icon>
+              查询
+            </el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+      <el-table :data="tableData.data" style="width: 100%" row-key="id" v-loading="tableData.loading">
+        <el-table-column prop="id" label="ID" width="100" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="deviceName" label="设备名称" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="status" label="状态" show-overflow-tooltip>
+          <template #default="scope">
+            <el-tag size="small" v-if="scope.row.status == 0">待推送</el-tag>
+            <el-tag size="small" v-if="scope.row.status == 1">已推送</el-tag>
+            <el-tag size="small" v-if="scope.row.status == 2">升级中</el-tag>
+            <el-tag size="small" v-if="scope.row.status == 3">升级成功</el-tag>
+            <el-tag size="small" v-if="scope.row.status == 4">升级失败</el-tag>
+            <el-tag size="small" v-if="scope.row.status == 5">已取消</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="step" label="升级进度" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="fail" label="失败原因" width="100" align="center">
+          <template #default="scope">
+            <el-tag size="small" v-if="scope.row.fail == -1">升级失败</el-tag>
+            <el-tag size="small" v-if="scope.row.fail == -2">下载失败</el-tag>
+            <el-tag size="small" v-if="scope.row.fail == -3">校验失败</el-tag>
+            <el-tag size="small" v-if="scope.row.fail == -4">烧写失败</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="createdAt" label="时间" width="170" align="center"></el-table-column>
+        <!-- <el-table-column label="操作" width="200" align="center">
 				<template #default="scope">
 
 					<el-button size="small" text type="warning" v-auth="'edit'" @click="addOrEdit(scope.row)">编辑</el-button>
@@ -50,20 +48,19 @@
 					<el-button size="small" text type="danger" v-auth="'del'" @click="del(scope.row)">删除</el-button>
 				</template>
 			</el-table-column> -->
-		</el-table>
-<!--		<pagination v-if="params.total" :total="params.total" v-model:page="params.pageNum" v-model:limit="params.pageSize" @pagination="getList()" />-->
-    <pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="getDetail" />
-
-	</el-card>
-</div>
+      </el-table>
+      <!--		<pagination v-if="params.total" :total="params.total" v-model:page="params.pageNum" v-model:limit="params.pageSize" @pagination="getList()" />-->
+      <pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="getDetail" />
+    </el-card>
+  </div>
 </template>
 
 <script lang="ts">
-import api from '/@/api/ota';
-import { useSearch } from '/@/hooks/useCommon';
-import { ElMessageBox, ElMessage } from 'element-plus';
-import {ref, onMounted, defineComponent, reactive, toRefs} from 'vue';
-import { useRoute } from 'vue-router'
+import api from "/@/api/ota";
+import { useSearch } from "/@/hooks/useCommon";
+import { ElMessageBox, ElMessage } from "element-plus";
+import { ref, onMounted, defineComponent, reactive, toRefs } from "vue";
+import { useRoute } from "vue-router";
 import EditForm from "/@/views/iot/ota-update/update/component/edit.vue";
 import InfoList from "/@/views/iot/ota-update/update/component/info.vue";
 import BatchList from "/@/views/iot/ota-update/update/component/batch.vue";
@@ -94,7 +91,7 @@ interface TableDataState {
 
 export default defineComponent({
   setup(props) {
-    const route = useRoute()
+    const route = useRoute();
     const state = reactive<TableDataState>({
       ids: [],
       tableData: {
@@ -104,30 +101,33 @@ export default defineComponent({
         param: {
           pageNum: 1,
           pageSize: 20,
-          deviceName: '',
+          deviceName: "",
           devOtaFirmwareId: 0,
         },
       },
     });
     const getDetail = () => {
       state.tableData.loading = true;
-      const id = route.params && route.params.id
+      const id = route.params && route.params.id;
       state.tableData.param.devOtaFirmwareId = Number(id);
-      api.device.getList(state.tableData.param).then((res: any) => {
-        state.tableData.data = res.Data;
-        state.tableData.total = res.Total;
-      }).finally(() => (state.tableData.loading = false));
+      api.device
+        .getList(state.tableData.param)
+        .then((res: any) => {
+          state.tableData.data = res.Data;
+          state.tableData.total = res.Total;
+        })
+        .finally(() => (state.tableData.loading = false));
     };
     onMounted(() => {
-      getDetail()
+      getDetail();
     });
     return {
       getDetail,
       ...toRefs(props),
       ...toRefs(state),
-    }
+    };
   },
-})
+});
 
 // const props = defineProps({
 // 	detail: {

+ 30 - 24
src/views/iot/ota-update/update/component/deviceList.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="ota-edit-module-container">
-    <el-dialog :title="'设备详情'" :before-close="closeDialog" v-model="isShowDialog" width="769px">
+    <el-dialog :title="'设备详情'" :before-close="closeDialog" v-model="isShowDialog" width="1000px">
       <div class="search">
         <el-form inline ref="queryRef">
           <el-form-item label="设备名称:" prop="name">
@@ -17,10 +17,10 @@
         </el-form>
       </div>
       <el-table :data="tableData.data" style="width: 100%" row-key="id" v-loading="tableData.loading">
-        <el-table-column prop="id" label="ID" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="id" label="ID" width="100" show-overflow-tooltip align="center"></el-table-column>
         <el-table-column prop="deviceName" label="设备名称" show-overflow-tooltip></el-table-column>
-        <el-table-column prop="deviceKey" label="设备标识"></el-table-column>
-        <el-table-column prop="status" label="状态" show-overflow-tooltip>
+        <el-table-column prop="deviceKey" label="设备标识" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="status" label="状态" show-overflow-tooltip align="center">
           <template #default="scope">
             <el-tag size="small" v-if="scope.row.status == 0">待推送</el-tag>
             <el-tag size="small" v-if="scope.row.status == 1">已推送</el-tag>
@@ -30,7 +30,7 @@
             <el-tag size="small" v-if="scope.row.status == 5">已取消</el-tag>
           </template>
         </el-table-column>
-        <el-table-column prop="step" label="升级进度" show-overflow-tooltip>
+        <el-table-column prop="step" label="升级进度" show-overflow-tooltip align="center">
           <template #default="scope">
             <el-tag size="small" type="success" v-if="scope.row.step > 0">{{ scope.row.step }}%</el-tag>
             <el-tag size="small" v-else>{{ scope.row.step }}</el-tag>
@@ -45,8 +45,8 @@
           </template>
         </el-table-column>
         <el-table-column prop="desc" label="备注信息" show-overflow-tooltip></el-table-column>
-        <el-table-column prop="createdAt" label="时间" min-width="100" align="center"></el-table-column>
-        <el-table-column label="操作" width="200" align="center">
+        <el-table-column prop="createdAt" label="时间" width="160" align="center"></el-table-column>
+        <el-table-column label="操作" width="80" align="center">
           <template #default="scope">
             <el-button size="small" text type="primary" @click="distribute(scope.row)">手动下发</el-button>
           </template>
@@ -58,9 +58,9 @@
 </template>
 
 <script lang="ts">
-import api from '/@/api/ota';
-import {defineComponent, reactive, toRefs} from 'vue';
-import {ElMessage} from "element-plus";
+import api from "/@/api/ota";
+import { defineComponent, reactive, toRefs } from "vue";
+import { ElMessage } from "element-plus";
 
 interface TableDataRow {
   id: number;
@@ -100,7 +100,7 @@ export default defineComponent({
         param: {
           pageNum: 1,
           pageSize: 20,
-          deviceName: '',
+          deviceName: "",
           devOtaStrategy: 0,
         },
       },
@@ -111,10 +111,13 @@ export default defineComponent({
     const openDialog = (row: any) => {
       state.tableData.loading = true;
       state.tableData.param.devOtaStrategy = Number(row.id);
-      api.device.getList(state.tableData.param).then((res: any) => {
-        state.tableData.data = res.Data;
-        state.tableData.total = res.Total;
-      }).finally(() => (state.tableData.loading = false));
+      api.device
+        .getList(state.tableData.param)
+        .then((res: any) => {
+          state.tableData.data = res.Data;
+          state.tableData.total = res.Total;
+        })
+        .finally(() => (state.tableData.loading = false));
       state.isShowDialog = true;
     };
     // 关闭弹窗
@@ -128,28 +131,31 @@ export default defineComponent({
     };
     const getDetail = () => {
       state.tableData.loading = true;
-      api.device.getList(state.tableData.param).then((res: any) => {
-        state.tableData.data = res.Data;
-        state.tableData.total = res.Total;
-      }).finally(() => (state.tableData.loading = false));
+      api.device
+        .getList(state.tableData.param)
+        .then((res: any) => {
+          state.tableData.data = res.Data;
+          state.tableData.total = res.Total;
+        })
+        .finally(() => (state.tableData.loading = false));
     };
     // 手动下发
     const distribute = (row: any) => {
       const deviceKey = row.deviceKey;
       const strategyId = row.strategyId;
-      api.batch.distribute({deviceKey: deviceKey, strategyId: strategyId}).then(() => {
-        ElMessage.success('操作成功');
+      api.batch.distribute({ deviceKey: deviceKey, strategyId: strategyId }).then(() => {
+        ElMessage.success("操作成功");
       });
       // 定时请求列表数据
       timer();
-    }
+    };
     // 定时请求列表
     const timer = () => {
       // 因列表更新数据不是实时更新,需设置定时后在请求列表
       state.timeoutTimer = setTimeout(() => {
         getDetail();
       }, 3000);
-    }
+    };
     return {
       getDetail,
       openDialog,
@@ -166,4 +172,4 @@ export default defineComponent({
 .width100 {
   width: 100%;
 }
-</style>
+</style>

+ 26 - 30
src/views/iot/ota-update/update/detail.vue

@@ -3,10 +3,10 @@
     <div class="content">
       <div class="flex cont_box">
         <div class="font26">升级包名称:{{ detail.name }}</div>
-        <div class="pro-status"><span :class="detail.checkres == 1 ? 'on' : 'off'"></span>{{ detail.checkres == 1 ? '已验证' : '未验证' }}</div>
+        <div class="pro-status"><span :class="detail.checkres == 1 ? 'on' : 'off'"></span>{{ detail.checkres == 1 ? "已验证" : "未验证" }}</div>
       </div>
       <div class="container mt-2">
-        <div class="item">升级包类型:{{ detail.types == 1 ? '整包' : '差分' }}</div>
+        <div class="item">升级包类型:{{ detail.types == 1 ? "整包" : "差分" }}</div>
         <div class="item">升级包签名:{{ detail.sign }}</div>
       </div>
       <div class="container mb-2">
@@ -25,45 +25,45 @@
   </div>
 </template>
 <script lang="ts">
-import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'
-import { useRoute } from 'vue-router'
-import { EditPen, DocumentAdd } from '@element-plus/icons-vue'
-import EditForm from '/@/views/iot/ota-update/update/component/edit.vue';
-import InfoList from './component/info.vue'
-import DeviceList from './component/device.vue'
-import BatchList from './component/batch.vue'
-import api from '/@/api/ota'
+import { toRefs, reactive, onMounted, ref, defineComponent } from "vue";
+import { useRoute } from "vue-router";
+import { EditPen, DocumentAdd } from "@element-plus/icons-vue";
+import EditForm from "/@/views/iot/ota-update/update/component/edit.vue";
+import InfoList from "./component/info.vue";
+import DeviceList from "./component/device.vue";
+import BatchList from "./component/batch.vue";
+import api from "/@/api/ota";
 
-const editFormRef = ref()
+const editFormRef = ref();
 
 export default defineComponent({
   components: { EditPen, EditForm, DocumentAdd, InfoList, DeviceList, BatchList },
   setup(props) {
-    const route = useRoute()
+    const route = useRoute();
     const state = reactive({
-      activeTab: 'tab1',
+      activeTab: "tab1",
       developer_status: 2,
       detail: {
-        id: '',
-        name: '',
+        id: "",
+        name: "",
         types: 1,
-        are: '',
-        moduleName: '',
+        are: "",
+        moduleName: "",
         checkres: 0,
-        sign: '',
+        sign: "",
       },
     });
     const getDetail = () => {
-      const id = route.params && route.params.id
+      const id = route.params && route.params.id;
       api.manage.detail(Number(id)).then((res: any) => {
-        state.detail = res
-      })
+        state.detail = res;
+      });
     };
     const addOrEdit = async (row?: any) => {
-      editFormRef.value.open(row)
+      editFormRef.value.open(row);
     };
     onMounted(() => {
-      getDetail()
+      getDetail();
     });
     return {
       addOrEdit,
@@ -71,9 +71,9 @@ export default defineComponent({
       getDetail,
       ...toRefs(props),
       ...toRefs(state),
-    }
+    };
   },
-})
+});
 </script>
 
 <style scoped lang="scss">
@@ -129,7 +129,6 @@ export default defineComponent({
             border-radius: 50%;
             margin-right: 5px;
           }
-
         }
 
         .otaflex_div3 {
@@ -138,10 +137,7 @@ export default defineComponent({
           color: #373d41;
         }
       }
-
-
     }
-
   }
 }
 
@@ -187,4 +183,4 @@ export default defineComponent({
     margin-right: 5px;
   }
 }
-</style>
+</style>