@pisell/private-materials 6.11.180 → 6.11.181
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/build/lowcode/assets-daily.json +11 -11
- package/build/lowcode/assets-dev.json +2 -2
- package/build/lowcode/assets-prod.json +11 -11
- package/build/lowcode/meta.js +1 -1
- package/build/lowcode/render/default/view.js +1 -1
- package/build/lowcode/view.js +1 -1
- package/es/plus/pisellReservation/PisellReservation.js +13 -4
- package/es/plus/pisellReservation/PisellVenueWallPage.d.ts +1 -0
- package/es/plus/pisellReservation/PisellVenueWallPage.js +1 -0
- package/es/plus/pisellReservation/floorMap/useReservationFloorPlan.d.ts +0 -1
- package/es/plus/pisellReservation/hooks/useReservationSalesHostData.d.ts +5 -0
- package/es/plus/pisellReservation/hooks/useReservationSalesHostData.js +7 -3
- package/es/plus/pisellReservation/hooks/useReservationWallClockFollow.d.ts +7 -4
- package/es/plus/pisellReservation/hooks/useReservationWallClockFollow.js +54 -15
- package/es/plus/pisellReservation/types.d.ts +6 -0
- package/lib/plus/pisellReservation/PisellReservation.js +13 -3
- package/lib/plus/pisellReservation/PisellVenueWallPage.d.ts +1 -0
- package/lib/plus/pisellReservation/floorMap/useReservationFloorPlan.d.ts +0 -1
- package/lib/plus/pisellReservation/hooks/useReservationSalesHostData.d.ts +5 -0
- package/lib/plus/pisellReservation/hooks/useReservationSalesHostData.js +4 -2
- package/lib/plus/pisellReservation/hooks/useReservationWallClockFollow.d.ts +7 -4
- package/lib/plus/pisellReservation/hooks/useReservationWallClockFollow.js +47 -16
- package/lib/plus/pisellReservation/types.d.ts +6 -0
- package/package.json +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var _excluded = ["gridDataSourceKey", "dataSources", "scheduleValue", "onScheduleChange", "toolBar", "floorMap", "scheduleStartSlot", "scheduleEndSlot", "onNewReservation", "timeNavigatorProps", "scheduleProps", "fab", "defaultBodyView", "data", "total", "pagination", "onPageChange", "onSearch", "onReset", "searchParams", "loading", "rowKey", "className", "style", "floorPlanId", "floorPlanCanvasWidth", "floorPlanCanvasHeight", "floorPlanCode", "floorPlanName", "floorPlanSort", "floorPlanStatus", "onFloorPlanPersisted", "putFloorPlan", "onFloorMapBookingClick", "bodyViewSwitchable", "lockedBodyView", "bodyViewStorageKey", "floorMapHudTableDrawer"];
|
|
1
|
+
var _excluded = ["gridDataSourceKey", "dataSources", "scheduleValue", "onScheduleChange", "toolBar", "floorMap", "scheduleStartSlot", "scheduleEndSlot", "onNewReservation", "timeNavigatorProps", "scheduleProps", "fab", "defaultBodyView", "data", "total", "pagination", "onPageChange", "onSearch", "onReset", "searchParams", "loading", "rowKey", "className", "style", "floorPlanId", "floorPlanCanvasWidth", "floorPlanCanvasHeight", "floorPlanCode", "floorPlanName", "floorPlanSort", "floorPlanStatus", "onFloorPlanPersisted", "putFloorPlan", "onFloorMapBookingClick", "bodyViewSwitchable", "lockedBodyView", "bodyViewStorageKey", "floorMapHudTableDrawer", "forceFollowWallClock"];
|
|
2
2
|
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
3
3
|
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
4
4
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
@@ -115,6 +115,7 @@ export var PisellReservationCore = function PisellReservationCore(props) {
|
|
|
115
115
|
bodyViewStorageKey = props.bodyViewStorageKey,
|
|
116
116
|
_props$floorMapHudTab = props.floorMapHudTableDrawer,
|
|
117
117
|
floorMapHudTableDrawer = _props$floorMapHudTab === void 0 ? false : _props$floorMapHudTab,
|
|
118
|
+
forceFollowWallClockProp = props.forceFollowWallClock,
|
|
118
119
|
rest = _objectWithoutProperties(props, _excluded);
|
|
119
120
|
void _unusedDefaultBodyView;
|
|
120
121
|
|
|
@@ -236,6 +237,11 @@ export var PisellReservationCore = function PisellReservationCore(props) {
|
|
|
236
237
|
_useState2 = _slicedToArray(_useState, 2),
|
|
237
238
|
shellBodyView = _useState2[0],
|
|
238
239
|
setShellBodyView = _useState2[1];
|
|
240
|
+
|
|
241
|
+
/** 锁定大屏子视图、显式 prop、或 Segmented 切到「大屏」:强制墙钟跟随且不可关 */
|
|
242
|
+
var wallClockFollowLocked = useMemo(function () {
|
|
243
|
+
return Boolean(forceFollowWallClockProp) || lockedBodyView === 'resourceWall' || shellBodyView === 'resourceWall';
|
|
244
|
+
}, [forceFollowWallClockProp, lockedBodyView, shellBodyView]);
|
|
239
245
|
var _useReservationFloorP = useReservationFloorPlan({
|
|
240
246
|
resolvedFloorPlanId: resolvedFloorPlanId,
|
|
241
247
|
effectiveFloorPlanCode: effectiveFloorPlanCode,
|
|
@@ -374,7 +380,7 @@ export var PisellReservationCore = function PisellReservationCore(props) {
|
|
|
374
380
|
debouncedSchedule = _useReservationSchedu.debouncedSchedule,
|
|
375
381
|
flushCommittedSchedule = _useReservationSchedu.flushCommittedSchedule,
|
|
376
382
|
queueCommittedSchedule = _useReservationSchedu.queueCommittedSchedule;
|
|
377
|
-
var _useReservationWallCl = useReservationWallClockFollow(scheduleValueProp, setInternalSchedule, flushCommittedSchedule, onScheduleChange),
|
|
383
|
+
var _useReservationWallCl = useReservationWallClockFollow(scheduleValueProp, setInternalSchedule, flushCommittedSchedule, onScheduleChange, wallClockFollowLocked),
|
|
378
384
|
followWallClock = _useReservationWallCl.followWallClock,
|
|
379
385
|
setFollowWallClock = _useReservationWallCl.setFollowWallClock,
|
|
380
386
|
onFollowWallClockToggle = _useReservationWallCl.onFollowWallClockToggle,
|
|
@@ -387,6 +393,7 @@ export var PisellReservationCore = function PisellReservationCore(props) {
|
|
|
387
393
|
pisellosRef: pisellosRef,
|
|
388
394
|
hasPisellosGetModule: hasPisellosGetModule,
|
|
389
395
|
debouncedSchedule: debouncedSchedule,
|
|
396
|
+
followWallClock: followWallClock,
|
|
390
397
|
resourceBoardLoading: resourceBoardData.loading,
|
|
391
398
|
floorDayBookingLoading: floorDayBookingData.loading,
|
|
392
399
|
floorDayBookingData: floorDayBookingData.data,
|
|
@@ -530,13 +537,15 @@ export var PisellReservationCore = function PisellReservationCore(props) {
|
|
|
530
537
|
}
|
|
531
538
|
}, [debouncedSchedule, isInternalListData, floorDayBookingData.patchSearchParams, operatingDayBoundary]);
|
|
532
539
|
var handleScheduleChange = useCallback(function (next) {
|
|
533
|
-
|
|
540
|
+
if (!wallClockFollowLocked) {
|
|
541
|
+
setFollowWallClock(false);
|
|
542
|
+
}
|
|
534
543
|
if (scheduleValueProp === undefined) {
|
|
535
544
|
setInternalSchedule(next);
|
|
536
545
|
}
|
|
537
546
|
onScheduleChange === null || onScheduleChange === void 0 || onScheduleChange(next);
|
|
538
547
|
queueCommittedSchedule(next);
|
|
539
|
-
}, [scheduleValueProp, onScheduleChange, setFollowWallClock, queueCommittedSchedule]);
|
|
548
|
+
}, [scheduleValueProp, onScheduleChange, setFollowWallClock, queueCommittedSchedule, wallClockFollowLocked]);
|
|
540
549
|
|
|
541
550
|
// --- 平面图:合并 props、点击预约、HUD;loading 防抖后交给 RecordBoard ---
|
|
542
551
|
|
|
@@ -7,6 +7,7 @@ import type { PisellReservationProps } from './types';
|
|
|
7
7
|
* - `lockedBodyView="resourceWall"`:锁定在大屏视图。
|
|
8
8
|
*
|
|
9
9
|
* **无需新增 props 类型**:沿用 {@link PisellReservationProps};可选行为与预约页相同(如 `toolBar`、`scheduleValue`、`floorMap` 等)。
|
|
10
|
+
* Core 在锁定大屏或预约页内 Segmented 切到「大屏」时(`shellBodyView === 'resourceWall'`)均 **强制跟随当前时间**(不可关闭)。
|
|
10
11
|
* 默认使用 {@link PISELL_RESERVATION_VENUE_WALL_PAGE_STORAGE_KEY} 作为 `bodyViewStorageKey`,以便大屏筛选与主预约页 localStorage 隔离;可传入自定义 key 覆盖。
|
|
11
12
|
*/
|
|
12
13
|
export declare const PisellVenueWallPage: React.FC<PisellReservationProps>;
|
|
@@ -12,6 +12,7 @@ import { PISELL_RESERVATION_VENUE_WALL_PAGE_STORAGE_KEY } from "./reservationCon
|
|
|
12
12
|
* - `lockedBodyView="resourceWall"`:锁定在大屏视图。
|
|
13
13
|
*
|
|
14
14
|
* **无需新增 props 类型**:沿用 {@link PisellReservationProps};可选行为与预约页相同(如 `toolBar`、`scheduleValue`、`floorMap` 等)。
|
|
15
|
+
* Core 在锁定大屏或预约页内 Segmented 切到「大屏」时(`shellBodyView === 'resourceWall'`)均 **强制跟随当前时间**(不可关闭)。
|
|
15
16
|
* 默认使用 {@link PISELL_RESERVATION_VENUE_WALL_PAGE_STORAGE_KEY} 作为 `bodyViewStorageKey`,以便大屏筛选与主预约页 localStorage 隔离;可传入自定义 key 覆盖。
|
|
16
17
|
*/
|
|
17
18
|
export var PisellVenueWallPage = function PisellVenueWallPage(props) {
|
|
@@ -10,12 +10,17 @@ declare type PisellOSLike = {
|
|
|
10
10
|
* 内置列表且资源台 + floorDayBooking 均就绪后,向宿主 sales 拉两套数据:
|
|
11
11
|
* - `getResourceBookingList`:游标时刻下的预约子集,参与合并进平面图 dataSources;
|
|
12
12
|
* - `getTimelineHighlights`:时间轴密度折线(无则退回 PisellReservation 内本地计算)。
|
|
13
|
+
*
|
|
14
|
+
* **跟随当前**:`followWallClock === true` 时第三个参数 `currentTimeStr` 与 `timeStr` 相同(均来自 `debouncedSchedule.at`),
|
|
15
|
+
* 避免与墙钟 `dayjs()` 差一分钟;手动关闭跟随后仍传实时 `dayjs()`,保留「游标 vs 此刻」双通道语义。
|
|
13
16
|
*/
|
|
14
17
|
export declare function useReservationSalesHostData(options: {
|
|
15
18
|
isInternalListData: boolean;
|
|
16
19
|
pisellosRef: MutableRefObject<PisellOSLike>;
|
|
17
20
|
hasPisellosGetModule: boolean;
|
|
18
21
|
debouncedSchedule: ReservationScheduleBandValue;
|
|
22
|
+
/** 顶栏「跟随当前时间」:为 true 时 `getResourceBookingList` 的 currentTime 与 timeStr 一致 */
|
|
23
|
+
followWallClock: boolean;
|
|
19
24
|
resourceBoardLoading: boolean;
|
|
20
25
|
floorDayBookingLoading: boolean;
|
|
21
26
|
floorDayBookingData: unknown[];
|
|
@@ -12,12 +12,16 @@ import { normalizeSalesResourceBookingListResult } from "../data/reservationTabl
|
|
|
12
12
|
* 内置列表且资源台 + floorDayBooking 均就绪后,向宿主 sales 拉两套数据:
|
|
13
13
|
* - `getResourceBookingList`:游标时刻下的预约子集,参与合并进平面图 dataSources;
|
|
14
14
|
* - `getTimelineHighlights`:时间轴密度折线(无则退回 PisellReservation 内本地计算)。
|
|
15
|
+
*
|
|
16
|
+
* **跟随当前**:`followWallClock === true` 时第三个参数 `currentTimeStr` 与 `timeStr` 相同(均来自 `debouncedSchedule.at`),
|
|
17
|
+
* 避免与墙钟 `dayjs()` 差一分钟;手动关闭跟随后仍传实时 `dayjs()`,保留「游标 vs 此刻」双通道语义。
|
|
15
18
|
*/
|
|
16
19
|
export function useReservationSalesHostData(options) {
|
|
17
20
|
var isInternalListData = options.isInternalListData,
|
|
18
21
|
pisellosRef = options.pisellosRef,
|
|
19
22
|
hasPisellosGetModule = options.hasPisellosGetModule,
|
|
20
23
|
debouncedSchedule = options.debouncedSchedule,
|
|
24
|
+
followWallClock = options.followWallClock,
|
|
21
25
|
resourceBoardLoading = options.resourceBoardLoading,
|
|
22
26
|
floorDayBookingLoading = options.floorDayBookingLoading,
|
|
23
27
|
floorDayBookingData = options.floorDayBookingData,
|
|
@@ -106,7 +110,7 @@ export function useReservationSalesHostData(options) {
|
|
|
106
110
|
if (!Array.isArray(list)) {
|
|
107
111
|
return;
|
|
108
112
|
}
|
|
109
|
-
var retryGateKey = "".concat(debouncedAtMs !== null && debouncedAtMs !== void 0 ? debouncedAtMs : 'na', "|").concat(floorDayBookingDepKey, "|v").concat(floorDayBookingDataVersion, "|").concat(hasPisellosGetModule ? 1 : 0);
|
|
113
|
+
var retryGateKey = "".concat(debouncedAtMs !== null && debouncedAtMs !== void 0 ? debouncedAtMs : 'na', "|").concat(floorDayBookingDepKey, "|v").concat(floorDayBookingDataVersion, "|").concat(hasPisellosGetModule ? 1 : 0, "|fw").concat(followWallClock ? 1 : 0);
|
|
110
114
|
if (retryGateKey !== resourceListRetryGateRef.current) {
|
|
111
115
|
resourceListRetryGateRef.current = retryGateKey;
|
|
112
116
|
resourceListHostSkipRef.current = false;
|
|
@@ -139,7 +143,7 @@ export function useReservationSalesHostData(options) {
|
|
|
139
143
|
|
|
140
144
|
var resourceBookingListTimeFormat = 'YYYY-MM-DD HH:mm';
|
|
141
145
|
var timeStr = dayjs(debouncedSchedule.at).format(resourceBookingListTimeFormat);
|
|
142
|
-
var currentTimeStr = dayjs().format(resourceBookingListTimeFormat);
|
|
146
|
+
var currentTimeStr = followWallClock ? timeStr : dayjs().format(resourceBookingListTimeFormat);
|
|
143
147
|
var applyHostList = function applyHostList(raw) {
|
|
144
148
|
if (salesBookingRequestRef.current !== reqId) return;
|
|
145
149
|
var normalized = normalizeSalesResourceBookingListResult(raw);
|
|
@@ -177,7 +181,7 @@ export function useReservationSalesHostData(options) {
|
|
|
177
181
|
* 兜底信号:哪怕 cheap hash 没变,只要有 WS 推送 mutate 就重跑 host call。
|
|
178
182
|
* 配合 `resourceListRetryGateRef` 保证非宿主场景不会重复打接口。
|
|
179
183
|
*/
|
|
180
|
-
floorDayBookingDataVersion, debouncedAtMs, pisellosRef]);
|
|
184
|
+
floorDayBookingDataVersion, debouncedAtMs, followWallClock, pisellosRef]);
|
|
181
185
|
var _useState3 = useState(null),
|
|
182
186
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
183
187
|
salesTimelineHighlights = _useState4[0],
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import { type SetStateAction } from 'react';
|
|
2
2
|
import type { ReservationScheduleBandValue } from '@pisell/materials';
|
|
3
3
|
declare type OnScheduleChange = ((v: ReservationScheduleBandValue) => void) | undefined;
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* 顶栏「跟随当前时间」:在每自然分钟整点(*: * :00)对齐日程,`at` 使用当前分钟的 `startOf('minute')`,
|
|
6
|
+
* 并通过 flushCommittedSchedule 触发防抖链。
|
|
7
|
+
*
|
|
8
|
+
* @param wallClockFollowLocked 为 true 时(如大屏锁定 resourceWall):定时器始终运行,且不可通过交互关闭跟随。
|
|
6
9
|
*/
|
|
7
|
-
export declare function useReservationWallClockFollow(scheduleValueProp: ReservationScheduleBandValue | undefined, setInternalSchedule: (v: ReservationScheduleBandValue) => void, flushCommittedSchedule: (v: ReservationScheduleBandValue) => void, onScheduleChange: OnScheduleChange): {
|
|
10
|
+
export declare function useReservationWallClockFollow(scheduleValueProp: ReservationScheduleBandValue | undefined, setInternalSchedule: (v: ReservationScheduleBandValue) => void, flushCommittedSchedule: (v: ReservationScheduleBandValue) => void, onScheduleChange: OnScheduleChange, wallClockFollowLocked?: boolean): {
|
|
8
11
|
followWallClock: boolean;
|
|
9
|
-
setFollowWallClock:
|
|
12
|
+
setFollowWallClock: (value: SetStateAction<boolean>) => void;
|
|
10
13
|
onFollowWallClockToggle: () => void;
|
|
11
14
|
onTimeNavigatorUserInteraction: () => void;
|
|
12
15
|
};
|
|
@@ -7,51 +7,90 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
|
7
7
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
8
8
|
import dayjs from 'dayjs';
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* 顶栏「跟随当前时间」:在每自然分钟整点(*: * :00)对齐日程,`at` 使用当前分钟的 `startOf('minute')`,
|
|
11
|
+
* 并通过 flushCommittedSchedule 触发防抖链。
|
|
12
|
+
*
|
|
13
|
+
* @param wallClockFollowLocked 为 true 时(如大屏锁定 resourceWall):定时器始终运行,且不可通过交互关闭跟随。
|
|
11
14
|
*/
|
|
12
15
|
export function useReservationWallClockFollow(scheduleValueProp, setInternalSchedule, flushCommittedSchedule, onScheduleChange) {
|
|
16
|
+
var wallClockFollowLocked = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
13
17
|
var _useState = useState(true),
|
|
14
18
|
_useState2 = _slicedToArray(_useState, 2),
|
|
15
19
|
followWallClock = _useState2[0],
|
|
16
|
-
|
|
20
|
+
setFollowWallClockInternal = _useState2[1];
|
|
17
21
|
var onScheduleChangeRef = useRef(onScheduleChange);
|
|
22
|
+
/** 避免 effect 依赖整个 `scheduleValueProp` 引用:父级每次 render 新对象会误重置定时器并多次首帧 tick */
|
|
23
|
+
var scheduleValuePropRef = useRef(scheduleValueProp);
|
|
24
|
+
scheduleValuePropRef.current = scheduleValueProp;
|
|
25
|
+
var scheduleControlled = scheduleValueProp !== undefined;
|
|
26
|
+
var followWallClockEffective = wallClockFollowLocked || followWallClock;
|
|
27
|
+
|
|
28
|
+
/** 锁定模式下始终保持内部开关为 true,避免闭包里读到 false */
|
|
29
|
+
useEffect(function () {
|
|
30
|
+
if (wallClockFollowLocked) setFollowWallClockInternal(true);
|
|
31
|
+
}, [wallClockFollowLocked]);
|
|
18
32
|
useEffect(function () {
|
|
19
33
|
onScheduleChangeRef.current = onScheduleChange;
|
|
20
34
|
});
|
|
21
35
|
useEffect(function () {
|
|
22
|
-
if (!
|
|
36
|
+
if (!followWallClockEffective) return;
|
|
37
|
+
var timeoutId = null;
|
|
38
|
+
var cancelled = false;
|
|
39
|
+
|
|
40
|
+
/** 距下一自然分钟整点的毫秒数(下一分钟的 :00.000) */
|
|
41
|
+
var msUntilNextMinuteBoundary = function msUntilNextMinuteBoundary() {
|
|
42
|
+
var now = dayjs();
|
|
43
|
+
return Math.max(0, now.startOf('minute').add(1, 'minute').diff(now));
|
|
44
|
+
};
|
|
23
45
|
var tick = function tick() {
|
|
24
46
|
var _onScheduleChangeRef$;
|
|
25
|
-
var now = dayjs();
|
|
47
|
+
var now = dayjs().startOf('minute');
|
|
26
48
|
var next = {
|
|
27
49
|
date: now.startOf('day'),
|
|
28
50
|
at: now
|
|
29
51
|
};
|
|
30
|
-
if (
|
|
52
|
+
if (scheduleValuePropRef.current === undefined) {
|
|
31
53
|
setInternalSchedule(next);
|
|
32
54
|
}
|
|
33
55
|
(_onScheduleChangeRef$ = onScheduleChangeRef.current) === null || _onScheduleChangeRef$ === void 0 || _onScheduleChangeRef$.call(onScheduleChangeRef, next);
|
|
34
56
|
/** 跟随当前:立即提交日程,patch / 外部 onSearch 由 debouncedSchedule effect 统一处理 */
|
|
35
57
|
flushCommittedSchedule(next);
|
|
36
58
|
};
|
|
59
|
+
var scheduleNextBoundary = function scheduleNextBoundary() {
|
|
60
|
+
if (cancelled) return;
|
|
61
|
+
timeoutId = window.setTimeout(function () {
|
|
62
|
+
if (cancelled) return;
|
|
63
|
+
tick();
|
|
64
|
+
scheduleNextBoundary();
|
|
65
|
+
}, msUntilNextMinuteBoundary());
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/** 首帧:立刻对齐到当前整分;之后仅在每分钟 rollover 时再 tick */
|
|
37
69
|
tick();
|
|
38
|
-
|
|
70
|
+
scheduleNextBoundary();
|
|
39
71
|
return function () {
|
|
40
|
-
|
|
72
|
+
cancelled = true;
|
|
73
|
+
if (timeoutId != null) window.clearTimeout(timeoutId);
|
|
41
74
|
};
|
|
42
|
-
// setInternalSchedule 为 schedule hook 的 setState
|
|
43
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps --
|
|
44
|
-
}, [
|
|
75
|
+
// setInternalSchedule 为 schedule hook 的 setState,引用稳定;不把 scheduleValueProp 放进 deps(见 ref)
|
|
76
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- scheduleControlled:仅受控/非受控切换时重启定时器
|
|
77
|
+
}, [followWallClockEffective, flushCommittedSchedule, scheduleControlled]);
|
|
78
|
+
var setFollowWallClock = useCallback(function (value) {
|
|
79
|
+
if (wallClockFollowLocked) return;
|
|
80
|
+
setFollowWallClockInternal(value);
|
|
81
|
+
}, [wallClockFollowLocked]);
|
|
45
82
|
var onFollowWallClockToggle = useCallback(function () {
|
|
46
|
-
|
|
83
|
+
if (wallClockFollowLocked) return;
|
|
84
|
+
setFollowWallClockInternal(function (v) {
|
|
47
85
|
return !v;
|
|
48
86
|
});
|
|
49
|
-
}, []);
|
|
87
|
+
}, [wallClockFollowLocked]);
|
|
50
88
|
var onTimeNavigatorUserInteraction = useCallback(function () {
|
|
51
|
-
|
|
52
|
-
|
|
89
|
+
if (wallClockFollowLocked) return;
|
|
90
|
+
setFollowWallClockInternal(false);
|
|
91
|
+
}, [wallClockFollowLocked]);
|
|
53
92
|
return {
|
|
54
|
-
followWallClock:
|
|
93
|
+
followWallClock: followWallClockEffective,
|
|
55
94
|
setFollowWallClock: setFollowWallClock,
|
|
56
95
|
onFollowWallClockToggle: onFollowWallClockToggle,
|
|
57
96
|
onTimeNavigatorUserInteraction: onTimeNavigatorUserInteraction
|
|
@@ -165,4 +165,10 @@ export interface PisellReservationProps extends Omit<RecordBoardProps, 'toolBar'
|
|
|
165
165
|
bodyViewStorageKey?: string;
|
|
166
166
|
/** 点击平面图左上角 HUD 打开窄屏表格抽屉(画布已绑定资源行) */
|
|
167
167
|
floorMapHudTableDrawer?: boolean;
|
|
168
|
+
/**
|
|
169
|
+
* 强制「跟随当前时间」不可关闭(定时对齐墙钟、`getResourceBookingList` 与游标时间一致)。
|
|
170
|
+
* - **默认**:{@link lockedBodyView} 为 `resourceWall`,或用户在 RecordBoard 内**切换到「大屏 / resourceWall」子视图**时自动启用。
|
|
171
|
+
* - 设为 `true` 可在其它场景也强制跟随。
|
|
172
|
+
*/
|
|
173
|
+
forceFollowWallClock?: boolean;
|
|
168
174
|
}
|
|
@@ -118,6 +118,7 @@ var PisellReservationCore = (props) => {
|
|
|
118
118
|
lockedBodyView,
|
|
119
119
|
bodyViewStorageKey,
|
|
120
120
|
floorMapHudTableDrawer = false,
|
|
121
|
+
forceFollowWallClock: forceFollowWallClockProp,
|
|
121
122
|
...rest
|
|
122
123
|
} = props;
|
|
123
124
|
const isInternalListData = (0, import_reservationDataUtils.shouldUseBuiltinReservationList)(
|
|
@@ -204,6 +205,10 @@ var PisellReservationCore = (props) => {
|
|
|
204
205
|
const [shellBodyView, setShellBodyView] = (0, import_react.useState)(
|
|
205
206
|
() => (0, import_reservationDataUtils.readBodyViewFromStorageKey)(bodyViewStorageKey)
|
|
206
207
|
);
|
|
208
|
+
const wallClockFollowLocked = (0, import_react.useMemo)(
|
|
209
|
+
() => Boolean(forceFollowWallClockProp) || lockedBodyView === "resourceWall" || shellBodyView === "resourceWall",
|
|
210
|
+
[forceFollowWallClockProp, lockedBodyView, shellBodyView]
|
|
211
|
+
);
|
|
207
212
|
const { baseFloorConfig, floorPlanRemoteId, setRemoteFloorPlanView } = (0, import_useReservationFloorPlan.useReservationFloorPlan)({
|
|
208
213
|
resolvedFloorPlanId,
|
|
209
214
|
effectiveFloorPlanCode,
|
|
@@ -338,7 +343,8 @@ var PisellReservationCore = (props) => {
|
|
|
338
343
|
scheduleValueProp,
|
|
339
344
|
setInternalSchedule,
|
|
340
345
|
flushCommittedSchedule,
|
|
341
|
-
onScheduleChange
|
|
346
|
+
onScheduleChange,
|
|
347
|
+
wallClockFollowLocked
|
|
342
348
|
);
|
|
343
349
|
const prevCommittedDateRef = (0, import_react.useRef)(null);
|
|
344
350
|
const { salesResourceBookings, salesTimelineHighlights } = (0, import_useReservationSalesHostData.useReservationSalesHostData)({
|
|
@@ -346,6 +352,7 @@ var PisellReservationCore = (props) => {
|
|
|
346
352
|
pisellosRef,
|
|
347
353
|
hasPisellosGetModule,
|
|
348
354
|
debouncedSchedule,
|
|
355
|
+
followWallClock,
|
|
349
356
|
resourceBoardLoading: resourceBoardData.loading,
|
|
350
357
|
floorDayBookingLoading: floorDayBookingData.loading,
|
|
351
358
|
floorDayBookingData: floorDayBookingData.data,
|
|
@@ -487,7 +494,9 @@ var PisellReservationCore = (props) => {
|
|
|
487
494
|
]);
|
|
488
495
|
const handleScheduleChange = (0, import_react.useCallback)(
|
|
489
496
|
(next) => {
|
|
490
|
-
|
|
497
|
+
if (!wallClockFollowLocked) {
|
|
498
|
+
setFollowWallClock(false);
|
|
499
|
+
}
|
|
491
500
|
if (scheduleValueProp === void 0) {
|
|
492
501
|
setInternalSchedule(next);
|
|
493
502
|
}
|
|
@@ -498,7 +507,8 @@ var PisellReservationCore = (props) => {
|
|
|
498
507
|
scheduleValueProp,
|
|
499
508
|
onScheduleChange,
|
|
500
509
|
setFollowWallClock,
|
|
501
|
-
queueCommittedSchedule
|
|
510
|
+
queueCommittedSchedule,
|
|
511
|
+
wallClockFollowLocked
|
|
502
512
|
]
|
|
503
513
|
);
|
|
504
514
|
const dataSources = (0, import_react.useMemo)(() => {
|
|
@@ -7,6 +7,7 @@ import type { PisellReservationProps } from './types';
|
|
|
7
7
|
* - `lockedBodyView="resourceWall"`:锁定在大屏视图。
|
|
8
8
|
*
|
|
9
9
|
* **无需新增 props 类型**:沿用 {@link PisellReservationProps};可选行为与预约页相同(如 `toolBar`、`scheduleValue`、`floorMap` 等)。
|
|
10
|
+
* Core 在锁定大屏或预约页内 Segmented 切到「大屏」时(`shellBodyView === 'resourceWall'`)均 **强制跟随当前时间**(不可关闭)。
|
|
10
11
|
* 默认使用 {@link PISELL_RESERVATION_VENUE_WALL_PAGE_STORAGE_KEY} 作为 `bodyViewStorageKey`,以便大屏筛选与主预约页 localStorage 隔离;可传入自定义 key 覆盖。
|
|
11
12
|
*/
|
|
12
13
|
export declare const PisellVenueWallPage: React.FC<PisellReservationProps>;
|
|
@@ -10,12 +10,17 @@ declare type PisellOSLike = {
|
|
|
10
10
|
* 内置列表且资源台 + floorDayBooking 均就绪后,向宿主 sales 拉两套数据:
|
|
11
11
|
* - `getResourceBookingList`:游标时刻下的预约子集,参与合并进平面图 dataSources;
|
|
12
12
|
* - `getTimelineHighlights`:时间轴密度折线(无则退回 PisellReservation 内本地计算)。
|
|
13
|
+
*
|
|
14
|
+
* **跟随当前**:`followWallClock === true` 时第三个参数 `currentTimeStr` 与 `timeStr` 相同(均来自 `debouncedSchedule.at`),
|
|
15
|
+
* 避免与墙钟 `dayjs()` 差一分钟;手动关闭跟随后仍传实时 `dayjs()`,保留「游标 vs 此刻」双通道语义。
|
|
13
16
|
*/
|
|
14
17
|
export declare function useReservationSalesHostData(options: {
|
|
15
18
|
isInternalListData: boolean;
|
|
16
19
|
pisellosRef: MutableRefObject<PisellOSLike>;
|
|
17
20
|
hasPisellosGetModule: boolean;
|
|
18
21
|
debouncedSchedule: ReservationScheduleBandValue;
|
|
22
|
+
/** 顶栏「跟随当前时间」:为 true 时 `getResourceBookingList` 的 currentTime 与 timeStr 一致 */
|
|
23
|
+
followWallClock: boolean;
|
|
19
24
|
resourceBoardLoading: boolean;
|
|
20
25
|
floorDayBookingLoading: boolean;
|
|
21
26
|
floorDayBookingData: unknown[];
|
|
@@ -42,6 +42,7 @@ function useReservationSalesHostData(options) {
|
|
|
42
42
|
pisellosRef,
|
|
43
43
|
hasPisellosGetModule,
|
|
44
44
|
debouncedSchedule,
|
|
45
|
+
followWallClock,
|
|
45
46
|
resourceBoardLoading,
|
|
46
47
|
floorDayBookingLoading,
|
|
47
48
|
floorDayBookingData,
|
|
@@ -104,7 +105,7 @@ function useReservationSalesHostData(options) {
|
|
|
104
105
|
if (!Array.isArray(list)) {
|
|
105
106
|
return;
|
|
106
107
|
}
|
|
107
|
-
const retryGateKey = `${debouncedAtMs ?? "na"}|${floorDayBookingDepKey}|v${floorDayBookingDataVersion}|${hasPisellosGetModule ? 1 : 0}`;
|
|
108
|
+
const retryGateKey = `${debouncedAtMs ?? "na"}|${floorDayBookingDepKey}|v${floorDayBookingDataVersion}|${hasPisellosGetModule ? 1 : 0}|fw${followWallClock ? 1 : 0}`;
|
|
108
109
|
if (retryGateKey !== resourceListRetryGateRef.current) {
|
|
109
110
|
resourceListRetryGateRef.current = retryGateKey;
|
|
110
111
|
resourceListHostSkipRef.current = false;
|
|
@@ -129,7 +130,7 @@ function useReservationSalesHostData(options) {
|
|
|
129
130
|
const timeStr = (0, import_dayjs.default)(debouncedSchedule.at).format(
|
|
130
131
|
resourceBookingListTimeFormat
|
|
131
132
|
);
|
|
132
|
-
const currentTimeStr = (0, import_dayjs.default)().format(resourceBookingListTimeFormat);
|
|
133
|
+
const currentTimeStr = followWallClock ? timeStr : (0, import_dayjs.default)().format(resourceBookingListTimeFormat);
|
|
133
134
|
const applyHostList = (raw) => {
|
|
134
135
|
if (salesBookingRequestRef.current !== reqId) return;
|
|
135
136
|
const normalized = (0, import_reservationTablesMerge.normalizeSalesResourceBookingListResult)(raw);
|
|
@@ -178,6 +179,7 @@ function useReservationSalesHostData(options) {
|
|
|
178
179
|
*/
|
|
179
180
|
floorDayBookingDataVersion,
|
|
180
181
|
debouncedAtMs,
|
|
182
|
+
followWallClock,
|
|
181
183
|
pisellosRef
|
|
182
184
|
]);
|
|
183
185
|
const [salesTimelineHighlights, setSalesTimelineHighlights] = (0, import_react.useState)(null);
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import { type SetStateAction } from 'react';
|
|
2
2
|
import type { ReservationScheduleBandValue } from '@pisell/materials';
|
|
3
3
|
declare type OnScheduleChange = ((v: ReservationScheduleBandValue) => void) | undefined;
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* 顶栏「跟随当前时间」:在每自然分钟整点(*: * :00)对齐日程,`at` 使用当前分钟的 `startOf('minute')`,
|
|
6
|
+
* 并通过 flushCommittedSchedule 触发防抖链。
|
|
7
|
+
*
|
|
8
|
+
* @param wallClockFollowLocked 为 true 时(如大屏锁定 resourceWall):定时器始终运行,且不可通过交互关闭跟随。
|
|
6
9
|
*/
|
|
7
|
-
export declare function useReservationWallClockFollow(scheduleValueProp: ReservationScheduleBandValue | undefined, setInternalSchedule: (v: ReservationScheduleBandValue) => void, flushCommittedSchedule: (v: ReservationScheduleBandValue) => void, onScheduleChange: OnScheduleChange): {
|
|
10
|
+
export declare function useReservationWallClockFollow(scheduleValueProp: ReservationScheduleBandValue | undefined, setInternalSchedule: (v: ReservationScheduleBandValue) => void, flushCommittedSchedule: (v: ReservationScheduleBandValue) => void, onScheduleChange: OnScheduleChange, wallClockFollowLocked?: boolean): {
|
|
8
11
|
followWallClock: boolean;
|
|
9
|
-
setFollowWallClock:
|
|
12
|
+
setFollowWallClock: (value: SetStateAction<boolean>) => void;
|
|
10
13
|
onFollowWallClockToggle: () => void;
|
|
11
14
|
onTimeNavigatorUserInteraction: () => void;
|
|
12
15
|
};
|
|
@@ -34,41 +34,72 @@ __export(useReservationWallClockFollow_exports, {
|
|
|
34
34
|
module.exports = __toCommonJS(useReservationWallClockFollow_exports);
|
|
35
35
|
var import_react = require("react");
|
|
36
36
|
var import_dayjs = __toESM(require("dayjs"));
|
|
37
|
-
function useReservationWallClockFollow(scheduleValueProp, setInternalSchedule, flushCommittedSchedule, onScheduleChange) {
|
|
38
|
-
const [followWallClock,
|
|
37
|
+
function useReservationWallClockFollow(scheduleValueProp, setInternalSchedule, flushCommittedSchedule, onScheduleChange, wallClockFollowLocked = false) {
|
|
38
|
+
const [followWallClock, setFollowWallClockInternal] = (0, import_react.useState)(true);
|
|
39
39
|
const onScheduleChangeRef = (0, import_react.useRef)(onScheduleChange);
|
|
40
|
+
const scheduleValuePropRef = (0, import_react.useRef)(scheduleValueProp);
|
|
41
|
+
scheduleValuePropRef.current = scheduleValueProp;
|
|
42
|
+
const scheduleControlled = scheduleValueProp !== void 0;
|
|
43
|
+
const followWallClockEffective = wallClockFollowLocked || followWallClock;
|
|
44
|
+
(0, import_react.useEffect)(() => {
|
|
45
|
+
if (wallClockFollowLocked) setFollowWallClockInternal(true);
|
|
46
|
+
}, [wallClockFollowLocked]);
|
|
40
47
|
(0, import_react.useEffect)(() => {
|
|
41
48
|
onScheduleChangeRef.current = onScheduleChange;
|
|
42
49
|
});
|
|
43
50
|
(0, import_react.useEffect)(() => {
|
|
44
|
-
if (!
|
|
51
|
+
if (!followWallClockEffective) return;
|
|
52
|
+
let timeoutId = null;
|
|
53
|
+
let cancelled = false;
|
|
54
|
+
const msUntilNextMinuteBoundary = () => {
|
|
55
|
+
const now = (0, import_dayjs.default)();
|
|
56
|
+
return Math.max(0, now.startOf("minute").add(1, "minute").diff(now));
|
|
57
|
+
};
|
|
45
58
|
const tick = () => {
|
|
46
59
|
var _a;
|
|
47
|
-
const now = (0, import_dayjs.default)();
|
|
60
|
+
const now = (0, import_dayjs.default)().startOf("minute");
|
|
48
61
|
const next = {
|
|
49
62
|
date: now.startOf("day"),
|
|
50
63
|
at: now
|
|
51
64
|
};
|
|
52
|
-
if (
|
|
65
|
+
if (scheduleValuePropRef.current === void 0) {
|
|
53
66
|
setInternalSchedule(next);
|
|
54
67
|
}
|
|
55
68
|
(_a = onScheduleChangeRef.current) == null ? void 0 : _a.call(onScheduleChangeRef, next);
|
|
56
69
|
flushCommittedSchedule(next);
|
|
57
70
|
};
|
|
71
|
+
const scheduleNextBoundary = () => {
|
|
72
|
+
if (cancelled) return;
|
|
73
|
+
timeoutId = window.setTimeout(() => {
|
|
74
|
+
if (cancelled) return;
|
|
75
|
+
tick();
|
|
76
|
+
scheduleNextBoundary();
|
|
77
|
+
}, msUntilNextMinuteBoundary());
|
|
78
|
+
};
|
|
58
79
|
tick();
|
|
59
|
-
|
|
60
|
-
return () =>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
scheduleNextBoundary();
|
|
81
|
+
return () => {
|
|
82
|
+
cancelled = true;
|
|
83
|
+
if (timeoutId != null) window.clearTimeout(timeoutId);
|
|
84
|
+
};
|
|
85
|
+
}, [followWallClockEffective, flushCommittedSchedule, scheduleControlled]);
|
|
86
|
+
const setFollowWallClock = (0, import_react.useCallback)(
|
|
87
|
+
(value) => {
|
|
88
|
+
if (wallClockFollowLocked) return;
|
|
89
|
+
setFollowWallClockInternal(value);
|
|
90
|
+
},
|
|
91
|
+
[wallClockFollowLocked]
|
|
69
92
|
);
|
|
93
|
+
const onFollowWallClockToggle = (0, import_react.useCallback)(() => {
|
|
94
|
+
if (wallClockFollowLocked) return;
|
|
95
|
+
setFollowWallClockInternal((v) => !v);
|
|
96
|
+
}, [wallClockFollowLocked]);
|
|
97
|
+
const onTimeNavigatorUserInteraction = (0, import_react.useCallback)(() => {
|
|
98
|
+
if (wallClockFollowLocked) return;
|
|
99
|
+
setFollowWallClockInternal(false);
|
|
100
|
+
}, [wallClockFollowLocked]);
|
|
70
101
|
return {
|
|
71
|
-
followWallClock,
|
|
102
|
+
followWallClock: followWallClockEffective,
|
|
72
103
|
setFollowWallClock,
|
|
73
104
|
onFollowWallClockToggle,
|
|
74
105
|
onTimeNavigatorUserInteraction
|
|
@@ -165,4 +165,10 @@ export interface PisellReservationProps extends Omit<RecordBoardProps, 'toolBar'
|
|
|
165
165
|
bodyViewStorageKey?: string;
|
|
166
166
|
/** 点击平面图左上角 HUD 打开窄屏表格抽屉(画布已绑定资源行) */
|
|
167
167
|
floorMapHudTableDrawer?: boolean;
|
|
168
|
+
/**
|
|
169
|
+
* 强制「跟随当前时间」不可关闭(定时对齐墙钟、`getResourceBookingList` 与游标时间一致)。
|
|
170
|
+
* - **默认**:{@link lockedBodyView} 为 `resourceWall`,或用户在 RecordBoard 内**切换到「大屏 / resourceWall」子视图**时自动启用。
|
|
171
|
+
* - 设为 `true` 可在其它场景也强制跟随。
|
|
172
|
+
*/
|
|
173
|
+
forceFollowWallClock?: boolean;
|
|
168
174
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pisell/private-materials",
|
|
3
|
-
"version": "6.11.
|
|
3
|
+
"version": "6.11.181",
|
|
4
4
|
"main": "./lib/index.js",
|
|
5
5
|
"module": "./es/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -69,8 +69,8 @@
|
|
|
69
69
|
"styled-components": "^6.0.0-rc.3",
|
|
70
70
|
"@pisell/utils": "3.0.2",
|
|
71
71
|
"@pisell/materials": "6.11.57",
|
|
72
|
-
"@pisell/
|
|
73
|
-
"@pisell/
|
|
72
|
+
"@pisell/date-picker": "3.0.8",
|
|
73
|
+
"@pisell/icon": "0.0.11"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
76
|
"react": "^18.0.0",
|