lvkun996 2 năm trước cách đây
mục cha
commit
34b471616d

+ 0 - 8
src/api/iot/ota.ts

@@ -24,14 +24,6 @@ export const addOtaPkg = (params: IOT.API.OTA.BodyParams) => {
   })
 }
 
-export const updateOtaPkg = (params: IOT.API.OTA.BodyParams) => {
-  return request<string>({
-    url: '/otaPkg/page',
-    method: 'GET',
-    params
-  })
-}
-
 export const delOtaPkg = (id: string) => {
   return request<string>({
     url: `/otaPkg/${id}`,

+ 10 - 5
src/components/UploadPro/index.tsx

@@ -3,23 +3,27 @@ import { InboxOutlined } from '@ant-design/icons-vue'
 import { UploadChangeParam, message } from 'ant-design-vue'
 import { instance } from '@/service/request'
 
+console.log('instance.defaults.proxy:', instance.defaults)
+
+console.log('instance.defaults.baseURL:')
+
 /**
  * @description 通用文件上传组件
  */
 
-export const UploadPro = defineComponent({
+export default defineComponent({
   name: 'upload-pro',
   props: {
     action: {
       type: String,
-      default: instance.defaults.baseURL + '/file'
+      default: ' '
     },
     accept: {
       type: String,
-      default: '.zip'
+      default: '.zip,.tar,.gz,.tgz'
     }
   },
-  emits: ['update:value'],
+  emits: ['done'],
   setup (props, ctx) {
     const handleChange = (info: UploadChangeParam) => {
       const status = info.file.status
@@ -27,7 +31,7 @@ export const UploadPro = defineComponent({
         console.log(info.file, info.fileList)
       }
       if (status === 'done') {
-        ctx.emit('update:value', info)
+        ctx.emit('done', info)
         message.success(`${info.file.name} 文件上传成功`)
       } else if (status === 'error') {
         message.error(`${info.file.name} 文件上传失败`)
@@ -41,6 +45,7 @@ export const UploadPro = defineComponent({
               name="file"
               action={props.action}
               onChange={handleChange}
+              maxCount={1}
             >
               <p class="ant-upload-drag-icon">
                 <InboxOutlined />

+ 18 - 7
src/controller/iot/device.ts

@@ -46,12 +46,12 @@ export class DeviceContriller {
   ]
 
   static otaStatusMap = new Map([
-    [OtaStatusEnum.QUEUED, { key: OtaStatusEnum.QUEUED, label: '在消息队列中' }],
-    [OtaStatusEnum.SENT, { key: OtaStatusEnum.SENT, label: '已经发送' }],
-    [OtaStatusEnum.DELIVERED, { key: OtaStatusEnum.DELIVERED, label: '设备已收到' }],
-    [OtaStatusEnum.SUCCESSFUL, { key: OtaStatusEnum.SUCCESSFUL, label: '成功' }],
-    [OtaStatusEnum.TIMEOUT, { key: OtaStatusEnum.TIMEOUT, label: '超时' }],
-    [OtaStatusEnum.FAILED, { key: OtaStatusEnum.FAILED, label: '失败' }]
+    [OtaStatusEnum.QUEUED, { key: OtaStatusEnum.QUEUED, label: '在消息队列中', color: 'orange' }],
+    [OtaStatusEnum.SENT, { key: OtaStatusEnum.SENT, label: '已经发送', color: 'blue' }],
+    [OtaStatusEnum.DELIVERED, { key: OtaStatusEnum.DELIVERED, label: '设备已收到', color: 'pink' }],
+    [OtaStatusEnum.SUCCESSFUL, { key: OtaStatusEnum.SUCCESSFUL, label: '成功', color: 'green' }],
+    [OtaStatusEnum.TIMEOUT, { key: OtaStatusEnum.TIMEOUT, label: '超时', color: 'red' }],
+    [OtaStatusEnum.FAILED, { key: OtaStatusEnum.FAILED, label: '失败', color: 'grey' }]
   ])
 
   static otaStatusList = [
@@ -255,7 +255,18 @@ export class DeviceContriller {
   }
 
   static async OtaByDeviceId (deviceId: string) {
-    return await getOtaByDeviceId(deviceId)
+    const data = await getOtaByDeviceId(deviceId)
+    console.log('data.data.otaPkgLabel:', data.data.otaPkgLabel === '--')
+
+    return {
+      ...data,
+      data: {
+        ...data,
+        otaTime: data.data.otaTime === 0 ? '尚未升级' : data.data.otaTime,
+        otaPkgLabel: data.data.otaPkgLabel === '--' ? '尚未升级' : data.data.otaPkgLabel,
+        otaPkgVersion: data.data.otaPkgVersion === '--' ? '尚未升级' : data.data.otaPkgVersion
+      }
+    }
   }
 
   static async OtaPageByDeviceId (params: IOT.API.DEVICE.OtaQueryParams) {

+ 2 - 2
src/controller/iot/ota.ts

@@ -1,4 +1,4 @@
-import { addOtaPkg, delOtaPkg, getOtaPkgById, getOtaPkgPage, updateOtaPkg } from '@/api/iot/ota'
+import { addOtaPkg, delOtaPkg, getOtaPkgById, getOtaPkgPage } from '@/api/iot/ota'
 import { PkgTypeEnum } from '@/enum/common'
 import { message } from 'ant-design-vue'
 
@@ -29,7 +29,7 @@ export class OtaController {
   }
 
   static async update (data: IOT.API.OTA.BodyParams) {
-    await updateOtaPkg(data)
+    // await updateOtaPkg(data)
     message.success('修改成功')
   }
 

+ 1 - 0
src/hooks/effect.ts

@@ -63,6 +63,7 @@ export const usePort = (title: string) => {
     setBaseUrl('/user')
   }
 }
+
 /**
  * `useDeviceResolution` 函数是一个 TypeScript 函数,允许您跟踪设备的屏幕宽度和高度,并在屏幕大小调整时执行回调函数。
  * @param {Function} cb - 参数“cb”是一个回调函数,每当设备分辨率发生变化时就会调用该函数。

+ 58 - 1
src/pages/Iot/device/components/ota.vue

@@ -1,6 +1,32 @@
 <template>
   <a-card>
-
+    <a-row  align="middle" style="width: 100%;height: 68px" class="title">
+      <a-col>
+        <a-space>
+          <span>设备名称:{{state.otaDetail.otaPkgLabel}}</span>
+          <span>设备版本:{{state.otaDetail.otaPkgVersion}}</span>
+        </a-space>
+      </a-col>
+      <a-col>
+        <a-button type="primary" >下发OTA程序包</a-button>
+      </a-col>
+    </a-row>
+    <a-table
+      style="margin-top: 20px;"
+      :columns="columns"
+      :data-source="state.dataSource"
+      :loading="state.loading"
+      :pagination="queryState"
+      @change="changePage"
+    >
+      <template #bodyCell="{column, record}">
+        <template v-if="column.key === 'status'" >
+          <a-tag :colo="DeviceContriller.otaStatusMap.get(record.status)?.color">
+            {{DeviceContriller.otaStatusMap.get(record.status)?.label}}
+          </a-tag>
+        </template>
+      </template>
+    </a-table>
   </a-card>
 </template>
 
@@ -13,6 +39,26 @@ const route = useRoute()
 
 const deviceId = route.query.id as string
 
+const columns = [
+  {
+    title: 'OTA名称',
+    dataIndex: 'otaPkgLabel'
+  },
+  {
+    title: 'OTA版本',
+    dataIndex: 'otaPkgVersion'
+  },
+  {
+    title: 'OTA升级名称',
+    dataIndex: 'otaTime'
+  },
+  {
+    title: '升级状态',
+    dataIndex: 'status',
+    key: 'status'
+  }
+]
+
 const queryState = reactive<IOT.API.DEVICE.OtaQueryParams & {total: number}>({
   page: 1,
   pageSize: 10,
@@ -33,6 +79,11 @@ const state = reactive<{
   otaDetail: {}
 })
 
+const changePage = ({ current }) => {
+  queryState.page = current
+  getOtaPkgPageByDeviceId()
+}
+
 const getOtaPkgPageByDeviceId = async () => {
   state.loading = true
   const { data, sum } = await DeviceContriller.OtaPageByDeviceId(queryState)
@@ -53,4 +104,10 @@ onMounted(() => {
 </script>
 
 <style lang="less" >
+@import '~@/styles/theme.less';
+
+.title {
+  background-color: @bg-color-1;
+  padding-left: 40px;
+}
 </style>

+ 21 - 6
src/pages/Iot/ota/index.vue

@@ -58,9 +58,14 @@
             </a-select-option>
         </a-select>
       </a-form-item>
-      <a-form-item label="类型" v-bind="validateInfos.pkgUrl"  >
+      <a-form-item v-if="otaPkgState.pkgType" label="包地址" v-bind="validateInfos.pkgUrl"  >
         <a-input v-if="otaPkgState.pkgType === PkgTypeEnum.FILE_URL" allowClear v-model:value="otaPkgState.pkgUrl" />
-        <upload-pro v-else></upload-pro>
+        <upload-pro
+          :action="instance.defaults.baseURL + '/file'"
+          @done="uploadDone"
+          v-else-if="otaPkgState.pkgType === PkgTypeEnum.FILE_ZIP"
+        >
+        </upload-pro>
       </a-form-item>
 </a-form>
 </modal-pro>
@@ -68,9 +73,10 @@
 <script lang='ts' setup >
 import { OtaController } from '@/controller/iot'
 import { reactive, onMounted, computed } from 'vue'
-import { Form, message } from 'ant-design-vue'
+import { Form, UploadChangeParam, message } from 'ant-design-vue'
 import { PkgTypeEnum } from '@/enum/common'
 import { CommonController } from '@/controller'
+import { instance } from '@/service/request'
 
 const columns = [
   {
@@ -126,7 +132,7 @@ const otaPkgState = reactive({
   label: ''
 })
 
-const fileState = reactive({
+let fileState = reactive({
   filePath: '', // 文件地址
   filename: '',
   fileUrl: ''
@@ -141,6 +147,14 @@ const { resetFields, validate, validateInfos } = useForm(otaPkgState, reactive({
   label: [{ required: true, message: '请填写包名' }]
 }))
 
+const uploadDone = async (info: UploadChangeParam) => {
+  if (fileState.filePath) {
+    await CommonController.delOtaPkg(fileState.filePath, fileState.filename)
+  }
+  fileState = reactive(info.file.response.data)
+  otaPkgState.pkgUrl = fileState.fileUrl
+}
+
 const changePage = ({ current }) => {
   queryState.page = current
   getOtaPkgPage()
@@ -153,8 +167,9 @@ const closeModal = async () => {
 }
 
 const ok = () => {
-  validate().then(() => {
-
+  validate().then(async () => {
+    await OtaController.add(otaPkgState)
+    state.visible = false
   })
 }
 

+ 4 - 4
src/type/iot.d.ts

@@ -249,10 +249,10 @@ declare namespace IOT {
 
       interface Ota {
         'deviceId': string,
-        'otaTime': 0, // 设备当前ota 升级名称,如果是0 说明从未升级过,有值的情况是 毫秒数字
-        'msgId': null,
-        'status': null, // QUEUED,SENT,DELIVERED,SUCCESSFUL,TIMEOUT,FAILED
-        'otaPkgId': null, // ota包id
+        'otaTime': number, // 设备当前ota 升级名称,如果是0 说明从未升级过,有值的情况是 毫秒数字
+        'msgId': any,
+        'status': any, // QUEUED,SENT,DELIVERED,SUCCESSFUL,TIMEOUT,FAILED
+        'otaPkgId': string, // ota包id
         'otaPkgLabel': string, // 设备当前ota 名称,如果是-- 说明从未升级过
         'otaPkgVersion': string // 设备当前ota 版本,如果是-- 说明从未升级过
       }

+ 2 - 0
src/utils/UsePro.ts

@@ -4,6 +4,7 @@ import TablePro from '@/components/TablePro/index.vue'
 import FormPro from '@/components/FormPro/index.vue'
 import RowPro from '@/components/RowPro/index.vue'
 import ColPro from '@/components/ColPro/index.vue'
+import UploadPro from '@/components/UploadPro/index'
 import { App } from 'vue'
 
 export default function (app: App) {
@@ -13,4 +14,5 @@ export default function (app: App) {
   app.component('form-pro', FormPro) // 别问问什么是oo, 问就是这样比较帅
   app.component('l-row', RowPro)
   app.component('l-col', ColPro)
+  app.component('upload-pro', UploadPro)
 }