@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.cjs.js CHANGED
@@ -1653,6 +1653,7 @@ async function getQuickEditSchema(field, options){
1653
1653
  {
1654
1654
  "actionType": "custom",
1655
1655
  "script": `
1656
+
1656
1657
  var _display = _.cloneDeep(event.data._display);
1657
1658
  ${displayField}
1658
1659
  doAction({actionType: 'setValue', "args": {"value": {_display}},componentId: "${quickEditId}"});
@@ -2039,7 +2040,9 @@ async function getTableColumns(fields, options){
2039
2040
  if(!options.isLookup && !options.isInputTable){
2040
2041
  //将_display放入crud的columns中,可以通过setvalue修改行内数据域的_display,而不影响上层items的_display,用于批量编辑
2041
2042
  columns.push({name: '_display',type: 'static', width: 32, placeholder: "",id: "_display_${_index}", className: "hidden"});
2042
- columns.push({name: '_index',type: 'text', width: 32, placeholder: ""});
2043
+ if(!options.enable_tree){
2044
+ columns.push({name: '_index',type: 'text', width: 32, placeholder: ""});
2045
+ }
2043
2046
  }
2044
2047
  const allowEdit = options.permissions?.allowEdit && !options.isLookup && options.enable_inline_edit != false;
2045
2048
 
@@ -2890,7 +2893,21 @@ async function getTableApi(mainObject, fields, options){
2890
2893
 
2891
2894
  if(enable_tree){
2892
2895
  const records = payload.data.rows || [];
2893
- const getTreeOptions = SteedosUI.getTreeOptions
2896
+ const getTreeOptions = SteedosUI.getTreeOptions;
2897
+ const assignIndexToTreeRecords = function(tree, parentIndex) {
2898
+ tree.forEach(function (node, index) {
2899
+ // 构建当前节点的 _index
2900
+ var currentIndex = parentIndex ? parentIndex + '-' + (index + 1) : '' + (index + 1);
2901
+
2902
+ // 赋值给节点
2903
+ node._index = currentIndex;
2904
+
2905
+ // 如果有子节点,递归调用函数
2906
+ if (node.children && node.children.length > 0) {
2907
+ assignIndexToTreeRecords(node.children, currentIndex);
2908
+ }
2909
+ });
2910
+ };
2894
2911
  let isTreeOptionsComputed = false;
2895
2912
  if(records.length === 1 && records[0].children){
2896
2913
  isTreeOptionsComputed = true;
@@ -2898,6 +2915,7 @@ async function getTableApi(mainObject, fields, options){
2898
2915
  if(!isTreeOptionsComputed){
2899
2916
  // 如果api接口设置在缓存,缓存期间并不会重新请求接口,payload.data.rows是上次计算后的结果
2900
2917
  payload.data.rows = getTreeOptions(records,{"valueField":"_id"});
2918
+ assignIndexToTreeRecords(payload.data.rows, '');
2901
2919
  }
2902
2920
  try{
2903
2921
  setTimeout(() => {
@@ -8000,7 +8018,8 @@ function getObjectFooterToolbar(mainObject, formFactor, options) {
8000
8018
  {
8001
8019
  "type": "pagination",
8002
8020
  "maxButtons": 5,
8003
- "showPageInput": false
8021
+ "showPageInput": true,
8022
+ "layout": "total,pager,go"
8004
8023
  }
8005
8024
  ]
8006
8025
  }
@@ -8253,7 +8272,7 @@ async function getObjectCRUD(objectSchema, fields, options){
8253
8272
  let tableOptions = Object.assign({
8254
8273
  idFieldName: objectSchema.idFieldName, labelFieldName: labelFieldName,
8255
8274
  permissions:objectSchema.permissions,enable_inline_edit:objectSchema.enable_inline_edit,
8256
- crudId: listSchema.id || id
8275
+ crudId: listSchema.id || id, enable_tree: objectSchema.enable_tree
8257
8276
  }, options);
8258
8277
  tableOptions.amisData = createObject(options.amisData || {}, {});
8259
8278
  const table = await getTableSchema$1(fields, tableOptions);
@@ -11589,7 +11608,16 @@ async function convertSFieldToAmisField(field, readonly, ctx) {
11589
11608
  format:'YYYY-MM-DDT00:00:00.000[Z]',
11590
11609
  tpl: readonly ? getDateTpl(field) : null,
11591
11610
  // utc: true,
11592
- joinValues: false
11611
+ joinValues: false,
11612
+ "shortcuts": [
11613
+ "thismonth",
11614
+ "2monthsago",
11615
+ "3monthslater",
11616
+ "prevquarter",
11617
+ "thisquarter",
11618
+ "thisyear",
11619
+ "lastYear"
11620
+ ]
11593
11621
  };
11594
11622
  break;
11595
11623
  case 'date':
@@ -12000,6 +12028,8 @@ async function convertSFieldToAmisField(field, readonly, ctx) {
12000
12028
  let subFieldName = subField.name.replace(`${field.name}.$.`, '').replace(`${field.name}.`, '');
12001
12029
  if(subField.type === 'grid'){
12002
12030
  subField = await getGridFieldSubFields(subField, ctx.__formFields);
12031
+ }else if(subField.type === 'table'){
12032
+ subField = await getTabledFieldSubFields(subField, ctx.__formFields);
12003
12033
  }else {
12004
12034
  if(readonly){
12005
12035
  subFieldName = `${field.name}.${subFieldName}`;
@@ -12116,7 +12146,8 @@ async function getFieldSearchable(perField, permissionFields, ctx){
12116
12146
  fieldNamePrefix = `${fieldNamePrefix}between__`;
12117
12147
  }
12118
12148
  if(_field.type === 'datetime'){
12119
- _field.type = 'input-datetime-range';
12149
+ // 特意改为日期范围而不是日期时间范围,因为搜索时一般精确到日期就足够了,需要精确到日期时间范围需要在字段上配置amis属性来实现
12150
+ _field.type = 'input-date-range';
12120
12151
  _field.is_wide = true;
12121
12152
  fieldNamePrefix = `${fieldNamePrefix}between__`;
12122
12153
  }
@@ -12428,7 +12459,7 @@ async function getFormBody(permissionFields, formFields, ctx){
12428
12459
  * @Author: 殷亮辉 yinlianghui@hotoa.com
12429
12460
  * @Date: 2023-11-15 09:50:22
12430
12461
  * @LastEditors: 殷亮辉 yinlianghui@hotoa.com
12431
- * @LastEditTime: 2023-12-19 15:53:32
12462
+ * @LastEditTime: 2023-12-25 13:13:56
12432
12463
  */
12433
12464
 
12434
12465
  /**
@@ -12474,6 +12505,28 @@ function getInputTableCell(field, showAsInlineEditMode) {
12474
12505
  }
12475
12506
  }
12476
12507
 
12508
+ function getComponentId(name, tag) {
12509
+ let id = "";
12510
+ switch (name) {
12511
+ case "table_service":
12512
+ id = `service_wrapper__${tag}`;
12513
+ break;
12514
+ case "form_pagination":
12515
+ id = `service_popup_pagination_wrapper__${tag}`;
12516
+ break;
12517
+ case "form":
12518
+ id = `form_popup__${tag}`;
12519
+ break;
12520
+ case "dialog":
12521
+ id = `dialog_popup__${tag}`;
12522
+ break;
12523
+ default:
12524
+ id = `${name}__${tag}`;
12525
+ break;
12526
+ }
12527
+ return id;
12528
+ }
12529
+
12477
12530
  /**
12478
12531
  * @param {*} props
12479
12532
  * @param {*} mode edit/new/readonly
@@ -12521,17 +12574,35 @@ async function getInputTableColumns(props) {
12521
12574
  }
12522
12575
  }
12523
12576
 
12524
- function getFormPagination(props) {
12577
+ /**
12578
+ * @param {*} props input-table组件props
12579
+ * @param {*} mode edit/new/readonly
12580
+ * @returns 翻页组件
12581
+ */
12582
+ function getFormPagination(props, mode) {
12583
+ let showPagination = true;
12584
+ if(mode === "new" && !!!props.editable){
12585
+ //不允许编辑只允许新建时不应该让用户操作翻页
12586
+ showPagination = false;
12587
+ }
12588
+ let buttonPrevId = getComponentId("button_prev", props.id);
12589
+ let buttonNextId = getComponentId("button_next", props.id);
12590
+ let formId = getComponentId("form", props.id);
12591
+ let tableServiceId = getComponentId("table_service", props.id);
12592
+ let formPaginationId = getComponentId("form_pagination", props.id);
12525
12593
  let onPageChangeScript = `
12526
12594
  let scope = event.context.scoped;
12527
- let __paginationServiceId = event.data.__paginationServiceId;
12528
- let __wrapperServiceId = event.data.__wrapperServiceId;
12529
- let __formId = event.data.__formId;
12595
+ let __paginationServiceId = "${formPaginationId}";
12596
+ let __wrapperServiceId = "${tableServiceId}";
12597
+ let __formId = "${formId}";
12530
12598
  let fieldValue = event.data.__tableItems;//这里不可以_.cloneDeep,因为翻页form中用的是event.data.__tableItems,直接变更其值即可改变表单中的值
12531
12599
  let pageChangeDirection = context.props.pageChangeDirection;
12600
+ // event.data中的index和__page分别表示当前要把表单数据提交到的行索引和用于标定下一页页码的当前页页码
12601
+ // 一般来说__page = index + 1,但是可以让event.data中传入__page和index值不是这种联系。
12602
+ // 比如__page设置为3,index设置为0表示把当前表单数据提交到第一页,但是跳转到第4页,弹出的表单中底下的新增和复制按钮依赖了此功能
12603
+ // let currentPage = currentIndex + 1;
12532
12604
  let currentPage = event.data.__page;
12533
12605
  let currentIndex = event.data.index;
12534
-
12535
12606
  // 翻页到下一页之前需要先把当前页改动的内容保存到中间变量__tableItems中
12536
12607
  let currentFormValues = scope.getComponentById(__formId).getValues();
12537
12608
  fieldValue[currentIndex] = currentFormValues;
@@ -12576,7 +12647,8 @@ function getFormPagination(props) {
12576
12647
  `;
12577
12648
  return {
12578
12649
  "type": "wrapper",
12579
- "className": "py-2",
12650
+ "size": "none",
12651
+ "className": "mr-1",
12580
12652
  "body": [
12581
12653
  {
12582
12654
  "type": "button",
@@ -12584,8 +12656,9 @@ function getFormPagination(props) {
12584
12656
  "icon": `fa fa-angle-left`,
12585
12657
  "level": "link",
12586
12658
  "pageChangeDirection": "prev",
12587
- "disabledOn": "${__page <= 1}",
12659
+ "disabledOn": showPagination ? "${__page <= 1}" : "true",
12588
12660
  "size": "sm",
12661
+ "id": buttonPrevId,
12589
12662
  "onEvent": {
12590
12663
  "click": {
12591
12664
  "actions": [
@@ -12599,7 +12672,7 @@ function getFormPagination(props) {
12599
12672
  },
12600
12673
  {
12601
12674
  "type": "tpl",
12602
- "tpl": "${__page}/${__total}"
12675
+ "tpl": "${__page}/${__tableItems.length}"
12603
12676
  },
12604
12677
  {
12605
12678
  "type": "button",
@@ -12607,8 +12680,9 @@ function getFormPagination(props) {
12607
12680
  "icon": `fa fa-angle-right`,
12608
12681
  "level": "link",
12609
12682
  "pageChangeDirection": "next",
12610
- "disabledOn": "${__page >= __total}",
12683
+ "disabledOn": showPagination ? "${__page >= __tableItems.length}" : "true",
12611
12684
  "size": "sm",
12685
+ "id": buttonNextId,
12612
12686
  "onEvent": {
12613
12687
  "click": {
12614
12688
  "actions": [
@@ -12628,11 +12702,13 @@ function getFormPagination(props) {
12628
12702
  * 传入formSchema输出带翻页容器的wrapper
12629
12703
  * @param {*} props input-table组件props
12630
12704
  * @param {*} form formSchema
12631
- * @param {*} mode edit/readonly
12705
+ * @param {*} mode edit/new/readonly
12632
12706
  * @returns 带翻页容器的wrapper
12633
12707
  */
12634
12708
  function getFormPaginationWrapper(props, form, mode) {
12635
- let serviceId = `service_popup_pagination_wrapper__${props.id}`;
12709
+ // console.log("==getFormPaginationWrapper===", props, mode);
12710
+ let serviceId = getComponentId("form_pagination", props.id);
12711
+ let tableServiceId = getComponentId("table_service", props.id);
12636
12712
  let innerForm = Object.assign({}, form, {
12637
12713
  "data": {
12638
12714
  // 这里加__super前缀是因为__parentForm变量(即主表单)中可能会正好有名为index的字段
@@ -12644,9 +12720,9 @@ function getFormPaginationWrapper(props, form, mode) {
12644
12720
  {
12645
12721
  "type": "wrapper",
12646
12722
  "size": "none",
12647
- "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",
12723
+ "className": "flex justify-end sticky top-0 right-0 left-0 z-20 bg-white -mt-2",
12648
12724
  "body": [
12649
- getFormPagination(props)
12725
+ getFormPagination(props, mode)
12650
12726
  ]
12651
12727
  },
12652
12728
  {
@@ -12667,11 +12743,29 @@ function getFormPaginationWrapper(props, form, mode) {
12667
12743
  // 处理思路是每次弹出form之前先把其__tableItems同步更新为最新值,这样就能在弹出form中包含单元格中做的修改
12668
12744
  // 注意:service init事件只会在每次弹出窗口时才执行,在触发翻页时并不会触发service init事件
12669
12745
  let scope = event.context.scoped;
12670
- let __wrapperServiceId = event.data.__wrapperServiceId;
12746
+ let __wrapperServiceId = "${tableServiceId}";
12671
12747
  let wrapperService = scope.getComponentById(__wrapperServiceId);
12672
12748
  let wrapperServiceData = wrapperService.getData();
12673
- let lastestFieldValue = wrapperServiceData["${props.name}"];//这里不可以用event.data["${props.name}"]因为amis input talbe有一层单独的作用域,其值会延迟一拍
12749
+ let lastestFieldValue = wrapperServiceData["${props.name}"] || [];//这里不可以用event.data["${props.name}"]因为amis input talbe有一层单独的作用域,其值会延迟一拍
12674
12750
  //不可以直接像event.data.__tableItems = lastestFieldValue; 这样整个赋值,否则作用域会断
12751
+ let mode = "${mode}";
12752
+ if(mode === "new"){
12753
+ // 点击子表组件底部新增按钮时新增一条空白行并自动翻页到新增行
12754
+ // 注意点击弹出的子表行详细表单中的新增按钮不会进此service init事件函数中
12755
+ let newItem = {};
12756
+ event.data.__tableItems.push(newItem);
12757
+ lastestFieldValue.push(newItem);
12758
+ event.data.index = lastestFieldValue.length - 1;
12759
+ event.data.__page = lastestFieldValue.length;
12760
+ // 这里新增空白行时要把值同步保存到子表组件中,如果不同步保存的话,用户点击弹出表单右上角的关闭窗口时不会自动删除这里自动增加的空白行,同步后可以让用户手动删除此行
12761
+ doAction({
12762
+ "componentId": "${props.id}",
12763
+ "actionType": "setValue",
12764
+ "args": {
12765
+ "value": lastestFieldValue
12766
+ }
12767
+ });
12768
+ }
12675
12769
  event.data.__tableItems.forEach(function(n,i){
12676
12770
  event.data.__tableItems[i] = lastestFieldValue[i];
12677
12771
  });
@@ -12696,9 +12790,9 @@ function getFormPaginationWrapper(props, form, mode) {
12696
12790
  "data": {
12697
12791
  "__page": "${index + 1}",
12698
12792
  // "__total": `\${${props.name}.length}`,
12699
- "__total": "${__tableItems.length}",
12700
- "__paginationServiceId": serviceId,
12701
- "__formId": form.id
12793
+ // "__total": "${__tableItems.length}",
12794
+ // "__paginationServiceId": serviceId,
12795
+ // "__formId": form.id
12702
12796
  },
12703
12797
  "onEvent": {
12704
12798
  "init": {
@@ -12721,8 +12815,8 @@ function getFormPaginationWrapper(props, form, mode) {
12721
12815
  async function getForm(props, mode = "edit", formId) {
12722
12816
  let formFields = getFormFields(props, mode);
12723
12817
  let body = await getFormBody(null, formFields);
12724
- if(!formId){
12725
- formId = `form_popup__${props.id}`;
12818
+ if (!formId) {
12819
+ formId = getComponentId("form", props.id);
12726
12820
  }
12727
12821
  let schema = {
12728
12822
  "type": "form",
@@ -12735,7 +12829,8 @@ async function getForm(props, mode = "edit", formId) {
12735
12829
  "canAccessSuperData": false,
12736
12830
  "className": "steedos-object-form steedos-amis-form"
12737
12831
  };
12738
- if (mode === "edit") {
12832
+ if (mode === "edit" || mode === "new") {
12833
+ // 新增行弹出编辑行表单,在弹出之前已经不用先增加一行,因为在翻页service初始化的时候会判断mode为new时自动新增一行
12739
12834
  let onEditItemSubmitScript = `
12740
12835
  // let fieldValue = _.cloneDeep(event.data["${props.name}"]);
12741
12836
  let fieldValue = event.data.__tableItems;//这里不可以_.cloneDeep,因为翻页form中用的是event.data.__tableItems,直接变更其值即可改变表单中的值
@@ -12774,103 +12869,366 @@ async function getForm(props, mode = "edit", formId) {
12774
12869
  }
12775
12870
  });
12776
12871
  }
12777
- else if (mode === "new") {
12778
- let onNewItemSubmitScript = `
12779
- let newItem = JSON.parse(JSON.stringify(event.data));
12780
- if(event.data["${props.name}"]){
12781
- // let fieldValue = event.data.__tableItems;
12782
- // 这里不用__tableItems是因为新建的时候没有翻页,里面没有也不需要走__tableItems变量
12783
- let fieldValue = event.data["${props.name}"];
12784
- fieldValue.push(newItem);
12785
- doAction({
12786
- "componentId": "${props.id}",
12787
- "actionType": "setValue",
12788
- "args": {
12789
- "value": fieldValue
12790
- }
12791
- });
12872
+ // else if (mode === "new") {
12873
+ // let onNewItemSubmitScript = `
12874
+ // let newItem = JSON.parse(JSON.stringify(event.data));
12875
+ // if(event.data["${props.name}"]){
12876
+ // // let fieldValue = event.data.__tableItems;
12877
+ // // 这里不用__tableItems是因为新建的时候没有翻页,里面没有也不需要走__tableItems变量
12878
+ // let fieldValue = event.data["${props.name}"];
12879
+ // fieldValue.push(newItem);
12880
+ // doAction({
12881
+ // "componentId": "${props.id}",
12882
+ // "actionType": "setValue",
12883
+ // "args": {
12884
+ // "value": fieldValue
12885
+ // }
12886
+ // });
12887
+ // }
12888
+ // else{
12889
+ // // 这里不可以执行event.data["${props.name}"]=[newItem],数据域会断掉
12890
+ // doAction({
12891
+ // "componentId": "${props.id}",
12892
+ // "actionType": "setValue",
12893
+ // "args": {
12894
+ // "value": [newItem]
12895
+ // }
12896
+ // });
12897
+ // }
12898
+ // `;
12899
+ // Object.assign(schema, {
12900
+ // "onEvent": {
12901
+ // "submit": {
12902
+ // "weight": 0,
12903
+ // "actions": [
12904
+ // {
12905
+ // "actionType": "custom",
12906
+ // "script": onNewItemSubmitScript
12907
+ // },
12908
+ // // {
12909
+ // // "componentId": props.id,
12910
+ // // "actionType": "addItem",//input-table组件的needConfirm属性为true时,addItem动作会把新加的行显示为编辑状态,所以只能使用上面的custom script来setValue实现添加行
12911
+ // // "args": {
12912
+ // // "index": `\${${props.name}.length || 9000}`,//这里加9000是因为字段如果没放在form组件内,props.name.length拿不到值
12913
+ // // "item": {
12914
+ // // "&": "$$"
12915
+ // // }
12916
+ // // }
12917
+ // // }
12918
+ // ]
12919
+ // }
12920
+ // }
12921
+ // });
12922
+ // }
12923
+ schema = getFormPaginationWrapper(props, schema, mode);
12924
+ return schema;
12925
+ }
12926
+
12927
+
12928
+ /**
12929
+ * 编辑、新增、删除、查看按钮actions
12930
+ * @param {*} props
12931
+ * @param {*} mode edit/new/readonly/delete
12932
+ */
12933
+ async function getButtonActions(props, mode) {
12934
+ let actions = [];
12935
+ let formId = getComponentId("form", props.id);
12936
+ let dialogId = getComponentId("dialog", props.id);
12937
+ let buttonNextId = getComponentId("button_next", props.id);
12938
+ let formPaginationId = getComponentId("form_pagination", props.id);
12939
+ if (mode == "new" || mode == "edit") {
12940
+ // let actionShowNewDialog = {
12941
+ // "actionType": "dialog",
12942
+ // "dialog": {
12943
+ // "type": "dialog",
12944
+ // "title": "新增行",
12945
+ // "body": [
12946
+ // await getForm(props, "new", formId)
12947
+ // ],
12948
+ // "size": "lg",
12949
+ // "showCloseButton": true,
12950
+ // "showErrorMsg": true,
12951
+ // "showLoading": true,
12952
+ // "className": "app-popover",
12953
+ // "closeOnEsc": false,
12954
+ // "onEvent": {
12955
+ // "confirm": {
12956
+ // "actions": [
12957
+ // {
12958
+ // "actionType": "validate",
12959
+ // "componentId": formId
12960
+ // },
12961
+ // {
12962
+ // "preventDefault": true,
12963
+ // "expression": "${event.data.validateResult.error}" //触发表单校验结果会存入validateResult,amis 3.2不支持,高版本比如 3.5.3支持
12964
+ // }
12965
+ // ]
12966
+ // }
12967
+ // }
12968
+ // }
12969
+ // };
12970
+ let onSaveAndNewItemScript = `
12971
+ let scope = event.context.scoped;
12972
+ let fieldValue = event.data.__tableItems;//这里不可以_.cloneDeep,因为翻页form中用的是event.data.__tableItems,直接变更其值即可改变表单中的值
12973
+ // 新建一条空白行并保存到子表组件
12974
+ fieldValue.push({});
12975
+ doAction({
12976
+ "componentId": "${props.id}",
12977
+ "actionType": "setValue",
12978
+ "args": {
12979
+ "value": fieldValue
12980
+ }
12981
+ });
12982
+ let buttonNextId = "${buttonNextId}";
12983
+ let __paginationServiceId = "${formPaginationId}";
12984
+ let __paginationData = scope.getComponentById(__paginationServiceId).getData();
12985
+ event.data.index = __paginationData.index;
12986
+ event.data.__page = fieldValue.length - 1;//这里不可以用Object.assign否则,event.data中上层作用域数据会丢失
12987
+ // 触发翻页按钮事件,实现保存当前页数据并跳转到最后一行
12988
+ scope.getComponentById(buttonNextId).props.dispatchEvent("click", event.data);
12989
+ `;
12990
+ let onSaveAndCopyItemScript = `
12991
+ let scope = event.context.scoped;
12992
+ let __formId = "${formId}";
12993
+ // let newItem = JSON.parse(JSON.stringify(event.data));
12994
+ let newItem = scope.getComponentById(__formId).getValues();//这里不可以用event.data,因为其拿到的是弹出表单时的初始值,不是用户实时填写的数据
12995
+ let fieldValue = event.data.__tableItems;//这里不可以_.cloneDeep,因为翻页form中用的是event.data.__tableItems,直接变更其值即可改变表单中的值
12996
+ // 复制当前页数据到新建行并保存到子表组件
12997
+ fieldValue.push(newItem);
12998
+ doAction({
12999
+ "componentId": "${props.id}",
13000
+ "actionType": "setValue",
13001
+ "args": {
13002
+ "value": fieldValue
13003
+ }
13004
+ });
13005
+ let buttonNextId = "${buttonNextId}";
13006
+ let __paginationServiceId = "${formPaginationId}";
13007
+ let __paginationData = scope.getComponentById(__paginationServiceId).getData();
13008
+ event.data.index = __paginationData.index;
13009
+ event.data.__page = fieldValue.length - 1;//这里不可以用Object.assign否则,event.data中上层作用域数据会丢失
13010
+ // 触发翻页按钮事件,实现保存当前页数据并跳转到最后一行
13011
+ scope.getComponentById(buttonNextId).props.dispatchEvent("click", event.data);
13012
+ `;
13013
+ let dialogButtons = [
13014
+ {
13015
+ "type": "button",
13016
+ "label": "完成",
13017
+ "actionType": "confirm",
13018
+ "level": "primary"
12792
13019
  }
12793
- else{
12794
- // 这里不可以执行event.data["${props.name}"]=[newItem],数据域会断掉
12795
- doAction({
12796
- "componentId": "${props.id}",
12797
- "actionType": "setValue",
12798
- "args": {
12799
- "value": [newItem]
13020
+ ];
13021
+ if(props.addable){
13022
+ // 有新增行权限时额外添加新增和复制按钮
13023
+ dialogButtons = [
13024
+ {
13025
+ "type": "button",
13026
+ "label": "新增",
13027
+ "tooltip": "保存并新增一行,即保存当前行数据并新增一条空白行",
13028
+ "onEvent": {
13029
+ "click": {
13030
+ "actions": [
13031
+ {
13032
+ "actionType": "custom",
13033
+ "script": onSaveAndNewItemScript
13034
+ }
13035
+ ]
13036
+ }
12800
13037
  }
12801
- });
13038
+ },
13039
+ {
13040
+ "type": "button",
13041
+ "label": "复制",
13042
+ "tooltip": "复制并新增一行,即保存当前行数据并复制当前行数据到新增行",
13043
+ "onEvent": {
13044
+ "click": {
13045
+ "actions": [
13046
+ {
13047
+ "actionType": "custom",
13048
+ "script": onSaveAndCopyItemScript
13049
+ }
13050
+ ]
13051
+ }
13052
+ }
13053
+ },
13054
+ dialogButtons[0]
13055
+ ];
13056
+ }
13057
+ let actionShowEditDialog = {
13058
+ "actionType": "dialog",
13059
+ "dialog": {
13060
+ "type": "dialog",
13061
+ "id": dialogId,
13062
+ "title": `\${uiSchema.fields.${props.name}.label} 明细`,
13063
+ "body": [
13064
+ await getForm(props, mode, formId)
13065
+ ],
13066
+ "size": "lg",
13067
+ "showCloseButton": true,
13068
+ "showErrorMsg": true,
13069
+ "showLoading": true,
13070
+ "className": "app-popover",
13071
+ "closeOnEsc": false,
13072
+ "data": {
13073
+ // 这里必须加data数据映射,否则翻页功能中取__tableItems值时会乱,比如翻页编辑后会把上一页中没改过的字段值带过去
13074
+ // 额外把华炎魔方主表记录ObjectForm中的字段值从record变量中映射到子表form中,因为子表lookup字段filtersFunction中可能依赖了主表记录中的字段值,比如“工作流规则”对象“时间触发器”字段中的“日期字段”字段
13075
+ // 额外把global、uiSchema也映射过去,有可能要用,后续需要用到其他变更可以这里加映射
13076
+ // "&": "${record || {}}",
13077
+ // 换成从__super来映射上级表单数据是因为对象列表视图界面中每行下拉菜单中的编辑按钮弹出的表单中的子表所在作用域中没有record变量
13078
+ // 映射到中间变量__parentForm而不是直接用&展开映射是为了避免表单中字段名与作用域中变量重名
13079
+ // "__parentForm": "${__super.__super || {}}",
13080
+ "__parentForm": mode == "new" ? "$$" : "${__super.__super || {}}",
13081
+ "global": "${global}",
13082
+ "uiSchema": "${uiSchema}",
13083
+ "index": "${index}",
13084
+ // "__tableItems": `\${${props.name}}`
13085
+ // 为了解决"弹出的dialog窗口中子表组件会影响页面布局界面中父作用域字段值",比如设计字段布局微页面中的设置分组功能,弹出的就是子表dialog
13086
+ // 所以这里使用json|toJson转一次,断掉event.data.__tableItems与上层任用域中props.name的联系
13087
+ // "__tableItems": `\${${props.name}|json|toJson}`
13088
+ "__tableItems": `\${(${props.name} || [])|json|toJson}`
13089
+ },
13090
+ "actions": dialogButtons,
13091
+ "onEvent": {
13092
+ "confirm": {
13093
+ "actions": [
13094
+ {
13095
+ "actionType": "validate",
13096
+ "componentId": formId
13097
+ },
13098
+ {
13099
+ "preventDefault": true,
13100
+ "expression": "${event.data.validateResult.error}" //触发表单校验结果会存入validateResult,amis 3.2不支持,高版本比如 3.5.3支持
13101
+ }
13102
+ ]
13103
+ }
13104
+ }
12802
13105
  }
12803
- `;
12804
- Object.assign(schema, {
12805
- "onEvent": {
12806
- "submit": {
12807
- "weight": 0,
12808
- "actions": [
12809
- {
12810
- "actionType": "custom",
12811
- "script": onNewItemSubmitScript
12812
- },
12813
- // {
12814
- // "componentId": props.id,
12815
- // "actionType": "addItem",//input-table组件的needConfirm属性为true时,addItem动作会把新加的行显示为编辑状态,所以只能使用上面的custom script来setValue实现添加行
12816
- // "args": {
12817
- // "index": `\${${props.name}.length || 9000}`,//这里加9000是因为字段如果没放在form组件内,props.name.length拿不到值
12818
- // "item": {
12819
- // "&": "$$"
12820
- // }
12821
- // }
12822
- // }
12823
- ]
13106
+ };
13107
+ if (props.dialog) {
13108
+ Object.assign(actionShowEditDialog.dialog, props.dialog);
13109
+ }
13110
+ if (mode == "new") {
13111
+ `
13112
+ let newItem = {};
13113
+ if(event.data["${props.name}"]){
13114
+ // let fieldValue = event.data.__tableItems;
13115
+ // 这里不用__tableItems是因为新建的时候没有翻页,里面没有也不需要走__tableItems变量
13116
+ // let fieldValue = _.clone(event.data["${props.name}"]);
13117
+ let fieldValue = event.data["${props.name}"];
13118
+ fieldValue.push(newItem);
13119
+ doAction({
13120
+ "componentId": "${props.id}",
13121
+ "actionType": "setValue",
13122
+ "args": {
13123
+ "value": fieldValue
13124
+ }
13125
+ });
13126
+ event.data.index = fieldValue.length - 1;
13127
+ }
13128
+ else{
13129
+ // 这里不可以执行event.data["${props.name}"]=[newItem],数据域会断掉
13130
+ doAction({
13131
+ "componentId": "${props.id}",
13132
+ "actionType": "setValue",
13133
+ "args": {
13134
+ "value": [newItem]
13135
+ }
13136
+ });
13137
+ event.data.index = 1;
13138
+ }
13139
+ `;
13140
+ // 新增行时不需要在弹出编辑表单前先加一行,因为会在编辑表单所在service初始化时判断到是新增就自动增加一行,因为这里拿不到event.data.__tableItems,也无法变更其值
13141
+ // actions = [actionNewLine, actionShowEditDialog];
13142
+ actions = [actionShowEditDialog];
13143
+ }
13144
+ else if (mode == "edit") {
13145
+ actions = [actionShowEditDialog];
13146
+ }
13147
+ }
13148
+ else if (mode == "readonly") {
13149
+ actions = [
13150
+ {
13151
+ "actionType": "dialog",
13152
+ "dialog": {
13153
+ "type": "dialog",
13154
+ "title": `\${uiSchema.fields.${props.name}.label} 明细`,
13155
+ "body": [
13156
+ await getForm(props, "readonly")
13157
+ ],
13158
+ "size": "lg",
13159
+ "showCloseButton": true,
13160
+ "showErrorMsg": true,
13161
+ "showLoading": true,
13162
+ "className": "app-popover",
13163
+ "closeOnEsc": false,
13164
+ "actions": [],
13165
+ "data": {
13166
+ // 这里必须加data数据映射,否则翻页功能中取__tableItems值时会乱,比如翻页编辑后会把上一页中没改过的字段值带过去
13167
+ // 额外把华炎魔方主表记录ObjectForm中的字段值从record变量中映射到子表form中,因为子表lookup字段filtersFunction中可能依赖了主表记录中的字段值,比如“工作流规则”对象“时间触发器”字段中的“日期字段”字段
13168
+ // 额外把global、uiSchema也映射过去,有可能要用,后续需要用到其他变更可以这里加映射
13169
+ // "&": "${record || {}}",
13170
+ // 换成从__super来映射上级表单数据是因为对象列表视图界面中每行下拉菜单中的编辑按钮弹出的表单中的子表所在作用域中没有record变量
13171
+ // 映射到中间变量__parentForm而不是直接用&展开映射是为了避免表单中字段名与作用域中变量重名
13172
+ // "__parentForm": "${__super.__super || {}}",
13173
+ "__parentForm": "${__super.__super || {}}",
13174
+ "global": "${global}",
13175
+ "uiSchema": "${uiSchema}",
13176
+ "index": "${index}",
13177
+ // "__tableItems": `\${${props.name}}`
13178
+ // 为了解决"弹出的dialog窗口中子表组件会影响页面布局界面中父作用域字段值",比如设计字段布局微页面中的设置分组功能,弹出的就是子表dialog
13179
+ // 所以这里使用json|toJson转一次,断掉event.data.__tableItems与上层任用域中props.name的联系
13180
+ // "__tableItems": `\${${props.name}|json|toJson}`
13181
+ "__tableItems": `\${(${props.name} || [])|json|toJson}`
13182
+ },
12824
13183
  }
12825
13184
  }
12826
- });
13185
+ ];
12827
13186
  }
12828
- if (mode === "edit" || mode === "readonly") {
12829
- schema = getFormPaginationWrapper(props, schema);
13187
+ else if (mode == "delete") {
13188
+ let tableServiceId = getComponentId("table_service", props.id);
13189
+ let onDeleteItemScript = `
13190
+ // let fieldValue = event.data["${props.name}"];
13191
+ let scope = event.context.scoped;
13192
+ let __wrapperServiceId = "${tableServiceId}";
13193
+ let wrapperService = scope.getComponentById(__wrapperServiceId);
13194
+ let wrapperServiceData = wrapperService.getData();
13195
+ // 这里不可以用event.data["${props.name}"]因为amis input talbe有一层单独的作用域,其值会延迟一拍
13196
+ // 这里_.clone是因为字段设计布局设置分组这种弹出窗口中的子表组件,直接删除后,点取消无法还原
13197
+ let lastestFieldValue = _.clone(wrapperServiceData["${props.name}"]);
13198
+ lastestFieldValue.splice(event.data.index, 1);
13199
+ doAction({
13200
+ "componentId": "${props.id}",
13201
+ "actionType": "setValue",
13202
+ "args": {
13203
+ "value": lastestFieldValue
13204
+ }
13205
+ });
13206
+ `;
13207
+ actions = [
13208
+ // {
13209
+ // "actionType": "deleteItem",
13210
+ // "args": {
13211
+ // "index": "${index+','}" //这里不加逗号后续会报错,语法是逗号分隔可以删除多行
13212
+ // },
13213
+ // "componentId": props.id
13214
+ // },
13215
+ {
13216
+ "actionType": "custom",
13217
+ "script": onDeleteItemScript
13218
+ }
13219
+ ];
12830
13220
  }
12831
- return schema;
13221
+ return actions;
12832
13222
  }
12833
13223
 
12834
13224
  async function getButtonNew(props) {
12835
- let formId = `form_popup__${props.id}`;
12836
13225
  return {
12837
13226
  "label": "新增",
12838
13227
  "type": "button",
12839
13228
  "icon": "fa fa-plus",
12840
13229
  "onEvent": {
12841
13230
  "click": {
12842
- "actions": [
12843
- {
12844
- "actionType": "dialog",
12845
- "dialog": {
12846
- "type": "dialog",
12847
- "title": "新增行",
12848
- "body": [
12849
- await getForm(props, "new", formId)
12850
- ],
12851
- "size": "lg",
12852
- "showCloseButton": true,
12853
- "showErrorMsg": true,
12854
- "showLoading": true,
12855
- "className": "app-popover",
12856
- "closeOnEsc": false,
12857
- "onEvent": {
12858
- "confirm": {
12859
- "actions": [
12860
- {
12861
- "actionType": "validate",
12862
- "componentId": formId
12863
- },
12864
- {
12865
- "preventDefault": true,
12866
- "expression": "${event.data.validateResult.error}" //触发表单校验结果会存入validateResult,amis 3.2不支持,高版本比如 3.5.3支持
12867
- }
12868
- ]
12869
- }
12870
- }
12871
- }
12872
- }
12873
- ]
13231
+ "actions": await getButtonActions(props, "new")
12874
13232
  }
12875
13233
  },
12876
13234
  "level": "primary"
@@ -12878,60 +13236,14 @@ async function getButtonNew(props) {
12878
13236
  }
12879
13237
 
12880
13238
  async function getButtonEdit(props, showAsInlineEditMode) {
12881
- let formId = `form_popup__${props.id}`;
12882
13239
  return {
12883
13240
  "type": "button",
12884
13241
  "label": "",
12885
- "icon": `fa fa-${showAsInlineEditMode ? "expand" : "pencil"}`,//inline edit模式时显示为放开按钮,只读时显示为笔按钮
13242
+ "icon": `fa fa-${showAsInlineEditMode ? "expand-alt" : "pencil"}`,//inline edit模式时显示为放开按钮,只读时显示为笔按钮
12886
13243
  "level": "link",
12887
13244
  "onEvent": {
12888
13245
  "click": {
12889
- "actions": [
12890
- {
12891
- "actionType": "dialog",
12892
- "dialog": {
12893
- "type": "dialog",
12894
- "title": "编辑行",
12895
- "body": [
12896
- await getForm(props, "edit", formId)
12897
- ],
12898
- "size": "lg",
12899
- "showCloseButton": true,
12900
- "showErrorMsg": true,
12901
- "showLoading": true,
12902
- "className": "app-popover",
12903
- "closeOnEsc": false,
12904
- "data": {
12905
- // 这里必须加data数据映射,否则翻页功能中取__tableItems值时会乱,比如翻页编辑后会把上一页中没改过的字段值带过去
12906
- // 额外把华炎魔方主表记录ObjectForm中的字段值从record变量中映射到子表form中,因为子表lookup字段filtersFunction中可能依赖了主表记录中的字段值,比如“工作流规则”对象“时间触发器”字段中的“日期字段”字段
12907
- // 额外把global、uiSchema也映射过去,有可能要用,后续需要用到其他变更可以这里加映射
12908
- // "&": "${record || {}}",
12909
- // 换成从__super来映射上级表单数据是因为对象列表视图界面中每行下拉菜单中的编辑按钮弹出的表单中的子表所在作用域中没有record变量
12910
- // 映射到中间变量__parentForm而不是直接用&展开映射是为了避免表单中字段名与作用域中变量重名
12911
- "__parentForm": "${__super.__super || {}}",
12912
- "global": "${global}",
12913
- "uiSchema": "${uiSchema}",
12914
- "index": "${index}",
12915
- "__tableItems": `\${${props.name}}`,
12916
- "__wrapperServiceId": "${__wrapperServiceId}"
12917
- },
12918
- "onEvent": {
12919
- "confirm": {
12920
- "actions": [
12921
- {
12922
- "actionType": "validate",
12923
- "componentId": formId
12924
- },
12925
- {
12926
- "preventDefault": true,
12927
- "expression": "${event.data.validateResult.error}" //触发表单校验结果会存入validateResult,amis 3.2不支持,高版本比如 3.5.3支持
12928
- }
12929
- ]
12930
- }
12931
- }
12932
- }
12933
- }
12934
- ]
13246
+ "actions": await getButtonActions(props, "edit")
12935
13247
  }
12936
13248
  }
12937
13249
  };
@@ -12941,83 +13253,25 @@ async function getButtonView(props) {
12941
13253
  return {
12942
13254
  "type": "button",
12943
13255
  "label": "",
12944
- "icon": "fa fa-expand",//fa-external-link
13256
+ "icon": "fa fa-expand-alt",//fa-external-link
12945
13257
  "level": "link",
12946
13258
  "onEvent": {
12947
13259
  "click": {
12948
- "actions": [
12949
- {
12950
- "actionType": "dialog",
12951
- "dialog": {
12952
- "type": "dialog",
12953
- "title": "查看行",
12954
- "body": [
12955
- await getForm(props, "readonly")
12956
- ],
12957
- "size": "lg",
12958
- "showCloseButton": true,
12959
- "showErrorMsg": true,
12960
- "showLoading": true,
12961
- "className": "app-popover",
12962
- "closeOnEsc": false,
12963
- "actions": [],
12964
- "data": {
12965
- // 这里必须加data数据映射,否则翻页功能中取__tableItems值时会乱,比如翻页编辑后会把上一页中没改过的字段值带过去
12966
- // 额外把华炎魔方主表记录ObjectForm中的字段值从formData变量中映射到子表form中,因为子表lookup字段filtersFunction中可能依赖了主表记录中的字段值,比如“工作流规则”对象“时间触发器”字段中的“日期字段”字段
12967
- // global、uiSchema等常用变量本来就在formData变量已经存在了,无需另外映射
12968
- // "&": "${formData || {}}",
12969
- // 换成从__super来映射上级表单数据是因为对象列表视图界面中每行下拉菜单中的编辑按钮弹出的表单中的子表所在作用域中没有formData变量
12970
- // 映射到中间变量__parentForm而不是直接用&展开映射是为了避免表单中字段名与作用域中变量重名
12971
- "__parentForm": "${__super.__super || {}}",
12972
- "index": "${index}",
12973
- "__tableItems": `\${${props.name}}`,
12974
- "__wrapperServiceId": "${__wrapperServiceId}"
12975
- }
12976
- }
12977
- }
12978
- ]
13260
+ "actions": await getButtonActions(props, "readonly")
12979
13261
  }
12980
13262
  }
12981
13263
  };
12982
13264
  }
12983
13265
 
12984
- function getButtonDelete(props) {
12985
- let onDeleteItemScript = `
12986
- // let fieldValue = event.data["${props.name}"];
12987
- let scope = event.context.scoped;
12988
- let __wrapperServiceId = event.data.__wrapperServiceId;
12989
- let wrapperService = scope.getComponentById(__wrapperServiceId);
12990
- let wrapperServiceData = wrapperService.getData();
12991
- let lastestFieldValue = wrapperServiceData["${props.name}"];//这里不可以用event.data["${props.name}"]因为amis input talbe有一层单独的作用域,其值会延迟一拍
12992
- lastestFieldValue.splice(event.data.index, 1);
12993
- doAction({
12994
- "componentId": "${props.id}",
12995
- "actionType": "setValue",
12996
- "args": {
12997
- "value": lastestFieldValue
12998
- }
12999
- });
13000
- `;
13266
+ async function getButtonDelete(props) {
13001
13267
  return {
13002
13268
  "type": "button",
13003
13269
  "label": "",
13004
- "icon": "fa fa-minus",
13270
+ "icon": "fa fa-trash-alt",//不可以用fa-trash-o,因为设计字段布局界面中弹出的设置分组列表中显示不了这个图标
13005
13271
  "level": "link",
13006
13272
  "onEvent": {
13007
13273
  "click": {
13008
- "actions": [
13009
- // {
13010
- // "actionType": "deleteItem",
13011
- // "args": {
13012
- // "index": "${index+','}" //这里不加逗号后续会报错,语法是逗号分隔可以删除多行
13013
- // },
13014
- // "componentId": props.id
13015
- // },
13016
- {
13017
- "actionType": "custom",
13018
- "script": onDeleteItemScript
13019
- }
13020
- ]
13274
+ "actions": await getButtonActions(props, "delete")
13021
13275
  }
13022
13276
  }
13023
13277
  };
@@ -13027,7 +13281,7 @@ const getAmisInputTableSchema = async (props) => {
13027
13281
  if (!props.id) {
13028
13282
  props.id = "steedos_input_table_" + props.name + "_" + Math.random().toString(36).substr(2, 9);
13029
13283
  }
13030
- let serviceId = `service_wrapper__${props.id}`;
13284
+ let serviceId = getComponentId("table_service", props.id);
13031
13285
  let buttonsForColumnOperations = [];
13032
13286
  let inlineEditMode = props.inlineEditMode;
13033
13287
  let showAsInlineEditMode = inlineEditMode && props.editable;
@@ -13057,7 +13311,7 @@ const getAmisInputTableSchema = async (props) => {
13057
13311
  buttonsForColumnOperations.push(buttonViewSchema);
13058
13312
  }
13059
13313
  if (props.removable) {
13060
- let buttonDeleteSchema = getButtonDelete(props);
13314
+ let buttonDeleteSchema = await getButtonDelete(props);
13061
13315
  buttonsForColumnOperations.push(buttonDeleteSchema);
13062
13316
  }
13063
13317
  let inputTableSchema = {
@@ -13118,24 +13372,22 @@ const getAmisInputTableSchema = async (props) => {
13118
13372
  "body": footerToolbar
13119
13373
  });
13120
13374
  }
13121
- // 不可以直接把headerToolbar unshift进schemaBody,因为它没有显示在label下面,而是显示在上面了,这没有意义
13375
+ // 直接把headerToolbar unshift进schemaBody,不会显示在label下面,而是显示在上面了,这个暂时没有解决办法,只能等amis 升级
13122
13376
  // 看起来amis官方后续会支持给input-table组件配置headerToolbar,见:https://github.com/baidu/amis/issues/7246
13123
- // let headerToolbar = clone(props.headerToolbar || []); //这里不clone的话,会造成死循环,应该是因为props属性变更会让组件重新渲染
13124
- // if (headerToolbar.length) {
13125
- // schemaBody.unshift({
13126
- // "type": "wrapper",
13127
- // "size": "none",
13128
- // "body": headerToolbar
13129
- // });
13130
- // }
13377
+ // 不过依然放开此功能的意义在于有的场景字段label本来就不需要显示出来,此时headerToolbar就有意义
13378
+ let headerToolbar = _$1.clone(props.headerToolbar || []); //这里不clone的话,会造成死循环,应该是因为props属性变更会让组件重新渲染
13379
+ if (headerToolbar.length) {
13380
+ schemaBody.unshift({
13381
+ "type": "wrapper",
13382
+ "size": "none",
13383
+ "body": headerToolbar
13384
+ });
13385
+ }
13131
13386
  let schema = {
13132
13387
  "type": "service",
13133
13388
  "body": schemaBody,
13134
13389
  "className": props.className,
13135
- "id": serviceId,
13136
- "data": {
13137
- "__wrapperServiceId": serviceId
13138
- }
13390
+ "id": serviceId
13139
13391
  };
13140
13392
  // console.log("===schema===", schema);
13141
13393
  return schema;