nayota-show-sdk 1.3.94 → 1.3.95

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,138 +1,4 @@
1
1
  import requestAlarm from '../utils/alarm-request'
2
- import { isV2 } from '../utils/version'
3
- import { getOne as getDeviceClassOne } from './deviceClass'
4
-
5
- function getLegacyRefId(value) {
6
- if (value == null) return ''
7
-
8
- if (typeof value === 'string' || typeof value === 'number') {
9
- return String(value)
10
- }
11
-
12
- if (typeof value === 'object') {
13
- if (value._id != null) return String(value._id)
14
- if (value.id != null) return String(value.id)
15
- }
16
-
17
- return ''
18
- }
19
-
20
- function getLegacyRefName(value) {
21
- if (!value || typeof value !== 'object') return ''
22
- return value.name || value.deviceClassName || value.typeName || value.label || ''
23
- }
24
-
25
- function normalizeLegacyDeviceClass(value, fallbackId = '') {
26
- if (!value || typeof value !== 'object') return value
27
-
28
- const id = getLegacyRefId(value) || fallbackId
29
- return {
30
- ...value,
31
- _id: value._id || id || undefined,
32
- id: value.id || id || undefined,
33
- name: getLegacyRefName(value) || undefined
34
- }
35
- }
36
-
37
- function getAlarmRows(response) {
38
- if (Array.isArray(response?.data?.rows)) return response.data.rows
39
- if (Array.isArray(response?.rows)) return response.rows
40
- return []
41
- }
42
-
43
- function withAlarmRows(response, rows) {
44
- if (Array.isArray(response?.data?.rows)) {
45
- return {
46
- ...response,
47
- data: {
48
- ...response.data,
49
- rows
50
- }
51
- }
52
- }
53
-
54
- if (Array.isArray(response?.rows)) {
55
- return {
56
- ...response,
57
- rows
58
- }
59
- }
60
-
61
- return response
62
- }
63
-
64
- async function loadDeviceClassMap(ids = []) {
65
- const uniqueIds = [...new Set(ids.filter(Boolean))]
66
- const entries = await Promise.all(uniqueIds.map(async id => {
67
- try {
68
- const response = await getDeviceClassOne(id)
69
- const item = response?.data
70
- const normalized = normalizeLegacyDeviceClass(item, id)
71
- return [id, normalized && getLegacyRefName(normalized) ? normalized : null]
72
- } catch (error) {
73
- return [id, null]
74
- }
75
- }))
76
-
77
- return new Map(entries.filter(([, item]) => item))
78
- }
79
-
80
- async function normalizeV2AlarmRecordListResponse(response) {
81
- if (!isV2()) return response
82
-
83
- const rows = getAlarmRows(response)
84
- if (!rows.length) return response
85
-
86
- const rowsWithLocalDeviceClass = rows.map(row => {
87
- const deviceClass = row?.deviceClass
88
- const deviceDeviceClass = row?.device?.deviceClass
89
-
90
- if (getLegacyRefName(deviceClass)) {
91
- return {
92
- ...row,
93
- deviceClass: normalizeLegacyDeviceClass(deviceClass)
94
- }
95
- }
96
-
97
- if (getLegacyRefName(deviceDeviceClass)) {
98
- return {
99
- ...row,
100
- deviceClass: normalizeLegacyDeviceClass(
101
- deviceDeviceClass,
102
- getLegacyRefId(deviceClass)
103
- )
104
- }
105
- }
106
-
107
- return row
108
- })
109
-
110
- const missingIds = rowsWithLocalDeviceClass
111
- .filter(row => row?.deviceClass && !getLegacyRefName(row.deviceClass))
112
- .map(row => getLegacyRefId(row.deviceClass))
113
-
114
- if (!missingIds.length) {
115
- return withAlarmRows(response, rowsWithLocalDeviceClass)
116
- }
117
-
118
- const deviceClassMap = await loadDeviceClassMap(missingIds)
119
- if (!deviceClassMap.size) {
120
- return withAlarmRows(response, rowsWithLocalDeviceClass)
121
- }
122
-
123
- return withAlarmRows(response, rowsWithLocalDeviceClass.map(row => {
124
- if (!row?.deviceClass || getLegacyRefName(row.deviceClass)) return row
125
-
126
- const id = getLegacyRefId(row.deviceClass)
127
- const deviceClass = deviceClassMap.get(id)
128
- if (!deviceClass) return row
129
-
130
- return {
131
- ...row,
132
- deviceClass
133
- }
134
- }))
135
- }
136
2
  /**
137
3
  * @file 报警记录api
138
4
  * @module 报警记录接口
@@ -458,7 +324,7 @@ export function list(query) {
458
324
  url: '/alarm-records',
459
325
  method: 'get',
460
326
  params: query
461
- }).then(normalizeV2AlarmRecordListResponse)
327
+ })
462
328
  }
463
329
 
464
330
  /**
@@ -0,0 +1,91 @@
1
+ import { requestShow } from '../utils'
2
+
3
+ const baseUrl = '/fire-drill-records'
4
+
5
+ /**
6
+ * 获取消防演练回放记录列表
7
+ * @param {Object} query - 查询参数
8
+ * @param {number} [query.page] - 页码
9
+ * @param {number} [query.limit] - 每页数量
10
+ * @param {string} [query.name] - 演练名称,模糊查询
11
+ * @param {string} [query.status] - 演练状态
12
+ * @param {string} [query.hierarchyID] - 主体层级/区域 ID
13
+ * @param {string} [query.hierarchyPathId] - 层级路径中的任意 ID
14
+ * @param {number} [query.startTimeFrom] - 开始时间范围起点,毫秒时间戳
15
+ * @param {number} [query.startTimeTo] - 开始时间范围终点,毫秒时间戳
16
+ */
17
+ export function list(query) {
18
+ return requestShow({
19
+ url: baseUrl,
20
+ method: 'get',
21
+ params: query
22
+ })
23
+ }
24
+
25
+ /**
26
+ * 新增消防演练回放记录
27
+ * @param {Object} data - 消防演练回放记录
28
+ */
29
+ export function create(data) {
30
+ return requestShow({
31
+ url: baseUrl,
32
+ method: 'post',
33
+ data
34
+ })
35
+ }
36
+
37
+ /**
38
+ * 获取消防演练回放记录详情
39
+ * @param {string} id - 记录 ID
40
+ */
41
+ export function getOne(id) {
42
+ return requestShow({
43
+ url: `${baseUrl}/${id}`,
44
+ method: 'get'
45
+ })
46
+ }
47
+
48
+ /**
49
+ * 修改消防演练回放记录
50
+ * @param {Object} data - 修改数据
51
+ * @param {string} data._id - 记录 ID
52
+ */
53
+ export function updateOne(data) {
54
+ return requestShow({
55
+ url: `${baseUrl}/${data._id}`,
56
+ method: 'put',
57
+ data
58
+ })
59
+ }
60
+
61
+ /**
62
+ * 删除消防演练回放记录
63
+ * @param {string} id - 记录 ID
64
+ */
65
+ export function deleteOne(id) {
66
+ return requestShow({
67
+ url: `${baseUrl}/${id}`,
68
+ method: 'delete'
69
+ })
70
+ }
71
+
72
+ /**
73
+ * 批量删除消防演练回放记录
74
+ * @param {Array<string>} ids - 记录 ID 数组
75
+ */
76
+ export function deleteMany(ids) {
77
+ return requestShow({
78
+ url: baseUrl,
79
+ method: 'delete',
80
+ data: ids
81
+ })
82
+ }
83
+
84
+ export default {
85
+ list,
86
+ create,
87
+ getOne,
88
+ updateOne,
89
+ deleteOne,
90
+ deleteMany
91
+ }
@@ -0,0 +1,75 @@
1
+ jest.mock('../utils', () => ({
2
+ requestShow: jest.fn()
3
+ }))
4
+
5
+ const { requestShow } = require('../utils')
6
+ const fireDrillRecords = require('./fireDrillRecords').default
7
+ const sdk = require('../index').default
8
+
9
+ describe('fireDrillRecords api', () => {
10
+ afterEach(() => {
11
+ jest.clearAllMocks()
12
+ })
13
+
14
+ test('lists fire drill records from show backend', () => {
15
+ const query = {
16
+ page: 1,
17
+ limit: 20,
18
+ status: 'finished',
19
+ hierarchyID: 'depart_102030',
20
+ hierarchyPathId: 'root_depart',
21
+ startTimeFrom: 1779253200000,
22
+ startTimeTo: 1779254100000
23
+ }
24
+
25
+ fireDrillRecords.list(query)
26
+
27
+ expect(requestShow).toHaveBeenCalledWith({
28
+ url: '/fire-drill-records',
29
+ method: 'get',
30
+ params: query
31
+ })
32
+ })
33
+
34
+ test('creates fire drill record', () => {
35
+ const data = {
36
+ name: '东区办公楼消防疏散演练',
37
+ status: 'running',
38
+ startTime: 1779253200000,
39
+ hierarchyID: 'depart_102030',
40
+ hierarchyPaths: ['root_depart', 'depart_102030'],
41
+ planSnapshot: {},
42
+ timelineEvents: [],
43
+ metricsSeries: [],
44
+ routeSnapshots: []
45
+ }
46
+
47
+ fireDrillRecords.create(data)
48
+
49
+ expect(requestShow).toHaveBeenCalledWith({
50
+ url: '/fire-drill-records',
51
+ method: 'post',
52
+ data
53
+ })
54
+ })
55
+
56
+ test('updates fire drill record by _id', () => {
57
+ const data = {
58
+ _id: '5e4bb8a8-8c4f-4ad4-a03d-4dfcefa18a57',
59
+ status: 'finished',
60
+ endTime: 1779254100000
61
+ }
62
+
63
+ fireDrillRecords.updateOne(data)
64
+
65
+ expect(requestShow).toHaveBeenCalledWith({
66
+ url: '/fire-drill-records/5e4bb8a8-8c4f-4ad4-a03d-4dfcefa18a57',
67
+ method: 'put',
68
+ data
69
+ })
70
+ })
71
+
72
+ test('exports module from sdk root', () => {
73
+ expect(sdk.fireDrillRecords).toBe(fireDrillRecords)
74
+ })
75
+ })
package/index.js CHANGED
@@ -40,6 +40,7 @@ import maintenanceRecord from "./api/maintenanceRecord";
40
40
  import sensorStatusConfig from "./api/sensorStatusConfig";
41
41
  import attendanceRecord from "./api/attendanceRecord";
42
42
  import workSchedule from "./api/workSchedule";
43
+ import fireDrillRecords from "./api/fireDrillRecords";
43
44
  const api = {
44
45
  alarmRecord,
45
46
  alarmProgress,
@@ -80,6 +81,7 @@ const api = {
80
81
  sensorStatusConfig,
81
82
  attendanceRecord,
82
83
  workSchedule,
84
+ fireDrillRecords,
83
85
  };
84
86
 
85
87
  export default {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nayota-show-sdk",
3
- "version": "1.3.94",
3
+ "version": "1.3.95",
4
4
  "description": "nayota-show-server rest-api",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -1,126 +0,0 @@
1
- jest.mock('../utils', () => ({
2
- requestShow: jest.fn(),
3
- requestIot: jest.fn(),
4
- requestForm: jest.fn()
5
- }))
6
-
7
- const urlcfg = require('../config/urlcfg').default
8
- const { requestIot, requestShow } = require('../utils')
9
- const { list } = require('./alarmRecord')
10
-
11
- describe('alarmRecord api compatibility', () => {
12
- const originalVersion = urlcfg.version
13
- const originalIotServer = urlcfg.iotServer
14
-
15
- afterEach(() => {
16
- urlcfg.version = originalVersion
17
- urlcfg.iotServer = originalIotServer
18
- jest.clearAllMocks()
19
- })
20
-
21
- test('keeps v1 list response unchanged', async () => {
22
- const response = {
23
- code: 0,
24
- data: {
25
- rows: [
26
- {
27
- _id: 'alarm-1',
28
- deviceClass: 'type-1'
29
- }
30
- ]
31
- }
32
- }
33
- urlcfg.version = 'v1'
34
- requestShow.mockResolvedValue(response)
35
-
36
- await expect(list({ limit: 1 })).resolves.toBe(response)
37
- expect(requestShow).toHaveBeenCalledWith({
38
- url: '/alarm-records',
39
- method: 'get',
40
- params: { limit: 1 }
41
- })
42
- expect(requestIot).not.toHaveBeenCalled()
43
- })
44
-
45
- test('fills v2 alarm deviceClass name from digital twin type detail', async () => {
46
- urlcfg.version = 'v2'
47
- urlcfg.iotServer = '/iot-api'
48
- requestIot.mockImplementation(config => {
49
- if (config.url === '/alarm-records') {
50
- return Promise.resolve({
51
- code: 0,
52
- data: {
53
- total: 1,
54
- rows: [
55
- {
56
- _id: 'alarm-1',
57
- device: { name: '安消智能摄像头' },
58
- deviceClass: 'type-1',
59
- subType: '事件告警'
60
- }
61
- ]
62
- }
63
- })
64
- }
65
-
66
- if (config.url === '/digital-twin-types/type-1') {
67
- return Promise.resolve({
68
- code: 0,
69
- data: {
70
- id: 'type-1',
71
- name: '安消智能摄像头',
72
- typeCode: 'CAMERA'
73
- }
74
- })
75
- }
76
-
77
- return Promise.reject(new Error(`unexpected request: ${config.url}`))
78
- })
79
-
80
- const response = await list({ limit: 1 })
81
-
82
- expect(response.data.rows[0].deviceClass).toMatchObject({
83
- _id: 'type-1',
84
- id: 'type-1',
85
- name: '安消智能摄像头',
86
- code: 'CAMERA'
87
- })
88
- expect(requestIot).toHaveBeenCalledWith({
89
- url: '/alarm-records',
90
- method: 'get',
91
- params: { limit: 1 }
92
- })
93
- expect(requestIot).toHaveBeenCalledWith({
94
- url: '/digital-twin-types/type-1',
95
- method: 'get'
96
- })
97
- })
98
-
99
- test('does not request device class detail when v2 row already has name', async () => {
100
- urlcfg.version = 'v2'
101
- urlcfg.iotServer = '/iot-api'
102
- requestIot.mockResolvedValue({
103
- code: 0,
104
- data: {
105
- rows: [
106
- {
107
- _id: 'alarm-1',
108
- deviceClass: {
109
- _id: 'type-1',
110
- name: '摄像头'
111
- }
112
- }
113
- ]
114
- }
115
- })
116
-
117
- const response = await list({ limit: 1 })
118
-
119
- expect(response.data.rows[0].deviceClass).toMatchObject({
120
- _id: 'type-1',
121
- id: 'type-1',
122
- name: '摄像头'
123
- })
124
- expect(requestIot).toHaveBeenCalledTimes(1)
125
- })
126
- })