ts-glitter 22.4.7 → 22.5.0

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 (98) 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/schedule.d.ts +0 -1
  64. package/src/api-public/services/schedule.js +12 -35
  65. package/src/api-public/services/schedule.js.map +1 -1
  66. package/src/api-public/services/schedule.ts +15 -39
  67. package/src/api-public/services/shopee.js +7 -17
  68. package/src/api-public/services/shopping.d.ts +27 -6
  69. package/src/api-public/services/shopping.js +364 -85
  70. package/src/api-public/services/shopping.js.map +1 -1
  71. package/src/api-public/services/shopping.ts +510 -101
  72. package/src/api-public/services/updated-table-checked.js +58 -1
  73. package/src/api-public/services/updated-table-checked.js.map +1 -1
  74. package/src/api-public/services/updated-table-checked.ts +62 -1
  75. package/src/api-public/services/user-update.js +14 -0
  76. package/src/api-public/services/user-update.js.map +1 -1
  77. package/src/api-public/services/user-update.ts +15 -0
  78. package/src/api-public/services/user.js +1 -1
  79. package/src/api-public/services/user.js.map +1 -1
  80. package/src/api-public/services/user.ts +1 -1
  81. package/src/app-project/serverless/src/modules/database.d.ts +1 -1
  82. package/src/app-project/serverless/src/modules/redis.d.ts +1 -1
  83. package/src/helper/glitter-util.d.ts +1 -0
  84. package/src/index.js +7 -5
  85. package/src/index.js.map +1 -1
  86. package/src/index.ts +45 -38
  87. package/src/modules/firebase.js +1 -0
  88. package/src/modules/firebase.js.map +1 -1
  89. package/src/modules/firebase.ts +1 -0
  90. package/src/seo-config.d.ts +1 -1
  91. package/src/seo-config.js +1 -2
  92. package/src/seo-config.js.map +1 -1
  93. package/src/seo-config.ts +1 -2
  94. package/src/services/saas-table-check.js.map +1 -1
  95. package/src/services/ses.js +4 -3
  96. package/src/services/ses.js.map +1 -1
  97. package/src/services/system-schedule.js.map +1 -1
  98. package/src/services/system-schedule.ts +1 -0
@@ -11,9 +11,10 @@ import { ProductSetting } from './module/product-setting.js';
11
11
  import { QuestionInfo } from './module/question-info.js';
12
12
  import { ProductAi } from './ai-generator/product-ai.js';
13
13
  import { ShoppingProductSetting } from './shopping-product-setting.js';
14
- import { ActiveSchedule, Product, Variant } from '../public-models/product.js';
14
+ import { Store, ActiveSchedule, Product, Variant } from '../public-models/product.js';
15
15
 
16
16
  const html = String.raw;
17
+ const css = String.raw;
17
18
 
18
19
  export class ShoppingSettingBasic {
19
20
  public static updateVariants(gvc: GVC, postMD: Product, shipment_config: any, variantsViewID: string, obj: any) {
@@ -83,24 +84,6 @@ export class ShoppingSettingBasic {
83
84
  }
84
85
  });
85
86
 
86
- postMD.variants = postMD.variants.filter(variant => {
87
- let pass = true;
88
- let index = 0;
89
- for (const b of variant.spec) {
90
- if (
91
- !postMD.specs[index] ||
92
- !postMD.specs[index].option.find((dd: any) => {
93
- return dd.title === b;
94
- })
95
- ) {
96
- pass = false;
97
- break;
98
- }
99
- index++;
100
- }
101
- return pass && variant.spec.length === postMD.specs.length;
102
- });
103
-
104
87
  if (postMD.variants.length === 0) {
105
88
  postMD.variants.push({
106
89
  show_understocking: 'true',
@@ -122,6 +105,27 @@ export class ShoppingSettingBasic {
122
105
  stockList: {},
123
106
  preview_image: '',
124
107
  });
108
+ } else {
109
+ if (postMD.variants.length === 1) {
110
+ } else {
111
+ postMD.variants = postMD.variants.filter(variant => {
112
+ let pass = true;
113
+ let index = 0;
114
+ for (const b of variant.spec) {
115
+ if (
116
+ !postMD.specs[index] ||
117
+ !postMD.specs[index].option.find((dd: any) => {
118
+ return dd.title === b;
119
+ })
120
+ ) {
121
+ pass = false;
122
+ break;
123
+ }
124
+ index++;
125
+ }
126
+ return pass && variant.spec.length === postMD.specs.length;
127
+ });
128
+ }
125
129
  }
126
130
 
127
131
  postMD.variants.map((dd: any) => {
@@ -170,6 +174,16 @@ export class ShoppingSettingBasic {
170
174
  const variantsViewID = gvc.glitter.getUUID();
171
175
  const dialog = new ShareDialog(gvc.glitter);
172
176
  const sel_lan = () => vm.language;
177
+ const section_ID = {
178
+ reserve_locations: gvc.glitter.getUUID(),
179
+ dialog_location_main: gvc.glitter.getUUID(),
180
+ dialog_location_list: gvc.glitter.getUUID(),
181
+ store_product_config_panel: gvc.glitter.getUUID(),
182
+ };
183
+ const loading = {
184
+ reserve_locations: true,
185
+ };
186
+ let stockList: Store[] = [];
173
187
  let selectFunRow = false;
174
188
  let createPage: any = { page: 'add' };
175
189
 
@@ -241,852 +255,1032 @@ export class ShoppingSettingBasic {
241
255
  });
242
256
  }
243
257
 
244
- ShoppingSettingBasic.updateVariants(gvc, postMD, shipment_config, variantsViewID, obj);
245
-
246
- const cat_title = (() => {
247
- switch (postMD.product_category) {
248
- case 'commodity':
249
- return '商品';
250
- case 'course':
251
- return '課程';
252
- case 'kitchen':
253
- return '餐飲組合';
254
- default:
255
- return '商品';
256
- }
257
- })();
258
-
259
- return BgWidget.container1x2(
260
- {
261
- html: [
262
- BgWidget.mainCard(html`
263
- <div class="d-flex flex-column guide5-4">
264
- <div style="font-weight: 700;">
265
- ${cat_title}名稱 ${BgWidget.requiredStar()}
266
- ${BgWidget.languageInsignia(vm.language, 'margin-left:5px;')}
267
- </div>
268
- ${BgWidget.editeInput({
269
- gvc: gvc,
270
- title: '',
271
- type: 'text',
272
- default: language_data.title ?? '',
273
- placeHolder: `請輸入${cat_title}名稱`,
274
- callback: text => {
275
- if (language_data.seo.domain === language_data.title) {
276
- language_data.seo.domain = text;
277
- }
278
- language_data.title = text;
279
- gvc.notifyDataChange('seo');
280
- },
281
- })}
282
- </div>
283
- `),
284
- BgWidget.mainCard(
285
- [
286
- obj.gvc.bindView(() => {
287
- const vm = {
288
- id: obj.gvc.glitter.getUUID(),
289
- type: 'product-detail',
290
- documents: [],
291
- };
292
-
293
- language_data.content_array = language_data.content_array ?? [];
294
- language_data.content_json = language_data.content_json ?? [];
295
- return {
296
- bind: vm.id,
297
- view: async () => {
298
- return html` <div class="d-flex align-items-center justify-content-end">
299
- <div class="d-flex align-items-center gap-2">
300
- <div style="color: #393939; font-weight: 700;">
301
- ${cat_title}簡述 ${BgWidget.languageInsignia(sel_lan(), 'margin-left:5px;')}
302
- </div>
303
- </div>
304
- <div class="flex-fill"></div>
258
+ function drawShortDescriptionRichText() {
259
+ return BgWidget.mainCard(
260
+ [
261
+ obj.gvc.bindView(() => {
262
+ const vm = {
263
+ id: obj.gvc.glitter.getUUID(),
264
+ type: 'product-detail',
265
+ documents: [],
266
+ };
267
+
268
+ language_data.content_array = language_data.content_array ?? [];
269
+ language_data.content_json = language_data.content_json ?? [];
270
+ return {
271
+ bind: vm.id,
272
+ view: async () => {
273
+ return html` <!-- 繪製商品的簡短描述區塊 -->
274
+ <div class="d-flex align-items-center justify-content-end">
275
+ <div class="d-flex align-items-center gap-2">
276
+ <div style="color: #393939; font-weight: 700;">
277
+ ${cat_title}簡述 ${BgWidget.languageInsignia(sel_lan(), 'margin-left:5px;')}
305
278
  </div>
306
- ${BgWidget.grayNote(`將顯示於${cat_title}名稱下方,快速呈現${cat_title}重點資訊,建議精簡`)}
307
- <div class="my-3">
308
- ${gvc.bindView(
309
- (() => {
310
- const id = gvc.glitter.getUUID();
311
- language_data.sub_title = language_data.sub_title ?? '';
312
- return {
313
- bind: id,
314
- view: () => {
315
- return html` <div
316
- class="d-flex justify-content-between align-items-center gap-3 mb-1"
317
- style="cursor: pointer;"
318
- onclick="${gvc.event(() => {
319
- const originContent = `${language_data.sub_title}`;
320
- BgWidget.fullDialog({
321
- gvc: gvc,
322
- title: gvc2 => {
323
- return html`<div class="d-flex align-items-center" style="gap:10px;">
324
- ${`${cat_title}簡述` +
325
- BgWidget.aiChatButton({
326
- gvc: gvc2,
327
- select: 'writer',
328
- click: () => {
329
- ProductAi.generateRichText(gvc, text => {
330
- language_data.sub_title += text;
331
- gvc.notifyDataChange(vm.id);
332
- gvc2.recreateView();
333
- });
334
- },
335
- })}
336
- </div>`;
337
- },
338
- innerHTML: gvc2 => {
339
- return html` <div>
340
- ${EditorElem.richText({
341
- gvc: gvc2,
342
- def: language_data.sub_title,
343
- setHeight: '100vh',
344
- hiddenBorder: true,
345
- insertImageEvent: editor => {
346
- const mark = `{{${Tool.randomString(8)}}}`;
347
- editor.selection.setAtEnd(editor.$el.get(0));
348
- editor.html.insert(mark);
349
- editor.undo.saveStep();
350
- imageLibrary.selectImageLibrary(
351
- gvc,
352
- urlArray => {
353
- if (urlArray.length > 0) {
354
- const imgHTML = urlArray
355
- .map(url => {
356
- return html` <img src="${url.data}" />`;
357
- })
358
- .join('');
359
- editor.html.set(
360
- editor.html
361
- .get(0)
362
- .replace(
363
- mark,
364
- html` <div class="d-flex flex-column">${imgHTML}</div>`
365
- )
366
- );
367
- editor.undo.saveStep();
368
- } else {
369
- dialog.errorMessage({ text: '請選擇至少一張圖片' });
370
- }
371
- },
372
- html` <div
373
- class="d-flex flex-column"
374
- style="border-radius: 10px 10px 0px 0px;background: #F2F2F2;"
375
- >
376
- 圖片庫
377
- </div>`,
378
- {
379
- mul: true,
380
- cancelEvent: () => {
381
- editor.html.set(editor.html.get(0).replace(mark, ''));
382
- editor.undo.saveStep();
383
- },
384
- }
385
- );
386
- },
387
- callback: text => {
388
- language_data.sub_title = text;
279
+ </div>
280
+ <div class="flex-fill"></div>
281
+ </div>
282
+ ${BgWidget.grayNote(`將顯示於${cat_title}名稱下方,快速呈現${cat_title}重點資訊,建議精簡`)}
283
+ <div class="my-3">
284
+ ${gvc.bindView(
285
+ (() => {
286
+ const id = gvc.glitter.getUUID();
287
+ language_data.sub_title = language_data.sub_title ?? '';
288
+ return {
289
+ bind: id,
290
+ view: () => {
291
+ return html` <div
292
+ class="d-flex justify-content-between align-items-center gap-3 mb-1"
293
+ style="cursor: pointer;"
294
+ onclick="${gvc.event(() => {
295
+ const originContent = `${language_data.sub_title}`;
296
+ BgWidget.fullDialog({
297
+ gvc: gvc,
298
+ title: gvc2 => {
299
+ return html` <div class="d-flex align-items-center" style="gap:10px;">
300
+ ${`${cat_title}簡述` +
301
+ BgWidget.aiChatButton({
302
+ gvc: gvc2,
303
+ select: 'writer',
304
+ click: () => {
305
+ ProductAi.generateRichText(gvc, text => {
306
+ language_data.sub_title += text;
307
+ gvc.notifyDataChange(vm.id);
308
+ gvc2.recreateView();
309
+ });
310
+ },
311
+ })}
312
+ </div>`;
313
+ },
314
+ innerHTML: gvc2 => {
315
+ return html` <div>
316
+ ${EditorElem.richText({
317
+ gvc: gvc2,
318
+ def: language_data.sub_title,
319
+ setHeight: '100vh',
320
+ hiddenBorder: true,
321
+ insertImageEvent: editor => {
322
+ const mark = `{{${Tool.randomString(8)}}}`;
323
+ editor.selection.setAtEnd(editor.$el.get(0));
324
+ editor.html.insert(mark);
325
+ editor.undo.saveStep();
326
+ imageLibrary.selectImageLibrary(
327
+ gvc,
328
+ urlArray => {
329
+ if (urlArray.length > 0) {
330
+ const imgHTML = urlArray
331
+ .map(url => {
332
+ return html` <img src="${url.data}" />`;
333
+ })
334
+ .join('');
335
+ editor.html.set(
336
+ editor.html
337
+ .get(0)
338
+ .replace(
339
+ mark,
340
+ html` <div class="d-flex flex-column">${imgHTML}</div>`
341
+ )
342
+ );
343
+ editor.undo.saveStep();
344
+ } else {
345
+ dialog.errorMessage({ text: '請選擇至少一張圖片' });
346
+ }
389
347
  },
390
- rich_height: `calc(${(window.parent as any).innerHeight}px - 70px - 58px - 49px - 64px - 40px + ${
391
- document.body.clientWidth < 800 ? `70` : `0`
392
- }px)`,
393
- })}
394
- </div>`;
395
- },
396
- footer_html: (gvc2: GVC) => {
397
- return [
398
- BgWidget.cancel(
399
- gvc2.event(() => {
400
- dialog.checkYesOrNot({
401
- text: '確定要取消並關閉嗎?',
402
- callback: bool => {
403
- if (bool) {
404
- language_data.sub_title = originContent;
405
- gvc2.closeDialog();
406
- }
407
- },
408
- });
409
- })
410
- ),
411
- BgWidget.save(
412
- gvc2.event(() => {
413
- dialog.checkYesOrNot({
414
- text: '確定要儲存並更新嗎?',
415
- callback: bool => {
416
- if (bool) {
417
- gvc2.closeDialog();
418
- gvc.notifyDataChange(id);
419
- }
420
- },
421
- });
422
- })
423
- ),
424
- ].join('');
425
- },
426
- closeCallback: () => {
427
- language_data.sub_title = originContent;
428
- },
429
- });
430
- })}"
431
- >
432
- ${(() => {
433
- const text = gvc.glitter.utText.removeTag(language_data.sub_title);
434
- return BgWidget.richTextView(Tool.truncateString(text, 100));
435
- })()}
436
- </div>`;
437
- },
438
- };
439
- })()
440
- )}
441
- </div>`;
442
- },
443
- };
444
- }),
445
- ].join(BgWidget.mbContainer(12))
446
- ),
447
- obj.postMD.productType.giveaway
448
- ? ''
449
- : BgWidget.mainCard(
450
- [
451
- obj.gvc.bindView(() => {
452
- const vm_this = vm;
453
- return (() => {
454
- const vm = {
455
- id: obj.gvc.glitter.getUUID(),
456
- type: 'product-detail',
457
- loading: true,
458
- documents: [],
459
- };
460
-
461
- language_data.content_array = language_data.content_array ?? [];
462
- language_data.content_json = language_data.content_json ?? [];
348
+ html` <div
349
+ class="d-flex flex-column"
350
+ style="border-radius: 10px 10px 0px 0px;background: #F2F2F2;"
351
+ >
352
+ 圖片庫
353
+ </div>`,
354
+ {
355
+ mul: true,
356
+ cancelEvent: () => {
357
+ editor.html.set(editor.html.get(0).replace(mark, ''));
358
+ editor.undo.saveStep();
359
+ },
360
+ }
361
+ );
362
+ },
363
+ callback: text => {
364
+ language_data.sub_title = text;
365
+ },
366
+ rich_height: `calc(${(window.parent as any).innerHeight}px - 70px - 58px - 49px - 64px - 40px + ${
367
+ document.body.clientWidth < 800 ? `70` : `0`
368
+ }px)`,
369
+ })}
370
+ </div>`;
371
+ },
372
+ footer_html: (gvc2: GVC) => {
373
+ return [
374
+ BgWidget.cancel(
375
+ gvc2.event(() => {
376
+ language_data.sub_title = originContent;
377
+ gvc2.closeDialog();
378
+ })
379
+ ),
380
+ BgWidget.save(
381
+ gvc2.event(() => {
382
+ gvc2.closeDialog();
383
+ gvc.notifyDataChange(id);
384
+ })
385
+ ),
386
+ ].join('');
387
+ },
388
+ closeCallback: () => {
389
+ language_data.sub_title = originContent;
390
+ },
391
+ });
392
+ })}"
393
+ >
394
+ ${(() => {
395
+ const text = gvc.glitter.utText.removeTag(language_data.sub_title);
396
+ return BgWidget.richTextView(Tool.truncateString(text, 100));
397
+ })()}
398
+ </div>`;
399
+ },
400
+ };
401
+ })()
402
+ )}
403
+ </div>`;
404
+ },
405
+ };
406
+ }),
407
+ ].join(BgWidget.mbContainer(12))
408
+ );
409
+ }
463
410
 
464
- if (!vm_this.content_detail) {
465
- ApiUser.getPublicConfig('text-manager', 'manager').then((data: any) => {
466
- vm.documents = data.response.value;
467
- if (!Array.isArray(vm.documents)) {
468
- vm.documents = [];
469
- }
470
- vm_this.content_detail = vm.documents;
471
- vm.loading = false;
472
- gvc.notifyDataChange(vm.id);
473
- });
474
- } else {
475
- vm.documents = vm_this.content_detail;
476
- vm.loading = false;
411
+ function drawDetailDescriptionRichText() {
412
+ return obj.postMD.productType.giveaway
413
+ ? ''
414
+ : BgWidget.mainCard(
415
+ [
416
+ obj.gvc.bindView(() => {
417
+ const vm_this = vm;
418
+ return (() => {
419
+ const vm = {
420
+ id: obj.gvc.glitter.getUUID(),
421
+ type: 'product-detail',
422
+ loading: true,
423
+ documents: [],
424
+ };
425
+
426
+ language_data.content_array = language_data.content_array ?? [];
427
+ language_data.content_json = language_data.content_json ?? [];
428
+
429
+ if (!vm_this.content_detail) {
430
+ ApiUser.getPublicConfig('text-manager', 'manager').then((data: any) => {
431
+ vm.documents = data.response.value;
432
+ if (!Array.isArray(vm.documents)) {
433
+ vm.documents = [];
477
434
  }
435
+ vm_this.content_detail = vm.documents;
436
+ vm.loading = false;
437
+ gvc.notifyDataChange(vm.id);
438
+ });
439
+ } else {
440
+ vm.documents = vm_this.content_detail;
441
+ vm.loading = false;
442
+ }
478
443
 
479
- return {
480
- bind: vm.id,
481
- view: async () => {
482
- if (vm.loading) {
483
- return BgWidget.spinner();
484
- }
444
+ return {
445
+ bind: vm.id,
446
+ view: async () => {
447
+ if (vm.loading) {
448
+ return BgWidget.spinner();
449
+ }
485
450
 
486
- language_data.content_array = language_data.content_array.filter((id: any) => {
487
- return vm.documents.some((item: any) => item.id === id);
488
- });
489
- language_data.content_json = language_data.content_json.filter((d: any) => {
490
- return vm.documents.some((item: any) => item.id === d.id);
491
- });
451
+ language_data.content_array = language_data.content_array.filter((id: any) => {
452
+ return vm.documents.some((item: any) => item.id === id);
453
+ });
454
+ language_data.content_json = language_data.content_json.filter((d: any) => {
455
+ return vm.documents.some((item: any) => item.id === d.id);
456
+ });
492
457
 
493
- function formatRichtext(
494
- text: string,
495
- tags: {
496
- key: string;
497
- title: string;
498
- font_size: string;
499
- font_color: string;
500
- font_bgr: string;
501
- }[],
502
- jsonData: {
503
- key: string;
504
- value: string;
505
- }[]
506
- ) {
507
- let gText = `${text}`;
508
- if (tags && tags.length > 0) {
509
- for (const item of tags) {
510
- const data = jsonData.find(j => j.key === item.key);
511
- const textImage =
512
- data && data.value
513
- ? html`<span
514
- style="font-size: ${item.font_size ?? '14'}px; color: ${item.font_color ??
515
- '#393939'}; background: ${item.font_bgr ?? '#fff'}"
516
- >${data.value}</span
517
- >`
518
- : html`#${item.title}#`;
519
- // : html`<img
520
- // alt="${item.key}"
521
- // class="rounded-2"
522
- // src="https://assets.imgix.net/~text?bg=4d86db&txtclr=f2f2f2&w=${Tool.twenLength(item.title) *
523
- // 20}&h=40&txtsize=12&txt=${item.title}&txtfont=Helvetica&txtalign=middle,center"
524
- // />`;
525
-
526
- const regex = new RegExp(`@{{${item.key}}}`, 'g');
527
- gText = gText.replace(regex, textImage);
528
- }
529
- }
530
- return gText;
458
+ function formatRichtext(
459
+ text: string,
460
+ tags: {
461
+ key: string;
462
+ title: string;
463
+ font_size: string;
464
+ font_color: string;
465
+ font_bgr: string;
466
+ }[],
467
+ jsonData: {
468
+ key: string;
469
+ value: string;
470
+ }[]
471
+ ) {
472
+ let gText = `${text}`;
473
+ if (tags && tags.length > 0) {
474
+ for (const item of tags) {
475
+ const data = jsonData.find(j => j.key === item.key);
476
+ const textImage =
477
+ data && data.value
478
+ ? html`<span
479
+ style="font-size: ${item.font_size ?? '14'}px; color: ${item.font_color ??
480
+ '#393939'}; background: ${item.font_bgr ?? '#fff'}"
481
+ >${data.value}</span
482
+ >`
483
+ : html`#${item.title}#`;
484
+ // : html`<img
485
+ // alt="${item.key}"
486
+ // class="rounded-2"
487
+ // src="https://assets.imgix.net/~text?bg=4d86db&txtclr=f2f2f2&w=${Tool.twenLength(item.title) *
488
+ // 20}&h=40&txtsize=12&txt=${item.title}&txtfont=Helvetica&txtalign=middle,center"
489
+ // />`;
490
+
491
+ const regex = new RegExp(`@{{${item.key}}}`, 'g');
492
+ gText = gText.replace(regex, textImage);
531
493
  }
494
+ }
495
+ return gText;
496
+ }
532
497
 
533
- return html` <div class="d-flex align-items-center justify-content-end mb-3">
534
- <div class="d-flex align-items-center gap-2">
535
- <div style="color: #393939; font-weight: 700;">
536
- ${cat_title}詳細描述 ${BgWidget.languageInsignia(sel_lan(), 'margin-left:5px;')}
537
- </div>
538
- </div>
539
- <div class="flex-fill"></div>
540
- <div
541
- class="cursor_pointer"
542
- onclick="${gvc.event(() => {
543
- BgWidget.dialog({
544
- gvc: gvc,
545
- title: '設定',
546
- xmark: () => {
547
- return new Promise<boolean>(resolve => {
548
- gvc.notifyDataChange(vm.id);
549
- resolve(true);
550
- });
551
- },
552
- innerHTML: gvc => {
553
- const id = gvc.glitter.getUUID();
554
- return gvc.bindView(() => {
555
- return {
556
- bind: id,
557
- view: () => {
558
- return vm.documents
559
- .map((dd: any) => {
560
- return html` <li class="w-100 px-2">
561
- <div class="w-100 d-flex justify-content-between">
562
- <div class="d-flex justify-content-start align-items-center gap-3">
563
- <i
564
- class="fa-solid fa-grip-dots-vertical dragItem cursor_pointer"
565
- ></i>
566
- <div class="tx_normal">${dd.title}</div>
567
- </div>
568
- ${gvc.bindView(
569
- (() => {
570
- const iconId = gvc.glitter.getUUID();
571
- return {
572
- bind: iconId,
573
- view: () => {
574
- return html` <i
575
- class="${language_data.content_array.includes(dd.id)
576
- ? 'fa-solid fa-eye'
577
- : 'fa-sharp fa-solid fa-eye-slash'} d-flex align-items-center justify-content-center cursor_pointer"
578
- onclick="${gvc.event(() => {
579
- if (language_data.content_array.includes(dd.id)) {
580
- language_data.content_array =
581
- language_data.content_array.filter(
582
- (d: any) => d !== dd.id
583
- );
584
- } else {
585
- language_data.content_array.push(dd.id);
586
- }
587
- gvc.notifyDataChange(iconId);
588
- })}"
589
- ></i>`;
590
- },
591
- divCreate: {
592
- class: 'd-flex',
593
- },
594
- };
595
- })()
596
- )}
597
- </div>
598
- </li>`;
599
- })
600
- .join('');
601
- },
602
- divCreate: {
603
- elem: 'ul',
604
- class: 'w-100 my-2 d-flex flex-column gap-4',
605
- },
606
- onCreate: () => {
607
- if (!vm.loading) {
608
- gvc.glitter.addMtScript(
609
- [
610
- {
611
- src: `https://raw.githack.com/SortableJS/Sortable/master/Sortable.js`,
612
- },
613
- ],
614
- () => {},
615
- () => {}
616
- );
617
- const interval = setInterval(() => {
618
- if ((window as any).Sortable) {
619
- try {
620
- gvc.addStyle(`
498
+ return html`<!-- 繪製商品的詳細描述區塊-->
499
+ <div class="d-flex align-items-center justify-content-end mb-3">
500
+ <div class="d-flex align-items-center gap-2">
501
+ <div style="color: #393939; font-weight: 700;">
502
+ ${cat_title}詳細描述 ${BgWidget.languageInsignia(sel_lan(), 'margin-left:5px;')}
503
+ </div>
504
+ </div>
505
+ <div class="flex-fill"></div>
506
+ <div
507
+ class="cursor_pointer"
508
+ onclick="${gvc.event(() => {
509
+ BgWidget.dialog({
510
+ gvc: gvc,
511
+ title: '設定',
512
+ xmark: () => {
513
+ return new Promise<boolean>(resolve => {
514
+ gvc.notifyDataChange(vm.id);
515
+ resolve(true);
516
+ });
517
+ },
518
+ innerHTML: gvc => {
519
+ const id = gvc.glitter.getUUID();
520
+ return gvc.bindView(() => {
521
+ return {
522
+ bind: id,
523
+ view: () => {
524
+ return vm.documents
525
+ .map((dd: any) => {
526
+ return html` <li class="w-100 px-2">
527
+ <div class="w-100 d-flex justify-content-between">
528
+ <div class="d-flex justify-content-start align-items-center gap-3">
529
+ <i class="fa-solid fa-grip-dots-vertical dragItem cursor_pointer"></i>
530
+ <div class="tx_normal">${dd.title}</div>
531
+ </div>
532
+ ${gvc.bindView(
533
+ (() => {
534
+ const iconId = gvc.glitter.getUUID();
535
+ return {
536
+ bind: iconId,
537
+ view: () => {
538
+ return html` <i
539
+ class="${language_data.content_array.includes(dd.id)
540
+ ? 'fa-solid fa-eye'
541
+ : 'fa-sharp fa-solid fa-eye-slash'} d-flex align-items-center justify-content-center cursor_pointer"
542
+ onclick="${gvc.event(() => {
543
+ if (language_data.content_array.includes(dd.id)) {
544
+ language_data.content_array =
545
+ language_data.content_array.filter(
546
+ (d: any) => d !== dd.id
547
+ );
548
+ } else {
549
+ language_data.content_array.push(dd.id);
550
+ }
551
+ gvc.notifyDataChange(iconId);
552
+ })}"
553
+ ></i>`;
554
+ },
555
+ divCreate: {
556
+ class: 'd-flex',
557
+ },
558
+ };
559
+ })()
560
+ )}
561
+ </div>
562
+ </li>`;
563
+ })
564
+ .join('');
565
+ },
566
+ divCreate: {
567
+ elem: 'ul',
568
+ class: 'w-100 my-2 d-flex flex-column gap-4',
569
+ },
570
+ onCreate: () => {
571
+ if (!vm.loading) {
572
+ gvc.glitter.addMtScript(
573
+ [
574
+ {
575
+ src: `https://raw.githack.com/SortableJS/Sortable/master/Sortable.js`,
576
+ },
577
+ ],
578
+ () => {},
579
+ () => {}
580
+ );
581
+ const interval = setInterval(() => {
582
+ if ((window as any).Sortable) {
583
+ try {
584
+ gvc.addStyle(`
621
585
  ul {
622
586
  list-style: none;
623
587
  padding: 0;
624
588
  }
625
589
  `);
626
590
 
627
- function swapArr(arr: any, t1: number, t2: number) {
628
- const data = arr[t1];
629
- arr.splice(t1, 1);
630
- arr.splice(t2, 0, data);
631
- }
591
+ function swapArr(arr: any, t1: number, t2: number) {
592
+ const data = arr[t1];
593
+ arr.splice(t1, 1);
594
+ arr.splice(t2, 0, data);
595
+ }
632
596
 
633
- let startIndex = 0;
634
- //@ts-ignore
635
- Sortable.create(gvc.getBindViewElem(id).get(0), {
636
- group: id,
637
- animation: 100,
638
- handle: '.dragItem',
639
- onEnd: (evt: any) => {
640
- swapArr(vm.documents, startIndex, evt.newIndex);
641
- ApiUser.setPublicConfig({
642
- key: 'text-manager',
643
- user_id: 'manager',
644
- value: vm.documents,
645
- }).then(result => {
646
- if (!result.response.result) {
647
- dialog.errorMessage({ text: '設定失敗' });
648
- }
649
- });
650
- },
651
- onStart: (evt: any) => {
652
- startIndex = evt.oldIndex;
653
- },
597
+ let startIndex = 0;
598
+ //@ts-ignore
599
+ Sortable.create(gvc.getBindViewElem(id).get(0), {
600
+ group: id,
601
+ animation: 100,
602
+ handle: '.dragItem',
603
+ onEnd: (evt: any) => {
604
+ swapArr(vm.documents, startIndex, evt.newIndex);
605
+ ApiUser.setPublicConfig({
606
+ key: 'text-manager',
607
+ user_id: 'manager',
608
+ value: vm.documents,
609
+ }).then(result => {
610
+ if (!result.response.result) {
611
+ dialog.errorMessage({ text: '設定失敗' });
612
+ }
654
613
  });
655
- } catch (e) {}
656
- clearInterval(interval);
657
- }
658
- }, 100);
614
+ },
615
+ onStart: (evt: any) => {
616
+ startIndex = evt.oldIndex;
617
+ },
618
+ });
619
+ } catch (e) {}
620
+ clearInterval(interval);
659
621
  }
660
- },
661
- };
662
- });
663
- },
622
+ }, 100);
623
+ }
624
+ },
625
+ };
664
626
  });
665
- })}"
666
- >
667
- 設定<i class="fa-regular fa-gear ms-1"></i>
668
- </div>
669
- </div>
670
- <div class="my-3">
671
- ${gvc.bindView(
672
- (() => {
673
- const id = gvc.glitter.getUUID();
674
- return {
675
- bind: id,
676
- view: () => {
677
- return html` <div
678
- class="d-flex justify-content-between align-items-center gap-3 mb-1"
679
- style="cursor: pointer;"
680
- onclick="${gvc.event(() => {
681
- const originContent = `${language_data.content}`;
682
- BgWidget.fullDialog({
683
- gvc: gvc,
684
- title: gvc2 => {
685
- return html`<div class="d-flex align-items-center" style="gap:10px;">
686
- ${`${cat_title}描述` +
687
- BgWidget.aiChatButton({
688
- gvc: gvc2,
689
- select: 'writer',
690
- click: () => {
691
- ProductAi.generateRichText(gvc, text => {
692
- language_data.content += text;
693
- gvc.notifyDataChange(vm.id);
694
- gvc2.recreateView();
695
- });
627
+ },
628
+ });
629
+ })}"
630
+ >
631
+ 設定<i class="fa-regular fa-gear ms-1"></i>
632
+ </div>
633
+ </div>
634
+ <div class="my-3">
635
+ ${gvc.bindView(
636
+ (() => {
637
+ const id = gvc.glitter.getUUID();
638
+ return {
639
+ bind: id,
640
+ view: () => {
641
+ return html` <div
642
+ class="d-flex justify-content-between align-items-center gap-3 mb-1"
643
+ style="cursor: pointer;"
644
+ onclick="${gvc.event(() => {
645
+ const originContent = `${language_data.content}`;
646
+ BgWidget.fullDialog({
647
+ gvc: gvc,
648
+ title: gvc2 => {
649
+ return html` <div class="d-flex align-items-center" style="gap:10px;">
650
+ ${`${cat_title}描述` +
651
+ BgWidget.aiChatButton({
652
+ gvc: gvc2,
653
+ select: 'writer',
654
+ click: () => {
655
+ ProductAi.generateRichText(gvc, text => {
656
+ language_data.content += text;
657
+ gvc.notifyDataChange(vm.id);
658
+ gvc2.recreateView();
659
+ });
660
+ },
661
+ })}
662
+ </div>`;
663
+ },
664
+ innerHTML: gvc2 => {
665
+ return html` <div>
666
+ ${EditorElem.richText({
667
+ gvc: gvc2,
668
+ def: language_data.content,
669
+ setHeight: '100vh',
670
+ hiddenBorder: true,
671
+ insertImageEvent: editor => {
672
+ const mark = `{{${Tool.randomString(8)}}}`;
673
+ editor.selection.setAtEnd(editor.$el.get(0));
674
+ editor.html.insert(mark);
675
+ editor.undo.saveStep();
676
+
677
+ imageLibrary.selectImageLibrary(
678
+ gvc,
679
+ urlArray => {
680
+ if (urlArray.length > 0) {
681
+ const imgHTML = urlArray
682
+ .map(url => {
683
+ return html` <img src="${url.data}" />`;
684
+ })
685
+ .join('');
686
+ editor.html.set(
687
+ editor.html
688
+ .get(0)
689
+ .replace(
690
+ mark,
691
+ html` <div class="d-flex flex-column">${imgHTML}</div>`
692
+ )
693
+ );
694
+ editor.undo.saveStep();
695
+ } else {
696
+ dialog.errorMessage({ text: '請選擇至少一張圖片' });
697
+ }
696
698
  },
697
- })}
698
- </div>`;
699
- },
700
- innerHTML: gvc2 => {
701
- return html` <div>
702
- ${EditorElem.richText({
703
- gvc: gvc2,
704
- def: language_data.content,
705
- setHeight: '100vh',
706
- hiddenBorder: true,
707
- insertImageEvent: editor => {
708
- const mark = `{{${Tool.randomString(8)}}}`;
709
- editor.selection.setAtEnd(editor.$el.get(0));
710
- editor.html.insert(mark);
711
- editor.undo.saveStep();
712
-
713
- imageLibrary.selectImageLibrary(
699
+ html` <div
700
+ class="d-flex flex-column"
701
+ style="border-radius: 10px 10px 0px 0px;background: #F2F2F2;"
702
+ >
703
+ 圖片庫
704
+ </div>`,
705
+ {
706
+ mul: true,
707
+ cancelEvent: () => {
708
+ editor.html.set(editor.html.get(0).replace(mark, ''));
709
+ editor.undo.saveStep();
710
+ },
711
+ }
712
+ );
713
+ },
714
+ callback: text => {
715
+ language_data.content = text;
716
+ },
717
+ rich_height: `calc(${(window.parent as any).innerHeight}px - 70px - 58px - 49px - 64px - 40px + ${
718
+ document.body.clientWidth < 800 ? `70` : `0`
719
+ }px)`,
720
+ })}
721
+ </div>`;
722
+ },
723
+ footer_html: (gvc2: GVC) => {
724
+ return [
725
+ BgWidget.cancel(
726
+ gvc2.event(() => {
727
+ language_data.content = originContent;
728
+ gvc2.closeDialog();
729
+ })
730
+ ),
731
+ BgWidget.save(
732
+ gvc2.event(() => {
733
+ gvc2.closeDialog();
734
+ gvc.notifyDataChange(id);
735
+ })
736
+ ),
737
+ ].join('');
738
+ },
739
+ closeCallback: () => {
740
+ language_data.content = originContent;
741
+ },
742
+ });
743
+ })}"
744
+ >
745
+ ${(() => {
746
+ const text = gvc.glitter.utText.removeTag(language_data.content);
747
+ return BgWidget.richTextView(Tool.truncateString(text, 100));
748
+ })()}
749
+ </div>`;
750
+ },
751
+ };
752
+ })()
753
+ )}
754
+ </div>
755
+ ${(vm.documents || [])
756
+ .filter((item: any) => {
757
+ return language_data.content_array.includes(item.id);
758
+ })
759
+ .map((item: any, index) => {
760
+ return BgWidget.openBoxContainer({
761
+ gvc,
762
+ tag: 'content_array',
763
+ title: item.title,
764
+ insideHTML: (() => {
765
+ if (item.data.tags && item.data.tags.length > 0) {
766
+ const id = obj.gvc.glitter.getUUID();
767
+ return html` <div
768
+ class="cursor_pointer text-end me-1 mb-2"
769
+ onclick="${gvc.event(() => {
770
+ const originJson = JSON.parse(JSON.stringify(language_data.content_json));
771
+ BgWidget.settingDialog({
772
+ gvc: gvc,
773
+ title: '設定',
774
+ innerHTML: gvc => {
775
+ return html` <div>
776
+ ${item.data.tags
777
+ .map((tag: { key: string; title: string }) => {
778
+ return html` <div>
779
+ ${BgWidget.editeInput({
714
780
  gvc,
715
- urlArray => {
716
- if (urlArray.length > 0) {
717
- const imgHTML = urlArray
718
- .map(url => {
719
- return html` <img src="${url.data}" />`;
720
- })
721
- .join('');
722
- editor.html.set(
723
- editor.html
724
- .get(0)
725
- .replace(
726
- mark,
727
- html` <div class="d-flex flex-column">${imgHTML}</div>`
728
- )
729
- );
730
- editor.undo.saveStep();
731
- } else {
732
- dialog.errorMessage({ text: '請選擇至少一張圖片' });
781
+ title: tag.title,
782
+ default: (() => {
783
+ const docIndex = language_data.content_json.findIndex(
784
+ (c: any) => c.id === item.id
785
+ );
786
+ if (docIndex === -1) {
787
+ return '';
733
788
  }
734
- },
735
- html` <div
736
- class="d-flex flex-column"
737
- style="border-radius: 10px 10px 0px 0px;background: #F2F2F2;"
738
- >
739
- 圖片庫
740
- </div>`,
741
- {
742
- mul: true,
743
- cancelEvent: () => {
744
- editor.html.set(editor.html.get(0).replace(mark, ''));
745
- editor.undo.saveStep();
746
- },
747
- }
748
- );
749
- },
750
- callback: text => {
751
- language_data.content = text;
752
- },
753
- rich_height: `calc(${(window.parent as any).innerHeight}px - 70px - 58px - 49px - 64px - 40px + ${
754
- document.body.clientWidth < 800 ? `70` : `0`
755
- }px)`,
756
- })}
757
- </div>`;
758
- },
759
- footer_html: (gvc2: GVC) => {
760
- return [
761
- BgWidget.cancel(
762
- gvc2.event(() => {
763
- dialog.checkYesOrNot({
764
- text: '確定要取消並關閉嗎?',
765
- callback: bool => {
766
- if (bool) {
767
- language_data.content = originContent;
768
- gvc2.closeDialog();
789
+ if (language_data.content_json[docIndex].list === undefined) {
790
+ return '';
769
791
  }
770
- },
771
- });
772
- })
773
- ),
774
- BgWidget.save(
775
- gvc2.event(() => {
776
- dialog.checkYesOrNot({
777
- text: '確定要儲存並更新嗎?',
778
- callback: bool => {
779
- if (bool) {
780
- gvc2.closeDialog();
781
- gvc.notifyDataChange(id);
792
+ const keyIndex = language_data.content_json[
793
+ docIndex
794
+ ].list.findIndex((l: any) => l.key === tag.key);
795
+ if (keyIndex === -1) {
796
+ return '';
782
797
  }
783
- },
784
- });
785
- })
786
- ),
787
- ].join('');
788
- },
789
- closeCallback: () => {
790
- language_data.content = originContent;
791
- },
792
- });
793
- })}"
794
- >
795
- ${(() => {
796
- const text = gvc.glitter.utText.removeTag(language_data.content);
797
- return BgWidget.richTextView(Tool.truncateString(text, 100));
798
- })()}
799
- </div>`;
800
- },
801
- };
802
- })()
803
- )}
804
- </div>
805
- ${(vm.documents || [])
806
- .filter((item: any) => {
807
- return language_data.content_array.includes(item.id);
808
- })
809
- .map((item: any, index) => {
810
- return BgWidget.openBoxContainer({
811
- gvc,
812
- tag: 'content_array',
813
- title: item.title,
814
- insideHTML: (() => {
815
- if (item.data.tags && item.data.tags.length > 0) {
816
- const id = obj.gvc.glitter.getUUID();
817
- return html` <div
818
- class="cursor_pointer text-end me-1 mb-2"
819
- onclick="${gvc.event(() => {
820
- const originJson = JSON.parse(JSON.stringify(language_data.content_json));
821
- BgWidget.settingDialog({
822
- gvc: gvc,
823
- title: '設定',
824
- innerHTML: gvc => {
825
- return html` <div>
826
- ${item.data.tags
827
- .map((tag: { key: string; title: string }) => {
828
- return html` <div>
829
- ${BgWidget.editeInput({
830
- gvc,
831
- title: tag.title,
832
- default: (() => {
833
- const docIndex = language_data.content_json.findIndex(
834
- (c: any) => c.id === item.id
835
- );
836
- if (docIndex === -1) {
837
- return '';
838
- }
839
- if (
840
- language_data.content_json[docIndex].list === undefined
841
- ) {
842
- return '';
843
- }
844
- const keyIndex = language_data.content_json[
845
- docIndex
846
- ].list.findIndex((l: any) => l.key === tag.key);
847
- if (keyIndex === -1) {
848
- return '';
849
- }
850
- return language_data.content_json[docIndex].list[keyIndex]
851
- .value;
852
- })(),
853
- callback: text => {
854
- const docIndex = language_data.content_json.findIndex(
855
- (c: any) => c.id === item.id
856
- );
857
- if (docIndex === -1) {
858
- language_data.content_json.push({
859
- id: item.id,
860
- list: [
861
- {
862
- key: tag.key,
863
- value: text,
864
- },
865
- ],
866
- });
867
- return;
868
- }
869
- if (
870
- language_data.content_json[docIndex].list === undefined
871
- ) {
872
- language_data.content_json[docIndex].list = [
873
- {
874
- key: tag.key,
875
- value: text,
876
- },
877
- ];
878
- return;
879
- }
880
- const keyIndex = language_data.content_json[
881
- docIndex
882
- ].list.findIndex((l: any) => l.key === tag.key);
883
- if (keyIndex === -1) {
884
- language_data.content_json[docIndex].list.push({
798
+ return language_data.content_json[docIndex].list[keyIndex]
799
+ .value;
800
+ })(),
801
+ callback: text => {
802
+ const docIndex = language_data.content_json.findIndex(
803
+ (c: any) => c.id === item.id
804
+ );
805
+ if (docIndex === -1) {
806
+ language_data.content_json.push({
807
+ id: item.id,
808
+ list: [
809
+ {
885
810
  key: tag.key,
886
811
  value: text,
887
- });
888
- return;
889
- }
890
- language_data.content_json[docIndex].list[keyIndex].value =
891
- text;
892
- },
893
- placeHolder: '輸入文本標籤',
894
- })}
895
- </div>`;
896
- })
897
- .join(BgWidget.mbContainer(12))}
898
- </div>`;
899
- },
900
- footer_html: (gvc2: GVC) => {
901
- return [
902
- BgWidget.cancel(
903
- gvc2.event(() => {
904
- language_data.content_json = originJson;
905
- gvc2.closeDialog();
906
- })
907
- ),
908
- BgWidget.save(
909
- gvc2.event(() => {
910
- gvc2.closeDialog();
911
- gvc.notifyDataChange(`${id}-${index}`);
912
- })
913
- ),
914
- ].join('');
915
- },
916
- closeCallback: () => {
917
- language_data.content_json = originJson;
918
- },
919
- });
920
- })}"
921
- >
922
- 標籤設值
923
- </div>
924
- ${gvc.bindView(
925
- (() => {
926
- return {
927
- bind: `${id}-${index}`,
928
- view: () => {
929
- const content = item.data.content || '';
930
- const tags = item.data.tags;
931
- const jsonData = language_data.content_json.find(
932
- (c: any) => c.id === item.id
933
- );
934
- return html` <div
935
- style="border: 2px #DDDDDD solid; border-radius: 6px; padding: 12px;"
936
- >
937
- ${tags
938
- ? formatRichtext(content, tags, jsonData ? jsonData.list : [])
939
- : content}
940
- </div>`;
941
- },
942
- };
943
- })()
944
- )}`;
945
- }
946
- return html` <div
947
- style="border: 1px #DDDDDD solid; border-radius: 6px; padding: 12px"
812
+ },
813
+ ],
814
+ });
815
+ return;
816
+ }
817
+ if (language_data.content_json[docIndex].list === undefined) {
818
+ language_data.content_json[docIndex].list = [
819
+ {
820
+ key: tag.key,
821
+ value: text,
822
+ },
823
+ ];
824
+ return;
825
+ }
826
+ const keyIndex = language_data.content_json[
827
+ docIndex
828
+ ].list.findIndex((l: any) => l.key === tag.key);
829
+ if (keyIndex === -1) {
830
+ language_data.content_json[docIndex].list.push({
831
+ key: tag.key,
832
+ value: text,
833
+ });
834
+ return;
835
+ }
836
+ language_data.content_json[docIndex].list[keyIndex].value =
837
+ text;
838
+ },
839
+ placeHolder: '輸入文本標籤',
840
+ })}
841
+ </div>`;
842
+ })
843
+ .join(BgWidget.mbContainer(12))}
844
+ </div>`;
845
+ },
846
+ footer_html: (gvc2: GVC) => {
847
+ return [
848
+ BgWidget.cancel(
849
+ gvc2.event(() => {
850
+ language_data.content_json = originJson;
851
+ gvc2.closeDialog();
852
+ })
853
+ ),
854
+ BgWidget.save(
855
+ gvc2.event(() => {
856
+ gvc2.closeDialog();
857
+ gvc.notifyDataChange(`${id}-${index}`);
858
+ })
859
+ ),
860
+ ].join('');
861
+ },
862
+ closeCallback: () => {
863
+ language_data.content_json = originJson;
864
+ },
865
+ });
866
+ })}"
948
867
  >
949
- ${item.data.content || ''}
950
- </div>`;
951
- })(),
952
- });
953
- })
954
- .join(BgWidget.mbContainer(8))}`;
955
- },
956
- };
957
- })();
958
- }),
959
- ].join(BgWidget.mbContainer(12))
960
- ),
961
- BgWidget.mainCard(html`
962
- <div
963
- class="d-flex align-items-center justify-content-between"
964
- style="color: #393939;font-size: 16px;font-weight: 700;margin-bottom: 18px;"
965
- >
966
- <div class="d-flex align-items-center">
967
- 圖片${BgWidget.languageInsignia(sel_lan(), 'margin-left:5px;')}
968
- </div>
969
- <div class="d-flex align-items-center gap-2">
970
- ${BgWidget.customButton({
971
- button: {
972
- color: 'black',
973
- size: 'sm',
974
- },
975
- text: {
976
- name: '上傳圖片',
868
+ 標籤設值
869
+ </div>
870
+ ${gvc.bindView(
871
+ (() => {
872
+ return {
873
+ bind: `${id}-${index}`,
874
+ view: () => {
875
+ const content = item.data.content || '';
876
+ const tags = item.data.tags;
877
+ const jsonData = language_data.content_json.find(
878
+ (c: any) => c.id === item.id
879
+ );
880
+ return html` <div
881
+ style="border: 2px #DDDDDD solid; border-radius: 6px; padding: 12px;"
882
+ >
883
+ ${tags
884
+ ? formatRichtext(content, tags, jsonData ? jsonData.list : [])
885
+ : content}
886
+ </div>`;
887
+ },
888
+ };
889
+ })()
890
+ )}`;
891
+ }
892
+ return html` <div style="border: 1px #DDDDDD solid; border-radius: 6px; padding: 12px">
893
+ ${item.data.content || ''}
894
+ </div>`;
895
+ })(),
896
+ });
897
+ })
898
+ .join(BgWidget.mbContainer(8))}`;
899
+ },
900
+ };
901
+ })();
902
+ }),
903
+ ].join(BgWidget.mbContainer(12))
904
+ );
905
+ }
906
+
907
+ function drawProductImageBlock() {
908
+ return BgWidget.mainCard(html`<!--繪製商品圖片展示區塊-->
909
+ <div
910
+ class="d-flex align-items-center justify-content-between"
911
+ style="color: #393939;font-size: 16px;font-weight: 700;margin-bottom: 18px;"
912
+ >
913
+ <div class="d-flex align-items-center">圖片${BgWidget.languageInsignia(sel_lan(), 'margin-left:5px;')}</div>
914
+ <div class="d-flex align-items-center gap-2">
915
+ ${BgWidget.customButton({
916
+ button: {
917
+ color: 'black',
918
+ size: 'sm',
919
+ },
920
+ text: {
921
+ name: '上傳圖片',
922
+ },
923
+ event: gvc.event(() => {
924
+ EditorElem.uploadFileFunction({
925
+ gvc: gvc,
926
+ callback: (images: any) => {
927
+ const addImage = (urlArray: string[]) => {
928
+ if (urlArray.length > 0) {
929
+ language_data.preview_image.push(...urlArray);
930
+ saveImageLib(urlArray);
931
+ obj.gvc.notifyDataChange('image_view');
932
+ } else {
933
+ dialog.errorMessage({ text: '請選擇至少一張圖片' });
934
+ }
935
+ };
936
+ addImage(images);
977
937
  },
978
- event: gvc.event(() => {
979
- EditorElem.uploadFileFunction({
980
- gvc: gvc,
981
- callback: (images: any) => {
982
- const addImage = (urlArray: string[]) => {
983
- if (urlArray.length > 0) {
984
- language_data.preview_image.push(...urlArray);
985
- saveImageLib(urlArray);
986
- obj.gvc.notifyDataChange('image_view');
987
- } else {
988
- dialog.errorMessage({ text: '請選擇至少一張圖片' });
989
- }
990
- };
991
- addImage(images);
992
- },
993
- type: `image/*`,
994
- return_array: true,
995
- multiple: true,
996
- });
997
- }),
998
- })}
999
- ${BgWidget.customButton({
1000
- button: {
1001
- color: 'black',
1002
- size: 'sm',
938
+ type: `image/*`,
939
+ return_array: true,
940
+ multiple: true,
941
+ });
942
+ }),
943
+ })}
944
+ ${BgWidget.customButton({
945
+ button: {
946
+ color: 'black',
947
+ size: 'sm',
948
+ },
949
+ text: {
950
+ name: '從圖片庫選取',
951
+ },
952
+ event: gvc.event(() => {
953
+ imageLibrary.selectImageLibrary(
954
+ gvc,
955
+ urlArray => {
956
+ if (urlArray.length > 0) {
957
+ language_data.preview_image.push(
958
+ ...urlArray.map((data: any) => {
959
+ return data.data;
960
+ })
961
+ );
962
+ obj.gvc.notifyDataChange('image_view');
963
+ } else {
964
+ dialog.errorMessage({ text: '請選擇至少一張圖片' });
965
+ }
1003
966
  },
1004
- text: {
1005
- name: '從圖片庫選取',
967
+ html` <div class="d-flex flex-column" style="border-radius: 10px 10px 0px 0px;background: #F2F2F2;">
968
+ 圖片庫
969
+ </div>`,
970
+ { mul: true }
971
+ );
972
+ }),
973
+ })}
974
+ </div>
975
+ </div>
976
+ ${obj.gvc.bindView(() => {
977
+ return {
978
+ bind: 'image_view',
979
+ view: () => {
980
+ return (
981
+ html` <div class="my-2"></div>` +
982
+ EditorElem.flexMediaManagerV2({
983
+ gvc: obj.gvc,
984
+ data: language_data.preview_image,
985
+ event: {
986
+ delete: (index: number) => {
987
+ postMD.variants.forEach((variant: any) => {
988
+ if (variant.preview_image === language_data.preview_image[index]) {
989
+ variant.preview_image = language_data.preview_image[0] ?? BgWidget.noImageURL;
990
+ }
991
+ if (variant[`preview_image_${vm.language}`] === language_data.preview_image[index]) {
992
+ variant[`preview_image_${vm.language}`] =
993
+ language_data.preview_image[0] ?? BgWidget.noImageURL;
994
+ }
995
+ });
996
+ ShoppingSettingBasic.updateVariants(gvc, postMD, shipment_config, variantsViewID, obj);
997
+ },
1006
998
  },
1007
- event: gvc.event(() => {
1008
- imageLibrary.selectImageLibrary(
1009
- gvc,
1010
- urlArray => {
1011
- if (urlArray.length > 0) {
1012
- language_data.preview_image.push(
1013
- ...urlArray.map((data: any) => {
1014
- return data.data;
1015
- })
999
+ })
1000
+ );
1001
+ },
1002
+ divCreate: {
1003
+ class: `d-flex w-100`,
1004
+ style: `overflow-y:scroll;height:180px;`,
1005
+ },
1006
+ };
1007
+ })}
1008
+ `);
1009
+ }
1010
+
1011
+ function drawReserveLocations() {
1012
+ if (postMD.product_category === 'reserve') {
1013
+ function getStockStore() {
1014
+ ApiUser.getPublicConfig('store_manager', 'manager').then((storeData: any) => {
1015
+ if (storeData.result) {
1016
+ stockList = storeData.response.value.list.filter((store: any) => store.is_shop) as Store[];
1017
+ postMD.reserve_locations = stockList;
1018
+ console.log('postMD.reserve_locations -- ', postMD.reserve_locations);
1019
+ gvc.notifyDataChange([section_ID.reserve_locations, section_ID.store_product_config_panel]);
1020
+ }
1021
+ });
1022
+ loading.reserve_locations = false;
1023
+ }
1024
+
1025
+ return gvc.bindView({
1026
+ bind: section_ID.reserve_locations,
1027
+ view: () => {
1028
+ gvc.addStyle(css`
1029
+ .location-btn {
1030
+ height: 34px;
1031
+ padding: 0 12px;
1032
+ border-radius: 10px;
1033
+ border: 1px solid #393939;
1034
+ gap: 6px;
1035
+ }
1036
+
1037
+ .location-dialog {
1038
+ display: flex;
1039
+ width: 504px;
1040
+
1041
+ flex-direction: column;
1042
+ align-items: center;
1043
+ gap: 18px;
1044
+ border-radius: 10px;
1045
+ background: #fff;
1046
+ }
1047
+
1048
+ .location-dialog .title {
1049
+ display: flex;
1050
+ padding: 12px 20px;
1051
+ justify-content: space-between;
1052
+ border-radius: 10px 10px 0 0;
1053
+ align-items: center;
1054
+ background: #f2f2f2;
1055
+ color: #393939;
1056
+ }
1057
+
1058
+ .location-dialog .section {
1059
+ padding: 0 20px;
1060
+ gap: 12px;
1061
+ }
1062
+ `);
1063
+ if (loading.reserve_locations) {
1064
+ getStockStore();
1065
+ return ``;
1066
+ }
1067
+
1068
+ function popoutSelectLocation(callback: (location: Store[]) => void) {
1069
+ gvc.glitter.innerDialog(gvc => {
1070
+ function drawRaw(store: Store) {
1071
+ const checked = temp_Reserve_locations.filter(store2 => store2.id == store.id).length > 0;
1072
+ return html`
1073
+ <div class="w-100 d-flex align-items-center" style="padding:0 4px;gap:8px;">
1074
+ ${BgWidget.checkInput(gvc, checked, () => {
1075
+ if (checked) {
1076
+ temp_Reserve_locations.splice(
1077
+ temp_Reserve_locations.findIndex(store2 => store2.id == store.id),
1078
+ 1
1016
1079
  );
1017
- obj.gvc.notifyDataChange('image_view');
1018
1080
  } else {
1019
- dialog.errorMessage({ text: '請選擇至少一張圖片' });
1081
+ temp_Reserve_locations.push(store);
1020
1082
  }
1021
- },
1022
- html` <div
1023
- class="d-flex flex-column"
1024
- style="border-radius: 10px 10px 0px 0px;background: #F2F2F2;"
1025
- >
1026
- 圖片庫
1027
- </div>`,
1028
- { mul: true }
1029
- );
1030
- }),
1031
- })}
1032
- </div>
1033
- </div>
1034
- ${obj.gvc.bindView(() => {
1035
- return {
1036
- bind: 'image_view',
1037
- view: () => {
1038
- return (
1039
- html` <div class="my-2"></div>` +
1040
- EditorElem.flexMediaManagerV2({
1041
- gvc: obj.gvc,
1042
- data: language_data.preview_image,
1043
- event: {
1044
- delete: (index: number) => {
1045
- postMD.variants.forEach((variant: any) => {
1046
- if (variant.preview_image === language_data.preview_image[index]) {
1047
- variant.preview_image = language_data.preview_image[0] ?? BgWidget.noImageURL;
1048
- }
1049
- if (variant[`preview_image_${vm.language}`] === language_data.preview_image[index]) {
1050
- variant[`preview_image_${vm.language}`] =
1051
- language_data.preview_image[0] ?? BgWidget.noImageURL;
1083
+ gvc.notifyDataChange([section_ID.dialog_location_main]);
1084
+ })}
1085
+ <div>${store.name}</div>
1086
+ </div>
1087
+ `;
1088
+ }
1089
+
1090
+ let temp_Reserve_locations = structuredClone(postMD.reserve_locations);
1091
+ let searchText = '';
1092
+ return gvc.bindView({
1093
+ bind: section_ID.dialog_location_main,
1094
+ view: () => {
1095
+ const allCheck = temp_Reserve_locations.length == stockList.length;
1096
+ return html`
1097
+ <div class="title w-100">
1098
+ <div class="tx_normal">新增服務地點</div>
1099
+ <i
1100
+ class="fa-solid fa-xmark cursor_pointer"
1101
+ onclick="${gvc.event(() => {
1102
+ gvc.glitter.closeDiaLog('location-select');
1103
+ })}"
1104
+ ></i>
1105
+ </div>
1106
+ <div class="section w-100 d-flex flex-column">
1107
+ ${BgWidget.searchFilter(
1108
+ gvc.event(e => {
1109
+ searchText = e.value;
1110
+ gvc.notifyDataChange(section_ID.dialog_location_list);
1111
+ }),
1112
+ searchText || '',
1113
+ '搜尋門市'
1114
+ )}
1115
+ <div class="d-flex align-items-center" style="gap:8px;padding:4px 4px 0; ">
1116
+ ${BgWidget.checkInput(gvc, allCheck, () => {
1117
+ if (allCheck) {
1118
+ temp_Reserve_locations = [];
1119
+ } else {
1120
+ temp_Reserve_locations = stockList;
1052
1121
  }
1053
- });
1054
- ShoppingSettingBasic.updateVariants(gvc, postMD, shipment_config, variantsViewID, obj);
1055
- },
1056
- },
1057
- })
1058
- );
1059
- },
1060
- divCreate: {
1061
- class: `d-flex w-100`,
1062
- style: `overflow-y:scroll;height:180px;`,
1063
- },
1064
- };
1065
- })}
1066
- `),
1067
- (() => {
1068
- if (postMD.variants.length === 1) {
1069
- try {
1070
- (postMD.variants[0] as any).editable = true;
1071
- return ShoppingProductSetting.editProductSpec({
1072
- vm: obj.vm,
1073
- defData: postMD,
1074
- gvc: gvc,
1075
- single: true,
1122
+ gvc.notifyDataChange([section_ID.dialog_location_list, section_ID.dialog_location_main]);
1123
+ })}
1124
+ 門市名稱
1125
+ </div>
1126
+ <hr class="w-100" />
1127
+ ${gvc.bindView({
1128
+ bind: section_ID.dialog_location_list,
1129
+ view: () => {
1130
+ const showList = stockList.filter(store =>
1131
+ store.name.toLowerCase().includes(searchText.toLowerCase())
1132
+ );
1133
+ return showList.map(drawRaw).join('');
1134
+ },
1135
+ divCreate: {
1136
+ class: 'd-flex flex-column',
1137
+ style: 'gap:16px',
1138
+ },
1139
+ })}
1140
+ </div>
1141
+ <div
1142
+ class="w-100 d-flex align-items-center justify-content-end"
1143
+ style="gap:14px;padding:0 20px 20px"
1144
+ >
1145
+ ${BgWidget.cancel(
1146
+ gvc.event(() => {
1147
+ gvc.glitter.closeDiaLog('location-select');
1148
+ })
1149
+ )}
1150
+ ${BgWidget.save(
1151
+ gvc.event(() => {
1152
+ gvc.glitter.closeDiaLog('location-select');
1153
+ callback(temp_Reserve_locations);
1154
+ })
1155
+ )}
1156
+ </div>
1157
+ `;
1158
+ },
1159
+ divCreate: {
1160
+ class: 'location-dialog',
1161
+ },
1076
1162
  });
1077
- } catch (e) {
1078
- console.error(e);
1079
- return '';
1080
- }
1163
+ }, 'location-select');
1081
1164
  }
1082
- return '';
1083
- })(),
1084
- BgWidget.mainCard(
1085
- obj.gvc.bindView(() => {
1086
- const specid = obj.gvc.glitter.getUUID();
1087
- let editIndex = -1;
1088
1165
 
1089
- gvc.addStyle(`
1166
+ function drawLocation(location: Store) {
1167
+ const width =
1168
+ postMD.reserve_locations.length > 3 ? 'width:calc(25% - 12px)' : 'flex:1 1 auto;max-width:50%;';
1169
+ return html`
1170
+ <div class="location-btn tx_normal d-flex align-items-center " style="${width} ">
1171
+ <div class="d-flex align-items-center justify-content-center flex-fill" style="cursor:default">
1172
+ ${location.name}
1173
+ </div>
1174
+ <i
1175
+ class="fa-solid fa-xmark ms-auto cursor_pointer"
1176
+ style="color:#B0B0B0"
1177
+ onclick="${gvc.event(() => {
1178
+ postMD.reserve_locations.splice(
1179
+ postMD.reserve_locations.findIndex(store => store.id == location.id),
1180
+ 1
1181
+ );
1182
+ gvc.notifyDataChange(section_ID.reserve_locations);
1183
+ })}"
1184
+ ></i>
1185
+ </div>
1186
+ `;
1187
+ }
1188
+
1189
+ return BgWidget.mainCard(html`<!--繪製預約門市選擇區塊-->
1190
+ <div class="d-flex flex-column" style="gap:18px;">
1191
+ <div class="d-flex align-items-center">
1192
+ 服務地點${BgWidget.languageInsignia(sel_lan(), 'margin-left:5px;')}
1193
+ </div>
1194
+ <div class="d-flex flex-wrap" style="gap:12px;">
1195
+ ${stockList.length == 0
1196
+ ? html` <div class="w-100 d-flex align-items-center justify-content-center tx_gray_16">
1197
+ 尚未設置門市,請前往POS實體門市>門市設定
1198
+ </div>`
1199
+ : postMD.reserve_locations.map(drawLocation).join('')}
1200
+ </div>
1201
+ <div
1202
+ class="d-flex justify-content-center align-items-center cursor_pointer"
1203
+ style="gap:4px;color: #36B;"
1204
+ onclick="${gvc.event(() => {
1205
+ popoutSelectLocation(newStoreList => {
1206
+ postMD.reserve_locations = newStoreList;
1207
+ gvc.notifyDataChange(section_ID.reserve_locations);
1208
+ });
1209
+ })}"
1210
+ >
1211
+ 新增服務地點 <i class="fa-solid fa-plus"></i>
1212
+ </div>
1213
+ </div>
1214
+ `);
1215
+ },
1216
+ divCreate: {},
1217
+ });
1218
+ } else {
1219
+ return ``;
1220
+ }
1221
+ }
1222
+
1223
+ function drawIndividualStoreProductConfigPanel() {
1224
+ if (postMD.product_category == 'reserve') {
1225
+ if (postMD.reserve_locations && postMD.reserve_locations.length > 0) {
1226
+ return gvc.bindView({
1227
+ bind: section_ID.store_product_config_panel,
1228
+ view: () => {
1229
+ return BgWidget.mainCard(html`<!--繪製單一門市的商品配置面板-->
1230
+ <div class="d-flex flex-column">
1231
+ <div class="tx_700">依門市管理</div>
1232
+ <div class="tx_gray_14">其他門市將預設套用此門市的設定,如需修改,請切換至對應門市進行調整</div>
1233
+ </div>
1234
+ ${BgWidget.select({
1235
+ default: postMD.reserve_locations[0].id,
1236
+ gvc: gvc,
1237
+ options: postMD.reserve_locations.map(location => {
1238
+ return {
1239
+ value: location.name,
1240
+ key: location.id,
1241
+ };
1242
+ }),
1243
+ callback(value: any): void {},
1244
+ })}
1245
+ `);
1246
+ },
1247
+ divCreate: {},
1248
+ });
1249
+ } else {
1250
+ return ``;
1251
+ }
1252
+ } else {
1253
+ return ``;
1254
+ }
1255
+ }
1256
+
1257
+ function drawSpecEditView() {
1258
+ if (postMD.variants.length === 1) {
1259
+ try {
1260
+ (postMD.variants[0] as any).editable = true;
1261
+ return html`
1262
+ <!-- 繪製 編輯商品規格編輯區塊-->
1263
+ `+ ShoppingProductSetting.editProductSpec({
1264
+ vm: obj.vm,
1265
+ defData: postMD,
1266
+ gvc: gvc,
1267
+ single: true,
1268
+ });
1269
+ } catch (e) {
1270
+ console.error(e);
1271
+ return '';
1272
+ }
1273
+ }
1274
+ return '';
1275
+ }
1276
+
1277
+ function drawProductSpecList() {
1278
+ return BgWidget.mainCard(
1279
+ obj.gvc.bindView(() => {
1280
+ const specid = obj.gvc.glitter.getUUID();
1281
+ let editIndex = -1;
1282
+
1283
+ gvc.addStyle(`
1090
1284
  .spec-option {
1091
1285
  border: 0.25px solid #393939;
1092
1286
  background-color: #f7f7f7;
@@ -1099,665 +1293,747 @@ export class ShoppingSettingBasic {
1099
1293
  }
1100
1294
  `);
1101
1295
 
1102
- return {
1103
- bind: specid,
1104
- dataList: [{ obj: createPage, key: 'page' }],
1105
- view: () => {
1106
- let returnHTML = html`
1107
- <div
1108
- class="d-flex align-items-center justify-content-between"
1109
- style="font-size: 16px;font-weight: 700;"
1110
- >
1111
- ${cat_title}規格 ${BgWidget.languageInsignia(sel_lan(), '')}
1112
- </div>
1113
- `;
1114
- let editSpectPage: any = [];
1115
- if (postMD.specs.length > 0) {
1116
- postMD.specs.map((d, index) => {
1117
- editSpectPage.push({
1118
- type: index === editIndex ? 'edit' : 'show',
1119
- });
1120
- });
1121
- returnHTML += html`
1122
- ${EditorElem.arrayItem({
1123
- customEditor: true,
1124
- gvc: obj.gvc,
1125
- title: '',
1126
- hoverGray: true,
1127
- position: 'front',
1128
- height: 100,
1129
- originalArray: postMD.specs,
1130
- expand: true,
1131
- copyable: false,
1132
- hr: true,
1133
- minus: false,
1134
- refreshComponent: (fromIndex, toIndex) => {
1135
- postMD.variants.map(item => {
1136
- // 確保索引值在數組範圍內
1137
- if (
1138
- fromIndex === undefined ||
1139
- toIndex === undefined ||
1140
- fromIndex < 0 ||
1141
- fromIndex >= item.spec.length ||
1142
- toIndex < 0 ||
1143
- toIndex >= item.spec.length
1144
- ) {
1145
- throw new Error('索引超出範圍');
1146
- }
1296
+ return {
1297
+ bind: specid,
1298
+ dataList: [{ obj: createPage, key: 'page' }],
1299
+ view: () => {
1300
+ let returnHTML = html`
1301
+ <!-- 繪製商品規格列表區塊-->
1302
+ <div
1303
+ class="d-flex align-items-center justify-content-between"
1304
+ style="font-size: 16px;font-weight: 700;"
1305
+ >
1306
+ ${cat_title}規格 ${BgWidget.languageInsignia(sel_lan(), '')}
1307
+ </div>
1308
+ `;
1309
+ let editSpectPage: any = [];
1310
+ if (postMD.specs.length > 0) {
1311
+ postMD.specs.map((d, index) => {
1312
+ editSpectPage.push({
1313
+ type: index === editIndex ? 'edit' : 'show',
1314
+ });
1315
+ });
1316
+ returnHTML += html`
1317
+ ${EditorElem.arrayItem({
1318
+ customEditor: true,
1319
+ gvc: obj.gvc,
1320
+ title: '',
1321
+ hoverGray: true,
1322
+ position: 'front',
1323
+ height: 100,
1324
+ originalArray: postMD.specs,
1325
+ expand: true,
1326
+ copyable: false,
1327
+ hr: true,
1328
+ minus: false,
1329
+ refreshComponent: (fromIndex, toIndex) => {
1330
+ postMD.variants.map(item => {
1331
+ // 確保索引值在數組範圍內
1332
+ if (
1333
+ fromIndex === undefined ||
1334
+ toIndex === undefined ||
1335
+ fromIndex < 0 ||
1336
+ fromIndex >= item.spec.length ||
1337
+ toIndex < 0 ||
1338
+ toIndex >= item.spec.length
1339
+ ) {
1340
+ throw new Error('索引超出範圍');
1341
+ }
1147
1342
 
1148
- // 取出元素並插入元素到新位置
1149
- let element = item.spec.splice(fromIndex, 1)[0];
1150
- item.spec.splice(toIndex, 0, element);
1343
+ // 取出元素並插入元素到新位置
1344
+ let element = item.spec.splice(fromIndex, 1)[0];
1345
+ item.spec.splice(toIndex, 0, element);
1151
1346
 
1152
- return item;
1153
- });
1347
+ return item;
1348
+ });
1154
1349
 
1155
- obj.gvc.notifyDataChange([specid, 'productInf', 'spec_text_show']);
1156
- },
1157
- array: () => {
1158
- function swapArray(arr: any[], index1: number, index2: number) {
1159
- if (index1 === index2) return;
1160
- const [item] = arr.splice(index1, 1);
1161
- arr.splice(index2, 0, item);
1162
- }
1350
+ obj.gvc.notifyDataChange([specid, 'productInf', 'spec_text_show']);
1351
+ },
1352
+ array: () => {
1353
+ function swapArray(arr: any[], index1: number, index2: number) {
1354
+ if (index1 === index2) return;
1355
+ const [item] = arr.splice(index1, 1);
1356
+ arr.splice(index2, 0, item);
1357
+ }
1163
1358
 
1164
- return postMD.specs.map((dd, specIndex: number) => {
1165
- let temp: any = {
1166
- title: '',
1167
- option: [],
1168
- };
1169
- return {
1170
- title: gvc.bindView({
1171
- bind: `editSpec${specIndex}`,
1172
- dataList: [
1173
- {
1174
- obj: editSpectPage[specIndex],
1175
- key: 'type',
1176
- },
1177
- ],
1178
- view: () => {
1179
- dd.language_title = (dd.language_title ?? ({} as any)) as any;
1180
- if (editSpectPage[specIndex].type == 'show') {
1181
- return gvc.bindView({
1182
- bind: gvc.glitter.getUUID(),
1183
- view: () => {
1184
- return html`<div style="font-size: 16px;">
1185
- ${(dd.language_title as any)[sel_lan()] || dd.title}
1186
- </div>
1187
- ${(() => {
1188
- let returnHTML = '';
1189
- dd.option.map((opt: any, index: number) => {
1190
- opt.language_title = (opt.language_title ?? ({} as any)) as any;
1191
- returnHTML += html`
1192
- <div
1193
- class="spec-option"
1194
- style="cursor: move;"
1195
- draggable="true"
1196
- data-index="${index}"
1197
- >
1198
- ${Tool.truncateString(
1199
- (opt.language_title as any)[sel_lan()] || opt.title,
1200
- 30
1201
- )}
1202
- </div>
1203
- `;
1204
- });
1205
- return html`
1206
- <div class="d-flex w-100 flex-wrap gap-2" id="sortable-list-${specIndex}">
1207
- ${returnHTML}
1208
- <div
1209
- class="position-absolute"
1210
- style="right:12px;top:50%;transform: translateY(-50%);"
1211
- onclick="${gvc.event(() => {
1212
- createPage.page = 'add';
1213
- editIndex = specIndex;
1214
- gvc.notifyDataChange(specid);
1215
- })}"
1216
- >
1217
- <svg
1218
- style="cursor: pointer;"
1219
- xmlns="http://www.w3.org/2000/svg"
1220
- width="16"
1221
- height="17"
1222
- viewBox="0 0 16 17"
1223
- fill="none"
1224
- >
1225
- <g clip-path="url(#clip0_8114_2928)">
1226
- <path
1227
- d="M1.13728 11.7785L0.418533 14.2191L0.0310334 15.5379C-0.0470916 15.8035 0.0247834 16.0879 0.218533 16.2816C0.412283 16.4754 0.696658 16.5473 0.959158 16.4723L2.28103 16.0816L4.72166 15.3629C5.04666 15.2691 5.34978 15.1129 5.61541 14.9098L5.62478 14.916L5.64041 14.891C5.68416 14.8566 5.72478 14.8223 5.76541 14.7879C5.80916 14.7504 5.84978 14.7098 5.89041 14.6691L15.3967 5.16602C16.081 4.48164 16.1654 3.42852 15.6529 2.65039C15.581 2.54102 15.4935 2.43477 15.3967 2.33789L14.1654 1.10352C13.3842 0.322266 12.1185 0.322266 11.3373 1.10352L1.83103 10.6098C1.75291 10.6879 1.67791 10.7723 1.60916 10.8598L1.58416 10.8754L1.59041 10.8848C1.38728 11.1504 1.23416 11.4535 1.13728 11.7785ZM11.9685 6.46914L6.16853 12.2691L4.61853 11.8816L4.23103 10.3316L10.031 4.53164L11.9685 6.46914ZM3.03103 11.716L3.27166 12.6848C3.33728 12.9535 3.54978 13.1629 3.81853 13.2316L4.78728 13.4723L4.55603 13.8223C4.47478 13.866 4.39041 13.9035 4.30291 13.9285L3.57166 14.1441L1.85603 14.6441L2.35916 12.9316L2.57478 12.2004C2.59978 12.1129 2.63728 12.0254 2.68103 11.9473L3.03103 11.716ZM9.85291 7.33477C10.0467 7.14102 10.0467 6.82227 9.85291 6.62852C9.65916 6.43477 9.34041 6.43477 9.14666 6.62852L6.14666 9.62852C5.95291 9.82227 5.95291 10.141 6.14666 10.3348C6.34041 10.5285 6.65916 10.5285 6.85291 10.3348L9.85291 7.33477Z"
1228
- fill="#393939"
1229
- />
1230
- </g>
1231
- <defs>
1232
- <clipPath id="clip0_8114_2928">
1233
- <rect
1234
- width="16"
1235
- height="16"
1236
- fill="white"
1237
- transform="translate(0 0.5)"
1238
- />
1239
- </clipPath>
1240
- </defs>
1241
- </svg>
1242
- </div>
1243
- </div>
1244
- `;
1245
- })()}`;
1246
- },
1247
- divCreate: {
1248
- class: 'd-flex flex-column',
1249
- style: 'gap: 6px; align-items: flex-start; padding: 12px 0;',
1250
- },
1251
- onCreate: () => {
1252
- gvc.addMtScript(
1253
- [{ src: 'https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js' }],
1254
- () => {
1255
- const interval = setInterval(() => {
1256
- const Sortable = (window as any).Sortable;
1257
- if (!Sortable) return;
1258
-
1259
- clearInterval(interval);
1260
-
1261
- try {
1262
- const dragId = `sortable-list-${specIndex}`;
1263
- const dragEl = document.getElementById(dragId);
1264
-
1265
- if (!dragEl) {
1266
- console.warn(`Element with id '${dragId}' not found.`);
1267
- return;
1268
- }
1269
-
1270
- Sortable.create(dragEl, {
1271
- group: { name: dragId, pull: false, put: false },
1272
- animation: 150,
1273
- onEnd(evt: any) {
1274
- swapArray(
1275
- postMD.specs[specIndex].option,
1276
- evt.oldIndex,
1277
- evt.newIndex
1278
- );
1279
- },
1280
- });
1281
- } catch (e) {
1282
- console.error('SortableJS initialization error:', e);
1283
- }
1284
- }, 100);
1285
- },
1286
- () => console.error('Failed to load SortableJS')
1287
- );
1288
- },
1289
- });
1290
- }
1291
- temp = JSON.parse(JSON.stringify(dd));
1292
- if (sel_lan() !== (window.parent as any).store_info.language_setting.def) {
1293
- return obj.gvc.bindView({
1294
- bind: 'spec_text_show',
1295
- dataList: [
1296
- {
1297
- obj: createPage,
1298
- key: 'page',
1299
- },
1300
- ],
1301
- view: () => {
1359
+ return postMD.specs.map((dd, specIndex: number) => {
1360
+ let temp: any = {
1361
+ title: '',
1362
+ option: [],
1363
+ };
1364
+ return {
1365
+ title: gvc.bindView({
1366
+ bind: `editSpec${specIndex}`,
1367
+ dataList: [
1368
+ {
1369
+ obj: editSpectPage[specIndex],
1370
+ key: 'type',
1371
+ },
1372
+ ],
1373
+ view: () => {
1374
+ dd.language_title = (dd.language_title ?? ({} as any)) as any;
1375
+ if (editSpectPage[specIndex].type == 'show') {
1376
+ return gvc.bindView({
1377
+ bind: gvc.glitter.getUUID(),
1378
+ view: () => {
1379
+ return html` <div style="font-size: 16px;">
1380
+ ${(dd.language_title as any)[sel_lan()] || dd.title}
1381
+ </div>
1382
+ ${(() => {
1302
1383
  let returnHTML = '';
1303
- let specs_in_line: string[] = [];
1304
- temp.option = temp.option ?? [];
1305
- specs_in_line.push(
1306
- html` <div class="d-flex flex-column w-100">
1307
- <div class="d-flex flex-column" style="gap:10px;">
1308
- <div class="fw-500">規格種類 - ${temp.title}</div>
1309
- <input
1310
- class="form-control w-100"
1311
- placeholder="${temp.title}"
1312
- style="width:100px;height: 35px;"
1313
- value="${(temp.language_title as any)[vm.language] || ''}"
1314
- onchange="${gvc.event((e, event) => {
1315
- (temp.language_title as any)[vm.language] = e.value;
1316
- })}"
1317
- />
1384
+ dd.option.map((opt: any, index: number) => {
1385
+ opt.language_title = (opt.language_title ?? ({} as any)) as any;
1386
+ returnHTML += html`
1387
+ <div
1388
+ class="spec-option"
1389
+ style="cursor: move;"
1390
+ draggable="true"
1391
+ data-index="${index}"
1392
+ >
1393
+ ${Tool.truncateString(
1394
+ (opt.language_title as any)[sel_lan()] || opt.title,
1395
+ 30
1396
+ )}
1318
1397
  </div>
1319
- <div class="d-flex flex-column w-100" style="gap:5px;">
1320
- ${temp.option
1321
- .map((d: any, index: number) => {
1322
- d.language_title = d.language_title ?? ({} as any);
1323
- return html` <div class="d-flex flex-column mt-2" style="gap:10px;">
1324
- <div class="fw-500">選項${index + 1} - ${d.title}</div>
1325
- <input
1326
- class="form-control w-100"
1327
- placeholder="${d.title}"
1328
- style="width:100px;height: 35px;"
1329
- value="${(d.language_title as any)[vm.language] || ''}"
1330
- onchange="${gvc.event((e, event) => {
1331
- (d.language_title as any)[vm.language] = e.value;
1332
- })}"
1398
+ `;
1399
+ });
1400
+ return html`
1401
+ <div class="d-flex w-100 flex-wrap gap-2" id="sortable-list-${specIndex}">
1402
+ ${returnHTML}
1403
+ <div
1404
+ class="position-absolute"
1405
+ style="right:12px;top:50%;transform: translateY(-50%);"
1406
+ onclick="${gvc.event(() => {
1407
+ createPage.page = 'add';
1408
+ editIndex = specIndex;
1409
+ gvc.notifyDataChange(specid);
1410
+ })}"
1411
+ >
1412
+ <svg
1413
+ style="cursor: pointer;"
1414
+ xmlns="http://www.w3.org/2000/svg"
1415
+ width="16"
1416
+ height="17"
1417
+ viewBox="0 0 16 17"
1418
+ fill="none"
1419
+ >
1420
+ <g clip-path="url(#clip0_8114_2928)">
1421
+ <path
1422
+ d="M1.13728 11.7785L0.418533 14.2191L0.0310334 15.5379C-0.0470916 15.8035 0.0247834 16.0879 0.218533 16.2816C0.412283 16.4754 0.696658 16.5473 0.959158 16.4723L2.28103 16.0816L4.72166 15.3629C5.04666 15.2691 5.34978 15.1129 5.61541 14.9098L5.62478 14.916L5.64041 14.891C5.68416 14.8566 5.72478 14.8223 5.76541 14.7879C5.80916 14.7504 5.84978 14.7098 5.89041 14.6691L15.3967 5.16602C16.081 4.48164 16.1654 3.42852 15.6529 2.65039C15.581 2.54102 15.4935 2.43477 15.3967 2.33789L14.1654 1.10352C13.3842 0.322266 12.1185 0.322266 11.3373 1.10352L1.83103 10.6098C1.75291 10.6879 1.67791 10.7723 1.60916 10.8598L1.58416 10.8754L1.59041 10.8848C1.38728 11.1504 1.23416 11.4535 1.13728 11.7785ZM11.9685 6.46914L6.16853 12.2691L4.61853 11.8816L4.23103 10.3316L10.031 4.53164L11.9685 6.46914ZM3.03103 11.716L3.27166 12.6848C3.33728 12.9535 3.54978 13.1629 3.81853 13.2316L4.78728 13.4723L4.55603 13.8223C4.47478 13.866 4.39041 13.9035 4.30291 13.9285L3.57166 14.1441L1.85603 14.6441L2.35916 12.9316L2.57478 12.2004C2.59978 12.1129 2.63728 12.0254 2.68103 11.9473L3.03103 11.716ZM9.85291 7.33477C10.0467 7.14102 10.0467 6.82227 9.85291 6.62852C9.65916 6.43477 9.34041 6.43477 9.14666 6.62852L6.14666 9.62852C5.95291 9.82227 5.95291 10.141 6.14666 10.3348C6.34041 10.5285 6.65916 10.5285 6.85291 10.3348L9.85291 7.33477Z"
1423
+ fill="#393939"
1424
+ />
1425
+ </g>
1426
+ <defs>
1427
+ <clipPath id="clip0_8114_2928">
1428
+ <rect
1429
+ width="16"
1430
+ height="16"
1431
+ fill="white"
1432
+ transform="translate(0 0.5)"
1333
1433
  />
1334
- </div>`;
1335
- })
1336
- .join('<div class="mx-1"></div>')}
1434
+ </clipPath>
1435
+ </defs>
1436
+ </svg>
1337
1437
  </div>
1338
- </div>`
1339
- );
1340
- returnHTML += specs_in_line.join(`<div class="w-100 border-top"></div>`);
1341
- returnHTML += html` <div
1342
- class="d-flex w-100 justify-content-end align-items-center w-100 bg-white"
1343
- style="gap:14px; margin-top: 12px;"
1344
- >
1345
- ${BgWidget.cancel(
1346
- obj.gvc.event(() => {
1347
- editIndex = -1;
1348
- gvc.notifyDataChange(vm.id);
1349
- })
1350
- )}
1351
- ${BgWidget.save(
1352
- obj.gvc.event(() => {
1353
- postMD.specs[specIndex] = temp;
1354
- ShoppingSettingBasic.updateVariants(
1355
- gvc,
1356
- postMD,
1357
- shipment_config,
1358
- variantsViewID,
1359
- obj
1360
- );
1361
- gvc.notifyDataChange(vm.id);
1362
- }),
1363
- '完成'
1364
- )}
1365
- </div>`;
1366
- return returnHTML;
1367
- },
1368
- divCreate: {
1369
- class: `d-flex flex-column p-3 my-2 border rounded-3`,
1370
- style: `gap:18px;background:white;`,
1438
+ </div>
1439
+ `;
1440
+ })()}`;
1441
+ },
1442
+ divCreate: {
1443
+ class: 'd-flex flex-column',
1444
+ style: 'gap: 6px; align-items: flex-start; padding: 12px 0;',
1445
+ },
1446
+ onCreate: () => {
1447
+ gvc.addMtScript(
1448
+ [{ src: 'https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js' }],
1449
+ () => {
1450
+ const interval = setInterval(() => {
1451
+ const Sortable = (window as any).Sortable;
1452
+ if (!Sortable) return;
1453
+
1454
+ clearInterval(interval);
1455
+
1456
+ try {
1457
+ const dragId = `sortable-list-${specIndex}`;
1458
+ const dragEl = document.getElementById(dragId);
1459
+
1460
+ if (!dragEl) {
1461
+ console.warn(`Element with id '${dragId}' not found.`);
1462
+ return;
1463
+ }
1464
+
1465
+ Sortable.create(dragEl, {
1466
+ group: { name: dragId, pull: false, put: false },
1467
+ animation: 150,
1468
+ onEnd(evt: any) {
1469
+ swapArray(postMD.specs[specIndex].option, evt.oldIndex, evt.newIndex);
1470
+ },
1471
+ });
1472
+ } catch (e) {
1473
+ console.error('SortableJS initialization error:', e);
1474
+ }
1475
+ }, 100);
1371
1476
  },
1372
- });
1373
- } else {
1374
- return html`
1477
+ () => console.error('Failed to load SortableJS')
1478
+ );
1479
+ },
1480
+ });
1481
+ }
1482
+ temp = JSON.parse(JSON.stringify(dd));
1483
+ if (sel_lan() !== (window.parent as any).store_info.language_setting.def) {
1484
+ return obj.gvc.bindView({
1485
+ bind: 'spec_text_show',
1486
+ dataList: [
1487
+ {
1488
+ obj: createPage,
1489
+ key: 'page',
1490
+ },
1491
+ ],
1492
+ view: () => {
1493
+ let returnHTML = '';
1494
+ let specs_in_line: string[] = [];
1495
+ temp.option = temp.option ?? [];
1496
+ specs_in_line.push(
1497
+ html` <div class="d-flex flex-column w-100">
1498
+ <div class="d-flex flex-column" style="gap:10px;">
1499
+ <div class="fw-500">規格種類 - ${temp.title}</div>
1500
+ <input
1501
+ class="form-control w-100"
1502
+ placeholder="${temp.title}"
1503
+ style="width:100px;height: 35px;"
1504
+ value="${(temp.language_title as any)[vm.language] || ''}"
1505
+ onchange="${gvc.event((e, event) => {
1506
+ (temp.language_title as any)[vm.language] = e.value;
1507
+ })}"
1508
+ />
1509
+ </div>
1510
+ <div class="d-flex flex-column w-100" style="gap:5px;">
1511
+ ${temp.option
1512
+ .map((d: any, index: number) => {
1513
+ d.language_title = d.language_title ?? ({} as any);
1514
+ return html` <div class="d-flex flex-column mt-2" style="gap:10px;">
1515
+ <div class="fw-500">選項${index + 1} - ${d.title}</div>
1516
+ <input
1517
+ class="form-control w-100"
1518
+ placeholder="${d.title}"
1519
+ style="width:100px;height: 35px;"
1520
+ value="${(d.language_title as any)[vm.language] || ''}"
1521
+ onchange="${gvc.event((e, event) => {
1522
+ (d.language_title as any)[vm.language] = e.value;
1523
+ })}"
1524
+ />
1525
+ </div>`;
1526
+ })
1527
+ .join('<div class="mx-1"></div>')}
1528
+ </div>
1529
+ </div>`
1530
+ );
1531
+ returnHTML += specs_in_line.join(`<div class="w-100 border-top"></div>`);
1532
+ returnHTML += html` <div
1533
+ class="d-flex w-100 justify-content-end align-items-center w-100 bg-white"
1534
+ style="gap:14px; margin-top: 12px;"
1535
+ >
1536
+ ${BgWidget.cancel(
1537
+ obj.gvc.event(() => {
1538
+ editIndex = -1;
1539
+ gvc.notifyDataChange(vm.id);
1540
+ })
1541
+ )}
1542
+ ${BgWidget.save(
1543
+ obj.gvc.event(() => {
1544
+ postMD.specs[specIndex] = temp;
1545
+ ShoppingSettingBasic.updateVariants(
1546
+ gvc,
1547
+ postMD,
1548
+ shipment_config,
1549
+ variantsViewID,
1550
+ obj
1551
+ );
1552
+ gvc.notifyDataChange(vm.id);
1553
+ }),
1554
+ '完成'
1555
+ )}
1556
+ </div>`;
1557
+ return returnHTML;
1558
+ },
1559
+ divCreate: {
1560
+ class: `d-flex flex-column p-3 my-2 border rounded-3`,
1561
+ style: `gap:18px;background:white;`,
1562
+ },
1563
+ });
1564
+ } else {
1565
+ return html`
1566
+ <div
1567
+ style="background-color:white !important;display: flex;padding: 20px;flex-direction: column;align-items: flex-end;gap: 24px;align-self: stretch;border-radius: 10px;border: 1px solid #DDD;"
1568
+ >
1569
+ <div
1570
+ style="display: flex;flex-direction: column;align-items: flex-end;gap: 18px;align-self: stretch;background-color:white !important;"
1571
+ >
1375
1572
  <div
1376
- style="background-color:white !important;display: flex;padding: 20px;flex-direction: column;align-items: flex-end;gap: 24px;align-self: stretch;border-radius: 10px;border: 1px solid #DDD;"
1573
+ style="width:100%;display: flex;flex-direction: column;align-items: flex-end;gap: 18px;background-color:white !important;"
1377
1574
  >
1378
- <div
1379
- style="display: flex;flex-direction: column;align-items: flex-end;gap: 18px;align-self: stretch;background-color:white !important;"
1380
- >
1381
- <div
1382
- style="width:100%;display: flex;flex-direction: column;align-items: flex-end;gap: 18px;background-color:white !important;"
1383
- >
1384
- ${ShoppingProductSetting.specInput(gvc, temp, {
1385
- cancel: () => {
1386
- editSpectPage[specIndex].type = 'show';
1387
- editIndex = -1;
1388
- gvc.notifyDataChange(specid);
1389
- },
1390
- save: () => {
1391
- editSpectPage[specIndex].type = 'show';
1392
- postMD.specs[specIndex] = temp;
1393
- checkSpecSingle();
1394
- ShoppingSettingBasic.updateVariants(
1395
- gvc,
1396
- postMD,
1397
- shipment_config,
1398
- variantsViewID,
1399
- obj
1400
- );
1401
- gvc.notifyDataChange(vm.id);
1402
- },
1403
- })}
1404
- </div>
1405
- </div>
1575
+ ${ShoppingProductSetting.specInput(gvc, temp, {
1576
+ cancel: () => {
1577
+ editSpectPage[specIndex].type = 'show';
1578
+ editIndex = -1;
1579
+ gvc.notifyDataChange(specid);
1580
+ },
1581
+ save: () => {
1582
+ editSpectPage[specIndex].type = 'show';
1583
+ postMD.specs[specIndex] = temp;
1584
+ checkSpecSingle();
1585
+ ShoppingSettingBasic.updateVariants(
1586
+ gvc,
1587
+ postMD,
1588
+ shipment_config,
1589
+ variantsViewID,
1590
+ obj
1591
+ );
1592
+ gvc.notifyDataChange(vm.id);
1593
+ },
1594
+ })}
1406
1595
  </div>
1407
- `;
1408
- }
1409
- },
1410
- divCreate: { class: `w-100 position-relative` },
1411
- }),
1412
- innerHtml: (gvc: GVC) => {
1413
- return '';
1414
- },
1415
- editTitle: `編輯規格`,
1416
- draggable: editSpectPage[specIndex].type === 'show',
1417
- };
1418
- });
1419
- },
1420
- })}
1421
- `;
1422
- }
1596
+ </div>
1597
+ </div>
1598
+ `;
1599
+ }
1600
+ },
1601
+ divCreate: { class: `w-100 position-relative` },
1602
+ }),
1603
+ innerHtml: (gvc: GVC) => {
1604
+ return '';
1605
+ },
1606
+ editTitle: `編輯規格`,
1607
+ draggable: editSpectPage[specIndex].type === 'show',
1608
+ };
1609
+ });
1610
+ },
1611
+ })}
1612
+ `;
1613
+ }
1423
1614
 
1424
- if (createPage.page == 'edit' && editIndex === -1) {
1425
- let temp: any = {
1426
- title: '',
1427
- option: [],
1428
- };
1429
- returnHTML += html`
1430
- ${BgWidget.mainCard(html`
1431
- <div
1432
- style="display: flex;flex-direction: column;align-items: flex-end;gap: 18px;align-self: stretch;"
1433
- >
1434
- <div style="width:100%;display: flex;flex-direction: column;align-items: flex-end;gap: 18px;">
1435
- ${ShoppingProductSetting.specInput(gvc, temp, {
1436
- cancel: () => {
1437
- createPage.page = 'add';
1438
- },
1439
- save: () => {
1440
- postMD.specs.push(temp);
1441
- createPage.page = 'add';
1442
- checkSpecSingle();
1443
- ShoppingSettingBasic.updateVariants(gvc, postMD, shipment_config, variantsViewID, obj);
1444
- gvc.notifyDataChange([vm.id]);
1445
- },
1446
- })}
1447
- </div>
1448
- </div>
1449
- `)}
1450
- `;
1451
- } else if (sel_lan() !== (window.parent as any).store_info.language_setting.def) {
1452
- returnHTML += `<div class="w-100 d-flex align-items-center justify-content-center">${BgWidget.grayNote('若要新增規格請切換至預設語言新增')}</div>`;
1453
- } else {
1454
- returnHTML += html`
1455
- <div
1456
- style="width:100%;display:flex;align-items: center;justify-content: center;color: #36B;gap:6px;cursor: pointer;"
1457
- onclick="${gvc.event(() => {
1458
- editIndex = -1;
1459
- createPage.page = 'edit';
1460
- })}"
1461
- >
1462
- 新增規格
1463
- <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none">
1464
- <path
1465
- d="M1.5 7.23926H12.5"
1466
- stroke="#3366BB"
1467
- stroke-width="2"
1468
- stroke-linecap="round"
1469
- stroke-linejoin="round"
1470
- />
1471
- <path
1472
- d="M6.76172 1.5L6.76172 12.5"
1473
- stroke="#3366BB"
1474
- stroke-width="2"
1475
- stroke-linecap="round"
1476
- stroke-linejoin="round"
1477
- />
1478
- </svg>
1615
+ if (createPage.page == 'edit' && editIndex === -1) {
1616
+ let temp: any = {
1617
+ title: '',
1618
+ option: [],
1619
+ };
1620
+ returnHTML += html`
1621
+ ${BgWidget.mainCard(html`
1622
+ <div
1623
+ style="display: flex;flex-direction: column;align-items: flex-end;gap: 18px;align-self: stretch;"
1624
+ >
1625
+ <div style="width:100%;display: flex;flex-direction: column;align-items: flex-end;gap: 18px;">
1626
+ ${ShoppingProductSetting.specInput(gvc, temp, {
1627
+ cancel: () => {
1628
+ createPage.page = 'add';
1629
+ },
1630
+ save: () => {
1631
+ postMD.specs.push(temp);
1632
+ createPage.page = 'add';
1633
+ checkSpecSingle();
1634
+ ShoppingSettingBasic.updateVariants(gvc, postMD, shipment_config, variantsViewID, obj);
1635
+ gvc.notifyDataChange([vm.id]);
1636
+ },
1637
+ })}
1479
1638
  </div>
1480
- `;
1481
- }
1639
+ </div>
1640
+ `)}
1641
+ `;
1642
+ } else if (sel_lan() !== (window.parent as any).store_info.language_setting.def) {
1643
+ returnHTML += `<div class="w-100 d-flex align-items-center justify-content-center">${BgWidget.grayNote('若要新增規格請切換至預設語言新增')}</div>`;
1644
+ } else {
1645
+ returnHTML += html`
1646
+ <div
1647
+ style="width:100%;display:flex;align-items: center;justify-content: center;color: #36B;gap:6px;cursor: pointer;"
1648
+ onclick="${gvc.event(() => {
1649
+ editIndex = -1;
1650
+ createPage.page = 'edit';
1651
+ })}"
1652
+ >
1653
+ 新增規格
1654
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none">
1655
+ <path
1656
+ d="M1.5 7.23926H12.5"
1657
+ stroke="#3366BB"
1658
+ stroke-width="2"
1659
+ stroke-linecap="round"
1660
+ stroke-linejoin="round"
1661
+ />
1662
+ <path
1663
+ d="M6.76172 1.5L6.76172 12.5"
1664
+ stroke="#3366BB"
1665
+ stroke-width="2"
1666
+ stroke-linecap="round"
1667
+ stroke-linejoin="round"
1668
+ />
1669
+ </svg>
1670
+ </div>
1671
+ `;
1672
+ }
1482
1673
 
1483
- return returnHTML;
1484
- },
1485
- divCreate: {
1486
- class: `d-flex flex-column`,
1487
- style: `gap:18px;`,
1488
- },
1489
- };
1490
- })
1491
- ),
1492
- postMD.product_category === 'kitchen'
1493
- ? (() => {
1494
- let map_: string[] = [];
1495
- postMD.shipment_type = postMD.shipment_type ?? 'volume';
1674
+ return returnHTML;
1675
+ },
1676
+ divCreate: {
1677
+ class: `d-flex flex-column`,
1678
+ style: `gap:18px;`,
1679
+ },
1680
+ };
1681
+ })
1682
+ );
1683
+ }
1496
1684
 
1497
- map_.push(
1498
- BgWidget.mainCard(
1499
- gvc.bindView(() => {
1500
- const vm = {
1501
- id: gvc.glitter.getUUID(),
1502
- };
1503
- return {
1504
- bind: vm.id,
1505
- view: () => {
1506
- return html` <div style="font-weight: 700;margin-bottom: 6px;">運費計算</div>
1507
- ${BgWidget.multiCheckboxContainer(
1508
- gvc,
1509
- [
1510
- {
1511
- key: 'volume',
1512
- name: '依材積計算',
1513
- customerClass: 'guide5-6',
1514
- },
1515
- {
1516
- key: 'weight',
1517
- name: '依重量計算',
1518
- },
1519
- {
1520
- key: 'none',
1521
- name: '不計算運費',
1522
- },
1523
- ],
1524
- [postMD.shipment_type!!],
1525
- data => {
1526
- postMD.shipment_type = data[0];
1527
- gvc.notifyDataChange(vm.id);
1528
- },
1529
- { single: true }
1530
- )}`;
1531
- },
1532
- divCreate: {
1533
- class: `d-flex flex-column `,
1534
- style: `gap:12px;`,
1535
- },
1536
- };
1537
- })
1538
- )
1539
- );
1540
- map_.push(
1541
- BgWidget.mainCard(html`
1542
- <div class="d-flex flex-column" style="gap:18px;">
1543
- <div class="d-flex flex-column guide5-7" style="gap:18px;">
1544
- <div style="font-weight: 700;"></div>
1545
- <div class="row">
1546
- ${[
1685
+ function drawKitchenSingleSpecDetail() {
1686
+ return postMD.product_category === 'kitchen'
1687
+ ? (() => {
1688
+ let map_: string[] = [];
1689
+ postMD.shipment_type = postMD.shipment_type ?? 'volume';
1690
+
1691
+ map_.push(
1692
+ BgWidget.mainCard(
1693
+ gvc.bindView(() => {
1694
+ const vm = {
1695
+ id: gvc.glitter.getUUID(),
1696
+ };
1697
+ return {
1698
+ bind: vm.id,
1699
+ view: () => {
1700
+ return html` <!-- 繪製餐飲組合的單規格詳細區塊-->
1701
+ <div style="font-weight: 700;margin-bottom: 6px;">運費計算</div>
1702
+ ${BgWidget.multiCheckboxContainer(
1703
+ gvc,
1704
+ [
1547
1705
  {
1548
- title: '長度',
1549
- value: 'v_length',
1550
- unit: '公分',
1706
+ key: 'volume',
1707
+ name: '依材積計算',
1708
+ customerClass: 'guide5-6',
1551
1709
  },
1552
1710
  {
1553
- title: '寬度',
1554
- value: 'v_width',
1555
- unit: '公分',
1711
+ key: 'weight',
1712
+ name: '依重量計算',
1556
1713
  },
1557
1714
  {
1558
- title: '高度',
1559
- value: 'v_height',
1560
- unit: '公分',
1715
+ key: 'none',
1716
+ name: '不計算運費',
1561
1717
  },
1562
- ]
1563
- .map(dd => {
1564
- (postMD as any)[dd.value] = (postMD as any)[dd.value] || '0';
1565
- return html` <div
1566
- style="display: flex;justify-content: center;align-items: center;gap: 10px;position: relative;"
1567
- class=" col-12 col-sm-4 mb-2"
1568
- >
1569
- <div style="white-space: nowrap;">${dd.title}</div>
1570
- <input
1571
- class="ps-3"
1572
- style="border-radius: 10px;border: 1px solid #DDD;height: 40px;width: calc(100% - 50px);"
1573
- type="number"
1574
- onchange="${gvc.event(e => {
1575
- (postMD as any)[dd.value] = e.value;
1576
- })}"
1577
- value="${(postMD as any)[dd.value]}"
1578
- />
1579
- <div style="color: #8D8D8D;position: absolute;right: 25px;top: 7px;">${dd.unit}</div>
1580
- </div>`;
1581
- })
1582
- .join('')}
1583
- </div>
1584
- </div>
1585
- <div style="font-weight: 700;">商品重量</div>
1586
- <div class="w-100 row m-0" style="color:#393939;">
1587
- <input
1588
- class="col-6"
1589
- style="display: flex;height: 40px;padding: 10px 18px;align-items: center;gap: 10px;border-radius: 10px;border: 1px solid #DDD;"
1590
- placeholder="請輸入商品重量"
1591
- value="${(postMD as any)['weight'] || 0}"
1592
- onchange="${gvc.event(e => {
1593
- (postMD as any)['weight'] = e.value;
1594
- })}"
1595
- />
1596
- <div class="col-6" style="display: flex;align-items: center;gap: 10px;">
1597
- <div style="white-space: nowrap;">單位</div>
1598
- <select
1599
- class="form-select d-flex align-items-center flex-fill"
1600
- style="border-radius: 10px;border: 1px solid #DDD;padding-left: 18px;"
1718
+ ],
1719
+ [postMD.shipment_type!!],
1720
+ data => {
1721
+ postMD.shipment_type = data[0];
1722
+ gvc.notifyDataChange(vm.id);
1723
+ },
1724
+ { single: true }
1725
+ )}`;
1726
+ },
1727
+ divCreate: {
1728
+ class: `d-flex flex-column `,
1729
+ style: `gap:12px;`,
1730
+ },
1731
+ };
1732
+ })
1733
+ )
1734
+ );
1735
+ map_.push(
1736
+ BgWidget.mainCard(html`
1737
+ <div class="d-flex flex-column" style="gap:18px;">
1738
+ <div class="d-flex flex-column guide5-7" style="gap:18px;">
1739
+ <div style="font-weight: 700;"></div>
1740
+ <div class="row">
1741
+ ${[
1742
+ {
1743
+ title: '長度',
1744
+ value: 'v_length',
1745
+ unit: '公分',
1746
+ },
1747
+ {
1748
+ title: '寬度',
1749
+ value: 'v_width',
1750
+ unit: '公分',
1751
+ },
1752
+ {
1753
+ title: '高度',
1754
+ value: 'v_height',
1755
+ unit: '公分',
1756
+ },
1757
+ ]
1758
+ .map(dd => {
1759
+ (postMD as any)[dd.value] = (postMD as any)[dd.value] || '0';
1760
+ return html` <div
1761
+ style="display: flex;justify-content: center;align-items: center;gap: 10px;position: relative;"
1762
+ class=" col-12 col-sm-4 mb-2"
1601
1763
  >
1602
- <option value="kg">公斤</option>
1603
- </select>
1604
- </div>
1605
- </div>
1764
+ <div style="white-space: nowrap;">${dd.title}</div>
1765
+ <input
1766
+ class="ps-3"
1767
+ style="border-radius: 10px;border: 1px solid #DDD;height: 40px;width: calc(100% - 50px);"
1768
+ type="number"
1769
+ onchange="${gvc.event(e => {
1770
+ (postMD as any)[dd.value] = e.value;
1771
+ })}"
1772
+ value="${(postMD as any)[dd.value]}"
1773
+ />
1774
+ <div style="color: #8D8D8D;position: absolute;right: 25px;top: 7px;">${dd.unit}</div>
1775
+ </div>`;
1776
+ })
1777
+ .join('')}
1606
1778
  </div>
1607
- `)
1608
- );
1609
- if (postMD.specs.length) {
1610
- map_.push(
1611
- BgWidget.mainCard(
1612
- [
1613
- html`
1614
- <div
1615
- class="d-flex flex-column"
1616
- style="font-size: 16px;font-weight: 700;color:#393939;${(postMD as any).shopee_id
1617
- ? ''
1618
- : `margin-bottom: 10px;`}"
1619
- >
1620
- 組合費用
1621
- ${BgWidget.grayNote('購買金額為用戶選擇的選項價格去進行加總,如未輸入庫存數量則不追蹤庫存')}
1622
- </div>
1623
- `,
1624
- obj.gvc.bindView(() => {
1625
- const vm = {
1626
- id: obj.gvc.glitter.getUUID(),
1627
- };
1628
- return {
1629
- bind: vm.id,
1630
- view: () => {
1631
- return (
1632
- html`
1633
- <div class="w-100 d-flex align-items-center border-bottom py-2 border-top">
1634
- <div class="fw-500" style="flex:1;">名稱</div>
1635
- <div class="fw-500" style="flex:1;">價格</div>
1636
- <div class="fw-500" style="flex:1;">庫存</div>
1637
- </div>
1638
- ` +
1639
- postMD.specs
1640
- .map(dd => {
1641
- return dd.option
1642
- .map((d1: any) => {
1643
- d1.price = d1.price ?? 0;
1644
- return html`<div class="w-100 d-flex align-items-center py-2">
1645
- <div class="fw-500" style="flex:1;">${dd.title} / ${d1.title}</div>
1646
- <div class="fw-50 pe-3" style="flex:1;">
1647
- ${BgWidget.editeInput({
1648
- gvc: gvc,
1649
- title: '',
1650
- default: `${d1.price}`,
1651
- callback: text => {
1652
- d1.price = parseInt(text, 10);
1653
- ShoppingSettingBasic.updateVariants(
1654
- gvc,
1655
- postMD,
1656
- shipment_config,
1657
- variantsViewID,
1658
- obj
1659
- );
1660
- },
1661
- placeHolder: '價格',
1662
- type: 'number',
1663
- })}
1664
- </div>
1665
- <div class="fw-50" style="flex:1;">
1666
- ${BgWidget.editeInput({
1667
- gvc: gvc,
1668
- title: '',
1669
- default: `${d1.stock}`,
1670
- callback: text => {
1671
- d1.stock = text;
1672
- },
1673
- placeHolder: '不追蹤庫存',
1674
- type: 'number',
1675
- })}
1676
- </div>
1677
- </div>`;
1678
- })
1679
- .join('');
1779
+ </div>
1780
+ <div style="font-weight: 700;">商品重量</div>
1781
+ <div class="w-100 row m-0" style="color:#393939;">
1782
+ <input
1783
+ class="col-6"
1784
+ style="display: flex;height: 40px;padding: 10px 18px;align-items: center;gap: 10px;border-radius: 10px;border: 1px solid #DDD;"
1785
+ placeholder="請輸入商品重量"
1786
+ value="${(postMD as any)['weight'] || 0}"
1787
+ onchange="${gvc.event(e => {
1788
+ (postMD as any)['weight'] = e.value;
1789
+ })}"
1790
+ />
1791
+ <div class="col-6" style="display: flex;align-items: center;gap: 10px;">
1792
+ <div style="white-space: nowrap;">單位</div>
1793
+ <select
1794
+ class="form-select d-flex align-items-center flex-fill"
1795
+ style="border-radius: 10px;border: 1px solid #DDD;padding-left: 18px;"
1796
+ >
1797
+ <option value="kg">公斤</option>
1798
+ </select>
1799
+ </div>
1800
+ </div>
1801
+ </div>
1802
+ `)
1803
+ );
1804
+ if (postMD.specs.length) {
1805
+ map_.push(
1806
+ BgWidget.mainCard(
1807
+ [
1808
+ html`
1809
+ <div
1810
+ class="d-flex flex-column"
1811
+ style="font-size: 16px;font-weight: 700;color:#393939;${(postMD as any).shopee_id
1812
+ ? ''
1813
+ : `margin-bottom: 10px;`}"
1814
+ >
1815
+ 組合費用
1816
+ ${BgWidget.grayNote('購買金額為用戶選擇的選項價格去進行加總,如未輸入庫存數量則不追蹤庫存')}
1817
+ </div>
1818
+ `,
1819
+ obj.gvc.bindView(() => {
1820
+ const vm = {
1821
+ id: obj.gvc.glitter.getUUID(),
1822
+ };
1823
+ return {
1824
+ bind: vm.id,
1825
+ view: () => {
1826
+ return (
1827
+ html`
1828
+ <div class="w-100 d-flex align-items-center border-bottom py-2 border-top">
1829
+ <div class="fw-500" style="flex:1;">名稱</div>
1830
+ <div class="fw-500" style="flex:1;">價格</div>
1831
+ <div class="fw-500" style="flex:1;">庫存</div>
1832
+ </div>
1833
+ ` +
1834
+ postMD.specs
1835
+ .map(dd => {
1836
+ return dd.option
1837
+ .map((d1: any) => {
1838
+ d1.price = d1.price ?? 0;
1839
+ return html` <div class="w-100 d-flex align-items-center py-2">
1840
+ <div class="fw-500" style="flex:1;">${dd.title} / ${d1.title}</div>
1841
+ <div class="fw-50 pe-3" style="flex:1;">
1842
+ ${BgWidget.editeInput({
1843
+ gvc: gvc,
1844
+ title: '',
1845
+ default: `${d1.price}`,
1846
+ callback: text => {
1847
+ d1.price = parseInt(text, 10);
1848
+ ShoppingSettingBasic.updateVariants(
1849
+ gvc,
1850
+ postMD,
1851
+ shipment_config,
1852
+ variantsViewID,
1853
+ obj
1854
+ );
1855
+ },
1856
+ placeHolder: '價格',
1857
+ type: 'number',
1858
+ })}
1859
+ </div>
1860
+ <div class="fw-50" style="flex:1;">
1861
+ ${BgWidget.editeInput({
1862
+ gvc: gvc,
1863
+ title: '',
1864
+ default: `${d1.stock}`,
1865
+ callback: text => {
1866
+ d1.stock = text;
1867
+ },
1868
+ placeHolder: '不追蹤庫存',
1869
+ type: 'number',
1870
+ })}
1871
+ </div>
1872
+ </div>`;
1680
1873
  })
1681
- .join('')
1682
- );
1683
- },
1684
- };
1685
- }),
1686
- ].join('')
1687
- )
1688
- );
1689
- } else {
1690
- map_.push(
1691
- BgWidget.mainCard(
1692
- obj.gvc.bindView(() => {
1693
- const vm = {
1694
- id: obj.gvc.glitter.getUUID(),
1695
- };
1696
- return {
1697
- bind: vm.id,
1698
- view: () => {
1699
- (postMD as any).price = (postMD as any).price ?? 0;
1700
- (postMD as any).stock = (postMD as any).stock ?? 0;
1701
- return [
1702
- html`
1703
- <div
1704
- class="d-flex flex-column"
1705
- style="font-size: 16px;font-weight: 700;color:#393939;${(postMD as any).shopee_id
1706
- ? ''
1707
- : `margin-bottom: 10px;`}"
1708
- >
1709
- 組合費用 ${BgWidget.grayNote('如未輸入庫存數量則不追蹤庫存')}
1710
- </div>
1711
- `,
1712
- html`
1713
- <div class="w-100 d-flex align-items-center border-bottom py-2 border-top">
1714
- <div class="fw-500" style="flex:1;">價格</div>
1715
- <div class="fw-500" style="flex:1;">庫存</div>
1716
- </div>
1717
- `,
1718
- html`<div class="w-100 d-flex align-items-center py-2">
1719
- <div class="fw-50 pe-3" style="flex:1;">
1720
- ${BgWidget.editeInput({
1721
- gvc: gvc,
1722
- title: '',
1723
- default: `${(postMD as any).price}`,
1724
- callback: text => {
1725
- (postMD as any).price = parseInt(text, 10);
1726
- ShoppingSettingBasic.updateVariants(
1727
- gvc,
1728
- postMD,
1729
- shipment_config,
1730
- variantsViewID,
1731
- obj
1732
- );
1733
- },
1734
- placeHolder: '價格',
1735
- type: 'number',
1736
- })}
1737
- </div>
1738
- <div class="fw-50" style="flex:1;">
1739
- ${BgWidget.editeInput({
1740
- gvc: gvc,
1741
- title: '',
1742
- default: `${(postMD as any).stock}`,
1743
- callback: text => {
1744
- (postMD as any).stock = text;
1745
- },
1746
- placeHolder: '不追蹤庫存',
1747
- type: 'number',
1748
- })}
1749
- </div>
1750
- </div>`,
1751
- ].join('');
1752
- },
1753
- };
1754
- })
1755
- )
1756
- );
1757
- }
1758
- return map_.join(BgWidget.mbContainer(18));
1759
- })()
1760
- : '',
1874
+ .join('');
1875
+ })
1876
+ .join('')
1877
+ );
1878
+ },
1879
+ };
1880
+ }),
1881
+ ].join('')
1882
+ )
1883
+ );
1884
+ } else {
1885
+ map_.push(
1886
+ BgWidget.mainCard(
1887
+ obj.gvc.bindView(() => {
1888
+ const vm = {
1889
+ id: obj.gvc.glitter.getUUID(),
1890
+ };
1891
+ return {
1892
+ bind: vm.id,
1893
+ view: () => {
1894
+ (postMD as any).price = (postMD as any).price ?? 0;
1895
+ (postMD as any).stock = (postMD as any).stock ?? 0;
1896
+ return [
1897
+ html`
1898
+ <div
1899
+ class="d-flex flex-column"
1900
+ style="font-size: 16px;font-weight: 700;color:#393939;${(postMD as any).shopee_id
1901
+ ? ''
1902
+ : `margin-bottom: 10px;`}"
1903
+ >
1904
+ 組合費用 ${BgWidget.grayNote('如未輸入庫存數量則不追蹤庫存')}
1905
+ </div>
1906
+ `,
1907
+ html`
1908
+ <div class="w-100 d-flex align-items-center border-bottom py-2 border-top">
1909
+ <div class="fw-500" style="flex:1;">價格</div>
1910
+ <div class="fw-500" style="flex:1;">庫存</div>
1911
+ </div>
1912
+ `,
1913
+ html` <div class="w-100 d-flex align-items-center py-2">
1914
+ <div class="fw-50 pe-3" style="flex:1;">
1915
+ ${BgWidget.editeInput({
1916
+ gvc: gvc,
1917
+ title: '',
1918
+ default: `${(postMD as any).price}`,
1919
+ callback: text => {
1920
+ (postMD as any).price = parseInt(text, 10);
1921
+ ShoppingSettingBasic.updateVariants(
1922
+ gvc,
1923
+ postMD,
1924
+ shipment_config,
1925
+ variantsViewID,
1926
+ obj
1927
+ );
1928
+ },
1929
+ placeHolder: '價格',
1930
+ type: 'number',
1931
+ })}
1932
+ </div>
1933
+ <div class="fw-50" style="flex:1;">
1934
+ ${BgWidget.editeInput({
1935
+ gvc: gvc,
1936
+ title: '',
1937
+ default: `${(postMD as any).stock}`,
1938
+ callback: text => {
1939
+ (postMD as any).stock = text;
1940
+ },
1941
+ placeHolder: '不追蹤庫存',
1942
+ type: 'number',
1943
+ })}
1944
+ </div>
1945
+ </div>`,
1946
+ ].join('');
1947
+ },
1948
+ };
1949
+ })
1950
+ )
1951
+ );
1952
+ }
1953
+ return map_.join(BgWidget.mbContainer(18));
1954
+ })()
1955
+ : '';
1956
+ }
1957
+
1958
+ function drawReservationSettings(){
1959
+ function drawTitle(title: string , subTitle: string , inputKey: string){
1960
+ return html`
1961
+ <div class="d-flex flex-column w-100" >
1962
+ <div class="tx_700 ">${title}</div>
1963
+ ${subTitle
1964
+ ? html`<div class="tx_gray_14" style="margin: 4px 0 8px 0;">${subTitle}</div>`
1965
+ : html`<div style="height: 18px;"></div>`}
1966
+ <div class="d-flex" style="gap: 18px;">
1967
+ <div class="d-flex flex-fill align-items-center" style="height: 40px;padding: 0 18px;border-radius: 10px;border: 1px solid #DDD;">
1968
+ <input class="border-0 h-100 flex-fill" >
1969
+ <div class="tx_gray_14 ms-auto">小時</div>
1970
+ </div>
1971
+ <div class="d-flex flex-fill align-items-center" style="height: 40px;padding: 0 18px;border-radius: 10px;border: 1px solid #DDD;">
1972
+ <input class="border-0 h-100 flex-fill" >
1973
+ <div class="tx_gray_14 ms-auto">分鐘</div>
1974
+ </div>
1975
+ </div>
1976
+ </div>
1977
+ `
1978
+ }
1979
+ return BgWidget.mainCard(html`
1980
+ ${drawTitle("預設服務時長" , "" , "defaultServiceDuration")}
1981
+ <div class="tx_700">
1982
+ 預設服務時長
1983
+ </div>
1984
+ `)
1985
+ }
1986
+
1987
+ ShoppingSettingBasic.updateVariants(gvc, postMD, shipment_config, variantsViewID, obj);
1988
+
1989
+ const cat_title = (() => {
1990
+ switch (postMD.product_category) {
1991
+ case 'commodity':
1992
+ return '商品';
1993
+ case 'course':
1994
+ return '課程';
1995
+ case 'reserve':
1996
+ return '預約';
1997
+ case 'kitchen':
1998
+ return '餐飲組合';
1999
+ default:
2000
+ return '商品';
2001
+ }
2002
+ })();
2003
+ return BgWidget.container1x2(
2004
+ {
2005
+ html: [
2006
+ BgWidget.mainCard(html`
2007
+ <div class="d-flex flex-column guide5-4">
2008
+ <div style="font-weight: 700;">
2009
+ ${cat_title}名稱 ${BgWidget.requiredStar()}
2010
+ ${BgWidget.languageInsignia(vm.language, 'margin-left:5px;')}
2011
+ </div>
2012
+ ${BgWidget.editeInput({
2013
+ gvc: gvc,
2014
+ title: '',
2015
+ type: 'text',
2016
+ default: language_data.title ?? '',
2017
+ placeHolder: `請輸入${cat_title}名稱`,
2018
+ callback: text => {
2019
+ if (language_data.seo.domain === language_data.title) {
2020
+ language_data.seo.domain = text;
2021
+ }
2022
+ language_data.title = text;
2023
+ gvc.notifyDataChange('seo');
2024
+ },
2025
+ })}
2026
+ </div>
2027
+ `),
2028
+ drawShortDescriptionRichText(),
2029
+ drawDetailDescriptionRichText(),
2030
+ drawProductImageBlock(),
2031
+ drawReserveLocations(),
2032
+ drawReservationSettings(),
2033
+ drawIndividualStoreProductConfigPanel(),
2034
+ drawSpecEditView(),
2035
+ drawProductSpecList(),
2036
+ drawKitchenSingleSpecDetail(),
1761
2037
  postMD.product_category !== 'kitchen' && postMD.specs.length
1762
2038
  ? (() => {
1763
2039
  return BgWidget.mainCard(
@@ -3181,13 +3457,13 @@ export class ShoppingSettingBasic {
3181
3457
  },
3182
3458
  });
3183
3459
  })
3184
- .join(html`<div class="border-bottom my-1 w-100"></div>`)
3460
+ .join(html` <div class="border-bottom my-1 w-100"></div>`)
3185
3461
  );
3186
3462
  }
3187
3463
 
3188
3464
  return viewList.join('');
3189
3465
  })
3190
- .join(html`<div class="border-bottom mx-n2 my-1 w-100"></div>`);
3466
+ .join(html` <div class="border-bottom mx-n2 my-1 w-100"></div>`);
3191
3467
  },
3192
3468
  };
3193
3469
  }),
@@ -3222,8 +3498,8 @@ export class ShoppingSettingBasic {
3222
3498
  搜尋引擎列表 ${BgWidget.languageInsignia(sel_lan(), 'margin-left:5px;')}
3223
3499
  </div>
3224
3500
  ${[
3225
- html`<div class="tx_normal fw-normal mb-2">${cat_title}網址 ${BgWidget.requiredStar()}</div> `,
3226
- html`<div
3501
+ html` <div class="tx_normal fw-normal mb-2">${cat_title}網址 ${BgWidget.requiredStar()}</div> `,
3502
+ html` <div
3227
3503
  style="justify-content: flex-start; align-items: center; display: inline-flex;border:1px solid #EAEAEA;border-radius: 10px;overflow: hidden; ${document
3228
3504
  .body.clientWidth > 768
3229
3505
  ? 'gap: 18px; '