@steedos-widgets/amis-lib 3.6.2-beta.9 → 3.6.3-beta.1

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 (26) hide show
  1. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  2. package/dist/index.cjs.js +884 -268
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.esm.js +884 -268
  5. package/dist/index.esm.js.map +1 -1
  6. package/dist/index.umd.js +212 -127
  7. package/dist/index.umd.js.map +1 -1
  8. package/dist/types/lib/converter/amis/api.d.ts +1 -0
  9. package/dist/types/lib/converter/amis/fields/editor.d.ts +1 -1
  10. package/dist/types/lib/converter/amis/fields/file.d.ts +52 -0
  11. package/dist/types/lib/converter/amis/fields/lookup.d.ts +3 -0
  12. package/dist/types/lib/converter/amis/toolbars/setting_listview/columns.d.ts +1 -0
  13. package/dist/types/lib/converter/amis/toolbars/setting_listview/copy.d.ts +21 -0
  14. package/dist/types/lib/converter/amis/toolbars/setting_listview/filters.d.ts +2 -1
  15. package/dist/types/lib/converter/amis/toolbars/setting_listview/new.d.ts +20 -0
  16. package/dist/types/lib/converter/amis/toolbars/setting_listview/rename.d.ts +1 -0
  17. package/dist/types/lib/converter/amis/toolbars/setting_listview/share.d.ts +15 -0
  18. package/dist/types/lib/converter/amis/toolbars/setting_listview/sort.d.ts +2 -0
  19. package/dist/types/lib/converter/amis/toolbars/setting_listview.d.ts +130 -0
  20. package/dist/types/lib/converter/amis/util.d.ts +5 -0
  21. package/dist/types/lib/input_table.d.ts +24 -15
  22. package/dist/types/lib/objectsRelated.d.ts +8 -17
  23. package/dist/types/lib/router.d.ts +2 -2
  24. package/dist/types/schema/standard_import_data.amis.d.ts +7 -0
  25. package/dist/types/standard/button.d.ts +7 -0
  26. package/package.json +2 -2
package/dist/index.cjs.js CHANGED
@@ -362,14 +362,13 @@ const getSteedosAuth = () => {
362
362
  /*
363
363
  * @Author: baozhoutao@steedos.com
364
364
  * @Date: 2022-08-16 17:02:08
365
- * @LastEditors: baozhoutao@steedos.com
366
- * @LastEditTime: 2023-06-20 13:50:15
365
+ * @LastEditors: 殷亮辉 yinlianghui@hotoa.com
366
+ * @LastEditTime: 2024-02-02 10:15:00
367
367
  * @Description:
368
368
  */
369
369
 
370
370
  const Router = {
371
- getTabDisplayAs(tab_id){
372
- const uiSchema = getUISchemaSync$1(tab_id, false);
371
+ getTabDisplayAs(tab_id, defaultEnableSplit){
373
372
  var urlSearch = new URLSearchParams(document.location.search);
374
373
  if(urlSearch.has('display')){
375
374
  return urlSearch.get('display')
@@ -378,9 +377,12 @@ const Router = {
378
377
  // const key = `page_display`;
379
378
  const value = sessionStorage.getItem(key);
380
379
  let defaultDisplay = "grid";
381
- if(uiSchema.enable_split){
380
+ if(defaultEnableSplit === true){
382
381
  defaultDisplay = "split";
383
382
  }
383
+ if(window.innerWidth <= 768){
384
+ return "grid";
385
+ }
384
386
  return value ? value : defaultDisplay;
385
387
  },
386
388
 
@@ -413,8 +415,8 @@ const Router = {
413
415
  /*
414
416
  * @Author: baozhoutao@steedos.com
415
417
  * @Date: 2022-07-20 16:29:22
416
- * @LastEditors: 殷亮辉 yinlianghui@hotoa.com
417
- * @LastEditTime: 2023-12-28 14:59:08
418
+ * @LastEditors: liaodaxue
419
+ * @LastEditTime: 2024-01-25 14:44:17
418
420
  * @Description:
419
421
  */
420
422
 
@@ -486,6 +488,25 @@ function getComparableAmisVersion() {
486
488
  }
487
489
  }
488
490
 
491
+ /**
492
+ * 判断浏览器类型
493
+ * @returns 按需返回浏览器类型;
494
+ */
495
+ function getBowserType() {
496
+ const userAgent = navigator.userAgent;
497
+ if (userAgent.indexOf("Chrome")!== -1 && userAgent.indexOf("Safari") !== -1 && userAgent.indexOf("Edg") === -1) {
498
+ return "Chrome";
499
+ } else if (userAgent.indexOf("Firefox") !== -1) {
500
+ return "Firefox";
501
+ } else if (userAgent.indexOf("Safari") !== -1 && userAgent.indexOf("Chrome") === -1 && userAgent.indexOf("Edge") === -1) {
502
+ return "Safari";
503
+ } else if (userAgent.indexOf("Edg") !== -1) {
504
+ return "Edge";
505
+ } else {
506
+ return "Unknown browser"; // 其他浏览器...(可根据自己需要确定是否新增其他浏览器的判断)
507
+ }
508
+ }
509
+
489
510
  /*
490
511
  * @Author: baozhoutao@steedos.com
491
512
  * @Date: 2022-05-23 09:53:08
@@ -548,7 +569,7 @@ function getSelectMap(selectOptions){
548
569
  _$1.forEach(selectOptions,(option)=>{
549
570
  const optionValue = option.value + '';
550
571
  const optionColor = option.color + '';
551
- if(optionColor){
572
+ if(optionColor && optionColor != "undefined"){
552
573
  const background = optionColor.charAt(0) === '#' ? optionColor : '#'+optionColor;
553
574
  const color = getContrastColor(background);
554
575
  const optionColorStyle = 'background:'+background+';color:'+color+';line-height:1.5rem';
@@ -1164,7 +1185,31 @@ const getAmisFileReadonlySchema = (steedosField)=>{
1164
1185
  }
1165
1186
  }
1166
1187
  if(type === 'file'){
1167
- return {
1188
+ return window.Meteor?.isCordova ? {
1189
+ "type": "control",
1190
+ "body": {
1191
+ "type": "each",
1192
+ "name": "_display." + steedosField.name,
1193
+ "items": {
1194
+ "type": "tpl",
1195
+ "tpl": "${name}",
1196
+ "className": "antd-Button--link inline-block",
1197
+ "onEvent": {
1198
+ "click": {
1199
+ "actions": [
1200
+ {
1201
+ "script": `
1202
+ Steedos.cordovaDownload(encodeURI(event.data.url), event.data.name);
1203
+ `,
1204
+ "actionType": "custom"
1205
+ }
1206
+ ],
1207
+ "weight": 0
1208
+ }
1209
+ }
1210
+ }
1211
+ }
1212
+ } : {
1168
1213
  type: amisFieldType,
1169
1214
  tpl: `
1170
1215
  <% let fileData = data._display.${steedosField.name}; if (fileData) { %>
@@ -1308,6 +1353,7 @@ var frontend_notifications$1 = "Notifications";
1308
1353
  var frontend_notifications_allread$1 = "Mark all as read";
1309
1354
  var frontend_notifications_allread_message$1 = "All marked as read";
1310
1355
  var frontend_profile$1 = "Profile";
1356
+ var switch_space$1 = "Switch Space";
1311
1357
  var frontend_about$1 = "About";
1312
1358
  var frontend_log_out$1 = "Log out";
1313
1359
  var frontend_listview_warning_start$1 = "The current ";
@@ -1395,6 +1441,7 @@ var en_us = {
1395
1441
  frontend_notifications_allread: frontend_notifications_allread$1,
1396
1442
  frontend_notifications_allread_message: frontend_notifications_allread_message$1,
1397
1443
  frontend_profile: frontend_profile$1,
1444
+ switch_space: switch_space$1,
1398
1445
  frontend_about: frontend_about$1,
1399
1446
  frontend_log_out: frontend_log_out$1,
1400
1447
  frontend_listview_warning_start: frontend_listview_warning_start$1,
@@ -1450,7 +1497,7 @@ var frontend_listview_control_delete_label = "删除";
1450
1497
  var frontend_listview_control_delete_confirm_text = "如果您删除此列表视图,该视图将为所有具备访问权限的用户永久删除。是否确定要删除?";
1451
1498
  var frontend_listview_control_delete_message_success = "删除成功";
1452
1499
  var frontend_listview_control_filters = "过滤设置";
1453
- var frontend_listview_control_filters_fields_extend = "条件组件1";
1500
+ var frontend_listview_control_filters_fields_extend = "条件组件";
1454
1501
  var frontend_listview_control_new_label = "新建";
1455
1502
  var frontend_listview_control_new_title = "新建 列表视图";
1456
1503
  var frontend_listview_control_new_message_success = "成功";
@@ -1484,6 +1531,7 @@ var frontend_notifications = "通知";
1484
1531
  var frontend_notifications_allread = "全部标记为已读";
1485
1532
  var frontend_notifications_allread_message = "已全部标记为已读";
1486
1533
  var frontend_profile = "个人资料";
1534
+ var switch_space = "切换工作区";
1487
1535
  var frontend_about = "关于";
1488
1536
  var frontend_log_out = "注销";
1489
1537
  var frontend_listview_warning_start = "当前";
@@ -1572,6 +1620,7 @@ var zh_cn = {
1572
1620
  frontend_notifications_allread: frontend_notifications_allread,
1573
1621
  frontend_notifications_allread_message: frontend_notifications_allread_message,
1574
1622
  frontend_profile: frontend_profile,
1623
+ switch_space: switch_space,
1575
1624
  frontend_about: frontend_about,
1576
1625
  frontend_log_out: frontend_log_out,
1577
1626
  frontend_listview_warning_start: frontend_listview_warning_start,
@@ -1626,7 +1675,7 @@ async function getQuickEditSchema(field, options){
1626
1675
  isAmisVersionforBatchEdit = window.Amis.version[0] >= 3 && window.Amis.version[2] >= 2;
1627
1676
  }
1628
1677
  const quickEditId = options.objectName + "_" + field.name + "_quickEdit";//定义快速编辑的表单id,用于setvalue传值
1629
- var quickEditSchema = { body: [], id: quickEditId };
1678
+ var quickEditSchema = { body: [], id: quickEditId, className: "steedos-table-quickEdit" };
1630
1679
  //select,avatar,image,file等组件无法行记录字段赋值,暂不支持批量编辑;
1631
1680
  if(field.type != 'avatar' && field.type != 'image' && field.type != 'file' && isAmisVersionforBatchEdit){
1632
1681
  const submitEvent = {
@@ -1885,7 +1934,8 @@ async function getQuickEditSchema(field, options){
1885
1934
  "failed": "失败了呢。。"
1886
1935
  }
1887
1936
  }
1888
- }
1937
+ },
1938
+ "expression": "${!recordPermissions.modifyAllRecords}"
1889
1939
  },
1890
1940
  {
1891
1941
  "actionType": "setValue",
@@ -1901,7 +1951,7 @@ async function getQuickEditSchema(field, options){
1901
1951
  "componentId": quickEditId,
1902
1952
  "args": {
1903
1953
  "value":{
1904
- "quickedit_record_permissions": "${event.data}"
1954
+ "quickedit_record_permissions": "${recordPermissions.modifyAllRecords ? {'allowEdit': true} : event.data}"
1905
1955
  }
1906
1956
  }
1907
1957
  }
@@ -1965,7 +2015,7 @@ async function getQuickEditSchema(field, options){
1965
2015
  `
1966
2016
  }
1967
2017
  },
1968
- "expression":"${event.data.value}"
2018
+ "expression":"${event.data.value && !recordPermissions.modifyAllRecords}"
1969
2019
  },
1970
2020
  {
1971
2021
  "actionType": "setValue",
@@ -1996,10 +2046,20 @@ async function getQuickEditSchema(field, options){
1996
2046
  "script": `
1997
2047
  const noPermission = event.data.noPermission;
1998
2048
  const crudComponent = event.context.scoped.getComponentById("${options.crudId}");
1999
- const selectedItems = crudComponent && crudComponent.props.store.selectedItems.concat();
2049
+ let selectedItems = crudComponent && crudComponent.props.store.selectedItems.concat();
2000
2050
  noPermission.forEach(function (item) {
2001
2051
  crudComponent && crudComponent.unSelectItem(_.find(selectedItems,{_id:item}));
2052
+ _.remove(selectedItems, (selected) => selected._id === item);
2002
2053
  })
2054
+ doAction({
2055
+ "componentId": "${quickEditId}",
2056
+ "actionType": "setValue",
2057
+ "args": {
2058
+ "value": {
2059
+ selectedItems
2060
+ }
2061
+ }
2062
+ });
2003
2063
  `
2004
2064
  },
2005
2065
  {
@@ -2060,7 +2120,7 @@ async function getQuickEditSchema(field, options){
2060
2120
  }
2061
2121
 
2062
2122
  function getFieldWidth(width){
2063
- const defaultWidth = "unset";//用于使table内的td标签下生成div,实现将快速编辑按钮固定在右侧的效果,并不是为了unset效果
2123
+ const defaultWidth = null;
2064
2124
  if(typeof width == 'string'){
2065
2125
  if(isNaN(width)){
2066
2126
  return width || defaultWidth;
@@ -2090,22 +2150,35 @@ async function getTableColumns(fields, options){
2090
2150
  //增加quickEdit属性,实现快速编辑
2091
2151
  const quickEditSchema = allowEdit ? await getQuickEditSchema(field, options) : allowEdit;
2092
2152
  let className = "";
2093
- if(field.wrap != true){
2094
- if(field.wrap != false && field.is_wide){
2095
- className += " break-words ";
2096
- }else {
2153
+ const bowserType = getBowserType();
2154
+ if(bowserType === "Safari"){
2155
+ className += " whitespace-nowrap ";
2156
+ }else {
2157
+ if(field.wrap != true){
2097
2158
  className += " whitespace-nowrap ";
2159
+ }else {
2160
+ className += " break-words ";
2098
2161
  }
2099
- }else {
2100
- className += " break-words ";
2101
2162
  }
2163
+
2164
+ if (typeof field.amis?.className == "object") {
2165
+ className = {
2166
+ [className]: "true",
2167
+ ...field.amis.className
2168
+ };
2169
+ } else if (typeof field.amis?.className == "string") {
2170
+ className = `${className} ${field.amis.className} `;
2171
+ }
2172
+ let fieldAmis = ___namespace.clone(field.amis);
2173
+ delete fieldAmis?.className;
2174
+
2102
2175
  let columnItem;
2103
2176
  if((field.is_name || field.name === options.labelFieldName) && options.objectName === 'cms_files'){
2104
2177
  const previewFileScript = `
2105
2178
  var data = event.data;
2106
2179
  var file_name = data.versions ? data.name : "${field.label}";
2107
- var file_id = data._id;
2108
- SteedosUI.previewFile && SteedosUI.previewFile({file_name, file_id});
2180
+ var file_id = data.versions && data.versions[0] && data.versions[0]._id;
2181
+ window.previewFile && window.previewFile({file_name, file_id});
2109
2182
  `;
2110
2183
  columnItem = {
2111
2184
  "type": "button",
@@ -2130,11 +2203,11 @@ async function getTableColumns(fields, options){
2130
2203
  "expression": "!!!(window && window.nw && window.nw.require)"//浏览器上直接下载
2131
2204
  },
2132
2205
  {
2133
- "args": {},
2134
- "actionType": "custom",
2135
- "script": previewFileScript,
2136
- // "expression": "!!window?.nw?.require" //PC客户端预览附件
2137
- "expression": "!!!(window && window.nw && window.nw.require)"//PC客户端预览附件
2206
+ "args": {},
2207
+ "actionType": "custom",
2208
+ "script": previewFileScript,
2209
+ // "expression": "!!window?.nw?.require" //PC客户端预览附件
2210
+ "expression": "!!(window && window.nw && window.nw.require)"//PC客户端预览附件
2138
2211
  }
2139
2212
  ]
2140
2213
  }
@@ -2149,7 +2222,7 @@ async function getTableColumns(fields, options){
2149
2222
  toggled: field.toggled,
2150
2223
  static: true,
2151
2224
  className,
2152
- }, field.amis, {name: field.name});
2225
+ }, fieldAmis, {name: field.name});
2153
2226
  }else if(field.type === 'avatar' || field.type === 'image' || field.type === 'file'){
2154
2227
  columnItem = Object.assign({}, {
2155
2228
  type: "switch",
@@ -2160,7 +2233,7 @@ async function getTableColumns(fields, options){
2160
2233
  static: true,
2161
2234
  className,
2162
2235
  ...getAmisFileReadonlySchema(field)
2163
- }, field.amis, {name: field.name});
2236
+ }, fieldAmis, {name: field.name});
2164
2237
  }
2165
2238
  else if(field.type === 'select'){
2166
2239
  const map = getSelectMap(field.options);
@@ -2175,7 +2248,7 @@ async function getTableColumns(fields, options){
2175
2248
  className,
2176
2249
  inputClassName: "inline",
2177
2250
  static: true,
2178
- }, field.amis, {name: field.name});
2251
+ }, fieldAmis, {name: field.name});
2179
2252
  }
2180
2253
  else {
2181
2254
  const tpl = await getFieldTpl(field, options);
@@ -2202,15 +2275,6 @@ async function getTableColumns(fields, options){
2202
2275
  // }
2203
2276
 
2204
2277
  //field上的amis属性里的clssname需要单独判断类型合并
2205
- if (typeof field.amis?.className == "object") {
2206
- className = {
2207
- [className]: "true",
2208
- ...field.amis.className
2209
- };
2210
- } else if (typeof field.amis?.className == "string") {
2211
- className = `${className} ${field.amis.className} `;
2212
- }
2213
- delete field.amis?.className;
2214
2278
 
2215
2279
  if(!field.hidden && !field.extra){
2216
2280
  columnItem = Object.assign({}, {
@@ -2227,7 +2291,7 @@ async function getTableColumns(fields, options){
2227
2291
  static: true,
2228
2292
  options: field.type === 'html' ? {html: true} : null
2229
2293
  // toggled: true
2230
- }, field.amis, {name: field.name});
2294
+ }, fieldAmis, {name: field.name});
2231
2295
 
2232
2296
  if(field.type === 'color'){
2233
2297
  columnItem.type = 'color';
@@ -2423,10 +2487,10 @@ async function getMobileTableColumns(fields, options){
2423
2487
  if(value.url){
2424
2488
  cms_url = value.url;
2425
2489
  }else{
2426
- cms_url = "/api/files/files/"+value+"?download=true"
2490
+ cms_url = Steedos.absoluteUrl("/api/files/files/"+value+"?download=true");
2427
2491
  }
2428
2492
  }
2429
- Steedos.cordovaDownload(encodeURI(Steedos.absoluteUrl(cms_url)), event.data.name);
2493
+ Steedos.cordovaDownload(encodeURI(cms_url), event.data.name);
2430
2494
  `,
2431
2495
  "actionType": "custom"
2432
2496
  }
@@ -2926,6 +2990,21 @@ async function getTableApi(mainObject, fields, options){
2926
2990
  return api;
2927
2991
  `;
2928
2992
  api.adaptor = `
2993
+ let fields = ${JSON.stringify(___namespace.map(fields, 'name'))};
2994
+ // 这里把行数据中所有为空的字段值配置为空字符串,是因为amis有bug:crud的columns中的列如果type为static-前缀的话,行数据中该字段为空的话会显示为父作用域中同名变量值,见:https://github.com/baidu/amis/issues/9556
2995
+ (payload.data.rows || []).forEach((itemRow) => {
2996
+ (fields || []).forEach((itemField) => {
2997
+ if(itemField && itemField.indexOf(".") > -1){
2998
+ return;
2999
+ }
3000
+ if(itemField && (itemRow[itemField] === undefined || itemRow[itemField] === null)){
3001
+ // 这里itemRow中不存在 itemField 属性,或者值为null时都会有“显示为父作用域中的同名变量值”的问题,所以null和undefined都要重置为空字符串
3002
+ // 实测数字、下拉框、多选lookup等字段类型重置为空字符串都不会有问题,而且实测amis from组件的清空表单字段值功能就是把表单中的各种字段类型设置为空字符串,所以看起来也符合amis规范
3003
+ itemRow[itemField] = "";
3004
+ }
3005
+ });
3006
+ });
3007
+
2929
3008
  if(api.body.listName == "recent"){
2930
3009
  payload.data.rows = _.sortBy(payload.data.rows, function(item){
2931
3010
  return _.indexOf(api.body._ids, item._id)
@@ -2950,7 +3029,13 @@ async function getTableApi(mainObject, fields, options){
2950
3029
  value = [value]
2951
3030
  };
2952
3031
  if(field.type === 'file'){
2953
- item[key] = value
3032
+ // item[key] = value
3033
+ // PC客户端附件子表列表点击标题预览附件功能依赖了_id,所以这里拼出来
3034
+ let itemKeyValue = item[key];
3035
+ item[key] = value.map(function(item, index){
3036
+ item._id = itemKeyValue[index];
3037
+ return item;
3038
+ });
2954
3039
  }else{
2955
3040
  item[key] = _.map(value, (item)=>{
2956
3041
  if(field.type === 'image'){
@@ -2992,15 +3077,8 @@ async function getTableApi(mainObject, fields, options){
2992
3077
  }
2993
3078
  });
2994
3079
  };
2995
- let isTreeOptionsComputed = false;
2996
- if(records.length === 1 && records[0].children){
2997
- isTreeOptionsComputed = true;
2998
- }
2999
- if(!isTreeOptionsComputed){
3000
- // 如果api接口设置在缓存,缓存期间并不会重新请求接口,payload.data.rows是上次计算后的结果
3001
- payload.data.rows = getTreeOptions(records,{"valueField":"_id"});
3002
- assignIndexToTreeRecords(payload.data.rows, '');
3003
- }
3080
+ payload.data.rows = getTreeOptions(records,{"valueField":"_id"});
3081
+ assignIndexToTreeRecords(payload.data.rows, '');
3004
3082
  }
3005
3083
 
3006
3084
 
@@ -3059,11 +3137,10 @@ async function getTableApi(mainObject, fields, options){
3059
3137
  };
3060
3138
  let formFactor = "${options.formFactor}";
3061
3139
  if(formFactor !== "SMALL"){
3062
- const listviewComponent = $(".steedos-object-listview .antd-Table-table");
3063
- const firstListviewComponent = listviewComponent && listviewComponent[0];
3064
- if(firstListviewComponent){
3140
+ const lisviewDom = document.querySelector(".steedos-object-listview .antd-Table-table");
3141
+ if(lisviewDom){
3065
3142
  setTimeout(()=>{
3066
- firstListviewComponent.scrollIntoView();
3143
+ lisviewDom.scrollIntoView();
3067
3144
  }, 600);
3068
3145
  }
3069
3146
  }
@@ -4896,9 +4973,16 @@ const getSchema$2 = (uiSchema) => {
4896
4973
  "form": {
4897
4974
  debug: false,
4898
4975
  resetAfterSubmit: false,
4976
+ data: {
4977
+ editFormInited: true,
4978
+ },
4899
4979
  initApi: {
4980
+ method: 'GET',
4900
4981
  url: '/api/v1/queue_import_history/${recordId}?fields=["state"]',
4901
4982
  sendOn: 'this.recordId',
4983
+ data: null,
4984
+ requestAdaptor: "return api;",
4985
+ adaptor: "return payload;",
4902
4986
  responseData: {
4903
4987
  importState: "${state}"
4904
4988
  }
@@ -5770,7 +5854,7 @@ async function getObjectFieldsFilterFormSchema(ctx) {
5770
5854
  const formSchema = {
5771
5855
  "type": "service",
5772
5856
  "visibleOn": "this.filterFormSearchableFields && this.filterFormSearchableFields.length",
5773
- "className": ctx.formFactor === 'SMALL' ? "slds-filters__body p-0 mb-2 overflow-y-auto overflow-x-hidden" : "slds-filters__body p-0 sm:grid sm:gap-2 sm:grid-cols-4 mb-2",
5857
+ "className": ctx.formFactor === 'SMALL' ? "slds-filters__body p-0 mb-2 overflow-y-auto overflow-x-hidden" : "slds-filters__body p-0 sm:grid sm:gap-4 sm:grid-cols-4 p-2",
5774
5858
  "style":{
5775
5859
  "max-height":ctx.formFactor === 'SMALL'?"30vh":"unset"
5776
5860
  },
@@ -6357,7 +6441,7 @@ async function getObjectFieldsFilterBarSchema(objectSchema, ctx) {
6357
6441
  "className": "slds-filters"
6358
6442
  },
6359
6443
  "size": "xs",
6360
- "className": `border-gray-300 border-y slds-grid slds-grid_vertical slds-nowrap ${!ctx.isLookup && "mt-2"}`,
6444
+ "className": `border-y slds-grid slds-grid_vertical slds-nowrap ${!ctx.isLookup && "mt-2"}`,
6361
6445
  "visibleOn": "this.showFieldsFilter",
6362
6446
  },
6363
6447
  "className": "bg-white"
@@ -6545,7 +6629,7 @@ async function getObjectListHeaderSecordLine(objectSchema, listViewName, ctx) {
6545
6629
  "icon": "fa fa-refresh",
6546
6630
  "actionType": "reload",
6547
6631
  "target": amisListViewId,
6548
- "className": "bg-white p-2 rounded border-gray-300 text-gray-500"
6632
+ "className": "bg-white p-2 rounded text-gray-500"
6549
6633
  },
6550
6634
  fieldsFilterButtonSchema,
6551
6635
  // {
@@ -6553,7 +6637,7 @@ async function getObjectListHeaderSecordLine(objectSchema, listViewName, ctx) {
6553
6637
  // "label": "",
6554
6638
  // "icon": "fa fa-filter",
6555
6639
  // "actionType": "custom",
6556
- // "className": "bg-transparent p-2 rounded border-gray-300 text-gray-500",
6640
+ // "className": "bg-transparent p-2 rounded text-gray-500",
6557
6641
  // "id": "u:c20cb87d96c9",
6558
6642
  // "onEvent": {
6559
6643
  // "click": {
@@ -6601,7 +6685,7 @@ function getObjectListHeader$1(objectSchema, listViewName, ctx) {
6601
6685
  let headerSchema = [{
6602
6686
  "type": "wrapper",
6603
6687
  "body": body,
6604
- "className": `bg-gray-100 sm:rounded-tl sm:rounded-tr p-4 -mb-4`
6688
+ "className": `sm:rounded-tl sm:rounded-tr p-4 -mb-4`
6605
6689
  }];
6606
6690
  return headerSchema;
6607
6691
  }
@@ -6736,7 +6820,7 @@ async function getObjectRecordDetailHeader(objectSchema, recordId, options) {
6736
6820
  let body = [
6737
6821
  {
6738
6822
  "type": "wrapper",
6739
- "className": "p-4 bg-gray-100 border-b",
6823
+ "className": "p-4 border-b",
6740
6824
  "body": [
6741
6825
  {
6742
6826
  "type": "grid",
@@ -6801,25 +6885,25 @@ async function getObjectRecordDetailHeader(objectSchema, recordId, options) {
6801
6885
  });
6802
6886
 
6803
6887
  // 注意: 以下注释不能删除. tailwind css 动态编译时会识别以下注释, 生成对应的样式
6804
- // xl:grid-cols-1
6805
- // xl:grid-cols-2
6806
- // xl:grid-cols-3
6807
- // xl:grid-cols-4
6808
- // xl:grid-cols-5
6809
- // xl:grid-cols-6
6810
- // xl:grid-cols-7
6811
- // xl:grid-cols-8
6812
- // xl:grid-cols-9
6813
- // xl:grid-cols-10
6814
- // xl:grid-cols-11
6815
- // xl:grid-cols-12
6888
+ // lg:grid-cols-1
6889
+ // lg:grid-cols-2
6890
+ // lg:grid-cols-3
6891
+ // lg:grid-cols-4
6892
+ // lg:grid-cols-5
6893
+ // lg:grid-cols-6
6894
+ // lg:grid-cols-7
6895
+ // lg:grid-cols-8
6896
+ // lg:grid-cols-9
6897
+ // lg:grid-cols-10
6898
+ // lg:grid-cols-11
6899
+ // lg:grid-cols-12
6816
6900
 
6817
6901
  body.push({
6818
6902
  "type": "wrapper",
6819
6903
  "body": {
6820
6904
  "type": "form",
6821
6905
  // "className": "gap-2 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-5 3xl:grid-cols-8 4xl:grid-cols-8 5xl:grid-cols-10", //max-h-12 overflow-hidden
6822
- "className": `gap-2 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 xl:grid-cols-${max}`,
6906
+ "className": `gap-2 grid grid-cols-1 lg:grid-cols-${max}`,
6823
6907
  "wrapWithPanel": false,
6824
6908
  "actions": [],
6825
6909
  "body": details,
@@ -6904,7 +6988,7 @@ async function getObjectRecordDetailRelatedListHeader(relatedObjectSchema, relat
6904
6988
  "className": "flex justify-between"
6905
6989
  }
6906
6990
  ],
6907
- "className": "steedos-record-related-header py-2 px-0"
6991
+ "className": "steedos-record-related-header py-2 px-3 bg-gray-50 border"
6908
6992
  };
6909
6993
  return recordRelatedListHeader;
6910
6994
  }
@@ -6947,6 +7031,7 @@ const getNewListviewButtonSchema = ()=>{
6947
7031
  "objectApiName": "object_listviews",
6948
7032
  "recordId": "",
6949
7033
  "mode": "edit",
7034
+ "layout": "normal",
6950
7035
  "defaultData": {
6951
7036
  "&": "${list_view}",
6952
7037
  "name":"",
@@ -6954,8 +7039,16 @@ const getNewListviewButtonSchema = ()=>{
6954
7039
  "filters":"",
6955
7040
  "shared":false,
6956
7041
  "object_name": "${targetObjectName}",
7042
+ "_id":"",
7043
+ "shared_to": null,
7044
+ "shared_to_organizations": null,
7045
+ "locked": false,
7046
+ "owner": null,
7047
+ "company_id": null,
7048
+ "company_ids": null,
7049
+ "is_system": false
6957
7050
  },
6958
- "fieldsExtend": fieldsExtend$4(),
7051
+ "fieldsExtend": fieldsExtend$5(),
6959
7052
  "fields": fields$1(),
6960
7053
  "onEvent": {
6961
7054
  "submitSucc": {
@@ -7006,14 +7099,17 @@ function fields$1(){
7006
7099
  "mobile_columns",
7007
7100
  "searchable_fields",
7008
7101
  "is_system",
7009
- "shared"
7102
+ "shared",
7103
+ "shared_to",
7104
+ "shared_to_organizations"
7010
7105
  ]
7011
7106
  }
7012
7107
 
7013
- function fieldsExtend$4(){
7108
+ function fieldsExtend$5(){
7014
7109
  return {
7015
7110
  "group": "",
7016
7111
  "label": {
7112
+ "group": "",
7017
7113
  "is_wide": true
7018
7114
  },
7019
7115
  "name": {
@@ -7095,9 +7191,19 @@ function fieldsExtend$4(){
7095
7191
  "shared": {
7096
7192
  "group": "",
7097
7193
  "amis": {
7098
- "visibleOn": "${global.user.is_space_admin}"
7194
+ "visibleOn": "${false}"
7195
+ }
7196
+ },
7197
+ "shared_to": {
7198
+ "group": "",
7199
+ "amis":{
7200
+ "type": "radios",
7201
+ "inline": false
7099
7202
  }
7100
7203
  },
7204
+ "shared_to_organizations": {
7205
+ "group": ""
7206
+ },
7101
7207
  "filters": {
7102
7208
  "group": "",
7103
7209
  "amis": {
@@ -7135,14 +7241,23 @@ const getCopyListviewButtonSchema = ()=>{
7135
7241
  "objectApiName": "object_listviews",
7136
7242
  "recordId": "",
7137
7243
  "mode": "edit",
7244
+ "layout": "normal",
7138
7245
  "defaultData": {
7139
7246
  "&": "${list_view}",
7140
7247
  "name":"",
7141
7248
  "label": i18next__default["default"].t('frontend_listview_control_clone_defaultData_label_start') + " ${list_view.label} " + i18next__default["default"].t('frontend_listview_control_clone_defaultData_label_end'),
7142
7249
  "shared":false,
7143
7250
  "object_name": "${targetObjectName}",
7251
+ "_id":"",
7252
+ "shared_to": null,
7253
+ "shared_to_organizations": null,
7254
+ "locked": false,
7255
+ "owner": null,
7256
+ "company_id": null,
7257
+ "company_ids": null,
7258
+ "is_system": false
7144
7259
  },
7145
- "fieldsExtend": fieldsExtend$3(),
7260
+ "fieldsExtend": fieldsExtend$4(),
7146
7261
  "fields": fields(),
7147
7262
  "onEvent": {
7148
7263
  "submitSucc": {
@@ -7190,13 +7305,16 @@ function fields(){
7190
7305
  "mobile_columns.$.field",
7191
7306
  "searchable_fields.$.field",
7192
7307
  "is_system",
7193
- "shared"
7308
+ "shared",
7309
+ "shared_to",
7310
+ "shared_to_organizations"
7194
7311
  ]
7195
7312
  }
7196
7313
 
7197
- function fieldsExtend$3(){
7314
+ function fieldsExtend$4(){
7198
7315
  return {
7199
7316
  "label": {
7317
+ "group": "",
7200
7318
  "is_wide": true
7201
7319
  },
7202
7320
  "name": {
@@ -7246,10 +7364,21 @@ function fieldsExtend$3(){
7246
7364
  }
7247
7365
  },
7248
7366
  "shared": {
7367
+ "group": "",
7249
7368
  "amis": {
7250
- "visibleOn": "${global.user.is_space_admin}"
7369
+ "visibleOn": "${false}"
7251
7370
  }
7252
7371
  },
7372
+ "shared_to": {
7373
+ "group": "",
7374
+ "amis":{
7375
+ "type": "radios",
7376
+ "inline": false
7377
+ }
7378
+ },
7379
+ "shared_to_organizations": {
7380
+ "group": ""
7381
+ },
7253
7382
  "filters": {
7254
7383
  "group": "",
7255
7384
  "amis": {
@@ -7259,6 +7388,12 @@ function fieldsExtend$3(){
7259
7388
  }
7260
7389
  }
7261
7390
 
7391
+ /*
7392
+ * @Author: 殷亮辉 yinlianghui@hotoa.com
7393
+ * @Date: 2023-06-13 13:51:19
7394
+ * @LastEditors: 殷亮辉 yinlianghui@hotoa.com
7395
+ * @LastEditTime: 2024-02-05 11:25:09
7396
+ */
7262
7397
  const getRenameListviewButtonSchema = ()=>{
7263
7398
  return {
7264
7399
  "type": "button",
@@ -7284,6 +7419,7 @@ const getRenameListviewButtonSchema = ()=>{
7284
7419
  "label": "对象表单",
7285
7420
  "objectApiName": "object_listviews",
7286
7421
  "recordId": "${recordId}",
7422
+ "layout": "normal",
7287
7423
  "mode": "edit",
7288
7424
  "fields": [
7289
7425
  "label"
@@ -7318,6 +7454,12 @@ const getRenameListviewButtonSchema = ()=>{
7318
7454
  }
7319
7455
  };
7320
7456
 
7457
+ /*
7458
+ * @Author: 殷亮辉 yinlianghui@hotoa.com
7459
+ * @Date: 2023-06-13 13:51:19
7460
+ * @LastEditors: 殷亮辉 yinlianghui@hotoa.com
7461
+ * @LastEditTime: 2024-02-06 15:38:49
7462
+ */
7321
7463
  const getSetListviewShareButtonSchema = ()=>{
7322
7464
  return {
7323
7465
  "type": "button",
@@ -7333,6 +7475,8 @@ const getSetListviewShareButtonSchema = ()=>{
7333
7475
  "title": i18next__default["default"].t('frontend_listview_control_share'),
7334
7476
  "data": {
7335
7477
  "recordId": "${uiSchema.list_views[listName]._id}",
7478
+ "appId": "${appId}",
7479
+ "global": "${global}",
7336
7480
  "context": "${context}"
7337
7481
  },
7338
7482
  "body": [
@@ -7342,9 +7486,12 @@ const getSetListviewShareButtonSchema = ()=>{
7342
7486
  "objectApiName": "object_listviews",
7343
7487
  "recordId": "${recordId}",
7344
7488
  "mode": "edit",
7489
+ "layout": "normal",
7345
7490
  "fields": [
7346
- "shared"
7347
- ]
7491
+ "shared_to",
7492
+ "shared_to_organizations"
7493
+ ],
7494
+ "fieldsExtend": fieldsExtend$3(),
7348
7495
  }
7349
7496
  ],
7350
7497
  "showCloseButton": true,
@@ -7362,6 +7509,21 @@ const getSetListviewShareButtonSchema = ()=>{
7362
7509
  }
7363
7510
  };
7364
7511
 
7512
+ function fieldsExtend$3(){
7513
+ return {
7514
+ "shared_to": {
7515
+ "group": "",
7516
+ "amis":{
7517
+ "type": "radios",
7518
+ "inline": false
7519
+ }
7520
+ },
7521
+ "shared_to_organizations": {
7522
+ "group": ""
7523
+ }
7524
+ }
7525
+ }
7526
+
7365
7527
  const getSetListviewFiltersButtonSchema = ()=>{
7366
7528
  return {
7367
7529
  "type": "button",
@@ -7493,10 +7655,12 @@ function apiRequestAdaptor$2(){
7493
7655
  function fieldsExtend$2(){
7494
7656
  return {
7495
7657
  "filters": {
7658
+ "label": "",
7659
+ "group": "",
7496
7660
  "visible_on": "true",
7497
7661
  "amis": {
7498
7662
  "type": "condition-builder",
7499
- "label": i18next__default["default"].t('frontend_listview_control_filters_fields_extend'),
7663
+ // "label": i18next.t('frontend_listview_control_filters_fields_extend'),
7500
7664
  "source": {
7501
7665
  "method": "get",
7502
7666
  "url": "${context.rootUrl}/service/api/amis-metadata-listviews/getFilterFields?objectName=${targetObjectName}",
@@ -7539,6 +7703,7 @@ const getSetListviewColumnsButtonSchema = ()=>{
7539
7703
  "objectApiName": "object_listviews",
7540
7704
  "recordId": "${recordId}",
7541
7705
  "mode": "edit",
7706
+ "layout": "normal",
7542
7707
  "fieldsExtend": fieldsExtend$1(),
7543
7708
  "initApiAdaptor": initApiAdaptor$1(),
7544
7709
  "apiRequestAdaptor": apiRequestAdaptor$1(),
@@ -7735,6 +7900,8 @@ const getSetListviewSortButtonSchema = ()=>{
7735
7900
  function fieldsExtend(){
7736
7901
  return {
7737
7902
  "sort": {
7903
+ "label": "",
7904
+ "group": "",
7738
7905
  "amis": {
7739
7906
  "type": "tabs-transfer",
7740
7907
  "sortable": true,
@@ -7862,7 +8029,7 @@ const getSettingListviewToolbarButtonSchema = ()=>{
7862
8029
  "icon": "fa fa-cog",
7863
8030
  //TODO: dropdown-button只支持在按钮上方配置提示,对于上方按钮的点击会有影响,为保持统一,暂时去除,等待amis优化,https://github.com/baidu/amis/issues/7330
7864
8031
  // "tooltip": i18next.t('frontend_button_listview_control_tooltip'),
7865
- "btnClassName": "antd-Button--iconOnly bg-white !p-2 rounded border-gray-300 text-gray-500",
8032
+ "btnClassName": "antd-Button--iconOnly bg-white !p-2 rounded text-gray-500",
7866
8033
  "align": "right",
7867
8034
  "visibleOn": "${!isLookup}",
7868
8035
  "buttons": [
@@ -7883,8 +8050,8 @@ const getSettingListviewToolbarButtonSchema = ()=>{
7883
8050
  }
7884
8051
  };
7885
8052
 
7886
- const getDisplayAsButton = function(objectName, showDisplayAs){
7887
- let displayAs = amisLib.Router.getTabDisplayAs(objectName);
8053
+ const getDisplayAsButton = function(objectName, defaultEnableSplit){
8054
+ let displayAs = amisLib.Router.getTabDisplayAs(objectName, defaultEnableSplit);
7888
8055
  let buttons = [
7889
8056
  {
7890
8057
  "type": "button",
@@ -7907,7 +8074,7 @@ const getDisplayAsButton = function(objectName, showDisplayAs){
7907
8074
  "icon": "fa fa-table-columns",
7908
8075
  //TODO: dropdown-button只支持在按钮上方配置提示,对于上方按钮的点击会有影响,暂时去除,等待amis优化,https://github.com/baidu/amis/issues/7330
7909
8076
  // "tooltip": `${i18next.t('frontend_display_as')} ${displayAsLabel}`,
7910
- "btnClassName": "antd-Button--iconOnly bg-white !p-2 rounded border-gray-300 text-gray-500",
8077
+ "btnClassName": "antd-Button--iconOnly bg-white !p-2 rounded text-gray-500",
7911
8078
  "align": "right",
7912
8079
  "visibleOn": "${window:innerWidth > 768 && !!!isLookup}",
7913
8080
  "buttons": [
@@ -8100,7 +8267,7 @@ function getObjectHeaderToolbar(mainObject, fields, formFactor, {
8100
8267
  // //TODO: dropdown-button只支持在按钮上方配置提示,对于上方按钮的点击会有影响,为保持统一,暂时去除,等待amis优化,https://github.com/baidu/amis/issues/7330
8101
8268
  // // "tooltip": i18next.t('frontend_button_reload_tooltip'),
8102
8269
  // "tooltipPlacement": "top",
8103
- // "className": "bg-white p-2 rounded border-gray-300 text-gray-500",
8270
+ // "className": "bg-white p-2 rounded text-gray-500",
8104
8271
  // "label": "",
8105
8272
  // "icon": "fa fa-sync",
8106
8273
  // "visibleOn": "${!showFieldsFilter}",
@@ -8124,7 +8291,7 @@ function getObjectHeaderToolbar(mainObject, fields, formFactor, {
8124
8291
  // "tooltip": i18next.t('frontend_button_reload_tooltip'),
8125
8292
  "tooltip":"",
8126
8293
  "tooltipPlacement": "top",
8127
- "className": "bg-white p-2 rounded border-gray-300 text-gray-500"
8294
+ "className": "bg-white p-2 rounded text-gray-500"
8128
8295
  };
8129
8296
  }
8130
8297
  else {
@@ -8135,7 +8302,7 @@ function getObjectHeaderToolbar(mainObject, fields, formFactor, {
8135
8302
  // "tooltip": i18next.t('frontend_button_reload_tooltip'),
8136
8303
  "tooltip":"",
8137
8304
  "tooltipPlacement": "top",
8138
- "className": "bg-white p-2 rounded border-gray-300 text-gray-500"
8305
+ "className": "bg-white p-2 rounded text-gray-500"
8139
8306
  };
8140
8307
  }
8141
8308
  let toolbarFilter;
@@ -8157,7 +8324,7 @@ function getObjectHeaderToolbar(mainObject, fields, formFactor, {
8157
8324
  "visibleOn": "${isFieldsFilterEmpty == false && isLookup != true}"
8158
8325
  },
8159
8326
  "align": "right",
8160
- "className": "bg-white p-2 rounded border-gray-300 text-gray-500",
8327
+ "className": "bg-white p-2 rounded text-gray-500",
8161
8328
  "onEvent": {
8162
8329
  "click": {
8163
8330
  "actions": [
@@ -8171,7 +8338,7 @@ function getObjectHeaderToolbar(mainObject, fields, formFactor, {
8171
8338
  "id": "steedos_crud_toolbar_filter"
8172
8339
  };
8173
8340
  }
8174
- let toolbarDisplayAsButton = getDisplayAsButton(mainObject?.name);
8341
+ let toolbarDisplayAsButton = getDisplayAsButton(mainObject?.name, mainObject?.enable_split);
8175
8342
  let toolbarDQuickSearchBox = getObjectHeaderQuickSearchBox(mainObject, fields, formFactor, { isLookup, keywordsSearchBoxName });
8176
8343
 
8177
8344
  // toolbars返回的数组元素不可以是空对象{},比如hiddenCount ? {} : {"type": "tpl",...},因为空对象最终还是会生成一个空的.antd-Crud-toolbar-item dom
@@ -8317,7 +8484,6 @@ async function getObjectFilter(objectSchema, fields, options) {
8317
8484
  "timeOut": 1000
8318
8485
  }
8319
8486
  });
8320
- resizeWindow();
8321
8487
  const scope = event.context.scoped;
8322
8488
  // let filterFormValues = event.data;
8323
8489
  let filterForm = SteedosUI.getClosestAmisComponentByType(scope, "form");
@@ -8484,7 +8650,7 @@ async function getObjectCRUD(objectSchema, fields, options){
8484
8650
  const bodyProps = {
8485
8651
  // toolbar: getToolbar(),
8486
8652
  // headerToolbar: getObjectHeaderToolbar(objectSchema, options.formFactor, {showDisplayAs}),
8487
- headerToolbarClassName: "px-4 py-2 border-gray-300 bg-gray-100 border-solid border-b",
8653
+ headerToolbarClassName: "px-4 py-2 border-b",
8488
8654
  footerToolbar: getObjectFooterToolbar(objectSchema, options.formFactor, {
8489
8655
  ...options,
8490
8656
  disableStatistics: options.queryCount === false
@@ -8631,14 +8797,7 @@ async function getObjectCRUD(objectSchema, fields, options){
8631
8797
  headers: {
8632
8798
  Authorization: "Bearer ${context.tenantId},${context.authToken}",
8633
8799
  },
8634
- requestAdaptor: quickSaveApiRequestAdaptor,
8635
- adaptor: `
8636
- if(payload.errors){
8637
- payload.status = 2;
8638
- payload.msg = window.t ? window.t(payload.errors[0].message) : payload.errors[0].message;
8639
- }
8640
- return payload;
8641
- `
8800
+ requestAdaptor: quickSaveApiRequestAdaptor
8642
8801
  },
8643
8802
  // 外层data发生变化的时候, 不会重新渲染rowClassNameExpr, 所以先用css标记tr唯一标识
8644
8803
  // 使用表达式给tr添加初始选中状态
@@ -8655,6 +8814,20 @@ async function getObjectCRUD(objectSchema, fields, options){
8655
8814
  crudModeClassName = `steedos-crud-mode-${body.mode}`;
8656
8815
  }
8657
8816
 
8817
+ body.quickSaveApi.adaptor = `
8818
+ if(payload.errors){
8819
+ payload.status = 2;
8820
+ payload.msg = window.t ? window.t(payload.errors[0].message) : payload.errors[0].message;
8821
+ }
8822
+ var scope = SteedosUI.getRef(context.scopeId);
8823
+ var scopeParent = scope && scope.parent;
8824
+ var crudScoped = scopeParent.getComponentById('${body.id}');
8825
+ setTimeout(()=>{
8826
+ crudScoped && crudScoped.control.updateAutoFillHeight();
8827
+ }, 500);
8828
+ return payload;
8829
+ `;
8830
+
8658
8831
  if(body.columns && options.formFactor != 'SMALL'){
8659
8832
  //将_display放入crud的columns的倒数第二列中(最后一列会影响固定列),可以通过setvalue修改行内数据域的_display,而不影响上层items的_display,用于批量编辑
8660
8833
  body.columns.splice(body.columns.length -1 , 0, {name: '_display',type: 'static', width: 1, placeholder: "",id: objectSchema.name + "_display_${_index}", tpl: "${''}"});
@@ -9019,8 +9192,8 @@ const getRecordPermissions = async (objectName, recordId)=>{
9019
9192
  /*
9020
9193
  * @Author: baozhoutao@steedos.com
9021
9194
  * @Date: 2022-07-05 15:55:39
9022
- * @LastEditors: baozhoutao@steedos.com
9023
- * @LastEditTime: 2024-01-15 10:34:46
9195
+ * @LastEditors: 殷亮辉 yinlianghui@hotoa.com
9196
+ * @LastEditTime: 2024-02-08 16:10:52
9024
9197
  * @Description:
9025
9198
  */
9026
9199
 
@@ -9119,7 +9292,9 @@ async function getRecordDetailRelatedListSchema(objectName, recordId, relatedObj
9119
9292
  const foreign_key_value = arr[2] ? arr[1]+'.'+arr[2] : arr[1];
9120
9293
  mainRelated[arr[0]] = foreign_key_value;
9121
9294
  }
9122
- }else {
9295
+ }
9296
+ // 防止related_lists中没有相关子表,但是details中有相关子表的情况
9297
+ if(!mainRelated[relatedObjectName]){
9123
9298
  const details = _$1.union(mainObjectUiSchema.details,mainObjectUiSchema.lookup_details) || [];
9124
9299
  for (const detail of details) {
9125
9300
  const arr = detail.split(".");
@@ -9135,19 +9310,6 @@ async function getRecordDetailRelatedListSchema(objectName, recordId, relatedObj
9135
9310
  let globalFilter = null;
9136
9311
  // TODO: refField变量去掉,写到amis运行时脚本中,uiSchema.fields[relatedKey];可以取到
9137
9312
  const refField = await getField(relatedObjectName, relatedKey);
9138
-
9139
- if(!refField){
9140
- return {
9141
- uiSchema: relatedObjectUiSchema,
9142
- amisSchema: {
9143
- "type": "alert",
9144
- "body": `${i18next__default["default"].t('frontend_objects_related_alert_start')} ${relatedObjectName} ${i18next__default["default"].t('frontend_objects_related_alert_end')}`,
9145
- "level": "warning",
9146
- "showIcon": true,
9147
- "className": "mb-3"
9148
- }
9149
- }
9150
- }
9151
9313
  // if(refField.reference_to_field && refField.reference_to_field != '_id'){
9152
9314
  // const masterRecord = await getRecord(objectName, recordId, [refField.reference_to_field]);
9153
9315
  // relatedValue = masterRecord[refField.reference_to_field]
@@ -9208,7 +9370,7 @@ async function getRecordDetailRelatedListSchema(objectName, recordId, relatedObj
9208
9370
  amisSchema: {
9209
9371
  type: "service",
9210
9372
  id: componentId,
9211
- className: `steedos-record-related-list py-2 first:pt-0 border-b last:border-b-0 ${componentId} ${className}`,
9373
+ className: `steedos-record-related-list mb-4 last:mb-0 ${componentId} ${className}`,
9212
9374
  data: {
9213
9375
  relatedKey: relatedKey,
9214
9376
  listViewId: `amis-\${appId}-${relatedObjectName}-listview`,
@@ -9391,7 +9553,10 @@ async function getRelatedListSchema(
9391
9553
  "filterVisible": false,
9392
9554
  "requestAdaptor": ctx.requestAdaptor,
9393
9555
  "adaptor": adaptor + ctx.adaptor || '',
9394
- "ctx": ctx
9556
+ "ctx": ctx,
9557
+ "crud": ctx.crud,
9558
+ "crudDataFilter": ctx.crudDataFilter,
9559
+ "onCrudDataFilter": ctx.onCrudDataFilter
9395
9560
  };
9396
9561
  // console.log(`getRelatedListSchema amisSchema`, amisSchema);
9397
9562
  return {
@@ -9436,8 +9601,8 @@ async function getObjectRelatedListsMiniSchema(objectApiName){
9436
9601
  /*
9437
9602
  * @Author: baozhoutao@steedos.com
9438
9603
  * @Date: 2022-07-05 15:55:39
9439
- * @LastEditors: baozhoutao@steedos.com
9440
- * @LastEditTime: 2024-01-16 11:14:34
9604
+ * @LastEditors: liaodaxue
9605
+ * @LastEditTime: 2024-02-05 17:56:27
9441
9606
  * @Description:
9442
9607
  */
9443
9608
 
@@ -9793,6 +9958,8 @@ async function convertColumnsToTableFields(columns, uiSchema, ctx = {}) {
9793
9958
  const rfUiSchema = await getUISchema(filedInfo.reference_to);
9794
9959
  const rfFieldInfo = rfUiSchema.fields[displayName];
9795
9960
  fields.push(Object.assign({}, rfFieldInfo, { name: `${fieldName}__expand.${displayName}`, expand: true, expandInfo: { fieldName, displayName } }, ctx));
9961
+ }else if(filedInfo && filedInfo.type === 'object'){
9962
+ fields.push(uiSchema.fields[column]);
9796
9963
  }
9797
9964
  } else {
9798
9965
  if (uiSchema.fields[column]) {
@@ -9954,7 +10121,7 @@ async function getRecordDetailSchema(objectName, appId, props = {}){
9954
10121
  };
9955
10122
  const content = {
9956
10123
  "type": "tabs",
9957
- "className": "steedos-record-tabs bg-white p-4 m-0 mt-2 border-y",
10124
+ "className": "steedos-record-tabs bg-white p-4 mt-3 border-y",
9958
10125
  "contentClassName": "bg-none",
9959
10126
  "tabs": [
9960
10127
  detailed
@@ -10655,17 +10822,13 @@ function getReferenceToSync(field) {
10655
10822
 
10656
10823
  function getLookupSapceUserTreeSchema(isMobile){
10657
10824
  let apiAdaptor = `
10658
- // console.log("===getLookupSapceUserTreeSchema===", JSON.stringify(payload));
10659
10825
  const records = payload.data.options;
10660
- let isTreeOptionsComputed = false;
10661
- if(records.length === 1 && records[0].children){
10662
- isTreeOptionsComputed = true;
10663
- }
10664
- if(isTreeOptionsComputed){
10665
- return payload;
10666
- }
10667
10826
  const treeRecords = [];
10668
- const getChildren = (records, childrenIds) => {
10827
+ const getChildren = (currentRecord, records, childrenIds) => {
10828
+ if (currentRecord.children && typeof currentRecord.children[0] === "object") {
10829
+ // 考虑api配置了cache缓存的话,不会请求接口但是会重新进这个接收适配器脚本且payload.data.options返回的会是上一次计算结果,这里直接返回计算过的children
10830
+ return currentRecord.children;
10831
+ }
10669
10832
  if (!childrenIds) {
10670
10833
  return;
10671
10834
  }
@@ -10674,7 +10837,7 @@ function getLookupSapceUserTreeSchema(isMobile){
10674
10837
  });
10675
10838
  _.each(children, (item) => {
10676
10839
  if (item.children) {
10677
- item.children = getChildren(records, item.children)
10840
+ item.children = getChildren(item, records, item.children)
10678
10841
  }else{
10679
10842
  item.children = [];
10680
10843
  }
@@ -10700,7 +10863,7 @@ function getLookupSapceUserTreeSchema(isMobile){
10700
10863
 
10701
10864
  _.each(records, (record) => {
10702
10865
  if (record.noParent == 1) {
10703
- treeRecords.push(Object.assign({}, record, { children: getChildren(records, record.children) }));
10866
+ treeRecords.push(Object.assign({}, record, { children: getChildren(record, records, record.children) }));
10704
10867
  }
10705
10868
  });
10706
10869
  console.log(treeRecords)
@@ -10750,6 +10913,7 @@ function getLookupSapceUserTreeSchema(isMobile){
10750
10913
  }
10751
10914
  },
10752
10915
  "label": "",
10916
+ "mode": "normal",
10753
10917
  "name": "organizations",
10754
10918
  "multiple": false,
10755
10919
  "joinValues": false,
@@ -10892,6 +11056,9 @@ async function lookupToAmisPicker(field, readonly, ctx){
10892
11056
  }
10893
11057
  });
10894
11058
 
11059
+ let listviewFilter = getListViewFilter(listView);
11060
+ let listviewFiltersFunction = listView && listView._filters;
11061
+
10895
11062
  let sort = "";
10896
11063
  if(listView){
10897
11064
  sort = getListViewSort(listView);
@@ -10938,7 +11105,7 @@ async function lookupToAmisPicker(field, readonly, ctx){
10938
11105
  Object.assign(api.data.$self, __changedSearchBoxValues, __changedFilterFormValues);
10939
11106
  }
10940
11107
  const selfData = JSON.parse(JSON.stringify(api.data.$self));
10941
- var filters = [];
11108
+ ${listviewFilter && !ctx.inFilterForm ? `var filters = ${JSON.stringify(listviewFilter)};` : 'var filters = [];'}
10942
11109
  var pageSize = api.data.pageSize || 10;
10943
11110
  var pageNo = api.data.pageNo || 1;
10944
11111
  var skip = (pageNo - 1) * pageSize;
@@ -11000,6 +11167,16 @@ async function lookupToAmisPicker(field, readonly, ctx){
11000
11167
  }
11001
11168
 
11002
11169
  const inFilterForm = ${ctx.inFilterForm};
11170
+
11171
+ const listviewFiltersFunction = ${listviewFiltersFunction};
11172
+
11173
+ if(listviewFiltersFunction && !inFilterForm){
11174
+ const _filters0 = listviewFiltersFunction(filters, api.data.$self.__super);
11175
+ if(_filters0 && _filters0.length){
11176
+ filters.push(_filters0);
11177
+ }
11178
+ }
11179
+
11003
11180
  const filtersFunction = ${field.filtersFunction || field._filtersFunction};
11004
11181
 
11005
11182
  if(filtersFunction && !inFilterForm){
@@ -11087,6 +11264,16 @@ async function lookupToAmisPicker(field, readonly, ctx){
11087
11264
  });
11088
11265
  payload.data.rows = treeRecords;
11089
11266
  }
11267
+ const result = payload.data.rows;
11268
+ if(result && result.length){
11269
+ const updatedResult = _.map(result, (element) => {
11270
+ const data = { ...element };
11271
+ // image字段值添加URL前缀
11272
+ ${getScriptForAddUrlPrefixForImgFields(___namespace.values(refObjectConfig.fields))}
11273
+ return data;
11274
+ });
11275
+ payload.data.rows = updatedResult;
11276
+ }
11090
11277
  return payload;
11091
11278
  `;
11092
11279
  if(field.optionsFunction || field._optionsFunction){
@@ -11118,13 +11305,15 @@ async function lookupToAmisPicker(field, readonly, ctx){
11118
11305
 
11119
11306
  pickerSchema.affixHeader = false;
11120
11307
 
11121
- var headerToolbarItems = [];
11308
+
11309
+
11310
+ pickerSchema.headerToolbar = getObjectHeaderToolbar(refObjectConfig, fieldsArr, ctx.formFactor, { isLookup: true, keywordsSearchBoxName });
11311
+
11122
11312
  if(referenceTo.objectName === "space_users" && field.reference_to_field === "user"){
11123
- headerToolbarItems = getLookupSapceUserTreeSchema(isMobile);
11313
+ pickerSchema.headerToolbar.push(getLookupSapceUserTreeSchema(isMobile));
11124
11314
  pickerSchema.className = pickerSchema.className || "" + " steedos-select-user";
11125
11315
  }
11126
-
11127
- pickerSchema.headerToolbar = getObjectHeaderToolbar(refObjectConfig, fieldsArr, ctx.formFactor, { headerToolbarItems, isLookup: true, keywordsSearchBoxName });
11316
+
11128
11317
  const isAllowCreate = refObjectConfig.permissions.allowCreate;
11129
11318
  const isCreate = ___namespace.isBoolean(field.create) ? field.create : true;
11130
11319
  // lookup字段配置过滤条件就强制不显示新建按钮
@@ -11237,8 +11426,19 @@ async function lookupToAmisPicker(field, readonly, ctx){
11237
11426
  pickerSchema.footerToolbar = ["pagination"];
11238
11427
  }
11239
11428
 
11429
+ if(field.inlineHelpText){
11430
+ pickerSchema.toolbarClassName = "hasHelpText";
11431
+ pickerSchema.headerToolbar = [{
11432
+ "type": "tpl",
11433
+ "tpl": field.inlineHelpText,
11434
+ "className": "text-secondary"
11435
+ }, ...pickerSchema.headerToolbar];
11436
+ }
11437
+ pickerSchema.className = (pickerSchema.className || "") + " steedos-lookup-crud";
11438
+
11240
11439
  const data = {
11241
11440
  type: getAmisStaticFieldType('picker', readonly),
11441
+ className: ctx.className || '',
11242
11442
  modalTitle: i18next__default["default"].t('frontend_form_please_select') + " " + refObjectConfig.label,
11243
11443
  labelField: referenceTo.labelField.name,
11244
11444
  valueField: referenceTo.valueField.name,
@@ -11312,6 +11512,9 @@ async function lookupToAmisSelect(field, readonly, ctx){
11312
11512
  const refObjectConfig = referenceTo && await getUISchema(referenceTo.objectName);
11313
11513
  let listView = getLookupListView(refObjectConfig);
11314
11514
 
11515
+ let listviewFilter = getListViewFilter(listView);
11516
+ let listviewFiltersFunction = listView && listView._filters;
11517
+
11315
11518
  let sort = "";
11316
11519
  if(listView){
11317
11520
  sort = getListViewSort(listView);
@@ -11341,7 +11544,7 @@ async function lookupToAmisSelect(field, readonly, ctx){
11341
11544
  apiInfo.data['rfield'] = `\${object_name}`;
11342
11545
  // [["_id", "=", "$${field.name}._id"],"or",["name", "contains", "$term"]]
11343
11546
  apiInfo.requestAdaptor = `
11344
- var filters = [];
11547
+ ${listviewFilter && !ctx.inFilterForm ? `var filters = ${JSON.stringify(listviewFilter)};` : 'var filters = [];'}
11345
11548
  var top = 200;
11346
11549
  if(api.data.$term){
11347
11550
  filters = [["${referenceTo?.NAME_FIELD_KEY || 'name'}", "contains", api.data.$term]];
@@ -11364,6 +11567,16 @@ async function lookupToAmisSelect(field, readonly, ctx){
11364
11567
  }
11365
11568
 
11366
11569
  const inFilterForm = ${ctx.inFilterForm};
11570
+
11571
+ const listviewFiltersFunction = ${listviewFiltersFunction};
11572
+
11573
+ if(listviewFiltersFunction && !inFilterForm){
11574
+ const _filters0 = listviewFiltersFunction(filters, api.data.$);
11575
+ if(_filters0 && _filters0.length){
11576
+ filters.push(_filters0);
11577
+ }
11578
+ }
11579
+
11367
11580
  const filtersFunction = ${field.filtersFunction || field._filtersFunction};
11368
11581
 
11369
11582
  if(filtersFunction && !inFilterForm){
@@ -11440,6 +11653,7 @@ async function lookupToAmisSelect(field, readonly, ctx){
11440
11653
  // 但是同时配置autoComplete和source会多请求一次接口
11441
11654
  // TODO:应该想办法把是否字段在子表组件内,即ctx.isInputTable,如果不在子表组件内不需要加source
11442
11655
  data.source = apiInfo;
11656
+ delete data.autoComplete;
11443
11657
  }
11444
11658
  //删除xlink:href中的rootUrl前缀,解决客户端svg为空的问题
11445
11659
  const select_menuTpl = `<span class='flex items-center mt-0.5'>
@@ -11486,7 +11700,8 @@ async function lookupToAmis(field, readonly, ctx){
11486
11700
  }
11487
11701
  // console.log(`lookupToAmis====`, field, readonly, ctx)
11488
11702
  if(readonly){
11489
- if(field.reference_to){
11703
+ if(field.reference_to && !field.isTableField){
11704
+ //isTableField只在grid字段内存在
11490
11705
  return {
11491
11706
  type: 'steedos-field',
11492
11707
  config: field,
@@ -11701,8 +11916,8 @@ if(typeof window != 'undefined'){
11701
11916
  /*
11702
11917
  * @Author: baozhoutao@steedos.com
11703
11918
  * @Date: 2023-01-13 17:27:54
11704
- * @LastEditors: 殷亮辉 yinlianghui@hotoa.com
11705
- * @LastEditTime: 2023-08-28 17:45:38
11919
+ * @LastEditors: liaodaxue
11920
+ * @LastEditTime: 2024-02-04 17:29:54
11706
11921
  * @Description:
11707
11922
  */
11708
11923
 
@@ -11803,7 +12018,8 @@ const getHtmlFieldSchema = (field, readonly, ctx)=>{
11803
12018
  "title": "Insert",
11804
12019
  "items": "image link media addcomment pageembed codesample inserttable | charmap emoticons hr | pagebreak nonbreaking anchor tableofcontents | insertdatetime"
11805
12020
  }
11806
- }
12021
+ },
12022
+ "statusbar": false
11807
12023
  },
11808
12024
  "name": field.name
11809
12025
  }
@@ -12148,13 +12364,31 @@ async function convertSFieldToAmisField(field, readonly, ctx) {
12148
12364
  };
12149
12365
  break;
12150
12366
  case 'input-datetime-range':
12367
+ // convertData = {
12368
+ // type: "input-datetime-range",
12369
+ // inputFormat: 'YYYY-MM-DD HH:mm',
12370
+ // format:'YYYY-MM-DDTHH:mm:ss.SSSZ',
12371
+ // tpl: readonly ? Tpl.getDateTimeTpl(field) : null,
12372
+ // utc: true,
12373
+ // joinValues: false
12374
+ // }
12375
+ // 日期时间字段,按日期方式展现显示控件,用户不用关心小时分钟
12151
12376
  convertData = {
12152
- type: "input-datetime-range",
12153
- inputFormat: 'YYYY-MM-DD HH:mm',
12377
+ type: "input-date-range",
12378
+ inputFormat: "YYYY-MM-DD HH:mm",
12154
12379
  format:'YYYY-MM-DDTHH:mm:ss.SSSZ',
12155
12380
  tpl: readonly ? getDateTimeTpl(field) : null,
12156
12381
  utc: true,
12157
- joinValues: false
12382
+ joinValues: false,
12383
+ "shortcuts": [
12384
+ "thismonth",
12385
+ "2monthsago",
12386
+ "3monthslater",
12387
+ "prevquarter",
12388
+ "thisquarter",
12389
+ "thisyear",
12390
+ "lastYear"
12391
+ ]
12158
12392
  };
12159
12393
  break;
12160
12394
  case 'datetime':
@@ -12205,7 +12439,7 @@ async function convertSFieldToAmisField(field, readonly, ctx) {
12205
12439
  convertData = {
12206
12440
  type: getAmisStaticFieldType('datetime', readonly),
12207
12441
  inputFormat: 'YYYY-MM-DD HH:mm',
12208
- format: 'YYYY-MM-DDTHH:mm:ss.SSSZ',
12442
+ format: 'YYYY-MM-DDTHH:mm:00.000Z',
12209
12443
  tpl: readonly ? getDateTimeTpl(field) : null,
12210
12444
  utc: true,
12211
12445
  };
@@ -12336,6 +12570,36 @@ async function convertSFieldToAmisField(field, readonly, ctx) {
12336
12570
  convertData = {
12337
12571
  type: 'static-text'
12338
12572
  };
12573
+ }else if(field.autonumber_enable_modify){
12574
+ convertData = {
12575
+ "type": "input-group",
12576
+ "body": [
12577
+ {
12578
+ "type": "input-text",
12579
+ "name": field.name
12580
+ },
12581
+ {
12582
+ "type": "button",
12583
+ "label": "自动获取",
12584
+ "actionType": "ajax",
12585
+ "api": {
12586
+ "url": `\${context.rootUrl}/api/autonumber/generator/\${objectName}/${field.name}`,
12587
+ "method": "post",
12588
+ "headers": {
12589
+ "Authorization": "Bearer ${context.tenantId},${context.authToken}"
12590
+ },
12591
+ "adaptor": `
12592
+ payload.data["${field.name}"] = payload.data && payload.data.autonumber;
12593
+ delete payload.data.autonumber;
12594
+ return payload;
12595
+ `
12596
+ },
12597
+ "messages": {
12598
+ "success": "获取成功"
12599
+ }
12600
+ }
12601
+ ]
12602
+ };
12339
12603
  }
12340
12604
  break;
12341
12605
  case 'url':
@@ -12541,12 +12805,13 @@ async function convertSFieldToAmisField(field, readonly, ctx) {
12541
12805
  break;
12542
12806
  }
12543
12807
  if(!___namespace.isEmpty(convertData)){
12808
+ const className = convertData.className;
12544
12809
  if(field.is_wide || convertData.type === 'group'){
12545
- convertData.className = 'col-span-2 m-0';
12810
+ convertData.className = className ? 'col-span-2 m-0 ' + className : 'col-span-2 m-0';
12546
12811
  }else {
12547
- convertData.className = 'm-0';
12812
+ convertData.className = className ? 'm-0 ' + className : 'm-0';
12548
12813
  }
12549
- if(readonly){
12814
+ if(readonly && ctx.mode !== 'edit'){
12550
12815
  convertData.className = `${convertData.className} border-b`;
12551
12816
  }
12552
12817
  if(readonly){
@@ -12554,11 +12819,7 @@ async function convertSFieldToAmisField(field, readonly, ctx) {
12554
12819
  }
12555
12820
 
12556
12821
  let fieldTypeClassName = ' steedos-' + convertData.type + (readonly ? '-readonly' : '-edit');
12557
- if (convertData.className) {
12558
- convertData.className = convertData.className + fieldTypeClassName;
12559
- } else {
12560
- convertData.className = fieldTypeClassName;
12561
- }
12822
+ convertData.className = convertData.className + fieldTypeClassName;
12562
12823
 
12563
12824
  if(field.visible_on && !ctx.inFilterForm){
12564
12825
  // convertData.visibleOn = `\$${field.visible_on.substring(1, field.visible_on.length -1).replace(/formData./g, '')}`;
@@ -12641,8 +12902,9 @@ async function getFieldSearchable(perField, permissionFields, ctx){
12641
12902
  fieldNamePrefix = `${fieldNamePrefix}between__`;
12642
12903
  }
12643
12904
  if(_field.type === 'datetime'){
12644
- // 特意改为日期范围而不是日期时间范围,因为搜索时一般精确到日期就足够了,需要精确到日期时间范围需要在字段上配置amis属性来实现
12645
- _field.type = 'input-date-range';
12905
+ // 这里如果想把搜索范围展示效果改为日期范围,不可以直接改为input-date-range,因为它们规则不一样,包括时区规则和小时分秒的存值规则都不一样
12906
+ // 所以想改为展示日期范围效果,只能改input-datetime-range类型本身的属性来实现
12907
+ _field.type = 'input-datetime-range';
12646
12908
  _field.is_wide = true;
12647
12909
  fieldNamePrefix = `${fieldNamePrefix}between__`;
12648
12910
  }
@@ -12828,6 +13090,13 @@ const getSection = async (formFields, permissionFields, fieldSchemaArray, sectio
12828
13090
  }
12829
13091
  }
12830
13092
 
13093
+ fieldSetBody.forEach((field)=>{
13094
+ //判断label是否存在,不存在时将label的空占位元素隐藏
13095
+ if(!field.label){
13096
+ field.labelClassName = "none";
13097
+ }
13098
+ });
13099
+
12831
13100
  // fieldSet 已支持显隐控制
12832
13101
  const sectionFieldsVisibleOn = ___namespace.map(___namespace.compact(___namespace.map(fieldSetBody, 'visibleOn')), (visibleOn) => {
12833
13102
  let visible = visibleOn;
@@ -12950,12 +13219,130 @@ async function getFormBody(permissionFields, formFields, ctx){
12950
13219
  return await getSections(permissionFields, formFields, ctx);
12951
13220
  }
12952
13221
 
13222
+ /*
13223
+ * @Author: 殷亮辉 yinlianghui@hotoa.com
13224
+ * @Date: 2024-01-18 15:12:41
13225
+ * @LastEditors: 殷亮辉 yinlianghui@hotoa.com
13226
+ * @LastEditTime: 2024-01-18 15:12:49
13227
+ */
13228
+ /**
13229
+ * 生成符合标准uuid格式的36位满足唯一性的随机串
13230
+ * @returns uuid
13231
+ */
13232
+ function uuidv4() {
13233
+ return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c =>
13234
+ (c ^ window.crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
13235
+ );
13236
+ }
13237
+
12953
13238
  /*
12954
13239
  * @Author: 殷亮辉 yinlianghui@hotoa.com
12955
13240
  * @Date: 2023-11-15 09:50:22
12956
13241
  * @LastEditors: 殷亮辉 yinlianghui@hotoa.com
12957
- * @LastEditTime: 2024-01-18 10:29:57
13242
+ * @LastEditTime: 2024-01-26 17:47:16
13243
+ */
13244
+
13245
+ /**
13246
+ * 子表组件字段值中每行数据补上字段值为空的的字段值,把值统一设置为空字符串,是为了解决amis amis 3.6/6.0 input-table组件bug:行中字段值为空时会显示为父作用域中的同名变量值,见:https://github.com/baidu/amis/issues/9520
13247
+ * amis #9520修正后此函数及相关代码可以移除
13248
+ * @param {*} value 子表组件字段值,数组
13249
+ * @param {*} fields 子表组件fields属性,数组
13250
+ * @returns 转换后的子表组件字段值
13251
+ */
13252
+ function getTableValueWithEmptyValue(value, fields) {
13253
+ return (value || []).map((itemValue) => {
13254
+ //这里不clone的话,会造成在pipeIn函数执行该函数后像pipeOut一样最终输出到表单项中,即库里字段值会被改了
13255
+ const newItemValue = _$1.clone(itemValue);
13256
+ (fields || []).forEach((itemField) => {
13257
+ if(itemField.name && (newItemValue[itemField.name] === undefined || newItemValue[itemField.name] === null)){
13258
+ // 这里newItemValue中不存在 itemField.name 属性,或者值为null时都会有“显示为父作用域中的同名变量值”的问题,所以null和undefined都要重置为空字符串
13259
+ // 实测数字、下拉框、多选lookup等字段类型重置为空字符串都不会有问题,而且实测amis from组件的清空表单字段值功能就是把表单中的各种字段类型设置为空字符串,所以看起来也符合amis规范
13260
+ newItemValue[itemField.name] = "";
13261
+ }
13262
+ if (newItemValue.children) {
13263
+ newItemValue.children = getTableValueWithEmptyValue(newItemValue.children, fields);
13264
+ }
13265
+ });
13266
+ return newItemValue;
13267
+ });
13268
+ }
13269
+
13270
+ /**
13271
+ * 把子表组件字段值中每行数据中经过上面getTableValueWithEmptyValue函数空字段值移除
13272
+ * amis #9520修正后此函数及相关代码可以移除
13273
+ * @param {*} value 子表组件字段值,数组
13274
+ * @param {*} fields 子表组件fields属性,数组
13275
+ * @returns 转换后的子表组件字段值
13276
+ */
13277
+ function getTableValueWithoutEmptyValue(value, fields) {
13278
+ return (value || []).map((itemValue) => {
13279
+ const newItemValue = _$1.clone(itemValue);
13280
+ (fields || []).forEach((itemField) => {
13281
+ if(itemField.name && (newItemValue[itemField.name] === "" || newItemValue[itemField.name] === undefined || newItemValue[itemField.name] === null)){
13282
+ // 这里额外把null和undefined值也删除掉纯粹是没必要输出保存它们
13283
+ delete newItemValue[itemField.name];
13284
+ }
13285
+ if (newItemValue.children) {
13286
+ newItemValue.children = getTableValueWithoutEmptyValue(newItemValue.children, fields);
13287
+ }
13288
+ });
13289
+ return newItemValue;
13290
+ });
13291
+ }
13292
+
13293
+ function getTablePrimaryKey(props) {
13294
+ return props.primaryKey || "_id";
13295
+ }
13296
+
13297
+ /**
13298
+ * 子表组件字段值中每行数据的补上唯一标识字段值,其值为随机uuid
13299
+ * @param {*} value 子表组件字段值,数组
13300
+ * @param {*} primaryKey 主键字段名,一般为_id
13301
+ * @returns 转换后的子表组件字段值
13302
+ */
13303
+ function getTableValueWithPrimaryKeyValue(value, primaryKey) {
13304
+ if (!primaryKey) {
13305
+ return value;
13306
+ }
13307
+ return (value || []).map((itemValue) => {
13308
+ //这里不clone的话,会造成在pipeIn函数执行该函数后像pipeOut一样最终输出到表单项中,即库里把primaryKey字段值保存了
13309
+ const newItemValue = _$1.clone(itemValue);
13310
+ if (newItemValue[primaryKey]) {
13311
+ if (newItemValue.children) {
13312
+ newItemValue.children = getTableValueWithPrimaryKeyValue(newItemValue.children, primaryKey);
13313
+ }
13314
+ return newItemValue;
13315
+ }
13316
+ else {
13317
+ newItemValue[primaryKey] = uuidv4();
13318
+ if (newItemValue.children) {
13319
+ newItemValue.children = getTableValueWithPrimaryKeyValue(newItemValue.children, primaryKey);
13320
+ }
13321
+ return newItemValue;
13322
+ }
13323
+ });
13324
+ }
13325
+
13326
+ /**
13327
+ * 子表组件字段值中每行数据的移除唯一标识字段值,因为该字段值一般只作临时标记,不存库
13328
+ * @param {*} value 子表组件字段值,数组
13329
+ * @param {*} primaryKey 主键字段名,一般为_id
13330
+ * @returns 转换后的子表组件字段值
12958
13331
  */
13332
+ function getTableValueWithoutPrimaryKeyValue(value, primaryKey) {
13333
+ if (!primaryKey) {
13334
+ return value;
13335
+ }
13336
+ return (value || []).map((itemValue) => {
13337
+ //这里clone只是为了保险,不是必须的,每次修改子表数据是否都会生成新的primaryKey字段值是由pipeOut中识别autoGeneratePrimaryKeyValue决定的,跟这里没关系
13338
+ const newItemValue = _$1.clone(itemValue);
13339
+ if (newItemValue.children) {
13340
+ newItemValue.children = getTableValueWithoutPrimaryKeyValue(newItemValue.children, primaryKey);
13341
+ }
13342
+ delete newItemValue[primaryKey];
13343
+ return newItemValue;
13344
+ });
13345
+ }
12959
13346
 
12960
13347
  /**
12961
13348
  * 子表组件字段值中每行数据的键值key移除指定前缀
@@ -12963,12 +13350,14 @@ async function getFormBody(permissionFields, formFields, ctx){
12963
13350
  * @param {*} fieldPrefix 字段前缀
12964
13351
  * @returns 转换后的子表组件字段值
12965
13352
  */
12966
- function getTableValueWithoutFieldPrefix(value, fieldPrefix){
13353
+ function getTableValueWithoutFieldPrefix(value, fieldPrefix) {
12967
13354
  let convertedValue = [];
12968
- (value || []).forEach((itemValue)=>{
13355
+ (value || []).forEach((itemValue) => {
12969
13356
  var newItemValue = {};
12970
- for(let n in itemValue){
12971
- newItemValue[n.replace(new RegExp(`^${fieldPrefix}`), "")] = itemValue[n];
13357
+ for (let n in itemValue) {
13358
+ if (itemValue.hasOwnProperty(n)) {
13359
+ newItemValue[n.replace(new RegExp(`^${fieldPrefix}`), "")] = itemValue[n];
13360
+ }
12972
13361
  }
12973
13362
  convertedValue.push(newItemValue);
12974
13363
  });
@@ -12979,17 +13368,21 @@ function getTableValueWithoutFieldPrefix(value, fieldPrefix){
12979
13368
  * 子表组件字段值中每行数据的键值key补上指定前缀
12980
13369
  * @param {*} value 子表组件字段值,数组
12981
13370
  * @param {*} fieldPrefix 字段前缀
13371
+ * @param {*} primaryKey 主键字段名,主键不参与被键值key规则,需要排除,审批王amis表单也是这个规则
12982
13372
  * @returns 转换后的子表组件字段值
12983
13373
  */
12984
- function getTableValuePrependFieldPrefix(value, fieldPrefix){
13374
+ function getTableValuePrependFieldPrefix(value, fieldPrefix, primaryKey) {
12985
13375
  let convertedValue = [];
12986
- (value || []).forEach((itemValue)=>{
13376
+ (value || []).forEach((itemValue) => {
12987
13377
  var newItemValue = {};
12988
- for(let n in itemValue){
12989
- if(typeof itemValue[n] !== undefined){
13378
+ for (let n in itemValue) {
13379
+ if (itemValue.hasOwnProperty(n) && typeof itemValue[n] !== undefined && n !== primaryKey) {
12990
13380
  newItemValue[`${fieldPrefix}${n}`] = itemValue[n];
12991
13381
  }
12992
13382
  }
13383
+ if (primaryKey && itemValue[primaryKey]) {
13384
+ newItemValue[primaryKey] = itemValue[primaryKey];
13385
+ }
12993
13386
  convertedValue.push(newItemValue);
12994
13387
  });
12995
13388
  return convertedValue;
@@ -13001,7 +13394,7 @@ function getTableValuePrependFieldPrefix(value, fieldPrefix){
13001
13394
  * @param {*} fieldPrefix 字段前缀
13002
13395
  * @returns 转换后的子表组件字段值
13003
13396
  */
13004
- function getTableFieldsWithoutFieldPrefix(fields, fieldPrefix){
13397
+ function getTableFieldsWithoutFieldPrefix(fields, fieldPrefix) {
13005
13398
  return (fields || []).map((item) => {
13006
13399
  const newItem = _$1.clone(item);//这里不clone的话,会造成子表组件重新render,从而审批王那边点开子表行编辑窗口时报错
13007
13400
  newItem.name = newItem.name.replace(new RegExp(`^${fieldPrefix}`), "");
@@ -13014,7 +13407,12 @@ function getTableFieldsWithoutFieldPrefix(fields, fieldPrefix){
13014
13407
  * @param {*} mode edit/new/readonly
13015
13408
  */
13016
13409
  function getFormFields(props, mode = "edit") {
13017
- return (props.fields || []).map(function (item) {
13410
+ let fieldPrefix = props.fieldPrefix;
13411
+ let fields = props.fields || [];
13412
+ if (fieldPrefix) {
13413
+ fields = getTableFieldsWithoutFieldPrefix(fields, fieldPrefix);
13414
+ }
13415
+ return (fields || []).map(function (item) {
13018
13416
  let formItem = {
13019
13417
  "type": "steedos-field",
13020
13418
  "name": item.name,
@@ -13034,6 +13432,7 @@ function getInputTableCell(field, showAsInlineEditMode) {
13034
13432
  name: field.name,
13035
13433
  quickEdit: {
13036
13434
  "type": "steedos-field",
13435
+ "mode": "inline",
13037
13436
  "config": Object.assign({}, field, {
13038
13437
  label: false
13039
13438
  })
@@ -13086,7 +13485,12 @@ async function getInputTableColumns(props) {
13086
13485
  let inlineEditMode = props.inlineEditMode;
13087
13486
  let showAsInlineEditMode = inlineEditMode && props.editable;
13088
13487
  // 实测过,直接不生成对应的隐藏column并不会对input-table值造成丢失问题,隐藏的列字段值能正常维护
13089
- let fields = props.fields;
13488
+
13489
+ let fieldPrefix = props.fieldPrefix;
13490
+ let fields = props.fields || [];
13491
+ if (fieldPrefix) {
13492
+ fields = getTableFieldsWithoutFieldPrefix(fields, fieldPrefix);
13493
+ }
13090
13494
  if (columns && columns.length) {
13091
13495
  return columns.map(function (column) {
13092
13496
  let field, extendColumnProps = {};
@@ -13108,8 +13512,26 @@ async function getInputTableColumns(props) {
13108
13512
  }
13109
13513
  }
13110
13514
  if (field) {
13111
- let tableCell = getInputTableCell(field, showAsInlineEditMode);
13112
- return Object.assign({}, tableCell, extendColumnProps);
13515
+ let mode = typeof extendColumnProps.inlineEditMode === "boolean" ?
13516
+ extendColumnProps.inlineEditMode : showAsInlineEditMode;
13517
+ let tableCell = getInputTableCell(field, mode);
13518
+ let className = "";
13519
+ //判断是否换行,目前规则默认换行
13520
+ if(extendColumnProps.wrap != true){
13521
+ className += " whitespace-nowrap ";
13522
+ }else {
13523
+ className += " break-words ";
13524
+ }
13525
+ //合并classname
13526
+ if (typeof extendColumnProps.className == "object") {
13527
+ className = {
13528
+ [className]: "true",
13529
+ ...extendColumnProps.className
13530
+ };
13531
+ } else if (typeof extendColumnProps.className == "string") {
13532
+ className = `${className} ${extendColumnProps.className} `;
13533
+ }
13534
+ return Object.assign({}, tableCell, extendColumnProps, {className});
13113
13535
  }
13114
13536
  else {
13115
13537
  return column;
@@ -13119,6 +13541,7 @@ async function getInputTableColumns(props) {
13119
13541
  else {
13120
13542
  return fields.map(function (field) {
13121
13543
  let tableCell = getInputTableCell(field, showAsInlineEditMode);
13544
+ tableCell.className = " whitespace-nowrap ";
13122
13545
  return tableCell;
13123
13546
  }) || [];
13124
13547
  }
@@ -13131,7 +13554,7 @@ async function getInputTableColumns(props) {
13131
13554
  */
13132
13555
  function getFormPagination(props, mode) {
13133
13556
  let showPagination = true;
13134
- if(mode === "new" && !!!props.editable){
13557
+ if (mode === "new" && !!!props.editable) {
13135
13558
  //不允许编辑只允许新建时不应该让用户操作翻页
13136
13559
  showPagination = false;
13137
13560
  }
@@ -13147,35 +13570,41 @@ function getFormPagination(props, mode) {
13147
13570
  let __formId = "${formId}";
13148
13571
  let fieldValue = event.data.__tableItems;//这里不可以_.cloneDeep,因为翻页form中用的是event.data.__tableItems,直接变更其值即可改变表单中的值
13149
13572
  let pageChangeDirection = context.props.pageChangeDirection;
13573
+ let mode = "${mode}";
13150
13574
  // event.data中的index和__page分别表示当前要把表单数据提交到的行索引和用于标定下一页页码的当前页页码
13151
13575
  // 一般来说__page = index + 1,但是可以让event.data中传入__page和index值不是这种联系。
13152
13576
  // 比如__page设置为3,index设置为0表示把当前表单数据提交到第一页,但是跳转到第4页,弹出的表单中底下的新增和复制按钮依赖了此功能
13153
13577
  // let currentPage = currentIndex + 1;
13154
13578
  let currentPage = event.data.__page;
13155
13579
  let currentIndex = event.data.index;
13156
- // 翻页到下一页之前需要先把当前页改动的内容保存到中间变量__tableItems中
13157
- let currentFormValues = scope.getComponentById(__formId).getValues();
13158
- var parent = event.data.parent;
13159
- var __parentIndex = event.data.__parentIndex;
13160
- if(parent){
13161
- fieldValue[__parentIndex].children[currentIndex] = currentFormValues;
13162
- // 重写父节点,并且改变其某个属性以让子节点修改的内容回显到界面上
13163
- fieldValue[__parentIndex] = Object.assign({}, fieldValue[__parentIndex], {
13164
- children: fieldValue[__parentIndex].children,
13165
- __fix_rerender_after_children_modified_tag: new Date().getTime()
13580
+ if(mode !== "readonly"){
13581
+ // 新建编辑时,翻页才需要把当前页表单保存,只读时直接翻页即可
13582
+ // 翻页到下一页之前需要先把当前页改动的内容保存到中间变量__tableItems中
13583
+ let currentFormValues = scope.getComponentById(__formId).getValues();
13584
+ // 这里不clone的话,其值会带上__super属性
13585
+ currentFormValues = _.clone(currentFormValues);
13586
+ var parent = event.data.parent;
13587
+ var __parentIndex = event.data.__parentIndex;
13588
+ if(parent){
13589
+ fieldValue[__parentIndex].children[currentIndex] = currentFormValues;
13590
+ // 重写父节点,并且改变其某个属性以让子节点修改的内容回显到界面上
13591
+ fieldValue[__parentIndex] = Object.assign({}, fieldValue[__parentIndex], {
13592
+ children: fieldValue[__parentIndex].children,
13593
+ __fix_rerender_after_children_modified_tag: new Date().getTime()
13594
+ });
13595
+ }
13596
+ else{
13597
+ fieldValue[currentIndex] = currentFormValues;
13598
+ }
13599
+ // 翻页到下一页前需要同时把改动的内容保存到最终正式的表单字段中,所以额外给正式表单字段执行一次setValue
13600
+ doAction({
13601
+ "componentId": "${props.id}",
13602
+ "actionType": "setValue",
13603
+ "args": {
13604
+ "value": fieldValue
13605
+ }
13166
13606
  });
13167
13607
  }
13168
- else{
13169
- fieldValue[currentIndex] = currentFormValues;
13170
- }
13171
- // 翻页到下一页前需要同时把改动的内容保存到最终正式的表单字段中,所以额外给正式表单字段执行一次setValue
13172
- doAction({
13173
- "componentId": "${props.id}",
13174
- "actionType": "setValue",
13175
- "args": {
13176
- "value": fieldValue
13177
- }
13178
- });
13179
13608
 
13180
13609
  // 以下是翻页逻辑,翻到下一页并把下一页内容显示到表单上
13181
13610
  let targetPage;
@@ -13224,9 +13653,14 @@ function getFormPagination(props, mode) {
13224
13653
  "onEvent": {
13225
13654
  "click": {
13226
13655
  "actions": [
13656
+ {
13657
+ "actionType": "validate",
13658
+ "componentId": formId
13659
+ },
13227
13660
  {
13228
13661
  "actionType": "custom",
13229
- "script": onPageChangeScript
13662
+ "script": onPageChangeScript,
13663
+ "expression": "${!!!event.data.validateResult.error}" //触发表单校验结果会存入validateResult,amis 3.2不支持,高版本比如 3.5.3支持
13230
13664
  }
13231
13665
  ]
13232
13666
  }
@@ -13235,7 +13669,7 @@ function getFormPagination(props, mode) {
13235
13669
  {
13236
13670
  "type": "tpl",
13237
13671
  // 这里用__super.parent,加__super是为了防止当前记录有字段名为parent的重名变量
13238
- "tpl": "${__page}/${__super.parent ? __tableItems[__parentIndex]['children'].length : __tableItems.length}"
13672
+ "tpl": "${__page}/${__super.parent ? COMPACT(__tableItems[__parentIndex]['children']).length : COMPACT(__tableItems).length}"
13239
13673
  },
13240
13674
  {
13241
13675
  "type": "button",
@@ -13245,15 +13679,20 @@ function getFormPagination(props, mode) {
13245
13679
  "pageChangeDirection": "next",
13246
13680
  // "disabledOn": showPagination ? "${__page >= __tableItems.length}" : "true",
13247
13681
  // 这里用__super.parent,加__super是为了防止当前记录有字段名为parent的重名变量
13248
- "disabledOn": showPagination ? "${__page >= (__super.parent ? __tableItems[__parentIndex]['children'].length : __tableItems.length)}" : "true",
13682
+ "disabledOn": showPagination ? "${__page >= (__super.parent ? COMPACT(__tableItems[__parentIndex]['children']).length : COMPACT(__tableItems).length)}" : "true",
13249
13683
  "size": "sm",
13250
13684
  "id": buttonNextId,
13251
13685
  "onEvent": {
13252
13686
  "click": {
13253
13687
  "actions": [
13688
+ {
13689
+ "actionType": "validate",
13690
+ "componentId": formId
13691
+ },
13254
13692
  {
13255
13693
  "actionType": "custom",
13256
- "script": onPageChangeScript
13694
+ "script": onPageChangeScript,
13695
+ "expression": "${!!!event.data.validateResult.error}" //触发表单校验结果会存入validateResult,amis 3.2不支持,高版本比如 3.5.3支持
13257
13696
  }
13258
13697
  ]
13259
13698
  }
@@ -13274,6 +13713,7 @@ function getFormPaginationWrapper(props, form, mode) {
13274
13713
  // console.log("==getFormPaginationWrapper===", props, mode);
13275
13714
  let serviceId = getComponentId("form_pagination", props.id);
13276
13715
  let tableServiceId = getComponentId("table_service", props.id);
13716
+ let primaryKey = getTablePrimaryKey(props);
13277
13717
  let innerForm = Object.assign({}, form, {
13278
13718
  "data": {
13279
13719
  // 这里加__super前缀是因为__parentForm变量(即主表单)中可能会正好有名为index的字段
@@ -13301,7 +13741,6 @@ function getFormPaginationWrapper(props, form, mode) {
13301
13741
  }
13302
13742
  ];
13303
13743
  let onServiceInitedScript = `
13304
-
13305
13744
  // 以下脚本解决了有时弹出编辑表单时,表单中的值比最后一次编辑保存的值会延迟一拍。
13306
13745
  // 比如:inlineEditMode模式时,用户在表格单元格中直接修改数据,然后弹出的表单form中并没有包含单元格中修改的内容
13307
13746
  // 另外有的地方在非inlineEditMode模式时也会有这种延迟一拍问题,比如对象字段中下拉框类型字段的”选择项“属性
@@ -13315,13 +13754,13 @@ function getFormPaginationWrapper(props, form, mode) {
13315
13754
  // 这里不可以用event.data["${props.name}"]因为amis input talbe有一层单独的作用域,其值会延迟一拍
13316
13755
  // 这里如果不.clone的话,在弹出窗口中显示的子表组件,添加行后点窗口的取消按钮关闭窗口后无法把之前的操作还原,即把之前添加的行自动移除
13317
13756
  let lastestFieldValue = _.clone(wrapperServiceData["${props.name}"] || []);
13318
- let fieldPrefix = "${props.fieldPrefix}";
13757
+ let fieldPrefix = "${props.fieldPrefix || ''}";
13319
13758
  if(fieldPrefix){
13320
13759
  let getTableValueWithoutFieldPrefix = new Function('v', 'f', "return (" + ${getTableValueWithoutFieldPrefix.toString()} + ")(v, f)");
13321
13760
  lastestFieldValue = getTableValueWithoutFieldPrefix(lastestFieldValue, fieldPrefix);
13322
13761
  }
13323
13762
  //不可以直接像event.data.__tableItems = lastestFieldValue; 这样整个赋值,否则作用域会断
13324
- let mode = "${mode}";
13763
+ let mode = "${mode || ''}";
13325
13764
  if(mode === "new"){
13326
13765
  // 点击子表组件底部新增按钮时新增一条空白行并自动翻页到新增行
13327
13766
  // 注意点击弹出的子表行详细表单中的新增按钮不会进此service init事件函数中
@@ -13347,10 +13786,20 @@ function getFormPaginationWrapper(props, form, mode) {
13347
13786
  var fieldValue = event.data.__tableItems;
13348
13787
  if(parent){
13349
13788
  // 如果是子行,即在节点嵌套情况下,当前节点如果是children属性下的子节点时,则算出其所属父行的索引值
13350
- var primaryKey = "${props.primaryKey}";
13789
+ var primaryKey = "${primaryKey}";
13351
13790
  event.data.__parentIndex = _.findIndex(fieldValue, function(item){
13352
13791
  return item[primaryKey] == parent[primaryKey];
13353
13792
  });
13793
+ if(event.data.__parentIndex < 0){
13794
+ let tableId = "${props.id}";
13795
+ let table = scope.getComponentById(tableId)
13796
+ // autoGeneratePrimaryKeyValue不为true的情况下,即子表组件input-table的pipeOut函数中会移除表单了子表字段的primaryKey字段值,
13797
+ // 此时行primaryKey字段值为空,但是pipeIn函数中已经为input-table自动生成过primaryKey字段值了,只是没有输出到表单字段值中而已
13798
+ // 所以上面从表单字段值中没找到__parentIndex,是因为此时行primaryKey字段值只经过pipeIn保存到table组件内而没有保存到tableService
13799
+ event.data.__parentIndex = _.findIndex(table.props.value, function(item){
13800
+ return item[primaryKey] == parent[primaryKey];
13801
+ });
13802
+ }
13354
13803
  }
13355
13804
  `;
13356
13805
  let schema = {
@@ -13399,6 +13848,7 @@ function getFormPaginationWrapper(props, form, mode) {
13399
13848
  async function getForm(props, mode = "edit", formId) {
13400
13849
  let formFields = getFormFields(props, mode);
13401
13850
  let body = await getFormBody(null, formFields);
13851
+ let primaryKey = getTablePrimaryKey(props);
13402
13852
  if (!formId) {
13403
13853
  formId = getComponentId("form", props.id);
13404
13854
  }
@@ -13417,6 +13867,18 @@ async function getForm(props, mode = "edit", formId) {
13417
13867
  // 新增行弹出编辑行表单,在弹出之前已经不用先增加一行,因为在翻页service初始化的时候会判断mode为new时自动新增一行
13418
13868
  let onEditItemSubmitScript = `
13419
13869
  // let fieldValue = _.cloneDeep(event.data["${props.name}"]);
13870
+ let removeEmptyItems = function(items){
13871
+ let i = _.findIndex(items, function(item){
13872
+ return item === undefined
13873
+ });
13874
+ if(i > -1){
13875
+ items.splice(i, 1);
13876
+ removeEmptyItems(items);
13877
+ }
13878
+ }
13879
+ // 因为删除时只是把input-table组件中的行数据删除了,并没有把父层service中的行删除,所以__tableItems会有值为undefined的数据,需要移除掉
13880
+ // 不用event.data.__tableItems = _.compact(event.data.__tableItems)是因为会把__tableItems变量保存到表单中
13881
+ removeEmptyItems(event.data.__tableItems);
13420
13882
  let fieldValue = event.data.__tableItems;//这里不可以_.cloneDeep,因为翻页form中用的是event.data.__tableItems,直接变更其值即可改变表单中的值
13421
13883
  //这里加__super.__super前缀是因为__parentForm变量(即主表单)中可能会正好有名为index的字段
13422
13884
  // 比如“对象字段”对象options字段是一个子表字段,但是主表(即“对象字段”对象)中正好有一个名为index的字段
@@ -13425,6 +13887,8 @@ async function getForm(props, mode = "edit", formId) {
13425
13887
  var currentFormValues = JSON.parse(JSON.stringify(event.data));
13426
13888
  var parent = event.data.__super.__super.parent;
13427
13889
  var __parentIndex = event.data.__super.__super.__parentIndex;
13890
+ let uuidv4 = new Function("return (" + ${uuidv4.toString()} + ")()");
13891
+ var primaryKey = "${primaryKey}";
13428
13892
  if(parent){
13429
13893
  fieldValue[__parentIndex].children[currentIndex] = currentFormValues;
13430
13894
  // 重写父节点,并且改变其某个属性以让子节点修改的内容回显到界面上
@@ -13434,6 +13898,8 @@ async function getForm(props, mode = "edit", formId) {
13434
13898
  });
13435
13899
  }
13436
13900
  else{
13901
+ // 这里currentFormValues中如果没有primaryKey字段值不用处理,因为组件的pipeIn/pipeOut中会为每行自动生成
13902
+ // 也不用担心复制行时_id会重复,因为点击复制按钮时已经处理过了
13437
13903
  fieldValue[currentIndex] = currentFormValues;
13438
13904
  }
13439
13905
  doAction({
@@ -13531,13 +13997,14 @@ async function getForm(props, mode = "edit", formId) {
13531
13997
  */
13532
13998
  async function getButtonActions(props, mode) {
13533
13999
  let actions = [];
14000
+ let primaryKey = getTablePrimaryKey(props);
13534
14001
  let formId = getComponentId("form", props.id);
13535
14002
  let dialogId = getComponentId("dialog", props.id);
13536
14003
  let buttonNextId = getComponentId("button_next", props.id);
13537
14004
  let formPaginationId = getComponentId("form_pagination", props.id);
13538
14005
  let parentFormData = "${__super.__super.__super.__super || {}}";
13539
14006
  let amisVersion = getComparableAmisVersion();
13540
- if(amisVersion < 3.6){
14007
+ if (amisVersion < 3.6) {
13541
14008
  parentFormData = "${__super.__super || {}}";
13542
14009
  }
13543
14010
  if (mode == "new" || mode == "edit") {
@@ -13573,13 +14040,35 @@ async function getButtonActions(props, mode) {
13573
14040
  // };
13574
14041
  let onSaveAndNewItemScript = `
13575
14042
  let scope = event.context.scoped;
14043
+ let removeEmptyItems = function(items){
14044
+ let i = _.findIndex(items, function(item){
14045
+ return item === undefined
14046
+ });
14047
+ if(i > -1){
14048
+ items.splice(i, 1);
14049
+ removeEmptyItems(items);
14050
+ }
14051
+ }
14052
+ // 因为删除时只是把input-table组件中的行数据删除了,并没有把父层service中的行删除,所以__tableItems会有值为undefined的数据,需要移除掉
14053
+ // 不用event.data.__tableItems = _.compact(event.data.__tableItems)是因为会把__tableItems变量保存到表单中
14054
+ removeEmptyItems(event.data.__tableItems);
13576
14055
  let fieldValue = event.data.__tableItems;//这里不可以_.cloneDeep,因为翻页form中用的是event.data.__tableItems,直接变更其值即可改变表单中的值
13577
14056
  // 新建一条空白行并保存到子表组件
13578
14057
  var parent = event.data.__super.parent;
13579
- var primaryKey = "${props.primaryKey}";
14058
+ var primaryKey = "${primaryKey}";
13580
14059
  var __parentIndex = parent && _.findIndex(fieldValue, function(item){
13581
14060
  return item[primaryKey] == parent[primaryKey];
13582
14061
  });
14062
+ if(parent && __parentIndex < 0){
14063
+ let tableId = "${props.id}";
14064
+ let table = scope.getComponentById(tableId)
14065
+ // autoGeneratePrimaryKeyValue不为true的情况下,即子表组件input-table的pipeOut函数中会移除表单了子表字段的primaryKey字段值,
14066
+ // 此时行primaryKey字段值为空,但是pipeIn函数中已经为input-table自动生成过primaryKey字段值了,只是没有输出到表单字段值中而已
14067
+ // 所以上面从表单字段值中没找到__parentIndex,是因为此时行primaryKey字段值只经过pipeIn保存到table组件内而没有保存到tableService
14068
+ __parentIndex = _.findIndex(table.props.value, function(item){
14069
+ return item[primaryKey] == parent[primaryKey];
14070
+ });
14071
+ }
13583
14072
  if(parent){
13584
14073
  fieldValue[__parentIndex].children.push({});
13585
14074
  // 这里实测不需要fieldValue[__parentIndex] = ... 来重写整个父行让子表回显,所以没加相关代码
@@ -13613,14 +14102,42 @@ async function getButtonActions(props, mode) {
13613
14102
  let __formId = "${formId}";
13614
14103
  // let newItem = JSON.parse(JSON.stringify(event.data));
13615
14104
  let newItem = scope.getComponentById(__formId).getValues();//这里不可以用event.data,因为其拿到的是弹出表单时的初始值,不是用户实时填写的数据
14105
+ newItem = _.clone(newItem);
14106
+ let removeEmptyItems = function(items){
14107
+ let i = _.findIndex(items, function(item){
14108
+ return item === undefined
14109
+ });
14110
+ if(i > -1){
14111
+ items.splice(i, 1);
14112
+ removeEmptyItems(items);
14113
+ }
14114
+ }
14115
+ // 因为删除时只是把input-table组件中的行数据删除了,并没有把父层service中的行删除,所以__tableItems会有值为undefined的数据,需要移除掉
14116
+ // 不用event.data.__tableItems = _.compact(event.data.__tableItems)是因为会把__tableItems变量保存到表单中
14117
+ removeEmptyItems(event.data.__tableItems);
13616
14118
  let fieldValue = event.data.__tableItems;//这里不可以_.cloneDeep,因为翻页form中用的是event.data.__tableItems,直接变更其值即可改变表单中的值
13617
14119
  // 复制当前页数据到新建行并保存到子表组件
13618
14120
  // fieldValue.push(newItem);
13619
14121
  var parent = event.data.__super.parent;
13620
- var primaryKey = "${props.primaryKey}";
14122
+ var primaryKey = "${primaryKey}";
13621
14123
  var __parentIndex = parent && _.findIndex(fieldValue, function(item){
13622
14124
  return item[primaryKey] == parent[primaryKey];
13623
14125
  });
14126
+ if(parent && __parentIndex < 0){
14127
+ let tableId = "${props.id}";
14128
+ let table = scope.getComponentById(tableId)
14129
+ // autoGeneratePrimaryKeyValue不为true的情况下,即子表组件input-table的pipeOut函数中会移除表单了子表字段的primaryKey字段值,
14130
+ // 此时行primaryKey字段值为空,但是pipeIn函数中已经为input-table自动生成过primaryKey字段值了,只是没有输出到表单字段值中而已
14131
+ // 所以上面从表单字段值中没找到__parentIndex,是因为此时行primaryKey字段值只经过pipeIn保存到table组件内而没有保存到tableService
14132
+ __parentIndex = _.findIndex(table.props.value, function(item){
14133
+ return item[primaryKey] == parent[primaryKey];
14134
+ });
14135
+ }
14136
+ if(newItem[primaryKey]){
14137
+ // 如果newItem已经有主键字段值,则重新生成新的主键值,否则会重复。
14138
+ let uuidv4 = new Function("return (" + ${uuidv4.toString()} + ")()");
14139
+ newItem[primaryKey] = uuidv4();
14140
+ }
13624
14141
  if(parent){
13625
14142
  fieldValue[__parentIndex].children.push(newItem);
13626
14143
  // 这里实测不需要fieldValue[__parentIndex] = ... 来重写整个父行让子表回显,所以没加相关代码
@@ -13651,13 +14168,13 @@ async function getButtonActions(props, mode) {
13651
14168
  `;
13652
14169
  let dialogButtons = [
13653
14170
  {
13654
- "type": "button",
13655
- "label": "完成",
13656
- "actionType": "confirm",
13657
- "level": "primary"
14171
+ "type": "button",
14172
+ "label": "完成",
14173
+ "actionType": "confirm",
14174
+ "level": "primary"
13658
14175
  }
13659
14176
  ];
13660
- if(props.addable){
14177
+ if (props.addable) {
13661
14178
  // 有新增行权限时额外添加新增和复制按钮
13662
14179
  dialogButtons = [
13663
14180
  {
@@ -13667,9 +14184,14 @@ async function getButtonActions(props, mode) {
13667
14184
  "onEvent": {
13668
14185
  "click": {
13669
14186
  "actions": [
14187
+ {
14188
+ "actionType": "validate",
14189
+ "componentId": formId
14190
+ },
13670
14191
  {
13671
14192
  "actionType": "custom",
13672
- "script": onSaveAndNewItemScript
14193
+ "script": onSaveAndNewItemScript,
14194
+ "expression": "${!!!event.data.validateResult.error}" //触发表单校验结果会存入validateResult,amis 3.2不支持,高版本比如 3.5.3支持
13673
14195
  }
13674
14196
  ]
13675
14197
  }
@@ -13682,9 +14204,14 @@ async function getButtonActions(props, mode) {
13682
14204
  "onEvent": {
13683
14205
  "click": {
13684
14206
  "actions": [
14207
+ {
14208
+ "actionType": "validate",
14209
+ "componentId": formId
14210
+ },
13685
14211
  {
13686
14212
  "actionType": "custom",
13687
- "script": onSaveAndCopyItemScript
14213
+ "script": onSaveAndCopyItemScript,
14214
+ "expression": "${!!!event.data.validateResult.error}" //触发表单校验结果会存入validateResult,amis 3.2不支持,高版本比如 3.5.3支持
13688
14215
  }
13689
14216
  ]
13690
14217
  }
@@ -13730,7 +14257,7 @@ async function getButtonActions(props, mode) {
13730
14257
  // 在节点嵌套情况下,当前节点正好是带children属性的节点的话,这里弹出的dialog映射到的会是children数组,这是amis目前的规则,
13731
14258
  // 所以这里加判断有children时,用__super.__super让映射到正确的作用域层,如果不加,则__tableItems取到的会是children数组,而不是整个子表组件的值
13732
14259
  "__tableItems": `\${((children ? __super.__super.${props.name} : __super.${props.name}) || [])|json|toJson}`
13733
- },
14260
+ },
13734
14261
  "actions": dialogButtons,
13735
14262
  "onEvent": {
13736
14263
  "confirm": {
@@ -13828,7 +14355,10 @@ async function getButtonActions(props, mode) {
13828
14355
  // 为了解决"弹出的dialog窗口中子表组件会影响页面布局界面中父作用域字段值",比如设计字段布局微页面中的设置分组功能,弹出的就是子表dialog
13829
14356
  // 所以这里使用json|toJson转一次,断掉event.data.__tableItems与上层任用域中props.name的联系
13830
14357
  // "__tableItems": `\${${props.name}|json|toJson}`
13831
- "__tableItems": `\${((__super.parent ? __super.__super.${props.name} : __super.${props.name}) || [])|json|toJson}`
14358
+ // "__tableItems": `\${((__super.parent ? __super.__super.${props.name} : __super.${props.name}) || [])|json|toJson}`
14359
+ // 在节点嵌套情况下,当前节点正好是带children属性的节点的话,这里弹出的dialog映射到的会是children数组,这是amis目前的规则,
14360
+ // 所以这里加判断有children时,用__super.__super让映射到正确的作用域层,如果不加,则__tableItems取到的会是children数组,而不是整个子表组件的值
14361
+ "__tableItems": `\${((children ? __super.__super.${props.name} : __super.${props.name}) || [])|json|toJson}`
13832
14362
  },
13833
14363
  }
13834
14364
  }
@@ -13844,13 +14374,24 @@ async function getButtonActions(props, mode) {
13844
14374
  let wrapperServiceData = wrapperService.getData();
13845
14375
  // 这里不可以用event.data["${props.name}"]因为amis input talbe有一层单独的作用域,其值会延迟一拍
13846
14376
  // 这里_.clone是因为字段设计布局设置分组这种弹出窗口中的子表组件,直接删除后,点取消无法还原
14377
+ // 也因为这里clone没有直接删除,所以弹出编辑表单提交事件中event.data.__tableItems中取到的值会有被删除的行数据为undefined
13847
14378
  let lastestFieldValue = _.clone(wrapperServiceData["${props.name}"]);
13848
14379
  var currentIndex = event.data.index;
13849
14380
  var parent = event.data.__super.parent;
13850
- var primaryKey = "${props.primaryKey}";
14381
+ var primaryKey = "${primaryKey}";
13851
14382
  var __parentIndex = parent && _.findIndex(lastestFieldValue, function(item){
13852
14383
  return item[primaryKey] == parent[primaryKey];
13853
14384
  });
14385
+ if(parent && __parentIndex < 0){
14386
+ let tableId = "${props.id}";
14387
+ let table = scope.getComponentById(tableId)
14388
+ // autoGeneratePrimaryKeyValue不为true的情况下,即子表组件input-table的pipeOut函数中会移除表单了子表字段的primaryKey字段值,
14389
+ // 此时行primaryKey字段值为空,但是pipeIn函数中已经为input-table自动生成过primaryKey字段值了,只是没有输出到表单字段值中而已
14390
+ // 所以上面从表单字段值中没找到__parentIndex,是因为此时行primaryKey字段值只经过pipeIn保存到table组件内而没有保存到tableService
14391
+ __parentIndex = _.findIndex(table.props.value, function(item){
14392
+ return item[primaryKey] == parent[primaryKey];
14393
+ });
14394
+ }
13854
14395
  if(parent){
13855
14396
  lastestFieldValue[__parentIndex].children.splice(currentIndex, 1);
13856
14397
  // 重写父节点,并且改变其某个属性以让子节点修改的内容回显到界面上
@@ -13862,6 +14403,11 @@ async function getButtonActions(props, mode) {
13862
14403
  else{
13863
14404
  lastestFieldValue.splice(currentIndex, 1);
13864
14405
  }
14406
+ let fieldPrefix = "${props.fieldPrefix || ''}";
14407
+ if(fieldPrefix){
14408
+ let getTableValueWithoutFieldPrefix = new Function('v', 'f', "return (" + ${getTableValueWithoutFieldPrefix.toString()} + ")(v, f)");
14409
+ lastestFieldValue = getTableValueWithoutFieldPrefix(lastestFieldValue, fieldPrefix);
14410
+ }
13865
14411
  doAction({
13866
14412
  "componentId": "${props.id}",
13867
14413
  "actionType": "setValue",
@@ -13931,45 +14477,77 @@ async function getButtonView(props) {
13931
14477
 
13932
14478
  async function getButtonDelete(props) {
13933
14479
  return {
13934
- "type": "button",
13935
- "label": "",
13936
- "icon": "fa fa-trash-alt",//不可以用fa-trash-o,因为设计字段布局界面中弹出的设置分组列表中显示不了这个图标
14480
+ "type": "dropdown-button",
13937
14481
  "level": "link",
13938
- "onEvent": {
13939
- "click": {
13940
- "actions": await getButtonActions(props, "delete")
14482
+ "icon": "fa fa-trash-alt",
14483
+ "size": "xs",
14484
+ "hideCaret": true,
14485
+ "closeOnClick": true,
14486
+ "body": [
14487
+ {
14488
+ "type": "wrapper",
14489
+ "size": "md",
14490
+ "className": "w-80",
14491
+ "body": [
14492
+ {
14493
+ "tpl": "确定要删除吗?",
14494
+ "type": "tpl"
14495
+ },
14496
+ {
14497
+ "type": "flex",
14498
+ "justify": "flex-end",
14499
+ "className": "mt-3",
14500
+ "items": [
14501
+ {
14502
+ "type": "button",
14503
+ "label": "取消",
14504
+ "className": "mr-2"
14505
+ },
14506
+ {
14507
+ "type": "button",
14508
+ "label": "删除",
14509
+ "level": "danger",
14510
+ "onEvent": {
14511
+ "click": {
14512
+ "actions": await getButtonActions(props, "delete")
14513
+ }
14514
+ }
14515
+ }
14516
+ ]
14517
+ }
14518
+ ]
13941
14519
  }
13942
- }
13943
- };
14520
+ ]
14521
+ }
13944
14522
  }
13945
14523
 
14524
+
13946
14525
  const getAmisInputTableSchema = async (props) => {
13947
14526
  if (!props.id) {
13948
14527
  props.id = "steedos_input_table_" + props.name + "_" + Math.random().toString(36).substr(2, 9);
13949
14528
  }
13950
- if (!props.primaryKey) {
13951
- props.primaryKey = "_id";
13952
- }
14529
+ let primaryKey = getTablePrimaryKey(props);
13953
14530
  let showOperation = props.showOperation;
13954
- if(showOperation !== false){
14531
+ if (showOperation !== false) {
13955
14532
  showOperation = true;
13956
14533
  }
13957
- // props.fieldPrefix = "project_milestone_";
13958
- if (props.fieldPrefix) {
13959
- props.fields = getTableFieldsWithoutFieldPrefix(props.fields, props.fieldPrefix);
14534
+ let fieldPrefix = props.fieldPrefix;
14535
+ let fields = props.fields || [];
14536
+ if (fieldPrefix) {
14537
+ fields = getTableFieldsWithoutFieldPrefix(fields, fieldPrefix);
13960
14538
  }
13961
14539
  let serviceId = getComponentId("table_service", props.id);
13962
14540
  let buttonsForColumnOperations = [];
13963
14541
  let inlineEditMode = props.inlineEditMode;
13964
14542
  let showAsInlineEditMode = inlineEditMode && props.editable;
13965
- if(showOperation){
14543
+ if (showOperation) {
13966
14544
  if (props.editable) {
13967
14545
  let showEditButton = true;
13968
14546
  if (showAsInlineEditMode) {
13969
14547
  // 始终显示弹出子表表单按钮,如果需要判断只在有列被隐藏时才需要显示弹出表单按钮放开下面的if逻辑就好
13970
14548
  showEditButton = true;
13971
14549
  // // inline edit模式下只在有列被隐藏时才需要显示编辑按钮
13972
- // if (props.columns && props.columns.length > 0 && props.columns.length < props.fields.length) {
14550
+ // if (props.columns && props.columns.length > 0 && props.columns.length < fields.length) {
13973
14551
  // showEditButton = true;
13974
14552
  // }
13975
14553
  // else {
@@ -13984,7 +14562,7 @@ const getAmisInputTableSchema = async (props) => {
13984
14562
  }
13985
14563
  else {
13986
14564
  // 只读时显示查看按钮
13987
- // 如果想只在有列被隐藏时才需要显示查看按钮可以加上判断:if (props.columns && props.columns.length > 0 && props.columns.length < props.fields.length)
14565
+ // 如果想只在有列被隐藏时才需要显示查看按钮可以加上判断:if (props.columns && props.columns.length > 0 && props.columns.length < fields.length)
13988
14566
  let buttonViewSchema = await getButtonView(props);
13989
14567
  buttonsForColumnOperations.push(buttonViewSchema);
13990
14568
  }
@@ -13993,10 +14571,10 @@ const getAmisInputTableSchema = async (props) => {
13993
14571
  buttonsForColumnOperations.push(buttonDeleteSchema);
13994
14572
  }
13995
14573
  }
13996
- let amis = props["input-table"] || props.amis;//额外支持"input-table"代替amis属性,是因为在字段yml文件中用amis作为key不好理解
14574
+ let amis = props["input-table"] || props.amis || {};//额外支持"input-table"代替amis属性,是因为在字段yml文件中用amis作为key不好理解
13997
14575
  let inputTableSchema = {
13998
14576
  "type": "input-table",
13999
- "label": props.label,
14577
+ "mode": "normal",
14000
14578
  "name": props.name,
14001
14579
  //不可以addable/editable/removable设置为true,因为会在原生的操作列显示操作按钮图标,此开关实测只控制这个按钮显示不会影响功能
14002
14580
  // "addable": props.addable,
@@ -14012,36 +14590,53 @@ const getAmisInputTableSchema = async (props) => {
14012
14590
  "showTableAddBtn": false,
14013
14591
  "showFooterAddBtn": false,
14014
14592
  "className": props.tableClassName,
14593
+ "pipeIn": (value, data) => {
14594
+ if (fieldPrefix) {
14595
+ value = getTableValueWithoutFieldPrefix(value, fieldPrefix);
14596
+ }
14597
+ value = getTableValueWithEmptyValue(value, fields);
14598
+ if (primaryKey) {
14599
+ // 这里临时给每行数据补上primaryKey字段值,如果库里不需要保存这里补上的字段值,pipeOut中会识别autoGeneratePrimaryKeyValue属性选择最终移除这里补上的字段值
14600
+ // 这里始终自动生成primaryKey字段值,而不是只在pipeOut输出整个子表字段值时才生成,是因为要支持当数据库里保存的子表字段行数据没有primaryKey字段值时的行嵌套模式(即节点的children属性)功能
14601
+ // 这里要注意,流程详细设置界面的字段设置功能中的子表组件中,数据库里保存的子表字段行数据是有primaryKey字段值的,它不依赖这里自动生成行primaryKey值功能
14602
+ value = getTableValueWithPrimaryKeyValue(value, primaryKey);
14603
+ }
14604
+ if (amis.pipeIn) {
14605
+ if (typeof amis.pipeIn === 'function') {
14606
+ return amis.pipeIn(value, data);
14607
+ }
14608
+ }
14609
+ return value;
14610
+ },
14015
14611
  "pipeOut": (value, data) => {
14016
- value = (value || []).map(function(item){
14612
+ value = (value || []).map(function (item) {
14017
14613
  delete item.__fix_rerender_after_children_modified_tag;
14018
14614
  return item;
14019
14615
  });
14020
- if(props.fieldPrefix){
14021
- value = getTableValuePrependFieldPrefix(value, props.fieldPrefix);
14616
+ if (fieldPrefix) {
14617
+ value = getTableValuePrependFieldPrefix(value, fieldPrefix, primaryKey);
14618
+ }
14619
+ value = getTableValueWithoutEmptyValue(value, fields);
14620
+ if (props.autoGeneratePrimaryKeyValue === true) {
14621
+ // 如果需要把自动生成的primaryKey值输出保存的库中,则补全所有行中的primaryKey值
14622
+ // 这里如果不全部补全的话,初始从库里返回的字段值中拿到的行没primaryKey值的话就不会自动补上
14623
+ value = getTableValueWithPrimaryKeyValue(value, primaryKey);
14624
+ }
14625
+ else {
14626
+ // 默认情况下,也就是没有配置autoGeneratePrimaryKey时,最终输出的字段值要移除行中的primaryKey值
14627
+ // 需要注意如果没有配置autoGeneratePrimaryKey时,因为每次弹出行编辑窗口保存后都会先后进入pipeOut和pipeIn,
14628
+ // 这里删除掉了primaryKey值,所以primaryKey值每次弹出编辑窗口保存后都会给每行重新生成新的primaryKey值
14629
+ // 只有autoGeneratePrimaryKey配置为true时,每行的primaryKey字段值才会始终保持不变
14630
+ value = getTableValueWithoutPrimaryKeyValue(value, primaryKey);
14022
14631
  }
14023
- if(amis.pipeOut){
14024
- if(typeof amis.pipeOut === 'function'){
14632
+ if (amis.pipeOut) {
14633
+ if (typeof amis.pipeOut === 'function') {
14025
14634
  return amis.pipeOut(value, data);
14026
14635
  }
14027
14636
  }
14028
14637
  return value;
14029
14638
  }
14030
14639
  };
14031
- if(amis.pipeIn){
14032
- inputTableSchema.pipeIn = amis.pipeIn;
14033
- }
14034
- if(props.fieldPrefix){
14035
- inputTableSchema.pipeIn = (value, data) => {
14036
- value = getTableValueWithoutFieldPrefix(value, props.fieldPrefix);
14037
- if(amis.pipeIn){
14038
- if(typeof amis.pipeIn === 'function'){
14039
- return amis.pipeIn(value, data);
14040
- }
14041
- }
14042
- return value;
14043
- };
14044
- }
14045
14640
  if (buttonsForColumnOperations.length) {
14046
14641
  inputTableSchema.columns.push({
14047
14642
  "name": "__op__",
@@ -14050,9 +14645,10 @@ const getAmisInputTableSchema = async (props) => {
14050
14645
  "width": buttonsForColumnOperations.length > 1 ? "60px" : "20px"
14051
14646
  });
14052
14647
  }
14053
- if (showAsInlineEditMode) {
14054
- inputTableSchema.needConfirm = false;
14055
- }
14648
+ // if (showAsInlineEditMode) {
14649
+ // // 因为要支持不同的列上配置inlineEditMode属性,所有不可以把整个子表组件都设置为inlineEditMode
14650
+ // inputTableSchema.needConfirm = false;
14651
+ // }
14056
14652
  if (amis) {
14057
14653
  // 支持配置amis属性重写或添加最终生成的input-table中任何属性。
14058
14654
  delete amis.id;//如果steedos-input-table组件配置了amis.id属性,会造成新建编辑行功能不生效
@@ -14060,7 +14656,7 @@ const getAmisInputTableSchema = async (props) => {
14060
14656
  delete amis.pipeOut;//该属性在上面合并过了
14061
14657
  Object.assign(inputTableSchema, amis);
14062
14658
  }
14063
- const isAnyFieldHasDependOn = (props.fields || []).find(function (item) {
14659
+ const isAnyFieldHasDependOn = (fields || []).find(function (item) {
14064
14660
  return item.depend_on;
14065
14661
  });
14066
14662
  if (isAnyFieldHasDependOn) {
@@ -14093,11 +14689,31 @@ const getAmisInputTableSchema = async (props) => {
14093
14689
  "body": headerToolbar
14094
14690
  });
14095
14691
  }
14692
+ let className = "steedos-input-table";
14693
+
14694
+ if (typeof props.className == "object") {
14695
+ className = {
14696
+ [className]: "true",
14697
+ ...props.className
14698
+ };
14699
+ } else if (typeof props.className == "string") {
14700
+ className = `${className} ${props.className} `;
14701
+ }
14702
+
14096
14703
  let schema = {
14097
- "type": "service",
14098
- "body": schemaBody,
14099
- "className": props.className,
14100
- "id": serviceId
14704
+ "type": "control",
14705
+ "body": {
14706
+ "type": "service",
14707
+ "body": schemaBody,
14708
+ "id": serviceId
14709
+ },
14710
+ "label": props.label,
14711
+ "labelClassName": props.label ? props.labelClassName : "none",
14712
+ "labelRemark": props.labelRemark,
14713
+ "labelAlign": props.labelAlign,
14714
+ //控制control的mode属性,https://aisuda.bce.baidu.com/amis/zh-CN/components/form/formitem#表单项展示
14715
+ "mode": props.mode || null,
14716
+ className
14101
14717
  };
14102
14718
  // console.log("===schema===", schema);
14103
14719
  return schema;