ts-glitter 14.3.9 → 14.4.2

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 (51) hide show
  1. package/lowcode/Entry.js +1 -1
  2. package/lowcode/Entry.ts +1 -1
  3. package/lowcode/backend-manager/bg-product.js +22 -20
  4. package/lowcode/backend-manager/bg-product.ts +85 -73
  5. package/lowcode/backend-manager/bg-recommend.js +31 -28
  6. package/lowcode/backend-manager/bg-recommend.ts +31 -28
  7. package/lowcode/cms-plugin/ai-message.ts +2 -1
  8. package/lowcode/cms-plugin/filter-options.js +6 -4
  9. package/lowcode/cms-plugin/filter-options.ts +8 -6
  10. package/lowcode/cms-plugin/module/product-excel.js +35 -14
  11. package/lowcode/cms-plugin/module/product-excel.ts +40 -15
  12. package/lowcode/cms-plugin/shopping-discount-setting.js +1 -1
  13. package/lowcode/cms-plugin/shopping-discount-setting.ts +5 -2
  14. package/lowcode/cms-plugin/shopping-invoice-manager.js +0 -1
  15. package/lowcode/cms-plugin/shopping-invoice-manager.ts +0 -1
  16. package/lowcode/cms-plugin/shopping-product-setting.js +265 -160
  17. package/lowcode/cms-plugin/shopping-product-setting.ts +295 -297
  18. package/lowcode/cms-plugin/shopping-product-stock.js +12 -16
  19. package/lowcode/cms-plugin/shopping-product-stock.ts +29 -35
  20. package/lowcode/glitter-base/route/shopping.js +25 -4
  21. package/lowcode/glitter-base/route/shopping.ts +52 -44
  22. package/lowcode/glitterBundle/html-component/widget.js +0 -3
  23. package/lowcode/glitterBundle/html-component/widget.ts +3 -3
  24. package/lowcode/public-components/blogs/blogs-01.js +138 -1
  25. package/lowcode/public-components/blogs/blogs-01.ts +142 -2
  26. package/lowcode/public-components/checkout/index.js +3 -2
  27. package/lowcode/public-components/checkout/index.ts +16 -3
  28. package/lowcode/public-components/product/product-detail.js +1 -0
  29. package/lowcode/public-components/product/product-detail.ts +1 -0
  30. package/lowcode/public-components/product/product-list.js +1 -0
  31. package/lowcode/public-components/product/product-list.ts +1 -0
  32. package/lowcode/public-components/user-manager/um-class.js +2 -2
  33. package/lowcode/public-components/user-manager/um-class.ts +2 -2
  34. package/lowcode/public-components/user-manager/um-rebate.js +18 -18
  35. package/lowcode/public-components/user-manager/um-rebate.ts +39 -38
  36. package/package.json +1 -1
  37. package/src/api-public/controllers/shop.js +18 -0
  38. package/src/api-public/controllers/shop.js.map +1 -1
  39. package/src/api-public/controllers/shop.ts +17 -1
  40. package/src/api-public/services/financial-service.d.ts +16 -0
  41. package/src/api-public/services/financial-service.js +70 -3
  42. package/src/api-public/services/financial-service.js.map +1 -1
  43. package/src/api-public/services/financial-service.ts +89 -4
  44. package/src/api-public/services/recommend.js +14 -0
  45. package/src/api-public/services/recommend.js.map +1 -1
  46. package/src/api-public/services/recommend.ts +15 -0
  47. package/src/api-public/services/shopping.d.ts +35 -0
  48. package/src/api-public/services/shopping.js +97 -9
  49. package/src/api-public/services/shopping.js.map +1 -1
  50. package/src/api-public/services/shopping.ts +136 -20
  51. package/src/services/template.js.map +1 -1
@@ -106,9 +106,7 @@ export class ShoppingProductSetting {
106
106
  product_type: type,
107
107
  });
108
108
  case 'list':
109
- window.parent.glitter.share.checkData = () => {
110
- return true;
111
- };
109
+ window.parent.glitter.share.checkData = () => true;
112
110
  vm.tableId = gvc.glitter.getUUID();
113
111
  vm.dataList = [];
114
112
  const vmlist = {
@@ -130,7 +128,10 @@ export class ShoppingProductSetting {
130
128
  type: 'multi_checkbox',
131
129
  name: '商品分類',
132
130
  data: vmlist.collections.map((item) => {
133
- return { key: `${item.key}`, name: item.value };
131
+ return {
132
+ key: `${item.key}`,
133
+ name: item.value,
134
+ };
134
135
  }),
135
136
  });
136
137
  }
@@ -309,13 +310,8 @@ export class ShoppingProductSetting {
309
310
  searchType: (_b = vm.queryType) !== null && _b !== void 0 ? _b : '',
310
311
  orderBy: (_c = vm.orderString) !== null && _c !== void 0 ? _c : '',
311
312
  status: (() => {
312
- if (vm.filter.status && vm.filter.status.length === 1) {
313
- switch (vm.filter.status[0]) {
314
- case 'active':
315
- return 'active';
316
- case 'draft':
317
- return 'draft';
318
- }
313
+ if (vm.filter.status && vm.filter.status.length > 0) {
314
+ return vm.filter.status.join(',');
319
315
  }
320
316
  return undefined;
321
317
  })(),
@@ -347,38 +343,50 @@ export class ShoppingProductSetting {
347
343
  let exportData = [];
348
344
  response.response.data.forEach((productData) => {
349
345
  const baseRowData = (index) => {
350
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6;
346
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5;
351
347
  return ({
352
348
  id: index === 0 ? productData.content.id || '' : '',
353
349
  name: index === 0 ? productData.content.title || '未命名商品' : '',
354
- status: index === 0 ? (((_a = productData.content) === null || _a === void 0 ? void 0 : _a.status) === 'active' ? '啟用' : '草稿') : '',
350
+ status: index === 0
351
+ ? (() => {
352
+ var _a;
353
+ switch ((_a = productData.content) === null || _a === void 0 ? void 0 : _a.status) {
354
+ case 'draft':
355
+ return '草稿';
356
+ case 'schedule':
357
+ return '期間限定';
358
+ default:
359
+ return '啟用';
360
+ }
361
+ })()
362
+ : '',
355
363
  category: index === 0 ? expo.checkString(productData.content.collection.join(' , ')) : '',
356
364
  productType: index === 0 ? expo.checkString(this.getProductTypeString(productData.content)) : '',
357
365
  img: index === 0 ? expo.checkString(productData.content.preview_image[0]) : '',
358
- SEO_domain: index === 0 ? expo.checkString((_c = (_b = productData.content) === null || _b === void 0 ? void 0 : _b.seo) === null || _c === void 0 ? void 0 : _c.domain) : '',
359
- SEO_title: index === 0 ? expo.checkString((_e = (_d = productData.content) === null || _d === void 0 ? void 0 : _d.seo) === null || _e === void 0 ? void 0 : _e.title) : '',
360
- SEO_desc: index === 0 ? expo.checkString((_g = (_f = productData.content) === null || _f === void 0 ? void 0 : _f.seo) === null || _g === void 0 ? void 0 : _g.content) : '',
361
- spec1: index === 0 ? expo.checkString((_j = (_h = productData.content) === null || _h === void 0 ? void 0 : _h.specs[0]) === null || _j === void 0 ? void 0 : _j.title) : '',
362
- spec1Value: expo.checkString((_k = productData.content.variants[index]) === null || _k === void 0 ? void 0 : _k.spec[0]),
363
- spec2: index === 0 ? expo.checkString((_m = (_l = productData.content) === null || _l === void 0 ? void 0 : _l.specs[1]) === null || _m === void 0 ? void 0 : _m.title) : '',
364
- spec2Value: expo.checkString((_o = productData.content.variants[index]) === null || _o === void 0 ? void 0 : _o.spec[1]),
365
- spec3: index === 0 ? expo.checkString((_q = (_p = productData.content) === null || _p === void 0 ? void 0 : _p.specs[2]) === null || _q === void 0 ? void 0 : _q.title) : '',
366
- spec3Value: expo.checkString((_r = productData.content.variants[index]) === null || _r === void 0 ? void 0 : _r.spec[2]),
367
- sku: expo.checkString((_s = productData.content.variants[index]) === null || _s === void 0 ? void 0 : _s.sku),
368
- cost: expo.checkNumber((_t = productData.content.variants[index]) === null || _t === void 0 ? void 0 : _t.cost),
369
- sale_price: expo.checkNumber((_u = productData.content.variants[index]) === null || _u === void 0 ? void 0 : _u.sale_price),
370
- compare_price: expo.checkNumber((_v = productData.content.variants[index]) === null || _v === void 0 ? void 0 : _v.compare_price),
371
- benefit: expo.checkNumber((_w = productData.content.variants[index]) === null || _w === void 0 ? void 0 : _w.profit),
372
- shipment_type: getShipmentType((_x = productData.content.variants[index]) === null || _x === void 0 ? void 0 : _x.shipment_type),
373
- length: expo.checkNumber(((_y = productData.content.variants[index]) === null || _y === void 0 ? void 0 : _y.v_length) || 0),
374
- width: expo.checkNumber(((_z = productData.content.variants[index]) === null || _z === void 0 ? void 0 : _z.v_width) || 0),
375
- height: expo.checkNumber(((_0 = productData.content.variants[index]) === null || _0 === void 0 ? void 0 : _0.v_height) || 0),
376
- weight: expo.checkNumber(((_1 = productData.content.variants[index]) === null || _1 === void 0 ? void 0 : _1.weight) || 0),
377
- weightUnit: expo.checkString(((_2 = productData.content.variants[index]) === null || _2 === void 0 ? void 0 : _2.weightUnit) || 'KG'),
378
- stockPolicy: ((_3 = productData.content.variants[index]) === null || _3 === void 0 ? void 0 : _3.show_understocking) === 'true' ? '追蹤' : '不追蹤',
379
- stock: expo.checkNumber((_4 = productData.content.variants[index]) === null || _4 === void 0 ? void 0 : _4.stock),
380
- save_stock: expo.checkNumber((_5 = productData.content.variants[index]) === null || _5 === void 0 ? void 0 : _5.save_stock),
381
- barcode: expo.checkString((_6 = productData.content.variants[index]) === null || _6 === void 0 ? void 0 : _6.barcode),
366
+ SEO_domain: index === 0 ? expo.checkString((_b = (_a = productData.content) === null || _a === void 0 ? void 0 : _a.seo) === null || _b === void 0 ? void 0 : _b.domain) : '',
367
+ SEO_title: index === 0 ? expo.checkString((_d = (_c = productData.content) === null || _c === void 0 ? void 0 : _c.seo) === null || _d === void 0 ? void 0 : _d.title) : '',
368
+ SEO_desc: index === 0 ? expo.checkString((_f = (_e = productData.content) === null || _e === void 0 ? void 0 : _e.seo) === null || _f === void 0 ? void 0 : _f.content) : '',
369
+ spec1: index === 0 ? expo.checkString((_h = (_g = productData.content) === null || _g === void 0 ? void 0 : _g.specs[0]) === null || _h === void 0 ? void 0 : _h.title) : '',
370
+ spec1Value: expo.checkString((_j = productData.content.variants[index]) === null || _j === void 0 ? void 0 : _j.spec[0]),
371
+ spec2: index === 0 ? expo.checkString((_l = (_k = productData.content) === null || _k === void 0 ? void 0 : _k.specs[1]) === null || _l === void 0 ? void 0 : _l.title) : '',
372
+ spec2Value: expo.checkString((_m = productData.content.variants[index]) === null || _m === void 0 ? void 0 : _m.spec[1]),
373
+ spec3: index === 0 ? expo.checkString((_p = (_o = productData.content) === null || _o === void 0 ? void 0 : _o.specs[2]) === null || _p === void 0 ? void 0 : _p.title) : '',
374
+ spec3Value: expo.checkString((_q = productData.content.variants[index]) === null || _q === void 0 ? void 0 : _q.spec[2]),
375
+ sku: expo.checkString((_r = productData.content.variants[index]) === null || _r === void 0 ? void 0 : _r.sku),
376
+ cost: expo.checkNumber((_s = productData.content.variants[index]) === null || _s === void 0 ? void 0 : _s.cost),
377
+ sale_price: expo.checkNumber((_t = productData.content.variants[index]) === null || _t === void 0 ? void 0 : _t.sale_price),
378
+ compare_price: expo.checkNumber((_u = productData.content.variants[index]) === null || _u === void 0 ? void 0 : _u.compare_price),
379
+ benefit: expo.checkNumber((_v = productData.content.variants[index]) === null || _v === void 0 ? void 0 : _v.profit),
380
+ shipment_type: getShipmentType((_w = productData.content.variants[index]) === null || _w === void 0 ? void 0 : _w.shipment_type),
381
+ length: expo.checkNumber(((_x = productData.content.variants[index]) === null || _x === void 0 ? void 0 : _x.v_length) || 0),
382
+ width: expo.checkNumber(((_y = productData.content.variants[index]) === null || _y === void 0 ? void 0 : _y.v_width) || 0),
383
+ height: expo.checkNumber(((_z = productData.content.variants[index]) === null || _z === void 0 ? void 0 : _z.v_height) || 0),
384
+ weight: expo.checkNumber(((_0 = productData.content.variants[index]) === null || _0 === void 0 ? void 0 : _0.weight) || 0),
385
+ weightUnit: expo.checkString(((_1 = productData.content.variants[index]) === null || _1 === void 0 ? void 0 : _1.weightUnit) || 'KG'),
386
+ stockPolicy: ((_2 = productData.content.variants[index]) === null || _2 === void 0 ? void 0 : _2.show_understocking) === 'true' ? '追蹤' : '不追蹤',
387
+ stock: expo.checkNumber((_3 = productData.content.variants[index]) === null || _3 === void 0 ? void 0 : _3.stock),
388
+ save_stock: expo.checkNumber((_4 = productData.content.variants[index]) === null || _4 === void 0 ? void 0 : _4.save_stock),
389
+ barcode: expo.checkString((_5 = productData.content.variants[index]) === null || _5 === void 0 ? void 0 : _5.barcode),
382
390
  });
383
391
  };
384
392
  const getShipmentType = (type) => {
@@ -484,13 +492,8 @@ export class ShoppingProductSetting {
484
492
  searchType: vm.queryType || undefined,
485
493
  orderBy: vm.orderString || undefined,
486
494
  status: (() => {
487
- if (vm.filter.status && vm.filter.status.length === 1) {
488
- switch (vm.filter.status[0]) {
489
- case 'active':
490
- return 'active';
491
- case 'draft':
492
- return 'draft';
493
- }
495
+ if (vm.filter.status && vm.filter.status.length > 0) {
496
+ return vm.filter.status.join(',');
494
497
  }
495
498
  return undefined;
496
499
  })(),
@@ -551,19 +554,14 @@ export class ShoppingProductSetting {
551
554
  return {
552
555
  bind: id,
553
556
  view: () => {
554
- BgWidget.switchTextButton(gvc, dd.content.status === 'active', { left: dd.content.status === 'active' ? '啟用' : '草稿' }, (bool) => {
555
- dd.content.status = bool ? 'active' : 'draft';
556
- ApiPost.put({
557
- postData: dd.content,
558
- token: window.parent.config.token,
559
- type: 'manager',
560
- }).then((res) => {
561
- res.result && gvc.notifyDataChange(id);
562
- });
563
- });
564
- return dd.content.status === 'active'
565
- ? BgWidget.successInsignia('啟用')
566
- : BgWidget.secondaryInsignia('草稿');
557
+ switch (dd.content.status) {
558
+ case 'draft':
559
+ return BgWidget.secondaryInsignia('草稿');
560
+ case 'schedule':
561
+ return BgWidget.notifyInsignia('期間限定');
562
+ default:
563
+ return BgWidget.successInsignia('啟用');
564
+ }
567
565
  },
568
566
  divCreate: {
569
567
  option: [
@@ -753,7 +751,7 @@ export class ShoppingProductSetting {
753
751
  orignData = data;
754
752
  }
755
753
  });
756
- function checkStore(next) {
754
+ function checkStore(next, cancel) {
757
755
  const dialog = new ShareDialog(gvc.glitter);
758
756
  if (JSON.stringify(orignData) !== JSON.stringify(variant)) {
759
757
  dialog.checkYesOrNot({
@@ -762,6 +760,10 @@ export class ShoppingProductSetting {
762
760
  if (response) {
763
761
  postMD.variants[index] = variant;
764
762
  }
763
+ if (cancel) {
764
+ cancel();
765
+ return;
766
+ }
765
767
  obj && obj.goBackEvent ? obj.goBackEvent.save(postMD) : next();
766
768
  },
767
769
  });
@@ -785,7 +787,7 @@ export class ShoppingProductSetting {
785
787
  <div class="flex-fill"></div>
786
788
  </div>
787
789
  <div class="d-flex flex-column ${obj.single ? `flex-column-reverse` : `flex-sm-row mt-4`} w-100 p-0" style="gap: 24px;">
788
- <div class="leftBigArea d-flex flex-column flex-fill" style="gap: 24px;">
790
+ <div class="leftBigArea d-flex flex-column flex-fill" style="gap: 18px;">
789
791
  ${!obj.single
790
792
  ? BgWidget.mainCard(gvc.bindView(() => {
791
793
  const id = gvc.glitter.getUUID();
@@ -971,7 +973,6 @@ export class ShoppingProductSetting {
971
973
  .join('')}
972
974
  </div>
973
975
  </div>
974
-
975
976
  <div style="font-weight: 700;">商品重量</div>
976
977
  <div class="w-100 row m-0" style="color:#393939;">
977
978
  <input
@@ -1156,7 +1157,7 @@ export class ShoppingProductSetting {
1156
1157
  });
1157
1158
  data.editable = true;
1158
1159
  obj.vm.type = 'editSpec';
1159
- });
1160
+ }, () => { });
1160
1161
  })}"
1161
1162
  >
1162
1163
  ${BgWidget.validImageBox({
@@ -1183,7 +1184,9 @@ export class ShoppingProductSetting {
1183
1184
  </div>
1184
1185
  ${obj.single ? '' : BgWidget.mbContainer(240)}
1185
1186
  </div>
1186
- `)}
1187
+ `, {
1188
+ style: obj.vm.type === 'editSpec' ? '' : 'margin-top: 0 !important;',
1189
+ })}
1187
1190
  <div class="update-bar-container ${obj.single ? `d-none` : ``}">
1188
1191
  ${BgWidget.cancel(obj.gvc.event(() => {
1189
1192
  checkStore(obj && obj.goBackEvent
@@ -1194,35 +1197,6 @@ export class ShoppingProductSetting {
1194
1197
  });
1195
1198
  }))}
1196
1199
  ${BgWidget.save(obj.gvc.event(() => {
1197
- function checkEmpty(variant, alert = false) {
1198
- const checkList = ['sale_price'];
1199
- for (const checkItem of checkList) {
1200
- if (!variant[checkItem]) {
1201
- dialog.infoMessage({
1202
- text: '價格輸入錯誤',
1203
- });
1204
- return false;
1205
- }
1206
- }
1207
- if (variant.shipment_type == 'weight') {
1208
- if (!variant.weight) {
1209
- dialog.infoMessage({
1210
- text: '商品重量未填',
1211
- });
1212
- return false;
1213
- }
1214
- }
1215
- if (variant.shipment_type == 'volume') {
1216
- if (!variant.v_height || !variant.v_length || !variant.v_width) {
1217
- dialog.infoMessage({
1218
- text: '商品材積未填',
1219
- });
1220
- return false;
1221
- }
1222
- }
1223
- return true;
1224
- }
1225
- const dialog = new ShareDialog(gvc.glitter);
1226
1200
  let checkPass = true;
1227
1201
  if (checkPass) {
1228
1202
  postMD.variants[index] = variant;
@@ -1266,6 +1240,12 @@ export class ShoppingProductSetting {
1266
1240
  template: '',
1267
1241
  content_array: [],
1268
1242
  content_json: [],
1243
+ active_schedule: {
1244
+ startDate: this.getDateTime().date,
1245
+ startTime: this.getDateTime().time,
1246
+ endDate: this.getDateTime(7).date,
1247
+ endTime: this.getDateTime(7).time,
1248
+ },
1269
1249
  };
1270
1250
  function setProductType() {
1271
1251
  switch (obj.product_type) {
@@ -1291,24 +1271,18 @@ export class ShoppingProductSetting {
1291
1271
  postMD.content_array = (_a = postMD.content_array) !== null && _a !== void 0 ? _a : [];
1292
1272
  postMD.content_json = (_b = postMD.content_json) !== null && _b !== void 0 ? _b : [];
1293
1273
  if (obj.type === 'replace') {
1294
- postMD = obj.defData;
1274
+ postMD = Object.assign(Object.assign({}, postMD), obj.defData);
1295
1275
  }
1296
1276
  else {
1297
1277
  obj.vm.replaceData = postMD;
1298
1278
  }
1299
1279
  const origin_data = JSON.stringify(postMD);
1300
- window.parent.glitter.share.checkData = () => {
1301
- return origin_data === JSON.stringify(postMD);
1302
- };
1280
+ window.parent.glitter.share.checkData = () => origin_data === JSON.stringify(postMD);
1303
1281
  const html = String.raw;
1304
1282
  const gvc = obj.gvc;
1305
- const seoID = gvc.glitter.getUUID();
1306
1283
  const variantsViewID = gvc.glitter.getUUID();
1307
- let createPage = {
1308
- page: 'add',
1309
- };
1310
- let selectFunRow = false;
1311
1284
  const saasConfig = window.parent.saasConfig;
1285
+ let selectFunRow = false;
1312
1286
  let shipment_config = yield saasConfig.api.getPrivateConfig(saasConfig.config.appName, `glitter_shipment`);
1313
1287
  if (shipment_config.response.result[0]) {
1314
1288
  shipment_config = shipment_config.response.result[0].value || {};
@@ -1316,6 +1290,9 @@ export class ShoppingProductSetting {
1316
1290
  else {
1317
1291
  shipment_config = {};
1318
1292
  }
1293
+ let createPage = {
1294
+ page: 'add',
1295
+ };
1319
1296
  function updateVariants() {
1320
1297
  const remove_indexs = [];
1321
1298
  let complexity = 1;
@@ -1433,6 +1410,7 @@ export class ShoppingProductSetting {
1433
1410
  preview_image: '',
1434
1411
  });
1435
1412
  }
1413
+ obj.vm.replaceData = postMD;
1436
1414
  obj.gvc.notifyDataChange(variantsViewID);
1437
1415
  }
1438
1416
  function checkSpecSingle() {
@@ -1462,12 +1440,12 @@ export class ShoppingProductSetting {
1462
1440
  const vm = {
1463
1441
  id: gvc.glitter.getUUID(),
1464
1442
  };
1465
- updateVariants();
1466
1443
  return gvc.bindView(() => {
1467
1444
  return {
1468
1445
  bind: vm.id,
1469
1446
  view: () => {
1470
1447
  var _a;
1448
+ updateVariants();
1471
1449
  return [
1472
1450
  BgWidget.container(html `
1473
1451
  <div class="title-container flex-column" style="gap:10px;">
@@ -1514,7 +1492,7 @@ export class ShoppingProductSetting {
1514
1492
  }).then((data) => {
1515
1493
  dialog.dataLoading({ visible: false });
1516
1494
  if (data.result && data.response.data && data.response.data.content) {
1517
- postMD = data.response.data.content;
1495
+ postMD = Object.assign(Object.assign({}, postMD), data.response.data.content);
1518
1496
  postMD.id = undefined;
1519
1497
  setProductType();
1520
1498
  gvc.notifyDataChange(vm.id);
@@ -1529,11 +1507,15 @@ export class ShoppingProductSetting {
1529
1507
  gvc.notifyDataChange(vm.id);
1530
1508
  });
1531
1509
  }), {}),
1532
- BgWidget.grayButton(document.body.clientWidth > 768 ? '預覽商品' : '預覽', gvc.event(() => {
1533
- const href = `https://${window.parent.glitter.share.editorViewModel.domain}/products/${postMD.seo.domain}`;
1534
- window.parent.glitter.openNewTab(href);
1535
- }), { icon: document.body.clientWidth > 768 ? 'fa-regular fa-eye' : undefined }),
1536
- ].join(html `<div class="mx-1"></div>`)}
1510
+ postMD.id
1511
+ ? BgWidget.grayButton(document.body.clientWidth > 768 ? '預覽商品' : '預覽', gvc.event(() => {
1512
+ const href = `https://${window.parent.glitter.share.editorViewModel.domain}/products/${postMD.seo.domain}`;
1513
+ window.parent.glitter.openNewTab(href);
1514
+ }), { icon: document.body.clientWidth > 768 ? 'fa-regular fa-eye' : undefined })
1515
+ : '',
1516
+ ]
1517
+ .filter((str) => str.length > 0)
1518
+ .join(html `<div class="mx-1"></div>`)}
1537
1519
  </div>
1538
1520
  </div>
1539
1521
  ${BgWidget.container1x2({
@@ -1541,18 +1523,20 @@ export class ShoppingProductSetting {
1541
1523
  BgWidget.mainCard(html `
1542
1524
  <div class="d-flex flex-column guide5-4">
1543
1525
  <div style="font-weight: 700;">商品名稱</div>
1544
- <input
1545
- class="w-100 mt-2"
1546
- value="${(_a = postMD.title) !== null && _a !== void 0 ? _a : ''}"
1547
- style="border-radius: 10px;border: 1px solid #DDD;display: flex;padding: 9px 18px 9px 18px;align-items: center;align-self: stretch;"
1548
- onchange="${gvc.event((e) => {
1549
- if (postMD.seo.domain === postMD.title) {
1550
- postMD.seo.domain = e.value;
1551
- }
1552
- postMD.title = e.value;
1553
- gvc.notifyDataChange('seo');
1554
- })}"
1555
- />
1526
+ ${BgWidget.editeInput({
1527
+ gvc: gvc,
1528
+ title: '',
1529
+ type: 'text',
1530
+ default: (_a = postMD.title) !== null && _a !== void 0 ? _a : '',
1531
+ placeHolder: '請輸入商品名稱',
1532
+ callback: (text) => {
1533
+ if (postMD.seo.domain === postMD.title) {
1534
+ postMD.seo.domain = text;
1535
+ }
1536
+ postMD.title = text;
1537
+ gvc.notifyDataChange('seo');
1538
+ },
1539
+ })}
1556
1540
  </div>
1557
1541
  `),
1558
1542
  BgWidget.mainCard([
@@ -1594,10 +1578,6 @@ export class ShoppingProductSetting {
1594
1578
  return html ` <div class="d-flex align-items-center justify-content-end mb-3">
1595
1579
  <div class="d-flex align-items-center gap-2">
1596
1580
  <div style="color: #393939; font-weight: 700;">商品描述</div>
1597
- ${BgWidget.aiChatButton({
1598
- gvc,
1599
- select: 'writer',
1600
- })}
1601
1581
  </div>
1602
1582
  <div class="flex-fill"></div>
1603
1583
  <div
@@ -1731,7 +1711,19 @@ export class ShoppingProductSetting {
1731
1711
  const originContent = `${postMD.content}`;
1732
1712
  BgWidget.fullDialog({
1733
1713
  gvc: gvc,
1734
- title: '商品描述',
1714
+ title: (gvc2) => {
1715
+ return `<div class="d-flex align-items-center me-2" style="gap:10px;">商品描述${BgWidget.aiChatButton({
1716
+ gvc: gvc2,
1717
+ select: 'writer',
1718
+ click: () => {
1719
+ ProductAi.generateRichText(gvc, (text) => {
1720
+ postMD.content += text;
1721
+ gvc.notifyDataChange(vm.id);
1722
+ gvc2.recreateView();
1723
+ });
1724
+ }
1725
+ })}</div>`;
1726
+ },
1735
1727
  innerHTML: (gvc2) => {
1736
1728
  return html ` <div>
1737
1729
  ${EditorElem.richText({
@@ -2055,13 +2047,13 @@ export class ShoppingProductSetting {
2055
2047
  view: () => {
2056
2048
  if (editSpectPage[specIndex].type == 'show') {
2057
2049
  gvc.addStyle(`
2058
- .option {
2059
- background-color: #f7f7f7;
2060
- }
2061
- .pen {
2062
- display: none;
2063
- }
2064
- `);
2050
+ .option {
2051
+ background-color: #f7f7f7;
2052
+ }
2053
+ .pen {
2054
+ display: none;
2055
+ }
2056
+ `);
2065
2057
  return html ` <div class="d-flex flex-column" style="gap:6px;align-items: flex-start;padding: 12px 0;">
2066
2058
  <div style="font-size: 16px;">${dd.title}</div>
2067
2059
  ${(() => {
@@ -2227,9 +2219,8 @@ export class ShoppingProductSetting {
2227
2219
  }
2228
2220
  return '';
2229
2221
  })(),
2230
- postMD.specs.length == 0
2231
- ? ''
2232
- : BgWidget.mainCard(html ` <div style="font-size: 16px;font-weight: 700;color:#393939;margin-bottom: 18px;">規格設定</div>` +
2222
+ postMD.variants.length > 1
2223
+ ? BgWidget.mainCard(html ` <div style="font-size: 16px;font-weight: 700;color:#393939;margin-bottom: 18px;">規格設定</div>` +
2233
2224
  obj.gvc.bindView(() => {
2234
2225
  var _a;
2235
2226
  function getPreviewImage(img) {
@@ -2793,7 +2784,19 @@ export class ShoppingProductSetting {
2793
2784
  <div
2794
2785
  style="display: flex;height: 40px;padding: 8px 17px 8px 18px;align-items: center;justify-content: space-between;gap: 4px;align-self: stretch;border-radius: 10px;background: #F7F7F7;"
2795
2786
  >
2796
- 已選取 ${selected.length}
2787
+ <div style="display: flex; gap: 12px;align-items: center;">
2788
+ <i
2789
+ class="fa-solid fa-square-check"
2790
+ style="width: 16px;height: 16px; margin-left: 3px; cursor: pointer;color: #393939;font-size: 18px;"
2791
+ onclick="${gvc.event(() => {
2792
+ postMD.variants.map((dd) => {
2793
+ dd.checked = false;
2794
+ });
2795
+ gvc.notifyDataChange(variantsViewID);
2796
+ })}"
2797
+ ></i>
2798
+ 已選取 ${selected.length} 項
2799
+ </div>
2797
2800
  <div
2798
2801
  style="position: relative"
2799
2802
  onclick="${gvc.event(() => {
@@ -2921,9 +2924,9 @@ export class ShoppingProductSetting {
2921
2924
  >
2922
2925
  <i
2923
2926
  class="${selected.length ? `fa-solid fa-square-check` : `fa-regular fa-square`}"
2924
- style="width: 16px;height: 16px;margin-left:2px;margin-right:18px;cursor: pointer;
2925
- color: ${selected.length ? `#393939` : `#DDD`};font-size: 18px;
2926
- "
2927
+ style="width: 16px;height: 16px;margin-left:2px;margin-right:18px;cursor: pointer; color: ${selected.length
2928
+ ? `#393939`
2929
+ : `#DDD`};font-size: 18px;"
2927
2930
  onclick="${gvc.event(() => {
2928
2931
  postMD.variants.map((dd) => {
2929
2932
  dd.checked = !selected.length;
@@ -3236,7 +3239,6 @@ export class ShoppingProductSetting {
3236
3239
  dd.editable = false;
3237
3240
  });
3238
3241
  data.editable = true;
3239
- obj.vm.from = 'add';
3240
3242
  obj.vm.type = 'editSpec';
3241
3243
  })}"
3242
3244
  >
@@ -3367,7 +3369,8 @@ export class ShoppingProductSetting {
3367
3369
  style: 'overflow: visible;',
3368
3370
  },
3369
3371
  };
3370
- })),
3372
+ }))
3373
+ : '',
3371
3374
  BgWidget.mainCard(obj.gvc.bindView(() => {
3372
3375
  const id = gvc.glitter.getUUID();
3373
3376
  return {
@@ -3536,9 +3539,102 @@ ${(_c = postMD.seo.content) !== null && _c !== void 0 ? _c : ''}</textarea
3536
3539
  },
3537
3540
  };
3538
3541
  })),
3542
+ BgWidget.mainCard(html ` <div class="mb-2" style="font-weight: 700;">商品狀態</div>
3543
+ ${gvc.bindView((() => {
3544
+ const id = gvc.glitter.getUUID();
3545
+ const inputStyle = 'display: block; width: 200px;';
3546
+ return {
3547
+ bind: id,
3548
+ view: () => {
3549
+ return [
3550
+ postMD.status === 'schedule'
3551
+ ? html ` <div class="tx_700">啟用期間</div>
3552
+ <div class="d-flex mb-3 ${document.body.clientWidth < 768 ? 'flex-column' : ''}" style="gap: 12px">
3553
+ <div class="d-flex align-items-center">
3554
+ <span class="tx_normal me-2">開始日期</span>
3555
+ ${BgWidget.editeInput({
3556
+ gvc: gvc,
3557
+ title: '',
3558
+ type: 'date',
3559
+ style: inputStyle,
3560
+ default: `${postMD.active_schedule.startDate}`,
3561
+ placeHolder: '',
3562
+ callback: (text) => {
3563
+ postMD.active_schedule.startDate = text;
3564
+ },
3565
+ })}
3566
+ </div>
3567
+ <div class="d-flex align-items-center">
3568
+ <span class="tx_normal me-2">開始時間</span>
3569
+ ${BgWidget.editeInput({
3570
+ gvc: gvc,
3571
+ title: '',
3572
+ type: 'time',
3573
+ style: inputStyle,
3574
+ default: `${postMD.active_schedule.startTime}`,
3575
+ placeHolder: '',
3576
+ callback: (text) => {
3577
+ postMD.active_schedule.startTime = text;
3578
+ },
3579
+ })}
3580
+ </div>
3581
+ </div>
3582
+ ${BgWidget.multiCheckboxContainer(gvc, [
3583
+ {
3584
+ key: 'noEnd',
3585
+ name: '無期限',
3586
+ },
3587
+ {
3588
+ key: 'withEnd',
3589
+ name: '結束時間',
3590
+ innerHtml: html ` <div
3591
+ class="d-flex mt-0 mt-md-1 ${document.body.clientWidth < 768 ? 'flex-column' : ''}"
3592
+ style="gap: 12px"
3593
+ >
3594
+ <div class="d-flex align-items-center">
3595
+ <span class="tx_normal me-2">結束日期</span>
3596
+ ${BgWidget.editeInput({
3597
+ gvc: gvc,
3598
+ title: '',
3599
+ type: 'date',
3600
+ style: inputStyle,
3601
+ default: `${postMD.active_schedule.endDate}`,
3602
+ placeHolder: '',
3603
+ callback: (text) => {
3604
+ postMD.active_schedule.endDate = text;
3605
+ },
3606
+ })}
3607
+ </div>
3608
+ <div class="d-flex align-items-center">
3609
+ <span class="tx_normal me-2">結束時間</span>
3610
+ ${BgWidget.editeInput({
3611
+ gvc: gvc,
3612
+ title: '',
3613
+ type: 'time',
3614
+ style: inputStyle,
3615
+ default: `${postMD.active_schedule.endTime}`,
3616
+ placeHolder: '',
3617
+ callback: (text) => {
3618
+ postMD.active_schedule.endTime = text;
3619
+ },
3620
+ })}
3621
+ </div>
3622
+ </div>`,
3623
+ },
3624
+ ], [postMD.active_schedule.endDate ? `withEnd` : `noEnd`], (text) => {
3625
+ if (text[0] === 'noEnd') {
3626
+ postMD.active_schedule.endDate = undefined;
3627
+ postMD.active_schedule.endTime = undefined;
3628
+ }
3629
+ }, { single: true })}`
3630
+ : '',
3631
+ ].join(BgWidget.mbContainer(12));
3632
+ },
3633
+ };
3634
+ })())}`),
3539
3635
  ]
3540
3636
  .filter((str) => str.length > 0)
3541
- .join(BgWidget.mbContainer(12)),
3637
+ .join(BgWidget.mbContainer(18)),
3542
3638
  ratio: 77,
3543
3639
  }, {
3544
3640
  html: html ` <div class="summary-card p-0">
@@ -3547,19 +3643,17 @@ ${(_c = postMD.seo.content) !== null && _c !== void 0 ? _c : ''}</textarea
3547
3643
  <div style="font-weight: 700;" class="mb-2">商品類型</div>
3548
3644
  <div style="font-weight: 400;" class="mb-2">${this.getProductTypeString(postMD)}</div>
3549
3645
  `),
3550
- BgWidget.mainCard(html ` <div style="font-weight: 700;" class="mb-2">商品狀態</div>` +
3551
- EditorElem.select({
3552
- gvc: obj.gvc,
3553
- title: '',
3554
- def: postMD.status,
3555
- array: [
3556
- { title: '啟用', value: 'active' },
3557
- { title: '草稿', value: 'draft' },
3558
- ],
3559
- callback: (text) => {
3560
- postMD.status = text;
3561
- },
3562
- })),
3646
+ BgWidget.mainCard(`<div style="font-weight: 700;" class="mb-2">商品狀態</div>` + BgWidget.select({
3647
+ gvc: obj.gvc,
3648
+ default: postMD.status,
3649
+ options: [
3650
+ { key: 'active', value: '啟用' },
3651
+ { key: 'draft', value: '草稿' },
3652
+ ],
3653
+ callback: (text) => {
3654
+ postMD.status = text;
3655
+ },
3656
+ })),
3563
3657
  BgWidget.mainCard(obj.gvc.bindView(() => {
3564
3658
  const id = obj.gvc.glitter.getUUID();
3565
3659
  return {
@@ -3568,10 +3662,10 @@ ${(_c = postMD.seo.content) !== null && _c !== void 0 ? _c : ''}</textarea
3568
3662
  return [
3569
3663
  html ` <div style="font-weight: 700;" class="mb-2">商品分類</div>`,
3570
3664
  postMD.collection
3571
- .map((dd, index) => {
3572
- return `<span style="font-size: 14px;">${dd}</span>`;
3665
+ .map((dd) => {
3666
+ return html `<span style="font-size: 14px;">${dd}</span>`;
3573
3667
  })
3574
- .join(`<div class="my-1"></div>`),
3668
+ .join(html `<div class="my-1"></div>`),
3575
3669
  html ` <div class="w-100 mt-3">
3576
3670
  ${BgWidget.darkButton(`設定商品分類`, gvc.event(() => {
3577
3671
  BgProduct.collectionsDialog({
@@ -3599,9 +3693,9 @@ ${(_c = postMD.seo.content) !== null && _c !== void 0 ? _c : ''}</textarea
3599
3693
  bind: id,
3600
3694
  view: () => {
3601
3695
  return [
3602
- `<div style="font-weight: 700;" class="mb-2">AI 選品</div>`,
3696
+ html `<div style="font-weight: 700;" class="mb-2">AI 選品</div>`,
3603
3697
  BgWidget.grayNote(postMD.ai_description || '尚未設定描述語句,透過設定描述語句,可以幫助AI更準確的定位產品。'),
3604
- `<div class="my-2"></div>`,
3698
+ html `<div class="my-2"></div>`,
3605
3699
  BgWidget.darkButton(`設定描述語句`, gvc.event(() => {
3606
3700
  function refresh() {
3607
3701
  gvc.notifyDataChange(id);
@@ -3641,7 +3735,7 @@ ${(_c = postMD.seo.content) !== null && _c !== void 0 ? _c : ''}</textarea
3641
3735
  })),
3642
3736
  ]
3643
3737
  .filter((str) => str.length > 0)
3644
- .join(BgWidget.mbContainer(24))}
3738
+ .join(BgWidget.mbContainer(18))}
3645
3739
  </div>`,
3646
3740
  ratio: 23,
3647
3741
  })}
@@ -3937,4 +4031,15 @@ ${(_c = postMD.seo.content) !== null && _c !== void 0 ? _c : ''}</textarea
3937
4031
  return '未知';
3938
4032
  }
3939
4033
  }
4034
+ ShoppingProductSetting.getDateTime = (n = 0) => {
4035
+ const now = new Date();
4036
+ now.setDate(now.getDate() + n);
4037
+ const year = now.getFullYear();
4038
+ const month = (now.getMonth() + 1).toString().padStart(2, '0');
4039
+ const day = now.getDate().toString().padStart(2, '0');
4040
+ const hours = now.getHours().toString().padStart(2, '0');
4041
+ const dateStr = `${year}-${month}-${day}`;
4042
+ const timeStr = `${hours}:00`;
4043
+ return { date: dateStr, time: timeStr };
4044
+ };
3940
4045
  window.glitter.setModule(import.meta.url, ShoppingProductSetting);