Selaa lähdekoodia

feat: 5 /28各类功能增加

lvkun996 1 vuosi sitten
vanhempi
commit
a319e3116e

+ 9 - 0
src/api/iot/data.ts

@@ -9,6 +9,15 @@ export const getHistoryDataPage = (params: IOT.API.DATA.QueryParams) => {
   })
 }
 
+export const exportHistoryExecel = (params: IOT.API.DATA.QueryParams) => {
+  return request<IOT.API.DATA.History[]>({
+    url: '/deviceAttribute/history',
+    method: 'GET',
+    responseType: 'blob',
+    params
+  })
+}
+
 export const getDataApiPage = (params: {page: number, pageSize: number, apiLabel: string}) => {
   return request<IOT.API.DATA.OpenApi>({
     url: '/dataApi/page',

+ 378 - 369
src/api/iot/device.ts

@@ -1,369 +1,378 @@
-import request from '@/service/request'
-
-/**
- * 此函数根据给定的查询参数检索设备列表。
- * @param params - “params”参数是一个“IOT.API.DEVICE.QueryPamars”类型的对象,其中包含 API 请求的查询参数。这些参数用于过滤和分页 API
- * 返回的结果。
- * @returns `getDevice` 函数返回一个解析为 `IOT.API.DEVICE.Device` 对象数组的 Promise。 Promise
- * 由“request”函数返回,该函数使用指定的查询参数(“params”)向“/model/page”端点发出 GET 请求。
- */
-export const getDevicePage = (params: IOT.API.DEVICE.QueryPamars) => {
-  return request<IOT.API.DEVICE.Device[]>({
-    url: '/device/page',
-    method: 'GET',
-    params
-  })
-}
-
-export const getDeviceList = (params: {modelId: string, deviceLabel: string, limit: number, lastId: string }) => {
-  return request<IOT.API.DEVICE.Device[]>({
-    url: '/device/list',
-    method: 'GET',
-    params
-  })
-}
-
-export const getDeviceById = (id: string) => {
-  return request<IOT.API.DEVICE.Device>({
-    url: `/device/${id}`,
-    method: 'GET'
-  })
-}
-
-/**
- *
- * @param id
- * @param authType 设备授权方式
- */
-export const getDeviceSecret = (params: {deviceId: string, authType: 'SECRET' | 'X509CERT'}) => {
-  return request<string>({
-    url: '/deviceSecret',
-    method: 'GET',
-    params
-  })
-}
-
-export const addDevice = (data: IOT.API.DEVICE.BodyParams) => {
-  return request<string>({
-    url: '/device',
-    method: 'POST',
-    data
-  })
-}
-
-export const delDevice = (id: string) => {
-  return request<string>({
-    url: `/device/${id}`,
-    method: 'DELETE'
-  })
-}
-
-export const delDeviceMul = (data: string[]) => {
-  return request<string>({
-    url: '/device',
-    method: 'DELETE',
-    data
-  })
-}
-
-export const updateDeviceLabel = (data: {id: string, deviceLabel: string}) => {
-  return request<string>({
-    url: '/device/deviceLabel',
-    method: 'PUT',
-    data
-  })
-}
-
-export const getSubDeviceList = (id: string, params: IOT.API.DEVICE.QueryPamars) => {
-  return request<string>({
-    url: `/device/subDevice/${id}`,
-    method: 'GET',
-    params
-  })
-}
-
-export const delSubDevice = (id: String) => {
-  return request<string>({
-    url: `/device/subDevice/${id}`,
-    method: 'DELETE'
-  })
-}
-
-export const addSubDevice = (data: IOT.API.DEVICE.SubBodyParams) => {
-  return request<string>({
-    url: '/device/subDevice',
-    method: 'POST',
-    data
-  })
-}
-
-export const addDeviceTag = (data: IOT.API.DEVICE.DeviceTag[]) => {
-  return request<string>({
-    url: '/deviceTag',
-    method: 'POST',
-    data
-  })
-}
-
-export const getDeviceTag = (params: {deviceId: number | string}) => {
-  return request<string>({
-    url: '/deviceTag',
-    method: 'GET',
-    params
-  })
-}
-
-export const delDeviceTag = (id: string) => {
-  return request<string>({
-    url: `/deviceTag/${id}`,
-    method: 'DELETE'
-  })
-}
-
-export const getDeviceCount = (params?: {modelId: string}) => {
-  return request<IOT.API.DEVICE.Count>({
-    url: '/device/count',
-    method: 'GET',
-    params
-  })
-}
-
-/**
- * 此函数检索特定设备的消息。
- * @param params - `params` 对象是传递给 `getDeviceMsgPage` 函数的参数。它有一个属性“deviceId”,它是一个表示设备 ID
- * 的字符串。此参数用于向“/toTransport/msg”端点发出 GET 请求以检索与以下内容相关的消息
- * @returns `getDeviceMsgPage` 函数返回一个解析为 `IOT.API.DEVICE.Msg` 类型对象的
- * Promise。根据传入的“deviceId”参数,此对象可能包含有关发送到特定设备的消息的信息。
- */
-export const getDeviceMsgList = (params: {deviceId: string}) => {
-  return request<IOT.API.DEVICE.Msg[]>({
-    url: '/toTransport/msg',
-    method: 'GET',
-    params
-  })
-}
-
-// "deviceId": “”设备id 必需
-// "msgPayload":"" 消息类容 必需
-// "msgLabel":“”消息名称 必需
-// “topic":"" 主题 非必需
-/**
- * 该函数向 IoT 系统中的设备添加消息。
- * @param data - `data` 参数是一个包含以下属性的对象:
- * @returns `addDeviceMsg` 函数返回一个解析为 `IOT.API.DEVICE.Msg` 类型对象的 Promise。
- */
-export const addDeviceMsg = (data: {deviceId: string, msgPayload: string, msgLabel: string, topic: string}) => {
-  return request<IOT.API.DEVICE.Msg>({
-    url: '/toTransport/msg',
-    method: 'POST',
-    data
-  })
-}
-
-/**
- * 此函数检索特定设备的命令列表。
- * @param params - `params` 参数是一个包含单个属性 `deviceId` 的对象,该属性是表示设备 ID 的字符串。此参数用于向“/toTransport/cmd”端点发出
- * GET 请求以检索消息列表(类型为“IOT.API.DEVICE.Msg”
- * @returns 函数 getDeviceCmdList 返回一个解析为 IOT.API.DEVICE.Msg 对象数组的 Promise。
- */
-export const getDeviceCmdList = (params: {deviceId: string}) => {
-  return request<IOT.API.DEVICE.Msg[]>({
-    url: '/toTransport/cmd',
-    method: 'GET',
-    params
-  })
-}
-
-/**
- * 函数“addDeviceCmd”向“/toTransport/cmd”发送一个 POST 请求,其中包含设备 ID、命令标签和命令参数作为数据。
- * @param data - 包含以下属性的对象:
- * @returns `addDeviceCmd` 函数返回一个解析为字符串的 Promise。 Promise
- * 由“request”函数返回,该函数使用提供的“data”对象作为请求主体向“/toTransport/cmd”端点发送 POST 请求。
- */
-export const addDeviceCmd = (data: { deviceId: string, cmdLabel: string, cmdParameters: any}) => {
-  return request<string>({
-    url: '/toTransport/cmd',
-    method: 'POST',
-    data
-  })
-}
-
-/**
- * 此函数发送一个 POST 请求以创建一个具有指定标签和上层组 ID 的新设备组。
- * @param data - `data` 参数是一个包含两个属性的对象:
- * @returns `addDeviceGroup` 函数返回一个解析为字符串的 Promise。该字符串是在使用提供的“数据”对象向“/deviceGroup”端点发出 POST 请求后服务器的响应。
- */
-export const addDeviceGroup = (data: { groupLabel: string, upperGroupId: string }) => {
-  return request<string>({
-    url: '/deviceGroup',
-    method: 'POST',
-    data
-  })
-}
-
-/**
- * 此函数发送 GET 请求以根据上层组 ID 参数检索设备组列表。
- * @param params - `params` 参数是一个包含 `upperGroupId` 属性的对象。此属性是一个字符串,表示用户要为其检索子组列表的上层设备组的 ID。
- * @returns `listDeviceGroup` 函数返回一个解析为字符串的 Promise。该字符串是使用提供的 params 对象作为查询参数向 `/deviceGroup` 端点发出 GET
- * 请求的响应。
- */
-export const listDeviceGroup = (params: { upperGroupId: string }) => {
-  return request<string>({
-    url: '/deviceGroup',
-    method: 'GET',
-    params
-  })
-}
-
-/**
- * 此函数发送 POST 请求以将设备绑定到设备组。
- * @param data - `data` 参数是一个包含两个属性的对象:
- * @returns 函数 postGroupBindDevice 返回一个解析为字符串的 Promise。该字符串是在使用提供的“数据”对象发出 POST 请求后来自 API
- * 端点“/deviceGroup/device”的响应。
- */
-export const postGroupBindDevice = (data: { deviceGroupId: string, deviceId: string }[]) => {
-  return request<string>({
-    url: '/deviceGroup/device',
-    method: 'POST',
-    data
-  })
-}
-/**
- * 此函数发送 DELETE 请求以从设备组中删除设备。
- * @param data - `data` 参数是一个包含两个属性的对象:
- * @returns 解析为字符串的 Promise。
- */
-export const delGroupBindDevice = (data: { deviceGroupId: string, deviceId: string }[]) => {
-  return request<string>({
-    url: '/deviceGroup/device',
-    method: 'DELETE',
-    data
-  })
-}
-
-export const getDeviceByGroup = (params: IOT.API.DEVICE.GroupQueryParams) => {
-  return request<IOT.API.DEVICE.Device[]>({
-    url: '/device/group',
-    method: 'GET',
-    params
-  })
-}
-
-export const removeDeviceByGroup = (id: string) => {
-  return request<IOT.API.DEVICE.Device[]>({
-    url: '/deviceGroup/' + id,
-    method: 'DELETE'
-  })
-}
-
-/** 获取设备属性 */
-export const getDeviceAttribute = (deviceId: string) => {
-  return request<IOT.API.DEVICE.Device[]>({
-    url: `/deviceAttribute/latest?deviceId=${deviceId}`,
-    method: 'GET'
-  })
-}
-
-/** 实时数据 */
-export const getDevicShadow = (deviceId: string) => {
-  return request<IOT.API.DEVICE.Device[]>({
-    url: `/deviceAttribute/shadow?deviceId=${deviceId}`,
-    method: 'GET'
-  })
-}
-
-/** 设备拓扑 */
-export const getDeviceTopology = (modelId: string) => {
-  return request<IOT.API.DEVICE.Topology>({
-    url: `/device/topology?modelId=${modelId}`,
-    method: 'GET'
-  })
-}
-
-/** 设备上下线 */
-export const getDeviceSession = (params: {deviceId: string, start: number, end: number}) => {
-  return request<IOT.API.DEVICE.Session>({
-    url: '/deviceAnalysis/session',
-    method: 'GET',
-    params
-  })
-}
-
-/** 设备属性 */
-export const getDeviceAttributes = (params: {deviceId: string, start: number, end: number}) => {
-  return request<IOT.API.DEVICE.Attr>({
-    url: '/deviceAnalysis/attributes',
-    method: 'GET',
-    params
-  })
-}
-
-/** ota  */
-export const getOtaByDeviceId = (deviceId: string) => {
-  return request<IOT.API.DEVICE.Ota>({
-    url: `/deviceOta/${deviceId}`,
-    method: 'GET'
-  })
-}
-
-export const otaUpgradationRecordByDeviceId = (params: IOT.API.DEVICE.OtaQueryParams) => {
-  return request<IOT.API.DEVICE.Ota[]>({
-    url: '/deviceOta/page',
-    method: 'GET',
-    params
-  })
-}
-
-/** 根据设备id, ota包id来升级设备 */
-export const upgradationOtaByDeviceId = (deviceId: string, otaPkgId: string) => {
-  return request<string>({
-    url: '/deviceOta',
-    method: 'POST',
-    data: {
-      deviceId,
-      otaPkgId
-    }
-  })
-}
-
-/** 视频流 */
-export const liveById = (deviceId: string) => {
-  return request<string>({
-    url: `/toTransport/rts/${deviceId}`,
-    method: 'POST'
-  })
-}
-
-/** 视频流通道控制 */
-export const liveControlRts = (deviceId: string, channel: number) => {
-  return request<string>({
-    url: `/toTransport/controlRts/${deviceId}/${channel}`,
-    method: 'POST'
-  })
-}
-
-/** 自定义视频流 */
-export const liveCustomRtsUrl = (data: {id: string, rtsUrl: string}) => {
-  return request<string>({
-    url: '/device/rtsUrl',
-    method: 'PUT',
-    data
-  })
-}
-
-// /device/deviceLabel?deviceLabel=xxxx
-/** 模糊查询:根据设备名称来查询全部的符合条件的设备名 */
-export const getDeviceLabelsByLabel = (deviceLabel: string) => {
-  return request<{id: number, deviceLabel: string}[]>({
-    url: `/device/deviceLabel?deviceLabel=${deviceLabel}`,
-    method: 'GET'
-  })
-}
-
-export const deviceSimulator = (data: {deviceId: string, payload: string}) => {
-  return request<string>({
-    url: '/device/simulator',
-    method: 'POST',
-    data
-  })
-}
+import request from '@/service/request'
+
+/**
+ * 此函数根据给定的查询参数检索设备列表。
+ * @param params - “params”参数是一个“IOT.API.DEVICE.QueryPamars”类型的对象,其中包含 API 请求的查询参数。这些参数用于过滤和分页 API
+ * 返回的结果。
+ * @returns `getDevice` 函数返回一个解析为 `IOT.API.DEVICE.Device` 对象数组的 Promise。 Promise
+ * 由“request”函数返回,该函数使用指定的查询参数(“params”)向“/model/page”端点发出 GET 请求。
+ */
+export const getDevicePage = (params: IOT.API.DEVICE.QueryPamars) => {
+  return request<IOT.API.DEVICE.Device[]>({
+    url: '/device/page',
+    method: 'GET',
+    params
+  })
+}
+
+export const getDeviceList = (params: {modelId: string, deviceLabel: string, limit: number, lastId: string }) => {
+  return request<IOT.API.DEVICE.Device[]>({
+    url: '/device/list',
+    method: 'GET',
+    params
+  })
+}
+
+export const getDeviceById = (id: string) => {
+  return request<IOT.API.DEVICE.Device>({
+    url: `/device/${id}`,
+    method: 'GET'
+  })
+}
+
+/**
+ *
+ * @param id
+ * @param authType 设备授权方式
+ */
+export const getDeviceSecret = (params: {deviceId: string, authType: 'SECRET' | 'X509CERT'}) => {
+  return request<string>({
+    url: '/deviceSecret',
+    method: 'GET',
+    params
+  })
+}
+
+export const addDevice = (data: IOT.API.DEVICE.BodyParams) => {
+  return request<string>({
+    url: '/device',
+    method: 'POST',
+    data
+  })
+}
+
+export const delDevice = (id: string) => {
+  return request<string>({
+    url: `/device/${id}`,
+    method: 'DELETE'
+  })
+}
+
+export const delDeviceMul = (data: string[]) => {
+  return request<string>({
+    url: '/device',
+    method: 'DELETE',
+    data
+  })
+}
+
+export const updateDeviceLabel = (data: {id: string, deviceLabel: string}) => {
+  return request<string>({
+    url: '/device/deviceLabel',
+    method: 'PUT',
+    data
+  })
+}
+
+export const getSubDeviceList = (id: string, params: IOT.API.DEVICE.QueryPamars) => {
+  return request<string>({
+    url: `/device/subDevice/${id}`,
+    method: 'GET',
+    params
+  })
+}
+
+export const delSubDevice = (id: String) => {
+  return request<string>({
+    url: `/device/subDevice/${id}`,
+    method: 'DELETE'
+  })
+}
+
+export const addSubDevice = (data: IOT.API.DEVICE.SubBodyParams) => {
+  return request<string>({
+    url: '/device/subDevice',
+    method: 'POST',
+    data
+  })
+}
+
+export const addDeviceTag = (data: IOT.API.DEVICE.DeviceTag[]) => {
+  return request<string>({
+    url: '/deviceTag',
+    method: 'POST',
+    data
+  })
+}
+
+export const getDeviceTag = (params: {deviceId: number | string}) => {
+  return request<string>({
+    url: '/deviceTag',
+    method: 'GET',
+    params
+  })
+}
+
+export const delDeviceTag = (id: string) => {
+  return request<string>({
+    url: `/deviceTag/${id}`,
+    method: 'DELETE'
+  })
+}
+
+export const getDeviceCount = (params?: {modelId: string}) => {
+  return request<IOT.API.DEVICE.Count>({
+    url: '/device/count',
+    method: 'GET',
+    params
+  })
+}
+
+/**
+ * 此函数检索特定设备的消息。
+ * @param params - `params` 对象是传递给 `getDeviceMsgPage` 函数的参数。它有一个属性“deviceId”,它是一个表示设备 ID
+ * 的字符串。此参数用于向“/toTransport/msg”端点发出 GET 请求以检索与以下内容相关的消息
+ * @returns `getDeviceMsgPage` 函数返回一个解析为 `IOT.API.DEVICE.Msg` 类型对象的
+ * Promise。根据传入的“deviceId”参数,此对象可能包含有关发送到特定设备的消息的信息。
+ */
+export const getDeviceMsgList = (params: {deviceId: string}) => {
+  return request<IOT.API.DEVICE.Msg[]>({
+    url: '/toTransport/msg',
+    method: 'GET',
+    params
+  })
+}
+
+// "deviceId": “”设备id 必需
+// "msgPayload":"" 消息类容 必需
+// "msgLabel":“”消息名称 必需
+// “topic":"" 主题 非必需
+/**
+ * 该函数向 IoT 系统中的设备添加消息。
+ * @param data - `data` 参数是一个包含以下属性的对象:
+ * @returns `addDeviceMsg` 函数返回一个解析为 `IOT.API.DEVICE.Msg` 类型对象的 Promise。
+ */
+export const addDeviceMsg = (data: {deviceId: string, msgPayload: string, msgLabel: string, topic: string}) => {
+  return request<IOT.API.DEVICE.Msg>({
+    url: '/toTransport/msg',
+    method: 'POST',
+    data
+  })
+}
+
+/**
+ * 此函数检索特定设备的命令列表。
+ * @param params - `params` 参数是一个包含单个属性 `deviceId` 的对象,该属性是表示设备 ID 的字符串。此参数用于向“/toTransport/cmd”端点发出
+ * GET 请求以检索消息列表(类型为“IOT.API.DEVICE.Msg”
+ * @returns 函数 getDeviceCmdList 返回一个解析为 IOT.API.DEVICE.Msg 对象数组的 Promise。
+ */
+export const getDeviceCmdList = (params: {deviceId: string}) => {
+  return request<IOT.API.DEVICE.Msg[]>({
+    url: '/toTransport/cmd',
+    method: 'GET',
+    params
+  })
+}
+
+/**
+ * 函数“addDeviceCmd”向“/toTransport/cmd”发送一个 POST 请求,其中包含设备 ID、命令标签和命令参数作为数据。
+ * @param data - 包含以下属性的对象:
+ * @returns `addDeviceCmd` 函数返回一个解析为字符串的 Promise。 Promise
+ * 由“request”函数返回,该函数使用提供的“data”对象作为请求主体向“/toTransport/cmd”端点发送 POST 请求。
+ */
+export const addDeviceCmd = (data: { deviceId: string, cmdLabel: string, cmdParameters: any}) => {
+  return request<string>({
+    url: '/toTransport/cmd',
+    method: 'POST',
+    data
+  })
+}
+
+/**
+ * 此函数发送一个 POST 请求以创建一个具有指定标签和上层组 ID 的新设备组。
+ * @param data - `data` 参数是一个包含两个属性的对象:
+ * @returns `addDeviceGroup` 函数返回一个解析为字符串的 Promise。该字符串是在使用提供的“数据”对象向“/deviceGroup”端点发出 POST 请求后服务器的响应。
+ */
+export const addDeviceGroup = (data: { groupLabel: string, upperGroupId: string }) => {
+  return request<string>({
+    url: '/deviceGroup',
+    method: 'POST',
+    data
+  })
+}
+
+/**
+ * 此函数发送 GET 请求以根据上层组 ID 参数检索设备组列表。
+ * @param params - `params` 参数是一个包含 `upperGroupId` 属性的对象。此属性是一个字符串,表示用户要为其检索子组列表的上层设备组的 ID。
+ * @returns `listDeviceGroup` 函数返回一个解析为字符串的 Promise。该字符串是使用提供的 params 对象作为查询参数向 `/deviceGroup` 端点发出 GET
+ * 请求的响应。
+ */
+export const listDeviceGroup = (params: { upperGroupId: string }) => {
+  return request<string>({
+    url: '/deviceGroup',
+    method: 'GET',
+    params
+  })
+}
+
+/**
+ * 此函数发送 POST 请求以将设备绑定到设备组。
+ * @param data - `data` 参数是一个包含两个属性的对象:
+ * @returns 函数 postGroupBindDevice 返回一个解析为字符串的 Promise。该字符串是在使用提供的“数据”对象发出 POST 请求后来自 API
+ * 端点“/deviceGroup/device”的响应。
+ */
+export const postGroupBindDevice = (data: { deviceGroupId: string, deviceId: string }[]) => {
+  return request<string>({
+    url: '/deviceGroup/device',
+    method: 'POST',
+    data
+  })
+}
+/**
+ * 此函数发送 DELETE 请求以从设备组中删除设备。
+ * @param data - `data` 参数是一个包含两个属性的对象:
+ * @returns 解析为字符串的 Promise。
+ */
+export const delGroupBindDevice = (data: { deviceGroupId: string, deviceId: string }[]) => {
+  return request<string>({
+    url: '/deviceGroup/device',
+    method: 'DELETE',
+    data
+  })
+}
+
+export const getDeviceByGroup = (params: IOT.API.DEVICE.GroupQueryParams) => {
+  return request<IOT.API.DEVICE.Device[]>({
+    url: '/device/group',
+    method: 'GET',
+    params
+  })
+}
+
+export const removeDeviceByGroup = (id: string) => {
+  return request<IOT.API.DEVICE.Device[]>({
+    url: '/deviceGroup/' + id,
+    method: 'DELETE'
+  })
+}
+
+/** 获取设备属性 */
+export const getDeviceAttribute = (deviceId: string) => {
+  return request<IOT.API.DEVICE.Device[]>({
+    url: `/deviceAttribute/latest?deviceId=${deviceId}`,
+    method: 'GET'
+  })
+}
+
+/** 实时数据 */
+export const getDevicShadow = (deviceId: string) => {
+  return request<IOT.API.DEVICE.Device[]>({
+    url: `/deviceAttribute/shadow?deviceId=${deviceId}`,
+    method: 'GET'
+  })
+}
+
+/** 设备拓扑 */
+export const getDeviceTopology = (modelId: string) => {
+  return request<IOT.API.DEVICE.Topology>({
+    url: `/device/topology?modelId=${modelId}`,
+    method: 'GET'
+  })
+}
+
+/** 设备上下线 */
+export const getDeviceSession = (params: {deviceId: string, start: number, end: number}) => {
+  return request<IOT.API.DEVICE.Session>({
+    url: '/deviceAnalysis/session',
+    method: 'GET',
+    params
+  })
+}
+
+/** 设备属性 */
+export const getDeviceAttributes = (params: {deviceId: string, start: number, end: number}) => {
+  return request<IOT.API.DEVICE.Attr>({
+    url: '/deviceAnalysis/attributes',
+    method: 'GET',
+    params
+  })
+}
+
+/** ota  */
+export const getOtaByDeviceId = (deviceId: string) => {
+  return request<IOT.API.DEVICE.Ota>({
+    url: `/deviceOta/${deviceId}`,
+    method: 'GET'
+  })
+}
+
+export const otaUpgradationRecordByDeviceId = (params: IOT.API.DEVICE.OtaQueryParams) => {
+  return request<IOT.API.DEVICE.Ota[]>({
+    url: '/deviceOta/page',
+    method: 'GET',
+    params
+  })
+}
+
+/** 根据设备id, ota包id来升级设备 */
+export const upgradationOtaByDeviceId = (deviceId: string, otaPkgId: string) => {
+  return request<string>({
+    url: '/deviceOta',
+    method: 'POST',
+    data: {
+      deviceId,
+      otaPkgId
+    }
+  })
+}
+
+/** 视频流 */
+export const liveById = (deviceId: string) => {
+  return request<string>({
+    url: `/toTransport/rts/${deviceId}`,
+    method: 'POST'
+  })
+}
+
+/** 视频流通道控制 */
+export const liveControlRts = (deviceId: string, channel: number) => {
+  return request<string>({
+    url: `/toTransport/controlRts/${deviceId}/${channel}`,
+    method: 'POST'
+  })
+}
+
+/** 自定义视频流 */
+export const liveCustomRtsUrl = (data: {id: string, rtsUrl: string}) => {
+  return request<string>({
+    url: '/device/rtsUrl',
+    method: 'PUT',
+    data
+  })
+}
+
+// /device/deviceLabel?deviceLabel=xxxx
+/** 模糊查询:根据设备名称来查询全部的符合条件的设备名 */
+export const getDeviceLabelsByLabel = (deviceLabel: string) => {
+  return request<{id: number, deviceLabel: string}[]>({
+    url: `/device/deviceLabel?deviceLabel=${deviceLabel}`,
+    method: 'GET'
+  })
+}
+
+export const deviceSimulator = (data: {deviceId: string, payload: string}) => {
+  return request<string>({
+    url: '/device/simulator',
+    method: 'POST',
+    data
+  })
+}
+
+export const exportDeviceExcel = (params: IOT.API.DEVICE.QueryPamars) => {
+  return request<string>({
+    url: '/deviceExcel/export',
+    method: 'GET',
+    responseType: 'blob',
+    params
+  })
+}

+ 5 - 1
src/controller/iot/data.ts

@@ -1,4 +1,4 @@
-import { getAppId, getDataApiPage, getHistoryDataPage, postAppId, delAppIdById, updateAppId } from '@/api/iot/data'
+import { getAppId, getDataApiPage, getHistoryDataPage, postAppId, delAppIdById, updateAppId, exportHistoryExecel } from '@/api/iot/data'
 import { message } from 'ant-design-vue'
 
 export class DataController {
@@ -6,6 +6,10 @@ export class DataController {
     return await getHistoryDataPage(params)
   }
 
+  static async exportHistoryExecel (params: IOT.API.DATA.QueryParams) {
+    await exportHistoryExecel(params)
+  }
+
   static async pageOpenAPiList (params: {page: number, pageSize: number, apiLabel: string}) {
     return await getDataApiPage(params)
   }

+ 5 - 1
src/controller/iot/device.ts

@@ -35,7 +35,7 @@ import {
   liveControlRts,
   liveCustomRtsUrl,
   getDeviceLabelsByLabel,
-  removeDeviceByGroup, deviceSimulator
+  removeDeviceByGroup, deviceSimulator, exportDeviceExcel
 } from '@/api/iot/device'
 import { DeviceMsgEnum, OtaStatusEnum } from '@/enum/common'
 import { message } from 'ant-design-vue'
@@ -360,4 +360,8 @@ export class DeviceContriller {
   static async deviceSimulator (data: { deviceId: string, payload: string }) {
     await deviceSimulator(data)
   }
+
+  static async exportDeviceExcel (data: IOT.API.DEVICE.QueryPamars) {
+    await exportDeviceExcel(data)
+  }
 }

+ 27 - 15
src/hooks/dom.ts

@@ -1,15 +1,27 @@
-import { message } from 'ant-design-vue'
-
-/**
- * 此 TypeScript 函数创建一个临时输入元素,将其值设置为给定字符串,将值复制到剪贴板,然后删除输入元素。
- * @param {string} content - content 参数是一个字符串,表示需要复制到剪贴板的文本。
- */
-export const useCopy = (content: string) => {
-  const inputValue = document.createElement('input')
-  document.body.appendChild(inputValue)
-  inputValue.value = content
-  inputValue.select()
-  document.execCommand('copy')
-  message.success('复制成功')
-  document.body.removeChild(inputValue)
-}
+import { message } from 'ant-design-vue'
+
+/**
+ * 此 TypeScript 函数创建一个临时输入元素,将其值设置为给定字符串,将值复制到剪贴板,然后删除输入元素。
+ * @param {string} content - content 参数是一个字符串,表示需要复制到剪贴板的文本。
+ */
+export const useCopy = (content: string) => {
+  const inputValue = document.createElement('input')
+  document.body.appendChild(inputValue)
+  inputValue.value = content
+  inputValue.select()
+  document.execCommand('copy')
+  message.success('复制成功')
+  document.body.removeChild(inputValue)
+}
+
+export const exportExcel = (data, fileName = '蛟龙云') => {
+  const blob = new Blob([data])
+  const downloadElement = document.createElement('a')
+  const href = window.URL.createObjectURL(blob) // 创建下载的链接
+  downloadElement.download = `${fileName}.xls`
+  downloadElement.href = href
+  document.body.appendChild(downloadElement)
+  downloadElement.click() // 点击下载
+  document.body.removeChild(downloadElement) // 下载完成移除元素
+  window.URL.revokeObjectURL(href)
+}

+ 57 - 31
src/pages/Iot/device/analysis.vue

@@ -43,11 +43,13 @@
                   v-for="item in deviceState.attrList"
                   :key="item.key"
                   :value="item.key"
-                >{{item.keyLabel}}</a-select-option>
+                >
+                  {{item.keyLabel}}
+                </a-select-option>
             </a-select>
             <!-- 聚合函数参数 -->
             <a-select v-if="activeTabKey ===  'poly'" placeholder="聚合函数只对数字类型有效"  style="width: 120px" v-model:value="state.aggregationFunc" >
-              <a-select-option v-for="item in aggregationFunc" :key="item.key">
+              <a-select-option v-for="item in aggregationFunc" :key="item.key" :value="item.key" >
                 {{item.title}}
               </a-select-option>
             </a-select>
@@ -68,16 +70,15 @@
           <a-spin :spinning="state.loading" >
           <a-empty style="margin: 0 auto;" v-if="emptyCondition" :description="emptyDesc" ></a-empty>
           <span v-else>
-
             <a-col :span="24" v-if="activeTabKey === 'session'" style="margin-top: 20px">
               <a-row  >
                 <a-col :xs="24" :md="24" :xl="12"  style="position: relative;width: 100%;height: 400px;" >
-                  <!-- <div style="position: absolute;right: 0;top: 0;z-index: 99;width: 40px;height: 60px" >
+                  <div style="position: absolute;right: 60px;top: 0;z-index: 99;width: 40px;height: 60px" >
                     <a-space>
                       <a-button :type="lineChartZindex.line > lineChartZindex.bar ? 'primary' : ''"  :icon="h(LineChartOutlined)"  @click="changeChart('line')"/>
                       <a-button :type="lineChartZindex.line <= lineChartZindex.bar ? 'primary' : ''"  :icon="h(BarChartOutlined)"  @click="changeChart('bar')"/>
                     </a-space>
-                  </div> -->
+                  </div>
                   <div id="device-session" :style="{backgroundColor: '#fff', width: '600px',height: '400px',position: 'absolute',top: '0',left: 0,zIndex: lineChartZindex.line}" ></div>
                   <div id="device-session-scatter" :style="{backgroundColor: '#fff',width: '600px',height: '400px',position: 'absolute',top: '0',left: 0,zIndex: lineChartZindex.bar}" ></div>
                 </a-col>
@@ -86,23 +87,29 @@
                     :dataSource="state.dataSource"
                     :columns="lineCloumns"
                   >
-                  </a-table>
-                </a-col>
-              </a-row>
-            </a-col>
-            <a-col :span="24" v-else>
-              <div  id="device-attr"  style="width: 1000px; height: 400px;"  ></div>
-              <a-table
-                :dataSource="state.attrSource"
-                :columns="columns"
-              >
-                <template #bodyCell="{column, record}" >
-                  <template v-if="column.key === 'value'">
-                    <span>{{record.value}}</span><span>{{record.dataunit}}</span>
-                  </template>
-                  <template v-if="column.key === 'ts'">
-                    <span>{{dayjs(record.ts).format('YYYY/MM/DD HH:mm:ss')}}</span>
-                  </template>
+                    <template #bodyCell="{column, record}" >
+                      <template v-if="column.key === 'sessionType'">
+                        <span>{{record.sessionType === 'DISCONNECT' ? "未连接" : '已连接'}}</span>
+                      </template>
+                    </template>
+                    </a-table>
+                  </a-col>
+                </a-row>
+              </a-col>
+              <a-col :span="24" v-else>
+                <div  id="device-attr"  style="width: 1000px; height: 400px;"  ></div>
+                <a-table
+                  :dataSource="state.attrSource"
+                  :columns="columns"
+                  :pagination="pagination"
+                >
+                  <template #bodyCell="{column, record}" >
+                    <template v-if="column.key === 'value'">
+                      <span>{{record.value}}</span><span>{{record.dataunit}}</span>
+                    </template>
+                    <template v-if="column.key === 'ts'">
+                      <span>{{dayjs(record.ts).format('YYYY/MM/DD HH:mm:ss')}}</span>
+                    </template>
                 </template>
               </a-table>
             </a-col>
@@ -122,7 +129,7 @@ import dayjs from 'dayjs'
 import StatisticsTemplate from '@/components/StatisticsTemplate'
 import { message } from 'ant-design-vue'
 import { LineChartOutlined, BarChartOutlined } from '@ant-design/icons-vue'
-import { useThrottle } from 'flicker-vue-hooks'
+import { useSchedulerOnce, useThrottle } from 'flicker-vue-hooks'
 
 const columns = [
   {
@@ -251,7 +258,13 @@ const times = ref([dayjs().subtract(30, 'minute'), dayjs()])
 
 state.deviceId = route.query.id as string
 
-const onTabChange = (key: 'session' | 'attr') => activeTabKey.value = key
+const onTabChange = (key: 'session' | 'attr') => {
+  state.dataSource = []
+  state.attrSource = []
+  state.deviceLit = []
+  deviceState.attrList = []
+  activeTabKey.value = key
+}
 
 // 切换上下线分析
 watch(
@@ -356,17 +369,21 @@ const selectDevice = async (value: string) => {
   state.deviceId = value
   console.log('选择了设备')
 
-  // getDeviceAttribute()
+  getDeviceAttribute()
 }
 
+const timeId = ref()
 // 获取设备列表
 const getDeviceLabel = async (val: string) => {
-  if (!val) return
-  state.spinning = true
-  const { data } = await DeviceContriller.labelsByLabel(val)
-  state.spinning = false
-  state.deviceLit = data.map(item => ({ value: item.id, label: item.deviceLabel }))
-  console.log(data)
+  clearTimeout(timeId.value)
+  timeId.value = setTimeout(async () => {
+    if (!val) return
+    state.spinning = true
+    const { data } = await DeviceContriller.labelsByLabel(val)
+    state.spinning = false
+    state.deviceLit = data.map(item => ({ value: item.id, label: item.deviceLabel }))
+    console.log(data)
+  }, 1500)
 }
 
 // 上下线分析
@@ -394,10 +411,19 @@ const getDeviceAttr = async () => {
   state.attrSource = data
 }
 
+const pagination = ref({
+  page: 0,
+  pageSize: 10,
+  hideOnSinglePage: true,
+  simple: true,
+  total: 0
+})
+
 // 属性聚合分析
 const getDeviceAttribute = async () => {
   const { data } = await DeviceContriller.getDeviceAttribute(state.deviceId)
   deviceState.attrList = data
+  pagination.value.total = data.length
 }
 
 onMounted(() => {

+ 8 - 8
src/pages/Iot/device/index.vue

@@ -66,9 +66,9 @@
         <template v-if="column.key === 'deviceNodeType'" >
           <a-tag>{{record.deviceNodeType == 'GATEWAY'?'直连类型':'非直连类型'}}</a-tag>
         </template>
-        <template v-if="column.key === 'rtsUrl'" >
+        <!-- <template v-if="column.key === 'rtsUrl'" >
           {{record.rtsUrl ? '支持': '否'}}
-        </template>
+        </template> -->
         <template v-if="column.key === 'action'">
             <a-space>
               <a @click="goDetailPage(record.id)">查看</a>
@@ -182,12 +182,12 @@ const columns = [
     dataIndex: 'modelLabel',
     ellipsis: true
   },
-  {
-    title: '支持live',
-    dataIndex: 'rtsUrl',
-    key: 'rtsUrl',
-    width: 100
-  },
+  // {
+  //   title: '支持live',
+  //   dataIndex: 'rtsUrl',
+  //   key: 'rtsUrl',
+  //   width: 100
+  // },
   {
     title: '状态',
     dataIndex: 'deviceStatus',

+ 248 - 248
src/pages/Iot/device/json/echartsJson.ts

@@ -1,248 +1,248 @@
-export const sessionEchartsJson = {
-  title: {
-    text: ''
-  },
-  tooltip: {
-    trigger: 'axis',
-    formatter: function (params, ticket, callback) {
-      console.log('params:', params)
-
-      // return params.name.split(' ')[1]
-      return ''
-    }
-  },
-  legend: {
-  },
-  grid: {
-    left: '3%',
-    right: '4%',
-    bottom: '3%',
-    containLabel: true
-  },
-  toolbox: {
-    feature: {
-      saveAsImage: {}
-    }
-  },
-  xAxis: {
-    type: 'category',
-    boundaryGap: false,
-    data: []
-  },
-  yAxis: {
-    type: 'category',
-    data: ['上线', '下线']
-  },
-  series: [
-    {
-      name: 'offlineNum',
-      type: 'line',
-      stack: 'Total',
-      data: [],
-      timeStamp: 7788
-    },
-    {
-      name: 'onlineNum',
-      type: 'line',
-      stack: 'Total',
-      data: [],
-      timeStamp: 7788
-    }
-  ]
-}
-
-// prettier-ignore
-const femaleData = [[161.2, 51.6], [167.5, 59.0], [159.5, 49.2], [157.0, 63.0], [155.8, 53.6],
-  [170.0, 59.0], [159.1, 47.6], [166.0, 69.8], [176.2, 66.8], [160.2, 75.2],
-  [172.5, 55.2], [170.9, 54.2], [172.9, 62.5], [153.4, 42.0], [160.0, 50.0],
-  [147.2, 49.8], [168.2, 49.2], [175.0, 73.2], [157.0, 47.8], [167.6, 68.8],
-  [159.5, 50.6], [175.0, 82.5], [166.8, 57.2], [176.5, 87.8], [170.2, 72.8],
-  [174.0, 54.5], [173.0, 59.8], [179.9, 67.3], [170.5, 67.8], [160.0, 47.0],
-  [154.4, 46.2], [162.0, 55.0], [176.5, 83.0], [160.0, 54.4], [152.0, 45.8],
-  [162.1, 53.6], [170.0, 73.2], [160.2, 52.1], [161.3, 67.9], [166.4, 56.6],
-  [168.9, 62.3], [163.8, 58.5], [167.6, 54.5], [160.0, 50.2], [161.3, 60.3],
-  [167.6, 58.3], [165.1, 56.2], [160.0, 50.2], [170.0, 72.9], [157.5, 59.8],
-  [167.6, 61.0], [160.7, 69.1], [163.2, 55.9], [152.4, 46.5], [157.5, 54.3],
-  [168.3, 54.8], [180.3, 60.7], [165.5, 60.0], [165.0, 62.0], [164.5, 60.3],
-  [156.0, 52.7], [160.0, 74.3], [163.0, 62.0], [165.7, 73.1], [161.0, 80.0],
-  [162.0, 54.7], [166.0, 53.2], [174.0, 75.7], [172.7, 61.1], [167.6, 55.7],
-  [151.1, 48.7], [164.5, 52.3], [163.5, 50.0], [152.0, 59.3], [169.0, 62.5],
-  [164.0, 55.7], [161.2, 54.8], [155.0, 45.9], [170.0, 70.6], [176.2, 67.2],
-  [170.0, 69.4], [162.5, 58.2], [170.3, 64.8], [164.1, 71.6], [169.5, 52.8],
-  [163.2, 59.8], [154.5, 49.0], [159.8, 50.0], [173.2, 69.2], [170.0, 55.9],
-  [161.4, 63.4], [169.0, 58.2], [166.2, 58.6], [159.4, 45.7], [162.5, 52.2],
-  [159.0, 48.6], [162.8, 57.8], [159.0, 55.6], [179.8, 66.8], [162.9, 59.4],
-  [161.0, 53.6], [151.1, 73.2], [168.2, 53.4], [168.9, 69.0], [173.2, 58.4],
-  [171.8, 56.2], [178.0, 70.6], [164.3, 59.8], [163.0, 72.0], [168.5, 65.2],
-  [166.8, 56.6], [172.7, 105.2], [163.5, 51.8], [169.4, 63.4], [167.8, 59.0],
-  [159.5, 47.6], [167.6, 63.0], [161.2, 55.2], [160.0, 45.0], [163.2, 54.0],
-  [162.2, 50.2], [161.3, 60.2], [149.5, 44.8], [157.5, 58.8], [163.2, 56.4],
-  [172.7, 62.0], [155.0, 49.2], [156.5, 67.2], [164.0, 53.8], [160.9, 54.4],
-  [162.8, 58.0], [167.0, 59.8], [160.0, 54.8], [160.0, 43.2], [168.9, 60.5],
-  [158.2, 46.4], [156.0, 64.4], [160.0, 48.8], [167.1, 62.2], [158.0, 55.5],
-  [167.6, 57.8], [156.0, 54.6], [162.1, 59.2], [173.4, 52.7], [159.8, 53.2],
-  [170.5, 64.5], [159.2, 51.8], [157.5, 56.0], [161.3, 63.6], [162.6, 63.2],
-  [160.0, 59.5], [168.9, 56.8], [165.1, 64.1], [162.6, 50.0], [165.1, 72.3],
-  [166.4, 55.0], [160.0, 55.9], [152.4, 60.4], [170.2, 69.1], [162.6, 84.5],
-  [170.2, 55.9], [158.8, 55.5], [172.7, 69.5], [167.6, 76.4], [162.6, 61.4],
-  [167.6, 65.9], [156.2, 58.6], [175.2, 66.8], [172.1, 56.6], [162.6, 58.6],
-  [160.0, 55.9], [165.1, 59.1], [182.9, 81.8], [166.4, 70.7], [165.1, 56.8],
-  [177.8, 60.0], [165.1, 58.2], [175.3, 72.7], [154.9, 54.1], [158.8, 49.1],
-  [172.7, 75.9], [168.9, 55.0], [161.3, 57.3], [167.6, 55.0], [165.1, 65.5],
-  [175.3, 65.5], [157.5, 48.6], [163.8, 58.6], [167.6, 63.6], [165.1, 55.2],
-  [165.1, 62.7], [168.9, 56.6], [162.6, 53.9], [164.5, 63.2], [176.5, 73.6],
-  [168.9, 62.0], [175.3, 63.6], [159.4, 53.2], [160.0, 53.4], [170.2, 55.0],
-  [162.6, 70.5], [167.6, 54.5], [162.6, 54.5], [160.7, 55.9], [160.0, 59.0],
-  [157.5, 63.6], [162.6, 54.5], [152.4, 47.3], [170.2, 67.7], [165.1, 80.9],
-  [172.7, 70.5], [165.1, 60.9], [170.2, 63.6], [170.2, 54.5], [170.2, 59.1],
-  [161.3, 70.5], [167.6, 52.7], [167.6, 62.7], [165.1, 86.3], [162.6, 66.4],
-  [152.4, 67.3], [168.9, 63.0], [170.2, 73.6], [175.2, 62.3], [175.2, 57.7],
-  [160.0, 55.4], [165.1, 104.1], [174.0, 55.5], [170.2, 77.3], [160.0, 80.5],
-  [167.6, 64.5], [167.6, 72.3], [167.6, 61.4], [154.9, 58.2], [162.6, 81.8],
-  [175.3, 63.6], [171.4, 53.4], [157.5, 54.5], [165.1, 53.6], [160.0, 60.0],
-  [174.0, 73.6], [162.6, 61.4], [174.0, 55.5], [162.6, 63.6], [161.3, 60.9],
-  [156.2, 60.0], [149.9, 46.8], [169.5, 57.3], [160.0, 64.1], [175.3, 63.6],
-  [169.5, 67.3], [160.0, 75.5], [172.7, 68.2], [162.6, 61.4], [157.5, 76.8],
-  [176.5, 71.8], [164.4, 55.5], [160.7, 48.6], [174.0, 66.4], [163.8, 67.3]
-]
-// prettier-ignore
-const maleDeta = [[174.0, 65.6], [175.3, 71.8], [193.5, 80.7], [186.5, 72.6], [187.2, 78.8],
-  [181.5, 74.8], [184.0, 86.4], [184.5, 78.4], [175.0, 62.0], [184.0, 81.6],
-  [180.0, 76.6], [177.8, 83.6], [192.0, 90.0], [176.0, 74.6], [174.0, 71.0],
-  [184.0, 79.6], [192.7, 93.8], [171.5, 70.0], [173.0, 72.4], [176.0, 85.9],
-  [176.0, 78.8], [180.5, 77.8], [172.7, 66.2], [176.0, 86.4], [173.5, 81.8],
-  [178.0, 89.6], [180.3, 82.8], [180.3, 76.4], [164.5, 63.2], [173.0, 60.9],
-  [183.5, 74.8], [175.5, 70.0], [188.0, 72.4], [189.2, 84.1], [172.8, 69.1],
-  [170.0, 59.5], [182.0, 67.2], [170.0, 61.3], [177.8, 68.6], [184.2, 80.1],
-  [186.7, 87.8], [171.4, 84.7], [172.7, 73.4], [175.3, 72.1], [180.3, 82.6],
-  [182.9, 88.7], [188.0, 84.1], [177.2, 94.1], [172.1, 74.9], [167.0, 59.1],
-  [169.5, 75.6], [174.0, 86.2], [172.7, 75.3], [182.2, 87.1], [164.1, 55.2],
-  [163.0, 57.0], [171.5, 61.4], [184.2, 76.8], [174.0, 86.8], [174.0, 72.2],
-  [177.0, 71.6], [186.0, 84.8], [167.0, 68.2], [171.8, 66.1], [182.0, 72.0],
-  [167.0, 64.6], [177.8, 74.8], [164.5, 70.0], [192.0, 101.6], [175.5, 63.2],
-  [171.2, 79.1], [181.6, 78.9], [167.4, 67.7], [181.1, 66.0], [177.0, 68.2],
-  [174.5, 63.9], [177.5, 72.0], [170.5, 56.8], [182.4, 74.5], [197.1, 90.9],
-  [180.1, 93.0], [175.5, 80.9], [180.6, 72.7], [184.4, 68.0], [175.5, 70.9],
-  [180.6, 72.5], [177.0, 72.5], [177.1, 83.4], [181.6, 75.5], [176.5, 73.0],
-  [175.0, 70.2], [174.0, 73.4], [165.1, 70.5], [177.0, 68.9], [192.0, 102.3],
-  [176.5, 68.4], [169.4, 65.9], [182.1, 75.7], [179.8, 84.5], [175.3, 87.7],
-  [184.9, 86.4], [177.3, 73.2], [167.4, 53.9], [178.1, 72.0], [168.9, 55.5],
-  [157.2, 58.4], [180.3, 83.2], [170.2, 72.7], [177.8, 64.1], [172.7, 72.3],
-  [165.1, 65.0], [186.7, 86.4], [165.1, 65.0], [174.0, 88.6], [175.3, 84.1],
-  [185.4, 66.8], [177.8, 75.5], [180.3, 93.2], [180.3, 82.7], [177.8, 58.0],
-  [177.8, 79.5], [177.8, 78.6], [177.8, 71.8], [177.8, 116.4], [163.8, 72.2],
-  [188.0, 83.6], [198.1, 85.5], [175.3, 90.9], [166.4, 85.9], [190.5, 89.1],
-  [166.4, 75.0], [177.8, 77.7], [179.7, 86.4], [172.7, 90.9], [190.5, 73.6],
-  [185.4, 76.4], [168.9, 69.1], [167.6, 84.5], [175.3, 64.5], [170.2, 69.1],
-  [190.5, 108.6], [177.8, 86.4], [190.5, 80.9], [177.8, 87.7], [184.2, 94.5],
-  [176.5, 80.2], [177.8, 72.0], [180.3, 71.4], [171.4, 72.7], [172.7, 84.1],
-  [172.7, 76.8], [177.8, 63.6], [177.8, 80.9], [182.9, 80.9], [170.2, 85.5],
-  [167.6, 68.6], [175.3, 67.7], [165.1, 66.4], [185.4, 102.3], [181.6, 70.5],
-  [172.7, 95.9], [190.5, 84.1], [179.1, 87.3], [175.3, 71.8], [170.2, 65.9],
-  [193.0, 95.9], [171.4, 91.4], [177.8, 81.8], [177.8, 96.8], [167.6, 69.1],
-  [167.6, 82.7], [180.3, 75.5], [182.9, 79.5], [176.5, 73.6], [186.7, 91.8],
-  [188.0, 84.1], [188.0, 85.9], [177.8, 81.8], [174.0, 82.5], [177.8, 80.5],
-  [171.4, 70.0], [185.4, 81.8], [185.4, 84.1], [188.0, 90.5], [188.0, 91.4],
-  [182.9, 89.1], [176.5, 85.0], [175.3, 69.1], [175.3, 73.6], [188.0, 80.5],
-  [188.0, 82.7], [175.3, 86.4], [170.5, 67.7], [179.1, 92.7], [177.8, 93.6],
-  [175.3, 70.9], [182.9, 75.0], [170.8, 93.2], [188.0, 93.2], [180.3, 77.7],
-  [177.8, 61.4], [185.4, 94.1], [168.9, 75.0], [185.4, 83.6], [180.3, 85.5],
-  [174.0, 73.9], [167.6, 66.8], [182.9, 87.3], [160.0, 72.3], [180.3, 88.6],
-  [167.6, 75.5], [186.7, 101.4], [175.3, 91.1], [175.3, 67.3], [175.9, 77.7],
-  [175.3, 81.8], [179.1, 75.5], [181.6, 84.5], [177.8, 76.6], [182.9, 85.0],
-  [177.8, 102.5], [184.2, 77.3], [179.1, 71.8], [176.5, 87.9], [188.0, 94.3],
-  [174.0, 70.9], [167.6, 64.5], [170.2, 77.3], [167.6, 72.3], [188.0, 87.3],
-  [174.0, 80.0], [176.5, 82.3], [180.3, 73.6], [167.6, 74.1], [188.0, 85.9],
-  [180.3, 73.2], [167.6, 76.3], [183.0, 65.9], [183.0, 90.9], [179.1, 89.1],
-  [170.2, 62.3], [177.8, 82.7], [179.1, 79.1], [190.5, 98.2], [177.8, 84.1],
-  [180.3, 83.2], [180.3, 83.2]
-]
-
-export function calculateAverage (length: number) {
-  return length
-}
-
-export const scatterOption = {
-  xAxis: {
-    scale: true
-  },
-  yAxis: {
-    scale: true
-  },
-  series: [
-    {
-      type: 'scatter',
-      id: 'female',
-      dataGroupId: 'female',
-      universalTransition: {
-        enabled: true,
-        delay: function (idx: string, count: string) {
-          return Math.random() * 400
-        }
-      },
-      data: femaleData
-    },
-    {
-      type: 'scatter',
-      id: 'male',
-      dataGroupId: 'male',
-      universalTransition: {
-        enabled: true,
-        delay: function (idx: string, count: string) {
-          return Math.random() * 400
-        }
-      },
-      data: maleDeta
-    }
-  ]
-}
-
-export const barOption = {
-  xAxis: {
-    type: 'category',
-    data: ['上线', '下线']
-  },
-  yAxis: {},
-  series: [
-    {
-      type: 'bar',
-      id: 'total',
-      data: [
-        {
-          value: 0,
-          groupId: 'male'
-        },
-        {
-          value: 0,
-          groupId: 'female'
-        }
-      ],
-      universalTransition: {
-        enabled: true,
-        seriesKey: ['female', 'male'],
-        delay: function (idx, count) {
-          return Math.random() * 400
-        }
-      }
-    }
-  ]
-}
-
-export const attrEchartsJson = {
-  title: {
-    text: 'Stacked Line'
-  },
-  xAxis: {
-    type: 'category',
-    data: []
-  },
-  yAxis: {
-    type: 'value'
-  },
-  series: [
-    {
-      data: [150, 230, 224, 218, 135, 147, 260],
-      type: 'line'
-    }
-  ]
-}
+export const sessionEchartsJson = {
+  title: {
+    text: ''
+  },
+  tooltip: {
+    trigger: 'axis',
+    formatter: function (params, ticket, callback) {
+      console.log('params:', params)
+
+      // return params.name.split(' ')[1]
+      return ''
+    }
+  },
+  legend: {
+  },
+  grid: {
+    left: '3%',
+    right: '4%',
+    bottom: '3%',
+    containLabel: true
+  },
+  toolbox: {
+    feature: {
+      // saveAsImage: {}
+    }
+  },
+  xAxis: {
+    type: 'category',
+    boundaryGap: false,
+    data: []
+  },
+  yAxis: {
+    type: 'category',
+    data: ['上线', '下线']
+  },
+  series: [
+    {
+      name: 'offlineNum',
+      type: 'line',
+      stack: 'Total',
+      data: [],
+      timeStamp: 7788
+    },
+    {
+      name: 'onlineNum',
+      type: 'line',
+      stack: 'Total',
+      data: [],
+      timeStamp: 7788
+    }
+  ]
+}
+
+// prettier-ignore
+const femaleData = [[161.2, 51.6], [167.5, 59.0], [159.5, 49.2], [157.0, 63.0], [155.8, 53.6],
+  [170.0, 59.0], [159.1, 47.6], [166.0, 69.8], [176.2, 66.8], [160.2, 75.2],
+  [172.5, 55.2], [170.9, 54.2], [172.9, 62.5], [153.4, 42.0], [160.0, 50.0],
+  [147.2, 49.8], [168.2, 49.2], [175.0, 73.2], [157.0, 47.8], [167.6, 68.8],
+  [159.5, 50.6], [175.0, 82.5], [166.8, 57.2], [176.5, 87.8], [170.2, 72.8],
+  [174.0, 54.5], [173.0, 59.8], [179.9, 67.3], [170.5, 67.8], [160.0, 47.0],
+  [154.4, 46.2], [162.0, 55.0], [176.5, 83.0], [160.0, 54.4], [152.0, 45.8],
+  [162.1, 53.6], [170.0, 73.2], [160.2, 52.1], [161.3, 67.9], [166.4, 56.6],
+  [168.9, 62.3], [163.8, 58.5], [167.6, 54.5], [160.0, 50.2], [161.3, 60.3],
+  [167.6, 58.3], [165.1, 56.2], [160.0, 50.2], [170.0, 72.9], [157.5, 59.8],
+  [167.6, 61.0], [160.7, 69.1], [163.2, 55.9], [152.4, 46.5], [157.5, 54.3],
+  [168.3, 54.8], [180.3, 60.7], [165.5, 60.0], [165.0, 62.0], [164.5, 60.3],
+  [156.0, 52.7], [160.0, 74.3], [163.0, 62.0], [165.7, 73.1], [161.0, 80.0],
+  [162.0, 54.7], [166.0, 53.2], [174.0, 75.7], [172.7, 61.1], [167.6, 55.7],
+  [151.1, 48.7], [164.5, 52.3], [163.5, 50.0], [152.0, 59.3], [169.0, 62.5],
+  [164.0, 55.7], [161.2, 54.8], [155.0, 45.9], [170.0, 70.6], [176.2, 67.2],
+  [170.0, 69.4], [162.5, 58.2], [170.3, 64.8], [164.1, 71.6], [169.5, 52.8],
+  [163.2, 59.8], [154.5, 49.0], [159.8, 50.0], [173.2, 69.2], [170.0, 55.9],
+  [161.4, 63.4], [169.0, 58.2], [166.2, 58.6], [159.4, 45.7], [162.5, 52.2],
+  [159.0, 48.6], [162.8, 57.8], [159.0, 55.6], [179.8, 66.8], [162.9, 59.4],
+  [161.0, 53.6], [151.1, 73.2], [168.2, 53.4], [168.9, 69.0], [173.2, 58.4],
+  [171.8, 56.2], [178.0, 70.6], [164.3, 59.8], [163.0, 72.0], [168.5, 65.2],
+  [166.8, 56.6], [172.7, 105.2], [163.5, 51.8], [169.4, 63.4], [167.8, 59.0],
+  [159.5, 47.6], [167.6, 63.0], [161.2, 55.2], [160.0, 45.0], [163.2, 54.0],
+  [162.2, 50.2], [161.3, 60.2], [149.5, 44.8], [157.5, 58.8], [163.2, 56.4],
+  [172.7, 62.0], [155.0, 49.2], [156.5, 67.2], [164.0, 53.8], [160.9, 54.4],
+  [162.8, 58.0], [167.0, 59.8], [160.0, 54.8], [160.0, 43.2], [168.9, 60.5],
+  [158.2, 46.4], [156.0, 64.4], [160.0, 48.8], [167.1, 62.2], [158.0, 55.5],
+  [167.6, 57.8], [156.0, 54.6], [162.1, 59.2], [173.4, 52.7], [159.8, 53.2],
+  [170.5, 64.5], [159.2, 51.8], [157.5, 56.0], [161.3, 63.6], [162.6, 63.2],
+  [160.0, 59.5], [168.9, 56.8], [165.1, 64.1], [162.6, 50.0], [165.1, 72.3],
+  [166.4, 55.0], [160.0, 55.9], [152.4, 60.4], [170.2, 69.1], [162.6, 84.5],
+  [170.2, 55.9], [158.8, 55.5], [172.7, 69.5], [167.6, 76.4], [162.6, 61.4],
+  [167.6, 65.9], [156.2, 58.6], [175.2, 66.8], [172.1, 56.6], [162.6, 58.6],
+  [160.0, 55.9], [165.1, 59.1], [182.9, 81.8], [166.4, 70.7], [165.1, 56.8],
+  [177.8, 60.0], [165.1, 58.2], [175.3, 72.7], [154.9, 54.1], [158.8, 49.1],
+  [172.7, 75.9], [168.9, 55.0], [161.3, 57.3], [167.6, 55.0], [165.1, 65.5],
+  [175.3, 65.5], [157.5, 48.6], [163.8, 58.6], [167.6, 63.6], [165.1, 55.2],
+  [165.1, 62.7], [168.9, 56.6], [162.6, 53.9], [164.5, 63.2], [176.5, 73.6],
+  [168.9, 62.0], [175.3, 63.6], [159.4, 53.2], [160.0, 53.4], [170.2, 55.0],
+  [162.6, 70.5], [167.6, 54.5], [162.6, 54.5], [160.7, 55.9], [160.0, 59.0],
+  [157.5, 63.6], [162.6, 54.5], [152.4, 47.3], [170.2, 67.7], [165.1, 80.9],
+  [172.7, 70.5], [165.1, 60.9], [170.2, 63.6], [170.2, 54.5], [170.2, 59.1],
+  [161.3, 70.5], [167.6, 52.7], [167.6, 62.7], [165.1, 86.3], [162.6, 66.4],
+  [152.4, 67.3], [168.9, 63.0], [170.2, 73.6], [175.2, 62.3], [175.2, 57.7],
+  [160.0, 55.4], [165.1, 104.1], [174.0, 55.5], [170.2, 77.3], [160.0, 80.5],
+  [167.6, 64.5], [167.6, 72.3], [167.6, 61.4], [154.9, 58.2], [162.6, 81.8],
+  [175.3, 63.6], [171.4, 53.4], [157.5, 54.5], [165.1, 53.6], [160.0, 60.0],
+  [174.0, 73.6], [162.6, 61.4], [174.0, 55.5], [162.6, 63.6], [161.3, 60.9],
+  [156.2, 60.0], [149.9, 46.8], [169.5, 57.3], [160.0, 64.1], [175.3, 63.6],
+  [169.5, 67.3], [160.0, 75.5], [172.7, 68.2], [162.6, 61.4], [157.5, 76.8],
+  [176.5, 71.8], [164.4, 55.5], [160.7, 48.6], [174.0, 66.4], [163.8, 67.3]
+]
+// prettier-ignore
+const maleDeta = [[174.0, 65.6], [175.3, 71.8], [193.5, 80.7], [186.5, 72.6], [187.2, 78.8],
+  [181.5, 74.8], [184.0, 86.4], [184.5, 78.4], [175.0, 62.0], [184.0, 81.6],
+  [180.0, 76.6], [177.8, 83.6], [192.0, 90.0], [176.0, 74.6], [174.0, 71.0],
+  [184.0, 79.6], [192.7, 93.8], [171.5, 70.0], [173.0, 72.4], [176.0, 85.9],
+  [176.0, 78.8], [180.5, 77.8], [172.7, 66.2], [176.0, 86.4], [173.5, 81.8],
+  [178.0, 89.6], [180.3, 82.8], [180.3, 76.4], [164.5, 63.2], [173.0, 60.9],
+  [183.5, 74.8], [175.5, 70.0], [188.0, 72.4], [189.2, 84.1], [172.8, 69.1],
+  [170.0, 59.5], [182.0, 67.2], [170.0, 61.3], [177.8, 68.6], [184.2, 80.1],
+  [186.7, 87.8], [171.4, 84.7], [172.7, 73.4], [175.3, 72.1], [180.3, 82.6],
+  [182.9, 88.7], [188.0, 84.1], [177.2, 94.1], [172.1, 74.9], [167.0, 59.1],
+  [169.5, 75.6], [174.0, 86.2], [172.7, 75.3], [182.2, 87.1], [164.1, 55.2],
+  [163.0, 57.0], [171.5, 61.4], [184.2, 76.8], [174.0, 86.8], [174.0, 72.2],
+  [177.0, 71.6], [186.0, 84.8], [167.0, 68.2], [171.8, 66.1], [182.0, 72.0],
+  [167.0, 64.6], [177.8, 74.8], [164.5, 70.0], [192.0, 101.6], [175.5, 63.2],
+  [171.2, 79.1], [181.6, 78.9], [167.4, 67.7], [181.1, 66.0], [177.0, 68.2],
+  [174.5, 63.9], [177.5, 72.0], [170.5, 56.8], [182.4, 74.5], [197.1, 90.9],
+  [180.1, 93.0], [175.5, 80.9], [180.6, 72.7], [184.4, 68.0], [175.5, 70.9],
+  [180.6, 72.5], [177.0, 72.5], [177.1, 83.4], [181.6, 75.5], [176.5, 73.0],
+  [175.0, 70.2], [174.0, 73.4], [165.1, 70.5], [177.0, 68.9], [192.0, 102.3],
+  [176.5, 68.4], [169.4, 65.9], [182.1, 75.7], [179.8, 84.5], [175.3, 87.7],
+  [184.9, 86.4], [177.3, 73.2], [167.4, 53.9], [178.1, 72.0], [168.9, 55.5],
+  [157.2, 58.4], [180.3, 83.2], [170.2, 72.7], [177.8, 64.1], [172.7, 72.3],
+  [165.1, 65.0], [186.7, 86.4], [165.1, 65.0], [174.0, 88.6], [175.3, 84.1],
+  [185.4, 66.8], [177.8, 75.5], [180.3, 93.2], [180.3, 82.7], [177.8, 58.0],
+  [177.8, 79.5], [177.8, 78.6], [177.8, 71.8], [177.8, 116.4], [163.8, 72.2],
+  [188.0, 83.6], [198.1, 85.5], [175.3, 90.9], [166.4, 85.9], [190.5, 89.1],
+  [166.4, 75.0], [177.8, 77.7], [179.7, 86.4], [172.7, 90.9], [190.5, 73.6],
+  [185.4, 76.4], [168.9, 69.1], [167.6, 84.5], [175.3, 64.5], [170.2, 69.1],
+  [190.5, 108.6], [177.8, 86.4], [190.5, 80.9], [177.8, 87.7], [184.2, 94.5],
+  [176.5, 80.2], [177.8, 72.0], [180.3, 71.4], [171.4, 72.7], [172.7, 84.1],
+  [172.7, 76.8], [177.8, 63.6], [177.8, 80.9], [182.9, 80.9], [170.2, 85.5],
+  [167.6, 68.6], [175.3, 67.7], [165.1, 66.4], [185.4, 102.3], [181.6, 70.5],
+  [172.7, 95.9], [190.5, 84.1], [179.1, 87.3], [175.3, 71.8], [170.2, 65.9],
+  [193.0, 95.9], [171.4, 91.4], [177.8, 81.8], [177.8, 96.8], [167.6, 69.1],
+  [167.6, 82.7], [180.3, 75.5], [182.9, 79.5], [176.5, 73.6], [186.7, 91.8],
+  [188.0, 84.1], [188.0, 85.9], [177.8, 81.8], [174.0, 82.5], [177.8, 80.5],
+  [171.4, 70.0], [185.4, 81.8], [185.4, 84.1], [188.0, 90.5], [188.0, 91.4],
+  [182.9, 89.1], [176.5, 85.0], [175.3, 69.1], [175.3, 73.6], [188.0, 80.5],
+  [188.0, 82.7], [175.3, 86.4], [170.5, 67.7], [179.1, 92.7], [177.8, 93.6],
+  [175.3, 70.9], [182.9, 75.0], [170.8, 93.2], [188.0, 93.2], [180.3, 77.7],
+  [177.8, 61.4], [185.4, 94.1], [168.9, 75.0], [185.4, 83.6], [180.3, 85.5],
+  [174.0, 73.9], [167.6, 66.8], [182.9, 87.3], [160.0, 72.3], [180.3, 88.6],
+  [167.6, 75.5], [186.7, 101.4], [175.3, 91.1], [175.3, 67.3], [175.9, 77.7],
+  [175.3, 81.8], [179.1, 75.5], [181.6, 84.5], [177.8, 76.6], [182.9, 85.0],
+  [177.8, 102.5], [184.2, 77.3], [179.1, 71.8], [176.5, 87.9], [188.0, 94.3],
+  [174.0, 70.9], [167.6, 64.5], [170.2, 77.3], [167.6, 72.3], [188.0, 87.3],
+  [174.0, 80.0], [176.5, 82.3], [180.3, 73.6], [167.6, 74.1], [188.0, 85.9],
+  [180.3, 73.2], [167.6, 76.3], [183.0, 65.9], [183.0, 90.9], [179.1, 89.1],
+  [170.2, 62.3], [177.8, 82.7], [179.1, 79.1], [190.5, 98.2], [177.8, 84.1],
+  [180.3, 83.2], [180.3, 83.2]
+]
+
+export function calculateAverage (length: number) {
+  return length
+}
+
+export const scatterOption = {
+  xAxis: {
+    scale: true
+  },
+  yAxis: {
+    scale: true
+  },
+  series: [
+    {
+      type: 'scatter',
+      id: 'female',
+      dataGroupId: 'female',
+      universalTransition: {
+        enabled: true,
+        delay: function (idx: string, count: string) {
+          return Math.random() * 400
+        }
+      },
+      data: femaleData
+    },
+    {
+      type: 'scatter',
+      id: 'male',
+      dataGroupId: 'male',
+      universalTransition: {
+        enabled: true,
+        delay: function (idx: string, count: string) {
+          return Math.random() * 400
+        }
+      },
+      data: maleDeta
+    }
+  ]
+}
+
+export const barOption = {
+  xAxis: {
+    type: 'category',
+    data: ['上线', '下线']
+  },
+  yAxis: {},
+  series: [
+    {
+      type: 'bar',
+      id: 'total',
+      data: [
+        {
+          value: 0,
+          groupId: 'male'
+        },
+        {
+          value: 0,
+          groupId: 'female'
+        }
+      ],
+      universalTransition: {
+        enabled: true,
+        seriesKey: ['female', 'male'],
+        delay: function (idx, count) {
+          return Math.random() * 400
+        }
+      }
+    }
+  ]
+}
+
+export const attrEchartsJson = {
+  title: {
+    text: 'Stacked Line'
+  },
+  xAxis: {
+    type: 'category',
+    data: []
+  },
+  yAxis: {
+    type: 'value'
+  },
+  series: [
+    {
+      data: [150, 230, 224, 218, 135, 147, 260],
+      type: 'line'
+    }
+  ]
+}