@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.
@@ -128,11 +128,12 @@ function convertToTimeRanges(schedules) {
128
128
  const isCrossDay = endMinutes < startMinutes;
129
129
 
130
130
  // 如果定时状态为关闭,则设置星期,忽略冲突判断
131
- const dayOfWeek = schedule.data.status ? daysOfWeek[isCrossDay ? (week + 1) % 7 : week] : null;
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 === otherId || otherId === currentPreId) {
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).toEqual({
47
- id: `${EScheduleFunctionType.TIMER}_10:00_1000000`,
48
- type: EScheduleFunctionType.TIMER,
49
- data: {
50
- status: true,
51
- weeks: [1, 0, 0, 0, 0, 0, 0],
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].id).toBe(`${EScheduleFunctionType.TIMER}_10:00_1000000`);
90
- expect(result[1].id).toBe(`${EScheduleFunctionType.TIMER}_12:00_0100000`);
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).toEqual({
110
- id: `${EScheduleFunctionType.WAKEUP}_08_30_1000000`,
111
- type: EScheduleFunctionType.WAKEUP,
112
- data: {
113
- status: true,
114
- weeks: [1, 0, 0, 0, 0, 0, 0],
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].id).toBe(`${EScheduleFunctionType.WAKEUP}_08_30_1000000`);
152
- expect(result[1].id).toBe(`${EScheduleFunctionType.WAKEUP}_09_00_0100000`);
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).toEqual({
172
- id: `${EScheduleFunctionType.SLEEP}_22_20_1000000`,
173
- type: EScheduleFunctionType.SLEEP,
174
- data: {
175
- status: true,
176
- weeks: [1, 0, 0, 0, 0, 0, 0],
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].id).toBe(`${EScheduleFunctionType.SLEEP}_22_20_1000000`);
214
- expect(result[1].id).toBe(`${EScheduleFunctionType.SLEEP}_23_20_0100000`);
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).toEqual({
282
- id: `${EScheduleFunctionType.RANDOM}_600_720_1000000`,
283
- type: EScheduleFunctionType.RANDOM,
284
- data: {
285
- status: true,
286
- weeks: [1, 0, 0, 0, 0, 0, 0],
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].id).toBe(`${EScheduleFunctionType.RANDOM}_600_720_1000000`);
330
- expect(result[1].id).toBe(`${EScheduleFunctionType.RANDOM}_780_840_0100000`);
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).toEqual({
355
- id: `${EScheduleFunctionType.CYCLE}_600_720_1000000`,
356
- type: EScheduleFunctionType.CYCLE,
357
- data: {
358
- status: true,
359
- weeks: [1, 0, 0, 0, 0, 0, 0],
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].id).toBe(`${EScheduleFunctionType.CYCLE}_600_720_1000000`);
407
- expect(result[1].id).toBe(`${EScheduleFunctionType.CYCLE}_780_840_0100000`);
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}_${data.time}_${data.loops}`,
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}_${numAddZero(data.hour)}_${numAddZero(data.minute)}_${data.loops}`,
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}_${numAddZero(data.hour)}_${numAddZero(data.minute)}_${data.loops}`,
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}_${data.startTime}_${data.endTime}_${data.loops}`,
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}_${data.startTime}_${data.endTime}_${data.loops}`,
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
 
@@ -35,6 +35,7 @@ export interface ConflictResult {
35
35
  export interface UnifiedTimeRange {
36
36
  id: string;
37
37
  type: EScheduleFunctionType;
38
+ status: boolean;
38
39
  dayOfWeek: DayOfWeek;
39
40
  startMinutes: number;
40
41
  endMinutes: number;
@@ -1,6 +1,6 @@
1
1
  import { renderHook, act } from '@testing-library/react-hooks';
2
2
  import { useCountdownDp, useCountdownDpPull } from '../useCountdownDp';
3
- import { useBaseLightDp, useFetchDpDataByMesh } from '../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
- useFetchDpDataByMesh.mockReturnValue({
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(useFetchDpDataByMesh).toHaveBeenCalledWith([scheduleDpCodes.COUNTDOWN]);
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(useFetchDpDataByMesh).toHaveBeenCalledWith([customDpCode]);
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, useFetchDpDataByMesh } from '../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
- useFetchDpDataByMesh.mockReturnValue({
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(useFetchDpDataByMesh).toHaveBeenCalledWith([scheduleDpCodes.TIMER_REPORT]);
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
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ray-js/lamp-schedule-core",
3
- "version": "1.0.0-beta-4",
3
+ "version": "1.0.0",
4
4
  "description": "照明计划模块核心能力",
5
5
  "main": "./lib/index.js",
6
6
  "files": [