diff --git a/src/api/things/otaPackage.ts b/src/api/things/otaPackage.ts new file mode 100644 index 0000000000000000000000000000000000000000..8e4fe6f42b1455f464160dc0c3c6b171dd729f07 --- /dev/null +++ b/src/api/things/otaPackage.ts @@ -0,0 +1,89 @@ +import { BasicModel, BasicQuery, Page } from "../model/baseModel"; +import { EntityId } from "/#/store"; +import { EntityType } from "/@/enums/entityTypeEnum"; +import { ContentTypeEnum } from "/@/enums/httpEnum"; +import { defHttp } from "/@/utils/http/axios"; +import { AxiosProgressEvent } from 'axios'; + +export interface OtaPackageInfo extends BasicModel { + tenantId: EntityId; + deviceProfileId: EntityId; + title?: string; + type?: 'FIRMWARE' | 'SOFTWARE'; + version?: string; + tag?: string; + url?: string; + hasData?: boolean; + fileName?: string; + contentType?: string; + checksum?: string; + dataSize?: number; + checksumAlgorithm?: 'MD5' | 'SHA256' | 'SHA384' | 'SHA512' | 'CRC32' | 'MURMUR3_32' | 'MURMUR3_128'; +} + +export interface otaPackage extends OtaPackageInfo { + data?: Recordable; +} + +export interface OtaPackageUploadParam { + otaPackageId: string, + file: File | Blob, + checksumAlgorithm?: string, + checksum?: string, +} + +export function downloadOtaPackage(otaPackageId: string) { + return defHttp.get( + { url: `/api/otaPackage/${otaPackageId}/download`, responseType: 'blob' }, + { isReturnNativeResponse: true, joinPrefix: false } + ); +} + +export function getOtaPackageInfoById(otaPackageId: string) { + return defHttp.get({ + url: `/api/otaPackage/info/${otaPackageId}`, + }) +} + +export function getOtaPackageById(otaPackageId: string) { + return defHttp.get({ + url: `/api/otaPackage/${otaPackageId}`, + }) +} + +export function saveOtaPackageInfo(data: { otaPackageInfo: OtaPackageInfo, usesUrl: boolean } | any) { + return defHttp.postJson({ + url: '/api/otaPackage', + data + }) +} + +export function saveOtaPackageData(params: OtaPackageUploadParam, onUploadProgress?: (progressEvent: AxiosProgressEvent) => void) { + return defHttp.post({ + url: `/api/otaPackage/${params.otaPackageId}`, + params: { checksum: params.checksum, checksumAlgorithm: params.checksumAlgorithm }, + data: { file: params.file }, + headers: { 'Content-type': ContentTypeEnum.FORM_DATA, }, + onUploadProgress + }) +} + +export function getOtaPackageList(params: BasicQuery) { + return defHttp.get>({ + url: '/api/otaPackages', + params, + }); +} + +export function getOtaPackageListByDeviceProfile(deviceProfileId: string, type: string, params: BasicQuery) { + return defHttp.get>({ + url: `/api/otaPackages/${deviceProfileId}/${type}`, + params, + }); +} + +export function deleteOtaPackage(otaPackageId: string) { + return defHttp.delete({ + url: `/api/otaPackage/${otaPackageId}`, + }); +} \ No newline at end of file diff --git a/src/enums/otaPackageEnum.ts b/src/enums/otaPackageEnum.ts new file mode 100644 index 0000000000000000000000000000000000000000..4b39b0927927d8487f651c3bb103509730cae5cf --- /dev/null +++ b/src/enums/otaPackageEnum.ts @@ -0,0 +1,19 @@ +export enum CHECK_SUM_ALGORITHM { + MD5 = 'MD5', + SHA256 = 'SHA256', + SHA384 = 'SHA384', + SHA512 = 'SHA512', + CRC32 = 'CRC32', + MURMUR3_32 = 'MURMUR3_32', + MURMUR3_128 = 'MURMUR3_128', +} + +export const CHECK_SUM_ALGORITHM_OPTIONS = [ + { value: CHECK_SUM_ALGORITHM.MD5, label: 'MD5' }, + { value: CHECK_SUM_ALGORITHM.CRC32, label: 'CRC-32' }, + { value: CHECK_SUM_ALGORITHM.SHA256, label: 'SHA-256' }, + { value: CHECK_SUM_ALGORITHM.SHA384, label: 'SHA-384' }, + { value: CHECK_SUM_ALGORITHM.SHA512, label: 'SHA-512' }, + { value: CHECK_SUM_ALGORITHM.MURMUR3_32, label: 'MURMUR3-32' }, + { value: CHECK_SUM_ALGORITHM.MURMUR3_128, label: 'MURMUR3-128' }, +] \ No newline at end of file diff --git a/src/locales/lang/en/things.ts b/src/locales/lang/en/things.ts index c04a789d8cb58ced659b8b43f2d3f695bab6cdf6..dbef3ee9b527e98a039bdc7f9511f15f12573582 100644 --- a/src/locales/lang/en/things.ts +++ b/src/locales/lang/en/things.ts @@ -27,4 +27,5 @@ export default { entity: 'Entity', asset: 'Asset', entityView: 'Entity View', + ota: 'OTA Update', } \ No newline at end of file diff --git a/src/locales/lang/zh-CN/things.ts b/src/locales/lang/zh-CN/things.ts index 9bd154cb4185f690c347a596bb78b59b48334fd1..944c98e005b226a05d3a8cb49914cec08bcd497f 100644 --- a/src/locales/lang/zh-CN/things.ts +++ b/src/locales/lang/zh-CN/things.ts @@ -27,4 +27,5 @@ export default { entity: '实体', asset: '资产', entityView: '实体视图', + ota: 'OTA升级', } \ No newline at end of file diff --git a/src/router/routes/modules/things.ts b/src/router/routes/modules/things.ts index 73a5b9816b8a2655e2cfe4af744b8e2a50ff062f..6ad52f6bbe833acda4c0d8d5de444a37c1c81f03 100644 --- a/src/router/routes/modules/things.ts +++ b/src/router/routes/modules/things.ts @@ -91,51 +91,28 @@ const things: AppRouteModule = { }, }, { - path: 'entity', - name: 'Entity', - component: LAYOUT, - redirect: '/entity/index', + path: '/asset/list', + name: 'AssetList', + component: () => import('/@/views/things/asset/list.vue'), meta: { orderNo: 50, - single: true, icon: 'ant-design:desktop-outlined', tabIcon: 'ant-design:desktop-outlined', - title: t('things.entity'), + title: t('things.asset'), + useAuthority: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER] + }, + }, + { + path: '/entity-view/list', + name: 'EntityViewList', + component: () => import('/@/views/things/entityView/list.vue'), + meta: { + orderNo: 60, + icon: 'ant-design:windows-outlined', + tabIcon: 'ant-design:windows-outlined', + title: t('things.entityView'), useAuthority: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER] }, - children: [ - { - path: '/entity/index', - name: 'EntityIndex', - component: () => import('/@/views/things/entityIndex.vue'), - meta: { - icon: 'ant-design:desktop-outlined', - tabIcon: 'ant-design:desktop-outlined', - title: t('things.entity'), - useAuthority: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER] - } - }, { - path: '/asset/list', - name: 'AssetList', - component: () => import('/@/views/things/asset/list.vue'), - meta: { - icon: 'ant-design:desktop-outlined', - tabIcon: 'ant-design:desktop-outlined', - title: t('things.asset'), - useAuthority: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER] - }, - }, - { - path: '/entity-view/list', - name: 'EntityViewList', - component: () => import('/@/views/things/entityView/list.vue'), - meta: { - icon: 'ant-design:right-circle-outlined', - tabIcon: 'ant-design:right-circle-outlined', - title: t('things.entityView'), - useAuthority: [Authority.TENANT_ADMIN, Authority.CUSTOMER_USER] - }, - }] }, { path: 'profile', @@ -229,7 +206,7 @@ const things: AppRouteModule = { component: LAYOUT, redirect: '/rule-chain/list', meta: { - orderNo: 130, + orderNo: 120, icon: 'ant-design:subnode-outlined', tabIcon: 'ant-design:subnode-outlined', title: t('things.ruleChain'), @@ -262,6 +239,18 @@ const things: AppRouteModule = { }, ] }, + { + path: '/otaPackage/list', + name: 'OtaPackage', + component: () => import('/@/views/things/otaPackage/list.vue'), + meta: { + orderNo: 130, + icon: 'ant-design:paper-clip-outlined', + tabIcon: 'ant-design:paper-clip-outlined', + title: t('things.ota'), + useAuthority: [Authority.TENANT_ADMIN] + }, + }, { path: 'resources', name: 'Resource', diff --git a/src/utils/index.ts b/src/utils/index.ts index 2a553d730e8c1024f59bc55e70dfcff4be67edd7..cf0c83ad0caf5599a53daae2f87ef4ca5ecf56f9 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -113,3 +113,10 @@ export function copyToClipboard(value: string, msg: string | undefined = '复制 export const sleep = (time: number) => { return new Promise(resolve => setTimeout(resolve, time)); } + +export function convertBytesToSize(bytes: number) { + const sizes = ['b', 'Kb', 'Mb', 'Gb', 'Tb']; // 存储单位的数组 + if (bytes === 0) { return '0 b' }; + const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); + return Number(bytes / Math.pow(1024, i)).toFixed(2) + ' ' + sizes[i]; +} diff --git a/src/views/things/desktop/sysadmin/index.vue b/src/views/things/desktop/sysadmin/index.vue index 192582ae25a01cdfab7519580c55bd2b1d9022ee..65516bee3ccef69be60802550af9c9923c78f603 100644 --- a/src/views/things/desktop/sysadmin/index.vue +++ b/src/views/things/desktop/sysadmin/index.vue @@ -122,13 +122,13 @@ - + @@ -150,6 +150,7 @@ import CpuStateLine from '../components/chart/CpuStateLine.vue'; import { ref, onMounted, onBeforeUnmount } from 'vue'; import { EntityType } from '/@/enums/entityTypeEnum'; import { isArray } from 'lodash'; +import { convertBytesToSize } from '/@/utils'; const go = useGo(); const { getAndIncrementCmdId, send, unsubscribe } = useWebsocketStore(); @@ -331,12 +332,7 @@ function initCmdId() { CPU_STATUS_CMD_ID.value = getAndIncrementCmdId(); } -function convertBytesToSize(bytes: number) { - const sizes = ['b', 'Kb', 'Mb', 'Gb', 'Tb']; // 存储单位的数组 - if (bytes === 0) { return '0 b' }; - const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); - return Number(bytes / Math.pow(1024, i)).toFixed(2) + ' ' + sizes[i]; -} + onBeforeUnmount(() => { unsubscribeEntityCount(); diff --git a/src/views/things/desktop/tenant/index.vue b/src/views/things/desktop/tenant/index.vue index d0edbbcc79de725baa21281d1d5ad63d8862a318..d64bbd3a13aee56feb1550103e311041fba5ca00 100644 --- a/src/views/things/desktop/tenant/index.vue +++ b/src/views/things/desktop/tenant/index.vue @@ -15,9 +15,9 @@ - +

diff --git a/src/views/things/otaPackage/detail.vue b/src/views/things/otaPackage/detail.vue new file mode 100644 index 0000000000000000000000000000000000000000..9212c4bcb658ada59c3d29dc9e866c73733800ca --- /dev/null +++ b/src/views/things/otaPackage/detail.vue @@ -0,0 +1,132 @@ + + \ No newline at end of file diff --git a/src/views/things/otaPackage/form.vue b/src/views/things/otaPackage/form.vue new file mode 100644 index 0000000000000000000000000000000000000000..51f0f850bc8e79db5cda42edf7d6e7446fbd4128 --- /dev/null +++ b/src/views/things/otaPackage/form.vue @@ -0,0 +1,222 @@ +