@ray-js/lamp-schedule-core 1.0.0-beta-4 → 1.0.0
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.
- package/lib/conflict/ConflictResolver.js +7 -10
- package/lib/conflict/__test__/transform.test.js +55 -55
- package/lib/conflict/transform.js +41 -35
- package/lib/conflict/type.d.ts +1 -0
- package/lib/hooks/__test__/useCountdownDp.test.js +4 -4
- package/lib/hooks/__test__/useTimerReportDp.test.js +3 -3
- package/lib/utils/objectToId.d.ts +1 -0
- package/lib/utils/objectToId.js +33 -0
- package/package.json +1 -1
|
@@ -128,11 +128,12 @@ function convertToTimeRanges(schedules) {
|
|
|
128
128
|
const isCrossDay = endMinutes < startMinutes;
|
|
129
129
|
|
|
130
130
|
// 如果定时状态为关闭,则设置星期,忽略冲突判断
|
|
131
|
-
const dayOfWeek =
|
|
131
|
+
const dayOfWeek = daysOfWeek[isCrossDay ? (week + 1) % 7 : week];
|
|
132
132
|
return [{
|
|
133
133
|
id: schedule.id,
|
|
134
134
|
type: schedule.type,
|
|
135
135
|
dayOfWeek: dayOfWeek,
|
|
136
|
+
status: schedule.data.status,
|
|
136
137
|
startMinutes,
|
|
137
138
|
endMinutes,
|
|
138
139
|
originalSchedule: schedule,
|
|
@@ -157,17 +158,12 @@ function convertToTimeRanges(schedules) {
|
|
|
157
158
|
const start = parseTimeToMinutes(startTimeStr);
|
|
158
159
|
const end = parseTimeToMinutes(endTimeStr);
|
|
159
160
|
const isCrossDay = end < start;
|
|
160
|
-
|
|
161
|
-
// 如果定时状态为关闭,则设置星期,忽略冲突判断
|
|
162
|
-
if (!schedule.data.status) {
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
161
|
// 添加当前星期的时间范围
|
|
167
162
|
result.push({
|
|
168
163
|
id: schedule.id,
|
|
169
164
|
type: schedule.type,
|
|
170
165
|
dayOfWeek: day,
|
|
166
|
+
status: schedule.data.status,
|
|
171
167
|
startMinutes: start,
|
|
172
168
|
endMinutes: end,
|
|
173
169
|
originalSchedule: schedule,
|
|
@@ -186,6 +182,7 @@ function convertToTimeRanges(schedules) {
|
|
|
186
182
|
id: schedule.id,
|
|
187
183
|
type: schedule.type,
|
|
188
184
|
dayOfWeek: nextDay,
|
|
185
|
+
status: schedule.data.status,
|
|
189
186
|
startMinutes: 0,
|
|
190
187
|
// 从午夜开始
|
|
191
188
|
endMinutes: end,
|
|
@@ -263,11 +260,11 @@ export function checkConflicts(scheduleList, currentSchedule) {
|
|
|
263
260
|
const currentPreId = current === null || current === void 0 || (_current$originalSche = current.originalSchedule) === null || _current$originalSche === void 0 ? void 0 : _current$originalSche.prevId;
|
|
264
261
|
const currentId = current === null || current === void 0 || (_current$originalSche2 = current.originalSchedule) === null || _current$originalSche2 === void 0 ? void 0 : _current$originalSche2.id;
|
|
265
262
|
const otherId = other.id;
|
|
266
|
-
// 如果当前定时自身修改 且 与自身冲突 则忽略
|
|
267
|
-
if (currentPreId && currentId ===
|
|
263
|
+
// 如果当前定时自身修改 且 与自身冲突 并且其他定时不等于当前定时id 则忽略
|
|
264
|
+
if (currentPreId && currentId === currentPreId && otherId !== currentId) {
|
|
268
265
|
return;
|
|
269
266
|
}
|
|
270
|
-
if (current.dayOfWeek && current.dayOfWeek === other.dayOfWeek && rule.isConflict(current, other)) {
|
|
267
|
+
if (current.dayOfWeek && current.status && other.status && current.dayOfWeek === other.dayOfWeek && rule.isConflict(current, other)) {
|
|
271
268
|
conflicts.push({
|
|
272
269
|
current: current.originalSchedule,
|
|
273
270
|
other: other.originalSchedule
|
|
@@ -43,16 +43,14 @@ describe('transform', () => {
|
|
|
43
43
|
aliasName: 'aliasName',
|
|
44
44
|
isAppPush: false
|
|
45
45
|
});
|
|
46
|
-
expect(result).
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
startTime: '10:00',
|
|
53
|
-
endTime: '10:00'
|
|
54
|
-
}
|
|
46
|
+
expect(result.type).toBe(EScheduleFunctionType.TIMER);
|
|
47
|
+
expect(result.data).toEqual({
|
|
48
|
+
status: true,
|
|
49
|
+
weeks: [1, 0, 0, 0, 0, 0, 0],
|
|
50
|
+
startTime: '10:00',
|
|
51
|
+
endTime: '10:00'
|
|
55
52
|
});
|
|
53
|
+
expect(result.id).toMatch(/^timer_/);
|
|
56
54
|
});
|
|
57
55
|
it('应该处理缺少状态的定时数据', () => {
|
|
58
56
|
const result = timerDataToSchedule({
|
|
@@ -86,8 +84,10 @@ describe('transform', () => {
|
|
|
86
84
|
isAppPush: false
|
|
87
85
|
}]);
|
|
88
86
|
expect(result.length).toBe(2);
|
|
89
|
-
expect(result[0].
|
|
90
|
-
expect(result[1].
|
|
87
|
+
expect(result[0].type).toBe(EScheduleFunctionType.TIMER);
|
|
88
|
+
expect(result[1].type).toBe(EScheduleFunctionType.TIMER);
|
|
89
|
+
expect(result[0].id).toMatch(/^timer_/);
|
|
90
|
+
expect(result[1].id).toMatch(/^timer_/);
|
|
91
91
|
});
|
|
92
92
|
});
|
|
93
93
|
describe('wakeUpNodeToSchedule', () => {
|
|
@@ -106,16 +106,14 @@ describe('transform', () => {
|
|
|
106
106
|
temperature: 1000,
|
|
107
107
|
index: 1
|
|
108
108
|
});
|
|
109
|
-
expect(result).
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
startTime: '8:20',
|
|
116
|
-
endTime: '8:45'
|
|
117
|
-
}
|
|
109
|
+
expect(result.type).toBe(EScheduleFunctionType.WAKEUP);
|
|
110
|
+
expect(result.data).toEqual({
|
|
111
|
+
status: true,
|
|
112
|
+
weeks: [1, 0, 0, 0, 0, 0, 0],
|
|
113
|
+
startTime: '8:20',
|
|
114
|
+
endTime: '8:45'
|
|
118
115
|
});
|
|
116
|
+
expect(result.id).toMatch(/^wakeup_/);
|
|
119
117
|
});
|
|
120
118
|
});
|
|
121
119
|
describe('wakeUpDataToScheduleList', () => {
|
|
@@ -148,8 +146,10 @@ describe('transform', () => {
|
|
|
148
146
|
index: 2
|
|
149
147
|
}]);
|
|
150
148
|
expect(result.length).toBe(2);
|
|
151
|
-
expect(result[0].
|
|
152
|
-
expect(result[1].
|
|
149
|
+
expect(result[0].type).toBe(EScheduleFunctionType.WAKEUP);
|
|
150
|
+
expect(result[1].type).toBe(EScheduleFunctionType.WAKEUP);
|
|
151
|
+
expect(result[0].id).toMatch(/^wakeup_/);
|
|
152
|
+
expect(result[1].id).toMatch(/^wakeup_/);
|
|
153
153
|
});
|
|
154
154
|
});
|
|
155
155
|
describe('sleepNodeToSchedule', () => {
|
|
@@ -168,16 +168,14 @@ describe('transform', () => {
|
|
|
168
168
|
temperature: 1000,
|
|
169
169
|
index: 2
|
|
170
170
|
});
|
|
171
|
-
expect(result).
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
startTime: '22:10',
|
|
178
|
-
endTime: '22:30'
|
|
179
|
-
}
|
|
171
|
+
expect(result.type).toBe(EScheduleFunctionType.SLEEP);
|
|
172
|
+
expect(result.data).toEqual({
|
|
173
|
+
status: true,
|
|
174
|
+
weeks: [1, 0, 0, 0, 0, 0, 0],
|
|
175
|
+
startTime: '22:10',
|
|
176
|
+
endTime: '22:30'
|
|
180
177
|
});
|
|
178
|
+
expect(result.id).toMatch(/^sleep_/);
|
|
181
179
|
});
|
|
182
180
|
});
|
|
183
181
|
describe('sleepDataToScheduleList', () => {
|
|
@@ -210,8 +208,10 @@ describe('transform', () => {
|
|
|
210
208
|
index: 2
|
|
211
209
|
}]);
|
|
212
210
|
expect(result.length).toBe(2);
|
|
213
|
-
expect(result[0].
|
|
214
|
-
expect(result[1].
|
|
211
|
+
expect(result[0].type).toBe(EScheduleFunctionType.SLEEP);
|
|
212
|
+
expect(result[1].type).toBe(EScheduleFunctionType.SLEEP);
|
|
213
|
+
expect(result[0].id).toMatch(/^sleep_/);
|
|
214
|
+
expect(result[1].id).toMatch(/^sleep_/);
|
|
215
215
|
});
|
|
216
216
|
});
|
|
217
217
|
describe('countdownToSchedule', () => {
|
|
@@ -278,16 +278,14 @@ describe('transform', () => {
|
|
|
278
278
|
temperature: 1000
|
|
279
279
|
}
|
|
280
280
|
});
|
|
281
|
-
expect(result).
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
startTime: '10:00',
|
|
288
|
-
endTime: '12:00'
|
|
289
|
-
}
|
|
281
|
+
expect(result.type).toBe(EScheduleFunctionType.RANDOM);
|
|
282
|
+
expect(result.data).toEqual({
|
|
283
|
+
status: true,
|
|
284
|
+
weeks: [1, 0, 0, 0, 0, 0, 0],
|
|
285
|
+
startTime: '10:00',
|
|
286
|
+
endTime: '12:00'
|
|
290
287
|
});
|
|
288
|
+
expect(result.id).toMatch(/^random_/);
|
|
291
289
|
});
|
|
292
290
|
});
|
|
293
291
|
describe('randomDataToScheduleList', () => {
|
|
@@ -326,8 +324,10 @@ describe('transform', () => {
|
|
|
326
324
|
}
|
|
327
325
|
}]);
|
|
328
326
|
expect(result.length).toBe(2);
|
|
329
|
-
expect(result[0].
|
|
330
|
-
expect(result[1].
|
|
327
|
+
expect(result[0].type).toBe(EScheduleFunctionType.RANDOM);
|
|
328
|
+
expect(result[1].type).toBe(EScheduleFunctionType.RANDOM);
|
|
329
|
+
expect(result[0].id).toMatch(/^random_/);
|
|
330
|
+
expect(result[1].id).toMatch(/^random_/);
|
|
331
331
|
});
|
|
332
332
|
});
|
|
333
333
|
describe('cycleNodeToSchedule', () => {
|
|
@@ -351,16 +351,14 @@ describe('transform', () => {
|
|
|
351
351
|
temperature: 1000
|
|
352
352
|
}
|
|
353
353
|
});
|
|
354
|
-
expect(result).
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
startTime: '10:00',
|
|
361
|
-
endTime: '12:00'
|
|
362
|
-
}
|
|
354
|
+
expect(result.type).toBe(EScheduleFunctionType.CYCLE);
|
|
355
|
+
expect(result.data).toEqual({
|
|
356
|
+
status: true,
|
|
357
|
+
weeks: [1, 0, 0, 0, 0, 0, 0],
|
|
358
|
+
startTime: '10:00',
|
|
359
|
+
endTime: '12:00'
|
|
363
360
|
});
|
|
361
|
+
expect(result.id).toMatch(/^cycle_/);
|
|
364
362
|
});
|
|
365
363
|
});
|
|
366
364
|
describe('cycleDataToScheduleList', () => {
|
|
@@ -403,8 +401,10 @@ describe('transform', () => {
|
|
|
403
401
|
}
|
|
404
402
|
}]);
|
|
405
403
|
expect(result.length).toBe(2);
|
|
406
|
-
expect(result[0].
|
|
407
|
-
expect(result[1].
|
|
404
|
+
expect(result[0].type).toBe(EScheduleFunctionType.CYCLE);
|
|
405
|
+
expect(result[1].type).toBe(EScheduleFunctionType.CYCLE);
|
|
406
|
+
expect(result[0].id).toMatch(/^cycle_/);
|
|
407
|
+
expect(result[1].id).toMatch(/^cycle_/);
|
|
408
408
|
});
|
|
409
409
|
});
|
|
410
410
|
describe('transScheduleListToConflictList', () => {
|
|
@@ -2,6 +2,7 @@ import "core-js/modules/esnext.iterator.constructor.js";
|
|
|
2
2
|
import "core-js/modules/esnext.iterator.for-each.js";
|
|
3
3
|
import "core-js/modules/esnext.iterator.map.js";
|
|
4
4
|
import dayjs from 'dayjs';
|
|
5
|
+
import { objectToId } from '../utils/objectToId';
|
|
5
6
|
import { getBackwardOffsetTimeByHourMins, getPreOffsetTimeByHourMins, getTimerStrByMinutes } from '../utils/time';
|
|
6
7
|
import { EScheduleFunctionType } from '../types';
|
|
7
8
|
import { scheduleLogger } from '../utils/ScheduleLogger';
|
|
@@ -18,15 +19,16 @@ const numAddZero = num => {
|
|
|
18
19
|
export const timerDataToSchedule = data => {
|
|
19
20
|
var _data$status;
|
|
20
21
|
scheduleLogger.debug('timerDataToSchedule:', data);
|
|
22
|
+
const _data = {
|
|
23
|
+
status: (_data$status = data.status) !== null && _data$status !== void 0 ? _data$status : false,
|
|
24
|
+
weeks: data.loops.split('').map(item => Number(item)),
|
|
25
|
+
startTime: data.time,
|
|
26
|
+
endTime: data.time
|
|
27
|
+
};
|
|
21
28
|
return {
|
|
22
|
-
id: `${EScheduleFunctionType.TIMER}_
|
|
29
|
+
id: objectToId(_data, `${EScheduleFunctionType.TIMER}_`),
|
|
23
30
|
type: EScheduleFunctionType.TIMER,
|
|
24
|
-
data:
|
|
25
|
-
status: (_data$status = data.status) !== null && _data$status !== void 0 ? _data$status : false,
|
|
26
|
-
weeks: data.loops.split('').map(item => Number(item)),
|
|
27
|
-
startTime: data.time,
|
|
28
|
-
endTime: data.time
|
|
29
|
-
}
|
|
31
|
+
data: _data
|
|
30
32
|
};
|
|
31
33
|
};
|
|
32
34
|
|
|
@@ -51,15 +53,16 @@ export const wakeUpNodeToSchedule = data => {
|
|
|
51
53
|
const startTime = getPreOffsetTimeByHourMins(data.hour, data.minute, data.step * 5 || 0);
|
|
52
54
|
const endTime = getBackwardOffsetTimeByHourMins(data.hour, data.minute, data.duration * 5);
|
|
53
55
|
scheduleLogger.debug('wakeUpNodeToSchedule:', data);
|
|
56
|
+
const _data = {
|
|
57
|
+
status: data.onOff,
|
|
58
|
+
weeks: data.loops.split('').map(item => Number(item)),
|
|
59
|
+
startTime,
|
|
60
|
+
endTime
|
|
61
|
+
};
|
|
54
62
|
return {
|
|
55
|
-
id: `${EScheduleFunctionType.WAKEUP}_
|
|
63
|
+
id: objectToId(_data, `${EScheduleFunctionType.WAKEUP}_`),
|
|
56
64
|
type: EScheduleFunctionType.WAKEUP,
|
|
57
|
-
data:
|
|
58
|
-
status: data.onOff,
|
|
59
|
-
weeks: data.loops.split('').map(item => Number(item)),
|
|
60
|
-
startTime,
|
|
61
|
-
endTime
|
|
62
|
-
}
|
|
65
|
+
data: _data
|
|
63
66
|
};
|
|
64
67
|
};
|
|
65
68
|
|
|
@@ -83,15 +86,16 @@ export const wakeUpDataToScheduleList = data => {
|
|
|
83
86
|
export const sleepNodeToSchedule = data => {
|
|
84
87
|
const startTime = getPreOffsetTimeByHourMins(data.hour, data.minute, data.step * 5);
|
|
85
88
|
scheduleLogger.debug('sleepNodeToSchedule:', data);
|
|
89
|
+
const _data = {
|
|
90
|
+
status: data.onOff,
|
|
91
|
+
weeks: data.loops.split('').map(item => Number(item)),
|
|
92
|
+
startTime,
|
|
93
|
+
endTime: data.time
|
|
94
|
+
};
|
|
86
95
|
return {
|
|
87
|
-
id: `${EScheduleFunctionType.SLEEP}_
|
|
96
|
+
id: objectToId(_data, `${EScheduleFunctionType.SLEEP}_`),
|
|
88
97
|
type: EScheduleFunctionType.SLEEP,
|
|
89
|
-
data:
|
|
90
|
-
status: data.onOff,
|
|
91
|
-
weeks: data.loops.split('').map(item => Number(item)),
|
|
92
|
-
startTime,
|
|
93
|
-
endTime: data.time
|
|
94
|
-
}
|
|
98
|
+
data: _data
|
|
95
99
|
};
|
|
96
100
|
};
|
|
97
101
|
|
|
@@ -155,15 +159,16 @@ export const randomNodeToSchedule = data => {
|
|
|
155
159
|
} = data;
|
|
156
160
|
const startTimeStr = getTimerStrByMinutes(startTime);
|
|
157
161
|
const endTimeStr = getTimerStrByMinutes(endTime);
|
|
162
|
+
const _data = {
|
|
163
|
+
status: data.onOff,
|
|
164
|
+
weeks: data.loops.split('').map(item => Number(item)),
|
|
165
|
+
startTime: startTimeStr,
|
|
166
|
+
endTime: endTimeStr
|
|
167
|
+
};
|
|
158
168
|
return {
|
|
159
|
-
id: `${EScheduleFunctionType.RANDOM}_
|
|
169
|
+
id: objectToId(_data, `${EScheduleFunctionType.RANDOM}_`),
|
|
160
170
|
type: EScheduleFunctionType.RANDOM,
|
|
161
|
-
data:
|
|
162
|
-
status: data.onOff,
|
|
163
|
-
weeks: data.loops.split('').map(item => Number(item)),
|
|
164
|
-
startTime: startTimeStr,
|
|
165
|
-
endTime: endTimeStr
|
|
166
|
-
}
|
|
171
|
+
data: _data
|
|
167
172
|
};
|
|
168
173
|
};
|
|
169
174
|
|
|
@@ -191,15 +196,16 @@ export const cycleNodeToSchedule = data => {
|
|
|
191
196
|
} = data;
|
|
192
197
|
const startTimeStr = getTimerStrByMinutes(startTime);
|
|
193
198
|
const endTimeStr = getTimerStrByMinutes(endTime);
|
|
199
|
+
const _data = {
|
|
200
|
+
status: data.onOff,
|
|
201
|
+
weeks: data.loops.split('').map(item => Number(item)),
|
|
202
|
+
startTime: startTimeStr,
|
|
203
|
+
endTime: endTimeStr
|
|
204
|
+
};
|
|
194
205
|
return {
|
|
195
|
-
id: `${EScheduleFunctionType.CYCLE}_
|
|
206
|
+
id: objectToId(_data, `${EScheduleFunctionType.CYCLE}_`),
|
|
196
207
|
type: EScheduleFunctionType.CYCLE,
|
|
197
|
-
data:
|
|
198
|
-
status: data.onOff,
|
|
199
|
-
weeks: data.loops.split('').map(item => Number(item)),
|
|
200
|
-
startTime: startTimeStr,
|
|
201
|
-
endTime: endTimeStr
|
|
202
|
-
}
|
|
208
|
+
data: _data
|
|
203
209
|
};
|
|
204
210
|
};
|
|
205
211
|
|
package/lib/conflict/type.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { renderHook, act } from '@testing-library/react-hooks';
|
|
2
2
|
import { useCountdownDp, useCountdownDpPull } from '../useCountdownDp';
|
|
3
|
-
import { useBaseLightDp,
|
|
3
|
+
import { useBaseLightDp, useFetchDpData } from '../useBaseLightDp';
|
|
4
4
|
import { scheduleDpCodes } from '../../config/dpCodes';
|
|
5
5
|
// Mock dependencies
|
|
6
6
|
jest.mock('../useBaseLightDp');
|
|
@@ -51,7 +51,7 @@ describe('useCountdownDpPull', () => {
|
|
|
51
51
|
const mockRefresh = jest.fn();
|
|
52
52
|
beforeEach(() => {
|
|
53
53
|
jest.clearAllMocks();
|
|
54
|
-
|
|
54
|
+
useFetchDpData.mockReturnValue({
|
|
55
55
|
refresh: mockRefresh
|
|
56
56
|
});
|
|
57
57
|
});
|
|
@@ -72,11 +72,11 @@ describe('useCountdownDpPull', () => {
|
|
|
72
72
|
});
|
|
73
73
|
it('should use correct dpCode', () => {
|
|
74
74
|
renderHook(() => useCountdownDpPull());
|
|
75
|
-
expect(
|
|
75
|
+
expect(useFetchDpData).toHaveBeenCalledWith([scheduleDpCodes.COUNTDOWN]);
|
|
76
76
|
});
|
|
77
77
|
it('should handle custom dpCode', () => {
|
|
78
78
|
const customDpCode = scheduleDpCodes.COUNTDOWN;
|
|
79
79
|
renderHook(() => useCountdownDpPull(customDpCode));
|
|
80
|
-
expect(
|
|
80
|
+
expect(useFetchDpData).toHaveBeenCalledWith([customDpCode]);
|
|
81
81
|
});
|
|
82
82
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { renderHook, act } from '@testing-library/react-hooks';
|
|
2
2
|
import { useTimerReportDp, useTimerReportDpPull } from '../useTimerReportDp';
|
|
3
|
-
import { useBaseLightDp,
|
|
3
|
+
import { useBaseLightDp, useFetchDpData } from '../useBaseLightDp';
|
|
4
4
|
import { useSupport } from '../useCommonSupport';
|
|
5
5
|
import { scheduleDpCodes } from '../../config/dpCodes';
|
|
6
6
|
import { timerReportParser } from '../../dpParser';
|
|
@@ -66,7 +66,7 @@ describe('useTimerReportDpPull', () => {
|
|
|
66
66
|
const mockRefresh = jest.fn();
|
|
67
67
|
beforeEach(() => {
|
|
68
68
|
jest.clearAllMocks();
|
|
69
|
-
|
|
69
|
+
useFetchDpData.mockReturnValue({
|
|
70
70
|
refresh: mockRefresh
|
|
71
71
|
});
|
|
72
72
|
});
|
|
@@ -88,6 +88,6 @@ describe('useTimerReportDpPull', () => {
|
|
|
88
88
|
});
|
|
89
89
|
it('should use correct dpCode', () => {
|
|
90
90
|
renderHook(() => useTimerReportDpPull());
|
|
91
|
-
expect(
|
|
91
|
+
expect(useFetchDpData).toHaveBeenCalledWith([scheduleDpCodes.TIMER_REPORT]);
|
|
92
92
|
});
|
|
93
93
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const objectToId: (obj: any, prefix?: string) => string;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import "core-js/modules/esnext.iterator.constructor.js";
|
|
2
|
+
import "core-js/modules/esnext.iterator.for-each.js";
|
|
3
|
+
import "core-js/modules/esnext.iterator.map.js";
|
|
4
|
+
export const objectToId = function (obj) {
|
|
5
|
+
let prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
|
|
6
|
+
// 递归排序对象键以确保一致性
|
|
7
|
+
function sortObjectKeys(obj) {
|
|
8
|
+
if (obj === null || typeof obj !== 'object') return obj;
|
|
9
|
+
if (Array.isArray(obj)) {
|
|
10
|
+
return obj.map(sortObjectKeys);
|
|
11
|
+
}
|
|
12
|
+
const sortedKeys = Object.keys(obj).sort();
|
|
13
|
+
const sortedObj = {};
|
|
14
|
+
sortedKeys.forEach(key => {
|
|
15
|
+
sortedObj[key] = sortObjectKeys(obj[key]);
|
|
16
|
+
});
|
|
17
|
+
return sortedObj;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// 转换为字符串
|
|
21
|
+
const sortedObj = sortObjectKeys(obj);
|
|
22
|
+
const str = JSON.stringify(sortedObj);
|
|
23
|
+
|
|
24
|
+
// 简单哈希算法
|
|
25
|
+
let hash = 5381;
|
|
26
|
+
for (let i = 0; i < str.length; i++) {
|
|
27
|
+
hash = (hash << 5) + hash + str.charCodeAt(i);
|
|
28
|
+
hash = hash & hash; // 转换为32位整数
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 转换为正数并生成字符串
|
|
32
|
+
return prefix + Math.abs(hash).toString(36);
|
|
33
|
+
};
|