ts-glitter 18.8.9 → 18.9.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.
@@ -0,0 +1 @@
1
+ {"question":[{"ask":"商店營業時間","response":"每天早上6:00到晚上9:30"},{"ask":"配送時間","response":"預計3-6個工作天"},{"ask":"查詢我的訂單狀態","response":"orders-search"},{"ask":"查詢我的訂單配送狀態","response":"orders-search"},{"ask":"查詢我的訂單付款狀態","response":"orders-search"},{"ask":"訂單號碼##########的配送狀態","response":"orders-search"},{"ask":"訂單號碼##########的付款狀態","response":"orders-search"},{"ask":"訂單號碼##########的狀態","response":"orders-search"}]}
package/lowcode/Entry.js CHANGED
@@ -131,7 +131,7 @@ export class Entry {
131
131
  }
132
132
  window.renderClock = (_b = window.renderClock) !== null && _b !== void 0 ? _b : createClock();
133
133
  console.log(`Entry-time:`, window.renderClock.stop());
134
- glitter.share.editerVersion = 'V_18.8.9';
134
+ glitter.share.editerVersion = 'V_18.9.0';
135
135
  glitter.share.start = new Date();
136
136
  const vm = { appConfig: [] };
137
137
  window.saasConfig = {
package/lowcode/Entry.ts CHANGED
@@ -131,7 +131,7 @@ export class Entry {
131
131
  }
132
132
  (window as any).renderClock = (window as any).renderClock ?? createClock();
133
133
  console.log(`Entry-time:`, (window as any).renderClock.stop());
134
- glitter.share.editerVersion = 'V_18.8.9';
134
+ glitter.share.editerVersion = 'V_18.9.0';
135
135
  glitter.share.start = new Date();
136
136
  const vm = { appConfig: [] };
137
137
  (window as any).saasConfig = {
@@ -1721,7 +1721,7 @@ export class BgRecommend {
1721
1721
  </div>
1722
1722
  <div>
1723
1723
  ${BgWidget.title(vm.data.name || '新增推薦人')}${cf.data.id
1724
- ? BgWidget.grayNote(`建立時間: ${Tool.convertDateTimeFormat(cf.data.created_time)}`)
1724
+ ? BgWidget.grayNote(`建立時間: ${Tool.formatDateTime(cf.data.created_time)}`)
1725
1725
  : ''}
1726
1726
  </div>
1727
1727
  </div>
@@ -1946,7 +1946,7 @@ export class BgRecommend {
1946
1946
  </div>
1947
1947
  <div>
1948
1948
  ${BgWidget.title(vm.data.name || '新增推薦人')}${cf.data.id
1949
- ? BgWidget.grayNote(`建立時間: ${Tool.convertDateTimeFormat(cf.data.created_time)}`)
1949
+ ? BgWidget.grayNote(`建立時間: ${Tool.formatDateTime(cf.data.created_time)}`)
1950
1950
  : ''}
1951
1951
  </div>
1952
1952
  </div>
@@ -29,4 +29,28 @@ export class Excel {
29
29
  XLSX.writeFile(workbook, fileName);
30
30
  });
31
31
  }
32
+ static parseExcelToJson(gvc, file) {
33
+ return __awaiter(this, void 0, void 0, function* () {
34
+ const XLSX = yield Excel.loadXLSX(gvc);
35
+ return new Promise((resolve, reject) => {
36
+ const reader = new FileReader();
37
+ reader.onload = event => {
38
+ var _a;
39
+ try {
40
+ const data = new Uint8Array((_a = event.target) === null || _a === void 0 ? void 0 : _a.result);
41
+ const workbook = XLSX.read(data, { type: 'array' });
42
+ const sheetName = workbook.SheetNames[0];
43
+ const sheet = workbook.Sheets[sheetName];
44
+ const jsonData = XLSX.utils.sheet_to_json(sheet);
45
+ resolve(jsonData);
46
+ }
47
+ catch (error) {
48
+ reject(error);
49
+ }
50
+ };
51
+ reader.onerror = error => reject(error);
52
+ reader.readAsArrayBuffer(file);
53
+ });
54
+ });
55
+ }
32
56
  }
@@ -31,4 +31,33 @@ export class Excel {
31
31
  // 生成 Excel 檔案並下載
32
32
  XLSX.writeFile(workbook, fileName);
33
33
  }
34
+
35
+ static async parseExcelToJson(gvc: GVC, file: File): Promise<any[]> {
36
+ const XLSX = await Excel.loadXLSX(gvc);
37
+ return new Promise((resolve, reject) => {
38
+ const reader = new FileReader();
39
+
40
+ reader.onload = event => {
41
+ try {
42
+ const data = new Uint8Array(event.target?.result as ArrayBuffer);
43
+ const workbook = XLSX.read(data, { type: 'array' });
44
+
45
+ // 取得第一個工作表名稱
46
+ const sheetName = workbook.SheetNames[0];
47
+
48
+ // 取得工作表內容並轉換為 JSON
49
+ const sheet = workbook.Sheets[sheetName];
50
+ const jsonData = XLSX.utils.sheet_to_json(sheet);
51
+
52
+ resolve(jsonData);
53
+ } catch (error) {
54
+ reject(error);
55
+ }
56
+ };
57
+
58
+ reader.onerror = error => reject(error);
59
+
60
+ reader.readAsArrayBuffer(file);
61
+ });
62
+ }
34
63
  }
@@ -124,6 +124,17 @@ export class OrderExcel {
124
124
  分銷連結名稱: (_f = (_e = orderData.distribution_info) === null || _e === void 0 ? void 0 : _e.title) !== null && _f !== void 0 ? _f : '',
125
125
  });
126
126
  };
127
+ const getProductJSON = (item) => {
128
+ var _a;
129
+ return formatJSON({
130
+ 商品名稱: item.title,
131
+ 商品規格: item.spec.length > 0 ? item.spec.join(' / ') : '單一規格',
132
+ 商品SKU: (_a = item.sku) !== null && _a !== void 0 ? _a : '',
133
+ 商品購買數量: item.count,
134
+ 商品價格: item.sale_price,
135
+ 商品折扣: item.discount_price,
136
+ });
137
+ };
127
138
  const getUserJSON = (order, orderData) => {
128
139
  var _a, _b, _c, _d, _e, _f;
129
140
  return formatJSON({
@@ -135,6 +146,10 @@ export class OrderExcel {
135
146
  收件人信箱: orderData.user_info.email,
136
147
  付款方式: findMethodName(orderData.customer_info.payment_select, payment_methods),
137
148
  配送方式: findMethodName(orderData.user_info.shipment, shipment_methods),
149
+ 收貨地址: [orderData.user_info.city, orderData.user_info.area, orderData.user_info.address]
150
+ .filter(Boolean)
151
+ .join(''),
152
+ 代收金額: orderData.customer_info.payment_select === 'cash_on_delivery' ? orderData.total : 0,
138
153
  出貨單號碼: (_a = orderData.user_info.shipment_number) !== null && _a !== void 0 ? _a : '',
139
154
  出貨單日期: formatDate(orderData.user_info.shipment_date),
140
155
  發票號碼: (_b = order.invoice_number) !== null && _b !== void 0 ? _b : '',
@@ -142,17 +157,6 @@ export class OrderExcel {
142
157
  備註: (_f = orderData.user_info.note) !== null && _f !== void 0 ? _f : '無備註',
143
158
  });
144
159
  };
145
- const getProductJSON = (item) => {
146
- var _a;
147
- return formatJSON({
148
- 商品名稱: item.title,
149
- 商品規格: item.spec.length > 0 ? item.spec.join(' / ') : '單一規格',
150
- 商品SKU: (_a = item.sku) !== null && _a !== void 0 ? _a : '',
151
- 商品購買數量: item.count,
152
- 商品價格: item.sale_price,
153
- 商品折扣: item.discount_price,
154
- });
155
- };
156
160
  function exportOrdersToExcel(dataArray) {
157
161
  if (!dataArray.length) {
158
162
  dialog.errorMessage({ text: '無訂單資料可以匯出' });
@@ -262,7 +266,250 @@ export class OrderExcel {
262
266
  },
263
267
  });
264
268
  }
269
+ static importWithShipment(gvc, target, callback) {
270
+ var _a;
271
+ return __awaiter(this, void 0, void 0, function* () {
272
+ const dialog = new ShareDialog(gvc.glitter);
273
+ function errorMsg(text) {
274
+ dialog.dataLoading({ visible: false });
275
+ dialog.errorMessage({ text: text });
276
+ }
277
+ if ((_a = target.files) === null || _a === void 0 ? void 0 : _a.length) {
278
+ try {
279
+ dialog.dataLoading({ visible: true, text: '上傳檔案中' });
280
+ const jsonData = yield Excel.parseExcelToJson(gvc, target.files[0]);
281
+ const importMap = new Map();
282
+ for (let i = 0; i < jsonData.length; i++) {
283
+ const order = jsonData[i];
284
+ if ((order['出貨單號碼'] && !order['訂單編號']) || (!order['出貨單號碼'] && order['訂單編號'])) {
285
+ errorMsg('每個訂單編號必須與出貨單號碼成對');
286
+ return;
287
+ }
288
+ importMap.set(`${order['訂單編號']}`, `${order['出貨單號碼']}`);
289
+ }
290
+ const cartTokens = [...importMap.keys()];
291
+ const getOrders = yield ApiShop.getOrder({
292
+ page: 0,
293
+ limit: 1000,
294
+ searchType: 'cart_token',
295
+ id_list: cartTokens.join(','),
296
+ });
297
+ if (!getOrders.result) {
298
+ errorMsg('訂單資料取得失敗');
299
+ return;
300
+ }
301
+ const orders = getOrders.response.data;
302
+ const orderMap = new Map(orders.map((order) => [order.cart_token, true]));
303
+ const importKey = cartTokens.find(key => !orderMap.has(key));
304
+ if (importKey) {
305
+ errorMsg(`訂單編號 #${importKey} 不存在`);
306
+ return;
307
+ }
308
+ for (const order of orders) {
309
+ try {
310
+ if (order.orderData.user_info.shipment_number) {
311
+ errorMsg(`出貨單號碼不可覆寫<br/>(訂單編號: ${order.cart_token})`);
312
+ return;
313
+ }
314
+ if (order.orderData.progress && order.orderData.progress !== 'wait') {
315
+ errorMsg(`訂單出貨狀態必須為「未出貨」<br/>(訂單編號: ${order.cart_token})`);
316
+ return;
317
+ }
318
+ order.orderData.user_info.shipment_number = importMap.get(order.cart_token);
319
+ }
320
+ catch (error) {
321
+ errorMsg('訂單資料有誤');
322
+ }
323
+ }
324
+ const saveEvent = (order, setShipping) => {
325
+ var _a;
326
+ const orderData = order.orderData;
327
+ const temps = [
328
+ {
329
+ time: Tool.formatDateTime(),
330
+ record: `建立出貨單號碼 #${orderData.user_info.shipment_number}`,
331
+ },
332
+ ];
333
+ if (setShipping) {
334
+ orderData.progress = 'shipping';
335
+ temps.push({
336
+ time: Tool.formatDateTime(),
337
+ record: '訂單已出貨',
338
+ });
339
+ }
340
+ orderData.editRecord = [...((_a = orderData.editRecord) !== null && _a !== void 0 ? _a : []), ...temps];
341
+ return ApiShop.putOrder({ id: `${order.id}`, order_data: orderData });
342
+ };
343
+ dialog.dataLoading({ visible: false });
344
+ dialog.checkYesOrNot({
345
+ text: '匯入的出貨單資料,是否要將出貨狀態改成「已出貨」?',
346
+ yesString: '是',
347
+ notString: '否',
348
+ callback: (bool) => __awaiter(this, void 0, void 0, function* () {
349
+ try {
350
+ dialog.dataLoading({ visible: true });
351
+ const responses = yield Promise.all(orders.map((order) => {
352
+ return saveEvent(order, bool);
353
+ }));
354
+ const failedResponse = responses.find(res => !res.result);
355
+ dialog.dataLoading({ visible: false });
356
+ if (failedResponse) {
357
+ console.error('匯入失敗:', failedResponse);
358
+ dialog.errorMessage({ text: '匯入失敗' });
359
+ }
360
+ else {
361
+ dialog.successMessage({ text: '匯入成功' });
362
+ setTimeout(() => callback(), 300);
363
+ }
364
+ }
365
+ catch (error) {
366
+ dialog.dataLoading({ visible: false });
367
+ console.error('批次出貨更新錯誤:', error);
368
+ dialog.errorMessage({ text: '系統錯誤,請稍後再試' });
369
+ }
370
+ }),
371
+ });
372
+ }
373
+ catch (error) {
374
+ console.error('Order Excel 解析失敗', error);
375
+ }
376
+ }
377
+ });
378
+ }
379
+ static importDialog(gvc, query, callback) {
380
+ const dialog = new ShareDialog(gvc.glitter);
381
+ const vm = {
382
+ id: 'importDialog',
383
+ fileInput: {},
384
+ type: '',
385
+ orderTitle: (() => {
386
+ if (query.isShipment)
387
+ return '出貨單';
388
+ if (query.isArchived)
389
+ return '已封存訂單';
390
+ return '訂單';
391
+ })(),
392
+ };
393
+ gvc.glitter.innerDialog((gvc) => {
394
+ return gvc.bindView({
395
+ bind: vm.id,
396
+ view: () => {
397
+ const viewData = {
398
+ title: `匯入${vm.orderTitle}`,
399
+ category: {
400
+ title: `匯入${vm.orderTitle}類型`,
401
+ options: [],
402
+ },
403
+ example: {
404
+ event: () => {
405
+ Excel.downloadExcel(gvc, (() => {
406
+ if (query.isShipment)
407
+ return OrderExcel.importShipmentExample;
408
+ if (query.isArchived)
409
+ return [];
410
+ return [];
411
+ })(), `範例_${vm.orderTitle}列表_${gvc.glitter.ut.dateFormat(new Date(), 'yyyyMMddhhmmss')}.xlsx`, `範例${vm.orderTitle}列表`);
412
+ },
413
+ },
414
+ import: {
415
+ event: () => {
416
+ if (query.isShipment) {
417
+ return this.importWithShipment(gvc, vm.fileInput, () => {
418
+ gvc.glitter.closeDiaLog();
419
+ callback();
420
+ });
421
+ }
422
+ if (query.isArchived) {
423
+ }
424
+ },
425
+ },
426
+ };
427
+ return html `
428
+ <div
429
+ class="d-flex align-items-center w-100 tx_700"
430
+ style="padding: 12px 0 12px 20px; align-items: center; border-radius: 10px 10px 0px 0px; background: #F2F2F2;"
431
+ >
432
+ ${viewData.title}
433
+ </div>
434
+ ${viewData.category.options.length > 0
435
+ ? html `<div class="d-flex flex-column align-items-start gap-2" style="padding: 20px 20px 0px;">
436
+ <div class="tx_700">${viewData.category.title}</div>
437
+ ${BgWidget.multiCheckboxContainer(gvc, viewData.category.options, [vm.type], res => {
438
+ vm.type = res[0];
439
+ }, { single: true })}
440
+ </div>`
441
+ : ''}
442
+ <div class="d-flex flex-column w-100 align-items-start gap-3" style="padding: 20px">
443
+ <div class="d-flex align-items-center gap-2">
444
+ <div class="tx_700">透過XLSX檔案匯入商品</div>
445
+ ${BgWidget.blueNote('下載範例', gvc.event(viewData.example.event))}
446
+ </div>
447
+ <input
448
+ class="d-none"
449
+ type="file"
450
+ id="upload-excel"
451
+ onchange="${gvc.event((_, event) => {
452
+ vm.fileInput = event.target;
453
+ gvc.notifyDataChange(vm.id);
454
+ })}"
455
+ />
456
+ <div
457
+ class="d-flex flex-column w-100 justify-content-center align-items-center gap-3"
458
+ style="border: 1px solid #DDD; border-radius: 10px; min-height: 180px;"
459
+ >
460
+ ${(() => {
461
+ if (vm.fileInput.files && vm.fileInput.files.length > 0) {
462
+ return html `
463
+ ${BgWidget.customButton({
464
+ button: { color: 'snow', size: 'md' },
465
+ text: { name: '更換檔案' },
466
+ event: gvc.event(() => {
467
+ document.querySelector('#upload-excel').click();
468
+ }),
469
+ })}
470
+ ${BgWidget.grayNote(vm.fileInput.files[0].name)}
471
+ `;
472
+ }
473
+ else {
474
+ return BgWidget.customButton({
475
+ button: { color: 'snow', size: 'md' },
476
+ text: { name: '新增檔案' },
477
+ event: gvc.event(() => {
478
+ document.querySelector('#upload-excel').click();
479
+ }),
480
+ });
481
+ }
482
+ })()}
483
+ </div>
484
+ </div>
485
+ <div class="d-flex justify-content-end gap-3" style="padding-right: 20px; padding-bottom: 20px;">
486
+ ${BgWidget.cancel(gvc.event(() => {
487
+ gvc.glitter.closeDiaLog();
488
+ }))}
489
+ ${BgWidget.save(gvc.event(() => {
490
+ if (vm.fileInput.files && vm.fileInput.files.length > 0) {
491
+ viewData.import.event();
492
+ }
493
+ else {
494
+ dialog.infoMessage({ text: '尚未上傳檔案' });
495
+ }
496
+ }), '匯入')}
497
+ </div>
498
+ `;
499
+ },
500
+ divCreate: {
501
+ style: 'border-radius: 10px; background: #FFF; width: 570px; min-height: 360px; max-width: 90%;',
502
+ },
503
+ });
504
+ }, vm.id);
505
+ }
265
506
  }
507
+ OrderExcel.importShipmentExample = [
508
+ {
509
+ 訂單編號: '1241770010001',
510
+ 出貨單號碼: '1249900602345',
511
+ },
512
+ ];
266
513
  OrderExcel.headerColumn = {
267
514
  訂單: [
268
515
  '訂單編號',
@@ -290,6 +537,8 @@ OrderExcel.headerColumn = {
290
537
  '收件人信箱',
291
538
  '付款方式',
292
539
  '配送方式',
540
+ '收貨地址',
541
+ '代收金額',
293
542
  '出貨單號碼',
294
543
  '出貨單日期',
295
544
  '發票號碼',