yanglzh 7 місяців тому
батько
коміт
3746cea786

+ 7 - 3
src/views/iot/alarm/dashboard/index.vue

@@ -46,10 +46,8 @@
 
 <script lang="ts" setup>
 import { toRefs, reactive, onMounted, ref, watch, nextTick, onActivated, getCurrentInstance, onUnmounted } from 'vue'
-import 'vue-data-ui/style.css'
 import api from '/@/api/alarm'
 import AlarmList from '/@/views/iot/alarm/list/index.vue'
-import { useThemeChange } from '/@/hooks/useCommon'
 import Chart from '/@/components/chart/index.vue'
 import { getLineOption, getPie2Option, getPie3Option, getPie4Option, getPieOption } from '/@/components/chart/options'
 import dayjs from 'dayjs'
@@ -177,6 +175,12 @@ const getOverviewData = () => {
 			endDate: dayjs().endOf('month').format('YYYY-MM-DD'),
 		})
 		.then((res: any) => {
+			const statusMap = {
+				0: '未处理',
+				1: '已处理',
+				2: '已忽略',
+			}
+
 			const resData = res || [
 				{
 					alarmCount: 4,
@@ -194,7 +198,7 @@ const getOverviewData = () => {
 			console.log(resData)
 			chart3.value?.draw(
 				getPieOption({
-					data: resData.map((item: any) => ({ name: item.status, value: item.alarmCount })),
+					data: resData.map((item: any) => ({ name: statusMap[item.status as keyof typeof statusMap], value: item.alarmCount })),
 				})
 			)
 		})

+ 232 - 223
src/views/iot/ota-update/update/component/batch.vue

@@ -1,236 +1,245 @@
 <template>
-  <div class="page page-full">
-    <el-form :model="tableData.param" ref="queryRef" inline label-width="90px" @keyup.enter.native="getList(1)">
-      <el-form-item label="批次名称:" prop="name">
-        <el-input v-model="tableData.param.keyWord" placeholder="请输入批次名称" clearable style="width: 240px" />
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" class="ml10" @click="getList(1)">
-          <el-icon>
-            <ele-Search />
-          </el-icon>
-          查询
-        </el-button>
-        <el-button @click="resetQuery()">
-          <el-icon>
-            <ele-Refresh />
-          </el-icon>
-          重置
-        </el-button>
-        <el-button type="primary" @click="onOpenAdd()">
-          <el-icon>
-            <ele-FolderAdd />
-          </el-icon>
-          添加批次
-        </el-button>
-      </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" 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">
-        <template #default="scope">
-          <el-tag type="success" size="small" v-if="scope.row.types == 0">验证</el-tag>
-          <el-tag type="primary" size="small" v-else>升级</el-tag>
-        </template>
-      </el-table-column>
-      <el-table-column label="状态" prop="active" width="120" align="center">
-        <template #default="scope">
-          <el-tag type="success" size="small" v-if="scope.row.active == 1">是</el-tag>
-          <el-tag type="info" size="small" v-else>否</el-tag>
-        </template>
-      </el-table-column>
-      <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 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>
+	<div class="page page-full">
+		<el-form :model="tableData.param" ref="queryRef" inline label-width="90px" @keyup.enter.native="getList(1)">
+			<el-form-item label="批次名称:" prop="name">
+				<el-input v-model="tableData.param.keyWord" placeholder="请输入批次名称" clearable style="width: 240px" />
+			</el-form-item>
+			<el-form-item>
+				<el-button type="primary" class="ml10" @click="getList(1)">
+					<el-icon>
+						<ele-Search />
+					</el-icon>
+					查询
+				</el-button>
+				<el-button @click="resetQuery()">
+					<el-icon>
+						<ele-Refresh />
+					</el-icon>
+					重置
+				</el-button>
+				<el-button type="primary" @click="onOpenAdd()">
+					<el-icon>
+						<ele-FolderAdd />
+					</el-icon>
+					添加批次
+				</el-button>
+			</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" 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">
+				<template #default="scope">
+					<el-tag type="success" size="small" v-if="scope.row.types == 0">验证</el-tag>
+					<el-tag type="primary" size="small" v-else>升级</el-tag>
+				</template>
+			</el-table-column>
+			<el-table-column label="状态" prop="status" width="120" align="center">
+				<template #default="scope">
+					<el-tag type="primary" size="small" v-if="scope.row.status == 1">升级中</el-tag>
+					<el-tag type="success" size="small" v-else>完成</el-tag>
+				</template>
+			</el-table-column>
+			<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 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 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="创建时间" width="160" align="center" />
-      <el-table-column label="操作" width="120" align="center">
-        <template #default="scope">
-          <el-button size="small" text type="primary" @click="getDeviceList(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>
-    <pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="getList" />
-    <CheckConfig ref="checkRef" @getList="getList(1)" />
-    <DeviceList ref="deviceRef" />
-  </div>
+			<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="创建时间" width="160" align="center" />
+			<el-table-column label="操作" width="120" align="center">
+				<template #default="scope">
+					<el-button size="small" text type="primary" @click="getDeviceList(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>
+		<pagination
+			v-show="tableData.total > 0"
+			:total="tableData.total"
+			v-model:page="tableData.param.pageNum"
+			v-model:limit="tableData.param.pageSize"
+			@pagination="getList"
+		/>
+		<CheckConfig ref="checkRef" @getList="getList(1)" />
+		<DeviceList ref="deviceRef" />
+	</div>
 </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 {
-  id: number;
-  name: string;
-  waitVersion: string;
-  method: number;
-  stratege: string;
-  push: string;
-  createdAt: string;
+	id: number
+	name: string
+	waitVersion: string
+	method: number
+	stratege: string
+	push: string
+	createdAt: string
 }
 interface TableDataState {
-  ids: number[];
-  tableData: {
-    data: Array<TableDataRow>;
-    total: number;
-    loading: boolean;
-    param: {
-      id: number;
-      pageNum: number;
-      pageSize: number;
-      keyWord: string;
-      dateRange: string[];
-      devOtaFirmwareId: number;
-    };
-  };
+	ids: number[]
+	tableData: {
+		data: Array<TableDataRow>
+		total: number
+		loading: boolean
+		param: {
+			id: number
+			pageNum: number
+			pageSize: number
+			productKey: string
+			keyWord: string
+			dateRange: string[]
+			devOtaFirmwareId: number
+		}
+	}
 }
 export default defineComponent({
-  components: { CheckConfig, DeviceList },
-  props: {
-    detail: {
-      type: Object,
-      default: "",
-    },
-  },
-  setup(props) {
-    const deviceRef = ref();
-    const checkRef = ref();
-    const queryRef = ref();
-    const tabDataList = ref([{ dictLabel: "全部", dictValue: "" }]);
-    const state = reactive<TableDataState>({
-      ids: [],
-      tableData: {
-        data: [],
-        total: 0,
-        loading: false,
-        param: {
-          id: 0,
-          dateRange: [],
-          pageNum: 1,
-          pageSize: 20,
-          keyWord: "",
-          devOtaFirmwareId: 0,
-        },
-      },
-    });
-    // 页面加载时
-    onMounted(() => {
-      initTableData();
-    });
-    // 激活操作
-    const activation = (row: any) => {
-      let active = 0;
-      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("操作成功");
-        batchList();
-      });
-    };
-    // 初始化表格数据
-    const initTableData = () => {
-      batchList();
-    };
-    const getList = (pageNum?: number) => {
-      typeof pageNum === "number" && (state.tableData.param.pageNum = pageNum);
-      state.tableData.loading = true;
-      state.tableData.param.devOtaFirmwareId = props.detail.id;
-      api.batch
-        .getList(state.tableData.param)
-        .then((res: any) => {
-          state.tableData.data = res.Data;
-          state.tableData.total = res.Total;
-        })
-        .finally(() => (state.tableData.loading = false));
-    };
-    // 打开新增弹窗
-    const onOpenAdd = () => {
-      state.tableData.param.id = props.detail.id;
-      checkRef.value.openDialog(state.tableData.param);
-    };
-    // 删除模块
-    const onRowDel = (row?: TableDataRow) => {
-      let msg = "你确定要删除所选数据?";
-      let ids: number[] = [];
-      if (row) {
-        msg = `此操作将永久删除:“${row.name}”,是否继续?`;
-        ids = [row.id];
-      } else {
-        ids = state.ids;
-      }
-      if (ids.length === 0) {
-        ElMessage.error("请选择要删除的数据。");
-        return;
-      }
-      ElMessageBox.confirm(msg, "提示", {
-        confirmButtonText: "确认",
-        cancelButtonText: "取消",
-        type: "warning",
-      })
-        .then(() => {
-          api.batch.del(ids).then(() => {
-            ElMessage.success("删除成功");
-            getList();
-          });
-        })
-        .catch(() => {});
-    };
-    /** 重置按钮操作 */
-    const resetQuery = () => {
-      queryRef.value.resetFields();
-      getList();
-    };
-    // 多选框选中数据
-    const handleSelectionChange = (selection: TableDataRow[]) => {
-      state.ids = selection.map((item) => item.id);
-    };
-    // 获取列表
-    const batchList = () => {
-      getList();
-    };
-    const getDeviceList = (row: any) => {
-      deviceRef.value.openDialog(row);
-    };
-    return {
-      deviceRef,
-      checkRef,
-      queryRef,
-      tabDataList,
-      onOpenAdd,
-      onRowDel,
-      getList,
-      activation,
-      resetQuery,
-      handleSelectionChange,
-      getDeviceList,
-      ...toRefs(props),
-      ...toRefs(state),
-    };
-  },
-});
+	components: { CheckConfig, DeviceList },
+	props: {
+		detail: {
+			type: Object,
+			default: '',
+		},
+	},
+	setup(props) {
+		const deviceRef = ref()
+		const checkRef = ref()
+		const queryRef = ref()
+		const tabDataList = ref([{ dictLabel: '全部', dictValue: '' }])
+		const state = reactive<TableDataState>({
+			ids: [],
+			tableData: {
+				data: [],
+				total: 0,
+				loading: false,
+				param: {
+					id: 0,
+					dateRange: [],
+					pageNum: 1,
+					pageSize: 20,
+					keyWord: '',
+					productKey: '',
+					devOtaFirmwareId: 0,
+				},
+			},
+		})
+		// 页面加载时
+		onMounted(() => {
+			initTableData()
+		})
+		// 激活操作
+		const activation = (row: any) => {
+			let active = 0
+			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('操作成功')
+				batchList()
+			})
+		}
+		// 初始化表格数据
+		const initTableData = () => {
+			batchList()
+		}
+		const getList = (pageNum?: number) => {
+			typeof pageNum === 'number' && (state.tableData.param.pageNum = pageNum)
+			state.tableData.loading = true
+			state.tableData.param.devOtaFirmwareId = props.detail.id
+			state.tableData.param.productKey = props.detail.productKey
+			api.batch
+				.getList(state.tableData.param)
+				.then((res: any) => {
+					state.tableData.data = res.Data
+					state.tableData.total = res.Total
+				})
+				.finally(() => (state.tableData.loading = false))
+		}
+		// 打开新增弹窗
+		const onOpenAdd = () => {
+			state.tableData.param.id = props.detail.id
+			checkRef.value.openDialog(state.tableData.param, props.detail)
+		}
+		// 删除模块
+		const onRowDel = (row?: TableDataRow) => {
+			let msg = '你确定要删除所选数据?'
+			let ids: number[] = []
+			if (row) {
+				msg = `此操作将永久删除:“${row.name}”,是否继续?`
+				ids = [row.id]
+			} else {
+				ids = state.ids
+			}
+			if (ids.length === 0) {
+				ElMessage.error('请选择要删除的数据。')
+				return
+			}
+			ElMessageBox.confirm(msg, '提示', {
+				confirmButtonText: '确认',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(() => {
+					api.batch.del(ids).then(() => {
+						ElMessage.success('删除成功')
+						getList()
+					})
+				})
+				.catch(() => {})
+		}
+		/** 重置按钮操作 */
+		const resetQuery = () => {
+			queryRef.value.resetFields()
+			getList()
+		}
+		// 多选框选中数据
+		const handleSelectionChange = (selection: TableDataRow[]) => {
+			state.ids = selection.map((item) => item.id)
+		}
+		// 获取列表
+		const batchList = () => {
+			getList()
+		}
+		const getDeviceList = (row: any) => {
+			deviceRef.value.openDialog(row)
+		}
+		return {
+			deviceRef,
+			checkRef,
+			queryRef,
+			tabDataList,
+			onOpenAdd,
+			onRowDel,
+			getList,
+			activation,
+			resetQuery,
+			handleSelectionChange,
+			getDeviceList,
+			...toRefs(props),
+			...toRefs(state),
+		}
+	},
+})
 </script>

+ 234 - 229
src/views/iot/ota-update/update/component/check.vue

@@ -1,254 +1,259 @@
 <template>
-  <div class="ota-edit-module-container">
-    <el-dialog :title="'操作升级包'" v-model="isShowDialog" width="769px">
-      <el-form :model="ruleForm" ref="formRef" :rules="rules" label-width="160px">
-        <el-form-item label="类型" prop="formType" @change="getFormType">
-          <el-radio-group v-model="ruleForm.types">
-            <el-radio label="1">验证</el-radio>
-            <el-radio label="2">升级</el-radio>
-          </el-radio-group>
-        </el-form-item>
+	<div class="ota-edit-module-container">
+		<el-dialog :title="'操作升级包'" v-model="isShowDialog" width="600px">
+			<el-form :model="ruleForm" ref="formRef" :rules="rules" label-width="100px">
+				<el-form-item label="类型" prop="formType" @change="getFormType">
+					<el-radio-group v-model="ruleForm.types">
+						<el-radio label="1">验证</el-radio>
+						<el-radio label="2" :disabled="!showUpdate">升级</el-radio>
+					</el-radio-group>
+				</el-form-item>
 
-        <el-form-item label="批次名称" prop="name">
-          <el-input v-model="ruleForm.name" placeholder="请输入批次名称" />
-        </el-form-item>
+				<el-form-item label="批次名称" prop="name">
+					<el-input v-model="ruleForm.name" placeholder="请输入批次名称" />
+				</el-form-item>
 
-        <el-form-item label="协议方式" prop="method">
-          <el-radio-group v-model="ruleForm.method" @change="getMethod">
-            <el-radio label="1">http</el-radio>
-            <el-radio label="2">https</el-radio>
-            <el-radio label="3">mqtt</el-radio>
-          </el-radio-group>
-        </el-form-item>
+				<el-form-item label="协议方式" prop="method">
+					<el-radio-group v-model="ruleForm.method" @change="getMethod">
+						<el-radio label="1">http</el-radio>
+						<el-radio label="2">https</el-radio>
+						<el-radio label="3">mqtt</el-radio>
+					</el-radio-group>
+				</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>
-          </template>
+				<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>
+					</template>
 
-          <el-button type="primary" @click="onOpenDevice()" style="margin-left: 5px; margin-top: 10px">选择设备</el-button>
-        </el-form-item>
+					<el-button type="primary" @click="onOpenDevice()" style="margin-left: 5px">选择设备</el-button>
+				</el-form-item>
 
-        <el-form-item label="升级方式" prop="stratege">
-          <el-radio-group v-model="ruleForm.stratege">
-            <el-radio label="1">静态升级</el-radio>
-            <el-radio label="2">动态升级</el-radio>
-          </el-radio-group>
-        </el-form-item>
+				<el-form-item label="升级方式" prop="stratege">
+					<el-radio-group v-model="ruleForm.stratege">
+						<el-radio label="1">静态升级</el-radio>
+						<el-radio label="2">动态升级</el-radio>
+					</el-radio-group>
+				</el-form-item>
 
-        <el-form-item label="主动推送" prop="push">
-          <el-radio-group v-model="ruleForm.push">
-            <el-radio label="1" :disabled="ruleForm.pushDisabled">是</el-radio>
-            <el-radio label="2">否</el-radio>
-          </el-radio-group>
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <span class="dialog-footer">
-          <el-button @click="onCancel">取 消</el-button>
-          <el-button type="primary" @click="onSubmit">{{ ruleForm.id !== 0 ? "修 改" : "添 加" }}</el-button>
-        </span>
-      </template>
-    </el-dialog>
+				<el-form-item label="主动推送" prop="push">
+					<el-radio-group v-model="ruleForm.push">
+						<el-radio label="1" :disabled="ruleForm.pushDisabled">是</el-radio>
+						<el-radio label="2">否</el-radio>
+					</el-radio-group>
+				</el-form-item>
+			</el-form>
+			<template #footer>
+				<span class="dialog-footer">
+					<el-button @click="onCancel">取 消</el-button>
+					<el-button type="primary" @click="onSubmit">{{ ruleForm.id !== 0 ? '修 改' : '添 加' }}</el-button>
+				</span>
+			</template>
+		</el-dialog>
 
-    <!-- 设备绑定弹窗 -->
-    <DeviceBind ref="deviceRef" @bindSuccess="getDeviceTableData" />
-  </div>
+		<!-- 设备绑定弹窗 -->
+		<DeviceBind ref="deviceRef" @bindSuccess="getDeviceTableData" />
+	</div>
 </template>
 
 <script lang="ts">
-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";
+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'
 
 interface RuleFormState {
-  id: number;
-  name: string;
-  waitVersion: string;
-  method: string;
-  devices: string[];
-  stratege: string;
-  devOtaFirmwareId: number;
-  push: string;
-  pushDisabled: boolean;
-  types: string;
-  productKey: string;
+	id: number
+	name: string
+	waitVersion: string
+	method: string
+	devices: string[]
+	stratege: string
+	devOtaFirmwareId: number
+	push: string
+	pushDisabled: boolean
+	types: string
+	productKey: string
 }
 interface UpdateState {
-  isShowDialog: boolean;
-  ruleForm: RuleFormState;
-  productData: [];
-  rules: {};
-  deviceShow: boolean;
-  deviceNameShow: boolean;
-  deviceNameList: [];
+	isShowDialog: boolean
+	showUpdate: boolean
+	ruleForm: RuleFormState
+	productData: []
+	rules: {}
+	deviceShow: boolean
+	deviceNameShow: boolean
+	deviceNameList: []
 }
 
 export default defineComponent({
-  name: "otaEditUpdateData",
-  components: { DeviceBind },
-  computed: {
-    rule() {
-      return rule;
-    },
-  },
-  setup(prop, { emit }) {
-    const deviceRef = ref();
-    const formRef = ref<HTMLElement | null>(null);
-    const state = reactive<UpdateState>({
-      isShowDialog: false,
-      ruleForm: {
-        id: 0,
-        name: "",
-        waitVersion: "",
-        method: "1",
-        devices: [],
-        stratege: "2",
-        devOtaFirmwareId: 0,
-        push: "2",
-        pushDisabled: true,
-        types: "1",
-        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" }],
-      },
-      deviceShow: false, // 所属设备是否显示
-      deviceNameShow: false, // 回显设备名称状态
-      deviceNameList: [], // 回显设备名称
-    });
-    // 页面加载时
-    onMounted(() => {
-      getFormType();
-    });
-    // 获取操作升级包类型
-    const getFormType = () => {
-      // 如果是验证类型,设备信息必填项
-      if (state.ruleForm.types === "1") {
-        state.deviceShow = true;
-      } else {
-        state.deviceShow = false;
-      }
-    };
-    // 获取协议方式
-    const getMethod = () => {
-      // 如果是http、https协议则主动推送为否
-      // if (state.ruleForm.method === '1') {
-      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") {
-        state.ruleForm.pushDisabled = false;
-        state.ruleForm.push = "1";
-      }
-    };
-    // 打开弹窗
-    const openDialog = (row: RuleFormState | null) => {
-      resetForm();
-      state.deviceNameList = [];
-      state.deviceNameShow = false;
-      if (row) {
-        state.ruleForm.devOtaFirmwareId = row.id;
-        state.ruleForm.productKey = row.productKey;
-      }
-      state.isShowDialog = true;
+	name: 'otaEditUpdateData',
+	components: { DeviceBind },
+	computed: {
+		rule() {
+			return rule
+		},
+	},
+	setup(prop, { emit }) {
+		const deviceRef = ref()
+		const formRef = ref<HTMLElement | null>(null)
+		const state = reactive<UpdateState>({
+			isShowDialog: false,
+			showUpdate: false,
+			ruleForm: {
+				id: 0,
+				name: '',
+				waitVersion: '',
+				method: '1',
+				devices: [],
+				stratege: '2',
+				devOtaFirmwareId: 0,
+				push: '2',
+				pushDisabled: true,
+				types: '1',
+				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' }],
+			},
+			deviceShow: false, // 所属设备是否显示
+			deviceNameShow: false, // 回显设备名称状态
+			deviceNameList: [], // 回显设备名称
+		})
+		// 页面加载时
+		onMounted(() => {
+			getFormType()
+		})
+		// 获取操作升级包类型
+		const getFormType = () => {
+			// 如果是验证类型,设备信息必填项
+			if (state.ruleForm.types === '1') {
+				state.deviceShow = true
+			} else {
+				state.deviceShow = false
+			}
+		}
+		// 获取协议方式
+		const getMethod = () => {
+			// 如果是http、https协议则主动推送为否
+			// if (state.ruleForm.method === '1') {
+			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') {
+				state.ruleForm.pushDisabled = false
+				state.ruleForm.push = '1'
+			}
+		}
+		// 打开弹窗
+		const openDialog = (row: RuleFormState | null, detail: any) => {
+			resetForm()
+			state.deviceNameList = []
+			state.deviceNameShow = false
+			if (row) {
+				state.ruleForm.devOtaFirmwareId = row.id
+				state.ruleForm.productKey = row.productKey
+			}
+			// 升级包状态是已验证才能选择升级类型,否则不可以
+			// 如果升级包是不需要验证类型的,则可以选择升级类型
+			state.showUpdate = detail.checkres === 2 || detail.check === 2
+			state.isShowDialog = true
 
-      if (state.ruleForm.types == "1") {
-        state.deviceShow = true;
-      }
-    };
-    const resetForm = () => {
-      state.ruleForm = {
-        id: 0,
-        name: "",
-        waitVersion: "",
-        method: "1",
-        devices: [],
-        stratege: "2",
-        devOtaFirmwareId: 0,
-        push: "2",
-        pushDisabled: true,
-        types: "1",
-        productKey: "",
-      };
-    };
-    // 关闭弹窗
-    const closeDialog = () => {
-      state.isShowDialog = false;
-      state.deviceNameList = [];
-      state.deviceNameShow = false;
-    };
-    // 取消
-    const onCancel = () => {
-      closeDialog();
-    };
-    // 新增
-    const onSubmit = () => {
-      const formWrap = unref(formRef) as any;
-      if (!formWrap) return;
-      formWrap.validate((valid: boolean) => {
-        if (valid) {
-          // 如果是升级类型,设备可选可不选
-          if (state.ruleForm.id !== 0) {
-            //修改
-            api.batch.edit(state.ruleForm).then(() => {
-              ElMessage.success("升级包修改成功");
-              closeDialog(); // 关闭弹窗
-              emit("getList");
-            });
-          } else {
-            //添加
-            api.batch.add(state.ruleForm).then(() => {
-              ElMessage.success("升级包添加成功");
-              closeDialog(); // 关闭弹窗
-              emit("getList");
-            });
-          }
-        }
-      });
-    };
-    // 获取设备列表
-    const getDeviceTableData = (deviceKeyList: any, deviceNameList: any) => {
-      state.ruleForm.devices = deviceKeyList;
-      state.deviceNameList = deviceNameList;
-      state.deviceNameShow = true;
-    };
-    // 打开设备列表
-    const onOpenDevice = () => {
-      deviceRef.value.openDialog(state.ruleForm.devices, state.ruleForm.productKey);
-    };
-    return {
-      deviceRef,
-      openDialog,
-      closeDialog,
-      onCancel,
-      onSubmit,
-      getMethod,
-      getFormType,
-      onOpenDevice,
-      getDeviceTableData,
-      formRef,
-      ...toRefs(state),
-    };
-  },
-});
+			if (state.ruleForm.types == '1') {
+				state.deviceShow = true
+			}
+		}
+		const resetForm = () => {
+			state.ruleForm = {
+				id: 0,
+				name: '',
+				waitVersion: '',
+				method: '1',
+				devices: [],
+				stratege: '2',
+				devOtaFirmwareId: 0,
+				push: '2',
+				pushDisabled: true,
+				types: '1',
+				productKey: '',
+			}
+		}
+		// 关闭弹窗
+		const closeDialog = () => {
+			state.isShowDialog = false
+			state.deviceNameList = []
+			state.deviceNameShow = false
+		}
+		// 取消
+		const onCancel = () => {
+			closeDialog()
+		}
+		// 新增
+		const onSubmit = () => {
+			const formWrap = unref(formRef) as any
+			if (!formWrap) return
+			formWrap.validate((valid: boolean) => {
+				if (valid) {
+					// 如果是升级类型,设备可选可不选
+					if (state.ruleForm.id !== 0) {
+						//修改
+						api.batch.edit(state.ruleForm).then(() => {
+							ElMessage.success('升级包修改成功')
+							closeDialog() // 关闭弹窗
+							emit('getList')
+						})
+					} else {
+						//添加
+						api.batch.add(state.ruleForm).then(() => {
+							ElMessage.success('升级包添加成功')
+							closeDialog() // 关闭弹窗
+							emit('getList')
+						})
+					}
+				}
+			})
+		}
+		// 获取设备列表
+		const getDeviceTableData = (deviceKeyList: any, deviceNameList: any) => {
+			state.ruleForm.devices = deviceKeyList
+			state.deviceNameList = deviceNameList
+			state.deviceNameShow = true
+		}
+		// 打开设备列表
+		const onOpenDevice = () => {
+			deviceRef.value.openDialog(state.ruleForm.devices, state.ruleForm.productKey)
+		}
+		return {
+			deviceRef,
+			openDialog,
+			closeDialog,
+			onCancel,
+			onSubmit,
+			getMethod,
+			getFormType,
+			onOpenDevice,
+			getDeviceTableData,
+			formRef,
+			...toRefs(state),
+		}
+	},
+})
 </script>
 
 <style lang="scss" scoped>
 .width100 {
-  width: 100%;
+	width: 100%;
 }
 </style>

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

@@ -1,46 +1,47 @@
 <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>
+	<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-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">
+					<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">
+						<!-- 0待推送,1已推送,2升级中,3升级成功,4升级失败,5已取消 -->
+						<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>
@@ -48,86 +49,92 @@
 					<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 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";
+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'
 
 interface TableDataRow {
-  id: number;
-  name: string;
-  types: string;
-  productName: number;
-  moduleName: string;
-  checkres: string;
-  createdAt: string;
+	id: number
+	name: string
+	types: string
+	productName: number
+	moduleName: string
+	checkres: string
+	createdAt: string
 }
 interface TableDataState {
-  ids: number[];
-  tableData: {
-    data: Array<TableDataRow>;
-    total: number;
-    loading: boolean;
-    param: {
-      pageNum: number;
-      pageSize: number;
-      deviceName: string;
-      devOtaFirmwareId: number;
-    };
-  };
+	ids: number[]
+	tableData: {
+		data: Array<TableDataRow>
+		total: number
+		loading: boolean
+		param: {
+			pageNum: number
+			pageSize: number
+			deviceName: string
+			devOtaFirmwareId: number
+		}
+	}
 }
 
 export default defineComponent({
-  setup(props) {
-    const route = useRoute();
-    const state = reactive<TableDataState>({
-      ids: [],
-      tableData: {
-        data: [],
-        total: 0,
-        loading: false,
-        param: {
-          pageNum: 1,
-          pageSize: 20,
-          deviceName: "",
-          devOtaFirmwareId: 0,
-        },
-      },
-    });
-    const getDetail = () => {
-      state.tableData.loading = true;
-      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));
-    };
-    onMounted(() => {
-      getDetail();
-    });
-    return {
-      getDetail,
-      ...toRefs(props),
-      ...toRefs(state),
-    };
-  },
-});
+	setup(props) {
+		const route = useRoute()
+		const state = reactive<TableDataState>({
+			ids: [],
+			tableData: {
+				data: [],
+				total: 0,
+				loading: false,
+				param: {
+					pageNum: 1,
+					pageSize: 20,
+					deviceName: '',
+					devOtaFirmwareId: 0,
+				},
+			},
+		})
+		const getDetail = () => {
+			state.tableData.loading = true
+			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))
+		}
+		onMounted(() => {
+			getDetail()
+		})
+		return {
+			getDetail,
+			...toRefs(props),
+			...toRefs(state),
+		}
+	},
+})
 
 // const props = defineProps({
 // 	detail: {

+ 172 - 163
src/views/iot/ota-update/update/component/deviceBind.vue

@@ -1,39 +1,47 @@
 <template>
-  <div class="mutiple-bind-dialog-wrap">
-    <el-dialog title="选择设备" v-model="isShowDialog" width="90%">
-      <el-form :model="ruleForm" ref="formRef" :rules="rules" size="small" label-width="110px">
-        <el-form-item label="设备名称" prop="name">
-          <el-input v-model="tableData.param.name" placeholder="请输入设备名称" clearable style="width: 240px" @keyup.enter.native="getDeviceList" />
-          <el-button style="margin-left: 20px;" type="primary" @click="getDeviceList()">查询</el-button>
-
-          <el-button style="margin-left: 20px;" :disabled="!deviceKeyList.length" type="danger" @click="confirmBind()">确定选择</el-button>
-        </el-form-item>
-      </el-form>
-      <el-table ref="multipleTable" :data="tableData.data" style="width: 100%" @selection-change="handleSelectionChange" v-loading="tableData.loading">
-        <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="标识" prop="key" width="130" show-overflow-tooltip v-col="'key'">
-          <template #default="{ row }">
-            <copy :text="row.key"></copy>
-          </template>
-        </el-table-column>
-        <el-table-column label="设备名称" prop="name" show-overflow-tooltip v-col="'name'" />
-        <el-table-column label="产品名称" prop="productName" show-overflow-tooltip v-col="'productName'" />
-
-        <el-table-column prop="status" label="状态" width="100" align="center" v-col="'status'">
-          <template #default="scope">
-            <el-tag type="info" size="small" v-if="scope.row.status == 1">离线</el-tag>
-            <el-tag type="success" size="small" v-if="scope.row.status == 2">在线</el-tag>
-            <el-tag type="info" size="small" v-if="scope.row.status == 0">未启用</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column prop="registryTime" label="激活时间" align="center" width="150" v-col="'registryTime'"></el-table-column>
-        <el-table-column prop="desc" label="说明" v-col="'desc'"></el-table-column>
-
-      </el-table>
-      <pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="getDeviceList" />
-
-    </el-dialog>
-  </div>
+	<div class="mutiple-bind-dialog-wrap">
+		<el-dialog title="选择设备" v-model="isShowDialog" width="1100px">
+			<el-form :model="ruleForm" ref="formRef" :rules="rules" @submit.native.prevent>
+				<el-form-item label="设备名称" prop="name">
+					<el-input v-model="tableData.param.name" placeholder="请输入设备名称" clearable style="width: 240px" @keyup.enter.native="getDeviceList" />
+					<el-button style="margin-left: 20px" type="primary" @click="getDeviceList()">查询</el-button>
+					<el-button style="margin-left: 20px" :disabled="!deviceKeyList.length" type="danger" @click="confirmBind()">确定选择</el-button>
+				</el-form-item>
+			</el-form>
+			<el-table
+				ref="multipleTable"
+				:data="tableData.data"
+				style="width: 100%"
+				@selection-change="handleSelectionChange"
+				v-loading="tableData.loading"
+			>
+				<el-table-column type="selection" width="55" align="center" />
+				<el-table-column label="标识" prop="key" width="130" show-overflow-tooltip>
+					<template #default="{ row }">
+						<copy :text="row.key"></copy>
+					</template>
+				</el-table-column>
+				<el-table-column label="设备名称" prop="name" show-overflow-tooltip />
+				<el-table-column label="产品名称" prop="productName" show-overflow-tooltip />
+				<el-table-column prop="status" label="状态" width="100" align="center">
+					<template #default="scope">
+						<el-tag type="info" size="small" v-if="scope.row.status == 1">离线</el-tag>
+						<el-tag type="success" size="small" v-if="scope.row.status == 2">在线</el-tag>
+						<el-tag type="info" size="small" v-if="scope.row.status == 0">未启用</el-tag>
+					</template>
+				</el-table-column>
+				<el-table-column prop="registryTime" label="激活时间" align="center" width="170"></el-table-column>
+				<el-table-column prop="desc" label="说明" show-overflow-tooltip></el-table-column>
+			</el-table>
+			<pagination
+				v-show="tableData.total > 0"
+				:total="tableData.total"
+				v-model:page="tableData.param.pageNum"
+				v-model:limit="tableData.param.pageSize"
+				@pagination="getDeviceList"
+			/>
+		</el-dialog>
+	</div>
 </template>
 <script lang="ts">
 import { toRefs, reactive, defineComponent, nextTick, getCurrentInstance } from 'vue'
@@ -41,135 +49,136 @@ import { ElMessageBox, ElMessage } from 'element-plus'
 import api from '/@/api/device'
 
 interface TableDataState {
-  isShowDialog: boolean,
-  productData: object[],
-  deviceKeyList: string[];
-  deviceNameList: string[];
-  checkKeyList: string[];
-  tableData: {
-    data: []
-    total: number
-    loading: boolean
-    param: {
-      pageNum: number
-      pageSize: number
-      name: string
-      productKey: string
-    }
-  },
-  ruleForm: {
-    productKey: string
-  },
-  rules: {}
+	isShowDialog: boolean
+	productData: object[]
+	deviceKeyList: string[]
+	deviceNameList: string[]
+	checkKeyList: string[]
+	tableData: {
+		data: []
+		total: number
+		loading: boolean
+		param: {
+			pageNum: number
+			pageSize: number
+			name: string
+			productKey: string
+		}
+	}
+	ruleForm: {
+		productKey: string
+	}
+	rules: {}
 }
 export default defineComponent({
-  name: 'DeviceBindDialog',
-
-  setup(prop, { emit }) {
-    const { proxy } = getCurrentInstance() as any;
-    const state = reactive<TableDataState>({
-      deviceKeyList: [],
-      deviceNameList: [],
-      isShowDialog: false,
-      productData: [],
-      checkKeyList: [],
-      tableData: {
-        data: [],
-        total: 0,
-        loading: false,
-        param: {
-          pageNum: 1,
-          pageSize: 20,
-          name: '',
-          productKey: '',
-        },
-      },
-      ruleForm: {
-        productKey: ''
-      },
-      rules: {
-        productKey: [{ required: true, message: '所属产品不能为空', trigger: 'blur' }],
-      }
-    })
-
-    const getDeviceList = () => {
-      // if (!state.ruleForm.productKey) {
-      //   state.tableData.data = [];
-      //   state.tableData.total = 0;
-      //   return;
-      // }
-      state.isShowDialog = true;
-      state.tableData.loading = true;
-      api.instance.getList(state.tableData.param).then((res: any) => {
-        state.tableData.data = res.device;
-        state.tableData.total = res.total;
-
-        changeSelect();
-      }).finally(() => (state.tableData.loading = false));
-    };
-
-    const getProductList = () => {
-      api.product.getSubList().then((res: any) => {
-        state.productData = res.product;
-        state.ruleForm.productKey = res.product[0].key
-        getDeviceList()
-      });
-    };
-
-    const openDialog = (checkKeyList: string[], productKey: any) => {
-      state.checkKeyList = checkKeyList;
-      state.tableData.param.productKey = productKey;
-      getDeviceList()
-    };
-
-    // 多选框选中数据
-    const handleSelectionChange = (selection: any[]) => {
-      state.deviceKeyList = selection.map((item) => item.key);
-      state.deviceNameList = selection.map((item) => item.name);
-    };
-
-    const confirmBind = () => {
-      let msg = '是否确定选择设备?';
-      if (state.deviceKeyList.length === 0) {
-        ElMessage.error('请选择要确定绑定的数据。');
-        return;
-      }
-      ElMessageBox.confirm(msg, '提示', {
-        confirmButtonText: '确认',
-        cancelButtonText: '取消',
-        type: 'warning',
-      }).then(() => {
-        emit('bindSuccess', state.deviceKeyList, state.deviceNameList)
-        state.isShowDialog = false;
-      })
-    };
-
-    const handleChange = (productKey: string) => {
-      state.ruleForm.productKey = productKey;
-      getDeviceList()
-    }
-
-    const changeSelect = () => {
-      nextTick(() => {
-        state.tableData.data.forEach((item: any) => {
-          if (state.checkKeyList.includes(item.key)) {
-            proxy.$refs.multipleTable.toggleRowSelection(item, true);
-          }
-        })
-      });
-    };
-
-    return {
-      openDialog,
-      getProductList,
-      confirmBind,
-      getDeviceList,
-      handleSelectionChange,
-      handleChange,
-      ...toRefs(state),
-    }
-  },
+	name: 'DeviceBindDialog',
+
+	setup(prop, { emit }) {
+		const { proxy } = getCurrentInstance() as any
+		const state = reactive<TableDataState>({
+			deviceKeyList: [],
+			deviceNameList: [],
+			isShowDialog: false,
+			productData: [],
+			checkKeyList: [],
+			tableData: {
+				data: [],
+				total: 0,
+				loading: false,
+				param: {
+					pageNum: 1,
+					pageSize: 20,
+					name: '',
+					productKey: '',
+				},
+			},
+			ruleForm: {
+				productKey: '',
+			},
+			rules: {
+				productKey: [{ required: true, message: '所属产品不能为空', trigger: 'blur' }],
+			},
+		})
+
+		const getDeviceList = () => {
+			// if (!state.ruleForm.productKey) {
+			//   state.tableData.data = [];
+			//   state.tableData.total = 0;
+			//   return;
+			// }
+			state.isShowDialog = true
+			state.tableData.loading = true
+			api.instance
+				.getList(state.tableData.param)
+				.then((res: any) => {
+					state.tableData.data = res.device
+					state.tableData.total = res.total
+
+					changeSelect()
+				})
+				.finally(() => (state.tableData.loading = false))
+		}
+
+		const getProductList = () => {
+			api.product.getSubList().then((res: any) => {
+				state.productData = res.product
+				state.ruleForm.productKey = res.product[0].key
+				getDeviceList()
+			})
+		}
+
+		const openDialog = (checkKeyList: string[], productKey: any) => {
+			state.checkKeyList = checkKeyList
+			state.tableData.param.productKey = productKey
+			getDeviceList()
+		}
+
+		// 多选框选中数据
+		const handleSelectionChange = (selection: any[]) => {
+			state.deviceKeyList = selection.map((item) => item.key)
+			state.deviceNameList = selection.map((item) => item.name)
+		}
+
+		const confirmBind = () => {
+			let msg = '是否确定选择设备?'
+			if (state.deviceKeyList.length === 0) {
+				ElMessage.error('请选择要确定绑定的数据。')
+				return
+			}
+			ElMessageBox.confirm(msg, '提示', {
+				confirmButtonText: '确认',
+				cancelButtonText: '取消',
+				type: 'warning',
+			}).then(() => {
+				emit('bindSuccess', state.deviceKeyList, state.deviceNameList)
+				state.isShowDialog = false
+			})
+		}
+
+		const handleChange = (productKey: string) => {
+			state.ruleForm.productKey = productKey
+			getDeviceList()
+		}
+
+		const changeSelect = () => {
+			nextTick(() => {
+				state.tableData.data.forEach((item: any) => {
+					if (state.checkKeyList.includes(item.key)) {
+						proxy.$refs.multipleTable.toggleRowSelection(item, true)
+					}
+				})
+			})
+		}
+
+		return {
+			openDialog,
+			getProductList,
+			confirmBind,
+			getDeviceList,
+			handleSelectionChange,
+			handleChange,
+			...toRefs(state),
+		}
+	},
 })
 </script>
-
-

+ 163 - 157
src/views/iot/ota-update/update/component/deviceList.vue

@@ -1,175 +1,181 @@
 <template>
-  <div class="ota-edit-module-container">
-    <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">
-            <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 align="center"></el-table-column>
-        <el-table-column prop="deviceName" label="设备名称" show-overflow-tooltip></el-table-column>
-        <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>
-            <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 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>
-          </template>
-        </el-table-column>
-        <el-table-column prop="fail" label="失败原因" width="100" align="center">
-          <template #default="scope">
-            <el-tag size="small" type="danger" v-if="scope.row.fail == -1">升级失败</el-tag>
-            <el-tag size="small" type="danger" v-if="scope.row.fail == -2">下载失败</el-tag>
-            <el-tag size="small" type="danger" v-if="scope.row.fail == -3">校验失败</el-tag>
-            <el-tag size="small" type="danger" v-if="scope.row.fail == -4">烧写失败</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column prop="desc" label="备注信息" show-overflow-tooltip></el-table-column>
-        <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>
-        </el-table-column>
-      </el-table>
-      <pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="getDetail" />
-    </el-dialog>
-  </div>
+	<div class="ota-edit-module-container">
+		<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">
+						<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 align="center"></el-table-column>
+				<el-table-column prop="deviceName" label="设备名称" show-overflow-tooltip></el-table-column>
+				<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>
+						<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 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>
+					</template>
+				</el-table-column>
+				<el-table-column prop="fail" label="失败原因" width="100" align="center">
+					<template #default="scope">
+						<el-tag size="small" type="danger" v-if="scope.row.fail == -1">升级失败</el-tag>
+						<el-tag size="small" type="danger" v-if="scope.row.fail == -2">下载失败</el-tag>
+						<el-tag size="small" type="danger" v-if="scope.row.fail == -3">校验失败</el-tag>
+						<el-tag size="small" type="danger" v-if="scope.row.fail == -4">烧写失败</el-tag>
+					</template>
+				</el-table-column>
+				<el-table-column prop="desc" label="备注信息" show-overflow-tooltip></el-table-column>
+				<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" v-if="![2, 3].includes(scope.row.status)" @click="distribute(scope.row)">手动下发</el-button>
+					</template>
+				</el-table-column>
+			</el-table>
+			<pagination
+				v-show="tableData.total > 0"
+				:total="tableData.total"
+				v-model:page="tableData.param.pageNum"
+				v-model:limit="tableData.param.pageSize"
+				@pagination="getDetail"
+			/>
+		</el-dialog>
+	</div>
 </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;
-  name: string;
-  types: string;
-  productName: number;
-  moduleName: string;
-  checkres: string;
-  createdAt: string;
+	id: number
+	name: string
+	types: string
+	productName: number
+	moduleName: string
+	checkres: string
+	createdAt: string
 }
 
 interface TableDataState {
-  ids: number[];
-  tableData: {
-    data: Array<TableDataRow>;
-    total: number;
-    loading: boolean;
-    param: {
-      pageNum: number;
-      pageSize: number;
-      deviceName: string;
-      devOtaStrategy: number;
-    };
-  };
-  isShowDialog: boolean;
-  timeoutTimer: any;
+	ids: number[]
+	tableData: {
+		data: Array<TableDataRow>
+		total: number
+		loading: boolean
+		param: {
+			pageNum: number
+			pageSize: number
+			deviceName: string
+			devOtaStrategy: number
+		}
+	}
+	isShowDialog: boolean
+	timeoutTimer: any
 }
 
 export default defineComponent({
-  setup() {
-    const state = reactive<TableDataState>({
-      ids: [],
-      tableData: {
-        data: [],
-        total: 0,
-        loading: false,
-        param: {
-          pageNum: 1,
-          pageSize: 20,
-          deviceName: "",
-          devOtaStrategy: 0,
-        },
-      },
-      isShowDialog: false,
-      timeoutTimer: null,
-    });
-    // 打开弹窗
-    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));
-      state.isShowDialog = true;
-    };
-    // 关闭弹窗
-    const closeDialog = () => {
-      clearTimeout(state.timeoutTimer);
-      state.isShowDialog = false;
-    };
-    // 取消
-    const onCancel = () => {
-      closeDialog();
-    };
-    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));
-    };
-    // 手动下发
-    const distribute = (row: any) => {
-      const deviceKey = row.deviceKey;
-      const strategyId = row.strategyId;
-      api.batch.distribute({ deviceKey: deviceKey, strategyId: strategyId }).then(() => {
-        ElMessage.success("操作成功");
-      });
-      // 定时请求列表数据
-      timer();
-    };
-    // 定时请求列表
-    const timer = () => {
-      // 因列表更新数据不是实时更新,需设置定时后在请求列表
-      state.timeoutTimer = setTimeout(() => {
-        getDetail();
-      }, 3000);
-    };
-    return {
-      getDetail,
-      openDialog,
-      closeDialog,
-      onCancel,
-      distribute,
-      ...toRefs(state),
-    };
-  },
-});
+	setup() {
+		const state = reactive<TableDataState>({
+			ids: [],
+			tableData: {
+				data: [],
+				total: 0,
+				loading: false,
+				param: {
+					pageNum: 1,
+					pageSize: 20,
+					deviceName: '',
+					devOtaStrategy: 0,
+				},
+			},
+			isShowDialog: false,
+			timeoutTimer: null,
+		})
+		// 打开弹窗
+		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))
+			state.isShowDialog = true
+		}
+		// 关闭弹窗
+		const closeDialog = () => {
+			clearTimeout(state.timeoutTimer)
+			state.isShowDialog = false
+		}
+		// 取消
+		const onCancel = () => {
+			closeDialog()
+		}
+		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))
+		}
+		// 手动下发
+		const distribute = (row: any) => {
+			const deviceKey = row.deviceKey
+			const strategyId = row.strategyId
+			api.batch.distribute({ deviceKey: deviceKey, strategyId: strategyId }).then(() => {
+				ElMessage.success('操作成功')
+			})
+			// 定时请求列表数据
+			timer()
+		}
+		// 定时请求列表
+		const timer = () => {
+			// 因列表更新数据不是实时更新,需设置定时后在请求列表
+			state.timeoutTimer = setTimeout(() => {
+				getDetail()
+			}, 3000)
+		}
+		return {
+			getDetail,
+			openDialog,
+			closeDialog,
+			onCancel,
+			distribute,
+			...toRefs(state),
+		}
+	},
+})
 </script>
 
 <style lang="scss" scoped>
 .width100 {
-  width: 100%;
+	width: 100%;
 }
 </style>

+ 163 - 159
src/views/iot/ota-update/update/detail.vue

@@ -1,186 +1,190 @@
 <template>
-  <div class="page page-full padding bg border" style="position: relative">
-    <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>
-      <div class="container mt-2">
-        <div class="item">升级包类型:{{ detail.types == 1 ? "整包" : "差分" }}</div>
-        <div class="item">升级包签名:{{ detail.sign }}</div>
-      </div>
-      <div class="container mb-2">
-        <div class="item">签名算法:{{ detail.are }}</div>
-        <div class="item">模块名称:{{ detail.moduleName }}</div>
-      </div>
-    </div>
-    <el-tabs v-model="activeTab">
-      <el-tab-pane label="批次管理" name="tab1">
-        <BatchList v-if="detail.id" :detail="detail" />
-      </el-tab-pane>
-      <el-tab-pane label="升级包信息" name="tab3">
-        <InfoList v-if="detail.id" :detail="detail" />
-      </el-tab-pane>
-    </el-tabs>
-  </div>
+	<div class="page page-full padding bg border" style="position: relative">
+		<div class="content">
+			<div class="flex cont_box">
+				<div class="font26">升级包名称:{{ detail.name }}</div>
+				<!-- 0未验证,1验证中 2已验证 -->
+				<div class="pro-status">
+					<span :class="detail.checkres ===2 ? 'on' : 'off'"></span
+					>{{ detail.checkres === 1 ? '验证中' : detail.checkres === 2 ? '已验证' : '未验证' }}
+				</div>
+			</div>
+			<div class="container mt-2">
+				<div class="item">升级包类型:{{ detail.types == 1 ? '整包' : '差分' }}</div>
+				<div class="item">升级包签名:{{ detail.sign }}</div>
+			</div>
+			<div class="container mb-2">
+				<div class="item">签名算法:{{ detail.are }}</div>
+				<div class="item">模块名称:{{ detail.moduleName }}</div>
+			</div>
+		</div>
+		<el-tabs v-model="activeTab">
+			<el-tab-pane label="批次管理" name="tab1">
+				<BatchList v-if="detail.id" :detail="detail" />
+			</el-tab-pane>
+			<el-tab-pane label="升级包信息" name="tab3">
+				<InfoList v-if="detail.id" :detail="detail" />
+			</el-tab-pane>
+		</el-tabs>
+	</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 state = reactive({
-      activeTab: "tab1",
-      developer_status: 2,
-      detail: {
-        id: "",
-        name: "",
-        types: 1,
-        are: "",
-        moduleName: "",
-        checkres: 0,
-        sign: "",
-      },
-    });
-    const getDetail = () => {
-      const id = route.params && route.params.id;
-      api.manage.detail(Number(id)).then((res: any) => {
-        state.detail = res;
-      });
-    };
-    const addOrEdit = async (row?: any) => {
-      editFormRef.value.open(row);
-    };
-    onMounted(() => {
-      getDetail();
-    });
-    return {
-      addOrEdit,
-      editFormRef,
-      getDetail,
-      ...toRefs(props),
-      ...toRefs(state),
-    };
-  },
-});
+	components: { EditPen, EditForm, DocumentAdd, InfoList, DeviceList, BatchList },
+	setup(props) {
+		const route = useRoute()
+		const state = reactive({
+			activeTab: 'tab1',
+			developer_status: 2,
+			detail: {
+				id: '',
+				name: '',
+				types: 1,
+				are: '',
+				moduleName: '',
+				checkres: 0,
+				sign: '',
+			},
+		})
+		const getDetail = () => {
+			const id = route.params && route.params.id
+			api.manage.detail(Number(id)).then((res: any) => {
+				state.detail = res
+			})
+		}
+		const addOrEdit = async (row?: any) => {
+			editFormRef.value.open(row)
+		}
+		onMounted(() => {
+			getDetail()
+		})
+		return {
+			addOrEdit,
+			editFormRef,
+			getDetail,
+			...toRefs(props),
+			...toRefs(state),
+		}
+	},
+})
 </script>
 
 <style scoped lang="scss">
 .status_list {
-  width: 100%;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  padding: 10px;
-
-  .otaflex {
-    font-size: 12px;
-    display: flex;
-    align-items: center;
-    margin-left: -6px;
-
-    .otaflex_div1 {
-      padding: 0 24px;
-      min-width: 200px;
-      width: fit-content;
-
-      .otaflex_div2 {
-        align-items: center;
-
-        .title {
-          color: #666;
-          font-size: 14px;
-        }
-
-        span {
-          display: block;
-          border-radius: 50%;
-
-          .on {
-            background: #52c41a;
-          }
-
-          .off {
-            background: #c41a1a;
-          }
-
-          .ofn {
-            background: rgb(255, 138, 0);
-          }
-
-          span {
-            position: relative;
-            top: -1px;
-            display: inline-block;
-            width: 10px;
-            height: 10px;
-            vertical-align: middle;
-            border-radius: 50%;
-            margin-right: 5px;
-          }
-        }
-
-        .otaflex_div3 {
-          font-size: 24px;
-          margin-top: 10px;
-          color: #373d41;
-        }
-      }
-    }
-  }
+	width: 100%;
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	padding: 10px;
+
+	.otaflex {
+		font-size: 12px;
+		display: flex;
+		align-items: center;
+		margin-left: -6px;
+
+		.otaflex_div1 {
+			padding: 0 24px;
+			min-width: 200px;
+			width: fit-content;
+
+			.otaflex_div2 {
+				align-items: center;
+
+				.title {
+					color: #666;
+					font-size: 14px;
+				}
+
+				span {
+					display: block;
+					border-radius: 50%;
+
+					.on {
+						background: #52c41a;
+					}
+
+					.off {
+						background: #c41a1a;
+					}
+
+					.ofn {
+						background: rgb(255, 138, 0);
+					}
+
+					span {
+						position: relative;
+						top: -1px;
+						display: inline-block;
+						width: 10px;
+						height: 10px;
+						vertical-align: middle;
+						border-radius: 50%;
+						margin-right: 5px;
+					}
+				}
+
+				.otaflex_div3 {
+					font-size: 24px;
+					margin-top: 10px;
+					color: #373d41;
+				}
+			}
+		}
+	}
 }
 
 .container {
-  display: flex;
-  padding: 2px 0;
+	display: flex;
+	padding: 2px 0;
 }
 
 .item {
-  flex: 1;
+	flex: 1;
 }
 
 .desc {
-  margin-top: 15px;
+	margin-top: 15px;
 }
 
 .edit {
-  line-height: 40px;
-  margin-top: 15px;
-  margin-left: 30px;
+	line-height: 40px;
+	margin-top: 15px;
+	margin-left: 30px;
 }
 
 .cont_box .pro-status {
-  line-height: 40px;
-  margin-left: 30px;
-
-  .on {
-    background: #52c41a;
-  }
-
-  .off {
-    background: #c41a1a;
-  }
-
-  span {
-    position: relative;
-    top: -1px;
-    display: inline-block;
-    width: 6px;
-    height: 6px;
-    vertical-align: middle;
-    border-radius: 50%;
-    margin-right: 5px;
-  }
+	line-height: 40px;
+	margin-left: 30px;
+
+	.on {
+		background: #52c41a;
+	}
+
+	.off {
+		background: #c41a1a;
+	}
+
+	span {
+		position: relative;
+		top: -1px;
+		display: inline-block;
+		width: 6px;
+		height: 6px;
+		vertical-align: middle;
+		border-radius: 50%;
+		margin-right: 5px;
+	}
 }
 </style>

+ 230 - 215
src/views/iot/ota-update/update/index.vue

@@ -1,229 +1,244 @@
 <template>
-  <div class="page">
-    <el-card shadow="nover">
-      <el-form :model="tableData.param" ref="queryRef" inline>
-        <el-form-item label="升级包名称" prop="keyWord">
-          <el-input v-model="tableData.param.keyWord" placeholder="请输入升级包名称" clearable style="width: 240px;" @keyup.enter.native="getList(1)" />
-        </el-form-item>
-        <el-form-item>
-          <el-button type="primary" class="ml10" @click="getList(1)">
-            <el-icon>
-              <ele-Search />
-            </el-icon>
-            查询
-          </el-button>
-          <el-button @click="resetQuery">
-            <el-icon>
-              <ele-Refresh />
-            </el-icon>
-            重置
-          </el-button>
-          <el-button type="primary" v-auth="'add'" @click="onOpenAdd()">
-            <el-icon>
-              <ele-FolderAdd />
-            </el-icon>
-            添加升级包
-          </el-button>
-        </el-form-item>
-      </el-form>
-      <el-table :data="tableData.data" style="width: 100%" v-loading="tableData.loading">
-        <el-table-column label="ID" v-col="'id'" align="center" prop="id" width="100" />
-        <el-table-column label="升级包名称" v-col="'name'" prop="name" show-overflow-tooltip />
-        <el-table-column prop="types" label="类型" show-overflow-tooltip v-col="'types'">
-          <template #default="scope">
-            <el-tag size="small" v-if="scope.row.types == 1">整包</el-tag>
-            <el-tag type="info" size="small" v-if="scope.row.types == 2">差分</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="所属产品" v-col="'productName'" align="center" show-overflow-tooltip>
-          <template #default="scope">
-            <router-link :to="'/iotmanager/device/product/detail/' + scope.row.productKey" class="link-type">
-              <span>{{ scope.row.productName }}</span>
-            </router-link>
-          </template>
-        </el-table-column>
-        <el-table-column label="模块名称" v-col="'moduleName'" align="center" show-overflow-tooltip>
-          <template #default="scope">
-            <router-link :to="'/iotmanager/operation/ota/module'" class="link-type">
-              <span>{{ scope.row.moduleName }}</span>
-            </router-link>
-          </template>
-        </el-table-column>
-        <el-table-column label="状态" prop="checkres" v-col="'checkres'" width="120" align="center">
-          <template #default="scope">
-            <el-tag type="success" size="small" v-if="scope.row.checkres == 1">验证</el-tag>
-            <el-tag type="info" size="small" v-else>未验证</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="创建时间" prop="createdAt" align="center" width="160" />
-        <el-table-column label="操作" width="200" v-col="'handle'" align="center" fixed="right">
-          <template #default="scope">
-            <el-button size="small" text type="primary" v-if="!scope.row.folderName" @click="toDetail(scope.row.id)">查看</el-button>
-            <el-button size="small" text type="warning" v-auth="'edit'" @click="onOpenEdit(scope.row)">编辑</el-button>
-            <el-button size="small" text type="success" v-auth="'handle'" @click="onOpenCheck(scope.row)">操作</el-button>
+	<div class="page">
+		<el-card shadow="nover">
+			<el-form :model="tableData.param" ref="queryRef" inline>
+				<el-form-item label="升级包名称" prop="keyWord">
+					<el-input
+						v-model="tableData.param.keyWord"
+						placeholder="请输入升级包名称"
+						clearable
+						style="width: 240px"
+						@keyup.enter.native="getList(1)"
+					/>
+				</el-form-item>
+				<el-form-item>
+					<el-button type="primary" class="ml10" @click="getList(1)">
+						<el-icon>
+							<ele-Search />
+						</el-icon>
+						查询
+					</el-button>
+					<el-button @click="resetQuery">
+						<el-icon>
+							<ele-Refresh />
+						</el-icon>
+						重置
+					</el-button>
+					<el-button type="primary" v-auth="'add'" @click="onOpenAdd()">
+						<el-icon>
+							<ele-FolderAdd />
+						</el-icon>
+						添加升级包
+					</el-button>
+				</el-form-item>
+			</el-form>
+			<el-table :data="tableData.data" style="width: 100%" v-loading="tableData.loading">
+				<el-table-column label="ID" v-col="'id'" align="center" prop="id" width="100" />
+				<el-table-column label="升级包名称" v-col="'name'" prop="name" min-width="120" show-overflow-tooltip />
+				<el-table-column prop="types" label="类型" show-overflow-tooltip v-col="'types'">
+					<template #default="scope">
+						<el-tag size="small" v-if="scope.row.types == 1">整包</el-tag>
+						<el-tag type="info" size="small" v-if="scope.row.types == 2">差分</el-tag>
+					</template>
+				</el-table-column>
+				<el-table-column label="所属产品" v-col="'productName'" min-width="120" align="center" show-overflow-tooltip>
+					<template #default="scope">
+						<router-link :to="'/iotmanager/device/product/detail/' + scope.row.productKey" class="link-type">
+							<span>{{ scope.row.productName }}</span>
+						</router-link>
+					</template>
+				</el-table-column>
+				<el-table-column label="模块名称" v-col="'moduleName'" align="center" show-overflow-tooltip>
+					<template #default="scope">
+						<router-link :to="'/iotmanager/operation/ota/module'" class="link-type">
+							<span>{{ scope.row.moduleName }}</span>
+						</router-link>
+					</template>
+				</el-table-column>
+				<el-table-column label="需要验证" prop="check" v-col="'check'" width="120" align="center">
+					<template #default="scope">
+						<!-- 1需要,2不需要  -->
+						<el-tag type="primary" size="small" v-if="scope.row.check === 1">需要</el-tag>
+						<el-tag type="danger" size="small" v-if="scope.row.check === 2">不需要</el-tag>
+					</template>
+				</el-table-column>
+				<el-table-column label="状态" prop="checkres" v-col="'checkres'" width="120" align="center">
+					<template #default="scope">
+						<!-- 升级包验证 0未验证,1验证中 2已验证 -->
+						<el-tag type="primary" size="small" v-if="scope.row.checkres === 1">验证中</el-tag>
+						<el-tag type="success" size="small" v-if="scope.row.checkres === 2">已验证</el-tag>
+						<el-tag type="danger" size="small" v-if="scope.row.checkres === 0">未验证</el-tag>
+					</template>
+				</el-table-column>
+				<el-table-column label="版本号" prop="version" align="center" width="160" />
+				<el-table-column label="创建时间" prop="createdAt" align="center" width="160" />
+				<el-table-column label="操作" width="150" v-col="'handle'" align="center" fixed="right">
+					<template #default="scope">
+						<el-button size="small" text type="primary" v-if="!scope.row.folderName" @click="toDetail(scope.row.id)">查看</el-button>
+						<el-button size="small" text type="warning" v-auth="'edit'" @click="onOpenEdit(scope.row)">编辑</el-button>
+						<el-button size="small" text type="info" v-auth="'del'" @click="onRowDel(scope.row)">删除</el-button>
+					</template>
+				</el-table-column>
+			</el-table>
+			<pagination
+				v-show="tableData.total > 0"
+				:total="tableData.total"
+				v-model:page="tableData.param.pageNum"
+				v-model:limit="tableData.param.pageSize"
+				@pagination="getList"
+			/>
+			<EditConfig ref="editRef" @getList="getList(1)" />
 
-            <el-button size="small" text type="info" v-auth="'del'" @click="onRowDel(scope.row)">删除</el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-      <pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="getList" />
-      <EditConfig ref="editRef" @getList="getList(1)" />
-
-      <CheckConfig ref="checkRef" @getList="getList(1)" />
-    </el-card>
-  </div>
+			<CheckConfig ref="checkRef" @getList="getList(1)" />
+		</el-card>
+	</div>
 </template>
 
 <script lang="ts">
-import api from '/@/api/ota';
-import { toRefs, reactive, onMounted, ref, defineComponent, getCurrentInstance } from 'vue';
+import api from '/@/api/ota'
+import { toRefs, reactive, onMounted, ref, defineComponent, getCurrentInstance } from 'vue'
 import { ElMessageBox, ElMessage, FormInstance } from 'element-plus'
-import EditConfig from '/@/views/iot/ota-update/update/component/edit.vue';
-import CheckConfig from '/@/views/iot/ota-update/update/component/check.vue';
-import { useRouter } from 'vue-router';
+import EditConfig from '/@/views/iot/ota-update/update/component/edit.vue'
+import CheckConfig from '/@/views/iot/ota-update/update/component/check.vue'
+import { useRouter } from 'vue-router'
 
 // 定义接口来定义对象的类型
 interface TableDataRow {
-  id: number;
-  name: string;
-  types: string;
-  productName: number;
-  moduleName: string;
-  checkres: string;
-  createdAt: string;
+	id: number
+	name: string
+	types: string
+	productName: number
+	moduleName: string
+	checkres: string
+	createdAt: string
 }
 interface TableDataState {
-  ids: number[];
-  tableData: {
-    data: Array<TableDataRow>;
-    total: number;
-    loading: boolean;
-    param: {
-      pageNum: number;
-      pageSize: number;
-      keyWord: string;
-      dateRange: string[];
-    };
-  };
+	ids: number[]
+	tableData: {
+		data: Array<TableDataRow>
+		total: number
+		loading: boolean
+		param: {
+			pageNum: number
+			pageSize: number
+			keyWord: string
+			dateRange: string[]
+		}
+	}
 }
 
 export default defineComponent({
-  name: 'apiV1OtaUpdateDataList',
-  components: { EditConfig, CheckConfig },
-  setup() {
-    const router = useRouter();
-    const editRef = ref();
-    const checkRef = ref();
-    const detailRef = ref();
-    const queryRef = ref();
-    const tabDataList = ref([{ dictLabel: '全部', dictValue: '' }]);
-    const state = reactive<TableDataState>({
-      ids: [],
-      tableData: {
-        data: [],
-        total: 0,
-        loading: false,
-        param: {
-          dateRange: [],
-          pageNum: 1,
-          pageSize: 20,
-          keyWord: '',
-        },
-      },
-    });
-    // 页面加载时
-    onMounted(() => {
-      initTableData();
-    });
-    // 初始化表格数据
-    const initTableData = () => {
-      manageList();
-    };
-    const getList = (pageNum?: number) => {
-      typeof pageNum === 'number' && (state.tableData.param.pageNum = pageNum)
-      state.tableData.loading = true;
-      api.manage
-        .getList(state.tableData.param)
-        .then((res: any) => {
-          state.tableData.data = res.firmware;
-          state.tableData.total = res.Total;
-        })
-        .finally(() => (state.tableData.loading = false));
-    };
-    // 打开新增弹窗
-    const onOpenAdd = () => {
-      editRef.value.openDialog();
-    };
-    // 打开修改弹窗
-    const onOpenEdit = (row: TableDataRow) => {
-      editRef.value.openDialog(row);
-    };
-    // 打开验证弹窗
-    const onOpenCheck = (row: TableDataRow) => {
-      checkRef.value.openDialog(row);
-    };
-    // 打开详情弹窗
-    // const opOpenDetail = (row: TableDataRow) => {
-
-    // };
-    const toDetail = (id: number) => {
-      router.push(`/iotmanager/operation/ota/update/detail/${id}`)
-    };
-    // 删除模块
-    const onRowDel = (row?: TableDataRow) => {
-      let msg = '你确定要删除所选数据?';
-      let ids: number[] = [];
-      if (row) {
-        msg = `此操作将永久删除:“${row.name}”,是否继续?`;
-        ids = [row.id];
-      } else {
-        ids = state.ids;
-      }
-      if (ids.length === 0) {
-        ElMessage.error('请选择要删除的数据。');
-        return;
-      }
-      ElMessageBox.confirm(msg, '提示', {
-        confirmButtonText: '确认',
-        cancelButtonText: '取消',
-        type: 'warning',
-      }).then(() => {
-        api.manage.del(ids).then(() => {
-          ElMessage.success('删除成功');
-          getList();
-        });
-      })
-        .catch(() => { });
-    };
-    /** 重置按钮操作 */
-    const resetQuery = () => {
-      if (!queryRef.value) return;
-      queryRef.value.resetFields();
-      getList(1);
-    };
-    // 多选框选中数据
-    const handleSelectionChange = (selection: TableDataRow[]) => {
-      state.ids = selection.map((item) => item.id);
-    };
-    // 获取列表
-    const manageList = () => {
-      getList();
-    };
-    return {
-      editRef,
-      checkRef,
-      queryRef,
-      tabDataList,
-      toDetail,
-      onOpenAdd,
-      onOpenEdit,
-      onOpenCheck,
-      onRowDel,
-      getList,
-      resetQuery,
-      handleSelectionChange,
-      ...toRefs(state),
-    };
-  },
-});
-</script>
+	name: 'apiV1OtaUpdateDataList',
+	components: { EditConfig, CheckConfig },
+	setup() {
+		const router = useRouter()
+		const editRef = ref()
+		const checkRef = ref()
+		const detailRef = ref()
+		const queryRef = ref()
+		const tabDataList = ref([{ dictLabel: '全部', dictValue: '' }])
+		const state = reactive<TableDataState>({
+			ids: [],
+			tableData: {
+				data: [],
+				total: 0,
+				loading: false,
+				param: {
+					dateRange: [],
+					pageNum: 1,
+					pageSize: 20,
+					keyWord: '',
+				},
+			},
+		})
+		// 页面加载时
+		onMounted(() => {
+			initTableData()
+		})
+		// 初始化表格数据
+		const initTableData = () => {
+			manageList()
+		}
+		const getList = (pageNum?: number) => {
+			typeof pageNum === 'number' && (state.tableData.param.pageNum = pageNum)
+			state.tableData.loading = true
+			api.manage
+				.getList(state.tableData.param)
+				.then((res: any) => {
+					state.tableData.data = res.firmware
+					state.tableData.total = res.Total
+				})
+				.finally(() => (state.tableData.loading = false))
+		}
+		// 打开新增弹窗
+		const onOpenAdd = () => {
+			editRef.value.openDialog()
+		}
+		// 打开修改弹窗
+		const onOpenEdit = (row: TableDataRow) => {
+			editRef.value.openDialog(row)
+		}
+		// 打开详情弹窗
+		// const opOpenDetail = (row: TableDataRow) => {
+		// };
+		const toDetail = (id: number) => {
+			router.push(`/iotmanager/operation/ota/update/detail/${id}`)
+		}
+		// 删除模块
+		const onRowDel = (row?: TableDataRow) => {
+			let msg = '你确定要删除所选数据?'
+			let ids: number[] = []
+			if (row) {
+				msg = `此操作将永久删除:“${row.name}”,是否继续?`
+				ids = [row.id]
+			} else {
+				ids = state.ids
+			}
+			if (ids.length === 0) {
+				ElMessage.error('请选择要删除的数据。')
+				return
+			}
+			ElMessageBox.confirm(msg, '提示', {
+				confirmButtonText: '确认',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(() => {
+					api.manage.del(ids).then(() => {
+						ElMessage.success('删除成功')
+						getList()
+					})
+				})
+				.catch(() => {})
+		}
+		/** 重置按钮操作 */
+		const resetQuery = () => {
+			if (!queryRef.value) return
+			queryRef.value.resetFields()
+			getList(1)
+		}
+		// 多选框选中数据
+		const handleSelectionChange = (selection: TableDataRow[]) => {
+			state.ids = selection.map((item) => item.id)
+		}
+		// 获取列表
+		const manageList = () => {
+			getList()
+		}
+		return {
+			editRef,
+			checkRef,
+			queryRef,
+			tabDataList,
+			toDetail,
+			onOpenAdd,
+			onOpenEdit,
+			onRowDel,
+			getList,
+			resetQuery,
+			handleSelectionChange,
+			...toRefs(state),
+		}
+	},
+})
+</script>

+ 38 - 4
yarn.lock

@@ -1094,6 +1094,11 @@ balanced-match@^1.0.0:
   resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz"
   integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
 
+base64-arraybuffer@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc"
+  integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==
+
 batch-processor@1.0.0:
   version "1.0.0"
   resolved "https://registry.npmmirror.com/batch-processor/-/batch-processor-1.0.0.tgz"
@@ -1340,6 +1345,13 @@ cross-spawn@^7.0.2:
     shebang-command "^2.0.0"
     which "^2.0.1"
 
+css-line-break@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.npmmirror.com/css-line-break/-/css-line-break-2.1.0.tgz#bfef660dfa6f5397ea54116bb3cb4873edbc4fa0"
+  integrity sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==
+  dependencies:
+    utrie "^1.0.2"
+
 css-tree@^2.3.1:
   version "2.3.1"
   resolved "https://registry.npmmirror.com/css-tree/-/css-tree-2.3.1.tgz"
@@ -2260,6 +2272,14 @@ highlight.js@^11.8.0:
   resolved "https://registry.npmmirror.com/highlight.js/-/highlight.js-11.10.0.tgz"
   integrity sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==
 
+html2canvas@^1.4.1:
+  version "1.4.1"
+  resolved "https://registry.npmmirror.com/html2canvas/-/html2canvas-1.4.1.tgz#7cef1888311b5011d507794a066041b14669a543"
+  integrity sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==
+  dependencies:
+    css-line-break "^2.1.0"
+    text-segmentation "^1.0.3"
+
 ignore@^5.1.8, ignore@^5.2.0:
   version "5.3.2"
   resolved "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz"
@@ -3192,6 +3212,13 @@ tape@^4.5.1:
     resolve "~1.22.6"
     string.prototype.trim "~1.2.8"
 
+text-segmentation@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.npmmirror.com/text-segmentation/-/text-segmentation-1.0.3.tgz#52a388159efffe746b24a63ba311b6ac9f2d7943"
+  integrity sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==
+  dependencies:
+    utrie "^1.0.2"
+
 text-table@^0.2.0:
   version "0.2.0"
   resolved "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz"
@@ -3344,6 +3371,13 @@ uri-js@^4.2.2:
   dependencies:
     punycode "^2.1.0"
 
+utrie@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.npmmirror.com/utrie/-/utrie-1.0.2.tgz#d42fe44de9bc0119c25de7f564a6ed1b2c87a645"
+  integrity sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==
+  dependencies:
+    base64-arraybuffer "^1.0.2"
+
 uuid@9.0.0:
   version "9.0.0"
   resolved "https://registry.npmmirror.com/uuid/-/uuid-9.0.0.tgz"
@@ -3387,10 +3421,10 @@ vue-clipboard3@1.0.1:
   dependencies:
     clipboard "^2.0.6"
 
-vue-data-ui@^2.3.98:
-  version "2.3.98"
-  resolved "https://registry.npmmirror.com/vue-data-ui/-/vue-data-ui-2.3.98.tgz#80d99bbfaecdaa33b51bd4060f4a3e6d07f636f0"
-  integrity sha512-NvUM1GuAZKb3qNy0kHqsuWOJOG2AhXQGNTLV+OohqJcV8ISLT/vTzMkNq8axuP1QI9yruc1B8ZEwNDdwHr1+MA==
+vue-data-ui@^2.4.17:
+  version "2.6.9"
+  resolved "https://registry.npmmirror.com/vue-data-ui/-/vue-data-ui-2.6.9.tgz#08c90093f98beb4a1f57a8336068f3d9a95e0cb5"
+  integrity sha512-q3lci39zyfKwpfK6ObnsZwTL0fu0hA0DrTVHZXhmwhS4b7K+cLYxIZuNyAp35o2zeVKhZ7hbW9g9P9jrSIqeZg==
 
 vue-demi@*:
   version "0.14.10"