@pisell/materials 1.8.34 → 1.8.36

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.
Files changed (86) hide show
  1. package/build/lowcode/assets-daily.json +11 -11
  2. package/build/lowcode/assets-dev.json +2 -2
  3. package/build/lowcode/assets-prod.json +11 -11
  4. package/build/lowcode/index.js +1 -1
  5. package/build/lowcode/meta.js +2 -2
  6. package/build/lowcode/preview.js +1 -1
  7. package/build/lowcode/render/default/view.css +1 -1
  8. package/build/lowcode/render/default/view.js +35 -35
  9. package/build/lowcode/view.css +1 -1
  10. package/build/lowcode/view.js +35 -35
  11. package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.js +25 -10
  12. package/es/components/pisellFloorMapLayout/appearance/floorMapAppearance.d.ts +4 -0
  13. package/es/components/pisellFloorMapLayout/appearance/floorMapAppearance.js +22 -0
  14. package/es/components/pisellFloorMapLayout/components/EditableItemLayer.js +3 -2
  15. package/es/components/pisellFloorMapLayout/components/ItemLayer.js +7 -4
  16. package/es/components/pisellFloorMapLayout/components/ItemLayer.less +10 -0
  17. package/es/components/pisellFloorMapLayout/components/ViewControls.js +6 -5
  18. package/es/components/pisellFloorMapLayout/components/ViewControls.less +29 -2
  19. package/es/components/pisellFloorMapLayout/components/ViewControlsWithZoom.js +1 -0
  20. package/es/components/pisellFloorMapLayout/context/mergeFloorMapLayoutContext.js +3 -1
  21. package/es/components/pisellFloorMapLayout/types.d.ts +21 -2
  22. package/es/components/pisellRecordBoard/index.d.ts +1 -1
  23. package/es/components/pisellRecordBoard/shellFrame/Calendar/BookingCalendar.js +280 -230
  24. package/es/components/pisellRecordBoard/shellFrame/Calendar/const/bookingCalendarConstants.js +18 -1
  25. package/es/components/pisellRecordBoard/shellFrame/Calendar/hooks/useBookingCalendarDayOverlayLayout.js +74 -0
  26. package/es/components/pisellRecordBoard/shellFrame/Calendar/modal/BookingCalendarBlockPanel.js +61 -0
  27. package/es/components/pisellRecordBoard/shellFrame/Calendar/modal/BookingCalendarOverflowListLayer.js +26 -0
  28. package/es/components/pisellRecordBoard/shellFrame/Calendar/utils/bookingCalendarDateUtils.js +11 -1
  29. package/es/components/pisellRecordBoard/shellFrame/Calendar/utils/bookingCalendarSelectionUtils.js +17 -0
  30. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarDaySelectionBar.js +12 -8
  31. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarDayView.js +3 -12
  32. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarResourceView.js +612 -0
  33. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/day/useBookingCalendarDayHourRemaining.js +33 -0
  34. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/day/useBookingCalendarDaySelection.js +37 -0
  35. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/resource/useBookingCalendarResourceCellToggle.js +18 -0
  36. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/resource/useBookingCalendarResourceDayHeaderRemaining.js +33 -0
  37. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/useBookingCalendarGoToDayFromCell.js +29 -0
  38. package/es/components/pisellRecordBoard/types.d.ts +38 -6
  39. package/es/components/pisellReservationSchedule/PisellReservationSchedule.js +19 -3
  40. package/es/components/pisellReservationSchedule/PisellReservationSchedule.less +23 -0
  41. package/es/index.d.ts +2 -2
  42. package/es/locales/en-US.js +6 -5
  43. package/es/locales/ja.js +1 -0
  44. package/es/locales/pt.js +1 -0
  45. package/es/locales/zh-CN.js +1 -0
  46. package/es/locales/zh-TW.js +1 -0
  47. package/es/pisell-materials.tw.css +2413 -2
  48. package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.js +25 -10
  49. package/lib/components/pisellFloorMapLayout/appearance/floorMapAppearance.d.ts +4 -0
  50. package/lib/components/pisellFloorMapLayout/appearance/floorMapAppearance.js +22 -0
  51. package/lib/components/pisellFloorMapLayout/components/EditableItemLayer.js +3 -2
  52. package/lib/components/pisellFloorMapLayout/components/ItemLayer.js +7 -4
  53. package/lib/components/pisellFloorMapLayout/components/ItemLayer.less +10 -0
  54. package/lib/components/pisellFloorMapLayout/components/ViewControls.js +6 -5
  55. package/lib/components/pisellFloorMapLayout/components/ViewControls.less +29 -2
  56. package/lib/components/pisellFloorMapLayout/components/ViewControlsWithZoom.js +1 -0
  57. package/lib/components/pisellFloorMapLayout/context/mergeFloorMapLayoutContext.js +3 -1
  58. package/lib/components/pisellFloorMapLayout/types.d.ts +21 -2
  59. package/lib/components/pisellRecordBoard/index.d.ts +1 -1
  60. package/lib/components/pisellRecordBoard/shellFrame/Calendar/BookingCalendar.js +277 -227
  61. package/lib/components/pisellRecordBoard/shellFrame/Calendar/const/bookingCalendarConstants.js +18 -0
  62. package/lib/components/pisellRecordBoard/shellFrame/Calendar/hooks/useBookingCalendarDayOverlayLayout.js +75 -0
  63. package/lib/components/pisellRecordBoard/shellFrame/Calendar/modal/BookingCalendarBlockPanel.js +63 -0
  64. package/lib/components/pisellRecordBoard/shellFrame/Calendar/modal/BookingCalendarOverflowListLayer.js +28 -0
  65. package/lib/components/pisellRecordBoard/shellFrame/Calendar/utils/bookingCalendarDateUtils.js +11 -1
  66. package/lib/components/pisellRecordBoard/shellFrame/Calendar/utils/bookingCalendarSelectionUtils.js +17 -0
  67. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarDaySelectionBar.js +12 -8
  68. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarDayView.js +3 -12
  69. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarResourceView.js +614 -0
  70. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/day/useBookingCalendarDayHourRemaining.js +34 -0
  71. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/day/useBookingCalendarDaySelection.js +38 -0
  72. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/resource/useBookingCalendarResourceCellToggle.js +19 -0
  73. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/resource/useBookingCalendarResourceDayHeaderRemaining.js +34 -0
  74. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/useBookingCalendarGoToDayFromCell.js +30 -0
  75. package/lib/components/pisellRecordBoard/types.d.ts +38 -6
  76. package/lib/components/pisellReservationSchedule/PisellReservationSchedule.js +19 -3
  77. package/lib/components/pisellReservationSchedule/PisellReservationSchedule.less +23 -0
  78. package/lib/index.d.ts +2 -2
  79. package/lib/locales/en-US.js +6 -5
  80. package/lib/locales/ja.js +1 -0
  81. package/lib/locales/pt.js +1 -0
  82. package/lib/locales/zh-CN.js +1 -0
  83. package/lib/locales/zh-TW.js +1 -0
  84. package/lib/pisell-materials.tw.css +2413 -2
  85. package/lowcode/pisell-record-board-calendar-view/meta.ts +8 -0
  86. package/package.json +1 -1
@@ -16,6 +16,23 @@ function dayCourtOverlayRowHeightPx(displayLaneCount) {
16
16
  const n = Math.max(1, displayLaneCount);
17
17
  return 16 + n * 64 + (n - 1) * 2;
18
18
  }
19
+ /**
20
+ * 资源视图:按某一格「courtDaySummary」结果估算该格所需最小高度(px)。
21
+ * 用于横向虚拟化仅挂载可见日期列时,仍按**全月**最大内容撑开行高,避免日程只在屏幕外列时出现行高塌陷。
22
+ */
23
+ function estimateResourceViewCourtCellHeightPx(summary) {
24
+ var _summary$items$length, _summary$items;
25
+ const pad = 8;
26
+ if (summary.fullyBooked) return 28 + pad;
27
+ const n = (_summary$items$length = (_summary$items = summary.items) === null || _summary$items === void 0 ? void 0 : _summary$items.length) !== null && _summary$items$length !== void 0 ? _summary$items$length : 0;
28
+ if (n === 0) return 44;
29
+ const previewCount = Math.min(3, n);
30
+ const showMoreTile = Math.max(0, n - 3) > 0 && previewCount > 0;
31
+ const gap = 4;
32
+ let content = previewCount * 48 + (previewCount > 1 ? (previewCount - 1) * gap : 0);
33
+ if (showMoreTile) content += gap + 48;
34
+ return pad + content;
35
+ }
19
36
  const MONTH_OVERFLOW_POPOVER_ITEM_H = 72;
20
37
  const OVERFLOW_MODAL_ROW_H = 108;
21
38
  //#endregion
@@ -24,3 +41,4 @@ exports.DEFAULT_CALENDAR_TIMELINE = DEFAULT_CALENDAR_TIMELINE;
24
41
  exports.MONTH_OVERFLOW_POPOVER_ITEM_H = MONTH_OVERFLOW_POPOVER_ITEM_H;
25
42
  exports.OVERFLOW_MODAL_ROW_H = OVERFLOW_MODAL_ROW_H;
26
43
  exports.dayCourtOverlayRowHeightPx = dayCourtOverlayRowHeightPx;
44
+ exports.estimateResourceViewCourtCellHeightPx = estimateResourceViewCourtCellHeightPx;
@@ -0,0 +1,75 @@
1
+ require("../../../../../_virtual/_rolldown/runtime.js");
2
+ const require_bookingCalendarConstants = require("../const/bookingCalendarConstants.js");
3
+ const require_bookingCalendarDateUtils = require("../utils/bookingCalendarDateUtils.js");
4
+ let react = require("react");
5
+ //#region src/components/pisellRecordBoard/shellFrame/Calendar/hooks/useBookingCalendarDayOverlayLayout.ts
6
+ /**
7
+ * 日视图:按 overlay 并行度计算行高、booking overlay 列表、+N 溢出汇总。
8
+ */
9
+ function useBookingCalendarDayOverlayLayout(visibleCourtRows, dayKey, bookings, hourSlots, slotStepHours) {
10
+ return (0, react.useMemo)(() => {
11
+ const defaultHeights = visibleCourtRows.map((row) => row.kind === "group" ? 38 : 44);
12
+ let overlays = require_bookingCalendarDateUtils.buildOverlayBookings(visibleCourtRows, dayKey, bookings, require_bookingCalendarDateUtils.buildDayRowTopMap(visibleCourtRows, defaultHeights), hourSlots, defaultHeights, slotStepHours);
13
+ const expandedHeights = visibleCourtRows.map((row, i) => {
14
+ if (row.kind !== "court") return defaultHeights[i];
15
+ if (!overlays.some((o) => o.courtId === row.id)) return defaultHeights[i];
16
+ return require_bookingCalendarConstants.dayCourtOverlayRowHeightPx(require_bookingCalendarDateUtils.effectiveDayOverlayDisplayLaneCount(require_bookingCalendarDateUtils.maxConcurrentBookingsOnCourt(overlays, row.id)));
17
+ });
18
+ const tops2 = require_bookingCalendarDateUtils.buildDayRowTopMap(visibleCourtRows, expandedHeights);
19
+ overlays = require_bookingCalendarDateUtils.buildOverlayBookings(visibleCourtRows, dayKey, bookings, tops2, hourSlots, expandedHeights, slotStepHours);
20
+ const courtDayDisplayLaneCount = {};
21
+ const hiddenDayOverlayIdSet = /* @__PURE__ */ new Set();
22
+ const dayOverlayOverflowPluses = [];
23
+ for (const row of visibleCourtRows) {
24
+ if (row.kind !== "court") continue;
25
+ const cid = row.id;
26
+ courtDayDisplayLaneCount[cid] = require_bookingCalendarDateUtils.effectiveDayOverlayDisplayLaneCount(require_bookingCalendarDateUtils.maxConcurrentBookingsOnCourt(overlays, cid));
27
+ const clusters = require_bookingCalendarDateUtils.clusterDayCourtOverlaysByOverlap(overlays, cid);
28
+ for (const cluster of clusters) {
29
+ if (cluster.length <= 3) continue;
30
+ const sortedByLane = [...cluster].sort((a, b) => {
31
+ var _a$lane, _b$lane;
32
+ return ((_a$lane = a.lane) !== null && _a$lane !== void 0 ? _a$lane : 0) - ((_b$lane = b.lane) !== null && _b$lane !== void 0 ? _b$lane : 0) || a.start - b.start;
33
+ });
34
+ for (let i = 3; i < sortedByLane.length; i++) {
35
+ const o = sortedByLane[i];
36
+ hiddenDayOverlayIdSet.add(require_bookingCalendarDateUtils.dayOverlayHiddenKey(o.item, dayKey, o.courtId));
37
+ }
38
+ const hidden = sortedByLane.slice(3);
39
+ let minS = Infinity;
40
+ let maxE = -Infinity;
41
+ for (const o of cluster) {
42
+ minS = Math.min(minS, o.start);
43
+ maxE = Math.max(maxE, o.start + o.span);
44
+ }
45
+ const anchor = hidden[0];
46
+ dayOverlayOverflowPluses.push({
47
+ key: `${cid}-${minS}-${maxE}-${dayKey}`,
48
+ courtId: cid,
49
+ rowTop: anchor.rowTop,
50
+ rowHeight: anchor.rowHeight,
51
+ start: minS,
52
+ span: maxE - minS,
53
+ plusCount: hidden.length,
54
+ overflowItems: hidden.map((o) => o.item)
55
+ });
56
+ }
57
+ }
58
+ return {
59
+ dayRowHeights: expandedHeights,
60
+ dayRowTopMap: tops2,
61
+ overlayBookings: overlays,
62
+ courtDayDisplayLaneCount,
63
+ hiddenDayOverlayIdSet,
64
+ dayOverlayOverflowPluses
65
+ };
66
+ }, [
67
+ visibleCourtRows,
68
+ dayKey,
69
+ bookings,
70
+ hourSlots,
71
+ slotStepHours
72
+ ]);
73
+ }
74
+ //#endregion
75
+ exports.useBookingCalendarDayOverlayLayout = useBookingCalendarDayOverlayLayout;
@@ -0,0 +1,63 @@
1
+ const require_runtime = require("../../../../../_virtual/_rolldown/runtime.js");
2
+ const require_calendarI18n = require("../calendarI18n.js");
3
+ let react = require("react");
4
+ react = require_runtime.__toESM(react);
5
+ let antd = require("antd");
6
+ let _ant_design_icons = require("@ant-design/icons");
7
+ //#region src/components/pisellRecordBoard/shellFrame/Calendar/modal/BookingCalendarBlockPanel.tsx
8
+ const { RangePicker } = antd.DatePicker;
9
+ /**
10
+ * 内置锁台 / 屏蔽时间表单(宿主未传 `onBlockedTimePanelRequest` 时使用)。
11
+ */
12
+ function BookingCalendarBlockPanel({ blockPanelRef, isLight, blockFormName, setBlockFormName, blockModalNote, setBlockModalNote, blockResourceId, setBlockResourceId, blockTimeRange, setBlockTimeRange, resolvedSlotMinutes, visibleCourts, blockSaving, onClose, onSave }) {
13
+ return /* @__PURE__ */ react.default.createElement("div", { className: "fixed inset-0 z-50 bg-black/55 backdrop-blur-sm flex items-end md:items-center justify-center p-2 md:p-4" }, /* @__PURE__ */ react.default.createElement("div", {
14
+ ref: blockPanelRef,
15
+ className: `w-full max-w-[720px] max-h-[92vh] overflow-y-auto rounded-t-3xl md:rounded-3xl border p-4 md:p-6 shadow-2xl ${isLight ? "theme-panel theme-border soft-shadow" : "border-zinc-700 bg-[#121217]"}`
16
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "mb-4 flex items-center justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: "text-xl font-semibold" }, require_calendarI18n.tCal("pisell2.recordBoard.calendar.block.panelTitle")), /* @__PURE__ */ react.default.createElement("button", {
17
+ type: "button",
18
+ "aria-label": require_calendarI18n.tCal("pisell2.recordBoard.calendar.block.closeAria"),
19
+ onClick: onClose,
20
+ className: `rounded-xl p-2 ${isLight ? "btn-neutral" : "border border-zinc-700 text-zinc-300"}`
21
+ }, /* @__PURE__ */ react.default.createElement(_ant_design_icons.CloseOutlined, { style: { fontSize: 20 } }))), /* @__PURE__ */ react.default.createElement("div", { className: `space-y-4 rounded-2xl border p-4 ${isLight ? "theme-panel-alt theme-border" : "border-zinc-700 bg-[#171820]"}` }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("label", { className: `mb-2 block text-sm ${isLight ? "theme-text-muted" : "text-zinc-400"}` }, require_calendarI18n.tCal("pisell2.recordBoard.calendar.block.fieldTitle")), /* @__PURE__ */ react.default.createElement("input", {
22
+ value: blockFormName,
23
+ onChange: (e) => setBlockFormName(e.target.value),
24
+ placeholder: require_calendarI18n.tCal("pisell2.recordBoard.calendar.block.placeholderTitle"),
25
+ className: `w-full rounded-xl px-3 py-2 outline-none ${isLight ? "theme-input theme-text" : "border border-zinc-700 bg-[#111218] text-white"}`
26
+ })), /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("label", { className: `mb-2 block text-sm ${isLight ? "theme-text-muted" : "text-zinc-400"}` }, "备注"), /* @__PURE__ */ react.default.createElement("input", {
27
+ value: blockModalNote,
28
+ onChange: (e) => setBlockModalNote(e.target.value),
29
+ placeholder: "选填",
30
+ className: `w-full rounded-xl px-3 py-2 outline-none ${isLight ? "theme-input theme-text" : "border border-zinc-700 bg-[#111218] text-white"}`
31
+ })), /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("label", { className: `mb-2 block text-sm ${isLight ? "theme-text-muted" : "text-zinc-400"}` }, require_calendarI18n.tCal("pisell2.recordBoard.calendar.block.fieldResource")), /* @__PURE__ */ react.default.createElement("select", {
32
+ value: blockResourceId,
33
+ onChange: (e) => setBlockResourceId(e.target.value),
34
+ className: `w-full rounded-xl px-3 py-2 outline-none ${isLight ? "theme-input theme-text" : "border border-zinc-700 bg-[#111218] text-white"}`
35
+ }, /* @__PURE__ */ react.default.createElement("option", { value: "" }, require_calendarI18n.tCal("pisell2.recordBoard.calendar.block.noResource")), visibleCourts.map((c) => /* @__PURE__ */ react.default.createElement("option", {
36
+ key: c.id,
37
+ value: String(c.id)
38
+ }, c.name)))), /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("label", { className: `mb-2 block text-sm ${isLight ? "theme-text-muted" : "text-zinc-400"}` }, require_calendarI18n.tCal("pisell2.recordBoard.calendar.block.fieldTimeRange")), /* @__PURE__ */ react.default.createElement(RangePicker, {
39
+ style: { width: "100%" },
40
+ showTime: {
41
+ format: "HH:mm",
42
+ minuteStep: resolvedSlotMinutes >= 60 ? 60 : Math.max(1, resolvedSlotMinutes)
43
+ },
44
+ format: "YYYY-MM-DD HH:mm",
45
+ value: blockTimeRange !== null && blockTimeRange !== void 0 ? blockTimeRange : void 0,
46
+ onChange: (v) => {
47
+ var _ref;
48
+ return setBlockTimeRange((_ref = v) !== null && _ref !== void 0 ? _ref : null);
49
+ }
50
+ }))), /* @__PURE__ */ react.default.createElement("div", { className: "mt-6 flex flex-col-reverse sm:flex-row items-stretch sm:items-center justify-end gap-3" }, /* @__PURE__ */ react.default.createElement("button", {
51
+ type: "button",
52
+ disabled: blockSaving,
53
+ onClick: onClose,
54
+ className: `rounded-xl px-4 py-2 ${isLight ? "btn-neutral" : "border border-zinc-700 text-zinc-300"}`
55
+ }, require_calendarI18n.tCal("pisell2.recordBoard.calendar.common.cancel")), /* @__PURE__ */ react.default.createElement("button", {
56
+ type: "button",
57
+ disabled: blockSaving,
58
+ onClick: () => void onSave(),
59
+ className: `rounded-xl px-5 py-3 text-sm font-semibold disabled:opacity-50 ${isLight ? "btn-brand" : "bg-violet-600 text-white"}`
60
+ }, blockSaving ? require_calendarI18n.tCal("pisell2.recordBoard.calendar.common.saving") : require_calendarI18n.tCal("pisell2.recordBoard.calendar.common.save")))));
61
+ }
62
+ //#endregion
63
+ exports.BookingCalendarBlockPanel = BookingCalendarBlockPanel;
@@ -0,0 +1,28 @@
1
+ const require_runtime = require("../../../../../_virtual/_rolldown/runtime.js");
2
+ const require_calendarI18n = require("../calendarI18n.js");
3
+ const require_OverflowListModal = require("./OverflowListModal.js");
4
+ let react = require("react");
5
+ react = require_runtime.__toESM(react);
6
+ //#region src/components/pisellRecordBoard/shellFrame/Calendar/modal/BookingCalendarOverflowListLayer.tsx
7
+ /**
8
+ * 全局溢出预约列表弹层(月/周/资源格 `+N` 点开后)。
9
+ */
10
+ function BookingCalendarOverflowListLayer({ overflowPanelRef, isLight, modal, onClose, onPickItem }) {
11
+ return /* @__PURE__ */ react.default.createElement("div", { className: "fixed inset-0 z-[69] bg-black/45 backdrop-blur-sm flex items-center justify-center p-4" }, /* @__PURE__ */ react.default.createElement("div", {
12
+ ref: overflowPanelRef,
13
+ className: `flex w-full max-w-[520px] max-h-[72vh] flex-col overflow-hidden rounded-3xl border p-5 shadow-2xl ${isLight ? "theme-panel theme-border soft-shadow" : "border-zinc-700 bg-[#121217]"}`
14
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "mb-4 flex shrink-0 items-start justify-between" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: "text-xl font-semibold" }, require_calendarI18n.tCal("pisell2.recordBoard.calendar.overflow.bookingsForDay")), /* @__PURE__ */ react.default.createElement("div", { className: "mt-1 text-sm text-zinc-400" }, modal.title)), /* @__PURE__ */ react.default.createElement("button", {
15
+ type: "button",
16
+ onClick: onClose,
17
+ className: "rounded-xl border border-zinc-700 px-3 py-2 text-zinc-300"
18
+ }, require_calendarI18n.tCal("pisell2.recordBoard.calendar.common.close"))), /* @__PURE__ */ react.default.createElement("div", { className: "min-h-0 flex-1 overflow-hidden px-0.5" }, /* @__PURE__ */ react.default.createElement(require_OverflowListModal.OverflowListModalVirtualList, {
19
+ items: modal.items,
20
+ dateKey: modal.date,
21
+ listWidth: 468,
22
+ onPickItem,
23
+ onClose,
24
+ showStatusUi: Boolean(modal.scope && String(modal.scope).startsWith("day-lane-overflow-"))
25
+ }))));
26
+ }
27
+ //#endregion
28
+ exports.BookingCalendarOverflowListLayer = BookingCalendarOverflowListLayer;
@@ -37,6 +37,16 @@ function rangeDays(anchor) {
37
37
  const start = startOfWeek(anchor);
38
38
  return Array.from({ length: 7 }, (_, i) => addDays(start, i));
39
39
  }
40
+ /**
41
+ * 锚定日所在自然月的每一天(1 号至月末),用于资源视图横向「日」列。
42
+ */
43
+ function monthCalendarDays(anchor) {
44
+ const base = anchor instanceof Date && !Number.isNaN(anchor.getTime()) ? anchor : /* @__PURE__ */ new Date();
45
+ const y = base.getFullYear();
46
+ const m = base.getMonth();
47
+ const last = new Date(y, m + 1, 0).getDate();
48
+ return Array.from({ length: last }, (_, i) => new Date(y, m, i + 1));
49
+ }
40
50
  function isHourInTimelineSlots(hour, hourSlots) {
41
51
  if (!(hourSlots === null || hourSlots === void 0 ? void 0 : hourSlots.length)) return false;
42
52
  return hourSlots.some((x) => Math.abs(x - hour) < 1e-6);
@@ -536,7 +546,6 @@ exports.fmtDate = fmtDate;
536
546
  exports.formatDateLoose = formatDateLoose;
537
547
  exports.formatHourLabel = formatHourLabel;
538
548
  exports.getBookingDetailData = getBookingDetailData;
539
- exports.getBookingSegmentForDate = getBookingSegmentForDate;
540
549
  exports.getDisplayStatusTag = getDisplayStatusTag;
541
550
  exports.getLateMinutes = getLateMinutes;
542
551
  exports.getViewNowReference = getViewNowReference;
@@ -544,6 +553,7 @@ exports.groupSelectedSlots = groupSelectedSlots;
544
553
  exports.isFreeSelectionContiguousSameResource = isFreeSelectionContiguousSameResource;
545
554
  exports.isHourInTimelineSlots = isHourInTimelineSlots;
546
555
  exports.maxConcurrentBookingsOnCourt = maxConcurrentBookingsOnCourt;
556
+ exports.monthCalendarDays = monthCalendarDays;
547
557
  exports.monthGrid = monthGrid;
548
558
  exports.parseDate = parseDate;
549
559
  exports.rangeDays = rangeDays;
@@ -0,0 +1,17 @@
1
+ //#region src/components/pisellRecordBoard/shellFrame/Calendar/utils/bookingCalendarSelectionUtils.ts
2
+ /**
3
+ * 资源视图选区是否「同一 court + 连续多天」:
4
+ * 仅当满足时才允许 Block / Create Booking(与日视图「同 court 连续多小时」语义对应)。
5
+ * 单天选中(n === 1)也算连续。
6
+ */
7
+ function isResourceSelectionContiguousSameCourt(selections) {
8
+ if (selections.length === 0) return false;
9
+ const courtId = selections[0].courtId;
10
+ if (selections.some((s) => s.courtId !== courtId)) return false;
11
+ if (selections.length === 1) return true;
12
+ const dates = [...selections].map((s) => s.dateKey).sort().map((s) => new Date(s).getTime());
13
+ for (let i = 1; i < dates.length; i += 1) if (Math.round((dates[i] - dates[i - 1]) / 864e5) !== 1) return false;
14
+ return true;
15
+ }
16
+ //#endregion
17
+ exports.isResourceSelectionContiguousSameCourt = isResourceSelectionContiguousSameCourt;
@@ -5,21 +5,25 @@ let react = require("react");
5
5
  react = require_runtime.__toESM(react);
6
6
  //#region src/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarDaySelectionBar.tsx
7
7
  /** 日视图底部:多选空闲 / 锁台后的固定操作条 */
8
- function BookingCalendarDaySelectionBar({ slotStepHours, selectedFreeSlots, selectedBlockSlots, deselectAll, openSelectedBlocks, onOpenBlockPanel, createBookingFromSelection }) {
9
- if (selectedFreeSlots.length === 0 && selectedBlockSlots.length === 0) return null;
8
+ function BookingCalendarDaySelectionBar({ slotStepHours, selectedFreeSlots, resourceSelectionSummary, deselectAll, onOpenBlockPanel, createBookingFromSelection }) {
9
+ if (!(resourceSelectionSummary != null ? resourceSelectionSummary.freePickCount > 0 : selectedFreeSlots.length > 0)) return null;
10
+ /**
11
+ * 是否允许「Block」与「Create booking」操作。
12
+ * - 资源视图:仅当同一 court 连续多天 → `freeAllowsBlockPanel = true`
13
+ * - 日视图:仅当同一 court 连续小时槽 → `isFreeSelectionContiguousSameResource = true`
14
+ *
15
+ * Create booking 与 Block 共用判定:散乱选择不允许任何创建动作。
16
+ */
17
+ const allowCreateOrBlock = resourceSelectionSummary != null ? resourceSelectionSummary.freeAllowsBlockPanel : require_bookingCalendarDateUtils.isFreeSelectionContiguousSameResource(selectedFreeSlots, slotStepHours);
10
18
  return /* @__PURE__ */ react.default.createElement("div", { className: "fixed bottom-6 left-1/2 z-50 -translate-x-1/2" }, /* @__PURE__ */ react.default.createElement("div", { className: "flex max-w-[92vw] flex-wrap items-center justify-center gap-3 rounded-2xl border border-white/10 bg-black/55 px-4 py-3 shadow-2xl shadow-black/40 backdrop-blur-xl" }, /* @__PURE__ */ react.default.createElement("button", {
11
19
  type: "button",
12
20
  onClick: deselectAll,
13
21
  className: "rounded-xl bg-red-500/85 px-4 py-2 text-sm font-semibold text-white"
14
- }, require_calendarI18n.tCal("pisell2.recordBoard.calendar.day.deselectAll")), selectedBlockSlots.length > 0 && /* @__PURE__ */ react.default.createElement("button", {
15
- type: "button",
16
- onClick: openSelectedBlocks,
17
- className: "rounded-xl bg-zinc-500/90 px-5 py-3 text-sm font-semibold text-white"
18
- }, require_calendarI18n.tCal("pisell2.recordBoard.calendar.day.openSlot")), selectedFreeSlots.length > 0 && require_bookingCalendarDateUtils.isFreeSelectionContiguousSameResource(selectedFreeSlots, slotStepHours) && /* @__PURE__ */ react.default.createElement("button", {
22
+ }, require_calendarI18n.tCal("pisell2.recordBoard.calendar.day.deselectAll")), allowCreateOrBlock && /* @__PURE__ */ react.default.createElement("button", {
19
23
  type: "button",
20
24
  onClick: onOpenBlockPanel,
21
25
  className: "rounded-xl bg-zinc-500/90 px-5 py-3 text-sm font-semibold text-white"
22
- }, require_calendarI18n.tCal("pisell2.recordBoard.calendar.day.block")), selectedFreeSlots.length > 0 && /* @__PURE__ */ react.default.createElement("button", {
26
+ }, require_calendarI18n.tCal("pisell2.recordBoard.calendar.day.block")), allowCreateOrBlock && /* @__PURE__ */ react.default.createElement("button", {
23
27
  type: "button",
24
28
  onClick: createBookingFromSelection,
25
29
  className: "rounded-xl bg-violet-600 px-6 py-3 text-sm font-semibold text-white"
@@ -6,7 +6,6 @@ const require_calendarI18n = require("../calendarI18n.js");
6
6
  const require_bookingCalendarDateUtils = require("../utils/bookingCalendarDateUtils.js");
7
7
  const require_bookingCalendarViewShared = require("../bookingCalendarViewShared.js");
8
8
  const require_BookingCalendarGroupRowHeader = require("./BookingCalendarGroupRowHeader.js");
9
- const require_BookingCalendarDaySelectionBar = require("./BookingCalendarDaySelectionBar.js");
10
9
  const require_bookingCalendarDayViewContext = require("./bookingCalendarDayViewContext.js");
11
10
  let react = require("react");
12
11
  react = require_runtime.__toESM(react);
@@ -17,7 +16,7 @@ let _ant_design_icons = require("@ant-design/icons");
17
16
  function BookingCalendarDayView(dayProps) {
18
17
  var _props$timelineHeader, _props$timelineHeader2, _props$timelineHeader3;
19
18
  const props = dayProps.calendarProps;
20
- const { isLight, view, anchorDate, dayKey, hourSlots, resolvedSlotMinutes, slotColWidth, firstTimelineHour, endTimelineExclusive, isBusinessHour, dayHourRemaining, timelinePxPerHour, dayContentHeight, dayRowHeights, visibleCourtRows, overlayBookings, dayOverlayOverflowPluses, setCollapsedGroups, visibleCourts, bookings, slotStepHours, isFreeSelected, isBlockSelected, toggleSlot, handleDropMove, hiddenDayOverlayIdSet, courtDayDisplayLaneCount, openBookingDetail, setDraggingItem, setNavDirection, commitAnchor, setFocusedCourtId, setOverflowListModal, selectedFreeSlots, selectedBlockSlots, deselectAll, openSelectedBlocks, onOpenBlockPanel, createBookingFromSelection, focusedCourtId, dayTimelineScrollToNowToken } = dayProps;
19
+ const { isLight, view, anchorDate, dayKey, hourSlots, resolvedSlotMinutes, slotColWidth, firstTimelineHour, endTimelineExclusive, isBusinessHour, dayHourRemaining, timelinePxPerHour, dayContentHeight, dayRowHeights, visibleCourtRows, overlayBookings, dayOverlayOverflowPluses, setCollapsedGroups, visibleCourts, bookings, slotStepHours, isFreeSelected, isBlockSelected, toggleSlot, handleDropMove, hiddenDayOverlayIdSet, courtDayDisplayLaneCount, openBookingDetail, setDraggingItem, setNavDirection, commitAnchor, setFocusedCourtId, setOverflowListModal, selectedFreeSlots, selectedBlockSlots, focusedCourtId, dayTimelineScrollToNowToken } = dayProps;
21
20
  const dayScrollRef = (0, react.useRef)(null);
22
21
  const dayBodyGridRef = (0, react.useRef)(null);
23
22
  const dayVirtRafRef = (0, react.useRef)(null);
@@ -497,7 +496,7 @@ function BookingCalendarDayView(dayProps) {
497
496
  handleDropMove(row.id, dayKey, hour);
498
497
  }
499
498
  },
500
- className: `relative flex h-full min-h-0 flex-col p-1 text-left transition outline-none ${isOccupied && !outsideBusiness ? "border-l-transparent border-b-transparent" : `border-b border-l ${isLight ? "theme-border" : "border-zinc-700"}`} ${outsideBusiness ? isLight ? "bg-slate-100 theme-text-faint" : "bg-zinc-800/80 text-zinc-500 border-zinc-700" : isBlock ? blockSelected ? "bg-red-500/25 border-red-400 ring-2 ring-red-400/60" : isLight ? "bg-red-50 border-red-200" : "bg-red-900/50 border-red-700/50" : isOccupied ? "bg-transparent" : freeSelected ? isLight ? "bg-violet-50 border-violet-300 ring-2 ring-violet-300/60" : "bg-white/10 border-violet-400 ring-2 ring-violet-400/60" : isLight ? "theme-grid-cell" : "bg-zinc-900 border-zinc-700"}`
499
+ className: `relative flex h-full min-h-0 flex-col p-1 text-left transition outline-none ${isOccupied && !outsideBusiness ? "border-l-transparent border-b-transparent" : `border-b border-l ${isLight ? "theme-border" : "border-zinc-700"}`} ${outsideBusiness ? isLight ? "bg-slate-100 theme-text-faint" : "bg-zinc-800/80 text-zinc-500 border-zinc-700" : isBlock ? blockSelected ? `bg-red-500/25 ring-1 ring-inset ring-red-400/75 border-b border-l ${isLight ? "theme-border" : "border-zinc-700"}` : isLight ? "bg-red-50 border-red-200" : "bg-red-900/50 border-red-700/50" : isOccupied ? "bg-transparent" : freeSelected ? isLight ? "bg-violet-50 ring-1 ring-inset ring-violet-400/75 border-b border-l theme-border" : "bg-white/10 ring-1 ring-inset ring-violet-400/70 border-b border-l border-zinc-700" : isLight ? "theme-grid-cell" : "bg-zinc-900 border-zinc-700"}`
501
500
  }, outsideBusiness ? /* @__PURE__ */ react.default.createElement("div", { className: "flex h-full items-center justify-center rounded-xl border border-dashed border-zinc-700 text-xs text-zinc-500" }, require_calendarI18n.tCal("pisell2.recordBoard.calendar.day.outsideHours")) : (item === null || item === void 0 ? void 0 : item.kind) === "block" ? /* @__PURE__ */ react.default.createElement("div", { className: "flex h-full w-full flex-col justify-center rounded-xl px-2.5 text-sm font-medium" }, /* @__PURE__ */ react.default.createElement("div", { className: "truncate" }, blockSelected ? require_calendarI18n.tCal("pisell2.recordBoard.calendar.day.selectedBlock") : item.name), item.note && /* @__PURE__ */ react.default.createElement("div", { className: "mt-1 text-xs text-zinc-300/90 truncate" }, item.note), require_bookingCalendarViewShared.getBlockMetaLine(item) && /* @__PURE__ */ react.default.createElement("div", { className: "mt-1 text-[10px] text-zinc-400 truncate" }, require_bookingCalendarViewShared.getBlockMetaLine(item))) : !item ? /* @__PURE__ */ react.default.createElement("div", { className: `${require_bookingCalendarConstants.CALENDAR_EMPTY_DASHED_SLOT_CLASSNAME} text-center ${isLight ? "border-[#d8d0eb] text-[#8f86a9]" : "border-zinc-700 text-zinc-500"}` }, freeSelected ? require_calendarI18n.tCal("pisell2.recordBoard.calendar.day.selected") : null) : null);
502
501
  })))), visibleDayOverlayBookings.map((booking) => {
503
502
  var _booking$rowHeight, _courtDayDisplayLaneC;
@@ -580,15 +579,7 @@ function BookingCalendarDayView(dayProps) {
580
579
  },
581
580
  className: `flex h-full w-full items-center justify-center rounded-xl px-1.5 text-sm font-semibold text-white shadow-sm ${isLight ? "bg-zinc-500/90" : "bg-zinc-600/90"}`
582
581
  }, "+", pill.plusCount));
583
- })))), /* @__PURE__ */ react.default.createElement(require_BookingCalendarDaySelectionBar.BookingCalendarDaySelectionBar, {
584
- slotStepHours,
585
- selectedFreeSlots,
586
- selectedBlockSlots,
587
- deselectAll,
588
- openSelectedBlocks,
589
- onOpenBlockPanel,
590
- createBookingFromSelection
591
- }))));
582
+ })))))));
592
583
  }
593
584
  //#endregion
594
585
  exports.BookingCalendarDayView = BookingCalendarDayView;