@steedos-widgets/amis-lib 1.3.22-beta.1 → 1.3.22-beta.3

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.
package/dist/index.esm.js CHANGED
@@ -1626,6 +1626,7 @@ async function getQuickEditSchema(field, options){
1626
1626
  {
1627
1627
  "actionType": "custom",
1628
1628
  "script": `
1629
+
1629
1630
  var _display = _.cloneDeep(event.data._display);
1630
1631
  ${displayField}
1631
1632
  doAction({actionType: 'setValue', "args": {"value": {_display}},componentId: "${quickEditId}"});
@@ -2012,7 +2013,9 @@ async function getTableColumns(fields, options){
2012
2013
  if(!options.isLookup && !options.isInputTable){
2013
2014
  //将_display放入crud的columns中,可以通过setvalue修改行内数据域的_display,而不影响上层items的_display,用于批量编辑
2014
2015
  columns.push({name: '_display',type: 'static', width: 32, placeholder: "",id: "_display_${_index}", className: "hidden"});
2015
- columns.push({name: '_index',type: 'text', width: 32, placeholder: ""});
2016
+ if(!options.enable_tree){
2017
+ columns.push({name: '_index',type: 'text', width: 32, placeholder: ""});
2018
+ }
2016
2019
  }
2017
2020
  const allowEdit = options.permissions?.allowEdit && !options.isLookup && options.enable_inline_edit != false;
2018
2021
 
@@ -2863,7 +2866,21 @@ async function getTableApi(mainObject, fields, options){
2863
2866
 
2864
2867
  if(enable_tree){
2865
2868
  const records = payload.data.rows || [];
2866
- const getTreeOptions = SteedosUI.getTreeOptions
2869
+ const getTreeOptions = SteedosUI.getTreeOptions;
2870
+ const assignIndexToTreeRecords = function(tree, parentIndex) {
2871
+ tree.forEach(function (node, index) {
2872
+ // 构建当前节点的 _index
2873
+ var currentIndex = parentIndex ? parentIndex + '-' + (index + 1) : '' + (index + 1);
2874
+
2875
+ // 赋值给节点
2876
+ node._index = currentIndex;
2877
+
2878
+ // 如果有子节点,递归调用函数
2879
+ if (node.children && node.children.length > 0) {
2880
+ assignIndexToTreeRecords(node.children, currentIndex);
2881
+ }
2882
+ });
2883
+ };
2867
2884
  let isTreeOptionsComputed = false;
2868
2885
  if(records.length === 1 && records[0].children){
2869
2886
  isTreeOptionsComputed = true;
@@ -2871,6 +2888,7 @@ async function getTableApi(mainObject, fields, options){
2871
2888
  if(!isTreeOptionsComputed){
2872
2889
  // 如果api接口设置在缓存,缓存期间并不会重新请求接口,payload.data.rows是上次计算后的结果
2873
2890
  payload.data.rows = getTreeOptions(records,{"valueField":"_id"});
2891
+ assignIndexToTreeRecords(payload.data.rows, '');
2874
2892
  }
2875
2893
  try{
2876
2894
  setTimeout(() => {
@@ -7973,7 +7991,8 @@ function getObjectFooterToolbar(mainObject, formFactor, options) {
7973
7991
  {
7974
7992
  "type": "pagination",
7975
7993
  "maxButtons": 5,
7976
- "showPageInput": false
7994
+ "showPageInput": true,
7995
+ "layout": "total,pager,go"
7977
7996
  }
7978
7997
  ]
7979
7998
  }
@@ -8226,7 +8245,7 @@ async function getObjectCRUD(objectSchema, fields, options){
8226
8245
  let tableOptions = Object.assign({
8227
8246
  idFieldName: objectSchema.idFieldName, labelFieldName: labelFieldName,
8228
8247
  permissions:objectSchema.permissions,enable_inline_edit:objectSchema.enable_inline_edit,
8229
- crudId: listSchema.id || id
8248
+ crudId: listSchema.id || id, enable_tree: objectSchema.enable_tree
8230
8249
  }, options);
8231
8250
  tableOptions.amisData = createObject(options.amisData || {}, {});
8232
8251
  const table = await getTableSchema$1(fields, tableOptions);
@@ -11562,7 +11581,16 @@ async function convertSFieldToAmisField(field, readonly, ctx) {
11562
11581
  format:'YYYY-MM-DDT00:00:00.000[Z]',
11563
11582
  tpl: readonly ? getDateTpl(field) : null,
11564
11583
  // utc: true,
11565
- joinValues: false
11584
+ joinValues: false,
11585
+ "shortcuts": [
11586
+ "thismonth",
11587
+ "2monthsago",
11588
+ "3monthslater",
11589
+ "prevquarter",
11590
+ "thisquarter",
11591
+ "thisyear",
11592
+ "lastYear"
11593
+ ]
11566
11594
  };
11567
11595
  break;
11568
11596
  case 'date':
@@ -11973,6 +12001,8 @@ async function convertSFieldToAmisField(field, readonly, ctx) {
11973
12001
  let subFieldName = subField.name.replace(`${field.name}.$.`, '').replace(`${field.name}.`, '');
11974
12002
  if(subField.type === 'grid'){
11975
12003
  subField = await getGridFieldSubFields(subField, ctx.__formFields);
12004
+ }else if(subField.type === 'table'){
12005
+ subField = await getTabledFieldSubFields(subField, ctx.__formFields);
11976
12006
  }else {
11977
12007
  if(readonly){
11978
12008
  subFieldName = `${field.name}.${subFieldName}`;
@@ -12089,7 +12119,8 @@ async function getFieldSearchable(perField, permissionFields, ctx){
12089
12119
  fieldNamePrefix = `${fieldNamePrefix}between__`;
12090
12120
  }
12091
12121
  if(_field.type === 'datetime'){
12092
- _field.type = 'input-datetime-range';
12122
+ // 特意改为日期范围而不是日期时间范围,因为搜索时一般精确到日期就足够了,需要精确到日期时间范围需要在字段上配置amis属性来实现
12123
+ _field.type = 'input-date-range';
12093
12124
  _field.is_wide = true;
12094
12125
  fieldNamePrefix = `${fieldNamePrefix}between__`;
12095
12126
  }
@@ -12401,7 +12432,7 @@ async function getFormBody(permissionFields, formFields, ctx){
12401
12432
  * @Author: 殷亮辉 yinlianghui@hotoa.com
12402
12433
  * @Date: 2023-11-15 09:50:22
12403
12434
  * @LastEditors: 殷亮辉 yinlianghui@hotoa.com
12404
- * @LastEditTime: 2023-12-19 15:53:32
12435
+ * @LastEditTime: 2023-12-25 13:13:56
12405
12436
  */
12406
12437
 
12407
12438
  /**
@@ -12447,6 +12478,28 @@ function getInputTableCell(field, showAsInlineEditMode) {
12447
12478
  }
12448
12479
  }
12449
12480
 
12481
+ function getComponentId(name, tag) {
12482
+ let id = "";
12483
+ switch (name) {
12484
+ case "table_service":
12485
+ id = `service_wrapper__${tag}`;
12486
+ break;
12487
+ case "form_pagination":
12488
+ id = `service_popup_pagination_wrapper__${tag}`;
12489
+ break;
12490
+ case "form":
12491
+ id = `form_popup__${tag}`;
12492
+ break;
12493
+ case "dialog":
12494
+ id = `dialog_popup__${tag}`;
12495
+ break;
12496
+ default:
12497
+ id = `${name}__${tag}`;
12498
+ break;
12499
+ }
12500
+ return id;
12501
+ }
12502
+
12450
12503
  /**
12451
12504
  * @param {*} props
12452
12505
  * @param {*} mode edit/new/readonly
@@ -12494,17 +12547,35 @@ async function getInputTableColumns(props) {
12494
12547
  }
12495
12548
  }
12496
12549
 
12497
- function getFormPagination(props) {
12550
+ /**
12551
+ * @param {*} props input-table组件props
12552
+ * @param {*} mode edit/new/readonly
12553
+ * @returns 翻页组件
12554
+ */
12555
+ function getFormPagination(props, mode) {
12556
+ let showPagination = true;
12557
+ if(mode === "new" && !!!props.editable){
12558
+ //不允许编辑只允许新建时不应该让用户操作翻页
12559
+ showPagination = false;
12560
+ }
12561
+ let buttonPrevId = getComponentId("button_prev", props.id);
12562
+ let buttonNextId = getComponentId("button_next", props.id);
12563
+ let formId = getComponentId("form", props.id);
12564
+ let tableServiceId = getComponentId("table_service", props.id);
12565
+ let formPaginationId = getComponentId("form_pagination", props.id);
12498
12566
  let onPageChangeScript = `
12499
12567
  let scope = event.context.scoped;
12500
- let __paginationServiceId = event.data.__paginationServiceId;
12501
- let __wrapperServiceId = event.data.__wrapperServiceId;
12502
- let __formId = event.data.__formId;
12568
+ let __paginationServiceId = "${formPaginationId}";
12569
+ let __wrapperServiceId = "${tableServiceId}";
12570
+ let __formId = "${formId}";
12503
12571
  let fieldValue = event.data.__tableItems;//这里不可以_.cloneDeep,因为翻页form中用的是event.data.__tableItems,直接变更其值即可改变表单中的值
12504
12572
  let pageChangeDirection = context.props.pageChangeDirection;
12573
+ // event.data中的index和__page分别表示当前要把表单数据提交到的行索引和用于标定下一页页码的当前页页码
12574
+ // 一般来说__page = index + 1,但是可以让event.data中传入__page和index值不是这种联系。
12575
+ // 比如__page设置为3,index设置为0表示把当前表单数据提交到第一页,但是跳转到第4页,弹出的表单中底下的新增和复制按钮依赖了此功能
12576
+ // let currentPage = currentIndex + 1;
12505
12577
  let currentPage = event.data.__page;
12506
12578
  let currentIndex = event.data.index;
12507
-
12508
12579
  // 翻页到下一页之前需要先把当前页改动的内容保存到中间变量__tableItems中
12509
12580
  let currentFormValues = scope.getComponentById(__formId).getValues();
12510
12581
  fieldValue[currentIndex] = currentFormValues;
@@ -12549,7 +12620,8 @@ function getFormPagination(props) {
12549
12620
  `;
12550
12621
  return {
12551
12622
  "type": "wrapper",
12552
- "className": "py-2",
12623
+ "size": "none",
12624
+ "className": "mr-1",
12553
12625
  "body": [
12554
12626
  {
12555
12627
  "type": "button",
@@ -12557,8 +12629,9 @@ function getFormPagination(props) {
12557
12629
  "icon": `fa fa-angle-left`,
12558
12630
  "level": "link",
12559
12631
  "pageChangeDirection": "prev",
12560
- "disabledOn": "${__page <= 1}",
12632
+ "disabledOn": showPagination ? "${__page <= 1}" : "true",
12561
12633
  "size": "sm",
12634
+ "id": buttonPrevId,
12562
12635
  "onEvent": {
12563
12636
  "click": {
12564
12637
  "actions": [
@@ -12572,7 +12645,7 @@ function getFormPagination(props) {
12572
12645
  },
12573
12646
  {
12574
12647
  "type": "tpl",
12575
- "tpl": "${__page}/${__total}"
12648
+ "tpl": "${__page}/${__tableItems.length}"
12576
12649
  },
12577
12650
  {
12578
12651
  "type": "button",
@@ -12580,8 +12653,9 @@ function getFormPagination(props) {
12580
12653
  "icon": `fa fa-angle-right`,
12581
12654
  "level": "link",
12582
12655
  "pageChangeDirection": "next",
12583
- "disabledOn": "${__page >= __total}",
12656
+ "disabledOn": showPagination ? "${__page >= __tableItems.length}" : "true",
12584
12657
  "size": "sm",
12658
+ "id": buttonNextId,
12585
12659
  "onEvent": {
12586
12660
  "click": {
12587
12661
  "actions": [
@@ -12601,11 +12675,13 @@ function getFormPagination(props) {
12601
12675
  * 传入formSchema输出带翻页容器的wrapper
12602
12676
  * @param {*} props input-table组件props
12603
12677
  * @param {*} form formSchema
12604
- * @param {*} mode edit/readonly
12678
+ * @param {*} mode edit/new/readonly
12605
12679
  * @returns 带翻页容器的wrapper
12606
12680
  */
12607
12681
  function getFormPaginationWrapper(props, form, mode) {
12608
- let serviceId = `service_popup_pagination_wrapper__${props.id}`;
12682
+ // console.log("==getFormPaginationWrapper===", props, mode);
12683
+ let serviceId = getComponentId("form_pagination", props.id);
12684
+ let tableServiceId = getComponentId("table_service", props.id);
12609
12685
  let innerForm = Object.assign({}, form, {
12610
12686
  "data": {
12611
12687
  // 这里加__super前缀是因为__parentForm变量(即主表单)中可能会正好有名为index的字段
@@ -12617,9 +12693,9 @@ function getFormPaginationWrapper(props, form, mode) {
12617
12693
  {
12618
12694
  "type": "wrapper",
12619
12695
  "size": "none",
12620
- "className": "flex justify-end border-y border-gray-200 -mx-6 shadow-inner sticky top-0 right-0 left-0 z-20 bg-white mb-4",
12696
+ "className": "flex justify-end sticky top-0 right-0 left-0 z-20 bg-white -mt-2",
12621
12697
  "body": [
12622
- getFormPagination(props)
12698
+ getFormPagination(props, mode)
12623
12699
  ]
12624
12700
  },
12625
12701
  {
@@ -12640,11 +12716,29 @@ function getFormPaginationWrapper(props, form, mode) {
12640
12716
  // 处理思路是每次弹出form之前先把其__tableItems同步更新为最新值,这样就能在弹出form中包含单元格中做的修改
12641
12717
  // 注意:service init事件只会在每次弹出窗口时才执行,在触发翻页时并不会触发service init事件
12642
12718
  let scope = event.context.scoped;
12643
- let __wrapperServiceId = event.data.__wrapperServiceId;
12719
+ let __wrapperServiceId = "${tableServiceId}";
12644
12720
  let wrapperService = scope.getComponentById(__wrapperServiceId);
12645
12721
  let wrapperServiceData = wrapperService.getData();
12646
- let lastestFieldValue = wrapperServiceData["${props.name}"];//这里不可以用event.data["${props.name}"]因为amis input talbe有一层单独的作用域,其值会延迟一拍
12722
+ let lastestFieldValue = wrapperServiceData["${props.name}"] || [];//这里不可以用event.data["${props.name}"]因为amis input talbe有一层单独的作用域,其值会延迟一拍
12647
12723
  //不可以直接像event.data.__tableItems = lastestFieldValue; 这样整个赋值,否则作用域会断
12724
+ let mode = "${mode}";
12725
+ if(mode === "new"){
12726
+ // 点击子表组件底部新增按钮时新增一条空白行并自动翻页到新增行
12727
+ // 注意点击弹出的子表行详细表单中的新增按钮不会进此service init事件函数中
12728
+ let newItem = {};
12729
+ event.data.__tableItems.push(newItem);
12730
+ lastestFieldValue.push(newItem);
12731
+ event.data.index = lastestFieldValue.length - 1;
12732
+ event.data.__page = lastestFieldValue.length;
12733
+ // 这里新增空白行时要把值同步保存到子表组件中,如果不同步保存的话,用户点击弹出表单右上角的关闭窗口时不会自动删除这里自动增加的空白行,同步后可以让用户手动删除此行
12734
+ doAction({
12735
+ "componentId": "${props.id}",
12736
+ "actionType": "setValue",
12737
+ "args": {
12738
+ "value": lastestFieldValue
12739
+ }
12740
+ });
12741
+ }
12648
12742
  event.data.__tableItems.forEach(function(n,i){
12649
12743
  event.data.__tableItems[i] = lastestFieldValue[i];
12650
12744
  });
@@ -12669,9 +12763,9 @@ function getFormPaginationWrapper(props, form, mode) {
12669
12763
  "data": {
12670
12764
  "__page": "${index + 1}",
12671
12765
  // "__total": `\${${props.name}.length}`,
12672
- "__total": "${__tableItems.length}",
12673
- "__paginationServiceId": serviceId,
12674
- "__formId": form.id
12766
+ // "__total": "${__tableItems.length}",
12767
+ // "__paginationServiceId": serviceId,
12768
+ // "__formId": form.id
12675
12769
  },
12676
12770
  "onEvent": {
12677
12771
  "init": {
@@ -12694,8 +12788,8 @@ function getFormPaginationWrapper(props, form, mode) {
12694
12788
  async function getForm(props, mode = "edit", formId) {
12695
12789
  let formFields = getFormFields(props, mode);
12696
12790
  let body = await getFormBody(null, formFields);
12697
- if(!formId){
12698
- formId = `form_popup__${props.id}`;
12791
+ if (!formId) {
12792
+ formId = getComponentId("form", props.id);
12699
12793
  }
12700
12794
  let schema = {
12701
12795
  "type": "form",
@@ -12708,7 +12802,8 @@ async function getForm(props, mode = "edit", formId) {
12708
12802
  "canAccessSuperData": false,
12709
12803
  "className": "steedos-object-form steedos-amis-form"
12710
12804
  };
12711
- if (mode === "edit") {
12805
+ if (mode === "edit" || mode === "new") {
12806
+ // 新增行弹出编辑行表单,在弹出之前已经不用先增加一行,因为在翻页service初始化的时候会判断mode为new时自动新增一行
12712
12807
  let onEditItemSubmitScript = `
12713
12808
  // let fieldValue = _.cloneDeep(event.data["${props.name}"]);
12714
12809
  let fieldValue = event.data.__tableItems;//这里不可以_.cloneDeep,因为翻页form中用的是event.data.__tableItems,直接变更其值即可改变表单中的值
@@ -12747,103 +12842,366 @@ async function getForm(props, mode = "edit", formId) {
12747
12842
  }
12748
12843
  });
12749
12844
  }
12750
- else if (mode === "new") {
12751
- let onNewItemSubmitScript = `
12752
- let newItem = JSON.parse(JSON.stringify(event.data));
12753
- if(event.data["${props.name}"]){
12754
- // let fieldValue = event.data.__tableItems;
12755
- // 这里不用__tableItems是因为新建的时候没有翻页,里面没有也不需要走__tableItems变量
12756
- let fieldValue = event.data["${props.name}"];
12757
- fieldValue.push(newItem);
12758
- doAction({
12759
- "componentId": "${props.id}",
12760
- "actionType": "setValue",
12761
- "args": {
12762
- "value": fieldValue
12763
- }
12764
- });
12845
+ // else if (mode === "new") {
12846
+ // let onNewItemSubmitScript = `
12847
+ // let newItem = JSON.parse(JSON.stringify(event.data));
12848
+ // if(event.data["${props.name}"]){
12849
+ // // let fieldValue = event.data.__tableItems;
12850
+ // // 这里不用__tableItems是因为新建的时候没有翻页,里面没有也不需要走__tableItems变量
12851
+ // let fieldValue = event.data["${props.name}"];
12852
+ // fieldValue.push(newItem);
12853
+ // doAction({
12854
+ // "componentId": "${props.id}",
12855
+ // "actionType": "setValue",
12856
+ // "args": {
12857
+ // "value": fieldValue
12858
+ // }
12859
+ // });
12860
+ // }
12861
+ // else{
12862
+ // // 这里不可以执行event.data["${props.name}"]=[newItem],数据域会断掉
12863
+ // doAction({
12864
+ // "componentId": "${props.id}",
12865
+ // "actionType": "setValue",
12866
+ // "args": {
12867
+ // "value": [newItem]
12868
+ // }
12869
+ // });
12870
+ // }
12871
+ // `;
12872
+ // Object.assign(schema, {
12873
+ // "onEvent": {
12874
+ // "submit": {
12875
+ // "weight": 0,
12876
+ // "actions": [
12877
+ // {
12878
+ // "actionType": "custom",
12879
+ // "script": onNewItemSubmitScript
12880
+ // },
12881
+ // // {
12882
+ // // "componentId": props.id,
12883
+ // // "actionType": "addItem",//input-table组件的needConfirm属性为true时,addItem动作会把新加的行显示为编辑状态,所以只能使用上面的custom script来setValue实现添加行
12884
+ // // "args": {
12885
+ // // "index": `\${${props.name}.length || 9000}`,//这里加9000是因为字段如果没放在form组件内,props.name.length拿不到值
12886
+ // // "item": {
12887
+ // // "&": "$$"
12888
+ // // }
12889
+ // // }
12890
+ // // }
12891
+ // ]
12892
+ // }
12893
+ // }
12894
+ // });
12895
+ // }
12896
+ schema = getFormPaginationWrapper(props, schema, mode);
12897
+ return schema;
12898
+ }
12899
+
12900
+
12901
+ /**
12902
+ * 编辑、新增、删除、查看按钮actions
12903
+ * @param {*} props
12904
+ * @param {*} mode edit/new/readonly/delete
12905
+ */
12906
+ async function getButtonActions(props, mode) {
12907
+ let actions = [];
12908
+ let formId = getComponentId("form", props.id);
12909
+ let dialogId = getComponentId("dialog", props.id);
12910
+ let buttonNextId = getComponentId("button_next", props.id);
12911
+ let formPaginationId = getComponentId("form_pagination", props.id);
12912
+ if (mode == "new" || mode == "edit") {
12913
+ // let actionShowNewDialog = {
12914
+ // "actionType": "dialog",
12915
+ // "dialog": {
12916
+ // "type": "dialog",
12917
+ // "title": "新增行",
12918
+ // "body": [
12919
+ // await getForm(props, "new", formId)
12920
+ // ],
12921
+ // "size": "lg",
12922
+ // "showCloseButton": true,
12923
+ // "showErrorMsg": true,
12924
+ // "showLoading": true,
12925
+ // "className": "app-popover",
12926
+ // "closeOnEsc": false,
12927
+ // "onEvent": {
12928
+ // "confirm": {
12929
+ // "actions": [
12930
+ // {
12931
+ // "actionType": "validate",
12932
+ // "componentId": formId
12933
+ // },
12934
+ // {
12935
+ // "preventDefault": true,
12936
+ // "expression": "${event.data.validateResult.error}" //触发表单校验结果会存入validateResult,amis 3.2不支持,高版本比如 3.5.3支持
12937
+ // }
12938
+ // ]
12939
+ // }
12940
+ // }
12941
+ // }
12942
+ // };
12943
+ let onSaveAndNewItemScript = `
12944
+ let scope = event.context.scoped;
12945
+ let fieldValue = event.data.__tableItems;//这里不可以_.cloneDeep,因为翻页form中用的是event.data.__tableItems,直接变更其值即可改变表单中的值
12946
+ // 新建一条空白行并保存到子表组件
12947
+ fieldValue.push({});
12948
+ doAction({
12949
+ "componentId": "${props.id}",
12950
+ "actionType": "setValue",
12951
+ "args": {
12952
+ "value": fieldValue
12953
+ }
12954
+ });
12955
+ let buttonNextId = "${buttonNextId}";
12956
+ let __paginationServiceId = "${formPaginationId}";
12957
+ let __paginationData = scope.getComponentById(__paginationServiceId).getData();
12958
+ event.data.index = __paginationData.index;
12959
+ event.data.__page = fieldValue.length - 1;//这里不可以用Object.assign否则,event.data中上层作用域数据会丢失
12960
+ // 触发翻页按钮事件,实现保存当前页数据并跳转到最后一行
12961
+ scope.getComponentById(buttonNextId).props.dispatchEvent("click", event.data);
12962
+ `;
12963
+ let onSaveAndCopyItemScript = `
12964
+ let scope = event.context.scoped;
12965
+ let __formId = "${formId}";
12966
+ // let newItem = JSON.parse(JSON.stringify(event.data));
12967
+ let newItem = scope.getComponentById(__formId).getValues();//这里不可以用event.data,因为其拿到的是弹出表单时的初始值,不是用户实时填写的数据
12968
+ let fieldValue = event.data.__tableItems;//这里不可以_.cloneDeep,因为翻页form中用的是event.data.__tableItems,直接变更其值即可改变表单中的值
12969
+ // 复制当前页数据到新建行并保存到子表组件
12970
+ fieldValue.push(newItem);
12971
+ doAction({
12972
+ "componentId": "${props.id}",
12973
+ "actionType": "setValue",
12974
+ "args": {
12975
+ "value": fieldValue
12976
+ }
12977
+ });
12978
+ let buttonNextId = "${buttonNextId}";
12979
+ let __paginationServiceId = "${formPaginationId}";
12980
+ let __paginationData = scope.getComponentById(__paginationServiceId).getData();
12981
+ event.data.index = __paginationData.index;
12982
+ event.data.__page = fieldValue.length - 1;//这里不可以用Object.assign否则,event.data中上层作用域数据会丢失
12983
+ // 触发翻页按钮事件,实现保存当前页数据并跳转到最后一行
12984
+ scope.getComponentById(buttonNextId).props.dispatchEvent("click", event.data);
12985
+ `;
12986
+ let dialogButtons = [
12987
+ {
12988
+ "type": "button",
12989
+ "label": "完成",
12990
+ "actionType": "confirm",
12991
+ "level": "primary"
12765
12992
  }
12766
- else{
12767
- // 这里不可以执行event.data["${props.name}"]=[newItem],数据域会断掉
12768
- doAction({
12769
- "componentId": "${props.id}",
12770
- "actionType": "setValue",
12771
- "args": {
12772
- "value": [newItem]
12993
+ ];
12994
+ if(props.addable){
12995
+ // 有新增行权限时额外添加新增和复制按钮
12996
+ dialogButtons = [
12997
+ {
12998
+ "type": "button",
12999
+ "label": "新增",
13000
+ "tooltip": "保存并新增一行,即保存当前行数据并新增一条空白行",
13001
+ "onEvent": {
13002
+ "click": {
13003
+ "actions": [
13004
+ {
13005
+ "actionType": "custom",
13006
+ "script": onSaveAndNewItemScript
13007
+ }
13008
+ ]
13009
+ }
12773
13010
  }
12774
- });
13011
+ },
13012
+ {
13013
+ "type": "button",
13014
+ "label": "复制",
13015
+ "tooltip": "复制并新增一行,即保存当前行数据并复制当前行数据到新增行",
13016
+ "onEvent": {
13017
+ "click": {
13018
+ "actions": [
13019
+ {
13020
+ "actionType": "custom",
13021
+ "script": onSaveAndCopyItemScript
13022
+ }
13023
+ ]
13024
+ }
13025
+ }
13026
+ },
13027
+ dialogButtons[0]
13028
+ ];
13029
+ }
13030
+ let actionShowEditDialog = {
13031
+ "actionType": "dialog",
13032
+ "dialog": {
13033
+ "type": "dialog",
13034
+ "id": dialogId,
13035
+ "title": `\${uiSchema.fields.${props.name}.label} 明细`,
13036
+ "body": [
13037
+ await getForm(props, mode, formId)
13038
+ ],
13039
+ "size": "lg",
13040
+ "showCloseButton": true,
13041
+ "showErrorMsg": true,
13042
+ "showLoading": true,
13043
+ "className": "app-popover",
13044
+ "closeOnEsc": false,
13045
+ "data": {
13046
+ // 这里必须加data数据映射,否则翻页功能中取__tableItems值时会乱,比如翻页编辑后会把上一页中没改过的字段值带过去
13047
+ // 额外把华炎魔方主表记录ObjectForm中的字段值从record变量中映射到子表form中,因为子表lookup字段filtersFunction中可能依赖了主表记录中的字段值,比如“工作流规则”对象“时间触发器”字段中的“日期字段”字段
13048
+ // 额外把global、uiSchema也映射过去,有可能要用,后续需要用到其他变更可以这里加映射
13049
+ // "&": "${record || {}}",
13050
+ // 换成从__super来映射上级表单数据是因为对象列表视图界面中每行下拉菜单中的编辑按钮弹出的表单中的子表所在作用域中没有record变量
13051
+ // 映射到中间变量__parentForm而不是直接用&展开映射是为了避免表单中字段名与作用域中变量重名
13052
+ // "__parentForm": "${__super.__super || {}}",
13053
+ "__parentForm": mode == "new" ? "$$" : "${__super.__super || {}}",
13054
+ "global": "${global}",
13055
+ "uiSchema": "${uiSchema}",
13056
+ "index": "${index}",
13057
+ // "__tableItems": `\${${props.name}}`
13058
+ // 为了解决"弹出的dialog窗口中子表组件会影响页面布局界面中父作用域字段值",比如设计字段布局微页面中的设置分组功能,弹出的就是子表dialog
13059
+ // 所以这里使用json|toJson转一次,断掉event.data.__tableItems与上层任用域中props.name的联系
13060
+ // "__tableItems": `\${${props.name}|json|toJson}`
13061
+ "__tableItems": `\${(${props.name} || [])|json|toJson}`
13062
+ },
13063
+ "actions": dialogButtons,
13064
+ "onEvent": {
13065
+ "confirm": {
13066
+ "actions": [
13067
+ {
13068
+ "actionType": "validate",
13069
+ "componentId": formId
13070
+ },
13071
+ {
13072
+ "preventDefault": true,
13073
+ "expression": "${event.data.validateResult.error}" //触发表单校验结果会存入validateResult,amis 3.2不支持,高版本比如 3.5.3支持
13074
+ }
13075
+ ]
13076
+ }
13077
+ }
12775
13078
  }
12776
- `;
12777
- Object.assign(schema, {
12778
- "onEvent": {
12779
- "submit": {
12780
- "weight": 0,
12781
- "actions": [
12782
- {
12783
- "actionType": "custom",
12784
- "script": onNewItemSubmitScript
12785
- },
12786
- // {
12787
- // "componentId": props.id,
12788
- // "actionType": "addItem",//input-table组件的needConfirm属性为true时,addItem动作会把新加的行显示为编辑状态,所以只能使用上面的custom script来setValue实现添加行
12789
- // "args": {
12790
- // "index": `\${${props.name}.length || 9000}`,//这里加9000是因为字段如果没放在form组件内,props.name.length拿不到值
12791
- // "item": {
12792
- // "&": "$$"
12793
- // }
12794
- // }
12795
- // }
12796
- ]
13079
+ };
13080
+ if (props.dialog) {
13081
+ Object.assign(actionShowEditDialog.dialog, props.dialog);
13082
+ }
13083
+ if (mode == "new") {
13084
+ `
13085
+ let newItem = {};
13086
+ if(event.data["${props.name}"]){
13087
+ // let fieldValue = event.data.__tableItems;
13088
+ // 这里不用__tableItems是因为新建的时候没有翻页,里面没有也不需要走__tableItems变量
13089
+ // let fieldValue = _.clone(event.data["${props.name}"]);
13090
+ let fieldValue = event.data["${props.name}"];
13091
+ fieldValue.push(newItem);
13092
+ doAction({
13093
+ "componentId": "${props.id}",
13094
+ "actionType": "setValue",
13095
+ "args": {
13096
+ "value": fieldValue
13097
+ }
13098
+ });
13099
+ event.data.index = fieldValue.length - 1;
13100
+ }
13101
+ else{
13102
+ // 这里不可以执行event.data["${props.name}"]=[newItem],数据域会断掉
13103
+ doAction({
13104
+ "componentId": "${props.id}",
13105
+ "actionType": "setValue",
13106
+ "args": {
13107
+ "value": [newItem]
13108
+ }
13109
+ });
13110
+ event.data.index = 1;
13111
+ }
13112
+ `;
13113
+ // 新增行时不需要在弹出编辑表单前先加一行,因为会在编辑表单所在service初始化时判断到是新增就自动增加一行,因为这里拿不到event.data.__tableItems,也无法变更其值
13114
+ // actions = [actionNewLine, actionShowEditDialog];
13115
+ actions = [actionShowEditDialog];
13116
+ }
13117
+ else if (mode == "edit") {
13118
+ actions = [actionShowEditDialog];
13119
+ }
13120
+ }
13121
+ else if (mode == "readonly") {
13122
+ actions = [
13123
+ {
13124
+ "actionType": "dialog",
13125
+ "dialog": {
13126
+ "type": "dialog",
13127
+ "title": `\${uiSchema.fields.${props.name}.label} 明细`,
13128
+ "body": [
13129
+ await getForm(props, "readonly")
13130
+ ],
13131
+ "size": "lg",
13132
+ "showCloseButton": true,
13133
+ "showErrorMsg": true,
13134
+ "showLoading": true,
13135
+ "className": "app-popover",
13136
+ "closeOnEsc": false,
13137
+ "actions": [],
13138
+ "data": {
13139
+ // 这里必须加data数据映射,否则翻页功能中取__tableItems值时会乱,比如翻页编辑后会把上一页中没改过的字段值带过去
13140
+ // 额外把华炎魔方主表记录ObjectForm中的字段值从record变量中映射到子表form中,因为子表lookup字段filtersFunction中可能依赖了主表记录中的字段值,比如“工作流规则”对象“时间触发器”字段中的“日期字段”字段
13141
+ // 额外把global、uiSchema也映射过去,有可能要用,后续需要用到其他变更可以这里加映射
13142
+ // "&": "${record || {}}",
13143
+ // 换成从__super来映射上级表单数据是因为对象列表视图界面中每行下拉菜单中的编辑按钮弹出的表单中的子表所在作用域中没有record变量
13144
+ // 映射到中间变量__parentForm而不是直接用&展开映射是为了避免表单中字段名与作用域中变量重名
13145
+ // "__parentForm": "${__super.__super || {}}",
13146
+ "__parentForm": "${__super.__super || {}}",
13147
+ "global": "${global}",
13148
+ "uiSchema": "${uiSchema}",
13149
+ "index": "${index}",
13150
+ // "__tableItems": `\${${props.name}}`
13151
+ // 为了解决"弹出的dialog窗口中子表组件会影响页面布局界面中父作用域字段值",比如设计字段布局微页面中的设置分组功能,弹出的就是子表dialog
13152
+ // 所以这里使用json|toJson转一次,断掉event.data.__tableItems与上层任用域中props.name的联系
13153
+ // "__tableItems": `\${${props.name}|json|toJson}`
13154
+ "__tableItems": `\${(${props.name} || [])|json|toJson}`
13155
+ },
12797
13156
  }
12798
13157
  }
12799
- });
13158
+ ];
12800
13159
  }
12801
- if (mode === "edit" || mode === "readonly") {
12802
- schema = getFormPaginationWrapper(props, schema);
13160
+ else if (mode == "delete") {
13161
+ let tableServiceId = getComponentId("table_service", props.id);
13162
+ let onDeleteItemScript = `
13163
+ // let fieldValue = event.data["${props.name}"];
13164
+ let scope = event.context.scoped;
13165
+ let __wrapperServiceId = "${tableServiceId}";
13166
+ let wrapperService = scope.getComponentById(__wrapperServiceId);
13167
+ let wrapperServiceData = wrapperService.getData();
13168
+ // 这里不可以用event.data["${props.name}"]因为amis input talbe有一层单独的作用域,其值会延迟一拍
13169
+ // 这里_.clone是因为字段设计布局设置分组这种弹出窗口中的子表组件,直接删除后,点取消无法还原
13170
+ let lastestFieldValue = _.clone(wrapperServiceData["${props.name}"]);
13171
+ lastestFieldValue.splice(event.data.index, 1);
13172
+ doAction({
13173
+ "componentId": "${props.id}",
13174
+ "actionType": "setValue",
13175
+ "args": {
13176
+ "value": lastestFieldValue
13177
+ }
13178
+ });
13179
+ `;
13180
+ actions = [
13181
+ // {
13182
+ // "actionType": "deleteItem",
13183
+ // "args": {
13184
+ // "index": "${index+','}" //这里不加逗号后续会报错,语法是逗号分隔可以删除多行
13185
+ // },
13186
+ // "componentId": props.id
13187
+ // },
13188
+ {
13189
+ "actionType": "custom",
13190
+ "script": onDeleteItemScript
13191
+ }
13192
+ ];
12803
13193
  }
12804
- return schema;
13194
+ return actions;
12805
13195
  }
12806
13196
 
12807
13197
  async function getButtonNew(props) {
12808
- let formId = `form_popup__${props.id}`;
12809
13198
  return {
12810
13199
  "label": "新增",
12811
13200
  "type": "button",
12812
13201
  "icon": "fa fa-plus",
12813
13202
  "onEvent": {
12814
13203
  "click": {
12815
- "actions": [
12816
- {
12817
- "actionType": "dialog",
12818
- "dialog": {
12819
- "type": "dialog",
12820
- "title": "新增行",
12821
- "body": [
12822
- await getForm(props, "new", formId)
12823
- ],
12824
- "size": "lg",
12825
- "showCloseButton": true,
12826
- "showErrorMsg": true,
12827
- "showLoading": true,
12828
- "className": "app-popover",
12829
- "closeOnEsc": false,
12830
- "onEvent": {
12831
- "confirm": {
12832
- "actions": [
12833
- {
12834
- "actionType": "validate",
12835
- "componentId": formId
12836
- },
12837
- {
12838
- "preventDefault": true,
12839
- "expression": "${event.data.validateResult.error}" //触发表单校验结果会存入validateResult,amis 3.2不支持,高版本比如 3.5.3支持
12840
- }
12841
- ]
12842
- }
12843
- }
12844
- }
12845
- }
12846
- ]
13204
+ "actions": await getButtonActions(props, "new")
12847
13205
  }
12848
13206
  },
12849
13207
  "level": "primary"
@@ -12851,60 +13209,14 @@ async function getButtonNew(props) {
12851
13209
  }
12852
13210
 
12853
13211
  async function getButtonEdit(props, showAsInlineEditMode) {
12854
- let formId = `form_popup__${props.id}`;
12855
13212
  return {
12856
13213
  "type": "button",
12857
13214
  "label": "",
12858
- "icon": `fa fa-${showAsInlineEditMode ? "expand" : "pencil"}`,//inline edit模式时显示为放开按钮,只读时显示为笔按钮
13215
+ "icon": `fa fa-${showAsInlineEditMode ? "expand-alt" : "pencil"}`,//inline edit模式时显示为放开按钮,只读时显示为笔按钮
12859
13216
  "level": "link",
12860
13217
  "onEvent": {
12861
13218
  "click": {
12862
- "actions": [
12863
- {
12864
- "actionType": "dialog",
12865
- "dialog": {
12866
- "type": "dialog",
12867
- "title": "编辑行",
12868
- "body": [
12869
- await getForm(props, "edit", formId)
12870
- ],
12871
- "size": "lg",
12872
- "showCloseButton": true,
12873
- "showErrorMsg": true,
12874
- "showLoading": true,
12875
- "className": "app-popover",
12876
- "closeOnEsc": false,
12877
- "data": {
12878
- // 这里必须加data数据映射,否则翻页功能中取__tableItems值时会乱,比如翻页编辑后会把上一页中没改过的字段值带过去
12879
- // 额外把华炎魔方主表记录ObjectForm中的字段值从record变量中映射到子表form中,因为子表lookup字段filtersFunction中可能依赖了主表记录中的字段值,比如“工作流规则”对象“时间触发器”字段中的“日期字段”字段
12880
- // 额外把global、uiSchema也映射过去,有可能要用,后续需要用到其他变更可以这里加映射
12881
- // "&": "${record || {}}",
12882
- // 换成从__super来映射上级表单数据是因为对象列表视图界面中每行下拉菜单中的编辑按钮弹出的表单中的子表所在作用域中没有record变量
12883
- // 映射到中间变量__parentForm而不是直接用&展开映射是为了避免表单中字段名与作用域中变量重名
12884
- "__parentForm": "${__super.__super || {}}",
12885
- "global": "${global}",
12886
- "uiSchema": "${uiSchema}",
12887
- "index": "${index}",
12888
- "__tableItems": `\${${props.name}}`,
12889
- "__wrapperServiceId": "${__wrapperServiceId}"
12890
- },
12891
- "onEvent": {
12892
- "confirm": {
12893
- "actions": [
12894
- {
12895
- "actionType": "validate",
12896
- "componentId": formId
12897
- },
12898
- {
12899
- "preventDefault": true,
12900
- "expression": "${event.data.validateResult.error}" //触发表单校验结果会存入validateResult,amis 3.2不支持,高版本比如 3.5.3支持
12901
- }
12902
- ]
12903
- }
12904
- }
12905
- }
12906
- }
12907
- ]
13219
+ "actions": await getButtonActions(props, "edit")
12908
13220
  }
12909
13221
  }
12910
13222
  };
@@ -12914,83 +13226,25 @@ async function getButtonView(props) {
12914
13226
  return {
12915
13227
  "type": "button",
12916
13228
  "label": "",
12917
- "icon": "fa fa-expand",//fa-external-link
13229
+ "icon": "fa fa-expand-alt",//fa-external-link
12918
13230
  "level": "link",
12919
13231
  "onEvent": {
12920
13232
  "click": {
12921
- "actions": [
12922
- {
12923
- "actionType": "dialog",
12924
- "dialog": {
12925
- "type": "dialog",
12926
- "title": "查看行",
12927
- "body": [
12928
- await getForm(props, "readonly")
12929
- ],
12930
- "size": "lg",
12931
- "showCloseButton": true,
12932
- "showErrorMsg": true,
12933
- "showLoading": true,
12934
- "className": "app-popover",
12935
- "closeOnEsc": false,
12936
- "actions": [],
12937
- "data": {
12938
- // 这里必须加data数据映射,否则翻页功能中取__tableItems值时会乱,比如翻页编辑后会把上一页中没改过的字段值带过去
12939
- // 额外把华炎魔方主表记录ObjectForm中的字段值从formData变量中映射到子表form中,因为子表lookup字段filtersFunction中可能依赖了主表记录中的字段值,比如“工作流规则”对象“时间触发器”字段中的“日期字段”字段
12940
- // global、uiSchema等常用变量本来就在formData变量已经存在了,无需另外映射
12941
- // "&": "${formData || {}}",
12942
- // 换成从__super来映射上级表单数据是因为对象列表视图界面中每行下拉菜单中的编辑按钮弹出的表单中的子表所在作用域中没有formData变量
12943
- // 映射到中间变量__parentForm而不是直接用&展开映射是为了避免表单中字段名与作用域中变量重名
12944
- "__parentForm": "${__super.__super || {}}",
12945
- "index": "${index}",
12946
- "__tableItems": `\${${props.name}}`,
12947
- "__wrapperServiceId": "${__wrapperServiceId}"
12948
- }
12949
- }
12950
- }
12951
- ]
13233
+ "actions": await getButtonActions(props, "readonly")
12952
13234
  }
12953
13235
  }
12954
13236
  };
12955
13237
  }
12956
13238
 
12957
- function getButtonDelete(props) {
12958
- let onDeleteItemScript = `
12959
- // let fieldValue = event.data["${props.name}"];
12960
- let scope = event.context.scoped;
12961
- let __wrapperServiceId = event.data.__wrapperServiceId;
12962
- let wrapperService = scope.getComponentById(__wrapperServiceId);
12963
- let wrapperServiceData = wrapperService.getData();
12964
- let lastestFieldValue = wrapperServiceData["${props.name}"];//这里不可以用event.data["${props.name}"]因为amis input talbe有一层单独的作用域,其值会延迟一拍
12965
- lastestFieldValue.splice(event.data.index, 1);
12966
- doAction({
12967
- "componentId": "${props.id}",
12968
- "actionType": "setValue",
12969
- "args": {
12970
- "value": lastestFieldValue
12971
- }
12972
- });
12973
- `;
13239
+ async function getButtonDelete(props) {
12974
13240
  return {
12975
13241
  "type": "button",
12976
13242
  "label": "",
12977
- "icon": "fa fa-minus",
13243
+ "icon": "fa fa-trash-alt",//不可以用fa-trash-o,因为设计字段布局界面中弹出的设置分组列表中显示不了这个图标
12978
13244
  "level": "link",
12979
13245
  "onEvent": {
12980
13246
  "click": {
12981
- "actions": [
12982
- // {
12983
- // "actionType": "deleteItem",
12984
- // "args": {
12985
- // "index": "${index+','}" //这里不加逗号后续会报错,语法是逗号分隔可以删除多行
12986
- // },
12987
- // "componentId": props.id
12988
- // },
12989
- {
12990
- "actionType": "custom",
12991
- "script": onDeleteItemScript
12992
- }
12993
- ]
13247
+ "actions": await getButtonActions(props, "delete")
12994
13248
  }
12995
13249
  }
12996
13250
  };
@@ -13000,7 +13254,7 @@ const getAmisInputTableSchema = async (props) => {
13000
13254
  if (!props.id) {
13001
13255
  props.id = "steedos_input_table_" + props.name + "_" + Math.random().toString(36).substr(2, 9);
13002
13256
  }
13003
- let serviceId = `service_wrapper__${props.id}`;
13257
+ let serviceId = getComponentId("table_service", props.id);
13004
13258
  let buttonsForColumnOperations = [];
13005
13259
  let inlineEditMode = props.inlineEditMode;
13006
13260
  let showAsInlineEditMode = inlineEditMode && props.editable;
@@ -13030,7 +13284,7 @@ const getAmisInputTableSchema = async (props) => {
13030
13284
  buttonsForColumnOperations.push(buttonViewSchema);
13031
13285
  }
13032
13286
  if (props.removable) {
13033
- let buttonDeleteSchema = getButtonDelete(props);
13287
+ let buttonDeleteSchema = await getButtonDelete(props);
13034
13288
  buttonsForColumnOperations.push(buttonDeleteSchema);
13035
13289
  }
13036
13290
  let inputTableSchema = {
@@ -13091,24 +13345,22 @@ const getAmisInputTableSchema = async (props) => {
13091
13345
  "body": footerToolbar
13092
13346
  });
13093
13347
  }
13094
- // 不可以直接把headerToolbar unshift进schemaBody,因为它没有显示在label下面,而是显示在上面了,这没有意义
13348
+ // 直接把headerToolbar unshift进schemaBody,不会显示在label下面,而是显示在上面了,这个暂时没有解决办法,只能等amis 升级
13095
13349
  // 看起来amis官方后续会支持给input-table组件配置headerToolbar,见:https://github.com/baidu/amis/issues/7246
13096
- // let headerToolbar = clone(props.headerToolbar || []); //这里不clone的话,会造成死循环,应该是因为props属性变更会让组件重新渲染
13097
- // if (headerToolbar.length) {
13098
- // schemaBody.unshift({
13099
- // "type": "wrapper",
13100
- // "size": "none",
13101
- // "body": headerToolbar
13102
- // });
13103
- // }
13350
+ // 不过依然放开此功能的意义在于有的场景字段label本来就不需要显示出来,此时headerToolbar就有意义
13351
+ let headerToolbar = clone(props.headerToolbar || []); //这里不clone的话,会造成死循环,应该是因为props属性变更会让组件重新渲染
13352
+ if (headerToolbar.length) {
13353
+ schemaBody.unshift({
13354
+ "type": "wrapper",
13355
+ "size": "none",
13356
+ "body": headerToolbar
13357
+ });
13358
+ }
13104
13359
  let schema = {
13105
13360
  "type": "service",
13106
13361
  "body": schemaBody,
13107
13362
  "className": props.className,
13108
- "id": serviceId,
13109
- "data": {
13110
- "__wrapperServiceId": serviceId
13111
- }
13363
+ "id": serviceId
13112
13364
  };
13113
13365
  // console.log("===schema===", schema);
13114
13366
  return schema;