ts-glitter 22.4.6 → 22.4.9

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 (100) hide show
  1. package/lib/glitterBundle/Glitter.css +74 -62
  2. package/lowcode/Entry.js +1 -1
  3. package/lowcode/Entry.ts +1 -1
  4. package/lowcode/backend-manager/bg-product.js +49 -32
  5. package/lowcode/backend-manager/bg-product.ts +57 -39
  6. package/lowcode/backend-manager/bg-widget.js +17 -0
  7. package/lowcode/backend-manager/bg-widget.ts +18 -0
  8. package/lowcode/cms-plugin/information/information-module.js +5 -5
  9. package/lowcode/cms-plugin/information/information-module.ts +9 -5
  10. package/lowcode/cms-plugin/menus-setting.js +69 -55
  11. package/lowcode/cms-plugin/menus-setting.ts +77 -61
  12. package/lowcode/cms-plugin/module/form-module.js +109 -89
  13. package/lowcode/cms-plugin/module/form-module.ts +680 -650
  14. package/lowcode/cms-plugin/module/product-excel.js +1 -0
  15. package/lowcode/cms-plugin/module/product-excel.ts +2 -0
  16. package/lowcode/cms-plugin/pos-pages/payment-page.js +28 -10
  17. package/lowcode/cms-plugin/pos-pages/payment-page.ts +29 -10
  18. package/lowcode/cms-plugin/shopping-allowance-manager.js +0 -1
  19. package/lowcode/cms-plugin/shopping-allowance-manager.ts +0 -1
  20. package/lowcode/cms-plugin/shopping-collections.js +367 -193
  21. package/lowcode/cms-plugin/shopping-collections.ts +664 -243
  22. package/lowcode/cms-plugin/shopping-information.js +392 -38
  23. package/lowcode/cms-plugin/shopping-information.ts +479 -87
  24. package/lowcode/cms-plugin/shopping-product-setting.js +2 -2
  25. package/lowcode/cms-plugin/shopping-product-setting.ts +2 -2
  26. package/lowcode/cms-plugin/shopping-setting-advance.js +906 -766
  27. package/lowcode/cms-plugin/shopping-setting-advance.ts +977 -841
  28. package/lowcode/cms-plugin/shopping-setting-basic.js +1547 -1285
  29. package/lowcode/cms-plugin/shopping-setting-basic.ts +1742 -1466
  30. package/lowcode/cms-plugin/stock-stores.js +1 -0
  31. package/lowcode/cms-plugin/stock-stores.ts +1 -0
  32. package/lowcode/cms-plugin/user-list.js +47 -12
  33. package/lowcode/cms-plugin/user-list.ts +52 -14
  34. package/lowcode/css/editor.css +6 -0
  35. package/lowcode/glitterBundle/Glitter.css +74 -62
  36. package/lowcode/jslib/nestable/index.html +317 -0
  37. package/lowcode/jslib/nestable/jquery.nestable.js +484 -0
  38. package/lowcode/official_view_component/form-widget/input-custom.js +98 -6
  39. package/lowcode/official_view_component/form-widget/input-custom.ts +121 -16
  40. package/lowcode/public-components/headers/header-class.js +63 -0
  41. package/lowcode/public-components/headers/header-class.ts +65 -0
  42. package/lowcode/public-components/headers/sy-02.js +386 -400
  43. package/lowcode/public-components/headers/sy-02.ts +482 -492
  44. package/lowcode/public-components/headers/sy-03.js +42 -43
  45. package/lowcode/public-components/headers/sy-03.ts +46 -43
  46. package/lowcode/public-components/headers/sy-04.js +43 -41
  47. package/lowcode/public-components/headers/sy-04.ts +48 -41
  48. package/lowcode/public-components/headers/sy-05.js +30 -27
  49. package/lowcode/public-components/headers/sy-05.ts +33 -27
  50. package/lowcode/public-components/product/product-list.js +160 -148
  51. package/lowcode/public-components/product/product-list.ts +186 -165
  52. package/lowcode/public-models/product.ts +26 -1
  53. package/lowcode/src/glitterBundle/Glitter.css +74 -62
  54. package/package.json +1 -1
  55. package/rxmnt81tnk.json +1 -0
  56. package/src/api-public/controllers/shop.js +10 -4
  57. package/src/api-public/controllers/shop.js.map +1 -1
  58. package/src/api-public/controllers/shop.ts +14 -9
  59. package/src/api-public/services/ezpay/tool.d.ts +1 -0
  60. package/src/api-public/services/mail.js +1 -1
  61. package/src/api-public/services/mail.js.map +1 -1
  62. package/src/api-public/services/mail.ts +1 -1
  63. package/src/api-public/services/monitor.js.map +1 -1
  64. package/src/api-public/services/monitor.ts +2 -0
  65. package/src/api-public/services/schedule.d.ts +0 -1
  66. package/src/api-public/services/schedule.js +12 -35
  67. package/src/api-public/services/schedule.js.map +1 -1
  68. package/src/api-public/services/schedule.ts +15 -39
  69. package/src/api-public/services/shopee.js +7 -17
  70. package/src/api-public/services/shopping.d.ts +27 -6
  71. package/src/api-public/services/shopping.js +364 -85
  72. package/src/api-public/services/shopping.js.map +1 -1
  73. package/src/api-public/services/shopping.ts +510 -101
  74. package/src/api-public/services/updated-table-checked.js +58 -1
  75. package/src/api-public/services/updated-table-checked.js.map +1 -1
  76. package/src/api-public/services/updated-table-checked.ts +62 -1
  77. package/src/api-public/services/user-update.js +14 -0
  78. package/src/api-public/services/user-update.js.map +1 -1
  79. package/src/api-public/services/user-update.ts +15 -0
  80. package/src/api-public/services/user.js +1 -1
  81. package/src/api-public/services/user.js.map +1 -1
  82. package/src/api-public/services/user.ts +1 -1
  83. package/src/app-project/serverless/src/modules/database.d.ts +1 -1
  84. package/src/app-project/serverless/src/modules/redis.d.ts +1 -1
  85. package/src/helper/glitter-util.d.ts +1 -0
  86. package/src/index.js +7 -4
  87. package/src/index.js.map +1 -1
  88. package/src/index.ts +45 -36
  89. package/src/modules/firebase.js +1 -0
  90. package/src/modules/firebase.js.map +1 -1
  91. package/src/modules/firebase.ts +1 -0
  92. package/src/seo-config.d.ts +2 -1
  93. package/src/seo-config.js +28 -22
  94. package/src/seo-config.js.map +1 -1
  95. package/src/seo-config.ts +33 -26
  96. package/src/services/saas-table-check.js.map +1 -1
  97. package/src/services/ses.js +4 -3
  98. package/src/services/ses.js.map +1 -1
  99. package/src/services/system-schedule.js.map +1 -1
  100. package/src/services/system-schedule.ts +1 -0
@@ -42,8 +42,10 @@ export class ShoppingCollections {
42
42
  },
43
43
  },
44
44
  dataList: undefined,
45
+ collectionList: [],
45
46
  query: '',
46
47
  allParents: [],
48
+ cloneTarget: null,
47
49
  };
48
50
  const dialog = new ShareDialog(gvc.glitter);
49
51
  const updateCollections = (data) => {
@@ -109,116 +111,152 @@ export class ShoppingCollections {
109
111
  dataList: [{ obj: vm, key: 'type' }],
110
112
  view: () => {
111
113
  if (vm.type === 'list') {
114
+ vm.cloneTarget = null;
112
115
  return BgWidget.container(html `
113
116
  <div class="title-container">
114
117
  ${BgWidget.title('商品分類')}
115
118
  <div class="flex-fill"></div>
116
119
  <div class="d-flex gap-2">
117
120
  ${BgWidget.grayButton('編輯順序', gvc.event(() => {
118
- return BgWidget.infoDialog({
121
+ const cloneCollectionList = vm.collectionList.slice();
122
+ return BgWidget.settingDialog({
119
123
  gvc,
120
124
  title: '編輯順序',
121
- innerHTML: gvc.bindView((() => {
125
+ width: 700,
126
+ innerHTML: (iGVC) => {
122
127
  const id = glitter.getUUID();
123
128
  let loading = true;
124
- return {
129
+ this.addStyle(iGVC);
130
+ return iGVC.bindView({
125
131
  bind: id,
126
132
  view: () => {
127
133
  if (loading) {
128
- this.addStyle(gvc);
129
- return '';
134
+ return BgWidget.spinner();
130
135
  }
131
- else {
132
- return html ` <div class="d-flex">
133
- <div class="parent-container">
134
- <div class="tx_title text-center mb-2">父層類別</div>
135
- <ul class="ul-style" id="parent-list">
136
- <!-- TS 生成的父層類別列表 -->
137
- </ul>
138
- </div>
139
- <div class="child-container">
140
- <div class="tx_title text-center mb-2">子層類別</div>
141
- <ul class="ul-style" id="child-list">
142
- <!-- TS 生成的子層類別列表 -->
143
- </ul>
136
+ return html `
137
+ <div class="p-2">
138
+ ${BgWidget.grayNote('提示:左鍵拖曳可排列順序,點擊可顯示向下一層分類')}
139
+ <div class="d-flex justify-content-start mt-3">
140
+ <div class="layer-container">
141
+ ${[0, 1, 2]
142
+ .map(depth => {
143
+ const title = ['第一層分類', '第二層分類', '第三層分類'][depth];
144
+ return html ` <div class="flex-1 layer-block">
145
+ <div class="tx_700 fs-4 text-center mb-2">${title}</div>
146
+ <ul class="ul-style" id="layer-list-${depth}"></ul>
147
+ </div>`;
148
+ })
149
+ .join('')}
144
150
  </div>
145
- </div>`;
146
- }
151
+ </div>
152
+ </div>
153
+ `;
147
154
  },
148
- divCreate: {},
149
155
  onCreate: () => {
156
+ var _a;
150
157
  if (loading) {
151
- gvc.addMtScript([
152
- {
153
- src: 'https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js',
154
- },
155
- ], () => {
158
+ iGVC.addMtScript([{ src: 'https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js' }], () => {
156
159
  const si = setInterval(() => {
157
- if (window.Sortable !== undefined) {
160
+ if (window.parent.Sortable !== undefined) {
158
161
  loading = false;
159
162
  clearInterval(si);
160
- gvc.notifyDataChange(id);
163
+ iGVC.notifyDataChange(id);
161
164
  }
162
165
  }, 300);
163
166
  }, () => { });
164
167
  }
165
168
  else {
169
+ const document = window.parent.document;
166
170
  function createListItem(item, index) {
171
+ var _a;
167
172
  const li = document.createElement('li');
168
173
  li.className = 'li-style';
169
174
  li.setAttribute('data-index', index.toString());
170
- li.setAttribute('data-parent', item.parentTitles[0] || 'root');
175
+ li.setAttribute('data-path', [...((_a = item.parentTitles) !== null && _a !== void 0 ? _a : []), item.title].join(' / '));
171
176
  li.innerHTML = `<span class="drag-icon"></span><span class="tx_normal">${item.title}</span>`;
177
+ li.addEventListener('click', (e) => {
178
+ var _a;
179
+ const target = e.currentTarget;
180
+ const ul = target.closest('ul');
181
+ if (ul) {
182
+ Array.from(ul.children).forEach((element) => {
183
+ element.style.backgroundColor = '#dddddd';
184
+ });
185
+ }
186
+ target.style.backgroundColor = '#d8ecda';
187
+ loadChildLayer([...((_a = item.parentTitles) !== null && _a !== void 0 ? _a : []), item.title]);
188
+ });
172
189
  return li;
173
190
  }
174
191
  function initSortable(containerId) {
175
- const el = document.querySelector(`#${containerId}`);
176
- window.Sortable.create(el, {
177
- animation: 150,
178
- onEnd: function () {
179
- const items = [...el.children].map(child => vm.dataList[parseInt(child.getAttribute('data-index'))]);
180
- ApiShop.sortCollections({
181
- data: { list: items },
182
- token: window.parent.config.token,
183
- }).then(res => {
184
- if (res.result && !res.response) {
185
- dialog.errorMessage({ text: '更改順序失敗' });
186
- }
187
- });
192
+ const el = document.getElementById(containerId);
193
+ window.parent.Sortable.create(el, {
194
+ animation: 200,
195
+ scroll: true,
196
+ onEnd: () => {
197
+ const items = [...el.children].map(child => { var _a; return (_a = vm.dataList) === null || _a === void 0 ? void 0 : _a[parseInt(child.getAttribute('data-index'))]; });
198
+ vm.collectionList = ShoppingCollections.sortedCollectionConfig(vm.collectionList, items);
188
199
  },
189
200
  });
190
201
  }
191
- function loadChildItems(parentTitle) {
192
- const childContainer = document.getElementById('child-list');
193
- childContainer.innerHTML = '';
194
- vm.dataList.forEach((item, index) => {
195
- if (item.parentTitles[0] === parentTitle) {
196
- childContainer.appendChild(createListItem(item, index));
202
+ function loadChildLayer(parentPath) {
203
+ var _a;
204
+ const nextDepth = parentPath.length;
205
+ const nextId = `layer-list-${nextDepth}`;
206
+ for (let i = nextDepth; i < 3; i++) {
207
+ const el = document.getElementById(`layer-list-${i}`);
208
+ if (el)
209
+ el.innerHTML = '';
210
+ }
211
+ const container = document.getElementById(nextId);
212
+ container.innerHTML = '';
213
+ (_a = vm.dataList) === null || _a === void 0 ? void 0 : _a.forEach((item, index) => {
214
+ var _a;
215
+ const path = (_a = item.parentTitles) !== null && _a !== void 0 ? _a : [];
216
+ if (path.length === parentPath.length &&
217
+ path.every((p, i) => p === parentPath[i])) {
218
+ container.appendChild(createListItem(item, index));
197
219
  }
198
220
  });
199
- initSortable('child-list');
221
+ initSortable(nextId);
200
222
  }
201
- const parentContainer = document.getElementById('parent-list');
202
- vm.dataList.forEach((item, index) => {
203
- if (item.parentTitles.length === 0) {
204
- const li = createListItem(item, index);
205
- li.addEventListener('click', () => {
206
- loadChildItems(item.title);
207
- document
208
- .querySelectorAll('#parent-list li')
209
- .forEach(li => li.classList.remove('selectCol'));
210
- li.classList.add('selectCol');
211
- });
212
- parentContainer.appendChild(li);
223
+ const root = document.getElementById('layer-list-0');
224
+ root.innerHTML = '';
225
+ (_a = vm.dataList) === null || _a === void 0 ? void 0 : _a.forEach((item, index) => {
226
+ var _a;
227
+ if (((_a = item.parentTitles) !== null && _a !== void 0 ? _a : []).length === 0) {
228
+ root.appendChild(createListItem(item, index));
213
229
  }
214
230
  });
215
- initSortable('parent-list');
231
+ initSortable('layer-list-0');
216
232
  }
217
233
  },
218
- };
219
- })()),
220
- closeCallback: () => {
221
- gvc.notifyDataChange(vm.id);
234
+ });
235
+ },
236
+ footer_html: (fGVC) => {
237
+ return [
238
+ BgWidget.cancel(fGVC.event(() => {
239
+ vm.collectionList = cloneCollectionList;
240
+ fGVC.closeDialog();
241
+ })),
242
+ BgWidget.save(fGVC.event(() => {
243
+ dialog.dataLoading({ visible: true });
244
+ ApiShop.sortCollections({
245
+ data: { list: vm.collectionList },
246
+ token: window.parent.config.token,
247
+ }).then(res => {
248
+ dialog.dataLoading({ visible: false });
249
+ if (res.result && !res.response) {
250
+ dialog.errorMessage({ text: '更改順序失敗' });
251
+ }
252
+ else {
253
+ dialog.successMessage({ text: '更改順序成功' });
254
+ fGVC.closeDialog();
255
+ gvc.notifyDataChange(vm.id);
256
+ }
257
+ });
258
+ })),
259
+ ].join('');
222
260
  },
223
261
  });
224
262
  }))}
@@ -249,7 +287,7 @@ export class ShoppingCollections {
249
287
  BgWidget.searchPlace(gvc.event(e => {
250
288
  vm.query = e.value;
251
289
  gvc.notifyDataChange(vm.id);
252
- }), vm.query || '', '搜尋類別'),
290
+ }), vm.query || '', '搜尋分類'),
253
291
  BgWidget.tableV3({
254
292
  gvc: gvc,
255
293
  getData: vmi => {
@@ -261,7 +299,8 @@ export class ShoppingCollections {
261
299
  const products = d.response.data;
262
300
  ApiShop.getCollection().then(data => {
263
301
  if (data.result && data.response.value.length > 0) {
264
- vm.allParents = ['(無)'].concat(data.response.value.map((item) => item.title));
302
+ vm.collectionList = data.response.value;
303
+ vm.allParents = [this.undefinedOption].concat(data.response.value.map((item) => item.title));
265
304
  const collections = updateCollections({
266
305
  products,
267
306
  collections: data.response.value,
@@ -286,7 +325,7 @@ export class ShoppingCollections {
286
325
  if (isChildren) {
287
326
  const parent = collectionsMap.get(dd.parentTitles[0]);
288
327
  if ((parent === null || parent === void 0 ? void 0 : parent.hidden) && dd.hidden) {
289
- dialog.infoMessage({ text: '請先開啟顯示父層類別' });
328
+ dialog.infoMessage({ text: '請先開啟顯示第一層分類' });
290
329
  }
291
330
  else {
292
331
  triggerHidden();
@@ -298,7 +337,7 @@ export class ShoppingCollections {
298
337
  }
299
338
  else {
300
339
  dialog.checkYesOrNot({
301
- text: '若關閉顯示該父層類別,所有子層也將會關閉顯示,是否確定要執行?',
340
+ text: '若關閉顯示該層分類,子層分類也將會關閉顯示,是否確定要執行?',
302
341
  callback: bool => bool && triggerHidden(),
303
342
  });
304
343
  }
@@ -309,12 +348,14 @@ export class ShoppingCollections {
309
348
  key: '標題',
310
349
  value: html `<div
311
350
  class="fs-7"
312
- style="min-width: ${document.body.clientWidth > 768 ? 400 : 225}px;"
351
+ style="min-width: ${document.body.clientWidth > 768
352
+ ? 400
353
+ : 225}px; padding-left: ${4 + dd.parentTitles.length * 12}px"
313
354
  >
314
- ${isChildren
315
- ? html ` <i class="fa-solid fa-arrow-turn-down-right me-2"></i
316
- >${dd.parentTitles.join(' / ')} / ${dd.title}`
317
- : dd.title}
355
+ ${dd.parentTitles.length > 0
356
+ ? html `<i class="fa-solid fa-arrow-turn-down-right me-1"></i>`
357
+ : ''}
358
+ ${dd.title}
318
359
  </div>`,
319
360
  },
320
361
  {
@@ -351,7 +392,9 @@ export class ShoppingCollections {
351
392
  });
352
393
  },
353
394
  rowClick: (_, index) => {
354
- vm.data = vm.dataList[index];
395
+ if (vm.dataList) {
396
+ vm.data = vm.dataList[index];
397
+ }
355
398
  vm.type = 'replace';
356
399
  },
357
400
  filter: [
@@ -359,12 +402,13 @@ export class ShoppingCollections {
359
402
  name: '批量移除',
360
403
  event: () => {
361
404
  dialog.checkYesOrNot({
362
- text: '確定要刪除商品類別嗎?<br/>(若此類別包含子類別,也將一併刪除)',
405
+ text: '確定要刪除商品分類嗎?<br/>(若包含子分類,也將一併刪除)',
363
406
  callback: response => {
407
+ var _a;
364
408
  if (response) {
365
409
  dialog.dataLoading({ visible: true });
366
410
  ApiShop.deleteCollections({
367
- data: { data: vm.dataList.filter((dd) => dd.checked) },
411
+ data: { data: (_a = vm.dataList) === null || _a === void 0 ? void 0 : _a.filter(dd => dd.checked) },
368
412
  token: window.parent.config.token,
369
413
  }).then(res => {
370
414
  dialog.dataLoading({ visible: false });
@@ -390,6 +434,7 @@ export class ShoppingCollections {
390
434
  `);
391
435
  }
392
436
  else if (vm.type == 'replace') {
437
+ vm.cloneTarget = null;
393
438
  return this.editorDetail({
394
439
  vm: vm,
395
440
  gvc: gvc,
@@ -409,33 +454,33 @@ export class ShoppingCollections {
409
454
  }
410
455
  static addStyle(gvc) {
411
456
  gvc.addStyle(`
412
- .parent-container,
413
- .child-container {
414
- flex: 1;
457
+ .layer-container {
458
+ display: flex;
459
+ gap: 18px;
415
460
  margin-right: 20px;
416
461
  }
417
462
 
418
- .parent-container:last-child,
419
- .child-container:last-child {
420
- margin-right: 0;
421
- }
422
-
423
463
  .ul-style {
424
464
  list-style-type: none;
425
- padding: 0;
465
+ padding: 8px;
426
466
  margin: 0;
427
467
  min-height: 200px;
428
468
  border: 1px solid #ccc;
469
+ border-radius: 10px;
470
+ width: 190px;
471
+ height: 380px;
472
+ overflow-y: auto;
429
473
  }
430
474
 
431
475
  .li-style {
476
+ width: 100%;
432
477
  padding: 6px 10px;
433
- margin-bottom: 5px;
434
- background-color: #eee;
478
+ margin-bottom: 6px;
479
+ background-color: #dddddd;
435
480
  cursor: move;
436
- border: 1px solid #ccc;
437
481
  display: flex;
438
482
  align-items: center;
483
+ border-radius: 10px;
439
484
  }
440
485
 
441
486
  .drag-icon {
@@ -444,34 +489,32 @@ export class ShoppingCollections {
444
489
  }
445
490
 
446
491
  .drag-icon::before {
447
- content: '';
448
- font-size: 18px;
449
- margin-right: 10px;
450
- }
451
-
452
- .selectCol {
453
- background-color: #dcdcdc;
492
+ content: '';
493
+ font-size: 20px;
494
+ cursor: grab;
454
495
  }
455
496
  `);
456
497
  }
457
498
  static editorDetail(obj) {
499
+ var _a;
458
500
  const gvc = obj.gvc;
459
501
  const glitter = gvc.glitter;
460
502
  const vm = obj.vm;
503
+ const dialog = new ShareDialog(glitter);
461
504
  const original = JSON.parse(JSON.stringify(vm.data));
462
- const dialog = new ShareDialog(gvc.glitter);
505
+ const originDataList = JSON.parse(JSON.stringify((_a = vm.dataList) !== null && _a !== void 0 ? _a : []));
463
506
  const language_setting = window.parent.store_info.language_setting;
464
507
  let select_lan = language_setting.def;
465
508
  function getValidLangDomain() {
466
509
  const supports = language_setting.support;
467
- const dataList = vm.dataList.filter((data) => data.title !== vm.data.title);
510
+ const targetData = vm.cloneTarget && vm.cloneTarget.title === vm.data.title ? vm.cloneTarget : original;
511
+ const dataList = originDataList.filter(item => {
512
+ return [...item.parentTitles, item.title].join('') !== [...targetData.parentTitles, targetData.title].join('');
513
+ });
468
514
  const lagDomain = supports.map(lang => {
469
- const domainMap = dataList.map((item) => {
470
- if (!item.language_data) {
471
- return '';
472
- }
515
+ const domainMap = dataList === null || dataList === void 0 ? void 0 : dataList.map(item => {
473
516
  try {
474
- return item.language_data[lang].seo.domain;
517
+ return item.language_data ? item.language_data[lang].seo.domain : '';
475
518
  }
476
519
  catch (error) {
477
520
  return '';
@@ -488,7 +531,7 @@ export class ShoppingCollections {
488
531
  });
489
532
  return {
490
533
  result: false,
491
- text: `語系「${text}」的連結網址「${vm.data.language_data[data.lang].seo.domain}」<br />已存在於其他類別,請更換連結網址`,
534
+ text: `語系「${text}」的連結網址「${vm.data.language_data[data.lang].seo.domain}」<br />已存在於其他分類,請更換連結網址`,
492
535
  };
493
536
  }
494
537
  }
@@ -497,9 +540,7 @@ export class ShoppingCollections {
497
540
  return gvc.bindView(() => {
498
541
  const viewID = gvc.glitter.getUUID();
499
542
  const domainID = gvc.glitter.getUUID();
500
- function refresh() {
501
- gvc.notifyDataChange(viewID);
502
- }
543
+ const refresh = () => gvc.notifyDataChange(viewID);
503
544
  return {
504
545
  bind: viewID,
505
546
  view: () => {
@@ -525,10 +566,10 @@ export class ShoppingCollections {
525
566
  ${BgWidget.goBack(gvc.event(() => {
526
567
  vm.type = 'list';
527
568
  }))}
528
- ${BgWidget.title(obj.type === 'add' ? '新增類別' : '編輯類別')}
569
+ ${BgWidget.title(obj.type === 'add' ? '新增分類' : '編輯分類')}
529
570
  <div class="flex-fill"></div>
530
- <div class="me-2 ">
531
- ${BgWidget.grayButton(html `<div class="d-flex align-items-center" style="gap:5px;">
571
+ <div class="d-flex align-items-center gap-2">
572
+ ${BgWidget.grayButton(html ` <div class="d-flex align-items-center gap-2">
532
573
  <i class="fa-duotone fa-solid fa-earth-americas"></i>${Language.getLanguageText({
533
574
  local: true,
534
575
  compare: select_lan,
@@ -543,7 +584,7 @@ export class ShoppingCollections {
543
584
  bind: id,
544
585
  view: () => {
545
586
  return html ` <div
546
- style="position: relative;word-break: break-all;white-space: normal;"
587
+ style="position: relative; word-break: break-all; white-space: normal;"
547
588
  >
548
589
  ${BgWidget.grayNote('前往商店設定->商店訊息中,設定支援的語言。')}
549
590
  ${gvc.bindView(() => {
@@ -567,7 +608,7 @@ export class ShoppingCollections {
567
608
  .filter(dd => {
568
609
  return window.parent.store_info.language_setting.support.includes(dd.key);
569
610
  })
570
- .sort((dd) => {
611
+ .sort(dd => {
571
612
  return dd.key === select_lan ? -1 : 1;
572
613
  });
573
614
  return html ` <div
@@ -575,7 +616,7 @@ export class ShoppingCollections {
575
616
  style="gap:15px;"
576
617
  >
577
618
  ${sup
578
- .map((dd) => {
619
+ .map(dd => {
579
620
  return html `
580
621
  <div
581
622
  class="px-3 py-1 text-white position-relative d-flex align-items-center justify-content-center"
@@ -590,8 +631,8 @@ export class ShoppingCollections {
590
631
  <div
591
632
  class="position-absolute text-white rounded-2 px-2 d-flex align-items-center rounded-3 ${dd.key !==
592
633
  select_lan
593
- ? `d-none`
594
- : ``}"
634
+ ? 'd-none'
635
+ : ''}"
595
636
  style="top: -12px;right: -10px; height:20px;font-size: 11px;background: #ff6c02;"
596
637
  >
597
638
  已選擇
@@ -606,8 +647,6 @@ export class ShoppingCollections {
606
647
  })}
607
648
  </div>`;
608
649
  },
609
- divCreate: {},
610
- onCreate: () => { },
611
650
  };
612
651
  })());
613
652
  },
@@ -618,6 +657,24 @@ export class ShoppingCollections {
618
657
  width: 300,
619
658
  });
620
659
  }))}
660
+ ${vm.type === 'add'
661
+ ? BgWidget.grayButton('代入現有分類', gvc.event(() => {
662
+ BgProduct.collectionsDialog({
663
+ gvc: gvc,
664
+ default: [],
665
+ callback: value => {
666
+ var _a;
667
+ const data = (_a = vm.dataList) === null || _a === void 0 ? void 0 : _a.find(item => [...item.parentTitles, item.title].join(' / ') === value[0]);
668
+ if (data) {
669
+ vm.data = data;
670
+ vm.cloneTarget = structuredClone(data);
671
+ }
672
+ gvc.notifyDataChange(viewID);
673
+ },
674
+ single: true,
675
+ });
676
+ }))
677
+ : ''}
621
678
  </div>
622
679
  </div>`,
623
680
  BgWidget.container1x2({
@@ -634,7 +691,7 @@ export class ShoppingCollections {
634
691
  })}`),
635
692
  BgWidget.mainCard(html ` <div class="d-flex flex-column" style="margin-bottom: 12px; gap:5px;">
636
693
  <div class="tx_700">前台分類顯示名稱 ${BgWidget.languageInsignia(select_lan)}</div>
637
- ${BgWidget.grayNote(`未設定則參照分類標籤顯示`)}
694
+ ${BgWidget.grayNote('未設定則參照分類標籤顯示')}
638
695
  </div>
639
696
  ${EditorElem.editeInput({
640
697
  gvc: gvc,
@@ -661,7 +718,7 @@ export class ShoppingCollections {
661
718
  gvc.bindView({
662
719
  bind: domainID,
663
720
  view: () => {
664
- return html `<div
721
+ return html ` <div
665
722
  class="${document.body.clientWidth < 800
666
723
  ? 'w-100'
667
724
  : ''} justify-content-start justify-content-lg-center"
@@ -824,62 +881,125 @@ export class ShoppingCollections {
824
881
  })}`,
825
882
  ,
826
883
  ].join(BgWidget.mbContainer(10))),
827
- ].join(html ` <div style="margin-top: 24px;"></div>`),
884
+ ].join(BgWidget.mbContainer(24)),
828
885
  ratio: 75,
829
886
  }, {
830
- html: [
831
- BgWidget.summaryCard((() => {
832
- var _a;
833
- if ((vm.data.allCollections &&
834
- vm.data.allCollections.length > 0 &&
835
- vm.data.parentTitles &&
836
- vm.data.parentTitles.length > 0) ||
837
- vm.type === 'add') {
838
- return html ` <div class="tx_700" style="margin-bottom: 12px">父層</div>
839
- ${BgWidget.select({
840
- gvc: gvc,
841
- callback: text => {
842
- vm.data.parentTitles[0] = text;
843
- },
844
- default: (_a = vm.data.parentTitles[0]) !== null && _a !== void 0 ? _a : '',
845
- options: vm.data.allCollections.map((item) => {
846
- return { key: item, value: item };
847
- }),
848
- style: 'margin: 8px 0;',
849
- })}`;
850
- }
851
- const id = gvc.glitter.getUUID();
852
- return html `
853
- <div class="tx_700" style="margin-bottom: 12px">子分類</div>
854
- ${gvc.bindView({
855
- bind: id,
856
- view: () => {
857
- return gvc.map(vm.data.subCollections.map((item) => {
858
- return html ` <div
859
- style="display: flex; align-items: center; justify-content: space-between; margin-top: 8px;"
860
- >
861
- ${item}<i
862
- class="fa-regular fa-trash cursor_pointer"
863
- onclick="${gvc.event(() => {
864
- vm.data.subCollections = vm.data.subCollections.filter((sub) => item !== sub);
865
- gvc.notifyDataChange(id);
866
- })}"
867
- ></i>
868
- </div>`;
869
- }));
870
- },
871
- })}
872
- `;
873
- })()),
874
- ].join(html ` <div style="margin-top: 24px;"></div>`),
887
+ html: gvc.bindView((() => {
888
+ const summaryId = glitter.getUUID();
889
+ return {
890
+ bind: summaryId,
891
+ view: () => {
892
+ function isUndefinedOption(key) {
893
+ return !key || ShoppingCollections.undefinedOption === key;
894
+ }
895
+ function firstParentView() {
896
+ var _a;
897
+ return [
898
+ html ` <div class="tx_700">第一層</div>`,
899
+ vm.type === 'add' && isUndefinedOption(vm.data.parentTitles[0])
900
+ ? BgWidget.grayNote('若未選取項目,則為第一層分類')
901
+ : '',
902
+ BgWidget.select({
903
+ gvc: gvc,
904
+ callback: text => {
905
+ vm.data.parentTitles[0] = text;
906
+ gvc.notifyDataChange(summaryId);
907
+ },
908
+ default: (_a = vm.data.parentTitles[0]) !== null && _a !== void 0 ? _a : '',
909
+ options: vm.data.allCollections.map((item) => {
910
+ return { key: item, value: item };
911
+ }),
912
+ style: 'margin: 8px 0;',
913
+ readonly: vm.type === 'replace',
914
+ }),
915
+ BgWidget.mbContainer(12),
916
+ ].join('');
917
+ }
918
+ function secondParentView(subs) {
919
+ var _a;
920
+ return [
921
+ html ` <div class="tx_700">第二層</div>`,
922
+ vm.type === 'add' && isUndefinedOption(vm.data.parentTitles[1])
923
+ ? BgWidget.grayNote('若未選取項目,則為第二層分類')
924
+ : '',
925
+ BgWidget.select({
926
+ gvc: gvc,
927
+ callback: text => {
928
+ vm.data.parentTitles[1] = text;
929
+ gvc.notifyDataChange(summaryId);
930
+ },
931
+ default: (_a = vm.data.parentTitles[1]) !== null && _a !== void 0 ? _a : '',
932
+ options: [ShoppingCollections.undefinedOption, ...subs].map((item) => {
933
+ return { key: item, value: item };
934
+ }),
935
+ style: 'margin: 8px 0;',
936
+ readonly: vm.type === 'replace',
937
+ }),
938
+ ].join('');
939
+ }
940
+ function editSubCollection() {
941
+ const id = gvc.glitter.getUUID();
942
+ if (vm.data.parentTitles.length === 2) {
943
+ return '';
944
+ }
945
+ return [
946
+ html ` <div class="tx_700" style="margin-bottom: 12px">子分類</div>`,
947
+ !vm.data.subCollections || vm.data.subCollections.length === 0
948
+ ? '尚未建立子分類'
949
+ : gvc.bindView({
950
+ bind: id,
951
+ view: () => vm.data.subCollections
952
+ .map((item) => {
953
+ return html ` <div
954
+ class="d-flex align-items-center justify-content-between mt-2"
955
+ >
956
+ ${item}<i
957
+ class="fa-regular fa-trash cursor_pointer"
958
+ onclick="${gvc.event(() => {
959
+ vm.data.subCollections = vm.data.subCollections.filter((sub) => item !== sub);
960
+ gvc.notifyDataChange(id);
961
+ })}"
962
+ ></i>
963
+ </div>`;
964
+ })
965
+ .join(''),
966
+ }),
967
+ ].join('');
968
+ }
969
+ function levelSetting() {
970
+ var _a;
971
+ const parentTitles = Array.isArray(vm.data.parentTitles) ? vm.data.parentTitles : [];
972
+ const parentTab = (_a = vm.dataList) === null || _a === void 0 ? void 0 : _a.find(item => item.title === parentTitles[0]);
973
+ const parentSubs = parentTab && Array.isArray(parentTab.subCollections) ? parentTab.subCollections : [];
974
+ if (vm.type === 'add') {
975
+ return [
976
+ firstParentView(),
977
+ parentSubs.length > 0
978
+ ? secondParentView(parentSubs.filter((item) => item !== vm.data.title))
979
+ : '',
980
+ ].join('');
981
+ }
982
+ if (vm.type === 'replace' && parentTitles.length > 0) {
983
+ return [
984
+ firstParentView(),
985
+ parentTitles[1] && parentSubs.length > 0 ? secondParentView(parentSubs) : '',
986
+ editSubCollection(),
987
+ ].join('');
988
+ }
989
+ return editSubCollection();
990
+ }
991
+ return [BgWidget.summaryCard(levelSetting())].join(BgWidget.mbContainer(24));
992
+ },
993
+ };
994
+ })()),
875
995
  ratio: 25,
876
996
  }),
877
997
  BgWidget.mbContainer(240),
878
998
  html ` <div class="update-bar-container">
879
999
  ${obj.type === 'replace'
880
- ? BgWidget.redButton('刪除類別', gvc.event(() => {
1000
+ ? BgWidget.redButton('刪除分類', gvc.event(() => {
881
1001
  dialog.checkYesOrNot({
882
- text: '確定要刪除商品類別嗎?<br/>(若此類別包含子類別,也將一併刪除)',
1002
+ text: '確定要刪除商品分類嗎?<br/>(若包含子分類,也將一併刪除)',
883
1003
  callback: bool => {
884
1004
  if (bool) {
885
1005
  dialog.dataLoading({ visible: true });
@@ -909,14 +1029,22 @@ export class ShoppingCollections {
909
1029
  dialog.infoMessage({ text: '請填寫「分類標籤」' });
910
1030
  return;
911
1031
  }
1032
+ const updateDataPath = [...vm.data.parentTitles, vm.data.title].join('');
1033
+ if ([...original.parentTitles, original.title].join('') !== updateDataPath) {
1034
+ const somePath = originDataList.some(item => {
1035
+ return [...item.parentTitles, item.title].join('') === updateDataPath;
1036
+ });
1037
+ if (somePath) {
1038
+ dialog.infoMessage({ text: '此「分類標籤」已存在' });
1039
+ return;
1040
+ }
1041
+ }
912
1042
  const forbiddenRegex = /[,/\\]/;
913
1043
  if (forbiddenRegex.test(vm.data.title)) {
914
1044
  dialog.infoMessage({ text: '標題不可包含空白格與以下符號:<br />「 , 」「 / 」「 \\ 」' });
915
1045
  return;
916
1046
  }
917
- const no_fill_language = window.parent.store_info.language_setting.support.find((dd) => {
918
- return !vm.data.language_data[dd].seo.domain;
919
- });
1047
+ const no_fill_language = window.parent.store_info.language_setting.support.find((dd) => !vm.data.language_data[dd].seo.domain);
920
1048
  if (no_fill_language) {
921
1049
  select_lan = no_fill_language;
922
1050
  refresh();
@@ -924,13 +1052,11 @@ export class ShoppingCollections {
924
1052
  return;
925
1053
  }
926
1054
  if (window.parent.store_info.language_setting.support.find((dd) => {
927
- if (!CheckInput.isChineseEnglishNumberHyphen(vm.data.language_data[dd].seo.domain)) {
928
- select_lan = dd;
929
- return true;
930
- }
931
- else {
1055
+ if (CheckInput.isChineseEnglishNumberHyphen(vm.data.language_data[dd].seo.domain)) {
932
1056
  return false;
933
1057
  }
1058
+ select_lan = dd;
1059
+ return true;
934
1060
  })) {
935
1061
  refresh();
936
1062
  dialog.infoMessage({ text: '連結僅限使用中英文數字與連接號' });
@@ -939,28 +1065,47 @@ export class ShoppingCollections {
939
1065
  const validLangDomain = getValidLangDomain();
940
1066
  if (!validLangDomain.result) {
941
1067
  refresh();
942
- dialog.warningMessage({ text: validLangDomain.text, callback: () => { } });
1068
+ dialog.infoMessage({ text: validLangDomain.text });
943
1069
  return;
944
1070
  }
945
- dialog.dataLoading({ visible: true });
946
- ApiShop.putCollections({
947
- data: { replace: vm.data, original },
948
- token: window.parent.config.token,
949
- }).then(res => {
950
- dialog.dataLoading({ visible: false });
951
- if (res.result) {
952
- if (res.response.result) {
953
- vm.type = 'list';
954
- dialog.successMessage({ text: '更新成功' });
1071
+ function putEvent() {
1072
+ dialog.dataLoading({ visible: true });
1073
+ ApiShop.putCollections({
1074
+ data: { replace: vm.data, original },
1075
+ token: window.parent.config.token,
1076
+ }).then(res => {
1077
+ dialog.dataLoading({ visible: false });
1078
+ if (res.result) {
1079
+ if (res.response.result) {
1080
+ vm.type = 'list';
1081
+ dialog.successMessage({ text: '更新成功' });
1082
+ }
1083
+ else {
1084
+ dialog.errorMessage({ text: res.response.message });
1085
+ }
955
1086
  }
956
1087
  else {
957
- dialog.errorMessage({ text: res.response.message });
1088
+ dialog.errorMessage({ text: '更新失敗' });
958
1089
  }
959
- }
960
- else {
961
- dialog.errorMessage({ text: '更新失敗' });
962
- }
963
- });
1090
+ });
1091
+ }
1092
+ if (vm.cloneTarget && vm.cloneTarget.title === vm.data.title) {
1093
+ dialog.checkYesOrNot({
1094
+ text: ['若移動當前商品分類,<b>附帶的子分類將不會保留</b>,', '確定要執行嗎?'].join('<br/>'),
1095
+ callback: bool => {
1096
+ if (bool && vm.cloneTarget) {
1097
+ ApiShop.deleteCollections({
1098
+ data: { data: [vm.cloneTarget] },
1099
+ token: window.parent.config.token,
1100
+ }).then(() => {
1101
+ putEvent();
1102
+ });
1103
+ }
1104
+ },
1105
+ });
1106
+ return;
1107
+ }
1108
+ putEvent();
964
1109
  }))}
965
1110
  </div>`,
966
1111
  ].join(BgWidget.mbContainer(24)));
@@ -968,5 +1113,34 @@ export class ShoppingCollections {
968
1113
  };
969
1114
  });
970
1115
  }
1116
+ static sortedCollectionConfig(config, dataArray) {
1117
+ var _a;
1118
+ if (!(dataArray === null || dataArray === void 0 ? void 0 : dataArray.length))
1119
+ return config;
1120
+ const parentTitles = (_a = dataArray[0].parentTitles) !== null && _a !== void 0 ? _a : [];
1121
+ function updateTree(currentLevel, depth) {
1122
+ if (depth === parentTitles.length) {
1123
+ const sorted = dataArray
1124
+ .map(item => {
1125
+ return currentLevel.find(c => c.title === item.title);
1126
+ })
1127
+ .filter(Boolean);
1128
+ for (let i = 0; i < sorted.length; i++) {
1129
+ currentLevel[i] = sorted[i];
1130
+ }
1131
+ currentLevel.length = sorted.length;
1132
+ return true;
1133
+ }
1134
+ const next = currentLevel.find(c => c.title === parentTitles[depth]);
1135
+ if (!next)
1136
+ return false;
1137
+ return updateTree(next.array, depth + 1);
1138
+ }
1139
+ const updated = updateTree(config, 0);
1140
+ if (!updated)
1141
+ throw new Error('找不到對應的父節點進行排序');
1142
+ return config;
1143
+ }
971
1144
  }
1145
+ ShoppingCollections.undefinedOption = '請選擇項目';
972
1146
  window.glitter.setModule(import.meta.url, ShoppingCollections);