ts-glitter 21.3.1 → 21.3.4

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 (38) hide show
  1. package/lowcode/Entry.js +1 -1
  2. package/lowcode/Entry.ts +1 -1
  3. package/lowcode/backend-manager/bg-customer-message.js +4 -2
  4. package/lowcode/backend-manager/bg-customer-message.ts +4 -2
  5. package/lowcode/cms-plugin/module/product-excel.js +169 -129
  6. package/lowcode/cms-plugin/module/product-excel.ts +174 -130
  7. package/lowcode/cms-plugin/shopping-discount-setting.js +640 -600
  8. package/lowcode/cms-plugin/shopping-discount-setting.ts +782 -716
  9. package/lowcode/cms-plugin/shopping-finance-setting.js +372 -407
  10. package/lowcode/cms-plugin/shopping-finance-setting.ts +918 -968
  11. package/lowcode/glitter-base/global/language.js +12 -0
  12. package/lowcode/glitter-base/global/language.ts +12 -0
  13. package/lowcode/glitter-base/route/api-track.js +2 -2
  14. package/lowcode/glitter-base/route/api-track.ts +20 -20
  15. package/lowcode/public-components/checkout/index.js +27 -5
  16. package/lowcode/public-components/checkout/index.ts +34 -6
  17. package/lowcode/public-components/headers/header-class.js +13 -18
  18. package/lowcode/public-components/headers/header-class.ts +16 -20
  19. package/lowcode/public-components/modules/cart-module.js +6 -0
  20. package/lowcode/public-components/modules/cart-module.ts +6 -0
  21. package/lowcode/public-components/product/pd-class.js +1 -3
  22. package/lowcode/public-components/product/pd-class.ts +1 -3
  23. package/omr85cp878.json +1 -0
  24. package/package.json +1 -1
  25. package/src/api-public/services/checkout-event.js +26 -12
  26. package/src/api-public/services/checkout-event.js.map +1 -1
  27. package/src/api-public/services/checkout-event.ts +34 -12
  28. package/src/api-public/services/data-analyze.d.ts +1 -1
  29. package/src/api-public/services/post.js +7 -17
  30. package/src/api-public/services/post.js.map +1 -1
  31. package/src/api-public/services/shopee.js +7 -17
  32. package/src/api-public/services/shopee.js.map +1 -1
  33. package/src/api-public/services/shopping.d.ts +44 -27
  34. package/src/api-public/services/shopping.js +56 -11
  35. package/src/api-public/services/shopping.js.map +1 -1
  36. package/src/api-public/services/shopping.ts +126 -58
  37. package/src/index.js +7 -17
  38. package/src/index.js.map +1 -1
@@ -7,8 +7,59 @@ import { EditorElem } from '../glitterBundle/plugins/editor-elem.js';
7
7
  import { ShareDialog } from '../glitterBundle/dialog/ShareDialog.js';
8
8
  import { FilterOptions } from './filter-options.js';
9
9
  import { Tool } from '../modules/tool.js';
10
+ import { ShipmentConfig } from '../glitter-base/global/shipment-config.js';
10
11
 
11
12
  type VoucherForType = 'all' | 'collection' | 'product' | 'manager_tag';
13
+ type RebackType = 'rebate' | 'discount' | 'shipment_free' | 'add_on_items' | 'giveaway';
14
+ type Trigger = 'auto' | 'code' | 'distribution';
15
+ type ProductOffStart = 'price_asc' | 'price_desc' | 'price_all';
16
+ type Device = 'normal' | 'pos';
17
+ type Method = 'fixed' | 'percent';
18
+ type Rule = 'min_price' | 'min_count';
19
+ type ConditionType = 'item' | 'order';
20
+ type Counting = 'single' | 'each';
21
+ type IncludeDiscount = 'before' | 'after';
22
+ type SelectShipmentType = 'all' | 'select';
23
+
24
+ interface VoucherData {
25
+ id: string;
26
+ type: 'voucher';
27
+ status: 0 | 1 | -1;
28
+ title: string;
29
+ code?: string;
30
+ reBackType: RebackType;
31
+ method: Method;
32
+ trigger: Trigger;
33
+ device: Device[];
34
+ value: string;
35
+ add_on_products?: string[];
36
+ for: VoucherForType;
37
+ rule: Rule;
38
+ counting: Counting;
39
+ conditionType: ConditionType;
40
+ includeDiscount: IncludeDiscount;
41
+ productOffStart: ProductOffStart;
42
+ forKey: (number | string)[];
43
+ ruleValue: number;
44
+ startDate: string;
45
+ startTime: string;
46
+ endDate?: string;
47
+ endTime?: string;
48
+ overlay: boolean;
49
+ start_ISO_Date: string;
50
+ end_ISO_Date: string;
51
+ rebateEndDay: string;
52
+ target: string;
53
+ targetList: (number | string)[];
54
+ macroLimited: number;
55
+ microLimited: number;
56
+ selectShipment: {
57
+ type: SelectShipmentType;
58
+ list: string[];
59
+ };
60
+ }
61
+
62
+ const html = String.raw;
12
63
 
13
64
  export class ShoppingDiscountSetting {
14
65
  public static getLabel(voucher_type: string): string {
@@ -22,8 +73,9 @@ export class ShoppingDiscountSetting {
22
73
  return labels[voucher_type] ?? '未知活動';
23
74
  }
24
75
 
25
- public static main(gvc: GVC, voucher_type: 'rebate' | 'discount' | 'shipment_free' | 'add_on_items' | 'giveaway') {
76
+ public static main(gvc: GVC, voucher_type: RebackType) {
26
77
  const glitter = gvc.glitter;
78
+ const dialog = new ShareDialog(glitter);
27
79
  const vm: {
28
80
  type: 'list' | 'add' | 'replace';
29
81
  data: any;
@@ -35,7 +87,6 @@ export class ShoppingDiscountSetting {
35
87
  dataList: undefined,
36
88
  query: undefined,
37
89
  };
38
- const html = String.raw;
39
90
 
40
91
  return gvc.bindView(() => {
41
92
  const id = glitter.getUUID();
@@ -140,7 +191,6 @@ export class ShoppingDiscountSetting {
140
191
  {
141
192
  name: '批量移除',
142
193
  event: () => {
143
- const dialog = new ShareDialog(gvc.glitter);
144
194
  dialog.checkYesOrNot({
145
195
  text: '是否確認刪除所選項目?',
146
196
  callback: response => {
@@ -219,41 +269,16 @@ export class ShoppingDiscountSetting {
219
269
  const gvc = obj.gvc;
220
270
  const glitter = gvc.glitter;
221
271
  const vm = obj.vm;
222
- const html = String.raw;
272
+ const dialog = new ShareDialog(glitter);
223
273
 
224
- const voucherData: {
225
- id: string;
226
- title: string;
227
- reBackType: 'rebate' | 'discount' | 'shipment_free' | 'add_on_items' | 'giveaway';
228
- method: 'percent' | 'fixed';
229
- trigger: 'auto' | 'code' | 'distribution';
230
- device: ('normal' | 'pos')[];
231
- value: string;
232
- add_on_products?: string[];
233
- for: VoucherForType;
234
- rule: 'min_price' | 'min_count';
235
- counting: 'single' | 'each';
236
- conditionType: 'item' | 'order';
237
- includeDiscount: 'before' | 'after';
238
- productOffStart: 'price_asc' | 'price_desc' | 'price_all';
239
- forKey: (number | string)[];
240
- ruleValue: number;
241
- startDate: string;
242
- startTime: string;
243
- endDate?: string;
244
- endTime?: string;
245
- status: 0 | 1 | -1;
246
- type: 'voucher';
247
- code?: string;
248
- overlay: boolean;
249
- start_ISO_Date: string;
250
- end_ISO_Date: string;
251
- rebateEndDay: string;
252
- target: string;
253
- targetList: [];
254
- macroLimited: number;
255
- microLimited: number;
256
- } = {
274
+ const pageVM = {
275
+ viewID: gvc.glitter.getUUID(),
276
+ conditionID: gvc.glitter.getUUID(),
277
+ countingID: gvc.glitter.getUUID(),
278
+ productOffID: gvc.glitter.getUUID(),
279
+ };
280
+
281
+ const voucherData: VoucherData = {
257
282
  title: '',
258
283
  code: '',
259
284
  trigger: 'auto',
@@ -283,10 +308,11 @@ export class ShoppingDiscountSetting {
283
308
  conditionType: 'order',
284
309
  includeDiscount: 'before',
285
310
  productOffStart: 'price_desc',
311
+ selectShipment: { type: 'all', list: [] },
286
312
  ...vm.data,
287
313
  };
288
314
 
289
- function getVoucherTextList() {
315
+ function summaryTextList() {
290
316
  return [
291
317
  `活動標題:${voucherData.title && voucherData.title.length > 0 ? voucherData.title : '尚無標題'}`,
292
318
  `適用商品:${(() => {
@@ -350,16 +376,551 @@ export class ShoppingDiscountSetting {
350
376
  ];
351
377
  }
352
378
 
353
- const pageVM = {
354
- conditionId: gvc.glitter.getUUID(),
355
- countingId: gvc.glitter.getUUID(),
356
- productOffId: gvc.glitter.getUUID(),
357
- };
379
+ function title() {
380
+ return html` <div class="tx_700">活動標題</div>
381
+ ${BgWidget.mbContainer(18)}
382
+ ${BgWidget.editeInput({
383
+ gvc: gvc,
384
+ title: '',
385
+ default: voucherData.title,
386
+ placeHolder: '請輸入活動標題',
387
+ callback: text => {
388
+ voucherData.title = text;
389
+ },
390
+ })}
391
+ ${BgWidget.grayNote('顧客將會在「購物車」與「結帳」看見此標題', 'margin-left: 4px;')}`;
392
+ }
393
+
394
+ function status() {
395
+ return html` <div class="tx_700">活動狀態</div>
396
+ ${BgWidget.mbContainer(12)}
397
+ ${BgWidget.switchTextButton(
398
+ gvc,
399
+ voucherData.status === 1,
400
+ {
401
+ left: '關閉',
402
+ right: '啟用',
403
+ },
404
+ bool => {
405
+ voucherData.status = bool ? 1 : 0;
406
+ }
407
+ )}`;
408
+ }
409
+
410
+ function trigger() {
411
+ return html` <div class="tx_700">活動方式</div>
412
+ ${BgWidget.mbContainer(18)}
413
+ ${BgWidget.multiCheckboxContainer(
414
+ gvc,
415
+ [
416
+ {
417
+ key: 'auto',
418
+ name: '自動折扣',
419
+ innerHtml: BgWidget.grayNote('顧客將在結帳時,自動獲得折扣'),
420
+ },
421
+ {
422
+ key: 'code',
423
+ name: '優惠代碼',
424
+ innerHtml: (() => {
425
+ const id = glitter.getUUID();
426
+ return gvc.bindView({
427
+ bind: id,
428
+ view: () =>
429
+ gvc.map([
430
+ BgWidget.grayNote('顧客可在結帳時輸入優惠代碼,來獲得折扣'),
431
+ BgWidget.editeInput({
432
+ gvc: gvc,
433
+ title: '',
434
+ default: voucherData.code ?? '',
435
+ placeHolder: '請輸入優惠券代碼',
436
+ callback: text => {
437
+ voucherData.code = text.toUpperCase();
438
+ },
439
+ endText: html` <div class="d-flex justify-content-end">
440
+ ${BgWidget.mbContainer(8)}
441
+ ${BgWidget.blueNote(
442
+ document.body.clientWidth > 768 ? '隨機產生優惠代碼' : '隨機產生',
443
+ gvc.event(() => {
444
+ voucherData.code = Tool.randomString(6).toUpperCase();
445
+ gvc.notifyDataChange(id);
446
+ })
447
+ )}
448
+ </div>`,
449
+ }),
450
+ ]),
451
+ });
452
+ })(),
453
+ },
454
+ {
455
+ key: 'distribution',
456
+ name: '供分銷連結或一頁式網頁使用',
457
+ },
458
+ ],
459
+ [voucherData.trigger],
460
+ text => {
461
+ if (text[0] === 'auto') {
462
+ voucherData.code = undefined;
463
+ }
464
+ if (text[0] === 'distribution') {
465
+ voucherData.for = 'all';
466
+ }
467
+ voucherData.trigger = text[0] as Trigger;
468
+ gvc.notifyDataChange(pageVM.viewID);
469
+ },
470
+ { single: true }
471
+ )}`;
472
+ }
473
+
474
+ function target() {
475
+ return html` <div class="tx_700">活動對象</div>
476
+ ${BgWidget.mbContainer(18)}
477
+ ${gvc.bindView(() => {
478
+ const id = gvc.glitter.getUUID();
479
+ return {
480
+ bind: id,
481
+ view: () => {
482
+ return html`
483
+ <div style="display: flex; flex-direction: column; gap: 8px;">
484
+ ${BgWidget.selectFilter({
485
+ gvc: gvc,
486
+ callback: text => {
487
+ voucherData.target = text;
488
+ gvc.notifyDataChange(id);
489
+ },
490
+ default: voucherData.target ?? 'all',
491
+ options: [
492
+ {
493
+ key: 'all',
494
+ value: '所有顧客',
495
+ },
496
+ {
497
+ key: 'customer',
498
+ value: '特定顧客',
499
+ },
500
+ {
501
+ key: 'levels',
502
+ value: '會員等級',
503
+ },
504
+ // {
505
+ // key: 'group',
506
+ // value: '顧客分群',
507
+ // },
508
+ ],
509
+ style: 'width: 100%;',
510
+ })}
511
+ <div>
512
+ ${(() => {
513
+ switch (voucherData.target) {
514
+ case 'all':
515
+ return '';
516
+ case 'customer':
517
+ return gvc.bindView(() => {
518
+ const customVM = {
519
+ id: gvc.glitter.getUUID(),
520
+ loading: true,
521
+ dataList: [] as OptionsItem[],
522
+ };
523
+ return {
524
+ bind: customVM.id,
525
+ view: () => {
526
+ if (customVM.loading) {
527
+ return BgWidget.spinner();
528
+ }
529
+ return html`
530
+ <div class="d-flex flex-column p-2" style="gap: 18px;">
531
+ <div
532
+ class="d-flex align-items-center gray-bottom-line-18"
533
+ style="justify-content: space-between;"
534
+ >
535
+ <div class="form-check-label c_updown_label">
536
+ <div class="tx_normal">顧客名稱</div>
537
+ </div>
538
+ ${BgWidget.grayButton(
539
+ '查看全部',
540
+ gvc.event(() => {
541
+ BgWidget.selectDropDialog({
542
+ gvc: gvc,
543
+ title: '搜尋特定顧客',
544
+ tag: 'select_users',
545
+ updownOptions: FilterOptions.userOrderBy,
546
+ callback: value => {
547
+ voucherData.targetList = value;
548
+ customVM.loading = true;
549
+ gvc.notifyDataChange(customVM.id);
550
+ },
551
+ default: (voucherData.targetList ?? []).map(id => id.toString()),
552
+ api: (data: { query: string; orderString: string }) => {
553
+ return new Promise(resolve => {
554
+ ApiUser.getUserListOrders({
555
+ page: 0,
556
+ limit: 99999,
557
+ search: data.query,
558
+ orderString: data.orderString,
559
+ }).then(dd => {
560
+ if (dd.response.data) {
561
+ resolve(
562
+ dd.response.data.map(
563
+ (item: {
564
+ userID: number;
565
+ userData: {
566
+ name: string;
567
+ email: string;
568
+ };
569
+ }) => {
570
+ return {
571
+ key: item.userID,
572
+ value: item.userData.name ?? '(尚無姓名)',
573
+ note: item.userData.email,
574
+ };
575
+ }
576
+ )
577
+ );
578
+ }
579
+ });
580
+ });
581
+ },
582
+ style: 'width: 100%;',
583
+ });
584
+ }),
585
+ { textStyle: 'font-weight: 400;' }
586
+ )}
587
+ </div>
588
+ ${obj.gvc.map(
589
+ customVM.dataList.map((opt: OptionsItem, index) => {
590
+ return html` <div class="form-check-label c_updown_label">
591
+ <span class="tx_normal">${index + 1}. ${opt.value}</span>
592
+ ${opt.note ? html` <span class="tx_gray_12 ms-2">${opt.note}</span> ` : ''}
593
+ </div>`;
594
+ })
595
+ )}
596
+ </div>
597
+ `;
598
+ },
599
+ onCreate: () => {
600
+ if (customVM.loading) {
601
+ if (voucherData.targetList.length === 0) {
602
+ setTimeout(() => {
603
+ customVM.dataList = [];
604
+ customVM.loading = false;
605
+ gvc.notifyDataChange(customVM.id);
606
+ }, 200);
607
+ } else {
608
+ ApiUser.getUserList({
609
+ page: 0,
610
+ limit: 99999,
611
+ id: voucherData.targetList.join(','),
612
+ }).then(dd => {
613
+ if (dd.response.data) {
614
+ customVM.dataList = dd.response.data.map(
615
+ (item: {
616
+ userID: string;
617
+ userData: {
618
+ name: string;
619
+ email: string;
620
+ };
621
+ }) => {
622
+ return {
623
+ key: item.userID,
624
+ value: item.userData.name,
625
+ note: item.userData.email,
626
+ };
627
+ }
628
+ );
629
+ }
630
+ customVM.loading = false;
631
+ gvc.notifyDataChange(customVM.id);
632
+ });
633
+ }
634
+ }
635
+ },
636
+ };
637
+ });
638
+ case 'levels':
639
+ return (() => {
640
+ const levelVM = {
641
+ id: gvc.glitter.getUUID(),
642
+ loading: true,
643
+ dataList: [],
644
+ };
645
+ return gvc.bindView({
646
+ bind: levelVM.id,
647
+ view: () => {
648
+ if (levelVM.loading) {
649
+ return BgWidget.spinner({ text: { visible: false } });
650
+ } else {
651
+ return BgWidget.selectDropList({
652
+ gvc: gvc,
653
+ callback: value => {
654
+ voucherData.targetList = value;
655
+ gvc.notifyDataChange(id);
656
+ },
657
+ default: (voucherData.targetList ?? []).map(id => id.toString()),
658
+ options: levelVM.dataList,
659
+ style: 'width: 100%;',
660
+ });
661
+ }
662
+ },
663
+ divCreate: {
664
+ style: 'width: 100%;',
665
+ },
666
+ onCreate: () => {
667
+ if (levelVM.loading) {
668
+ ApiUser.getPublicConfig('member_level_config', 'manager').then((dd: any) => {
669
+ if (dd.result && dd.response.value) {
670
+ levelVM.dataList = dd.response.value.levels.map(
671
+ (item: { id: string; tag_name: string }) => {
672
+ return {
673
+ key: item.id,
674
+ value: item.tag_name,
675
+ // note.txt: '人數'
676
+ };
677
+ }
678
+ );
679
+ levelVM.loading = false;
680
+ gvc.notifyDataChange(levelVM.id);
681
+ }
682
+ });
683
+ }
684
+ },
685
+ });
686
+ })();
687
+ case 'group':
688
+ return (() => {
689
+ const levelVM = {
690
+ id: gvc.glitter.getUUID(),
691
+ loading: true,
692
+ dataList: [],
693
+ };
694
+ return gvc.bindView({
695
+ bind: levelVM.id,
696
+ view: () => {
697
+ if (levelVM.loading) {
698
+ return BgWidget.spinner({ text: { visible: false } });
699
+ } else {
700
+ return BgWidget.selectDropList({
701
+ gvc: gvc,
702
+ callback: (value: []) => {
703
+ voucherData.targetList = value;
704
+ gvc.notifyDataChange(id);
705
+ },
706
+ default: (voucherData.targetList ?? []).map(id => id.toString()),
707
+ options: levelVM.dataList,
708
+ style: 'width: 100%;',
709
+ });
710
+ }
711
+ },
712
+ divCreate: {
713
+ style: 'width: 100%;',
714
+ },
715
+ onCreate: () => {
716
+ if (levelVM.loading) {
717
+ ApiUser.getUserGroupList().then((dd: any) => {
718
+ if (dd.result && dd.response.data) {
719
+ levelVM.dataList = dd.response.data
720
+ .filter((item: any) => {
721
+ return item.type !== 'level';
722
+ })
723
+ .map((item: any) => {
724
+ return {
725
+ key: item.type,
726
+ value: item.title,
727
+ };
728
+ });
729
+ levelVM.loading = false;
730
+ gvc.notifyDataChange(levelVM.id);
731
+ }
732
+ });
733
+ }
734
+ },
735
+ });
736
+ })();
737
+ default:
738
+ return '';
739
+ }
740
+ })()}
741
+ </div>
742
+ </div>
743
+ `;
744
+ },
745
+ };
746
+ })}`;
747
+ }
748
+
749
+ function device() {
750
+ return html` <div class="tx_700">可使用訂單來源</div>
751
+ ${BgWidget.mbContainer(18)}
752
+ ${BgWidget.multiCheckboxContainer(
753
+ gvc,
754
+ [
755
+ { key: 'normal', name: 'APP & 官網' },
756
+ { key: 'pos', name: 'POS' },
757
+ ],
758
+ voucherData.device ?? ['normal'],
759
+ text => {
760
+ voucherData.device = text as Device[];
761
+ gvc.notifyDataChange(pageVM.viewID);
762
+ },
763
+ { single: false }
764
+ )}`;
765
+ }
766
+
767
+ function selectShipment() {
768
+ const id = glitter.getUUID();
769
+ return gvc.bindView({
770
+ bind: id,
771
+ view: () => {
772
+ return html` <div class="tx_700">可使用物流</div>
773
+ ${BgWidget.mbContainer(18)}
774
+ ${[
775
+ BgWidget.select({
776
+ gvc,
777
+ callback: value => {
778
+ voucherData.selectShipment.type = value as SelectShipmentType;
779
+ gvc.notifyDataChange(id);
780
+ },
781
+ default: voucherData.selectShipment.type,
782
+ options: [
783
+ { key: 'all', value: '所有物流' },
784
+ { key: 'select', value: '指定物流' },
785
+ ],
786
+ }),
787
+ voucherData.selectShipment.type === 'all'
788
+ ? ''
789
+ : BgWidget.selectDropList({
790
+ gvc: gvc,
791
+ callback: value => {
792
+ voucherData.selectShipment.list = value;
793
+ },
794
+ default: voucherData.selectShipment.list ?? [],
795
+ options: ShipmentConfig.list.map(item => {
796
+ return {
797
+ key: item.value,
798
+ value: item.title,
799
+ };
800
+ }),
801
+ style: 'width: 100%;',
802
+ }),
803
+ ]
804
+ .filter(Boolean)
805
+ .join(BgWidget.mbContainer(8))}`;
806
+ },
807
+ });
808
+ }
809
+
810
+ function rebackProduct() {
811
+ return gvc.bindView(() => {
812
+ const vm = {
813
+ id: gvc.glitter.getUUID(),
814
+ };
815
+ if (!Array.isArray(voucherData.add_on_products)) {
816
+ voucherData.add_on_products = [];
817
+ }
818
+ return {
819
+ bind: vm.id,
820
+ view: () => {
821
+ return html`
822
+ <div class="tx_700">${voucherData.reBackType === 'add_on_items' ? `加購品項` : `贈品品項`}</div>
823
+ ${BgWidget.mbContainer(18)}
824
+ ${obj.gvc.bindView(() => {
825
+ const id = gvc.glitter.getUUID();
826
+ return {
827
+ bind: id,
828
+ view: () => {
829
+ try {
830
+ return html`
831
+ <div
832
+ class="d-flex align-items-center gray-bottom-line-18"
833
+ style="gap: 24px; justify-content: space-between;"
834
+ >
835
+ <div class="form-check-label c_updown_label">
836
+ <div class="tx_normal">商品列表</div>
837
+ </div>
838
+ ${BgWidget.grayButton(
839
+ '選擇商品',
840
+ gvc.event(() => {
841
+ BgProduct.productsDialog({
842
+ gvc: gvc,
843
+ default: voucherData.add_on_products ?? [],
844
+ callback: async value => {
845
+ voucherData.add_on_products = value;
846
+ gvc.notifyDataChange(id);
847
+ },
848
+ filter: dd => {
849
+ return true;
850
+ },
851
+ productType: voucherData.reBackType === 'add_on_items' ? 'addProduct' : 'giveaway',
852
+ });
853
+ }),
854
+ { textStyle: 'font-weight: 400;' }
855
+ )}
856
+ </div>
857
+ ${gvc.bindView(() => {
858
+ const vm: {
859
+ id: string;
860
+ loading: boolean;
861
+ data: OptionsItem[];
862
+ } = {
863
+ id: gvc.glitter.getUUID(),
864
+ loading: true,
865
+ data: [],
866
+ };
867
+ BgProduct.getProductOpts(
868
+ voucherData.add_on_products!,
869
+ voucherData.reBackType === 'add_on_items' ? 'addProduct' : 'giveaway'
870
+ ).then(res => {
871
+ vm.data = res;
872
+ vm.loading = false;
873
+ gvc.notifyDataChange(vm.id);
874
+ });
875
+ return {
876
+ bind: vm.id,
877
+ view: async () => {
878
+ if (vm.loading) {
879
+ return BgWidget.spinner();
880
+ }
881
+ return vm.data
882
+ .map((opt: OptionsItem, index) => {
883
+ return html` <div
884
+ class="d-flex align-items-center form-check-label c_updown_label gap-3"
885
+ >
886
+ <span class="tx_normal">${index + 1}.</span>
887
+ ${BgWidget.validImageBox({
888
+ gvc: gvc,
889
+ image: opt.image,
890
+ width: 40,
891
+ })}
892
+ <div class="tx_normal ${opt.note ? 'mb-1' : ''}">${opt.value}</div>
893
+ ${opt.note ? html` <div class="tx_gray_12">${opt.note}</div> ` : ''}
894
+ </div>`;
895
+ })
896
+ .join('');
897
+ },
898
+ divCreate: {
899
+ class: `d-flex py-2 flex-column`,
900
+ style: `gap:10px;`,
901
+ },
902
+ };
903
+ })}
904
+ `;
905
+ } catch (e) {
906
+ console.error(e);
907
+ return '';
908
+ }
909
+ },
910
+ divCreate: {
911
+ class: `w-100`,
912
+ },
913
+ };
914
+ })}
915
+ `;
916
+ },
917
+ };
918
+ });
919
+ }
358
920
 
359
921
  return gvc.bindView(() => {
360
- const viewID = gvc.glitter.getUUID();
361
922
  return {
362
- bind: viewID,
923
+ bind: pageVM.viewID,
363
924
  view: () => {
364
925
  return BgWidget.container(
365
926
  [
@@ -371,9 +932,7 @@ export class ShoppingDiscountSetting {
371
932
  })
372
933
  )}
373
934
  ${BgWidget.title(
374
- obj.type === 'add'
375
- ? `新增${ShoppingDiscountSetting.getLabel(obj.reBackType)}`
376
- : `編輯${ShoppingDiscountSetting.getLabel(obj.reBackType)}`
935
+ `${obj.type === 'add' ? '新增' : '編輯'}${ShoppingDiscountSetting.getLabel(obj.reBackType)}`
377
936
  )}
378
937
  </div>`,
379
938
  // 左右容器
@@ -381,394 +940,16 @@ export class ShoppingDiscountSetting {
381
940
  {
382
941
  // 優惠券設定
383
942
  html: [
943
+ BgWidget.mainCard([title(), status()].join(BgWidget.horizontalLine())),
384
944
  BgWidget.mainCard(
385
945
  [
386
- html` <div class="tx_700">活動標題</div>
387
- ${BgWidget.mbContainer(18)}
388
- ${BgWidget.editeInput({
389
- gvc: gvc,
390
- title: '',
391
- default: voucherData.title,
392
- placeHolder: '請輸入活動標題',
393
- callback: text => {
394
- voucherData.title = text;
395
- },
396
- })}
397
- ${BgWidget.grayNote('顧客將會在「購物車」與「結帳」看見此標題', 'margin-left: 4px;')}`,
398
- html` <div class="tx_700">活動狀態</div>
399
- ${BgWidget.mbContainer(12)}
400
- ${BgWidget.switchTextButton(
401
- gvc,
402
- voucherData.status === 1,
403
- {
404
- left: '關閉',
405
- right: '啟用',
406
- },
407
- bool => {
408
- voucherData.status = bool ? 1 : 0;
409
- }
410
- )}`,
411
- ].join(BgWidget.horizontalLine())
412
- ),
413
- BgWidget.mainCard(
414
- [
415
- html` <div class="tx_700">活動方式</div>
416
- ${BgWidget.mbContainer(18)}
417
- ${BgWidget.multiCheckboxContainer(
418
- gvc,
419
- [
420
- {
421
- key: 'auto',
422
- name: '自動折扣',
423
- innerHtml: BgWidget.grayNote('顧客將在結帳時,自動獲得折扣'),
424
- },
425
- {
426
- key: 'code',
427
- name: '優惠代碼',
428
- innerHtml: (() => {
429
- const id = glitter.getUUID();
430
- return gvc.bindView({
431
- bind: id,
432
- view: () =>
433
- gvc.map([
434
- BgWidget.grayNote('顧客可在結帳時輸入優惠代碼,來獲得折扣'),
435
- BgWidget.editeInput({
436
- gvc: gvc,
437
- title: '',
438
- default: voucherData.code ?? '',
439
- placeHolder: '請輸入優惠券代碼',
440
- callback: text => {
441
- voucherData.code = text.toUpperCase();
442
- },
443
- endText: html` <div class="d-flex justify-content-end">
444
- ${BgWidget.mbContainer(8)}
445
- ${BgWidget.blueNote(
446
- document.body.clientWidth > 768 ? '隨機產生優惠代碼' : '隨機產生',
447
- gvc.event(() => {
448
- voucherData.code = Tool.randomString(6).toUpperCase();
449
- gvc.notifyDataChange(id);
450
- })
451
- )}
452
- </div>`,
453
- }),
454
- ]),
455
- });
456
- })(),
457
- },
458
- {
459
- key: 'distribution',
460
- name: '供分銷連結或一頁式網頁使用',
461
- },
462
- ],
463
- [voucherData.trigger],
464
- text => {
465
- if (text[0] === 'auto') {
466
- voucherData.code = undefined;
467
- }
468
- if (text[0] === 'distribution') {
469
- voucherData.for = 'all';
470
- }
471
- voucherData.trigger = text[0] as 'auto' | 'code' | 'distribution';
472
- gvc.notifyDataChange(viewID);
473
- },
474
- { single: true }
475
- )}`,
476
- html` <div class="tx_700">活動對象</div>
477
- ${BgWidget.mbContainer(18)}
478
- ${gvc.bindView(() => {
479
- const id = gvc.glitter.getUUID();
480
- return {
481
- bind: id,
482
- view: () => {
483
- return html`
484
- <div style="display: flex; flex-direction: column; gap: 8px;">
485
- ${BgWidget.selectFilter({
486
- gvc: gvc,
487
- callback: text => {
488
- voucherData.target = text;
489
- gvc.notifyDataChange(id);
490
- },
491
- default: voucherData.target ?? 'all',
492
- options: [
493
- {
494
- key: 'all',
495
- value: '所有顧客',
496
- },
497
- {
498
- key: 'customer',
499
- value: '特定顧客',
500
- },
501
- {
502
- key: 'levels',
503
- value: '會員等級',
504
- },
505
- // {
506
- // key: 'group',
507
- // value: '顧客分群',
508
- // },
509
- ],
510
- style: 'width: 100%;',
511
- })}
512
- <div>
513
- ${(() => {
514
- switch (voucherData.target) {
515
- case 'all':
516
- return '';
517
- case 'customer':
518
- return gvc.bindView(() => {
519
- const customVM = {
520
- id: gvc.glitter.getUUID(),
521
- loading: true,
522
- dataList: [] as OptionsItem[],
523
- };
524
- return {
525
- bind: customVM.id,
526
- view: () => {
527
- if (customVM.loading) {
528
- return BgWidget.spinner();
529
- }
530
- return html`
531
- <div class="d-flex flex-column p-2" style="gap: 18px;">
532
- <div
533
- class="d-flex align-items-center gray-bottom-line-18"
534
- style="justify-content: space-between;"
535
- >
536
- <div class="form-check-label c_updown_label">
537
- <div class="tx_normal">顧客名稱</div>
538
- </div>
539
- ${BgWidget.grayButton(
540
- '查看全部',
541
- gvc.event(() => {
542
- BgWidget.selectDropDialog({
543
- gvc: gvc,
544
- title: '搜尋特定顧客',
545
- tag: 'select_users',
546
- updownOptions: FilterOptions.userOrderBy,
547
- callback: value => {
548
- voucherData.targetList = value;
549
- customVM.loading = true;
550
- gvc.notifyDataChange(customVM.id);
551
- },
552
- default: voucherData.targetList ?? [],
553
- api: (data: { query: string; orderString: string }) => {
554
- return new Promise(resolve => {
555
- ApiUser.getUserListOrders({
556
- page: 0,
557
- limit: 99999,
558
- search: data.query,
559
- orderString: data.orderString,
560
- }).then(dd => {
561
- if (dd.response.data) {
562
- resolve(
563
- dd.response.data.map(
564
- (item: {
565
- userID: number;
566
- userData: {
567
- name: string;
568
- email: string;
569
- };
570
- }) => {
571
- return {
572
- key: item.userID,
573
- value:
574
- item.userData.name ?? '(尚無姓名)',
575
- note: item.userData.email,
576
- };
577
- }
578
- )
579
- );
580
- }
581
- });
582
- });
583
- },
584
- style: 'width: 100%;',
585
- });
586
- }),
587
- { textStyle: 'font-weight: 400;' }
588
- )}
589
- </div>
590
- ${obj.gvc.map(
591
- customVM.dataList.map((opt: OptionsItem, index) => {
592
- return html` <div class="form-check-label c_updown_label">
593
- <span class="tx_normal">${index + 1}. ${opt.value}</span>
594
- ${opt.note
595
- ? html` <span class="tx_gray_12 ms-2">${opt.note}</span> `
596
- : ''}
597
- </div>`;
598
- })
599
- )}
600
- </div>
601
- `;
602
- },
603
- onCreate: () => {
604
- if (customVM.loading) {
605
- if (voucherData.targetList.length === 0) {
606
- setTimeout(() => {
607
- customVM.dataList = [];
608
- customVM.loading = false;
609
- gvc.notifyDataChange(customVM.id);
610
- }, 200);
611
- } else {
612
- ApiUser.getUserList({
613
- page: 0,
614
- limit: 99999,
615
- id: voucherData.targetList.join(','),
616
- }).then(dd => {
617
- if (dd.response.data) {
618
- customVM.dataList = dd.response.data.map(
619
- (item: {
620
- userID: string;
621
- userData: {
622
- name: string;
623
- email: string;
624
- };
625
- }) => {
626
- return {
627
- key: item.userID,
628
- value: item.userData.name,
629
- note: item.userData.email,
630
- };
631
- }
632
- );
633
- }
634
- customVM.loading = false;
635
- gvc.notifyDataChange(customVM.id);
636
- });
637
- }
638
- }
639
- },
640
- };
641
- });
642
- case 'levels':
643
- return (() => {
644
- const levelVM = {
645
- id: gvc.glitter.getUUID(),
646
- loading: true,
647
- dataList: [],
648
- };
649
- return gvc.bindView({
650
- bind: levelVM.id,
651
- view: () => {
652
- if (levelVM.loading) {
653
- return BgWidget.spinner({ text: { visible: false } });
654
- } else {
655
- return BgWidget.selectDropList({
656
- gvc: gvc,
657
- callback: (value: []) => {
658
- voucherData.targetList = value;
659
- gvc.notifyDataChange(id);
660
- },
661
- default: voucherData.targetList ?? [],
662
- options: levelVM.dataList,
663
- style: 'width: 100%;',
664
- });
665
- }
666
- },
667
- divCreate: {
668
- style: 'width: 100%;',
669
- },
670
- onCreate: () => {
671
- if (levelVM.loading) {
672
- ApiUser.getPublicConfig('member_level_config', 'manager').then(
673
- (dd: any) => {
674
- if (dd.result && dd.response.value) {
675
- levelVM.dataList = dd.response.value.levels.map(
676
- (item: { id: string; tag_name: string }) => {
677
- return {
678
- key: item.id,
679
- value: item.tag_name,
680
- // note.txt: '人數'
681
- };
682
- }
683
- );
684
- levelVM.loading = false;
685
- gvc.notifyDataChange(levelVM.id);
686
- }
687
- }
688
- );
689
- }
690
- },
691
- });
692
- })();
693
- case 'group':
694
- return (() => {
695
- const levelVM = {
696
- id: gvc.glitter.getUUID(),
697
- loading: true,
698
- dataList: [],
699
- };
700
- return gvc.bindView({
701
- bind: levelVM.id,
702
- view: () => {
703
- if (levelVM.loading) {
704
- return BgWidget.spinner({ text: { visible: false } });
705
- } else {
706
- return BgWidget.selectDropList({
707
- gvc: gvc,
708
- callback: (value: []) => {
709
- voucherData.targetList = value;
710
- gvc.notifyDataChange(id);
711
- },
712
- default: voucherData.targetList ?? [],
713
- options: levelVM.dataList,
714
- style: 'width: 100%;',
715
- });
716
- }
717
- },
718
- divCreate: {
719
- style: 'width: 100%;',
720
- },
721
- onCreate: () => {
722
- if (levelVM.loading) {
723
- ApiUser.getUserGroupList().then((dd: any) => {
724
- if (dd.result && dd.response.data) {
725
- levelVM.dataList = dd.response.data
726
- .filter((item: any) => {
727
- return item.type !== 'level';
728
- })
729
- .map((item: any) => {
730
- return {
731
- key: item.type,
732
- value: item.title,
733
- };
734
- });
735
- levelVM.loading = false;
736
- gvc.notifyDataChange(levelVM.id);
737
- }
738
- });
739
- }
740
- },
741
- });
742
- })();
743
- default:
744
- return '';
745
- }
746
- })()}
747
- </div>
748
- </div>
749
- `;
750
- },
751
- };
752
- })}`,
753
- html` <div class="tx_700">可使用訂單來源</div>
754
- ${BgWidget.mbContainer(18)}
755
- ${BgWidget.multiCheckboxContainer(
756
- gvc,
757
- [
758
- { key: 'normal', name: 'APP & 官網' },
759
- { key: 'pos', name: 'POS' },
760
- ],
761
- voucherData.device ?? ['normal'],
762
- text => {
763
- voucherData.device = text as ('normal' | 'pos')[];
764
- gvc.notifyDataChange(viewID);
765
- },
766
- { single: false }
767
- )}`,
946
+ trigger(),
947
+ target(),
948
+ device(),
949
+ voucherData.reBackType === 'shipment_free' ? selectShipment() : '',
768
950
  ]
769
- .map(str => {
770
- return html` <div>${str}</div>`;
771
- })
951
+ .filter(Boolean)
952
+ .map(str => html`<div>${str}</div>`)
772
953
  .join(BgWidget.horizontalLine())
773
954
  ),
774
955
  BgWidget.mainCard(
@@ -781,6 +962,7 @@ export class ShoppingDiscountSetting {
781
962
  product: JSON.parse(JSON.stringify(voucherData.forKey)),
782
963
  manager_tag: JSON.parse(JSON.stringify(voucherData.forKey)),
783
964
  };
965
+
784
966
  return {
785
967
  bind: id,
786
968
  dataList: [
@@ -793,6 +975,7 @@ export class ShoppingDiscountSetting {
793
975
  if (['shipment_free', 'add_on_items', 'giveaway'].includes(voucherData.reBackType)) {
794
976
  return [];
795
977
  }
978
+
796
979
  const valueInput = (obj: { startText?: string; endText?: string }) => {
797
980
  return BgWidget.editeInput({
798
981
  gvc: gvc,
@@ -804,10 +987,9 @@ export class ShoppingDiscountSetting {
804
987
  callback: text => {
805
988
  const texInt = parseInt(text, 10);
806
989
  if (voucherData.method === 'percent' && (texInt > 100 || texInt < 0)) {
807
- const dialog = new ShareDialog(gvc.glitter);
808
990
  dialog.infoMessage({ text: '數值需介於0~100' });
809
991
  gvc.notifyDataChange(id);
810
- gvc.notifyDataChange(pageVM.countingId);
992
+ gvc.notifyDataChange(pageVM.countingID);
811
993
  } else {
812
994
  voucherData.value = text;
813
995
  }
@@ -816,6 +998,7 @@ export class ShoppingDiscountSetting {
816
998
  endText: obj.endText,
817
999
  });
818
1000
  };
1001
+
819
1002
  return [
820
1003
  html` <div>
821
1004
  <div class="tx_700">折扣金額</div>
@@ -837,8 +1020,8 @@ export class ShoppingDiscountSetting {
837
1020
  [voucherData.method],
838
1021
  text => {
839
1022
  voucherData.value = '0';
840
- voucherData.method = text[0] as 'fixed' | 'percent';
841
- gvc.notifyDataChange(pageVM.conditionId);
1023
+ voucherData.method = text[0] as Method;
1024
+ gvc.notifyDataChange(pageVM.conditionID);
842
1025
  },
843
1026
  { single: true }
844
1027
  )}
@@ -849,6 +1032,7 @@ export class ShoppingDiscountSetting {
849
1032
  if (voucherData.trigger === 'distribution') {
850
1033
  return [];
851
1034
  }
1035
+
852
1036
  return [
853
1037
  html`
854
1038
  <div class="tx_700">套用至</div>
@@ -1097,137 +1281,13 @@ export class ShoppingDiscountSetting {
1097
1281
  };
1098
1282
  })
1099
1283
  ),
1100
- ...(() => {
1101
- if (['giveaway', 'add_on_items'].includes(voucherData.reBackType)) {
1102
- return [
1103
- BgWidget.mainCard(
1104
- gvc.bindView(() => {
1105
- const vm = {
1106
- id: gvc.glitter.getUUID(),
1107
- };
1108
- if (!Array.isArray(voucherData.add_on_products)) {
1109
- voucherData.add_on_products = [];
1110
- }
1111
- return {
1112
- bind: vm.id,
1113
- view: () => {
1114
- return html`
1115
- <div class="tx_700">
1116
- ${voucherData.reBackType === 'add_on_items' ? `加購品項` : `贈品品項`}
1117
- </div>
1118
- ${BgWidget.mbContainer(18)}
1119
- ${obj.gvc.bindView(() => {
1120
- const id = gvc.glitter.getUUID();
1121
- return {
1122
- bind: id,
1123
- view: () => {
1124
- try {
1125
- return html`
1126
- <div
1127
- class="d-flex align-items-center gray-bottom-line-18"
1128
- style="gap: 24px; justify-content: space-between;"
1129
- >
1130
- <div class="form-check-label c_updown_label">
1131
- <div class="tx_normal">商品列表</div>
1132
- </div>
1133
- ${BgWidget.grayButton(
1134
- '選擇商品',
1135
- gvc.event(() => {
1136
- BgProduct.productsDialog({
1137
- gvc: gvc,
1138
- default: voucherData.add_on_products ?? [],
1139
- callback: async value => {
1140
- voucherData.add_on_products = value;
1141
- gvc.notifyDataChange(id);
1142
- },
1143
- filter: dd => {
1144
- return true;
1145
- },
1146
- productType:
1147
- voucherData.reBackType === 'add_on_items'
1148
- ? 'addProduct'
1149
- : 'giveaway',
1150
- });
1151
- }),
1152
- { textStyle: 'font-weight: 400;' }
1153
- )}
1154
- </div>
1155
- ${gvc.bindView(() => {
1156
- const vm: {
1157
- id: string;
1158
- loading: boolean;
1159
- data: OptionsItem[];
1160
- } = {
1161
- id: gvc.glitter.getUUID(),
1162
- loading: true,
1163
- data: [],
1164
- };
1165
- BgProduct.getProductOpts(
1166
- voucherData.add_on_products!,
1167
- voucherData.reBackType === 'add_on_items' ? 'addProduct' : 'giveaway'
1168
- ).then(res => {
1169
- vm.data = res;
1170
- vm.loading = false;
1171
- gvc.notifyDataChange(vm.id);
1172
- });
1173
- return {
1174
- bind: vm.id,
1175
- view: async () => {
1176
- if (vm.loading) {
1177
- return BgWidget.spinner();
1178
- }
1179
- return vm.data
1180
- .map((opt: OptionsItem, index) => {
1181
- return html` <div
1182
- class="d-flex align-items-center form-check-label c_updown_label gap-3"
1183
- >
1184
- <span class="tx_normal">${index + 1}.</span>
1185
- ${BgWidget.validImageBox({
1186
- gvc: gvc,
1187
- image: opt.image,
1188
- width: 40,
1189
- })}
1190
- <div class="tx_normal ${opt.note ? 'mb-1' : ''}">
1191
- ${opt.value}
1192
- </div>
1193
- ${opt.note
1194
- ? html` <div class="tx_gray_12">${opt.note}</div> `
1195
- : ''}
1196
- </div>`;
1197
- })
1198
- .join('');
1199
- },
1200
- divCreate: {
1201
- class: `d-flex py-2 flex-column`,
1202
- style: `gap:10px;`,
1203
- },
1204
- };
1205
- })}
1206
- `;
1207
- } catch (e) {
1208
- console.error(e);
1209
- return '';
1210
- }
1211
- },
1212
- divCreate: {
1213
- class: `w-100`,
1214
- },
1215
- };
1216
- })}
1217
- `;
1218
- },
1219
- };
1220
- })
1221
- ),
1222
- ];
1223
- } else {
1224
- return [];
1225
- }
1226
- })(),
1284
+ ['giveaway', 'add_on_items'].includes(voucherData.reBackType)
1285
+ ? BgWidget.mainCard(rebackProduct())
1286
+ : '',
1227
1287
  BgWidget.mainCard(
1228
1288
  gvc.bindView(() => {
1229
1289
  return {
1230
- bind: pageVM.conditionId,
1290
+ bind: pageVM.conditionID,
1231
1291
  view: () => {
1232
1292
  const conditionInput = (text: string) => {
1233
1293
  return BgWidget.editeInput({
@@ -1238,7 +1298,7 @@ export class ShoppingDiscountSetting {
1238
1298
  placeHolder: '',
1239
1299
  callback: value => {
1240
1300
  voucherData.ruleValue = parseInt(value, 10);
1241
- gvc.notifyDataChange(pageVM.conditionId);
1301
+ gvc.notifyDataChange(pageVM.conditionID);
1242
1302
  },
1243
1303
  endText: text,
1244
1304
  });
@@ -1274,8 +1334,8 @@ export class ShoppingDiscountSetting {
1274
1334
  [voucherData.rule],
1275
1335
  text => {
1276
1336
  voucherData.ruleValue = 0;
1277
- voucherData.rule = text[0] as 'min_price' | 'min_count';
1278
- gvc.notifyDataChange(pageVM.conditionId);
1337
+ voucherData.rule = text[0] as Rule;
1338
+ gvc.notifyDataChange(pageVM.conditionID);
1279
1339
  },
1280
1340
  { single: true }
1281
1341
  )}`,
@@ -1309,46 +1369,16 @@ export class ShoppingDiscountSetting {
1309
1369
  ],
1310
1370
  [voucherData.conditionType],
1311
1371
  text => {
1312
- voucherData.conditionType = text[0] as 'item' | 'order';
1313
- gvc.notifyDataChange(pageVM.conditionId);
1372
+ voucherData.conditionType = text[0] as ConditionType;
1373
+ gvc.notifyDataChange(pageVM.conditionID);
1314
1374
  },
1315
1375
  {
1316
1376
  single: true,
1317
1377
  readonly: voucherData.reBackType === 'shipment_free',
1318
1378
  }
1319
1379
  )}`,
1320
- html` ${BgWidget.horizontalLine()}
1321
- <div class="tx_700">消費金額於其他折扣觸發時機</div>
1322
- ${BgWidget.mbContainer(18)}
1323
- ${BgWidget.multiCheckboxContainer(
1324
- gvc,
1325
- [
1326
- {
1327
- key: 'before',
1328
- name: '觸發前',
1329
- innerHtml: BgWidget.grayNote(
1330
- '在其他折扣觸發前,訂單的消費金額將做為達成消費條件的金額,來判斷是否可使用此優惠券'
1331
- ),
1332
- },
1333
- {
1334
- key: 'after',
1335
- name: '觸發後',
1336
- innerHtml: BgWidget.grayNote(
1337
- '將訂單的消費金額包含其他折扣後,做為達成消費條件的金額,來判斷是否可使用此優惠券'
1338
- ),
1339
- },
1340
- ],
1341
- [voucherData.includeDiscount],
1342
- text => {
1343
- voucherData.includeDiscount = text[0] as 'before' | 'after';
1344
- gvc.notifyDataChange(pageVM.conditionId);
1345
- },
1346
- {
1347
- single: true,
1348
- }
1349
- )}`,
1350
1380
  gvc.bindView({
1351
- bind: pageVM.countingId,
1381
+ bind: pageVM.countingID,
1352
1382
  view: () => {
1353
1383
  if (voucherData.method === 'percent' || voucherData.reBackType === 'shipment_free') {
1354
1384
  return '';
@@ -1376,8 +1406,8 @@ export class ShoppingDiscountSetting {
1376
1406
  ],
1377
1407
  [voucherData.counting],
1378
1408
  text => {
1379
- voucherData.counting = text[0] as 'single' | 'each';
1380
- gvc.notifyDataChange(pageVM.conditionId);
1409
+ voucherData.counting = text[0] as Counting;
1410
+ gvc.notifyDataChange(pageVM.conditionID);
1381
1411
  },
1382
1412
  {
1383
1413
  single: true,
@@ -1386,7 +1416,7 @@ export class ShoppingDiscountSetting {
1386
1416
  },
1387
1417
  }),
1388
1418
  gvc.bindView({
1389
- bind: pageVM.productOffId,
1419
+ bind: pageVM.productOffID,
1390
1420
  view: () => {
1391
1421
  if (
1392
1422
  !(
@@ -1430,7 +1460,7 @@ export class ShoppingDiscountSetting {
1430
1460
  | 'price_asc'
1431
1461
  | 'price_desc'
1432
1462
  | 'price_all';
1433
- gvc.notifyDataChange(pageVM.productOffId);
1463
+ gvc.notifyDataChange(pageVM.productOffID);
1434
1464
  },
1435
1465
  {
1436
1466
  single: true,
@@ -1449,28 +1479,66 @@ export class ShoppingDiscountSetting {
1449
1479
  return {
1450
1480
  bind: id,
1451
1481
  view: () => {
1452
- return html` <div class="tx_700">是否與其他優惠券疊加使用</div>
1453
- ${BgWidget.mbContainer(18)}
1454
- ${BgWidget.multiCheckboxContainer(
1455
- gvc,
1456
- [
1457
- {
1458
- key: 'false',
1459
- name: '不可疊加',
1460
- innerHtml: BgWidget.grayNote('系統將以最大優惠排序進行判定'),
1482
+ function overlay() {
1483
+ return html` <div class="tx_700">是否與其他優惠券疊加使用</div>
1484
+ ${BgWidget.mbContainer(18)}
1485
+ ${BgWidget.multiCheckboxContainer(
1486
+ gvc,
1487
+ [
1488
+ {
1489
+ key: 'false',
1490
+ name: '不可疊加',
1491
+ innerHtml: BgWidget.grayNote('系統將以最大優惠排序進行判定'),
1492
+ },
1493
+ {
1494
+ key: 'true',
1495
+ name: '可以疊加',
1496
+ },
1497
+ ],
1498
+ [voucherData.overlay ? 'true' : 'false'],
1499
+ text => {
1500
+ voucherData.overlay = text[0] === 'true';
1501
+ gvc.notifyDataChange(id);
1461
1502
  },
1462
- {
1463
- key: 'true',
1464
- name: '可以疊加',
1503
+ { single: true }
1504
+ )}`;
1505
+ }
1506
+
1507
+ function isIncludeDiscount() {
1508
+ return html` <div class="tx_700">消費金額於其他折扣觸發時機</div>
1509
+ ${BgWidget.mbContainer(18)}
1510
+ ${BgWidget.multiCheckboxContainer(
1511
+ gvc,
1512
+ [
1513
+ {
1514
+ key: 'before',
1515
+ name: '觸發前',
1516
+ innerHtml: BgWidget.grayNote(
1517
+ '在其他折扣觸發前,訂單的消費金額將做為達成消費條件的金額,來判斷是否可使用此優惠券'
1518
+ ),
1519
+ },
1520
+ {
1521
+ key: 'after',
1522
+ name: '觸發後',
1523
+ innerHtml: BgWidget.grayNote(
1524
+ '將訂單的消費金額包含其他折扣後,做為達成消費條件的金額,來判斷是否可使用此優惠券'
1525
+ ),
1526
+ },
1527
+ ],
1528
+ [voucherData.includeDiscount],
1529
+ text => {
1530
+ voucherData.includeDiscount = text[0] as IncludeDiscount;
1531
+ gvc.notifyDataChange(pageVM.conditionID);
1465
1532
  },
1466
- ],
1467
- [voucherData.overlay ? 'true' : 'false'],
1468
- text => {
1469
- voucherData.overlay = text[0] === 'true';
1470
- gvc.notifyDataChange(id);
1471
- },
1472
- { single: true }
1473
- )}`;
1533
+ {
1534
+ single: true,
1535
+ }
1536
+ )}`;
1537
+ }
1538
+
1539
+ return [overlay(), voucherData.overlay ? isIncludeDiscount() : '']
1540
+ .filter(Boolean)
1541
+ .join(BgWidget.horizontalLine());
1474
1542
  },
1475
1543
  };
1476
1544
  })
@@ -1478,12 +1546,13 @@ export class ShoppingDiscountSetting {
1478
1546
  BgWidget.mainCard(
1479
1547
  gvc.bindView(() => {
1480
1548
  const id = glitter.getUUID();
1549
+ const inputStyle = 'display: block; width: 200px;';
1550
+
1481
1551
  return {
1482
1552
  bind: id,
1483
1553
  view: () => {
1484
- const inputStyle = 'display: block; width: 200px;';
1485
- return [
1486
- html` <div class="tx_700">全館總使用次數</div>
1554
+ function storeUseTimeLimit() {
1555
+ return html` <div class="tx_700">全館總使用次數</div>
1487
1556
  ${BgWidget.mbContainer(18)}
1488
1557
  ${BgWidget.multiCheckboxContainer(
1489
1558
  gvc,
@@ -1519,8 +1588,11 @@ export class ShoppingDiscountSetting {
1519
1588
  }
1520
1589
  },
1521
1590
  { single: true }
1522
- )}`,
1523
- html` <div class="tx_700">個人總使用次數</div>
1591
+ )}`;
1592
+ }
1593
+
1594
+ function memberUseTimeLimit() {
1595
+ return html` <div class="tx_700">個人總使用次數</div>
1524
1596
  ${BgWidget.mbContainer(18)}
1525
1597
  ${BgWidget.multiCheckboxContainer(
1526
1598
  gvc,
@@ -1556,61 +1628,11 @@ export class ShoppingDiscountSetting {
1556
1628
  }
1557
1629
  },
1558
1630
  { single: true }
1559
- )}`,
1560
- ...(() => {
1561
- if (voucherData.reBackType === 'rebate') {
1562
- return [
1563
- [
1564
- `<div class="tx_700">購物金有效天數</div>`,
1565
- BgWidget.multiCheckboxContainer(
1566
- gvc,
1567
- [
1568
- {
1569
- key: 'noEnd',
1570
- name: '無期限',
1571
- },
1572
- {
1573
- key: 'withEnd',
1574
- name: '有效期限',
1575
- innerHtml: html` <div
1576
- class="d-flex mt-0 mt-md-3 ${document.body.clientWidth < 768
1577
- ? 'flex-column'
1578
- : ''}"
1579
- style="gap: 12px"
1580
- >
1581
- <div class="d-flex align-items-center" style="gap:10px;">
1582
- ${BgWidget.editeInput({
1583
- gvc: gvc,
1584
- title: '',
1585
- type: 'number',
1586
- style: inputStyle,
1587
- default: `${voucherData.rebateEndDay ?? ''}`,
1588
- placeHolder: '0則為無期限',
1589
- callback: text => {
1590
- voucherData.rebateEndDay = text;
1591
- gvc.notifyDataChange(id);
1592
- },
1593
- })}
1594
- <span class="tx_normal me-2">天</span>
1595
- </div>
1596
- </div>`,
1597
- },
1598
- ],
1599
- [parseInt(voucherData.rebateEndDay ?? '0', 10) ? `withEnd` : `noEnd`],
1600
- text => {
1601
- if (text[0] === 'noEnd') {
1602
- voucherData.rebateEndDay = '0';
1603
- }
1604
- },
1605
- { single: true }
1606
- ),
1607
- ].join('<div class="my-2"></div>'),
1608
- ];
1609
- } else {
1610
- return [];
1611
- }
1612
- })(),
1613
- html` <div class="tx_700">優惠券有效日期</div>
1631
+ )}`;
1632
+ }
1633
+
1634
+ function startDateTime() {
1635
+ return html` <div class="tx_700">優惠券有效日期</div>
1614
1636
  <div
1615
1637
  class="d-flex mb-3 ${document.body.clientWidth < 768 ? 'flex-column' : ''}"
1616
1638
  style="gap: 12px"
@@ -1699,17 +1721,72 @@ export class ShoppingDiscountSetting {
1699
1721
  }
1700
1722
  },
1701
1723
  { single: true }
1702
- )}`,
1724
+ )}`;
1725
+ }
1726
+
1727
+ function rebateEndDay() {
1728
+ return [
1729
+ html`<div class="tx_700">購物金有效天數</div>`,
1730
+ BgWidget.multiCheckboxContainer(
1731
+ gvc,
1732
+ [
1733
+ {
1734
+ key: 'noEnd',
1735
+ name: '無期限',
1736
+ },
1737
+ {
1738
+ key: 'withEnd',
1739
+ name: '有效期限',
1740
+ innerHtml: html` <div
1741
+ class="d-flex mt-0 mt-md-3 ${document.body.clientWidth < 768
1742
+ ? 'flex-column'
1743
+ : ''}"
1744
+ style="gap: 12px"
1745
+ >
1746
+ <div class="d-flex align-items-center" style="gap:10px;">
1747
+ ${BgWidget.editeInput({
1748
+ gvc: gvc,
1749
+ title: '',
1750
+ type: 'number',
1751
+ style: inputStyle,
1752
+ default: `${voucherData.rebateEndDay ?? ''}`,
1753
+ placeHolder: '0則為無期限',
1754
+ callback: text => {
1755
+ voucherData.rebateEndDay = text;
1756
+ gvc.notifyDataChange(id);
1757
+ },
1758
+ })}
1759
+ <span class="tx_normal me-2">天</span>
1760
+ </div>
1761
+ </div>`,
1762
+ },
1763
+ ],
1764
+ [parseInt(voucherData.rebateEndDay ?? '0', 10) ? `withEnd` : `noEnd`],
1765
+ text => {
1766
+ if (text[0] === 'noEnd') {
1767
+ voucherData.rebateEndDay = '0';
1768
+ }
1769
+ },
1770
+ { single: true }
1771
+ ),
1772
+ ].join(html`<div class="my-2"></div>`);
1773
+ }
1774
+
1775
+ return [
1776
+ storeUseTimeLimit(),
1777
+ memberUseTimeLimit(),
1778
+ voucherData.reBackType === 'rebate' ? rebateEndDay() : '',
1779
+ startDateTime(),
1703
1780
  ]
1704
- .filter(dd => {
1705
- return dd;
1706
- })
1781
+ .filter(Boolean)
1707
1782
  .join(BgWidget.horizontalLine());
1708
1783
  },
1709
1784
  };
1710
1785
  })
1711
1786
  ),
1712
- ].join(BgWidget.mbContainer(24)),
1787
+ ]
1788
+ .filter(Boolean)
1789
+ .join(BgWidget.mbContainer(24)),
1713
1790
  ratio: 68,
1714
1791
  },
1715
1792
  {
@@ -1722,31 +1799,19 @@ export class ShoppingDiscountSetting {
1722
1799
  return { obj: voucherData, key };
1723
1800
  }),
1724
1801
  view: () => {
1725
- return BgWidget.mainCard(
1726
- gvc.bindView(() => {
1727
- const id = gvc.glitter.getUUID();
1728
- return {
1729
- bind: id,
1730
- view: () => {
1731
- return html`
1732
- <div class="tx_700">摘要</div>
1733
- ${BgWidget.mbContainer(18)}
1734
- <div style="display: flex; gap: 12px; flex-direction: column;">
1735
- ${gvc.map(
1736
- getVoucherTextList().map(text => {
1737
- return html` <div
1738
- class="${text.length > 0 ? 'tx_normal' : 'gray-top-bottom-line-6'}"
1739
- >
1740
- ${text}
1741
- </div>`;
1742
- })
1743
- )}
1744
- </div>
1745
- `;
1746
- },
1747
- };
1748
- })
1749
- );
1802
+ return BgWidget.mainCard(html`
1803
+ <div class="tx_700">摘要</div>
1804
+ ${BgWidget.mbContainer(18)}
1805
+ <div style="display: flex; gap: 12px; flex-direction: column;">
1806
+ ${summaryTextList()
1807
+ .map(text => {
1808
+ return html` <div class="${text.length > 0 ? 'tx_normal' : 'gray-top-bottom-line-6'}">
1809
+ ${text}
1810
+ </div>`;
1811
+ })
1812
+ .join('')}
1813
+ </div>
1814
+ `);
1750
1815
  },
1751
1816
  divCreate: {
1752
1817
  class: 'summary-card p-0',
@@ -1795,6 +1860,7 @@ export class ShoppingDiscountSetting {
1795
1860
  gvc.event(() => {
1796
1861
  voucherData.start_ISO_Date = '';
1797
1862
  voucherData.end_ISO_Date = '';
1863
+
1798
1864
  glitter.ut.tryMethod([
1799
1865
  () => {
1800
1866
  voucherData.start_ISO_Date = new Date(
@@ -1807,7 +1873,7 @@ export class ShoppingDiscountSetting {
1807
1873
  ).toISOString();
1808
1874
  },
1809
1875
  ]);
1810
- const dialog = new ShareDialog(gvc.glitter);
1876
+
1811
1877
  if (obj.type === 'replace') {
1812
1878
  dialog.dataLoading({ text: '正在更新優惠券', visible: true });
1813
1879
  ApiShop.putVoucher({