@pisell/pisellos 2.2.123 → 2.2.125

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.
@@ -0,0 +1,9 @@
1
+ // 导出评估器
2
+ export { PromotionEvaluator } from "./evaluator";
3
+
4
+ // 导出适配器
5
+ export { PromotionAdapter } from "./adapter";
6
+ export { default } from "./adapter";
7
+
8
+ // 导出策略配置示例常量
9
+ export { X_ITEMS_FOR_Y_PRICE_STRATEGY, BUY_X_GET_Y_FREE_STRATEGY } from "./examples";
@@ -49,5 +49,5 @@ export declare class Product extends BaseModule implements Module {
49
49
  getCategories(): ProductCategory[];
50
50
  setOtherParams(key: string, value: any): void;
51
51
  getOtherParams(): any;
52
- getProductType(): "normal" | "duration" | "session";
52
+ getProductType(): "duration" | "session" | "normal";
53
53
  }
@@ -0,0 +1,48 @@
1
+ import { Module, PisellCore, ModuleOptions } from '../../types';
2
+ import { BaseModule } from '../BaseModule';
3
+ import type { ScheduleItem } from '../Schedule/types';
4
+ import type { QuotationItem } from './types';
5
+ export type { QuotationItem, QuotationProductData, QuotationSchedule, QuotationState } from './types';
6
+ export declare class QuotationModule extends BaseModule implements Module {
7
+ protected defaultName: string;
8
+ protected defaultVersion: string;
9
+ private request;
10
+ private store;
11
+ private scheduleResolver?;
12
+ constructor(name?: string, version?: string);
13
+ initialize(core: PisellCore, options: ModuleOptions): Promise<void>;
14
+ loadQuotations(params?: {
15
+ channel?: string;
16
+ }): Promise<void>;
17
+ getQuotationList(): QuotationItem[];
18
+ /**
19
+ * Look up the quotation price for a specific product (+ optional variant) at a given datetime.
20
+ * Returns the price as a string (e.g. "300.00"), or null if no quotation applies.
21
+ *
22
+ * Priority: iterates quotations already sorted by `sort` ascending (lowest = highest priority).
23
+ * First matching quotation whose schedule covers `datetime` and whose product_data contains
24
+ * the requested productId wins.
25
+ */
26
+ getPriceForProduct(params: {
27
+ productId: number;
28
+ variantId?: number;
29
+ datetime: string;
30
+ }): string | null;
31
+ getQuotationShelfId(params: {
32
+ productId: number;
33
+ variantId?: number;
34
+ datetime: string;
35
+ }): number;
36
+ /**
37
+ * Batch pre-compute quotation prices for a set of products across multiple time points.
38
+ * Key format: `${productId}:${timePoint}`
39
+ * This avoids repeated schedule matching when the same product appears in multiple resource rows.
40
+ */
41
+ buildProductPriceMap(params: {
42
+ productIds: number[];
43
+ timePoints: string[];
44
+ }): Map<string, string | null>;
45
+ setScheduleResolver(resolver: (id: number) => ScheduleItem | undefined): void;
46
+ private isQuotationActiveAt;
47
+ private findProductData;
48
+ }
@@ -0,0 +1,248 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
5
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
6
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
7
+ function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
8
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
9
+ function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
10
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
11
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
12
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
13
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
14
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
15
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
16
+ function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
17
+ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
18
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
19
+ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
20
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
21
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
22
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
23
+ import { BaseModule } from "../BaseModule";
24
+ import { getDateIsInSchedule } from "../Schedule/getDateIsInSchedule";
25
+ export var QuotationModule = /*#__PURE__*/function (_BaseModule) {
26
+ _inherits(QuotationModule, _BaseModule);
27
+ var _super = _createSuper(QuotationModule);
28
+ function QuotationModule(name, version) {
29
+ var _this;
30
+ _classCallCheck(this, QuotationModule);
31
+ _this = _super.call(this, name, version);
32
+ _defineProperty(_assertThisInitialized(_this), "defaultName", 'quotation');
33
+ _defineProperty(_assertThisInitialized(_this), "defaultVersion", '1.0.0');
34
+ _defineProperty(_assertThisInitialized(_this), "request", void 0);
35
+ _defineProperty(_assertThisInitialized(_this), "store", {
36
+ list: []
37
+ });
38
+ _defineProperty(_assertThisInitialized(_this), "scheduleResolver", void 0);
39
+ return _this;
40
+ }
41
+ _createClass(QuotationModule, [{
42
+ key: "initialize",
43
+ value: function () {
44
+ var _initialize = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(core, options) {
45
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
46
+ while (1) switch (_context.prev = _context.next) {
47
+ case 0:
48
+ this.core = core;
49
+ this.request = core.getPlugin('request');
50
+ if (this.request) {
51
+ _context.next = 4;
52
+ break;
53
+ }
54
+ throw new Error('QuotationModule 需要 request 插件支持');
55
+ case 4:
56
+ this.store = {
57
+ list: []
58
+ };
59
+ case 5:
60
+ case "end":
61
+ return _context.stop();
62
+ }
63
+ }, _callee, this);
64
+ }));
65
+ function initialize(_x, _x2) {
66
+ return _initialize.apply(this, arguments);
67
+ }
68
+ return initialize;
69
+ }()
70
+ }, {
71
+ key: "loadQuotations",
72
+ value: function () {
73
+ var _loadQuotations = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(params) {
74
+ var _data;
75
+ var query, res, list;
76
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
77
+ while (1) switch (_context2.prev = _context2.next) {
78
+ case 0:
79
+ query = {};
80
+ if (params !== null && params !== void 0 && params.channel) query.channel = params.channel;
81
+ if ((params === null || params === void 0 ? void 0 : params.channel) === 'online_store') {
82
+ query.channel = 'online-store';
83
+ }
84
+ _context2.next = 5;
85
+ return this.request.get('/quotation/available', query, {
86
+ useCache: false
87
+ });
88
+ case 5:
89
+ res = _context2.sent;
90
+ list = (res === null || res === void 0 || (_data = res.data) === null || _data === void 0 ? void 0 : _data.list) || (res === null || res === void 0 ? void 0 : res.list) || [];
91
+ list.sort(function (a, b) {
92
+ return a.sort - b.sort;
93
+ });
94
+ this.store.list = list;
95
+ case 9:
96
+ case "end":
97
+ return _context2.stop();
98
+ }
99
+ }, _callee2, this);
100
+ }));
101
+ function loadQuotations(_x3) {
102
+ return _loadQuotations.apply(this, arguments);
103
+ }
104
+ return loadQuotations;
105
+ }()
106
+ }, {
107
+ key: "getQuotationList",
108
+ value: function getQuotationList() {
109
+ return this.store.list;
110
+ }
111
+
112
+ /**
113
+ * Look up the quotation price for a specific product (+ optional variant) at a given datetime.
114
+ * Returns the price as a string (e.g. "300.00"), or null if no quotation applies.
115
+ *
116
+ * Priority: iterates quotations already sorted by `sort` ascending (lowest = highest priority).
117
+ * First matching quotation whose schedule covers `datetime` and whose product_data contains
118
+ * the requested productId wins.
119
+ */
120
+ }, {
121
+ key: "getPriceForProduct",
122
+ value: function getPriceForProduct(params) {
123
+ var productId = params.productId,
124
+ variantId = params.variantId,
125
+ datetime = params.datetime;
126
+ var _iterator = _createForOfIteratorHelper(this.store.list),
127
+ _step;
128
+ try {
129
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
130
+ var quotation = _step.value;
131
+ if (!this.isQuotationActiveAt(quotation, datetime)) continue;
132
+ var match = this.findProductData(quotation.product_data, productId, variantId);
133
+ if (!match) continue;
134
+ if (match.value === 0) continue;
135
+ return String(match.value);
136
+ }
137
+ } catch (err) {
138
+ _iterator.e(err);
139
+ } finally {
140
+ _iterator.f();
141
+ }
142
+ return null;
143
+ }
144
+ }, {
145
+ key: "getQuotationShelfId",
146
+ value: function getQuotationShelfId(params) {
147
+ var productId = params.productId,
148
+ variantId = params.variantId,
149
+ datetime = params.datetime;
150
+ var _iterator2 = _createForOfIteratorHelper(this.store.list),
151
+ _step2;
152
+ try {
153
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
154
+ var quotation = _step2.value;
155
+ if (!this.isQuotationActiveAt(quotation, datetime)) continue;
156
+ var match = this.findProductData(quotation.product_data, productId, variantId);
157
+ if (!match || match.value === 0) continue;
158
+ return quotation.id;
159
+ }
160
+ } catch (err) {
161
+ _iterator2.e(err);
162
+ } finally {
163
+ _iterator2.f();
164
+ }
165
+ return 0;
166
+ }
167
+
168
+ /**
169
+ * Batch pre-compute quotation prices for a set of products across multiple time points.
170
+ * Key format: `${productId}:${timePoint}`
171
+ * This avoids repeated schedule matching when the same product appears in multiple resource rows.
172
+ */
173
+ }, {
174
+ key: "buildProductPriceMap",
175
+ value: function buildProductPriceMap(params) {
176
+ var map = new Map();
177
+ if (!this.store.list.length) return map;
178
+ var _iterator3 = _createForOfIteratorHelper(params.productIds),
179
+ _step3;
180
+ try {
181
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
182
+ var productId = _step3.value;
183
+ var _iterator4 = _createForOfIteratorHelper(params.timePoints),
184
+ _step4;
185
+ try {
186
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
187
+ var timePoint = _step4.value;
188
+ var key = "".concat(productId, ":").concat(timePoint);
189
+ var price = this.getPriceForProduct({
190
+ productId: productId,
191
+ datetime: timePoint
192
+ });
193
+ if (price !== null) {
194
+ map.set(key, price);
195
+ }
196
+ }
197
+ } catch (err) {
198
+ _iterator4.e(err);
199
+ } finally {
200
+ _iterator4.f();
201
+ }
202
+ }
203
+ } catch (err) {
204
+ _iterator3.e(err);
205
+ } finally {
206
+ _iterator3.f();
207
+ }
208
+ return map;
209
+ }
210
+ }, {
211
+ key: "setScheduleResolver",
212
+ value: function setScheduleResolver(resolver) {
213
+ this.scheduleResolver = resolver;
214
+ }
215
+ }, {
216
+ key: "isQuotationActiveAt",
217
+ value: function isQuotationActiveAt(quotation, datetime) {
218
+ var _quotation$schedule,
219
+ _this2 = this;
220
+ if (!((_quotation$schedule = quotation.schedule) !== null && _quotation$schedule !== void 0 && _quotation$schedule.length)) return false;
221
+ var scheduleItems = quotation.schedule.map(function (s) {
222
+ var _this2$scheduleResolv;
223
+ var full = (_this2$scheduleResolv = _this2.scheduleResolver) === null || _this2$scheduleResolv === void 0 ? void 0 : _this2$scheduleResolv.call(_this2, s.id);
224
+ if (full) return full;
225
+ return _objectSpread(_objectSpread({}, s), {}, {
226
+ repeat_type: s.repeat_type || 'none',
227
+ repeat_rule: s.repeat_rule || null,
228
+ time_slot: s.time_slot || []
229
+ });
230
+ });
231
+ return getDateIsInSchedule(datetime, scheduleItems);
232
+ }
233
+ }, {
234
+ key: "findProductData",
235
+ value: function findProductData(productData, productId, variantId) {
236
+ if (variantId && variantId !== 0) {
237
+ var variantMatch = productData.find(function (p) {
238
+ return p.product_id === productId && p.variant_id === variantId;
239
+ });
240
+ if (variantMatch) return variantMatch;
241
+ }
242
+ return productData.find(function (p) {
243
+ return p.product_id === productId && p.variant_id === 0;
244
+ });
245
+ }
246
+ }]);
247
+ return QuotationModule;
248
+ }(BaseModule);
@@ -0,0 +1,42 @@
1
+ export interface QuotationProductData {
2
+ id: number;
3
+ shelf_id: number;
4
+ product_id: number;
5
+ variant_id: number;
6
+ type: string;
7
+ value: number;
8
+ }
9
+ export interface QuotationSchedule {
10
+ id: number;
11
+ name: string;
12
+ type: 'standard' | 'time-slots' | 'designation';
13
+ start_time: string;
14
+ end_time: string;
15
+ is_all: number;
16
+ repeat_type?: string;
17
+ repeat_rule?: any;
18
+ designation?: any;
19
+ time_slot?: Array<{
20
+ start_time: string;
21
+ end_time: string;
22
+ }>;
23
+ pivot?: Record<string, any>;
24
+ }
25
+ export interface QuotationItem {
26
+ id: number;
27
+ shop_id: number;
28
+ shelf_type_id?: number;
29
+ name: string;
30
+ description?: string;
31
+ status: string;
32
+ sort: number;
33
+ channel: string[];
34
+ created_at?: string;
35
+ updated_at?: string;
36
+ deleted_at?: string | null;
37
+ schedule: QuotationSchedule[];
38
+ product_data: QuotationProductData[];
39
+ }
40
+ export interface QuotationState {
41
+ list: QuotationItem[];
42
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -206,7 +206,9 @@ declare class Server {
206
206
  */
207
207
  private shouldUseLocalBookingQuery;
208
208
  /**
209
- * 日历 SSE 精简 with:只拉日历渲染必需的关联字段
209
+ * 日历 SSE 精简 with:由调用方显式声明 compact_fields 决定
210
+ * - compact_fields === true → 精简字段(周/月视图)
211
+ * - 其余(false / 未传)→ ['all'](日视图/表格/平面图合并)
210
212
  */
211
213
  private resolveBookingSalesWith;
212
214
  /**
@@ -214,6 +216,11 @@ declare class Server {
214
216
  * business_code / payment_status 不直接用于渲染,但 matchOrder 过滤依赖
215
217
  */
216
218
  private resolveBookingSalesSelect;
219
+ /**
220
+ * 日历(compact_fields)场景下要直接在 SSE 层排除的订单类型:
221
+ * 这些类型不会出现在日历上,拉取它们只会浪费带宽并增加前端过滤成本。
222
+ */
223
+ private readonly BOOKING_SALES_COMPACT_EXCLUDE_TYPES;
217
224
  private normalizeBookingRemoteQueryPayload;
218
225
  /**
219
226
  * 远端预约查询内存缓存开关:默认 false,仅显式 true 才启用。
@@ -325,6 +325,11 @@ var Server = /*#__PURE__*/function () {
325
325
  return _ref11.apply(this, arguments);
326
326
  };
327
327
  }());
328
+ /**
329
+ * 日历(compact_fields)场景下要直接在 SSE 层排除的订单类型:
330
+ * 这些类型不会出现在日历上,拉取它们只会浪费带宽并增加前端过滤成本。
331
+ */
332
+ _defineProperty(this, "BOOKING_SALES_COMPACT_EXCLUDE_TYPES", ['virtual', 'shipping', 'delivery', 'pickup']);
328
333
  /**
329
334
  * 处理预约列表查询
330
335
  * 今天:注册订阅者 + 本地数据筛选;非今天:清理订阅者 + 走真实 API
@@ -1647,12 +1652,19 @@ var Server = /*#__PURE__*/function () {
1647
1652
  }
1648
1653
 
1649
1654
  /**
1650
- * 日历 SSE 精简 with:只拉日历渲染必需的关联字段
1655
+ * 日历 SSE 精简 with:由调用方显式声明 compact_fields 决定
1656
+ * - compact_fields === true → 精简字段(周/月视图)
1657
+ * - 其余(false / 未传)→ ['all'](日视图/表格/平面图合并)
1651
1658
  */
1652
1659
  }, {
1653
1660
  key: "resolveBookingSalesWith",
1654
- value: function resolveBookingSalesWith(_queryPayload) {
1655
- return ['bookings:booking_id,start_date,start_time,end_date,end_time,holder,metadata,parent_id,item_type', 'customer:id,display_name,phone', 'products'];
1661
+ value: function resolveBookingSalesWith(queryPayload) {
1662
+ if ((queryPayload === null || queryPayload === void 0 ? void 0 : queryPayload.compact_fields) === true) {
1663
+ return ['bookings:booking_id,start_date,start_time,end_date,end_time,holder,metadata,parent_id,item_type', 'customer:id,display_name,phone', 'products'
1664
+ // 'resources'
1665
+ ];
1666
+ }
1667
+ return ['all'];
1656
1668
  }
1657
1669
 
1658
1670
  /**
@@ -1667,11 +1679,18 @@ var Server = /*#__PURE__*/function () {
1667
1679
  }, {
1668
1680
  key: "normalizeBookingRemoteQueryPayload",
1669
1681
  value: function normalizeBookingRemoteQueryPayload(data, withFields) {
1670
- return _objectSpread(_objectSpread({}, data), {}, {
1682
+ var isFullWith = withFields.length === 1 && withFields[0] === 'all';
1683
+ var isCompact = (data === null || data === void 0 ? void 0 : data.compact_fields) === true;
1684
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, data), {}, {
1671
1685
  form_record_ids: undefined,
1672
1686
  enable_remote_memory_cache: undefined,
1673
- with: withFields,
1674
- select: this.resolveBookingSalesSelect(),
1687
+ compact_fields: undefined,
1688
+ with: withFields
1689
+ }, isFullWith ? {} : {
1690
+ select: this.resolveBookingSalesSelect()
1691
+ }), isCompact ? {
1692
+ exclude_types: this.BOOKING_SALES_COMPACT_EXCLUDE_TYPES
1693
+ } : {}), {}, {
1675
1694
  chunk_size: 50
1676
1695
  });
1677
1696
  }
@@ -136,7 +136,7 @@ export declare class BookingTicketImpl extends BaseModule implements Module {
136
136
  * 获取当前的客户搜索条件
137
137
  * @returns 当前搜索条件
138
138
  */
139
- getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
139
+ getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "skip" | "num">;
140
140
  /**
141
141
  * 获取客户列表状态(包含滚动加载相关状态)
142
142
  * @returns 客户状态
@@ -86,12 +86,41 @@ export declare class SalesImpl extends BaseModule implements Module, SalesModule
86
86
  */
87
87
  private pickBookingsForCurrentPoint;
88
88
  /**
89
- * 标准化单条 booking
90
- * - 过滤终态(rejected/cancelled/completed)
91
- * - deviceTime 早于 currentTime 时,过滤 end_time 早于 currentTime 的历史数据
92
- * - 注入 status / isTimeout / reserved_status
89
+ * 计算 booking 在 current 时刻的执行进度百分比(0-100)。
90
+ * - startAt/endAt 非法或 totalMinutes <= 0 返回 0
91
+ * - current 早于 startAt 返回 0,晚于 endAt 返回 100
92
+ */
93
+ private calcProgressPercent;
94
+ /**
95
+ * 标准化单条 booking 的分发入口:
96
+ * - 统一过滤 rejected / cancelled(视为没来过)
97
+ * - current === deviceCurrent 走实时分支(信任 appointment_status)
98
+ * - 否则走快照分支(纯时间窗判定,忽略 appointment_status 的 arrived/started/completed 差异)
93
99
  */
94
100
  private normalizeMatchedBooking;
101
+ /**
102
+ * 实时模式(current === deviceCurrent):信任 appointment_status
103
+ * - 过滤 new / completed(实时视角下视为非活跃数据)
104
+ * - status 由 getBookingStatus 映射
105
+ * - occupied 且 current > endAt 标记 isTimeout + timeoutTime
106
+ * - reserved 且 current < startAt 标记 not_arrived,否则标记 late
107
+ */
108
+ private buildRealtimeBooking;
109
+ /**
110
+ * 快照模式(current !== deviceCurrent,过去或未来):忽略 appointment_status
111
+ * 的实时态差异,仅按 booking 时间窗判定,为 current 提供时间点快照视图。
112
+ *
113
+ * - new:视作尚未成为真实预约,过滤
114
+ * - locked:保留 status=locked,不计算 timeout/late/progress
115
+ * - 其他非终态:
116
+ * - startAt/endAt 非法 → 过滤
117
+ * - current > endAt → 过滤(已结束,不入池)
118
+ * - current ∈ [startAt, endAt] → occupied,附带 progressPercent
119
+ * - current < startAt → reserved + not_arrived,附带 remainingReserveTime
120
+ *
121
+ * 快照模式下 isTimeout 恒为 false,lateTime / timeoutTime 始终置空。
122
+ */
123
+ private buildSnapshotBooking;
95
124
  getResourceBookingList(currentTime: string, bookingList?: BookingData[], deviceTime?: string): Promise<SalesResourceBookingItem[]>;
96
125
  }
97
126
  export { SalesImpl as Sales };
@@ -429,36 +429,57 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
429
429
  }
430
430
 
431
431
  /**
432
- * 标准化单条 booking
433
- * - 过滤终态(rejected/cancelled/completed)
434
- * - deviceTime 早于 currentTime 时,过滤 end_time 早于 currentTime 的历史数据
435
- * - 注入 status / isTimeout / reserved_status
432
+ * 计算 booking 在 current 时刻的执行进度百分比(0-100)。
433
+ * - startAt/endAt 非法或 totalMinutes <= 0 返回 0
434
+ * - current 早于 startAt 返回 0,晚于 endAt 返回 100
435
+ */
436
+ }, {
437
+ key: "calcProgressPercent",
438
+ value: function calcProgressPercent(current, startAt, endAt) {
439
+ if (!startAt.isValid() || !endAt.isValid()) return 0;
440
+ var totalMinutes = endAt.diff(startAt, 'minute');
441
+ if (totalMinutes <= 0) return 0;
442
+ var elapsedMinutes = current.diff(startAt, 'minute');
443
+ if (elapsedMinutes <= 0) return 0;
444
+ if (elapsedMinutes >= totalMinutes) return 100;
445
+ return Math.floor(elapsedMinutes / totalMinutes * 100);
446
+ }
447
+
448
+ /**
449
+ * 标准化单条 booking 的分发入口:
450
+ * - 统一过滤 rejected / cancelled(视为没来过)
451
+ * - current === deviceCurrent 走实时分支(信任 appointment_status)
452
+ * - 否则走快照分支(纯时间窗判定,忽略 appointment_status 的 arrived/started/completed 差异)
436
453
  */
437
454
  }, {
438
455
  key: "normalizeMatchedBooking",
439
456
  value: function normalizeMatchedBooking(current, deviceCurrent, booking) {
440
457
  var _ref3, _booking$appointment_;
441
458
  var appointmentStatus = String((_ref3 = (_booking$appointment_ = booking.appointment_status) !== null && _booking$appointment_ !== void 0 ? _booking$appointment_ : booking.status) !== null && _ref3 !== void 0 ? _ref3 : '');
442
- if (appointmentStatus === 'new' || appointmentStatus === 'rejected' || appointmentStatus === 'cancelled' || appointmentStatus === 'completed') {
443
- return null;
444
- }
459
+ if (appointmentStatus === 'rejected' || appointmentStatus === 'cancelled') return null;
460
+ var startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
445
461
  var endAt = this.toBookingDateTime(booking.end_date, booking.end_time);
446
- var shouldFilterHistoryByCurrent = deviceCurrent.isBefore(current);
447
- if (shouldFilterHistoryByCurrent && endAt.isValid() && endAt.isBefore(current)) return null;
462
+ if (current.isSame(deviceCurrent)) {
463
+ return this.buildRealtimeBooking(current, booking, appointmentStatus, startAt, endAt);
464
+ }
465
+ return this.buildSnapshotBooking(current, booking, appointmentStatus, startAt, endAt);
466
+ }
467
+
468
+ /**
469
+ * 实时模式(current === deviceCurrent):信任 appointment_status
470
+ * - 过滤 new / completed(实时视角下视为非活跃数据)
471
+ * - status 由 getBookingStatus 映射
472
+ * - occupied 且 current > endAt 标记 isTimeout + timeoutTime
473
+ * - reserved 且 current < startAt 标记 not_arrived,否则标记 late
474
+ */
475
+ }, {
476
+ key: "buildRealtimeBooking",
477
+ value: function buildRealtimeBooking(current, booking, appointmentStatus, startAt, endAt) {
478
+ if (appointmentStatus === 'new' || appointmentStatus === 'completed') return null;
448
479
  var bookingStatus = this.getBookingStatus(appointmentStatus);
449
- var startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
450
480
  var isTimeout = bookingStatus === 'occupied' && endAt.isValid() && current.isAfter(endAt);
451
481
  var timeoutTime = isTimeout ? current.diff(endAt, 'minute') : undefined;
452
- var progressPercent = function () {
453
- if (bookingStatus !== 'occupied') return 0;
454
- if (!startAt.isValid() || !endAt.isValid()) return 0;
455
- var totalMinutes = endAt.diff(startAt, 'minute');
456
- if (totalMinutes <= 0) return 0;
457
- var elapsedMinutes = current.diff(startAt, 'minute');
458
- if (elapsedMinutes <= 0) return 0;
459
- if (elapsedMinutes >= totalMinutes) return 100;
460
- return Math.floor(elapsedMinutes / totalMinutes * 100);
461
- }();
482
+ var progressPercent = bookingStatus === 'occupied' ? this.calcProgressPercent(current, startAt, endAt) : 0;
462
483
  var reservedStatus;
463
484
  var lateTime;
464
485
  var remainingReserveTime;
@@ -471,24 +492,6 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
471
492
  lateTime = Math.max(current.diff(startAt, 'minute'), 0);
472
493
  }
473
494
  }
474
- // 未来查询投影:查询时间晚于设备时间时,预留+迟到且 end_time 仍在查询时间之后的预约强制视为占用
475
- if (current.isAfter(deviceCurrent) && bookingStatus === 'reserved' && reservedStatus === 'late' && endAt.isValid() && endAt.isSameOrAfter(current)) {
476
- bookingStatus = 'occupied';
477
- reservedStatus = undefined;
478
- lateTime = undefined;
479
- remainingReserveTime = undefined;
480
- isTimeout = false;
481
- timeoutTime = undefined;
482
- progressPercent = function () {
483
- if (!startAt.isValid() || !endAt.isValid()) return 0;
484
- var totalMinutes = endAt.diff(startAt, 'minute');
485
- if (totalMinutes <= 0) return 0;
486
- var elapsedMinutes = current.diff(startAt, 'minute');
487
- if (elapsedMinutes <= 0) return 0;
488
- if (elapsedMinutes >= totalMinutes) return 100;
489
- return Math.floor(elapsedMinutes / totalMinutes * 100);
490
- }();
491
- }
492
495
  return _objectSpread(_objectSpread({}, booking), {}, {
493
496
  status: bookingStatus,
494
497
  isTimeout: isTimeout,
@@ -499,6 +502,59 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
499
502
  remainingReserveTime: remainingReserveTime
500
503
  });
501
504
  }
505
+
506
+ /**
507
+ * 快照模式(current !== deviceCurrent,过去或未来):忽略 appointment_status
508
+ * 的实时态差异,仅按 booking 时间窗判定,为 current 提供时间点快照视图。
509
+ *
510
+ * - new:视作尚未成为真实预约,过滤
511
+ * - locked:保留 status=locked,不计算 timeout/late/progress
512
+ * - 其他非终态:
513
+ * - startAt/endAt 非法 → 过滤
514
+ * - current > endAt → 过滤(已结束,不入池)
515
+ * - current ∈ [startAt, endAt] → occupied,附带 progressPercent
516
+ * - current < startAt → reserved + not_arrived,附带 remainingReserveTime
517
+ *
518
+ * 快照模式下 isTimeout 恒为 false,lateTime / timeoutTime 始终置空。
519
+ */
520
+ }, {
521
+ key: "buildSnapshotBooking",
522
+ value: function buildSnapshotBooking(current, booking, appointmentStatus, startAt, endAt) {
523
+ if (appointmentStatus === 'new') return null;
524
+ if (appointmentStatus === 'locked') {
525
+ return _objectSpread(_objectSpread({}, booking), {}, {
526
+ status: 'locked',
527
+ isTimeout: false,
528
+ timeoutTime: undefined,
529
+ progressPercent: 0,
530
+ lateTime: undefined,
531
+ reserved_status: undefined,
532
+ remainingReserveTime: undefined
533
+ });
534
+ }
535
+ if (!startAt.isValid() || !endAt.isValid()) return null;
536
+ if (current.isAfter(endAt)) return null;
537
+ if (this.isSameOrAfter(current, startAt) && this.isSameOrBefore(current, endAt)) {
538
+ return _objectSpread(_objectSpread({}, booking), {}, {
539
+ status: 'occupied',
540
+ isTimeout: false,
541
+ timeoutTime: undefined,
542
+ progressPercent: this.calcProgressPercent(current, startAt, endAt),
543
+ lateTime: undefined,
544
+ reserved_status: undefined,
545
+ remainingReserveTime: undefined
546
+ });
547
+ }
548
+ return _objectSpread(_objectSpread({}, booking), {}, {
549
+ status: 'reserved',
550
+ isTimeout: false,
551
+ timeoutTime: undefined,
552
+ progressPercent: 0,
553
+ lateTime: undefined,
554
+ reserved_status: 'not_arrived',
555
+ remainingReserveTime: Math.max(startAt.diff(current, 'minute'), 0)
556
+ });
557
+ }
502
558
  }, {
503
559
  key: "getResourceBookingList",
504
560
  value: function () {
@@ -49,5 +49,5 @@ export declare class Product extends BaseModule implements Module {
49
49
  getCategories(): ProductCategory[];
50
50
  setOtherParams(key: string, value: any): void;
51
51
  getOtherParams(): any;
52
- getProductType(): "normal" | "duration" | "session";
52
+ getProductType(): "duration" | "session" | "normal";
53
53
  }
@@ -0,0 +1,48 @@
1
+ import { Module, PisellCore, ModuleOptions } from '../../types';
2
+ import { BaseModule } from '../BaseModule';
3
+ import type { ScheduleItem } from '../Schedule/types';
4
+ import type { QuotationItem } from './types';
5
+ export type { QuotationItem, QuotationProductData, QuotationSchedule, QuotationState } from './types';
6
+ export declare class QuotationModule extends BaseModule implements Module {
7
+ protected defaultName: string;
8
+ protected defaultVersion: string;
9
+ private request;
10
+ private store;
11
+ private scheduleResolver?;
12
+ constructor(name?: string, version?: string);
13
+ initialize(core: PisellCore, options: ModuleOptions): Promise<void>;
14
+ loadQuotations(params?: {
15
+ channel?: string;
16
+ }): Promise<void>;
17
+ getQuotationList(): QuotationItem[];
18
+ /**
19
+ * Look up the quotation price for a specific product (+ optional variant) at a given datetime.
20
+ * Returns the price as a string (e.g. "300.00"), or null if no quotation applies.
21
+ *
22
+ * Priority: iterates quotations already sorted by `sort` ascending (lowest = highest priority).
23
+ * First matching quotation whose schedule covers `datetime` and whose product_data contains
24
+ * the requested productId wins.
25
+ */
26
+ getPriceForProduct(params: {
27
+ productId: number;
28
+ variantId?: number;
29
+ datetime: string;
30
+ }): string | null;
31
+ getQuotationShelfId(params: {
32
+ productId: number;
33
+ variantId?: number;
34
+ datetime: string;
35
+ }): number;
36
+ /**
37
+ * Batch pre-compute quotation prices for a set of products across multiple time points.
38
+ * Key format: `${productId}:${timePoint}`
39
+ * This avoids repeated schedule matching when the same product appears in multiple resource rows.
40
+ */
41
+ buildProductPriceMap(params: {
42
+ productIds: number[];
43
+ timePoints: string[];
44
+ }): Map<string, string | null>;
45
+ setScheduleResolver(resolver: (id: number) => ScheduleItem | undefined): void;
46
+ private isQuotationActiveAt;
47
+ private findProductData;
48
+ }
@@ -0,0 +1,152 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/modules/Quotation/index.ts
20
+ var Quotation_exports = {};
21
+ __export(Quotation_exports, {
22
+ QuotationModule: () => QuotationModule
23
+ });
24
+ module.exports = __toCommonJS(Quotation_exports);
25
+ var import_BaseModule = require("../BaseModule");
26
+ var import_getDateIsInSchedule = require("../Schedule/getDateIsInSchedule");
27
+ var QuotationModule = class extends import_BaseModule.BaseModule {
28
+ constructor(name, version) {
29
+ super(name, version);
30
+ this.defaultName = "quotation";
31
+ this.defaultVersion = "1.0.0";
32
+ this.store = { list: [] };
33
+ }
34
+ async initialize(core, options) {
35
+ this.core = core;
36
+ this.request = core.getPlugin("request");
37
+ if (!this.request)
38
+ throw new Error("QuotationModule 需要 request 插件支持");
39
+ this.store = { list: [] };
40
+ }
41
+ async loadQuotations(params) {
42
+ var _a;
43
+ const query = {};
44
+ if (params == null ? void 0 : params.channel)
45
+ query.channel = params.channel;
46
+ if ((params == null ? void 0 : params.channel) === "online_store") {
47
+ query.channel = "online-store";
48
+ }
49
+ const res = await this.request.get(
50
+ "/quotation/available",
51
+ query,
52
+ { useCache: false }
53
+ );
54
+ const list = ((_a = res == null ? void 0 : res.data) == null ? void 0 : _a.list) || (res == null ? void 0 : res.list) || [];
55
+ list.sort((a, b) => a.sort - b.sort);
56
+ this.store.list = list;
57
+ }
58
+ getQuotationList() {
59
+ return this.store.list;
60
+ }
61
+ /**
62
+ * Look up the quotation price for a specific product (+ optional variant) at a given datetime.
63
+ * Returns the price as a string (e.g. "300.00"), or null if no quotation applies.
64
+ *
65
+ * Priority: iterates quotations already sorted by `sort` ascending (lowest = highest priority).
66
+ * First matching quotation whose schedule covers `datetime` and whose product_data contains
67
+ * the requested productId wins.
68
+ */
69
+ getPriceForProduct(params) {
70
+ const { productId, variantId, datetime } = params;
71
+ for (const quotation of this.store.list) {
72
+ if (!this.isQuotationActiveAt(quotation, datetime))
73
+ continue;
74
+ const match = this.findProductData(quotation.product_data, productId, variantId);
75
+ if (!match)
76
+ continue;
77
+ if (match.value === 0)
78
+ continue;
79
+ return String(match.value);
80
+ }
81
+ return null;
82
+ }
83
+ getQuotationShelfId(params) {
84
+ const { productId, variantId, datetime } = params;
85
+ for (const quotation of this.store.list) {
86
+ if (!this.isQuotationActiveAt(quotation, datetime))
87
+ continue;
88
+ const match = this.findProductData(quotation.product_data, productId, variantId);
89
+ if (!match || match.value === 0)
90
+ continue;
91
+ return quotation.id;
92
+ }
93
+ return 0;
94
+ }
95
+ /**
96
+ * Batch pre-compute quotation prices for a set of products across multiple time points.
97
+ * Key format: `${productId}:${timePoint}`
98
+ * This avoids repeated schedule matching when the same product appears in multiple resource rows.
99
+ */
100
+ buildProductPriceMap(params) {
101
+ const map = /* @__PURE__ */ new Map();
102
+ if (!this.store.list.length)
103
+ return map;
104
+ for (const productId of params.productIds) {
105
+ for (const timePoint of params.timePoints) {
106
+ const key = `${productId}:${timePoint}`;
107
+ const price = this.getPriceForProduct({ productId, datetime: timePoint });
108
+ if (price !== null) {
109
+ map.set(key, price);
110
+ }
111
+ }
112
+ }
113
+ return map;
114
+ }
115
+ setScheduleResolver(resolver) {
116
+ this.scheduleResolver = resolver;
117
+ }
118
+ isQuotationActiveAt(quotation, datetime) {
119
+ var _a;
120
+ if (!((_a = quotation.schedule) == null ? void 0 : _a.length))
121
+ return false;
122
+ const scheduleItems = quotation.schedule.map((s) => {
123
+ var _a2;
124
+ const full = (_a2 = this.scheduleResolver) == null ? void 0 : _a2.call(this, s.id);
125
+ if (full)
126
+ return full;
127
+ return {
128
+ ...s,
129
+ repeat_type: s.repeat_type || "none",
130
+ repeat_rule: s.repeat_rule || null,
131
+ time_slot: s.time_slot || []
132
+ };
133
+ });
134
+ return (0, import_getDateIsInSchedule.getDateIsInSchedule)(datetime, scheduleItems);
135
+ }
136
+ findProductData(productData, productId, variantId) {
137
+ if (variantId && variantId !== 0) {
138
+ const variantMatch = productData.find(
139
+ (p) => p.product_id === productId && p.variant_id === variantId
140
+ );
141
+ if (variantMatch)
142
+ return variantMatch;
143
+ }
144
+ return productData.find(
145
+ (p) => p.product_id === productId && p.variant_id === 0
146
+ );
147
+ }
148
+ };
149
+ // Annotate the CommonJS export names for ESM import in node:
150
+ 0 && (module.exports = {
151
+ QuotationModule
152
+ });
@@ -0,0 +1,42 @@
1
+ export interface QuotationProductData {
2
+ id: number;
3
+ shelf_id: number;
4
+ product_id: number;
5
+ variant_id: number;
6
+ type: string;
7
+ value: number;
8
+ }
9
+ export interface QuotationSchedule {
10
+ id: number;
11
+ name: string;
12
+ type: 'standard' | 'time-slots' | 'designation';
13
+ start_time: string;
14
+ end_time: string;
15
+ is_all: number;
16
+ repeat_type?: string;
17
+ repeat_rule?: any;
18
+ designation?: any;
19
+ time_slot?: Array<{
20
+ start_time: string;
21
+ end_time: string;
22
+ }>;
23
+ pivot?: Record<string, any>;
24
+ }
25
+ export interface QuotationItem {
26
+ id: number;
27
+ shop_id: number;
28
+ shelf_type_id?: number;
29
+ name: string;
30
+ description?: string;
31
+ status: string;
32
+ sort: number;
33
+ channel: string[];
34
+ created_at?: string;
35
+ updated_at?: string;
36
+ deleted_at?: string | null;
37
+ schedule: QuotationSchedule[];
38
+ product_data: QuotationProductData[];
39
+ }
40
+ export interface QuotationState {
41
+ list: QuotationItem[];
42
+ }
@@ -0,0 +1,17 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __copyProps = (to, from, except, desc) => {
6
+ if (from && typeof from === "object" || typeof from === "function") {
7
+ for (let key of __getOwnPropNames(from))
8
+ if (!__hasOwnProp.call(to, key) && key !== except)
9
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
10
+ }
11
+ return to;
12
+ };
13
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
14
+
15
+ // src/modules/Quotation/types.ts
16
+ var types_exports = {};
17
+ module.exports = __toCommonJS(types_exports);
@@ -206,7 +206,9 @@ declare class Server {
206
206
  */
207
207
  private shouldUseLocalBookingQuery;
208
208
  /**
209
- * 日历 SSE 精简 with:只拉日历渲染必需的关联字段
209
+ * 日历 SSE 精简 with:由调用方显式声明 compact_fields 决定
210
+ * - compact_fields === true → 精简字段(周/月视图)
211
+ * - 其余(false / 未传)→ ['all'](日视图/表格/平面图合并)
210
212
  */
211
213
  private resolveBookingSalesWith;
212
214
  /**
@@ -214,6 +216,11 @@ declare class Server {
214
216
  * business_code / payment_status 不直接用于渲染,但 matchOrder 过滤依赖
215
217
  */
216
218
  private resolveBookingSalesSelect;
219
+ /**
220
+ * 日历(compact_fields)场景下要直接在 SSE 层排除的订单类型:
221
+ * 这些类型不会出现在日历上,拉取它们只会浪费带宽并增加前端过滤成本。
222
+ */
223
+ private readonly BOOKING_SALES_COMPACT_EXCLUDE_TYPES;
217
224
  private normalizeBookingRemoteQueryPayload;
218
225
  /**
219
226
  * 远端预约查询内存缓存开关:默认 false,仅显式 true 才启用。
@@ -225,6 +225,16 @@ var Server = class {
225
225
  }
226
226
  return { code: 200, message: "ok", status: true };
227
227
  };
228
+ /**
229
+ * 日历(compact_fields)场景下要直接在 SSE 层排除的订单类型:
230
+ * 这些类型不会出现在日历上,拉取它们只会浪费带宽并增加前端过滤成本。
231
+ */
232
+ this.BOOKING_SALES_COMPACT_EXCLUDE_TYPES = [
233
+ "virtual",
234
+ "shipping",
235
+ "delivery",
236
+ "pickup"
237
+ ];
228
238
  /**
229
239
  * 处理预约列表查询
230
240
  * 今天:注册订阅者 + 本地数据筛选;非今天:清理订阅者 + 走真实 API
@@ -1022,14 +1032,20 @@ var Server = class {
1022
1032
  return !this.isRangeBothNotToday(range[0], range[1]);
1023
1033
  }
1024
1034
  /**
1025
- * 日历 SSE 精简 with:只拉日历渲染必需的关联字段
1035
+ * 日历 SSE 精简 with:由调用方显式声明 compact_fields 决定
1036
+ * - compact_fields === true → 精简字段(周/月视图)
1037
+ * - 其余(false / 未传)→ ['all'](日视图/表格/平面图合并)
1026
1038
  */
1027
- resolveBookingSalesWith(_queryPayload) {
1028
- return [
1029
- "bookings:booking_id,start_date,start_time,end_date,end_time,holder,metadata,parent_id,item_type",
1030
- "customer:id,display_name,phone",
1031
- "products"
1032
- ];
1039
+ resolveBookingSalesWith(queryPayload) {
1040
+ if ((queryPayload == null ? void 0 : queryPayload.compact_fields) === true) {
1041
+ return [
1042
+ "bookings:booking_id,start_date,start_time,end_date,end_time,holder,metadata,parent_id,item_type",
1043
+ "customer:id,display_name,phone",
1044
+ "products"
1045
+ // 'resources'
1046
+ ];
1047
+ }
1048
+ return ["all"];
1033
1049
  }
1034
1050
  /**
1035
1051
  * 日历 SSE 精简 select:渲染 + filterBookingsFromOrders 所需的主表字段
@@ -1039,12 +1055,16 @@ var Server = class {
1039
1055
  return "status,payment_status,business_code,phone,customer_name,schedule_date,created_at,metadata";
1040
1056
  }
1041
1057
  normalizeBookingRemoteQueryPayload(data, withFields) {
1058
+ const isFullWith = withFields.length === 1 && withFields[0] === "all";
1059
+ const isCompact = (data == null ? void 0 : data.compact_fields) === true;
1042
1060
  return {
1043
1061
  ...data,
1044
1062
  form_record_ids: void 0,
1045
1063
  enable_remote_memory_cache: void 0,
1064
+ compact_fields: void 0,
1046
1065
  with: withFields,
1047
- select: this.resolveBookingSalesSelect(),
1066
+ ...isFullWith ? {} : { select: this.resolveBookingSalesSelect() },
1067
+ ...isCompact ? { exclude_types: this.BOOKING_SALES_COMPACT_EXCLUDE_TYPES } : {},
1048
1068
  chunk_size: 50
1049
1069
  };
1050
1070
  }
@@ -136,7 +136,7 @@ export declare class BookingTicketImpl extends BaseModule implements Module {
136
136
  * 获取当前的客户搜索条件
137
137
  * @returns 当前搜索条件
138
138
  */
139
- getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
139
+ getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "skip" | "num">;
140
140
  /**
141
141
  * 获取客户列表状态(包含滚动加载相关状态)
142
142
  * @returns 客户状态
@@ -86,12 +86,41 @@ export declare class SalesImpl extends BaseModule implements Module, SalesModule
86
86
  */
87
87
  private pickBookingsForCurrentPoint;
88
88
  /**
89
- * 标准化单条 booking
90
- * - 过滤终态(rejected/cancelled/completed)
91
- * - deviceTime 早于 currentTime 时,过滤 end_time 早于 currentTime 的历史数据
92
- * - 注入 status / isTimeout / reserved_status
89
+ * 计算 booking 在 current 时刻的执行进度百分比(0-100)。
90
+ * - startAt/endAt 非法或 totalMinutes <= 0 返回 0
91
+ * - current 早于 startAt 返回 0,晚于 endAt 返回 100
92
+ */
93
+ private calcProgressPercent;
94
+ /**
95
+ * 标准化单条 booking 的分发入口:
96
+ * - 统一过滤 rejected / cancelled(视为没来过)
97
+ * - current === deviceCurrent 走实时分支(信任 appointment_status)
98
+ * - 否则走快照分支(纯时间窗判定,忽略 appointment_status 的 arrived/started/completed 差异)
93
99
  */
94
100
  private normalizeMatchedBooking;
101
+ /**
102
+ * 实时模式(current === deviceCurrent):信任 appointment_status
103
+ * - 过滤 new / completed(实时视角下视为非活跃数据)
104
+ * - status 由 getBookingStatus 映射
105
+ * - occupied 且 current > endAt 标记 isTimeout + timeoutTime
106
+ * - reserved 且 current < startAt 标记 not_arrived,否则标记 late
107
+ */
108
+ private buildRealtimeBooking;
109
+ /**
110
+ * 快照模式(current !== deviceCurrent,过去或未来):忽略 appointment_status
111
+ * 的实时态差异,仅按 booking 时间窗判定,为 current 提供时间点快照视图。
112
+ *
113
+ * - new:视作尚未成为真实预约,过滤
114
+ * - locked:保留 status=locked,不计算 timeout/late/progress
115
+ * - 其他非终态:
116
+ * - startAt/endAt 非法 → 过滤
117
+ * - current > endAt → 过滤(已结束,不入池)
118
+ * - current ∈ [startAt, endAt] → occupied,附带 progressPercent
119
+ * - current < startAt → reserved + not_arrived,附带 remainingReserveTime
120
+ *
121
+ * 快照模式下 isTimeout 恒为 false,lateTime / timeoutTime 始终置空。
122
+ */
123
+ private buildSnapshotBooking;
95
124
  getResourceBookingList(currentTime: string, bookingList?: BookingData[], deviceTime?: string): Promise<SalesResourceBookingItem[]>;
96
125
  }
97
126
  export { SalesImpl as Sales };
@@ -315,39 +315,54 @@ var SalesImpl = class extends import_BaseModule.BaseModule {
315
315
  return fallback ? [fallback] : [];
316
316
  }
317
317
  /**
318
- * 标准化单条 booking
319
- * - 过滤终态(rejected/cancelled/completed)
320
- * - deviceTime 早于 currentTime 时,过滤 end_time 早于 currentTime 的历史数据
321
- * - 注入 status / isTimeout / reserved_status
318
+ * 计算 booking 在 current 时刻的执行进度百分比(0-100)。
319
+ * - startAt/endAt 非法或 totalMinutes <= 0 返回 0
320
+ * - current 早于 startAt 返回 0,晚于 endAt 返回 100
321
+ */
322
+ calcProgressPercent(current, startAt, endAt) {
323
+ if (!startAt.isValid() || !endAt.isValid())
324
+ return 0;
325
+ const totalMinutes = endAt.diff(startAt, "minute");
326
+ if (totalMinutes <= 0)
327
+ return 0;
328
+ const elapsedMinutes = current.diff(startAt, "minute");
329
+ if (elapsedMinutes <= 0)
330
+ return 0;
331
+ if (elapsedMinutes >= totalMinutes)
332
+ return 100;
333
+ return Math.floor(elapsedMinutes / totalMinutes * 100);
334
+ }
335
+ /**
336
+ * 标准化单条 booking 的分发入口:
337
+ * - 统一过滤 rejected / cancelled(视为没来过)
338
+ * - current === deviceCurrent 走实时分支(信任 appointment_status)
339
+ * - 否则走快照分支(纯时间窗判定,忽略 appointment_status 的 arrived/started/completed 差异)
322
340
  */
323
341
  normalizeMatchedBooking(current, deviceCurrent, booking) {
324
342
  const appointmentStatus = String(booking.appointment_status ?? booking.status ?? "");
325
- if (appointmentStatus === "new" || appointmentStatus === "rejected" || appointmentStatus === "cancelled" || appointmentStatus === "completed") {
343
+ if (appointmentStatus === "rejected" || appointmentStatus === "cancelled")
326
344
  return null;
327
- }
345
+ const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
328
346
  const endAt = this.toBookingDateTime(booking.end_date, booking.end_time);
329
- const shouldFilterHistoryByCurrent = deviceCurrent.isBefore(current);
330
- if (shouldFilterHistoryByCurrent && endAt.isValid() && endAt.isBefore(current))
347
+ if (current.isSame(deviceCurrent)) {
348
+ return this.buildRealtimeBooking(current, booking, appointmentStatus, startAt, endAt);
349
+ }
350
+ return this.buildSnapshotBooking(current, booking, appointmentStatus, startAt, endAt);
351
+ }
352
+ /**
353
+ * 实时模式(current === deviceCurrent):信任 appointment_status
354
+ * - 过滤 new / completed(实时视角下视为非活跃数据)
355
+ * - status 由 getBookingStatus 映射
356
+ * - occupied 且 current > endAt 标记 isTimeout + timeoutTime
357
+ * - reserved 且 current < startAt 标记 not_arrived,否则标记 late
358
+ */
359
+ buildRealtimeBooking(current, booking, appointmentStatus, startAt, endAt) {
360
+ if (appointmentStatus === "new" || appointmentStatus === "completed")
331
361
  return null;
332
- let bookingStatus = this.getBookingStatus(appointmentStatus);
333
- const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
334
- let isTimeout = bookingStatus === "occupied" && endAt.isValid() && current.isAfter(endAt);
335
- let timeoutTime = isTimeout ? current.diff(endAt, "minute") : void 0;
336
- let progressPercent = (() => {
337
- if (bookingStatus !== "occupied")
338
- return 0;
339
- if (!startAt.isValid() || !endAt.isValid())
340
- return 0;
341
- const totalMinutes = endAt.diff(startAt, "minute");
342
- if (totalMinutes <= 0)
343
- return 0;
344
- const elapsedMinutes = current.diff(startAt, "minute");
345
- if (elapsedMinutes <= 0)
346
- return 0;
347
- if (elapsedMinutes >= totalMinutes)
348
- return 100;
349
- return Math.floor(elapsedMinutes / totalMinutes * 100);
350
- })();
362
+ const bookingStatus = this.getBookingStatus(appointmentStatus);
363
+ const isTimeout = bookingStatus === "occupied" && endAt.isValid() && current.isAfter(endAt);
364
+ const timeoutTime = isTimeout ? current.diff(endAt, "minute") : void 0;
365
+ const progressPercent = bookingStatus === "occupied" ? this.calcProgressPercent(current, startAt, endAt) : 0;
351
366
  let reservedStatus;
352
367
  let lateTime;
353
368
  let remainingReserveTime;
@@ -360,27 +375,6 @@ var SalesImpl = class extends import_BaseModule.BaseModule {
360
375
  lateTime = Math.max(current.diff(startAt, "minute"), 0);
361
376
  }
362
377
  }
363
- if (current.isAfter(deviceCurrent) && bookingStatus === "reserved" && reservedStatus === "late" && endAt.isValid() && endAt.isSameOrAfter(current)) {
364
- bookingStatus = "occupied";
365
- reservedStatus = void 0;
366
- lateTime = void 0;
367
- remainingReserveTime = void 0;
368
- isTimeout = false;
369
- timeoutTime = void 0;
370
- progressPercent = (() => {
371
- if (!startAt.isValid() || !endAt.isValid())
372
- return 0;
373
- const totalMinutes = endAt.diff(startAt, "minute");
374
- if (totalMinutes <= 0)
375
- return 0;
376
- const elapsedMinutes = current.diff(startAt, "minute");
377
- if (elapsedMinutes <= 0)
378
- return 0;
379
- if (elapsedMinutes >= totalMinutes)
380
- return 100;
381
- return Math.floor(elapsedMinutes / totalMinutes * 100);
382
- })();
383
- }
384
378
  return {
385
379
  ...booking,
386
380
  status: bookingStatus,
@@ -392,6 +386,62 @@ var SalesImpl = class extends import_BaseModule.BaseModule {
392
386
  remainingReserveTime
393
387
  };
394
388
  }
389
+ /**
390
+ * 快照模式(current !== deviceCurrent,过去或未来):忽略 appointment_status
391
+ * 的实时态差异,仅按 booking 时间窗判定,为 current 提供时间点快照视图。
392
+ *
393
+ * - new:视作尚未成为真实预约,过滤
394
+ * - locked:保留 status=locked,不计算 timeout/late/progress
395
+ * - 其他非终态:
396
+ * - startAt/endAt 非法 → 过滤
397
+ * - current > endAt → 过滤(已结束,不入池)
398
+ * - current ∈ [startAt, endAt] → occupied,附带 progressPercent
399
+ * - current < startAt → reserved + not_arrived,附带 remainingReserveTime
400
+ *
401
+ * 快照模式下 isTimeout 恒为 false,lateTime / timeoutTime 始终置空。
402
+ */
403
+ buildSnapshotBooking(current, booking, appointmentStatus, startAt, endAt) {
404
+ if (appointmentStatus === "new")
405
+ return null;
406
+ if (appointmentStatus === "locked") {
407
+ return {
408
+ ...booking,
409
+ status: "locked",
410
+ isTimeout: false,
411
+ timeoutTime: void 0,
412
+ progressPercent: 0,
413
+ lateTime: void 0,
414
+ reserved_status: void 0,
415
+ remainingReserveTime: void 0
416
+ };
417
+ }
418
+ if (!startAt.isValid() || !endAt.isValid())
419
+ return null;
420
+ if (current.isAfter(endAt))
421
+ return null;
422
+ if (this.isSameOrAfter(current, startAt) && this.isSameOrBefore(current, endAt)) {
423
+ return {
424
+ ...booking,
425
+ status: "occupied",
426
+ isTimeout: false,
427
+ timeoutTime: void 0,
428
+ progressPercent: this.calcProgressPercent(current, startAt, endAt),
429
+ lateTime: void 0,
430
+ reserved_status: void 0,
431
+ remainingReserveTime: void 0
432
+ };
433
+ }
434
+ return {
435
+ ...booking,
436
+ status: "reserved",
437
+ isTimeout: false,
438
+ timeoutTime: void 0,
439
+ progressPercent: 0,
440
+ lateTime: void 0,
441
+ reserved_status: "not_arrived",
442
+ remainingReserveTime: Math.max(startAt.diff(current, "minute"), 0)
443
+ };
444
+ }
395
445
  async getResourceBookingList(currentTime, bookingList = [], deviceTime = currentTime) {
396
446
  var _a;
397
447
  const current = (0, import_dayjs.default)(currentTime);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.2.123",
4
+ "version": "2.2.125",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",