@steedos-widgets/amis-object 1.2.13 → 1.2.15

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.
@@ -1773,8 +1773,8 @@ const parseSingleExpression$1 = function (func, formData, dataPath, global, user
1773
1773
  /*
1774
1774
  * @Author: baozhoutao@steedos.com
1775
1775
  * @Date: 2022-11-01 15:51:00
1776
- * @LastEditors: Please set LastEditors
1777
- * @LastEditTime: 2023-04-26 11:52:04
1776
+ * @LastEditors: liaodaxue
1777
+ * @LastEditTime: 2023-06-06 11:12:33
1778
1778
  * @Description:
1779
1779
  */
1780
1780
 
@@ -1857,7 +1857,7 @@ const getSchema$4 = async (uiSchema, ctx) => {
1857
1857
  "isLookup": "${isLookup}",
1858
1858
  "listName": "${listName}"
1859
1859
  },
1860
- "title": "新建 ${uiSchema.label}",
1860
+ "title": "新建 ${uiSchema.label | raw}",
1861
1861
  "body": [
1862
1862
  {
1863
1863
  "type": "service",
@@ -5830,6 +5830,7 @@ async function lookupToAmisPicker(field, readonly, ctx){
5830
5830
  pickerSchema = await getTableSchema$1(tableFields, {
5831
5831
  labelFieldName: refObjectConfig.NAME_FIELD_KEY,
5832
5832
  top: top,
5833
+ isLookup: true,
5833
5834
  ...ctx
5834
5835
  });
5835
5836
 
@@ -5879,6 +5880,10 @@ async function lookupToAmisPicker(field, readonly, ctx){
5879
5880
  };
5880
5881
  }
5881
5882
 
5883
+ if(field.pickerSchema){
5884
+ pickerSchema = Object.assign({}, pickerSchema, field.pickerSchema);
5885
+ }
5886
+
5882
5887
  const data = {
5883
5888
  type: getAmisStaticFieldType('picker', readonly),
5884
5889
  labelField: referenceTo.labelField.name,
@@ -6405,7 +6410,7 @@ const getAmisFileReadonlySchema = (steedosField)=>{
6405
6410
  return {
6406
6411
  type: amisFieldType,
6407
6412
  tpl: `
6408
- <% let fileData = data.${steedosField.name}; if (fileData) { %>
6413
+ <% let fileData = data._display.${steedosField.name}; if (fileData) { %>
6409
6414
  <% if(!Array.isArray(fileData)){ fileData = [fileData]} %>
6410
6415
  <% fileData.forEach(function(item) { %>
6411
6416
  <a href='<%= item.url %>' target='_self' class='block'><%= item.name %></a>
@@ -6446,7 +6451,6 @@ const getAmisFileEditSchema = (steedosField)=>{
6446
6451
  }
6447
6452
  }
6448
6453
  };
6449
-
6450
6454
  if(steedosField.multiple){
6451
6455
  convertData.multiple = true;
6452
6456
  convertData.joinValues = false;
@@ -7169,2204 +7173,2439 @@ var index = /*#__PURE__*/Object.freeze({
7169
7173
  getAmisStaticFieldType: getAmisStaticFieldType
7170
7174
  });
7171
7175
 
7172
- const API_CACHE = 100;
7176
+ /*
7177
+ * @Author: baozhoutao@steedos.com
7178
+ * @Date: 2022-08-04 10:42:49
7179
+ * @LastEditors: baozhoutao@steedos.com
7180
+ * @LastEditTime: 2022-08-25 10:28:47
7181
+ * @Description:
7182
+ */
7183
+ var config = {
7184
+ listView: {
7185
+ newRecordMode: 'modal',
7186
+ editRecordMode: 'modal',
7187
+ perPage: 20
7188
+ }
7189
+ };
7173
7190
 
7174
- function getReadonlyFormAdaptor(object, fields){
7175
- let scriptStr = '';
7176
- const selectFields = ___default__namespace.filter(fields, function(field){return field.name.indexOf('.') < 0 && ((field.type == 'select' && field.options) || ((field.type == 'lookup' || field.type == 'master_detail') && !field.reference_to))});
7177
- const gridAndObjectFieldsName = ___default__namespace.map(___default__namespace.filter(fields, function(field){return field.name.indexOf('.') < 0 && (field.type === 'object' || field.type === 'grid')}), 'name');
7178
- ___default__namespace.each(selectFields, function(field){
7179
- if(!___default__namespace.includes(OMIT_FIELDS, field.name)){
7180
- field.name;
7181
- if(field.options){
7182
- const options = JSON.stringify({options: field.options});
7183
- scriptStr = scriptStr + `var ${field.name}Options= (${options}).options;`;
7184
- }else if(field.optionsFunction){
7185
- scriptStr = scriptStr + `var ${field.name}Options = eval(${field.optionsFunction.toString()})(api.data);`;
7186
- }else if(field._optionsFunction){
7187
- scriptStr = scriptStr + `var ${field.name}Options = eval(${field._optionsFunction})(api.data);`;
7188
- }
7189
- if(field.multiple){
7190
- scriptStr = scriptStr + `data.${field.name}__label = _.map(_.filter(${field.name}Options, function(option){return _.includes(data.${field.name}, option.value)}), 'label');`;
7191
- }else {
7192
- scriptStr = scriptStr + `var ${field.name}Selected = _.find(${field.name}Options, function(option){return data.${field.name} == option.value});`;
7193
- scriptStr = scriptStr + `data.${field.name}__label = ${field.name}Selected ? ${field.name}Selected.label:null;`;
7191
+ async function getQuickEditSchema(field, options){
7192
+ const quickEditId = options.objectName + "_" + field.name + "QuickEdit";//定义快速编辑的表单id,用于setvalue传值
7193
+ var quickEditSchema = { body: [], id: quickEditId };
7194
+ if (field.disabled) {
7195
+ quickEditSchema = false;
7196
+ } else {
7197
+ var fieldSchema = await convertSFieldToAmisField(field, false, ___default__namespace.omit(options, 'buttons'));
7198
+ //存在属性上可编辑,实际不可编辑的字段,convertSFieldToAmisField函数可能会返回undefined,如summary
7199
+ if (!!fieldSchema) {
7200
+ quickEditSchema.body.push(fieldSchema);
7201
+ //以下字段使用_display的数据,因此在触发change等事件时对数据_display进行修改,以实现保存前的回显
7202
+ var TempDisplayField = ``;
7203
+ quickEditSchema.body[0].onEvent = {};
7204
+ const quickEditOnEvent = function (displayField) {
7205
+ const EventType = {
7206
+ "actions": [
7207
+ {
7208
+ "actionType": "custom",
7209
+ "script": `
7210
+ var _display = event.data._display;
7211
+ ${displayField}
7212
+ doAction({actionType: 'setValue', "args": {"value": {_display}},componentId: "${quickEditId}"});
7213
+ `
7214
+ }
7215
+ ]
7216
+ };
7217
+ return EventType;
7218
+ };
7219
+ switch (field.type) {
7220
+ //TODO:amis的picker组件直接点击选项x时不会触发change事件,待处理
7221
+ case "lookup":
7222
+ case "master_detail":
7223
+ if (field.multiple) {
7224
+ TempDisplayField = `
7225
+ _display["${field.name}"] = [];
7226
+ event.data.value.forEach(function(item,index){
7227
+ _display["${field.name}"].push(
7228
+ {
7229
+ "label": event.data.option[index].${quickEditSchema.body[0].labelField},
7230
+ "value": event.data.option[index]._id,
7231
+ "objectName": "${field.reference_to}"
7232
+ }
7233
+ )
7234
+ })
7235
+ `;
7236
+ } else {
7237
+ TempDisplayField = `
7238
+ _display["${field.name}"] = {
7239
+ "label": event.data.option.${quickEditSchema.body[0].labelField},
7240
+ "value": event.data._id,
7241
+ "objectName": "${field.reference_to}"
7242
+ }
7243
+ `;
7244
+ }
7245
+ quickEditSchema.body[0].onEvent["change"] = quickEditOnEvent(TempDisplayField);
7246
+ break;
7247
+ case "select":
7248
+ TempDisplayField = `
7249
+ _display["${field.name}"] = event.data.selectedItems.label;
7250
+ `;
7251
+ quickEditSchema.body[0].onEvent["change"] = quickEditOnEvent(TempDisplayField);
7252
+ break;
7253
+ case "percent":
7254
+ TempDisplayField = `
7255
+ _display["${field.name}"] = (event.data.value * 100).toFixed(${field.scale}) + '%';
7256
+ `;
7257
+ quickEditSchema.body[0].onEvent["change"] = quickEditOnEvent(TempDisplayField);
7258
+ break;
7259
+ case "time":
7260
+ TempDisplayField = `
7261
+ _display["${field.name}"] = moment(event.data.value).utc().format('HH:mm');
7262
+ `;
7263
+ quickEditSchema.body[0].onEvent["change"] = quickEditOnEvent(TempDisplayField);
7264
+ break;
7265
+ case "date":
7266
+ TempDisplayField = `
7267
+ _display["${field.name}"] = moment(event.data.value).utc().format('YYYY-MM-DD');
7268
+ `;
7269
+ quickEditSchema.body[0].onEvent["change"] = quickEditOnEvent(TempDisplayField);
7270
+ break;
7271
+ case "datetime":
7272
+ TempDisplayField = `
7273
+ _display["${field.name}"] = moment(event.data.value).format('YYYY-MM-DD HH:mm');
7274
+ `;
7275
+ quickEditSchema.body[0].onEvent["change"] = quickEditOnEvent(TempDisplayField);
7276
+ break;
7277
+ case "boolean":
7278
+ TempDisplayField = `
7279
+ _display["${field.name}"] = event.data.value?"√":"";
7280
+ `;
7281
+ quickEditSchema.body[0].onEvent["change"] = quickEditOnEvent(TempDisplayField);
7282
+ break;
7283
+ case "number":
7284
+ case "currency":
7285
+ TempDisplayField = `
7286
+ _display["${field.name}"] = event.data.value?.toFixed(${field.scale});
7287
+ `;
7288
+ quickEditSchema.body[0].onEvent["change"] = quickEditOnEvent(TempDisplayField);
7289
+
7290
+ break;
7291
+ case "file":
7292
+ var removeDisplayField = ``;
7293
+ if (field.multiple) {
7294
+ TempDisplayField = `
7295
+ _display["${field.name}"].push({
7296
+ "name": event.data.result.name,
7297
+ "url": event.data.result.url,
7298
+ "type": event.data.item.type,
7299
+ "size": event.data.item.size
7300
+ });
7301
+ `;
7302
+ removeDisplayField = `
7303
+ _.remove(_display["${field.name}"], function(file){return file.url == event.data.item.url});
7304
+ `;
7305
+ } else {
7306
+ TempDisplayField = `
7307
+ _display["${field.name}"] = {
7308
+ "name": event.data.result.name,
7309
+ "url": event.data.result.url,
7310
+ "type": event.data.item.type,
7311
+ "size": event.data.item.size
7312
+ };
7313
+ `;
7314
+ removeDisplayField = `
7315
+ if(_display["${field.name}"].url == event.data.item.url){
7316
+ _display["${field.name}"] = {};
7317
+ }
7318
+ `;
7319
+ }
7320
+ quickEditSchema.body[0].onEvent["success"] = quickEditOnEvent(TempDisplayField);
7321
+ quickEditSchema.body[0].onEvent["remove"] = quickEditOnEvent(removeDisplayField);
7322
+ break;
7323
+ case "avatar":
7324
+ case "image":
7325
+ quickEditSchema.body[0].receiver.adaptor = `
7326
+ const { context } = api.body;
7327
+ var rootUrl = context.rootUrl + "/api/files/${field.type}s/";
7328
+ payload = {
7329
+ status: response.status == 200 ? 0 : response.status,
7330
+ msg: response.statusText,
7331
+ data: {
7332
+ value: rootUrl + payload._id,//为了实现图片crud的回显,需要将value从id改为url,当保存数据数据时,再在发送适配器内重新将id提取出来
7333
+ name: payload.original.name,
7334
+ url: rootUrl + payload._id,
7335
+ }
7336
+ }
7337
+ return payload;
7338
+ `;
7339
+ break;
7194
7340
  }
7195
- }
7196
- });
7197
-
7198
- // const refFields = _.filter(fields, function(field){return field.name.indexOf('.') < 0 && (field.type == 'lookup' || field.type == 'master_detail') && !field.reference_to});
7199
- // _.each(refFields, function(field){
7200
- // if(!_.includes(OMIT_FIELDS, field.name)){
7201
- // const valueField = field.reference_to_field || '_id';
7202
- // scriptStr = scriptStr + `var ${field.name}Options = eval(${field.optionsFunction.toString()})(api.data);`
7203
- // if(field.multiple){
7204
- // scriptStr = scriptStr + `data.${field.name}__label = _.map(_.filter(${field.name}Options, function(option){return _.includes(data.${field.name}, option.value)}), 'label');`
7205
- // }else{
7206
- // scriptStr = scriptStr + `var ${field.name}Selected = _.find(${field.name}Options, function(option){return data.${field.name} == option.value});`
7207
- // scriptStr = scriptStr + `data.${field.name}__label = ${field.name}Selected ? ${field.name}Selected.label:null;`
7208
- // }
7209
- // }
7210
- // })
7211
7341
 
7212
- return `
7213
- if(payload.data.data.length === 0){
7214
- return {
7215
- status: 2,
7216
- msg: "无法找到记录"
7217
- }
7218
- }
7219
- if(payload.data.data){
7220
- var data = payload.data.data[0];
7221
- var gridAndObjectFieldsName = ${JSON.stringify(gridAndObjectFieldsName)};
7222
- try{
7223
- ${scriptStr}
7224
- ${getScriptForAddUrlPrefixForImgFields(fields)}
7225
- ${getScriptForRewriteValueForFileFields(fields)}
7226
- }catch(e){
7227
- console.error(e)
7342
+ } else {
7343
+ quickEditSchema = false;
7228
7344
  }
7229
- // 原始记录
7230
- var record = _.cloneDeep(data);
7231
- try{
7232
- _.each(gridAndObjectFieldsName, function(name){
7233
- data[name] = data._display[name];
7234
- })
7235
- }catch(e){
7236
- console.error(e)
7345
+ //TODO:附件多选时会覆盖老数据,暂时禁用
7346
+ if(field.type == "file" && field.multiple){
7347
+ quickEditSchema = false;
7237
7348
  }
7238
- payload.data = data;
7239
- payload.data.__objectName = "${object.name}";
7240
- payload.data.__record = record;
7241
- window.postMessage(Object.assign({type: "record.loaded"}, {record: record}), "*")
7242
7349
  }
7243
- if(payload.errors){
7244
- payload.status = 2;
7245
- payload.msg = payload.errors[0].message;
7246
- }
7247
- return payload;
7248
- `
7350
+ return quickEditSchema;
7249
7351
  }
7250
7352
 
7251
- async function getReadonlyFormInitApi(object, recordId, fields, options){
7252
- return {
7253
- method: "post",
7254
- url: getApi$2()+"&recordId=${recordId}",
7255
- cache: API_CACHE,
7256
- // requestAdaptor: "console.log('getReadonlyFormInitApi requestAdaptor', api);return api;",
7257
- adaptor: getReadonlyFormAdaptor(object, fields),
7258
- data: await getFindOneQuery$1(object, recordId, fields, options),
7259
- headers: {
7260
- Authorization: "Bearer ${context.tenantId},${context.authToken}"
7353
+ async function getTableColumns$1(fields, options){
7354
+ const columns = [{name: '_index',type: 'text', width: 32, placeholder: ""}];
7355
+ const allowEdit = options.permissions?.allowEdit && options.permissions?.modifyAllRecords && !options.isLookup && options.enable_inline_edit != false;
7356
+ for (const field of fields) {
7357
+ //增加quickEdit属性,实现快速编辑
7358
+ const quickEditSchema = allowEdit ? await getQuickEditSchema(field, options) : allowEdit;
7359
+ if((field.is_name || field.name === options.labelFieldName) && options.objectName === 'cms_files'){
7360
+ const previewFileScript = `
7361
+ var data = event.data;
7362
+ var file_name = data.versions ? data.name : "${field.label}";
7363
+ var file_id = data._id;
7364
+ SteedosUI.previewFile && SteedosUI.previewFile({file_name, file_id});
7365
+ `;
7366
+ columns.push({
7367
+ "type": "button",
7368
+ "label": `<%=data.versions ? data.name : "${field.label}"%>`,
7369
+ "className": "whitespace-nowrap",
7370
+ "level": "link",
7371
+ "quickEdit": quickEditSchema,
7372
+ "onEvent": {
7373
+ "click": {
7374
+ "actions": [
7375
+ {
7376
+ "args": {
7377
+ "api": {
7378
+ "url": "${context.rootUrl}/api/files/files/${versions[0]}?download=true",
7379
+ "method": "get",
7380
+ "headers": {
7381
+ "Authorization": "Bearer ${context.tenantId},${context.authToken}"
7382
+ }
7383
+ }
7384
+ },
7385
+ "actionType": "download",
7386
+ "expression": "!!!window?.nw?.require"//浏览器上直接下载
7387
+ },
7388
+ {
7389
+ "args": {},
7390
+ "actionType": "custom",
7391
+ "script": previewFileScript,
7392
+ "expression": "!!window?.nw?.require" //PC客户端预览附件
7393
+ }
7394
+ ]
7395
+ }
7396
+ }
7397
+ });
7398
+ }else if(field.type === 'toggle'){
7399
+ columns.push(Object.assign({}, {
7400
+ type: "switch",
7401
+ name: field.name,
7402
+ label: field.label,
7403
+ width: field.width,
7404
+ toggled: field.toggled,
7405
+ className:"whitespace-nowrap"
7406
+ }, field.amis, {name: field.name}));
7407
+ }else if(field.type === 'avatar' || field.type === 'image' || field.type === 'file'){
7408
+ columns.push(Object.assign({}, {
7409
+ type: "switch",
7410
+ name: field.name,
7411
+ label: field.label,
7412
+ width: field.width,
7413
+ toggled: field.toggled,
7414
+ quickEdit: quickEditSchema,
7415
+ className:"whitespace-nowrap",
7416
+ ...getAmisFileReadonlySchema(field)
7417
+ }, field.amis, {name: field.name}));
7418
+ }
7419
+ else if(field.type === 'select'){
7420
+ const map = getSelectMap(field.options);
7421
+ columns.push(Object.assign({}, {
7422
+ type: "mapping",
7423
+ name: field.name,
7424
+ label: field.label,
7425
+ map: map,
7426
+ sortable: field.sortable,
7427
+ width: field.width,
7428
+ toggled: field.toggled,
7429
+ className:"whitespace-nowrap",
7430
+ quickEdit: quickEditSchema
7431
+ }, field.amis, {name: field.name}));
7261
7432
  }
7433
+ else {
7434
+ const tpl = await getFieldTpl(field, options);
7435
+ let type = 'text';
7436
+ if(tpl){
7437
+ type = 'tpl';
7438
+ }else if(field.type === 'html'){
7439
+ type = 'markdown';
7440
+ }else if(field.type === 'url' && field.show_as_qr){
7441
+ type = 'qr-code';
7442
+ }
7443
+ let className = "";
7444
+ if(field.type === 'textarea'){
7445
+ className = 'min-w-56';
7446
+ }
7447
+ if(field.wrap === false){
7448
+ className += " whitespace-nowrap";
7449
+ }
7450
+ if(!field.hidden && !field.extra){
7451
+ columns.push(Object.assign({}, {
7452
+ name: field.name,
7453
+ label: field.label,
7454
+ sortable: field.sortable,
7455
+ // searchable: field.searchable,
7456
+ width: field.width,
7457
+ type: type,
7458
+ tpl: tpl,
7459
+ toggled: field.toggled,
7460
+ className,
7461
+ quickEdit: quickEditSchema,
7462
+ options: field.type === 'html' ? {html: true} : null
7463
+ // toggled: true
7464
+ }, field.amis, {name: field.name}));
7465
+ }
7466
+ }
7467
+ }
7468
+ // columns.push(getOperation(fields));
7469
+ if(!___default__namespace.some(columns, { name: options.labelFieldName })){
7470
+ const href = Router$1.getObjectDetailPath({
7471
+ ...options, formFactor: options.formFactor, appId: "${appId}", objectName: options.objectName || "${objectName}", recordId: `\${${options.idFieldName}}`
7472
+ });
7473
+ columns[0].type = "tpl";
7474
+ columns[0].tpl = `<a href="${href}">\${${columns[0].name}}</a>`;
7262
7475
  }
7476
+ return columns;
7263
7477
  }
7264
7478
 
7265
- /*
7266
- img/avatar字段值添加URL前缀使其在amis中正常显示图片。
7267
- */
7268
- function getScriptForAddUrlPrefixForImgFields(fields){
7269
- let imgFieldsKeys = [];
7270
- let imgFields = {};
7271
- fields.forEach((item)=>{
7272
- if(___default__namespace.includes(['image','avatar'], item.type)){
7273
- imgFieldsKeys.push(item.name);
7274
- imgFields[item.name] = {
7275
- name: item.name,
7276
- type: item.type,
7277
- multiple: item.multiple
7278
- };
7279
- }
7280
- });
7281
- if(!imgFieldsKeys.length){
7282
- return '';
7283
- }
7284
- return `
7285
- // image字段值添加URL前缀
7286
- let imgFieldsKeys = ${JSON.stringify(imgFieldsKeys)};
7287
- let imgFields = ${JSON.stringify(imgFields)};
7288
- imgFieldsKeys.forEach((item)=>{
7289
- let imgFieldValue = data[item];
7290
- let imgFieldDisplayValue = data._display && data._display[item];
7291
- if(imgFieldValue && imgFieldValue.length){
7292
- let fieldProps = imgFields[item];
7293
- if(fieldProps.multiple){
7294
- if(imgFieldDisplayValue instanceof Array){
7295
- data[item] = imgFieldDisplayValue.map((i)=>{ return i.url });
7296
- }
7297
- }else{
7298
- data[item] = imgFieldDisplayValue && imgFieldDisplayValue.url;
7299
- }
7300
- }
7301
- })
7302
- `
7303
- }
7479
+ /**
7480
+ * 生成移动端列表每行显示的amis
7481
+ * @param {*} tpls 要显示的每个字段的tpl
7482
+ * @returns {
7483
+ "type": "wrapper",
7484
+ "body": [{
7485
+ "type": "tpl",
7486
+ "tpl": tpls[index].tpl,
7487
+ "className": "truncate"//左侧样式类
7488
+ },{
7489
+ "type": "tpl",
7490
+ "tpl": tpls[index + 1].tpl,
7491
+ "className": "truncate ml-2 flex flex-shrink-0"//右侧样式类
7492
+ }],
7493
+ "size": "none",
7494
+ "className": "flex items-center justify-between"//每行样式类
7495
+ }
7496
+ */
7497
+ function getMobileLines(tpls){
7498
+ let lines = [];
7499
+ let maxLineCount = 2;
7500
+ let lineChildren = [];
7501
+ let isNewLine = false;
7502
+ let isLeft = true;
7503
+ let lineChildrenClassName = "";
7504
+ let lineClassName = "flex items-center justify-between h-[20px]";
7505
+ tpls.forEach(function(item){
7506
+ if(isNewLine && lines.length < maxLineCount){
7507
+ lines.push({
7508
+ "type": "wrapper",
7509
+ "body": lineChildren,
7510
+ "size": "none",
7511
+ "className": lineClassName
7512
+ });
7513
+ lineChildren = [];
7514
+ }
7515
+ if(isLeft){
7516
+ // 左侧半行
7517
+ lineChildrenClassName = "steedos-listview-item-left truncate";
7518
+ if(item.field.is_wide){
7519
+ // 左侧全行样式可以单独写
7520
+ lineChildrenClassName = "steedos-listview-item-wide truncate";
7521
+ }
7522
+ if(lines.length === 0){
7523
+ // 第一个字段加粗黑色显示
7524
+ lineChildrenClassName += " font-bold text-gray-800";
7525
+ }
7526
+ }
7527
+ else {
7528
+ // 右侧半行
7529
+ lineChildrenClassName = "steedos-listview-item-right truncate ml-2 flex flex-shrink-0";
7530
+ }
7531
+ lineChildren.push({
7532
+ "type": "tpl",
7533
+ "tpl": item.tpl,
7534
+ "className": lineChildrenClassName
7535
+ });
7304
7536
 
7305
- /*
7306
- file字段值重写使其在amis中正常显示附件名、点击附件名下载文件。
7307
- */
7308
- function getScriptForRewriteValueForFileFields(fields){
7309
- let fileFieldsKeys = [];
7310
- let fileFields = {};
7311
- fields.forEach((item)=>{
7312
- if(item.type === 'file'){
7313
- fileFieldsKeys.push(item.name);
7314
- fileFields[item.name] = {
7315
- name: item.name,
7316
- multiple: item.multiple
7317
- };
7537
+ if(item.field.is_wide){
7538
+ // 宽字段占整行
7539
+ isLeft = true;
7540
+ isNewLine = true;
7541
+ }
7542
+ else {
7543
+ isLeft = !isLeft;
7544
+ isNewLine = isLeft;
7318
7545
  }
7319
7546
  });
7320
- if(!fileFieldsKeys.length){
7321
- return '';
7547
+
7548
+ if(lineChildren.length && lines.length < maxLineCount){
7549
+ lines.push({
7550
+ "type": "wrapper",
7551
+ "body": lineChildren,
7552
+ "size": "none",
7553
+ "className": lineClassName
7554
+ });
7322
7555
  }
7323
- return `
7324
- // file字段值重写以便编辑时正常显示附件名、点击附件名正常下载附件
7325
- let fileFieldsKeys = ${JSON.stringify(fileFieldsKeys)};
7326
- let fileFields = ${JSON.stringify(fileFields)};
7327
- fileFieldsKeys.forEach((item)=>{
7328
- let fileFieldValue = data[item];
7329
- let fileFieldDisplayValue = data._display && data._display[item];
7330
- if(fileFieldValue && fileFieldValue.length){
7331
- if(fileFields[item].multiple){
7332
- if(fileFieldDisplayValue instanceof Array){
7333
- data[item] = fileFieldDisplayValue.map((item, index)=>{
7334
- return {
7335
- value: fileFieldValue[index],
7336
- name: item.name,
7337
- url: item.url + "?download=true",
7338
- state: "uploaded"
7339
- }
7340
- });
7341
- }
7342
- }else{
7343
- data[item] = [{
7344
- value: fileFieldValue,
7345
- name: fileFieldDisplayValue.name,
7346
- url: fileFieldDisplayValue.url + "?download=true",
7347
- state: "uploaded"
7348
- }];
7349
- }
7350
- }
7351
- })
7352
- `
7556
+
7557
+ return lines;
7353
7558
  }
7354
7559
 
7355
- async function getEditFormInitApi(object, recordId, fields, options){
7356
- const data = await getFindOneQuery$1(object, recordId, fields);
7357
- data.recordId = "${recordId}";
7358
- data.objectName = "${objectName}";
7359
- data.uiSchema = "${uiSchema}";
7360
- data.global = "${global}";
7361
- data.context = "${context}";
7362
- data.defaultData = "${defaultData}";
7363
- data._master = "${_master}";
7364
-
7365
- return {
7366
- method: "post",
7367
- url: getApi$2() + '&objectName=${objectName}' ,
7368
- // sendOn: "!!this.recordId",
7369
- cache: API_CACHE,
7370
- requestAdaptor: `
7371
- // 所有不想在network请求中发送的数据都应该从data中分离出来,data变量只需要留下query才需要发送出去
7372
- var { recordId, objectName, uiSchema, global, context, ...data} = api.data;
7373
- if(!recordId){
7374
- // 新建则不请求任何数据
7375
- data.query = "{data:" + objectName + "(filters: " + JSON.stringify(["_id", "=", null]) + ", top: 1){_id}}";
7560
+ async function getMobileTableColumns(fields, options){
7561
+ const columns = [];
7562
+ let nameField = {};
7563
+ let tpls = [];
7564
+ for (const field of fields) {
7565
+ let tpl = "";
7566
+ if(field.is_name || field.name === options.labelFieldName){
7567
+ nameField = field;
7568
+ options.onlyDisplayLabel = true;
7569
+ tpl = await getFieldTpl(field, options);
7570
+ }
7571
+ else if(field.type === 'avatar' || field.type === 'image' || field.type === 'file'){
7572
+ // 图片和附件类型字段暂时显示为附件名称,后续需要再优化
7573
+ tpl = `\${_display.${field.name}.name}`;
7574
+ }
7575
+ else {
7576
+ if(field.type === 'lookup' || field.type === 'master_detail'){
7577
+ options.onlyDisplayLabel = true;
7376
7578
  }
7377
- api.data = data;
7378
- ${options.initApiRequestAdaptor || ''}
7379
- return api;
7380
- `,
7381
- adaptor: `
7382
- const recordId = api.body.recordId;
7383
- let initialValues={};
7384
- if(recordId && payload.data.data){
7385
- var data = payload.data.data[0];
7386
- const dataKeys = _.keys(data);
7387
- const uiSchema = api.body.uiSchema;
7388
- const fieldKeys = uiSchema && _.keys(uiSchema.fields);
7579
+ tpl = await getFieldTpl(field, options);
7580
+ }
7581
+ if(!tpl){
7582
+ tpl = `\${${field.name}}`;
7583
+ }
7584
+ if(!field.hidden && !field.extra){
7585
+ tpls.push({ field, tpl });
7586
+ }
7587
+ }
7588
+ const url = getNameTplUrl(nameField, options);
7389
7589
 
7390
- if(data){
7391
- ${getScriptForAddUrlPrefixForImgFields(fields)}
7392
- ${getScriptForRewriteValueForFileFields(fields)}
7590
+ const columnLines = getMobileLines(tpls);
7393
7591
 
7394
- _.each(dataKeys, function(key){
7395
- if(fieldKeys.indexOf(key)<0){
7396
- delete data[key];
7397
- }
7398
- })
7399
-
7400
- //初始化接口返回的字段移除字段值为null的字段
7401
- for (key in data){
7402
- if(data[key] === null){
7403
- delete data[key];
7404
- }
7592
+
7593
+ let column = {
7594
+ name: nameField.name,
7595
+ label: nameField.label,
7596
+ sortable: nameField.sortable,
7597
+ type: "button",
7598
+ level: "link",
7599
+ actionType: "link",
7600
+ link: url,
7601
+ innerClassName: "steedos-listview-item block text-gray-500",
7602
+ body: {
7603
+ "type": "wrapper",
7604
+ "body": columnLines,
7605
+ "size": "none",
7606
+ "className": "p-1"
7607
+ }
7608
+ };
7609
+
7610
+ if(options.objectName === 'cms_files'){
7611
+ if(window.Meteor?.isCordova){
7612
+ column = {
7613
+ ...column,
7614
+ actionType: "",
7615
+ link: "",
7616
+ onEvent: {
7617
+ "click": {
7618
+ "actions": [
7619
+ {
7620
+ "script": `
7621
+ let cms_url = "/api/files/files/"+event.data.versions[0]+"?download=true"
7622
+ Steedos.cordovaDownload(encodeURI(Steedos.absoluteUrl(cms_url)), event.data.name);
7623
+ `,
7624
+ "actionType": "custom"
7625
+ }
7626
+ ],
7627
+ "weight": 0
7405
7628
  }
7406
- };
7407
- initialValues = data;
7408
- }
7409
- else{
7410
- var uiSchema = api.body.uiSchema;
7411
- var defaultData = api.body.defaultData;
7412
- var defaultValues = {};
7413
- _.each(uiSchema?.fields, function(field){
7414
- var value = SteedosUI.getFieldDefaultValue(field, api.body.global);
7415
- if(value){
7416
- defaultValues[field.name] = value;
7417
- }
7418
- });
7419
- if(defaultData && _.isObject(defaultData) && !_.isArray(defaultData)){
7420
- defaultValues = Object.assign({}, defaultValues, defaultData)
7421
7629
  }
7422
- if(uiSchema.form){
7423
- try{
7424
- var objectFormConfig = JSON.parse(uiSchema.form);
7425
- var formInitialValuesFun = objectFormConfig.initialValues;
7426
- if(formInitialValuesFun){
7427
- formInitialValuesFun = new Function("return " + formInitialValuesFun)();
7428
- }
7429
- if(typeof formInitialValuesFun === "function"){
7430
- initialValues = formInitialValuesFun.apply({doc: defaultValues || {} , global: api.body.global, master: api.body._master })
7431
- }
7432
- }
7433
- catch(ex){
7434
- console.warn(ex);
7630
+ };
7631
+ }else {
7632
+ column = {
7633
+ ...column,
7634
+ actionType: "",
7635
+ link: "",
7636
+ onEvent: {
7637
+ "click": {
7638
+ "actions": [
7639
+ {
7640
+ "args": {
7641
+ "api": {
7642
+ "url": url,
7643
+ "method": "get",
7644
+ "headers": {
7645
+ "Authorization": "Bearer ${context.tenantId},${context.authToken}"
7646
+ }
7647
+ }
7648
+ },
7649
+ "actionType": "download"
7650
+ }
7651
+ ],
7652
+ "weight": 0
7435
7653
  }
7436
7654
  }
7437
- if(_.isObject(initialValues)){
7438
- // uiSchema.form.initialValues为函数且执行后为json,则优先取initialValues中的默认值
7439
- initialValues = Object.assign({}, defaultValues, initialValues);
7440
- }
7441
- else{
7442
- initialValues = defaultValues;
7443
- }
7444
- }
7445
- // data下的变量需要在保存接口(getSaveApi)中被删除。
7446
- payload.data = {
7447
- ...initialValues
7448
- }
7449
- ${options.initApiAdaptor || ''}
7450
- return payload;
7451
- `,
7452
- responseData: {
7453
- initialValues: "$$",
7454
- editFormInited: true
7455
- },
7456
- data: data,
7457
- headers: {
7458
- Authorization: "Bearer ${context.tenantId},${context.authToken}"
7655
+ };
7459
7656
  }
7657
+
7460
7658
  }
7461
- }
7462
7659
 
7660
+ columns.push(column);
7661
+
7463
7662
 
7464
- function getSaveApi(object, recordId, fields, options){
7465
- return {
7466
- method: 'post',
7467
- url: getApi$2(),
7468
- data: getSaveQuery(object, recordId),
7469
- requestAdaptor: getSaveRequestAdaptor(fields, options),
7470
- responseData: {
7471
- "recordId": "${record._id}"
7472
- },
7473
- adaptor: `
7474
- if(payload.errors){
7475
- payload.status = 2;
7476
- payload.msg = window.t ? window.t(payload.errors[0].message) : payload.errors[0].message;
7477
- }
7478
- ${options.apiAdaptor || ''}
7479
- return payload;
7480
- `,
7481
- headers: {
7482
- Authorization: "Bearer ${context.tenantId},${context.authToken}"
7483
- }
7484
- }
7663
+ return columns;
7485
7664
  }
7486
7665
 
7487
- function getBatchDelete(objectName){
7666
+ function getDefaultParams(options){
7488
7667
  return {
7489
- method: 'post',
7490
- url: getApi$2(),
7491
- requestAdaptor: `
7492
- var ids = api.data.ids.split(",");
7493
- var deleteArray = [];
7494
- ids.forEach((id,index)=>{
7495
- deleteArray.push(\`delete__\${index}:${objectName}__delete(id: "\${id}")\`);
7496
- })
7497
- api.data = {query: \`mutation{\${deleteArray.join(',')}}\`};
7498
- return api;
7499
- `,
7500
- data: {
7501
- ids: `\${ids}`
7502
- },
7503
- headers: {
7504
- Authorization: "Bearer ${context.tenantId},${context.authToken}"
7505
- }
7668
+ perPage: options.top || options.perPage || config.listView.perPage
7506
7669
  }
7507
7670
  }
7508
7671
 
7509
- /*
7510
- * @Author: baozhoutao@steedos.com
7511
- * @Date: 2022-05-26 16:02:08
7512
- * @LastEditors: baozhoutao@steedos.com
7513
- * @LastEditTime: 2023-03-13 16:01:40
7514
- * @Description:
7515
- */
7516
-
7517
- const getFieldSchemaArray = (formFields)=>{
7518
- let fieldSchemaArray = [];
7519
- fieldSchemaArray.length = 0;
7672
+ function getButtonVisibleOn(button){
7673
+ let visible= button.visible;
7520
7674
 
7521
- ___default__namespace.forEach(formFields, (field) => {
7522
- if (!field.group || field.group == 'null' || field.group == '-')
7523
- field.group = '通用';
7524
- const fieldName = field.name;
7525
- let isObjectField = /\w+\.\w+/.test(fieldName);
7526
- if (field.type == 'grid' || field.type == 'object') {
7527
- // field.group = field.label
7528
- field.is_wide = true;
7529
- }
7530
-
7531
- if (!isObjectField){
7532
- if(!field.hidden){
7533
- fieldSchemaArray.push(Object.assign({name: fieldName}, field, {permission: {allowEdit: true}}));
7534
- }
7675
+ if(button._visible){
7676
+ visible = button._visible;
7535
7677
  }
7536
- });
7537
- return fieldSchemaArray;
7538
- };
7539
-
7540
- const getSection = async (formFields, permissionFields, fieldSchemaArray, sectionName, ctx) => {
7541
- const sectionFields = ___default__namespace.filter(fieldSchemaArray, { 'group': sectionName });
7542
- if(sectionFields.length == ___default__namespace.filter(sectionFields, ['hidden', true]).length){
7543
- return ;
7544
- }
7545
-
7546
- const fieldSetBody = [];
7547
-
7548
- for (const perField of sectionFields) {
7549
- let field = perField;
7550
- if(perField.type === 'grid'){
7551
- field = await getGridFieldSubFields(perField, formFields);
7552
- // console.log(`perField.type grid ===> field`, field)
7553
- }else if(perField.type === 'object'){
7554
- field = await getObjectFieldSubFields(perField, formFields);
7555
- // console.log(`perField.type object ===> field`, field)
7556
- }
7557
- if(field.name.indexOf(".") < 0){
7558
- ctx.__formFields = formFields;
7559
- const amisField = await convertSFieldToAmisField(field, field.readonly, ctx);
7560
- // console.log(`${field.name} amisField`, field, amisField)
7561
- if(amisField){
7562
- fieldSetBody.push(amisField);
7563
- }
7564
- }
7565
- }
7566
-
7567
- // fieldSet 已支持显隐控制
7568
- const sectionFieldsVisibleOn = ___default__namespace.map(___default__namespace.compact(___default__namespace.map(fieldSetBody, 'visibleOn')) , (visibleOn)=>{
7569
- return visibleOn;
7570
- });
7571
- const section = {
7572
- "type": "fieldSet",
7573
- "title": sectionName,
7574
- "collapsable": true,
7575
- "body": fieldSetBody,
7576
- };
7577
- if(sectionFieldsVisibleOn.length > 0 && fieldSetBody.length === sectionFieldsVisibleOn.length){
7578
- section.visibleOn = `${sectionFieldsVisibleOn.join(" || ")}`;
7579
- }
7580
- return section
7581
- };
7582
7678
 
7583
- const getSections = async (permissionFields, formFields, ctx) => {
7584
- const fieldSchemaArray = getFieldSchemaArray(formFields);
7585
- const _sections = ___default__namespace.groupBy(fieldSchemaArray, 'group');
7586
- const sections = [];
7587
- var sectionHeaderVisibleOn=[];
7588
- for (const key in _sections) {
7589
- const section = await getSection(formFields, permissionFields, fieldSchemaArray, key, ctx);
7590
- if(section.body.length > 0){
7591
- if(section.visibleOn){
7592
- sectionHeaderVisibleOn.push(section.visibleOn);
7593
- }
7594
- sections.push(section);
7679
+ if(___default.isBoolean(visible)){
7680
+ visible = visible.toString();
7595
7681
  }
7596
- }
7597
- /*
7598
- 为了实现只有一个分组时隐藏该分组标题,需要分三种情况(分组如果没有visibleon属性就代表一定显示,有visibleon需要进行判断)
7599
- 1.所有分组中只有一个分组没有visibleon,还需要判断其他有visibleon的分组是否显示,只有其他都不显示时,才需要隐藏标题;反之,有任何一个显示,就不需要隐藏标题
7600
- 2.所有分组都有visibleon
7601
- 2.1 当前分组为隐藏时,标题就设置为隐藏
7602
- 2.2 当前分组为显示时,其他分组只要有一个是显示,就显示该分组标题
7603
- 2.3 当前分组为显示时,其他分组都隐藏,就隐藏该分组标题
7604
- 3.所有分组中有两个以上的分组没有visibleon(这种情况不用处理)
7605
- */
7606
- if(ctx.mode == "edit"){
7607
- if (sections.length - sectionHeaderVisibleOn.length == 1) {
7608
- sections.forEach((section) => {
7609
- section.headingClassName = {
7610
- "hidden": `!(${sectionHeaderVisibleOn.join(" || ") || 'false'})`
7611
- };
7612
- });
7613
- } else if (sections.length == sectionHeaderVisibleOn.length) {
7614
- sections.forEach((section, index) => {
7615
- var tempSectionHeaderVisibleOn = sectionHeaderVisibleOn.slice();
7616
- tempSectionHeaderVisibleOn.splice(index, 1);
7617
- section.headingClassName = {
7618
- "hidden": `!((${tempSectionHeaderVisibleOn.join(" || ") || 'false'}) && ${sectionHeaderVisibleOn[index]})`
7619
- };
7620
- });
7621
- }
7622
- }
7623
-
7624
- return sections;
7625
- };
7626
7682
 
7627
- /*
7628
- * @Author: baozhoutao@steedos.com
7629
- * @Date: 2022-07-07 11:02:29
7630
- * @LastEditors: baozhoutao@steedos.com
7631
- * @LastEditTime: 2023-03-07 17:19:34
7632
- * @Description:
7633
- */
7683
+ if(visible){
7684
+ // if(visible.indexOf("Meteor.") > 0 || visible.indexOf("Creator.") > 0 || visible.indexOf("Session.") > 0){
7685
+ // console.warn('无效的visible', visible)
7686
+ // return 'false';
7687
+ // }
7688
+ if(visible.trim().startsWith('function')){
7689
+ return `${visible}(objectName, typeof _id === 'undefined' ? null: _id, typeof record === 'undefined' ? (typeof recordPermissions === 'undefined' ? {} : recordPermissions) : record.recordPermissions, data)`
7690
+ }
7691
+ return visible;
7692
+ }
7634
7693
 
7635
- async function getFormBody(permissionFields, formFields, ctx){
7636
- return await getSections(permissionFields, formFields, ctx);
7694
+ if(button.type === 'amis_button'){
7695
+ const amisSchema = button.amis_schema;
7696
+ if(amisSchema && amisSchema.body && amisSchema.body.length > 0){
7697
+ const btn1 = amisSchema.body[0];
7698
+ return btn1.visibleOn
7699
+ }
7700
+ }
7637
7701
  }
7638
7702
 
7639
- // lodash的defaultsDeep函数有bug,无法正确合并值为数值的节点,重写修正该函数
7640
- // 源码出处:https://github.com/nodeutils/defaults-deep
7641
- const defaultsDeep = (...args)=>{
7642
- let output = {};
7643
- ___default.toArray(args).reverse().forEach(item=> {
7644
- ___default.mergeWith(output, item, (objectValue, sourceValue) => {
7645
- return ___default.isArray(sourceValue) ? sourceValue : undefined;
7703
+ async function getTableOperation(ctx){
7704
+ const buttons = ctx.buttons;
7705
+ const operationButtons = [];
7706
+ ___default.each(buttons, (button)=>{
7707
+ if(___default.isBoolean(button.visible)){
7708
+ button.visible = button.visible.toString();
7709
+ }
7710
+ // operationButtons.push({
7711
+ // type: 'button',
7712
+ // label: button.label,
7713
+ // visibleOn: button.visible ? `${button.visible}` : (button._visible ? `${button._visible}` : null),
7714
+ // onEvent: {
7715
+ // click: {
7716
+ // actions: []
7717
+ // }
7718
+ // }
7719
+ // })
7720
+
7721
+ operationButtons.push({
7722
+ type: 'steedos-object-button',
7723
+ name: button.name,
7724
+ objectName: button.objectName,
7725
+ visibleOn: getButtonVisibleOn(button),
7726
+ className: 'antd-Button--default'
7646
7727
  });
7647
7728
  });
7648
- return output;
7649
- };
7650
-
7651
- function getBulkActions(objectSchema){
7652
- return [
7653
- {
7654
- "type": "button",
7655
- "level": "danger",
7656
- "label": "批量删除",
7657
- "actionType": "ajax",
7658
- "confirmText": "确定要删除吗",
7659
- "className": "hidden",
7660
- "id": "batchDelete",
7661
- "api": getBatchDelete(objectSchema.name),
7662
- }
7663
- // {
7664
- // "label": "批量修改",
7665
- // "actionType": "dialog",
7666
- // "dialog": {
7667
- // "title": "批量编辑",
7668
- // "name": "sample-bulk-edit",
7669
- // "body": {
7670
- // "type": "form",
7671
- // "api": "https://3xsw4ap8wah59.cfc-execute.bj.baidubce.com/api/amis-mock/sample/bulkUpdate2",
7672
- // "controls": [
7673
- // {
7674
- // "type": "hidden",
7675
- // "name": "ids"
7676
- // },
7677
- // {
7678
- // "type": "text",
7679
- // "name": "name",
7680
- // "label": "Name"
7681
- // }
7682
- // ]
7683
- // }
7684
- // }
7685
- // }
7686
- ]
7729
+ if(operationButtons.length < 1){
7730
+ return ;
7731
+ }
7732
+ return {
7733
+ type: 'operation',
7734
+ label: '操作',
7735
+ fixed: 'right',
7736
+ labelClassName: 'text-center',
7737
+ className: 'text-center steedos-listview-operation w-20',
7738
+ buttons: [
7739
+ {
7740
+ "type": "steedos-dropdown-button",
7741
+ "label": "xxx",
7742
+ "buttons": operationButtons,
7743
+ "placement": "bottomRight",
7744
+ "overlayClassName": "shadow !min-w-[160px]",
7745
+ "trigger": ["click"],
7746
+ "id": "u:c2140a365019",
7747
+ onOpenApi: {
7748
+ url: `\${context.rootUrl}/service/api/@\${objectName}/recordPermissions/\${_id}`,
7749
+ method: "get",
7750
+ data: {
7751
+ $: "$$",
7752
+ objectName: "${objectName}",
7753
+ listViewId: "${listViewId}",
7754
+ appId: "${appId}",
7755
+ formFactor: "${formFactor}",
7756
+ context: `\${context}`
7757
+ },
7758
+ headers: {
7759
+ Authorization: "Bearer ${context.tenantId},${context.authToken}"
7760
+ },
7761
+ adaptor: `
7762
+ payload = {
7763
+ record: {
7764
+ recordPermissions: payload
7765
+ }
7766
+ };
7767
+ return payload;
7768
+ `,
7769
+ }
7770
+ }
7771
+ ]
7772
+ }
7687
7773
  }
7688
7774
 
7689
- async function getObjectCRUD(objectSchema, fields, options){
7690
- // console.time('getObjectCRUD');
7691
- const { top, perPage, showDisplayAs = false, displayAs, crudClassName = "" } = options;
7692
- const nonpaged = objectSchema.paging && objectSchema.paging.enabled === false;
7693
- const isTreeObject = objectSchema.enable_tree;
7694
- const bulkActions = getBulkActions(objectSchema);
7695
- const bodyProps = {
7696
- // toolbar: getToolbar(),
7697
- // headerToolbar: getObjectHeaderToolbar(objectSchema, options.formFactor, {showDisplayAs}),
7698
- headerToolbarClassName: "px-4 py-2 border-gray-300 bg-gray-100 border-solid border-b",
7699
- footerToolbar: getObjectFooterToolbar(objectSchema, options.formFactor, {
7700
- disableStatistics: options.queryCount === false
7701
- }),
7702
- filter: options.filterVisible !== false && await getObjectFilter(objectSchema, fields, options),
7703
- };
7704
- if(options.formFactor !== 'SMALL' || ["split"].indexOf(options.displayAs) == -1){
7705
- Object.assign(bodyProps, {
7706
- bulkActions: options.bulkActions != false ? bulkActions : false
7707
- });
7775
+ async function getTableSchema$1(fields, options){
7776
+ if(!options){
7777
+ options = {};
7708
7778
  }
7709
- // yml里配置的 不分页和enable_tree:true 优先级最高,组件中输入的top次之。
7710
- options.queryCount = true;
7711
- if(nonpaged || isTreeObject){
7712
- options.top = 50000;
7713
- bodyProps.footerToolbar = [];
7714
- options.queryCount = true; // 禁止翻页的时候, 需要查找总数
7715
- }else if(top){
7716
- bodyProps.footerToolbar = [];
7717
- if(options.isRelated){
7718
- options.queryCount = true;
7719
- }else {
7720
- options.queryCount = false;
7721
- }
7779
+ let columns = [];
7780
+ if(options.formFactor === 'SMALL' || ["split"].indexOf(options.displayAs) > -1){
7781
+ columns = await getMobileTableColumns(fields, options);
7722
7782
  }
7723
- // console.log(`getObjectHeaderToolbar====2===>`, options.filterVisible)
7724
- bodyProps.headerToolbar = getObjectHeaderToolbar(objectSchema, options.formFactor, {
7725
- showDisplayAs,
7726
- hiddenCount: options.queryCount === false,
7727
- headerToolbarItems: options.headerToolbarItems,
7728
- filterVisible: options.filterVisible
7729
- });
7783
+ else {
7784
+ columns = await getTableColumns$1(fields, options);
7785
+ columns.push(await getTableOperation(options));
7786
+ }
7787
+ return {
7788
+ mode: "table",
7789
+ name: "thelist",
7790
+ headerToolbarClassName: "py-2 px-2 border-gray-300 bg-gray-100 border-solid border-b",
7791
+ className: "",
7792
+ draggable: false,
7793
+ defaultParams: getDefaultParams(options),
7794
+ columns: columns,
7795
+ syncLocation: false,
7796
+ keepItemSelectionOnPageChange: true,
7797
+ checkOnItemClick: false,
7798
+ labelTpl: `\${${options.labelFieldName}}`,
7799
+ autoFillHeight: false, // 自动高度效果不理想,先关闭
7800
+ columnsTogglable: false,
7801
+ }
7802
+ }
7730
7803
 
7731
7804
 
7732
- let body = null;
7733
- const id = `listview_${objectSchema.name}`;
7734
- if(options.formFactor === 'SMALL' && false){
7735
- delete bodyProps.bulkActions;
7736
- delete bodyProps.headerToolbar;
7737
- delete bodyProps.footerToolbar;
7738
- const card = await getCardSchema(fields, Object.assign({idFieldName: objectSchema.idFieldName, labelFieldName: objectSchema.NAME_FIELD_KEY || 'name'}, options, {actions: false}));
7739
- body = Object.assign({}, card , {
7740
- type: 'crud',
7741
- primaryField: '_id',
7742
- id: id,
7743
- name: id,
7744
- keepItemSelectionOnPageChange: false,
7745
- api: await getTableApi(objectSchema, fields, options),
7746
- hiddenOn: options.tableHiddenOn,
7747
- },
7748
- bodyProps
7749
- );
7750
- }else {
7751
- let labelFieldName = objectSchema.NAME_FIELD_KEY || 'name';
7752
- // organizations 对象的历史遗留问题, fullname 被标记为了 名称字段. 在此处特殊处理.
7753
- if(objectSchema.name === 'organizations'){
7754
- labelFieldName = 'name';
7755
- }
7756
- const table = await getTableSchema$1(fields, Object.assign({idFieldName: objectSchema.idFieldName, labelFieldName: labelFieldName}, options));
7757
- delete table.mode;
7758
7805
 
7759
- body = Object.assign({}, table, {
7760
- type: 'crud',
7761
- primaryField: '_id',
7762
- affixHeader: false,
7763
- id: id,
7764
- name: id,
7765
- keepItemSelectionOnPageChange: true,
7766
- api: await getTableApi(objectSchema, fields, options),
7767
- hiddenOn: options.tableHiddenOn,
7768
- autoFillHeight: options.isRelated ? false : true,
7769
- className: `flex-auto ${crudClassName || ""}`,
7770
- bodyClassName: "bg-white",
7771
- crudClassName: crudClassName,
7772
- },
7773
- bodyProps,
7774
- );
7806
+ /**
7807
+ *
7808
+ * @param {*} mainObject
7809
+ * @param {*} fields
7810
+ * @param {*} options = {filter: listview 过滤条件, ...}
7811
+ * @returns
7812
+ */
7813
+ async function getTableApi(mainObject, fields, options){
7814
+ const searchableFields = [];
7815
+ let { filter, filtersFunction, sort, top, setDataToComponentId = '' } = options;
7816
+
7817
+ if(___default__namespace.isArray(filter)){
7818
+ filter = ___default__namespace.map(filter, function(item){
7819
+ if(item.operation){
7820
+ return [item.field, item.operation, item.value];
7821
+ }else {
7822
+ return item
7823
+ }
7824
+ });
7775
7825
  }
7826
+ if(!filter){
7827
+ filter = [];
7828
+ }
7829
+ let baseFilters = null;
7830
+ if(filter){
7831
+ baseFilters = filter;
7832
+ }
7833
+ ___default__namespace.each(fields,function(field){
7834
+ if(field.searchable){
7835
+ searchableFields.push(field.name);
7836
+ }
7837
+ });
7776
7838
 
7777
- const defaults = options.defaults;
7778
- if (defaults) {
7779
- const listSchema = defaults.listSchema || {};
7780
- body = defaultsDeep({}, listSchema, body);
7781
- const headerSchema = defaults.headerSchema;
7782
- const footerSchema = defaults.footerSchema;
7783
- if (headerSchema || footerSchema) {
7784
- let wrappedBody = [body];
7785
- if (headerSchema) {
7786
- if(___default__default["default"].isArray(headerSchema)){
7787
- wrappedBody = ___default__default["default"].union(headerSchema,wrappedBody);
7788
- }
7789
- else {
7790
- wrappedBody.unshift(headerSchema);
7791
- }
7839
+ const fileFields = {};
7840
+ const fileFieldsKeys = [];
7841
+ // 含有optionsFunction属性, 无reference_to属性的lookup字段
7842
+ const lookupFields = {};
7843
+ fields.forEach((item)=>{
7844
+ if(___default__namespace.includes(['image','avatar','file'], item.type)){
7845
+ fileFieldsKeys.push(item.name);
7846
+ fileFields[item.name] = {
7847
+ name: item.name,
7848
+ type: item.type,
7849
+ multiple: item.multiple
7850
+ };
7792
7851
  }
7793
- if (footerSchema) {
7794
- if(___default__default["default"].isArray(footerSchema)){
7795
- wrappedBody = ___default__default["default"].union(wrappedBody,footerSchema);
7796
- }
7797
- else {
7798
- wrappedBody.push(footerSchema);
7799
- }
7852
+ if(___default__namespace.includes(['lookup'], item.type) && !item.reference_to ){
7853
+ lookupFields[item.name] = item;
7800
7854
  }
7801
- body = wrappedBody;
7802
- }
7855
+ });
7856
+
7857
+ let valueField = mainObject.key_field || '_id';
7858
+ const api = await getApi(mainObject, null, fields, {count: options.queryCount, alias: 'rows', limit: top, queryOptions: `filters: {__filters}, top: {__top}, skip: {__skip}, sort: "{__sort}"`});
7859
+
7860
+ if(options.isRelated){
7861
+ api.url += "&recordId=${_master.recordId}";
7803
7862
  }
7804
- // console.timeEnd('getObjectCRUD');
7805
- // TODO: data应该只留loaded,其他属性都改为从上层传递下来
7806
- return {
7807
- type: 'service',
7808
- className: '',
7809
- id: `service_${id}`,
7810
- name: `page`,
7811
- data: {
7812
- objectName: objectSchema.name,
7813
- // _id: null,
7814
- recordPermissions: objectSchema.permissions,
7815
- uiSchema: objectSchema,
7816
- // loaded: false //crud接收适配器中设置为true,否则就是刷新浏览器第一次加载
7817
- },
7818
- body: body
7819
- }
7820
- }
7821
7863
 
7822
- const getGlobalData = (mode)=>{
7823
- const user = getSteedosAuth();
7824
- return {mode: mode, user: user, spaceId: user.spaceId, userId: user.userId}
7825
- };
7864
+ api.data.$term = "$term";
7865
+ api.data.term = "$term";
7866
+ api.data.$self = "$$";
7867
+ api.data.self = "$$";
7868
+ api.data.filter = "$filter";
7869
+ api.data.loaded = "${loaded}";
7870
+ api.data.listViewId = "${listViewId}";
7871
+ api.data.listName = "${listName}";
7872
+ api.requestAdaptor = `
7873
+ // selfData 中的数据由 CRUD 控制. selfData中,只能获取到 CRUD 给定的data. 无法从数据链中获取数据.
7874
+ let selfData = JSON.parse(JSON.stringify(api.data.$self));
7875
+ // 保留一份初始data,以供自定义发送适配器中获取原始数据。
7876
+ const data = _.cloneDeep(api.data);
7877
+ try{
7878
+ // TODO: 不应该直接在这里取localStorage,应该从外面传入
7879
+ const listViewId = api.data.listViewId;
7880
+ const listViewPropsStoreKey = location.pathname + "/crud/" + listViewId ;
7881
+ let localListViewProps = sessionStorage.getItem(listViewPropsStoreKey);
7882
+ if(localListViewProps){
7883
+ localListViewProps = JSON.parse(localListViewProps);
7884
+ selfData = Object.assign({}, localListViewProps, selfData);
7885
+ if(!api.data.filter){
7886
+ api.data.filter = localListViewProps.filter;
7887
+ }
7888
+ if(!api.data.loaded){
7889
+ // 第一次加载组件,比如刷新浏览器时因为api.data.pageNo有默认值1
7890
+ // 所以会把localSearchableFilter中已经存过的页码覆盖
7891
+ // 如果是第一次加载组件始终让翻页页码从本地存储中取值
7892
+ let formFactor = "${options.formFactor}";
7893
+ // 移动端不识别本地存储中的翻页页码,否则点击加载更多按钮后无法刷新回第一页
7894
+ api.data.pageNo = formFactor === "SMALL" ? 1 : (localListViewProps.page || 1);
7895
+ }
7896
+ }
7897
+ }
7898
+ catch(ex){
7899
+ console.error("本地存储中crud参数解析异常:", ex);
7900
+ }
7901
+ ${baseFilters ? `var systemFilters = ${JSON.stringify(baseFilters)};` : 'var systemFilters = [];'}
7902
+ var _ids = []
7903
+ const filtersFunction = ${filtersFunction};
7904
+ if(filtersFunction){
7905
+ const _filters = filtersFunction(systemFilters, api.data.$self);
7906
+ if(api.data.listName == "recent"){
7907
+ _ids = _filters[2]
7908
+ }
7909
+ if(_filters && _filters.length > 0){
7910
+ if(_.isEmpty(systemFilters)){
7911
+ systemFilters = _filters || [];
7912
+ }else{
7913
+ systemFilters = [systemFilters, 'and', _filters];
7914
+ }
7915
+ }
7916
+ }
7917
+ let userFilters =[];
7918
+
7919
+ if(_.isEmpty(systemFilters)){
7920
+ systemFilters = api.data.filter || [];
7921
+ }else{
7922
+ if(!_.isEmpty(api.data.filter)){
7923
+ systemFilters = [systemFilters, 'and', api.data.filter];
7924
+ }
7925
+ }
7926
+ var pageSize = api.data.pageSize || 10;
7927
+ var pageNo = api.data.pageNo || 1;
7928
+ var skip = (pageNo - 1) * pageSize;
7929
+ var orderBy = api.data.orderBy || '';
7930
+ var orderDir = api.data.orderDir || '';
7931
+ var sort = orderBy + ' ' + orderDir;
7932
+ sort = orderBy ? sort : "${sort || ''}";
7933
+ var allowSearchFields = ${JSON.stringify(searchableFields)};
7934
+ if(api.data.$term){
7935
+ userFilters = [["name", "contains", "'+ api.data.$term +'"]];
7936
+ }else if(selfData.op === 'loadOptions' && selfData.value){
7937
+ userFilters = [["${valueField.name}", "=", selfData.value]];
7938
+ }
7939
+
7940
+ var searchableFilter = SteedosUI.getSearchFilter(selfData) || [];
7826
7941
 
7827
- const getFormFields = (objectSchema, formProps)=>{
7828
- /**
7829
- * fieldsExtend: 重写字段定义
7830
- * fields: 包含的字段
7831
- * excludedFields: 排除的字段
7832
- */
7833
- const { fieldsExtend, fields: includedFields, excludedFields } = formProps;
7834
-
7835
- let fields = {};
7836
- // 以uiSchema fields 为基础, 遍历字段, 并更新字段定义
7837
- ___default__default["default"].forEach(objectSchema.fields, (field, fieldName)=>{
7838
- if(!lodash.has(field, "name")){
7839
- field.name = fieldName;
7840
- }
7841
- if(fieldsExtend && fieldsExtend[fieldName]){
7842
- fields[field.name] = Object.assign({}, field, fieldsExtend[fieldName], {name: field.name});
7843
- }else {
7844
- fields[field.name] = field;
7845
- }
7846
- });
7942
+ if(searchableFilter.length > 0){
7943
+ if(userFilters.length > 0 ){
7944
+ userFilters = [userFilters, 'and', searchableFilter];
7945
+ }else{
7946
+ userFilters = searchableFilter;
7947
+ }
7948
+ }
7847
7949
 
7848
- if(!___default__default["default"].isEmpty(includedFields) && ___default__default["default"].isArray(includedFields)){
7849
- const includedFieldsMap = {};
7850
- ___default__default["default"].each(includedFields, (fName, index)=>{
7851
- if(fields[fName]){
7852
- includedFieldsMap[fName] = Object.assign({}, fields[fName], {sort_no: index});
7853
- }
7854
- });
7855
- fields = includedFieldsMap;
7856
- }
7950
+ if(allowSearchFields){
7951
+ allowSearchFields.forEach(function(key){
7952
+ const keyValue = selfData[key];
7953
+ if(_.isString(keyValue)){
7954
+ userFilters.push([key, "contains", keyValue]);
7955
+ }else if(_.isArray(keyValue) || _.isBoolean(keyValue) || keyValue){
7956
+ userFilters.push([key, "=", keyValue]);
7957
+ }
7958
+ })
7959
+ }
7857
7960
 
7858
- if(!___default__default["default"].isEmpty(excludedFields) && ___default__default["default"].isArray(excludedFields)){
7859
- ___default__default["default"].each(excludedFields, (fName)=>{
7860
- delete fields[fName];
7861
- });
7862
- }
7961
+ if(selfData.__keywords && allowSearchFields){
7962
+ const keywordsFilters = [];
7963
+ allowSearchFields.forEach(function(key, index){
7964
+ const keyValue = selfData.__keywords;
7965
+ if(keyValue){
7966
+ keywordsFilters.push([key, "contains", keyValue]);
7967
+ if(index < allowSearchFields.length - 1){
7968
+ keywordsFilters.push('or');
7969
+ }
7970
+ }
7971
+ })
7972
+ userFilters.push(keywordsFilters);
7973
+ };
7863
7974
 
7864
- return lodash.sortBy(___default__default["default"].values(fields), "sort_no");
7865
- };
7975
+ let filters = [];
7866
7976
 
7867
- async function getObjectForm(objectSchema, ctx){
7868
- const { recordId, formFactor, layout = formFactor === 'SMALL' ? 'normal' : "normal", labelAlign, tabId, appId, defaults } = ctx;
7869
- const fields = ___default__default["default"].values(objectSchema.fields);
7870
- const formFields = getFormFields(objectSchema, ctx);
7871
- const formSchema = defaults && defaults.formSchema || {};
7872
- if(___default__default["default"].has(formSchema, 'className')){
7873
- formSchema.className = 'steedos-amis-form';
7874
- }
7875
- const amisSchema = {
7876
- type: 'service',
7877
- className: 'p-0',
7878
- name: `page_edit_${recordId}`,
7879
- api: await getEditFormInitApi(objectSchema, recordId, fields, ctx),
7880
- data:{
7881
- editFormInited: false
7882
- },
7883
- // data: {global: getGlobalData('edit'), recordId: recordId, objectName: objectSchema.name, context: {rootUrl: getRootUrl(), tenantId: getTenantId(), authToken: getAuthToken()}},
7884
- initApi: null,
7885
- initFetch: null ,
7886
- body: [defaultsDeep({}, formSchema, {
7887
- type: "form",
7888
- mode: layout,
7889
- data: {
7890
- "&": "${initialValues}"
7891
- },
7892
- labelAlign,
7893
- persistData: false,
7894
- resetAfterSubmit: true,
7895
- preventEnterSubmit: true,
7896
- promptPageLeave: true,
7897
- canAccessSuperData: false,
7898
- name: `form_edit_${recordId}`,
7899
- debug: false,
7900
- title: "",
7901
- submitText: "", // amis 表单不显示提交按钮, 表单提交由项目代码接管
7902
- api: await getSaveApi(objectSchema, recordId, fields, ctx),
7903
- initFetch: recordId != 'new',
7904
- body: await getFormBody(fields, formFields, ctx),
7905
- panelClassName:'m-0 sm:rounded-lg shadow-none border-none',
7906
- bodyClassName: 'p-0',
7907
- className: 'steedos-amis-form',
7908
- hiddenOn: "${editFormInited != true}",
7909
- onEvent: {
7910
- "submitSucc": {
7911
- "weight": 0,
7912
- "actions": [
7913
- {
7914
- "actionType": "broadcast",
7915
- "args": {
7916
- "eventName": `@data.changed.${objectSchema.name}`
7917
- },
7918
- "data": {
7919
- "objectName": `${objectSchema.name}`,
7920
- "displayAs": "${displayAs}"
7921
- }
7922
- },
7923
- {
7924
- "actionType": "broadcast",
7925
- "args": {
7926
- "eventName": "@data.changed.${_master.objectName}"
7927
- },
7928
- "data": {
7929
- "objectName": "${_master.objectName}",
7930
- "_isRelated": "${_isRelated || _master._isRelated}"
7931
- },
7932
- "expression": `\${_master.objectName != '${objectSchema.name}' && _master.objectName}`
7933
- },
7934
- // {
7935
- // "actionType": "custom",
7936
- // "script": "debugger;"
7937
- // },
7938
- // {
7939
- // "args": {},
7940
- // "actionType": "closeDialog"
7941
- // }
7942
- ]
7943
- }
7977
+ if(!_.isEmpty(systemFilters)){
7978
+ filters = systemFilters;
7979
+ };
7980
+ if(api.data.$self.additionalFilters){
7981
+ if(_.isString(api.data.$self.additionalFilters)){
7982
+ userFilters.push(eval(api.data.$self.additionalFilters))
7983
+ }else{
7984
+ userFilters.push(api.data.$self.additionalFilters)
7985
+ }
7944
7986
  }
7945
- })]
7946
- };
7947
- if(formSchema.id){
7948
- amisSchema.id = `service-${formSchema.id}`;
7949
- }
7950
- return amisSchema;
7951
- }
7952
7987
 
7953
- async function getObjectDetail(objectSchema, recordId, ctx){
7954
- const { formFactor, layout = formFactor === 'SMALL' ? 'normal' : "normal", labelAlign, formInitProps } = ctx;
7955
- const fields = ___default__default["default"].values(objectSchema.fields);
7956
- const formFields = getFormFields(objectSchema, ctx);
7957
- const serviceId = `service_detail_page`;
7958
- return {
7959
- type: 'service',
7960
- name: `page_readonly_${recordId}`,
7961
- id: serviceId,
7962
- data: {global: getGlobalData('read'), context: {rootUrl: getRootUrl(), tenantId: getTenantId(), authToken: getAuthToken()}},
7963
- api: await getReadonlyFormInitApi(objectSchema, recordId, fields, formInitProps),
7964
- body: [
7965
- {
7966
- "type": "wrapper", //form 的 hiddenOn 会导致 form onEvent 异常, 使用wrapper包裹一次form,并在wrapper上控制显隐
7967
- hiddenOn: "${recordLoaded != true}",
7968
- "className": "p-0 m-0",
7969
- "body": {
7970
- type: "form",
7971
- mode: layout,
7972
- labelAlign,
7973
- persistData: false,
7974
- promptPageLeave: false,
7975
- name: `form_readonly_${recordId}`,
7976
- debug: false,
7977
- title: "",
7978
- data: {
7979
- "formData": "$$"
7980
- },
7981
- wrapWithPanel: false,
7982
- body: await getFormBody(___default.map(fields, (field)=>{field.readonly = true; return field;}), ___default.map(formFields, (field)=>{field.readonly = true; return field;}), Object.assign({}, ctx, {showSystemFields: true})),
7983
- className: 'steedos-amis-form bg-white',
7984
- actions: [], // 不显示表单默认的提交按钮
7985
- onEvent: {
7986
- [`@data.changed.${objectSchema.name}`]: { // 由于amis service 组件的 onEvent 存在bug ,此处借助form来刷新 上层 service https://github.com/baidu/amis/issues/6294
7987
- "actions": [
7988
- {
7989
- "actionType": "reload",
7990
- "componentId": serviceId,
7991
- "expression": "this.__deletedRecord != true"
7992
- },
7993
- {
7994
- // "args": {
7995
- // "url": "/app/${appId}/${objectName}/grid/${side_listview_id}",
7996
- // "blank": false
7997
- // },
7998
- "actionType": "custom",
7999
- "script": "Steedos.goBack()",
8000
- "expression": "this.__deletedRecord === true"
8001
- }
8002
- ]
7988
+ if(api.data.$self._isRelated){
7989
+ const self = api.data.$self;
7990
+ const relatedKey = self.relatedKey;
7991
+ const refField = self.uiSchema.fields[relatedKey];
7992
+ const masterRecord = self._master.record;
7993
+ const masterObjectName = self._master.objectName;
7994
+ let relatedValue = self._master.recordId;
7995
+ if(refField.reference_to_field && refField.reference_to_field != '_id'){
7996
+ relatedValue = masterRecord[refField.reference_to_field]
7997
+ }
7998
+ let relatedFilters;
7999
+ if (
8000
+ refField._reference_to ||
8001
+ (refField.reference_to && !_.isString(refField.reference_to))
8002
+ ) {
8003
+ relatedFilters = [
8004
+ [relatedKey + "/o", "=", masterObjectName],
8005
+ [relatedKey + "/ids", "=", relatedValue],
8006
+ ];
8007
+ } else {
8008
+ relatedFilters = [relatedKey, "=", relatedValue];
8009
+ }
8010
+ userFilters.push(relatedFilters)
8011
+ }
8012
+
8013
+ if(!_.isEmpty(userFilters)){
8014
+ if(_.isEmpty(filters)){
8015
+ filters = userFilters;
8016
+ }else{
8017
+ filters = [filters, 'and', userFilters]
8018
+ }
8019
+ }
8020
+ api.data._ids = _ids;
8021
+ api.data = {
8022
+ query: api.data.query.replace(/{__filters}/g, JSON.stringify(filters)).replace('{__top}', pageSize).replace('{__skip}', skip).replace('{__sort}', sort.trim())
8023
+ }
8024
+ ${options.requestAdaptor || ''}
8025
+ return api;
8026
+ `;
8027
+ api.adaptor = `
8028
+ if(api.body.listName == "recent"){
8029
+ payload.data.rows = _.sortBy(payload.data.rows, function(item){
8030
+ return _.indexOf(api.body._ids, item._id)
8031
+ });
8032
+ }
8033
+ const enable_tree = ${mainObject.enable_tree};
8034
+ if(!enable_tree){
8035
+ _.each(payload.data.rows, function(item, index){
8036
+ const {pageNo, pageSize} = api.body;
8037
+ const skip = (pageNo - 1) * pageSize;
8038
+ item._index = skip + index + 1;
8039
+ })
8040
+ }
8041
+ window.postMessage(Object.assign({type: "listview.loaded"}), "*");
8042
+ let fileFields = ${JSON.stringify(fileFields)};
8043
+ let lookupFields = ${JSON.stringify(lookupFields)};
8044
+ _.each(payload.data.rows, function(item, index){
8045
+ _.each(fileFields , (field, key)=>{
8046
+ if(item[key] && item._display && item._display[key]){
8047
+ let value = item._display[key];
8048
+ if(!_.isArray(value)){
8049
+ value = [value]
8050
+ };
8051
+ if(field.type === 'file'){
8052
+ item[key] = value
8053
+ }else{
8054
+ item[key] = _.map(value, 'url')
8003
8055
  }
8004
- }
8005
- },
8006
- }
8007
- ],
8008
- onEvent: {
8009
- "fetchInited": {
8010
- "weight": 0,
8011
- "actions": [
8012
- {
8013
- actionType: 'broadcast',
8014
- eventName: "recordLoaded",
8015
- args: {
8016
- eventName: "recordLoaded"
8017
- },
8018
- data: {
8019
- objectName: "${event.data.__objectName}",
8020
- record: "${event.data.__record}"
8021
- },
8022
- expression: "${event.data.__response.error != true}"
8023
- },
8024
- {
8025
- "actionType": "setValue",
8026
- "args": {
8027
- value: {
8028
- "recordLoaded": true,
8029
- }
8030
- },
8031
- expression: "${event.data.__response.error != true}"
8032
8056
  }
8033
- ]
8034
- }
8057
+ })
8058
+ _.each(lookupFields , (field, key)=>{
8059
+ if(item[key]){
8060
+ if(field._optionsFunction){
8061
+ const optionsFunction = eval("(" + field._optionsFunction+ ")")(item);
8062
+ item[key + '__label'] = _.map(_.filter(optionsFunction, function(option){return _.includes(item[key], option.value)}), 'label').join(' ');
8063
+ }
8064
+ }
8065
+ })
8066
+ })
8067
+
8068
+ if(enable_tree){
8069
+ const records = payload.data.rows || [];
8070
+ const getTreeOptions = SteedosUI.getTreeOptions
8071
+ payload.data.rows = getTreeOptions(records,{"valueField":"_id"});
8072
+ }
8073
+
8074
+
8075
+ try{
8076
+ // TODO: 不应该直接在这里取localStorage,应该从外面传入
8077
+ const listViewId = api.body.listViewId;
8078
+ const listViewPropsStoreKey = location.pathname + "/crud/" + listViewId ;
8079
+ /**
8080
+ * localListViewProps规范来自crud请求api中api.data.$self参数值的。
8081
+ * 比如:{"perPage":20,"page":1,"__searchable__name":"7","__searchable__between__n1__c":[null,null],"filter":[["name","contains","a"]]}
8082
+ * __searchable__...:顶部放大镜搜索条件
8083
+ * filter:右侧过滤器
8084
+ * perPage:每页条数
8085
+ * page:当前页码
8086
+ * orderBy:排序字段
8087
+ * orderDir:排序方向
8088
+ */
8089
+ let localListViewProps = sessionStorage.getItem(listViewPropsStoreKey);
8090
+ let selfData = JSON.parse(JSON.stringify(api.body.$self));
8091
+ if(localListViewProps){
8092
+ localListViewProps = JSON.parse(localListViewProps);
8093
+ selfData = Object.assign({}, localListViewProps, selfData, { filter: api.body.filter });
8094
+ if(!api.body.loaded){
8095
+ // 第一次加载组件,比如刷新浏览器时因为api.data.pageNo有默认值1
8096
+ // 所以会把localSearchableFilter中已经存过的页码覆盖
8097
+ // 如果是第一次加载组件始终让翻页页码从本地存储中取值
8098
+ let formFactor = "${options.formFactor}";
8099
+ // 移动端不识别本地存储中的翻页页码,否则点击加载更多按钮后无法刷新回第一页
8100
+ selfData.page = formFactor === "SMALL" ? 1 : (localListViewProps.page || 1);
8101
+ }
8035
8102
  }
8103
+ delete selfData.context;
8104
+ delete selfData.global;
8105
+ sessionStorage.setItem(listViewPropsStoreKey, JSON.stringify(selfData));
8106
+ // 返回页码到UI界面
8107
+ payload.data.page= selfData.page;
8036
8108
  }
8109
+ catch(ex){
8110
+ console.error("本地存储中crud参数解析异常:", ex);
8111
+ }
8112
+ // 标记加载过,后续优先从本地存储中加载相关参数
8113
+ payload.data.loaded= true;
8114
+
8115
+ const setDataToComponentId = "${setDataToComponentId}";
8116
+ if(setDataToComponentId){
8117
+ SteedosUI.getRef(api.body.$self.$scopeId)?.getComponentById(setDataToComponentId)?.setData({$count: payload.data.count})
8118
+ };
8119
+ ${options.adaptor || ''}
8120
+ return payload;
8121
+ `;
8122
+ return api;
8037
8123
  }
8038
8124
 
8039
- /*
8040
- * @Author: baozhoutao@steedos.com
8041
- * @Date: 2022-08-04 10:42:49
8042
- * @LastEditors: baozhoutao@steedos.com
8043
- * @LastEditTime: 2022-08-25 10:28:47
8044
- * @Description:
8045
- */
8046
- var config = {
8047
- listView: {
8048
- newRecordMode: 'modal',
8049
- editRecordMode: 'modal',
8050
- perPage: 20
8125
+ async function getApi(object, recordId, fields, options){
8126
+ const data = await getFindQuery(object, recordId, fields, options);
8127
+ return {
8128
+ method: "post",
8129
+ url: getApi$2(), // + "&recordId=${recordId}"
8130
+ data: data,
8131
+ headers: {
8132
+ Authorization: "Bearer ${context.tenantId},${context.authToken}"
8133
+ }
8051
8134
  }
8052
- };
8135
+ }
8053
8136
 
8054
- async function getTableColumns$1(fields, options){
8055
- const columns = [{name: '_index',type: 'text', width: 32, placeholder: ""}];
8056
- for (const field of fields) {
8057
- if((field.is_name || field.name === options.labelFieldName) && options.objectName === 'cms_files'){
8058
- const previewFileScript = `
8059
- var data = event.data;
8060
- var file_name = data.versions ? data.name : "${field.label}";
8061
- var file_id = data._id;
8062
- SteedosUI.previewFile && SteedosUI.previewFile({file_name, file_id});
8063
- `;
8064
- columns.push({
8065
- "type": "button",
8066
- "label": `<%=data.versions ? data.name : "${field.label}"%>`,
8067
- "className": "whitespace-nowrap",
8068
- "level": "link",
8069
- "onEvent": {
8070
- "click": {
8071
- "actions": [
8072
- {
8073
- "args": {
8074
- "api": {
8075
- "url": "${context.rootUrl}/api/files/files/${versions[0]}?download=true",
8076
- "method": "get",
8077
- "headers": {
8078
- "Authorization": "Bearer ${context.tenantId},${context.authToken}"
8079
- }
8080
- }
8081
- },
8082
- "actionType": "download",
8083
- "expression": "!!!window?.nw?.require"//浏览器上直接下载
8084
- },
8085
- {
8086
- "args": {},
8087
- "actionType": "custom",
8088
- "script": previewFileScript,
8089
- "expression": "!!window?.nw?.require" //PC客户端预览附件
8090
- }
8091
- ]
8092
- }
8093
- }
8094
- });
8095
- }else if(field.type === 'toggle'){
8096
- columns.push(Object.assign({}, {
8097
- type: "switch",
8098
- name: field.name,
8099
- label: field.label,
8100
- width: field.width,
8101
- toggled: field.toggled,
8102
- disabled: true,
8103
- className:"whitespace-nowrap",
8104
- }, field.amis, {name: field.name}));
8105
- }else if(field.type === 'avatar' || field.type === 'image' || field.type === 'file'){
8106
- columns.push(Object.assign({}, {
8107
- type: "switch",
8108
- name: field.name,
8109
- label: field.label,
8110
- width: field.width,
8111
- toggled: field.toggled,
8112
- disabled: true,
8113
- className:"whitespace-nowrap",
8114
- ...getAmisFileReadonlySchema(field)
8115
- }, field.amis, {name: field.name}));
8116
- }
8117
- else if(field.type === 'select'){
8118
- const map = getSelectMap(field.options);
8119
- columns.push(Object.assign({}, {
8120
- type: "mapping",
8121
- name: field.name,
8122
- label: field.label,
8123
- map: map,
8124
- sortable: field.sortable,
8125
- width: field.width,
8126
- toggled: field.toggled,
8127
- className:"whitespace-nowrap",
8128
- }, field.amis, {name: field.name}));
8137
+ function getRecordPermissionsApi(object, recordId, options){
8138
+ const data = getRecordPermissionsQuery(object, recordId, options);
8139
+ return {
8140
+ method: "post",
8141
+ url: getApi$2(),
8142
+ data: data,
8143
+ headers: {
8144
+ Authorization: "Bearer ${context.tenantId},${context.authToken}"
8129
8145
  }
8130
- else {
8131
- const tpl = await getFieldTpl(field, options);
8146
+ }
8147
+ }
8132
8148
 
8133
- let type = 'text';
8134
- if(tpl){
8135
- type = 'tpl';
8136
- }else if(field.type === 'html'){
8137
- type = 'markdown';
8138
- }else if(field.type === 'url' && field.show_as_qr){
8139
- type = 'qr-code';
8140
- }
8141
- let className = "";
8142
- if(field.type === 'textarea'){
8143
- className = 'min-w-56';
8144
- }
8145
- if(field.wrap === false){
8146
- className += " whitespace-nowrap";
8149
+ const API_CACHE = 100;
8150
+
8151
+ function getReadonlyFormAdaptor(object, fields){
8152
+ let scriptStr = '';
8153
+ const selectFields = ___default__namespace.filter(fields, function(field){return field.name.indexOf('.') < 0 && ((field.type == 'select' && field.options) || ((field.type == 'lookup' || field.type == 'master_detail') && !field.reference_to))});
8154
+ const gridAndObjectFieldsName = ___default__namespace.map(___default__namespace.filter(fields, function(field){return field.name.indexOf('.') < 0 && (field.type === 'object' || field.type === 'grid')}), 'name');
8155
+ ___default__namespace.each(selectFields, function(field){
8156
+ if(!___default__namespace.includes(OMIT_FIELDS, field.name)){
8157
+ field.name;
8158
+ if(field.options){
8159
+ const options = JSON.stringify({options: field.options});
8160
+ scriptStr = scriptStr + `var ${field.name}Options= (${options}).options;`;
8161
+ }else if(field.optionsFunction){
8162
+ scriptStr = scriptStr + `var ${field.name}Options = eval(${field.optionsFunction.toString()})(api.data);`;
8163
+ }else if(field._optionsFunction){
8164
+ scriptStr = scriptStr + `var ${field.name}Options = eval(${field._optionsFunction})(api.data);`;
8147
8165
  }
8148
- if(!field.hidden && !field.extra){
8149
- columns.push(Object.assign({}, {
8150
- name: field.name,
8151
- label: field.label,
8152
- sortable: field.sortable,
8153
- // searchable: field.searchable,
8154
- width: field.width,
8155
- type: type,
8156
- tpl: tpl,
8157
- toggled: field.toggled,
8158
- className,
8159
- options: field.type === 'html' ? {html: true} : null
8160
- // toggled: true
8161
- }, field.amis, {name: field.name}));
8166
+ if(field.multiple){
8167
+ scriptStr = scriptStr + `data.${field.name}__label = _.map(_.filter(${field.name}Options, function(option){return _.includes(data.${field.name}, option.value)}), 'label');`;
8168
+ }else {
8169
+ scriptStr = scriptStr + `var ${field.name}Selected = _.find(${field.name}Options, function(option){return data.${field.name} == option.value});`;
8170
+ scriptStr = scriptStr + `data.${field.name}__label = ${field.name}Selected ? ${field.name}Selected.label:null;`;
8162
8171
  }
8163
8172
  }
8164
-
8173
+ });
8174
+
8175
+ // const refFields = _.filter(fields, function(field){return field.name.indexOf('.') < 0 && (field.type == 'lookup' || field.type == 'master_detail') && !field.reference_to});
8176
+ // _.each(refFields, function(field){
8177
+ // if(!_.includes(OMIT_FIELDS, field.name)){
8178
+ // const valueField = field.reference_to_field || '_id';
8179
+ // scriptStr = scriptStr + `var ${field.name}Options = eval(${field.optionsFunction.toString()})(api.data);`
8180
+ // if(field.multiple){
8181
+ // scriptStr = scriptStr + `data.${field.name}__label = _.map(_.filter(${field.name}Options, function(option){return _.includes(data.${field.name}, option.value)}), 'label');`
8182
+ // }else{
8183
+ // scriptStr = scriptStr + `var ${field.name}Selected = _.find(${field.name}Options, function(option){return data.${field.name} == option.value});`
8184
+ // scriptStr = scriptStr + `data.${field.name}__label = ${field.name}Selected ? ${field.name}Selected.label:null;`
8185
+ // }
8186
+ // }
8187
+ // })
8188
+
8189
+ return `
8190
+ if(payload.data.data.length === 0){
8191
+ return {
8192
+ status: 2,
8193
+ msg: "无法找到记录"
8194
+ }
8165
8195
  }
8166
- // columns.push(getOperation(fields));
8167
- if(!___default__namespace.some(columns, { name: options.labelFieldName })){
8168
- const href = Router$1.getObjectDetailPath({
8169
- ...options, formFactor: options.formFactor, appId: "${appId}", objectName: options.objectName || "${objectName}", recordId: `\${${options.idFieldName}}`
8170
- });
8171
- columns[0].type = "tpl";
8172
- columns[0].tpl = `<a href="${href}">\${${columns[0].name}}</a>`;
8196
+ if(payload.data.data){
8197
+ var data = payload.data.data[0];
8198
+ var gridAndObjectFieldsName = ${JSON.stringify(gridAndObjectFieldsName)};
8199
+ try{
8200
+ ${scriptStr}
8201
+ ${getScriptForAddUrlPrefixForImgFields(fields)}
8202
+ ${getScriptForRewriteValueForFileFields(fields)}
8203
+ }catch(e){
8204
+ console.error(e)
8205
+ }
8206
+ // 原始记录
8207
+ var record = _.cloneDeep(data);
8208
+ try{
8209
+ _.each(gridAndObjectFieldsName, function(name){
8210
+ data[name] = data._display[name];
8211
+ })
8212
+ }catch(e){
8213
+ console.error(e)
8214
+ }
8215
+ payload.data = data;
8216
+ payload.data.__objectName = "${object.name}";
8217
+ payload.data.__record = record;
8218
+ window.postMessage(Object.assign({type: "record.loaded"}, {record: record}), "*")
8173
8219
  }
8174
- return columns;
8220
+ if(payload.errors){
8221
+ payload.status = 2;
8222
+ payload.msg = payload.errors[0].message;
8223
+ }
8224
+ return payload;
8225
+ `
8175
8226
  }
8176
8227
 
8177
- /**
8178
- * 生成移动端列表每行显示的amis行
8179
- * @param {*} tpls 要显示的每个字段的tpl
8180
- * @returns {
8181
- "type": "wrapper",
8182
- "body": [{
8183
- "type": "tpl",
8184
- "tpl": tpls[index].tpl,
8185
- "className": "truncate"//左侧样式类
8186
- },{
8187
- "type": "tpl",
8188
- "tpl": tpls[index + 1].tpl,
8189
- "className": "truncate ml-2 flex flex-shrink-0"//右侧样式类
8190
- }],
8191
- "size": "none",
8192
- "className": "flex items-center justify-between"//每行样式类
8228
+ async function getReadonlyFormInitApi(object, recordId, fields, options){
8229
+ return {
8230
+ method: "post",
8231
+ url: getApi$2()+"&recordId=${recordId}",
8232
+ cache: API_CACHE,
8233
+ // requestAdaptor: "console.log('getReadonlyFormInitApi requestAdaptor', api);return api;",
8234
+ adaptor: getReadonlyFormAdaptor(object, fields),
8235
+ data: await getFindOneQuery$1(object, recordId, fields, options),
8236
+ headers: {
8237
+ Authorization: "Bearer ${context.tenantId},${context.authToken}"
8238
+ }
8193
8239
  }
8194
- */
8195
- function getMobileLines(tpls){
8196
- let lines = [];
8197
- let maxLineCount = 2;
8198
- let lineChildren = [];
8199
- let isNewLine = false;
8200
- let isLeft = true;
8201
- let lineChildrenClassName = "";
8202
- let lineClassName = "flex items-center justify-between h-[20px]";
8203
- tpls.forEach(function(item){
8204
- if(isNewLine && lines.length < maxLineCount){
8205
- lines.push({
8206
- "type": "wrapper",
8207
- "body": lineChildren,
8208
- "size": "none",
8209
- "className": lineClassName
8210
- });
8211
- lineChildren = [];
8240
+ }
8241
+
8242
+ /*
8243
+ img/avatar字段值添加URL前缀使其在amis中正常显示图片。
8244
+ */
8245
+ function getScriptForAddUrlPrefixForImgFields(fields){
8246
+ let imgFieldsKeys = [];
8247
+ let imgFields = {};
8248
+ fields.forEach((item)=>{
8249
+ if(___default__namespace.includes(['image','avatar'], item.type)){
8250
+ imgFieldsKeys.push(item.name);
8251
+ imgFields[item.name] = {
8252
+ name: item.name,
8253
+ type: item.type,
8254
+ multiple: item.multiple
8255
+ };
8212
8256
  }
8213
- if(isLeft){
8214
- // 左侧半行
8215
- lineChildrenClassName = "steedos-listview-item-left truncate";
8216
- if(item.field.is_wide){
8217
- // 左侧全行样式可以单独写
8218
- lineChildrenClassName = "steedos-listview-item-wide truncate";
8257
+ });
8258
+ if(!imgFieldsKeys.length){
8259
+ return '';
8260
+ }
8261
+ return `
8262
+ // image字段值添加URL前缀
8263
+ let imgFieldsKeys = ${JSON.stringify(imgFieldsKeys)};
8264
+ let imgFields = ${JSON.stringify(imgFields)};
8265
+ imgFieldsKeys.forEach((item)=>{
8266
+ let imgFieldValue = data[item];
8267
+ let imgFieldDisplayValue = data._display && data._display[item];
8268
+ if(imgFieldValue && imgFieldValue.length){
8269
+ let fieldProps = imgFields[item];
8270
+ if(fieldProps.multiple){
8271
+ if(imgFieldDisplayValue instanceof Array){
8272
+ data[item] = imgFieldDisplayValue.map((i)=>{ return i.url });
8273
+ }
8274
+ }else{
8275
+ data[item] = imgFieldDisplayValue && imgFieldDisplayValue.url;
8276
+ }
8277
+ }
8278
+ })
8279
+ `
8280
+ }
8281
+
8282
+ /*
8283
+ file字段值重写使其在amis中正常显示附件名、点击附件名下载文件。
8284
+ */
8285
+ function getScriptForRewriteValueForFileFields(fields){
8286
+ let fileFieldsKeys = [];
8287
+ let fileFields = {};
8288
+ fields.forEach((item)=>{
8289
+ if(item.type === 'file'){
8290
+ fileFieldsKeys.push(item.name);
8291
+ fileFields[item.name] = {
8292
+ name: item.name,
8293
+ multiple: item.multiple
8294
+ };
8295
+ }
8296
+ });
8297
+ if(!fileFieldsKeys.length){
8298
+ return '';
8299
+ }
8300
+ return `
8301
+ // file字段值重写以便编辑时正常显示附件名、点击附件名正常下载附件
8302
+ let fileFieldsKeys = ${JSON.stringify(fileFieldsKeys)};
8303
+ let fileFields = ${JSON.stringify(fileFields)};
8304
+ fileFieldsKeys.forEach((item)=>{
8305
+ let fileFieldValue = data[item];
8306
+ let fileFieldDisplayValue = data._display && data._display[item];
8307
+ if(fileFieldValue && fileFieldValue.length){
8308
+ if(fileFields[item].multiple){
8309
+ if(fileFieldDisplayValue instanceof Array){
8310
+ data[item] = fileFieldDisplayValue.map((item, index)=>{
8311
+ return {
8312
+ value: fileFieldValue[index],
8313
+ name: item.name,
8314
+ url: item.url + "?download=true",
8315
+ state: "uploaded"
8316
+ }
8317
+ });
8318
+ }
8319
+ }else{
8320
+ data[item] = [{
8321
+ value: fileFieldValue,
8322
+ name: fileFieldDisplayValue.name,
8323
+ url: fileFieldDisplayValue.url + "?download=true",
8324
+ state: "uploaded"
8325
+ }];
8326
+ }
8327
+ }
8328
+ })
8329
+ `
8330
+ }
8331
+
8332
+ async function getEditFormInitApi(object, recordId, fields, options){
8333
+ const data = await getFindOneQuery$1(object, recordId, fields);
8334
+ data.recordId = "${recordId}";
8335
+ data.objectName = "${objectName}";
8336
+ data.uiSchema = "${uiSchema}";
8337
+ data.global = "${global}";
8338
+ data.context = "${context}";
8339
+ data.defaultData = "${defaultData}";
8340
+ data._master = "${_master}";
8341
+
8342
+ return {
8343
+ method: "post",
8344
+ url: getApi$2() + '&objectName=${objectName}' ,
8345
+ // sendOn: "!!this.recordId",
8346
+ cache: API_CACHE,
8347
+ requestAdaptor: `
8348
+ // 所有不想在network请求中发送的数据都应该从data中分离出来,data变量只需要留下query才需要发送出去
8349
+ var { recordId, objectName, uiSchema, global, context, ...data} = api.data;
8350
+ if(!recordId){
8351
+ // 新建则不请求任何数据
8352
+ data.query = "{data:" + objectName + "(filters: " + JSON.stringify(["_id", "=", null]) + ", top: 1){_id}}";
8353
+ }
8354
+ api.data = data;
8355
+ ${options.initApiRequestAdaptor || ''}
8356
+ return api;
8357
+ `,
8358
+ adaptor: `
8359
+ const recordId = api.body.recordId;
8360
+ let initialValues={};
8361
+ if(recordId && payload.data.data){
8362
+ var data = payload.data.data[0];
8363
+ const dataKeys = _.keys(data);
8364
+ const uiSchema = api.body.uiSchema;
8365
+ const fieldKeys = uiSchema && _.keys(uiSchema.fields);
8366
+
8367
+ if(data){
8368
+ ${getScriptForAddUrlPrefixForImgFields(fields)}
8369
+ ${getScriptForRewriteValueForFileFields(fields)}
8370
+
8371
+ _.each(dataKeys, function(key){
8372
+ if(fieldKeys.indexOf(key)<0){
8373
+ delete data[key];
8374
+ }
8375
+ })
8376
+
8377
+ //初始化接口返回的字段移除字段值为null的字段
8378
+ for (key in data){
8379
+ if(data[key] === null){
8380
+ delete data[key];
8381
+ }
8382
+ }
8383
+ };
8384
+ initialValues = data;
8385
+ }
8386
+ else{
8387
+ var uiSchema = api.body.uiSchema;
8388
+ var defaultData = api.body.defaultData;
8389
+ var defaultValues = {};
8390
+ _.each(uiSchema?.fields, function(field){
8391
+ var value = SteedosUI.getFieldDefaultValue(field, api.body.global);
8392
+ if(value){
8393
+ defaultValues[field.name] = value;
8394
+ }
8395
+ });
8396
+ if(defaultData && _.isObject(defaultData) && !_.isArray(defaultData)){
8397
+ defaultValues = Object.assign({}, defaultValues, defaultData)
8398
+ }
8399
+ if(uiSchema.form){
8400
+ try{
8401
+ var objectFormConfig = JSON.parse(uiSchema.form);
8402
+ var formInitialValuesFun = objectFormConfig.initialValues;
8403
+ if(formInitialValuesFun){
8404
+ formInitialValuesFun = new Function("return " + formInitialValuesFun)();
8405
+ }
8406
+ if(typeof formInitialValuesFun === "function"){
8407
+ initialValues = formInitialValuesFun.apply({doc: defaultValues || {} , global: api.body.global, master: api.body._master })
8408
+ }
8409
+ }
8410
+ catch(ex){
8411
+ console.warn(ex);
8412
+ }
8413
+ }
8414
+ if(_.isObject(initialValues)){
8415
+ // uiSchema.form.initialValues为函数且执行后为json,则优先取initialValues中的默认值
8416
+ initialValues = Object.assign({}, defaultValues, initialValues);
8417
+ }
8418
+ else{
8419
+ initialValues = defaultValues;
8420
+ }
8219
8421
  }
8220
- if(lines.length === 0){
8221
- // 第一个字段加粗黑色显示
8222
- lineChildrenClassName += " font-bold text-gray-800";
8422
+ // data下的变量需要在保存接口(getSaveApi)中被删除。
8423
+ payload.data = {
8424
+ ...initialValues
8223
8425
  }
8426
+ ${options.initApiAdaptor || ''}
8427
+ return payload;
8428
+ `,
8429
+ responseData: {
8430
+ initialValues: "$$",
8431
+ editFormInited: true
8432
+ },
8433
+ data: data,
8434
+ headers: {
8435
+ Authorization: "Bearer ${context.tenantId},${context.authToken}"
8224
8436
  }
8225
- else {
8226
- // 右侧半行
8227
- lineChildrenClassName = "steedos-listview-item-right truncate ml-2 flex flex-shrink-0";
8228
- }
8229
- lineChildren.push({
8230
- "type": "tpl",
8231
- "tpl": item.tpl,
8232
- "className": lineChildrenClassName
8233
- });
8234
-
8235
- if(item.field.is_wide){
8236
- // 宽字段占整行
8237
- isLeft = true;
8238
- isNewLine = true;
8239
- }
8240
- else {
8241
- isLeft = !isLeft;
8242
- isNewLine = isLeft;
8243
- }
8244
- });
8245
-
8246
- if(lineChildren.length && lines.length < maxLineCount){
8247
- lines.push({
8248
- "type": "wrapper",
8249
- "body": lineChildren,
8250
- "size": "none",
8251
- "className": lineClassName
8252
- });
8253
8437
  }
8254
-
8255
- return lines;
8256
8438
  }
8257
8439
 
8258
- async function getMobileTableColumns(fields, options){
8259
- const columns = [];
8260
- let nameField = {};
8261
- let tpls = [];
8262
- for (const field of fields) {
8263
- let tpl = "";
8264
- if(field.is_name || field.name === options.labelFieldName){
8265
- nameField = field;
8266
- options.onlyDisplayLabel = true;
8267
- tpl = await getFieldTpl(field, options);
8268
- }
8269
- else if(field.type === 'avatar' || field.type === 'image' || field.type === 'file'){
8270
- // 图片和附件类型字段暂时显示为附件名称,后续需要再优化
8271
- tpl = `\${_display.${field.name}.name}`;
8272
- }
8273
- else {
8274
- if(field.type === 'lookup' || field.type === 'master_detail'){
8275
- options.onlyDisplayLabel = true;
8440
+
8441
+ function getSaveApi(object, recordId, fields, options){
8442
+ return {
8443
+ method: 'post',
8444
+ url: getApi$2(),
8445
+ data: getSaveQuery(object, recordId),
8446
+ requestAdaptor: getSaveRequestAdaptor(fields, options),
8447
+ responseData: {
8448
+ "recordId": "${record._id}"
8449
+ },
8450
+ adaptor: `
8451
+ if(payload.errors){
8452
+ payload.status = 2;
8453
+ payload.msg = window.t ? window.t(payload.errors[0].message) : payload.errors[0].message;
8276
8454
  }
8277
- tpl = await getFieldTpl(field, options);
8278
- }
8279
- if(!tpl){
8280
- tpl = `\${${field.name}}`;
8455
+ ${options.apiAdaptor || ''}
8456
+ return payload;
8457
+ `,
8458
+ headers: {
8459
+ Authorization: "Bearer ${context.tenantId},${context.authToken}"
8281
8460
  }
8282
- if(!field.hidden && !field.extra){
8283
- tpls.push({ field, tpl });
8461
+ }
8462
+ }
8463
+
8464
+ function getBatchDelete(objectName){
8465
+ return {
8466
+ method: 'post',
8467
+ url: getApi$2(),
8468
+ requestAdaptor: `
8469
+ var ids = api.data.ids.split(",");
8470
+ var deleteArray = [];
8471
+ ids.forEach((id,index)=>{
8472
+ deleteArray.push(\`delete__\${index}:${objectName}__delete(id: "\${id}")\`);
8473
+ })
8474
+ api.data = {query: \`mutation{\${deleteArray.join(',')}}\`};
8475
+ return api;
8476
+ `,
8477
+ data: {
8478
+ ids: `\${ids}`
8479
+ },
8480
+ headers: {
8481
+ Authorization: "Bearer ${context.tenantId},${context.authToken}"
8284
8482
  }
8285
8483
  }
8286
- const url = getNameTplUrl(nameField, options);
8484
+ }
8287
8485
 
8288
- const columnLines = getMobileLines(tpls);
8486
+ const DEFAULT_CALENDAR_OPTIONS = {
8487
+ startDateExpr: "start",
8488
+ endDateExpr: "end",
8489
+ allDayExpr: "is_all_day",
8490
+ textExpr: "name"
8491
+ };
8289
8492
 
8493
+ async function getCalendarApi(mainObject, fields, options) {
8494
+ if (!options) {
8495
+ options = {};
8496
+ }
8497
+ const calendarOptions = options.calendarOptions;
8498
+ const searchableFields = [];
8499
+ let { filter, sort, top, setDataToComponentId = '' } = options;
8290
8500
 
8291
- let column = {
8292
- name: nameField.name,
8293
- label: nameField.label,
8294
- sortable: nameField.sortable,
8295
- type: "button",
8296
- level: "link",
8297
- actionType: "link",
8298
- link: url,
8299
- innerClassName: "steedos-listview-item block text-gray-500",
8300
- body: {
8301
- "type": "wrapper",
8302
- "body": columnLines,
8303
- "size": "none",
8304
- "className": "p-1"
8305
- }
8306
- };
8307
-
8308
- if(options.objectName === 'cms_files'){
8309
- if(window.Meteor?.isCordova){
8310
- column = {
8311
- ...column,
8312
- actionType: "",
8313
- link: "",
8314
- onEvent: {
8315
- "click": {
8316
- "actions": [
8317
- {
8318
- "script": `
8319
- let cms_url = "/api/files/files/"+event.data.versions[0]+"?download=true"
8320
- Steedos.cordovaDownload(encodeURI(Steedos.absoluteUrl(cms_url)), event.data.name);
8321
- `,
8322
- "actionType": "custom"
8323
- }
8324
- ],
8325
- "weight": 0
8326
- }
8327
- }
8328
- };
8329
- }else {
8330
- column = {
8331
- ...column,
8332
- actionType: "",
8333
- link: "",
8334
- onEvent: {
8335
- "click": {
8336
- "actions": [
8337
- {
8338
- "args": {
8339
- "api": {
8340
- "url": url,
8341
- "method": "get",
8342
- "headers": {
8343
- "Authorization": "Bearer ${context.tenantId},${context.authToken}"
8344
- }
8345
- }
8346
- },
8347
- "actionType": "download"
8348
- }
8349
- ],
8350
- "weight": 0
8351
- }
8352
- }
8353
- };
8354
- }
8355
-
8356
- }
8501
+ if (!top) {
8502
+ // 日历请求不翻页
8503
+ top = 200;
8504
+ }
8357
8505
 
8358
- columns.push(column);
8359
-
8506
+ if (___default__default["default"].isArray(filter)) {
8507
+ filter = ___default__default["default"].map(filter, function (item) {
8508
+ if (item.operation) {
8509
+ return [item.field, item.operation, item.value];
8510
+ } else {
8511
+ return item
8512
+ }
8513
+ });
8514
+ }
8515
+ if (!filter) {
8516
+ filter = [];
8517
+ }
8360
8518
 
8361
- return columns;
8362
- }
8519
+ ___default__default["default"].each(fields, function (field) {
8520
+ if (field.searchable) {
8521
+ searchableFields.push(field.name);
8522
+ }
8523
+ });
8363
8524
 
8364
- function getDefaultParams(options){
8365
- return {
8366
- perPage: options.top || options.perPage || config.listView.perPage
8525
+ const idFieldName = mainObject.idFieldName || "_id";
8526
+ let valueField = mainObject.key_field || '_id';
8527
+ const api = await getApi(mainObject, null, fields, { alias: 'rows', limit: top, queryOptions: `filters: {__filters}, top: {__top}, skip: {__skip}, sort: "{__sort}"` });
8528
+ api.data.$term = "$term";
8529
+ api.data.$self = "$$";
8530
+ api.data.filter = "$filter";
8531
+ api.data.pageSize = top || 10;
8532
+ api.requestAdaptor = `
8533
+ let selfData = JSON.parse(JSON.stringify(api.data.$self));
8534
+ var filters = api.data.filter || ${JSON.stringify(filter)} || [];
8535
+ const eventFetchInfo = selfData.fetchInfo;
8536
+ const startDateExpr = "${calendarOptions.startDateExpr}";
8537
+ const endDateExpr = "${calendarOptions.endDateExpr}";
8538
+ const eventDurationFilters = [[endDateExpr, ">=", eventFetchInfo.start], [startDateExpr, "<=", eventFetchInfo.end]];
8539
+ if(_.isEmpty(filters)){
8540
+ filters = eventDurationFilters;
8541
+ }else{
8542
+ filters = [filters, 'and', eventDurationFilters]
8367
8543
  }
8368
- }
8369
-
8370
- function getButtonVisibleOn(button){
8371
- let visible= button.visible;
8372
8544
 
8373
- if(button._visible){
8374
- visible = button._visible;
8545
+ if(api.data.$self.additionalFilters){
8546
+ filters.push(api.data.$self.additionalFilters)
8375
8547
  }
8376
8548
 
8377
- if(___default.isBoolean(visible)){
8378
- visible = visible.toString();
8549
+ var pageSize = api.data.pageSize || 10;
8550
+ var pageNo = api.data.pageNo || 1;
8551
+ var skip = (pageNo - 1) * pageSize;
8552
+ var orderBy = api.data.orderBy || '';
8553
+ var orderDir = api.data.orderDir || '';
8554
+ var sort = orderBy + ' ' + orderDir;
8555
+ sort = orderBy ? sort : "${sort}";
8556
+ var allowSearchFields = ${JSON.stringify(searchableFields)};
8557
+ if(api.data.$term){
8558
+ filters = [["name", "contains", "'+ api.data.$term +'"]];
8559
+ }else if(selfData.op === 'loadOptions' && selfData.value){
8560
+ filters = [["${valueField.name}", "=", selfData.value]];
8379
8561
  }
8562
+ var searchableFilter = SteedosUI.getSearchFilter(selfData) || [];
8380
8563
 
8381
- if(visible){
8382
- // if(visible.indexOf("Meteor.") > 0 || visible.indexOf("Creator.") > 0 || visible.indexOf("Session.") > 0){
8383
- // console.warn('无效的visible', visible)
8384
- // return 'false';
8385
- // }
8386
- if(visible.trim().startsWith('function')){
8387
- return `${visible}(objectName, typeof _id === 'undefined' ? null: _id, typeof record === 'undefined' ? (typeof recordPermissions === 'undefined' ? {} : recordPermissions) : record.recordPermissions, data)`
8564
+ if(searchableFilter.length > 0){
8565
+ if(filters.length > 0 ){
8566
+ filters = [filters, 'and', searchableFilter];
8567
+ }else{
8568
+ filters = searchableFilter;
8388
8569
  }
8389
- return visible;
8390
8570
  }
8391
8571
 
8392
- if(button.type === 'amis_button'){
8393
- const amisSchema = button.amis_schema;
8394
- if(amisSchema && amisSchema.body && amisSchema.body.length > 0){
8395
- const btn1 = amisSchema.body[0];
8396
- return btn1.visibleOn
8397
- }
8572
+ if(allowSearchFields){
8573
+ allowSearchFields.forEach(function(key){
8574
+ const keyValue = selfData[key];
8575
+ if(_.isString(keyValue)){
8576
+ filters.push([key, "contains", keyValue]);
8577
+ }else if(_.isArray(keyValue) || _.isBoolean(keyValue) || keyValue){
8578
+ filters.push([key, "=", keyValue]);
8579
+ }
8580
+ })
8398
8581
  }
8399
- }
8400
-
8401
- async function getTableOperation(ctx){
8402
- const buttons = ctx.buttons;
8403
- const operationButtons = [];
8404
- ___default.each(buttons, (button)=>{
8405
- if(___default.isBoolean(button.visible)){
8406
- button.visible = button.visible.toString();
8407
- }
8408
- // operationButtons.push({
8409
- // type: 'button',
8410
- // label: button.label,
8411
- // visibleOn: button.visible ? `${button.visible}` : (button._visible ? `${button._visible}` : null),
8412
- // onEvent: {
8413
- // click: {
8414
- // actions: []
8415
- // }
8416
- // }
8417
- // })
8418
8582
 
8419
- operationButtons.push({
8420
- type: 'steedos-object-button',
8421
- name: button.name,
8422
- objectName: button.objectName,
8423
- visibleOn: getButtonVisibleOn(button),
8424
- className: 'antd-Button--default'
8425
- });
8426
- });
8427
- if(operationButtons.length < 1){
8428
- return ;
8429
- }
8430
- return {
8431
- type: 'operation',
8432
- label: '操作',
8433
- fixed: 'right',
8434
- labelClassName: 'text-center',
8435
- className: 'text-center steedos-listview-operation w-20',
8436
- buttons: [
8437
- {
8438
- "type": "steedos-dropdown-button",
8439
- "label": "xxx",
8440
- "buttons": operationButtons,
8441
- "placement": "bottomRight",
8442
- "overlayClassName": "shadow !min-w-[160px]",
8443
- "trigger": ["click"],
8444
- "id": "u:c2140a365019",
8445
- onOpenApi: {
8446
- url: `\${context.rootUrl}/service/api/@\${objectName}/recordPermissions/\${_id}`,
8447
- method: "get",
8448
- data: {
8449
- $: "$$",
8450
- objectName: "${objectName}",
8451
- listViewId: "${listViewId}",
8452
- appId: "${appId}",
8453
- formFactor: "${formFactor}",
8454
- context: `\${context}`
8455
- },
8456
- headers: {
8457
- Authorization: "Bearer ${context.tenantId},${context.authToken}"
8458
- },
8459
- adaptor: `
8460
- payload = {
8461
- record: {
8462
- recordPermissions: payload
8463
- }
8464
- };
8465
- return payload;
8466
- `,
8583
+ if(selfData.__keywords && allowSearchFields){
8584
+ const keywordsFilters = [];
8585
+ allowSearchFields.forEach(function(key, index){
8586
+ const keyValue = selfData.__keywords;
8587
+ if(keyValue){
8588
+ keywordsFilters.push([key, "contains", keyValue]);
8589
+ if(index < allowSearchFields.length - 1){
8590
+ keywordsFilters.push('or');
8467
8591
  }
8468
- }
8469
- ]
8592
+ }
8593
+ })
8594
+ filters.push(keywordsFilters);
8595
+ }
8596
+ api.data.query = api.data.query.replace(/{__filters}/g, JSON.stringify(filters)).replace('{__top}', pageSize).replace('{__skip}', skip).replace('{__sort}', sort.trim());
8597
+ delete api.data.$term;
8598
+ delete api.data.filter;
8599
+ delete api.data.pageSize;
8600
+ delete api.data.pageNo;
8601
+ delete api.data.orderBy;
8602
+ delete api.data.orderDir;
8603
+ return api;
8604
+ `;
8605
+ api.adaptor = `
8606
+ window.postMessage(Object.assign({type: "listview.loaded"}), "*");
8607
+ const setDataToComponentId = "${setDataToComponentId}";
8608
+ if(setDataToComponentId){
8609
+ SteedosUI.getRef(api.body.$self.scopeId)?.getComponentById(setDataToComponentId)?.setData({$count: payload.data.count})
8470
8610
  }
8611
+ const rows = payload.data.rows || [];
8612
+ const selfData = api.data.$self;
8613
+ const events = rows.map(function(n){
8614
+ return {
8615
+ id: n["${idFieldName}"],
8616
+ title: n["${calendarOptions.textExpr}"],
8617
+ start: n["${calendarOptions.startDateExpr}"],
8618
+ end: n["${calendarOptions.endDateExpr}"],
8619
+ allDay: n["${calendarOptions.allDayExpr}"],
8620
+ extendedProps: n
8621
+ }
8622
+ });
8623
+ const successCallback = selfData.successCallback;
8624
+ const failureCallback = selfData.failureCallback;
8625
+ successCallback(events);
8626
+ return payload;
8627
+ `;
8628
+ return api;
8471
8629
  }
8472
8630
 
8473
- async function getTableSchema$1(fields, options){
8474
- if(!options){
8475
- options = {};
8476
- }
8477
- let columns = [];
8478
- if(options.formFactor === 'SMALL' || ["split"].indexOf(options.displayAs) > -1){
8479
- columns = await getMobileTableColumns(fields, options);
8480
- }
8481
- else {
8482
- columns = await getTableColumns$1(fields, options);
8483
- columns.push(await getTableOperation(options));
8631
+ function getCalendarRecordPermissionsApi(mainObject, recordId) {
8632
+ const api = getRecordPermissionsApi(mainObject, recordId, { alias: 'rows', limit: 1, fields: ["allowEdit"] });
8633
+ api.data.$self = "$$";
8634
+ api.adaptor = `
8635
+ const rows = payload.data.rows || [];
8636
+ const selfData = api.data.$self;
8637
+ const revert = selfData.revert;
8638
+ const recordPermissions = rows[0] && rows[0].recordPermissions;
8639
+ const editable = !!(recordPermissions && recordPermissions.allowEdit);
8640
+ if(!editable){
8641
+ // 没有权限时还原
8642
+ revert && revert();
8484
8643
  }
8485
- return {
8486
- mode: "table",
8487
- name: "thelist",
8488
- headerToolbarClassName: "py-2 px-2 border-gray-300 bg-gray-100 border-solid border-b",
8489
- className: "",
8490
- draggable: false,
8491
- defaultParams: getDefaultParams(options),
8492
- columns: columns,
8493
- syncLocation: false,
8494
- keepItemSelectionOnPageChange: true,
8495
- checkOnItemClick: false,
8496
- labelTpl: `\${${options.labelFieldName}}`,
8497
- autoFillHeight: false, // 自动高度效果不理想,先关闭
8498
- columnsTogglable: false,
8644
+ payload.data.editable = editable;
8645
+ return payload;
8646
+ `;
8647
+ return api;
8648
+ }
8649
+
8650
+ function getCalendarRecordSaveApi(object, calendarOptions) {
8651
+ const formData = {};
8652
+ const idFieldName = object.idFieldName || "_id";
8653
+ formData[idFieldName] = "${event.data.event.id}";
8654
+ const nameFieldKey = object.NAME_FIELD_KEY || "name";
8655
+ formData[nameFieldKey] = "${event.data.event.title}";
8656
+ formData[calendarOptions.startDateExpr] = "${event.data.event.start}";
8657
+ formData[calendarOptions.endDateExpr] = "${event.data.event.end}";
8658
+ formData[calendarOptions.allDayExpr] = "${event.data.event.allDay}";
8659
+ // formData[calendarOptions.textExpr] = "${event.data.event.title}";
8660
+ const apiData = {
8661
+ objectName: "${objectName}",
8662
+ $: formData,
8663
+ $self: "$$"
8664
+ };
8665
+ const saveDataTpl = `
8666
+ const formData = api.data.$;
8667
+ const objectName = api.data.objectName;
8668
+ let query = \`mutation{record: \${objectName}__update(id: "\${formData.${idFieldName}}", doc: {__saveData}){${idFieldName}}}\`;
8669
+ delete formData.${idFieldName};
8670
+ let __saveData = JSON.stringify(JSON.stringify(formData));
8671
+ `;
8672
+ const requestAdaptor = `
8673
+ ${saveDataTpl}
8674
+ api.data.query = query.replace('{__saveData}', __saveData);
8675
+ return api;
8676
+ `;
8677
+
8678
+ return {
8679
+ method: 'post',
8680
+ url: getApi$2(),
8681
+ data: apiData,
8682
+ requestAdaptor: requestAdaptor,
8683
+ adaptor: `
8684
+ if(payload.errors){
8685
+ payload.status = 2;
8686
+ payload.msg = payload.errors[0].message;
8687
+ const revert = api.data.$self.event.data.revert;
8688
+ revert && revert();
8689
+ }
8690
+ return payload;
8691
+ `,
8692
+ headers: {
8693
+ Authorization: "Bearer ${context.tenantId},${context.authToken}"
8499
8694
  }
8695
+ };
8500
8696
  }
8501
8697
 
8502
-
8503
-
8504
8698
  /**
8505
- *
8506
- * @param {*} mainObject
8507
- * @param {*} fields
8508
- * @param {*} options = {filter: listview 过滤条件, ...}
8509
- * @returns
8699
+ * 列表视图Calendar amisSchema
8700
+ * @param {*} objectSchema 对象UISchema
8701
+ * @returns amisSchema
8510
8702
  */
8511
- async function getTableApi(mainObject, fields, options){
8512
- const searchableFields = [];
8513
- let { filter, filtersFunction, sort, top, setDataToComponentId = '' } = options;
8703
+ async function getObjectCalendar(objectSchema, calendarOptions, options) {
8704
+ const permissions = objectSchema.permissions;
8705
+ if (!options) {
8706
+ options = {};
8707
+ }
8514
8708
 
8515
- if(___default__namespace.isArray(filter)){
8516
- filter = ___default__namespace.map(filter, function(item){
8517
- if(item.operation){
8518
- return [item.field, item.operation, item.value];
8519
- }else {
8520
- return item
8521
- }
8522
- });
8709
+ calendarOptions = Object.assign({}, DEFAULT_CALENDAR_OPTIONS, ___default.omitBy(calendarOptions, ___default.isNil));
8710
+
8711
+ const titleFields = calendarOptions.title || [
8712
+ calendarOptions.startDateExpr,
8713
+ calendarOptions.endDateExpr,
8714
+ calendarOptions.allDayExpr,
8715
+ calendarOptions.textExpr
8716
+ ];
8717
+ let fields = [];
8718
+ ___default.each(titleFields, function (n) {
8719
+ if (objectSchema.fields[n]) {
8720
+ fields.push(objectSchema.fields[n]);
8523
8721
  }
8524
- if(!filter){
8525
- filter = [];
8722
+ });
8723
+
8724
+ if (objectSchema.fields[calendarOptions.allDayExpr]) {
8725
+ fields.push(objectSchema.fields[calendarOptions.allDayExpr]);
8726
+ }
8727
+
8728
+ let sort = options.sort;
8729
+ if (!sort) {
8730
+ const sortField = options.sortField;
8731
+ const sortOrder = options.sortOrder;
8732
+ if (sortField) {
8733
+ let sortStr = sortField + ' ' + sortOrder || 'asc';
8734
+ sort = sortStr;
8526
8735
  }
8527
- let baseFilters = null;
8528
- if(filter){
8529
- baseFilters = filter;
8736
+ }
8737
+ let initialView = calendarOptions.currentView;
8738
+ if (initialView) {
8739
+ // day, week, month, agenda
8740
+ switch (initialView) {
8741
+ case "day":
8742
+ initialView = "timeGridDay";
8743
+ break;
8744
+ case "week":
8745
+ initialView = "timeGridWeek";
8746
+ break;
8747
+ case "month":
8748
+ initialView = "dayGridMonth";
8749
+ break;
8750
+ case "agenda":
8751
+ initialView = "listWeek";
8752
+ break;
8530
8753
  }
8531
- ___default__namespace.each(fields,function(field){
8532
- if(field.searchable){
8533
- searchableFields.push(field.name);
8534
- }
8535
- });
8536
-
8537
- const fileFields = {};
8538
- const fileFieldsKeys = [];
8539
- // 含有optionsFunction属性, 无reference_to属性的lookup字段
8540
- const lookupFields = {};
8541
- fields.forEach((item)=>{
8542
- if(___default__namespace.includes(['image','avatar','file'], item.type)){
8543
- fileFieldsKeys.push(item.name);
8544
- fileFields[item.name] = {
8545
- name: item.name,
8546
- type: item.type,
8547
- multiple: item.multiple
8548
- };
8549
- }
8550
- if(___default__namespace.includes(['lookup'], item.type) && !item.reference_to ){
8551
- lookupFields[item.name] = item;
8552
- }
8553
- });
8754
+ }
8755
+ else {
8756
+ initialView = "timeGridWeek";
8757
+ }
8554
8758
 
8555
- let valueField = mainObject.key_field || '_id';
8556
- const api = await getApi(mainObject, null, fields, {count: options.queryCount, alias: 'rows', limit: top, queryOptions: `filters: {__filters}, top: {__top}, skip: {__skip}, sort: "{__sort}"`});
8759
+ options.calendarOptions = calendarOptions;
8760
+ const api = await getCalendarApi(objectSchema, fields, options);
8557
8761
 
8558
- if(options.isRelated){
8559
- api.url += "&recordId=${_master.recordId}";
8560
- }
8762
+ const onGetEventsScript = `
8763
+ const api = ${JSON.stringify(api)};
8764
+ event.data.calendarOptions = ${JSON.stringify(calendarOptions)};
8765
+ doAction({
8766
+ "actionType": 'ajax',
8767
+ "args": {
8768
+ "api": api
8769
+ },
8770
+ });
8771
+ `;
8561
8772
 
8562
- api.data.$term = "$term";
8563
- api.data.term = "$term";
8564
- api.data.$self = "$$";
8565
- api.data.self = "$$";
8566
- api.data.filter = "$filter";
8567
- api.data.loaded = "${loaded}";
8568
- api.data.listViewId = "${listViewId}";
8569
- api.data.listName = "${listName}";
8570
- api.requestAdaptor = `
8571
- // selfData 中的数据由 CRUD 控制. selfData中,只能获取到 CRUD 给定的data. 无法从数据链中获取数据.
8572
- let selfData = JSON.parse(JSON.stringify(api.data.$self));
8573
- // 保留一份初始data,以供自定义发送适配器中获取原始数据。
8574
- const data = _.cloneDeep(api.data);
8575
- try{
8576
- // TODO: 不应该直接在这里取localStorage,应该从外面传入
8577
- const listViewId = api.data.listViewId;
8578
- const listViewPropsStoreKey = location.pathname + "/crud/" + listViewId ;
8579
- let localListViewProps = sessionStorage.getItem(listViewPropsStoreKey);
8580
- if(localListViewProps){
8581
- localListViewProps = JSON.parse(localListViewProps);
8582
- selfData = Object.assign({}, localListViewProps, selfData);
8583
- if(!api.data.filter){
8584
- api.data.filter = localListViewProps.filter;
8585
- }
8586
- if(!api.data.loaded){
8587
- // 第一次加载组件,比如刷新浏览器时因为api.data.pageNo有默认值1
8588
- // 所以会把localSearchableFilter中已经存过的页码覆盖
8589
- // 如果是第一次加载组件始终让翻页页码从本地存储中取值
8590
- let formFactor = "${options.formFactor}";
8591
- // 移动端不识别本地存储中的翻页页码,否则点击加载更多按钮后无法刷新回第一页
8592
- api.data.pageNo = formFactor === "SMALL" ? 1 : (localListViewProps.page || 1);
8593
- }
8594
- }
8595
- }
8596
- catch(ex){
8597
- console.error("本地存储中crud参数解析异常:", ex);
8598
- }
8599
- ${baseFilters ? `var systemFilters = ${JSON.stringify(baseFilters)};` : 'var systemFilters = [];'}
8600
- var _ids = []
8601
- const filtersFunction = ${filtersFunction};
8602
- if(filtersFunction){
8603
- const _filters = filtersFunction(systemFilters, api.data.$self);
8604
- if(api.data.listName == "recent"){
8605
- _ids = _filters[2]
8606
- }
8607
- if(_filters && _filters.length > 0){
8608
- if(_.isEmpty(systemFilters)){
8609
- systemFilters = _filters || [];
8610
- }else{
8611
- systemFilters = [systemFilters, 'and', _filters];
8773
+ const onSelectScript = `
8774
+ const data = event.data;
8775
+ const doc = {};
8776
+ doc["${calendarOptions.startDateExpr}"] = data.start;
8777
+ doc["${calendarOptions.endDateExpr}"] = data.end;
8778
+ doc["${calendarOptions.allDayExpr}"] = data.allDay;
8779
+ doc["${calendarOptions.textExpr}"] = data.title;
8780
+ // ObjectForm会认作用域下的变量值
8781
+ // TODO: 待组件支持initValues属性后应该改掉,不应该通过data直接传值
8782
+ // TODO: 全天事件属性传入doc了但是没有生效,需要手动在ObjectForm中勾选全天事件
8783
+ const title = "新建 ${objectSchema.label}";
8784
+ doAction(
8785
+ {
8786
+ "actionType": "dialog",
8787
+ "dialog": {
8788
+ "type": "dialog",
8789
+ "title": title,
8790
+ "body": [
8791
+ {
8792
+ "type": "steedos-object-form",
8793
+ "objectApiName": "\${objectName}",
8794
+ "mode": "edit",
8795
+ "defaultData": doc,
8796
+ "onEvent": {
8797
+ "submitSucc": {
8798
+ "weight": 0,
8799
+ "actions": [
8800
+ {
8801
+ "actionType": "custom",
8802
+ "script": "event.data.view?.calendar.refetchEvents();"
8803
+ }
8804
+ ]
8612
8805
  }
8806
+ }
8613
8807
  }
8808
+ ],
8809
+ "closeOnEsc": false,
8810
+ "closeOnOutside": false,
8811
+ "showCloseButton": true,
8812
+ "size": "lg"
8614
8813
  }
8615
- let userFilters =[];
8616
-
8617
- if(_.isEmpty(systemFilters)){
8618
- systemFilters = api.data.filter || [];
8619
- }else{
8620
- if(!_.isEmpty(api.data.filter)){
8621
- systemFilters = [systemFilters, 'and', api.data.filter];
8622
- }
8623
- }
8624
- var pageSize = api.data.pageSize || 10;
8625
- var pageNo = api.data.pageNo || 1;
8626
- var skip = (pageNo - 1) * pageSize;
8627
- var orderBy = api.data.orderBy || '';
8628
- var orderDir = api.data.orderDir || '';
8629
- var sort = orderBy + ' ' + orderDir;
8630
- sort = orderBy ? sort : "${sort || ''}";
8631
- var allowSearchFields = ${JSON.stringify(searchableFields)};
8632
- if(api.data.$term){
8633
- userFilters = [["name", "contains", "'+ api.data.$term +'"]];
8634
- }else if(selfData.op === 'loadOptions' && selfData.value){
8635
- userFilters = [["${valueField.name}", "=", selfData.value]];
8636
- }
8637
-
8638
- var searchableFilter = SteedosUI.getSearchFilter(selfData) || [];
8639
-
8640
- if(searchableFilter.length > 0){
8641
- if(userFilters.length > 0 ){
8642
- userFilters = [userFilters, 'and', searchableFilter];
8643
- }else{
8644
- userFilters = searchableFilter;
8645
- }
8646
- }
8814
+ });
8815
+ `;
8647
8816
 
8648
- if(allowSearchFields){
8649
- allowSearchFields.forEach(function(key){
8650
- const keyValue = selfData[key];
8651
- if(_.isString(keyValue)){
8652
- userFilters.push([key, "contains", keyValue]);
8653
- }else if(_.isArray(keyValue) || _.isBoolean(keyValue) || keyValue){
8654
- userFilters.push([key, "=", keyValue]);
8655
- }
8656
- })
8657
- }
8817
+ const onEventClickScript = `
8818
+ const data = event.data;
8819
+ const eventData = data.event;
8820
+ const appId = data.appId;
8821
+ const objectName = data.objectName;
8822
+ const eventId = data.event && data.event.id;
8823
+ doAction({
8824
+ "actionType": "dialog",
8825
+ "dialog": {
8826
+ "type": "dialog",
8827
+ "title": "",
8828
+ "body": [
8829
+ {
8830
+ "type": "steedos-record-detail",
8831
+ "objectApiName": "\${objectName}",
8832
+ "recordId": data.event && data.event.id
8833
+ }
8834
+ ],
8835
+ "closeOnEsc": false,
8836
+ "closeOnOutside": false,
8837
+ "showCloseButton": true,
8838
+ "size": "lg",
8839
+ "actions": []
8840
+ }
8841
+ });
8842
+ `;
8658
8843
 
8659
- if(selfData.__keywords && allowSearchFields){
8660
- const keywordsFilters = [];
8661
- allowSearchFields.forEach(function(key, index){
8662
- const keyValue = selfData.__keywords;
8663
- if(keyValue){
8664
- keywordsFilters.push([key, "contains", keyValue]);
8665
- if(index < allowSearchFields.length - 1){
8666
- keywordsFilters.push('or');
8667
- }
8668
- }
8669
- })
8670
- userFilters.push(keywordsFilters);
8671
- };
8844
+ const recordId = "${event.id}";
8845
+ const recordPermissionsApi = getCalendarRecordPermissionsApi(objectSchema, recordId);
8846
+ const recordSaveApi = getCalendarRecordSaveApi(objectSchema, calendarOptions);
8672
8847
 
8673
- let filters = [];
8848
+ const businessHours = {
8849
+ daysOfWeek: [1, 2, 3, 4, 5],
8850
+ startTime: '08:00',
8851
+ endTime: '18:00',
8852
+ };
8853
+ if (!___default.isEmpty(calendarOptions.startDayHour)) {
8854
+ businessHours.startTime = `${calendarOptions.startDayHour}:00`;
8855
+ }
8856
+ if (!___default.isEmpty(calendarOptions.endDayHour)) {
8857
+ businessHours.endTime = `${calendarOptions.endDayHour}:00`;
8858
+ }
8674
8859
 
8675
- if(!_.isEmpty(systemFilters)){
8676
- filters = systemFilters;
8677
- };
8678
- if(api.data.$self.additionalFilters){
8679
- if(_.isString(api.data.$self.additionalFilters)){
8680
- userFilters.push(eval(api.data.$self.additionalFilters))
8681
- }else{
8682
- userFilters.push(api.data.$self.additionalFilters)
8683
- }
8860
+ const onEvent = {
8861
+ "getEvents": {
8862
+ "weight": 0,
8863
+ "actions": [
8864
+ {
8865
+ "componentId": "",
8866
+ "args": {
8867
+ },
8868
+ "actionType": "custom",
8869
+ "script": onGetEventsScript
8684
8870
  }
8685
-
8686
- if(api.data.$self._isRelated){
8687
- const self = api.data.$self;
8688
- const relatedKey = self.relatedKey;
8689
- const refField = self.uiSchema.fields[relatedKey];
8690
- const masterRecord = self._master.record;
8691
- const masterObjectName = self._master.objectName;
8692
- let relatedValue = self._master.recordId;
8693
- if(refField.reference_to_field && refField.reference_to_field != '_id'){
8694
- relatedValue = masterRecord[refField.reference_to_field]
8695
- }
8696
- let relatedFilters;
8697
- if (
8698
- refField._reference_to ||
8699
- (refField.reference_to && !_.isString(refField.reference_to))
8700
- ) {
8701
- relatedFilters = [
8702
- [relatedKey + "/o", "=", masterObjectName],
8703
- [relatedKey + "/ids", "=", relatedValue],
8704
- ];
8705
- } else {
8706
- relatedFilters = [relatedKey, "=", relatedValue];
8707
- }
8708
- userFilters.push(relatedFilters)
8871
+ ]
8872
+ },
8873
+ "select": {
8874
+ "weight": 0,
8875
+ "actions": [
8876
+ {
8877
+ "componentId": "",
8878
+ "args": {
8879
+ },
8880
+ "actionType": "custom",
8881
+ "script": onSelectScript
8709
8882
  }
8710
-
8711
- if(!_.isEmpty(userFilters)){
8712
- if(_.isEmpty(filters)){
8713
- filters = userFilters;
8714
- }else{
8715
- filters = [filters, 'and', userFilters]
8716
- }
8883
+ ]
8884
+ },
8885
+ "eventClick": {
8886
+ "weight": 0,
8887
+ "actions": [
8888
+ {
8889
+ "componentId": "",
8890
+ "args": {
8891
+ },
8892
+ "actionType": "custom",
8893
+ "script": onEventClickScript
8717
8894
  }
8718
- api.data._ids = _ids;
8719
- api.data = {
8720
- query: api.data.query.replace(/{__filters}/g, JSON.stringify(filters)).replace('{__top}', pageSize).replace('{__skip}', skip).replace('{__sort}', sort.trim())
8895
+ ]
8896
+ },
8897
+ "eventAdd": {
8898
+ "weight": 0,
8899
+ "actions": [
8900
+ {
8901
+ "componentId": "",
8902
+ "args": {
8903
+ },
8904
+ "actionType": "custom",
8905
+ "script": "console.log('eventAdd'); console.log(event);"
8721
8906
  }
8722
- ${options.requestAdaptor || ''}
8723
- return api;
8724
- `;
8725
- api.adaptor = `
8726
- if(api.body.listName == "recent"){
8727
- payload.data.rows = _.sortBy(payload.data.rows, function(item){
8728
- return _.indexOf(api.body._ids, item._id)
8729
- });
8730
- }
8731
- const enable_tree = ${mainObject.enable_tree};
8732
- if(!enable_tree){
8733
- _.each(payload.data.rows, function(item, index){
8734
- const {pageNo, pageSize} = api.body;
8735
- const skip = (pageNo - 1) * pageSize;
8736
- item._index = skip + index + 1;
8737
- })
8738
- }
8739
- window.postMessage(Object.assign({type: "listview.loaded"}), "*");
8740
- let fileFields = ${JSON.stringify(fileFields)};
8741
- let lookupFields = ${JSON.stringify(lookupFields)};
8742
- _.each(payload.data.rows, function(item, index){
8743
- _.each(fileFields , (field, key)=>{
8744
- if(item[key] && item._display && item._display[key]){
8745
- let value = item._display[key];
8746
- if(!_.isArray(value)){
8747
- value = [value]
8748
- };
8749
- if(field.type === 'file'){
8750
- item[key] = value
8751
- }else{
8752
- item[key] = _.map(value, 'url')
8753
- }
8754
- }
8755
- })
8756
- _.each(lookupFields , (field, key)=>{
8757
- if(item[key]){
8758
- if(field._optionsFunction){
8759
- const optionsFunction = eval("(" + field._optionsFunction+ ")")(item);
8760
- item[key + '__label'] = _.map(_.filter(optionsFunction, function(option){return _.includes(item[key], option.value)}), 'label').join(' ');
8761
- }
8762
- }
8763
- })
8764
- })
8765
-
8766
- if(enable_tree){
8767
- const records = payload.data.rows || [];
8768
- const getTreeOptions = SteedosUI.getTreeOptions
8769
- payload.data.rows = getTreeOptions(records,{"valueField":"_id"});
8770
- }
8771
-
8772
-
8773
- try{
8774
- // TODO: 不应该直接在这里取localStorage,应该从外面传入
8775
- const listViewId = api.body.listViewId;
8776
- const listViewPropsStoreKey = location.pathname + "/crud/" + listViewId ;
8777
- /**
8778
- * localListViewProps规范来自crud请求api中api.data.$self参数值的。
8779
- * 比如:{"perPage":20,"page":1,"__searchable__name":"7","__searchable__between__n1__c":[null,null],"filter":[["name","contains","a"]]}
8780
- * __searchable__...:顶部放大镜搜索条件
8781
- * filter:右侧过滤器
8782
- * perPage:每页条数
8783
- * page:当前页码
8784
- * orderBy:排序字段
8785
- * orderDir:排序方向
8786
- */
8787
- let localListViewProps = sessionStorage.getItem(listViewPropsStoreKey);
8788
- let selfData = JSON.parse(JSON.stringify(api.body.$self));
8789
- if(localListViewProps){
8790
- localListViewProps = JSON.parse(localListViewProps);
8791
- selfData = Object.assign({}, localListViewProps, selfData, { filter: api.body.filter });
8792
- if(!api.body.loaded){
8793
- // 第一次加载组件,比如刷新浏览器时因为api.data.pageNo有默认值1
8794
- // 所以会把localSearchableFilter中已经存过的页码覆盖
8795
- // 如果是第一次加载组件始终让翻页页码从本地存储中取值
8796
- let formFactor = "${options.formFactor}";
8797
- // 移动端不识别本地存储中的翻页页码,否则点击加载更多按钮后无法刷新回第一页
8798
- selfData.page = formFactor === "SMALL" ? 1 : (localListViewProps.page || 1);
8907
+ ]
8908
+ },
8909
+ "eventChange": {
8910
+ "weight": 0,
8911
+ "actions": [
8912
+ {
8913
+ "actionType": 'ajax',
8914
+ "args": {
8915
+ "api": recordPermissionsApi
8916
+ }
8917
+ },
8918
+ {
8919
+ "actionType": "toast",
8920
+ "expression": "!event.data.editable",
8921
+ "args": {
8922
+ "msgType": "error",
8923
+ "msg": "您没有编辑该记录的权限!",
8924
+ "position": "top-center"
8925
+ }
8926
+ },
8927
+ {
8928
+ "actionType": 'ajax',
8929
+ "expression": "event.data.editable",
8930
+ "args": {
8931
+ "api": recordSaveApi,
8932
+ "messages": {
8933
+ "success": objectSchema.label + "修改成功",
8934
+ "failed": objectSchema.label + "修改失败!"
8799
8935
  }
8936
+ }
8937
+ }
8938
+ ]
8939
+ },
8940
+ "eventRemove": {
8941
+ "weight": 0,
8942
+ "actions": [
8943
+ {
8944
+ "componentId": "",
8945
+ "args": {
8946
+ },
8947
+ "actionType": "custom",
8948
+ "script": "console.log('eventRemove'); console.log(event);"
8949
+ }
8950
+ ]
8951
+ },
8952
+ "eventsSet": {
8953
+ "weight": 0,
8954
+ "actions": [
8955
+ {
8956
+ "componentId": "",
8957
+ "args": {
8958
+ },
8959
+ "actionType": "custom",
8960
+ "script": "console.log('eventsSet'); console.log(event);"
8800
8961
  }
8801
- delete selfData.context;
8802
- delete selfData.global;
8803
- sessionStorage.setItem(listViewPropsStoreKey, JSON.stringify(selfData));
8804
- // 返回页码到UI界面
8805
- payload.data.page= selfData.page;
8806
- }
8807
- catch(ex){
8808
- console.error("本地存储中crud参数解析异常:", ex);
8962
+ ]
8809
8963
  }
8810
- // 标记加载过,后续优先从本地存储中加载相关参数
8811
- payload.data.loaded= true;
8964
+ };
8812
8965
 
8813
- const setDataToComponentId = "${setDataToComponentId}";
8814
- if(setDataToComponentId){
8815
- SteedosUI.getRef(api.body.$self.$scopeId)?.getComponentById(setDataToComponentId)?.setData({$count: payload.data.count})
8816
- };
8817
- ${options.adaptor || ''}
8818
- return payload;
8819
- `;
8820
- return api;
8821
- }
8966
+ Object.assign(onEvent, options.onEvent);
8822
8967
 
8823
- async function getApi(object, recordId, fields, options){
8824
- const data = await getFindQuery(object, recordId, fields, options);
8825
- return {
8826
- method: "post",
8827
- url: getApi$2(), // + "&recordId=${recordId}"
8828
- data: data,
8829
- headers: {
8830
- Authorization: "Bearer ${context.tenantId},${context.authToken}"
8831
- }
8968
+ const config = options.config || {};
8969
+ if(config.eventContent && typeof config.eventContent === "string"){
8970
+ const hasReturn = /\breturn\b/.test(config.eventContent);
8971
+ if(hasReturn){
8972
+ try {
8973
+ // 如果是包括return语句的字符串,则按函数解析,见 https://fullcalendar.io/docs/content-injection
8974
+ let fn = new Function("arg", config.eventContent);
8975
+ config.eventContent = fn;
8976
+ } catch (e) {
8977
+ console.warn(e);
8978
+ }
8832
8979
  }
8833
- }
8980
+ }
8834
8981
 
8835
- function getRecordPermissionsApi(object, recordId, options){
8836
- const data = getRecordPermissionsQuery(object, recordId, options);
8837
- return {
8838
- method: "post",
8839
- url: getApi$2(),
8840
- data: data,
8841
- headers: {
8842
- Authorization: "Bearer ${context.tenantId},${context.authToken}"
8843
- }
8982
+ if(config.noEventsContent && typeof config.noEventsContent === "string"){
8983
+ const hasReturn = /\breturn\b/.test(config.noEventsContent);
8984
+ if(hasReturn){
8985
+ try {
8986
+ // 如果是包括return语句的字符串,则按函数解析,见 https://fullcalendar.io/docs/content-injection
8987
+ let fn = new Function("arg", config.noEventsContent);
8988
+ config.noEventsContent = fn;
8989
+ } catch (e) {
8990
+ console.warn(e);
8991
+ }
8844
8992
  }
8993
+ }
8994
+
8995
+ const amisSchema = {
8996
+ "type": "steedos-fullcalendar",
8997
+ "label": "",
8998
+ "name": "fullcalendar",
8999
+ "placeholder":"${additionalFilters}",//用于触发reload
9000
+ "editable": permissions.allowEdit,
9001
+ "selectable": permissions.allowCreate,
9002
+ "selectMirror": permissions.allowCreate,
9003
+ "initialView": initialView,
9004
+ "businessHours": businessHours,
9005
+ ...config,
9006
+ "onEvent": onEvent
9007
+ };
9008
+ return amisSchema;
8845
9009
  }
8846
9010
 
8847
- const DEFAULT_CALENDAR_OPTIONS = {
8848
- startDateExpr: "start",
8849
- endDateExpr: "end",
8850
- allDayExpr: "is_all_day",
8851
- textExpr: "name"
9011
+ /*
9012
+ * @Author: baozhoutao@steedos.com
9013
+ * @Date: 2022-05-26 16:02:08
9014
+ * @LastEditors: 殷亮辉 yinlianghui@hotoa.com
9015
+ * @LastEditTime: 2023-06-04 15:49:23
9016
+ * @Description:
9017
+ */
9018
+
9019
+ const getFieldSchemaArray = (formFields) => {
9020
+ let fieldSchemaArray = [];
9021
+ fieldSchemaArray.length = 0;
9022
+
9023
+ ___default__namespace.forEach(formFields, (field) => {
9024
+ if (!field.group || field.group == 'null' || field.group == '-')
9025
+ field.group = '通用';
9026
+ const fieldName = field.name;
9027
+ let isObjectField = /\w+\.\w+/.test(fieldName);
9028
+ if (field.type == 'grid' || field.type == 'object') {
9029
+ // field.group = field.label
9030
+ field.is_wide = true;
9031
+ }
9032
+
9033
+ if (!isObjectField) {
9034
+ if (!field.hidden) {
9035
+ fieldSchemaArray.push(Object.assign({ name: fieldName }, field, { permission: { allowEdit: true } }));
9036
+ }
9037
+ }
9038
+ });
9039
+ return fieldSchemaArray;
8852
9040
  };
8853
9041
 
8854
- async function getCalendarApi(mainObject, fields, options) {
8855
- if (!options) {
8856
- options = {};
9042
+ const getSection = async (formFields, permissionFields, fieldSchemaArray, sectionName, ctx) => {
9043
+ if (!ctx) {
9044
+ ctx = {};
8857
9045
  }
8858
- const calendarOptions = options.calendarOptions;
8859
- const searchableFields = [];
8860
- let { filter, sort, top, setDataToComponentId = '' } = options;
8861
-
8862
- if (!top) {
8863
- // 日历请求不翻页
8864
- top = 200;
9046
+ const sectionFields = ___default__namespace.filter(fieldSchemaArray, { 'group': sectionName });
9047
+ if (sectionFields.length == ___default__namespace.filter(sectionFields, ['hidden', true]).length) {
9048
+ return;
8865
9049
  }
8866
9050
 
8867
- if (___default__default["default"].isArray(filter)) {
8868
- filter = ___default__default["default"].map(filter, function (item) {
8869
- if (item.operation) {
8870
- return [item.field, item.operation, item.value];
8871
- } else {
8872
- return item
9051
+ const fieldSetBody = [];
9052
+
9053
+ for (const perField of sectionFields) {
9054
+ let field = perField;
9055
+ if (perField.type === 'grid') {
9056
+ field = await getGridFieldSubFields(perField, formFields);
9057
+ // console.log(`perField.type grid ===> field`, field)
9058
+ } else if (perField.type === 'object') {
9059
+ field = await getObjectFieldSubFields(perField, formFields);
9060
+ // console.log(`perField.type object ===> field`, field)
9061
+ }
9062
+ if (field.name.indexOf(".") < 0) {
9063
+ ctx.__formFields = formFields;
9064
+ const amisField = await convertSFieldToAmisField(field, field.readonly, ctx);
9065
+ // console.log(`${field.name} amisField`, field, amisField)
9066
+ if (amisField) {
9067
+ fieldSetBody.push(amisField);
8873
9068
  }
8874
- });
9069
+ }
8875
9070
  }
8876
- if (!filter) {
8877
- filter = [];
9071
+
9072
+ // fieldSet 已支持显隐控制
9073
+ const sectionFieldsVisibleOn = ___default__namespace.map(___default__namespace.compact(___default__namespace.map(fieldSetBody, 'visibleOn')), (visibleOn) => {
9074
+ return visibleOn;
9075
+ });
9076
+
9077
+ let section = {
9078
+ "type": "fieldSet",
9079
+ "title": sectionName,
9080
+ "collapsable": true,
9081
+ "body": fieldSetBody,
9082
+ };
9083
+
9084
+ if (ctx.enableTabs) {
9085
+ section = {
9086
+ "title": sectionName,
9087
+ "body": fieldSetBody,
9088
+ };
8878
9089
  }
8879
9090
 
8880
- ___default__default["default"].each(fields, function (field) {
8881
- if (field.searchable) {
8882
- searchableFields.push(field.name);
9091
+ if (sectionFieldsVisibleOn.length > 0 && fieldSetBody.length === sectionFieldsVisibleOn.length) {
9092
+ section.visibleOn = `${sectionFieldsVisibleOn.join(" || ")}`;
9093
+ }
9094
+ return section
9095
+ };
9096
+
9097
+ const getSections = async (permissionFields, formFields, ctx) => {
9098
+ if (!ctx) {
9099
+ ctx = {};
9100
+ }
9101
+ const fieldSchemaArray = getFieldSchemaArray(formFields);
9102
+ const _sections = ___default__namespace.groupBy(fieldSchemaArray, 'group');
9103
+ const sections = [];
9104
+ var sectionVisibleOns = [];
9105
+ for (const key in _sections) {
9106
+ const section = await getSection(formFields, permissionFields, fieldSchemaArray, key, ctx);
9107
+ if (section.body.length > 0) {
9108
+ if (section.visibleOn) {
9109
+ sectionVisibleOns.push(section.visibleOn);
9110
+ }
9111
+ else {
9112
+ sectionVisibleOns.push("true");
9113
+ }
9114
+ sections.push(section);
8883
9115
  }
9116
+ }
9117
+ /*
9118
+ 为了实现只有一个分组时隐藏该分组标题,需要分三种情况(分组如果没有visibleon属性就代表一定显示,有visibleon需要进行判断)
9119
+ 1 当前分组为隐藏时,标题就设置为隐藏
9120
+ 2 当前分组为显示时,其他分组只要有一个是显示,就显示该分组标题
9121
+ 3 当前分组为显示时,其他分组都隐藏,就隐藏该分组标题
9122
+ */
9123
+ sections.forEach((section, index) => {
9124
+ var tempSectionVisibleOns = sectionVisibleOns.slice();
9125
+ tempSectionVisibleOns.splice(index, 1);
9126
+ section.headingClassName = {
9127
+ "hidden": `!((${tempSectionVisibleOns.join(" || ") || 'false'}) && ${sectionVisibleOns[index]})`
9128
+ };
8884
9129
  });
8885
9130
 
8886
- const idFieldName = mainObject.idFieldName || "_id";
8887
- let valueField = mainObject.key_field || '_id';
8888
- const api = await getApi(mainObject, null, fields, { alias: 'rows', limit: top, queryOptions: `filters: {__filters}, top: {__top}, skip: {__skip}, sort: "{__sort}"` });
8889
- api.data.$term = "$term";
8890
- api.data.$self = "$$";
8891
- api.data.filter = "$filter";
8892
- api.data.pageSize = top || 10;
8893
- api.requestAdaptor = `
8894
- let selfData = JSON.parse(JSON.stringify(api.data.$self));
8895
- var filters = api.data.filter || ${JSON.stringify(filter)} || [];
8896
- const eventFetchInfo = selfData.fetchInfo;
8897
- const startDateExpr = "${calendarOptions.startDateExpr}";
8898
- const endDateExpr = "${calendarOptions.endDateExpr}";
8899
- const eventDurationFilters = [[endDateExpr, ">=", eventFetchInfo.start], [startDateExpr, "<=", eventFetchInfo.end]];
8900
- if(_.isEmpty(filters)){
8901
- filters = eventDurationFilters;
8902
- }else{
8903
- filters = [filters, 'and', eventDurationFilters]
8904
- }
9131
+ if (ctx.enableTabs) {
9132
+ // TODO: 以下sectionHeaderVisibleOn代码逻辑是为实现只有一个选项卡时给选项卡添加sectionHeaderVisibleOn样式类来把选项卡顶部卡头隐藏
9133
+ // 但是 amis filter过滤器有两个bug造成此功能不好实现:
9134
+ // 1.filter过滤器只支持对象数组,并不支持boolean或字符串数组,见: https://github.com/baidu/amis/issues/7078
9135
+ // 2.filter过滤器的返回结果无法进一步获取最终过滤后的数组长度,见:https://github.com/baidu/amis/issues/7077
9136
+ // let sectionHeaderVisibleOn = "false";
9137
+ // if(sectionVisibleOns.length){
9138
+ // sectionHeaderVisibleOn = "[" + sectionVisibleOns.join(",") + "]" + "|filter:equals:true.length > 1";
9139
+ // }
9140
+ // console.log("===sectionHeaderVisibleOn===", sectionHeaderVisibleOn);
9141
+ // sectionHeaderVisibleOn = "[true]|filter:equals:true.length > 1";
9142
+ // sectionHeaderVisibleOn = "false";
9143
+ // sectionHeaderVisibleOn = "[1,1,1]|filter:equals:1.length > 1";
9144
+ return [
9145
+ {
9146
+ "type": "tabs",
9147
+ // "className": {
9148
+ // "hiddenFormTabs": `!(${sectionHeaderVisibleOn})`
9149
+ // },
9150
+ "tabs": sections,
9151
+ "tabsMode": ctx.tabsMode
9152
+ }
9153
+ ]
9154
+ }
9155
+
9156
+ return sections;
9157
+ };
9158
+
9159
+ /*
9160
+ * @Author: baozhoutao@steedos.com
9161
+ * @Date: 2022-07-07 11:02:29
9162
+ * @LastEditors: baozhoutao@steedos.com
9163
+ * @LastEditTime: 2023-03-07 17:19:34
9164
+ * @Description:
9165
+ */
9166
+
9167
+ async function getFormBody(permissionFields, formFields, ctx){
9168
+ return await getSections(permissionFields, formFields, ctx);
9169
+ }
9170
+
9171
+ // lodash的defaultsDeep函数有bug,无法正确合并值为数值的节点,重写修正该函数
9172
+ // 源码出处:https://github.com/nodeutils/defaults-deep
9173
+ const defaultsDeep = (...args)=>{
9174
+ let output = {};
9175
+ ___default.toArray(args).reverse().forEach(item=> {
9176
+ ___default.mergeWith(output, item, (objectValue, sourceValue) => {
9177
+ return ___default.isArray(sourceValue) ? sourceValue : undefined;
9178
+ });
9179
+ });
9180
+ return output;
9181
+ };
9182
+
9183
+ function getBulkActions(objectSchema){
9184
+ return [
9185
+ {
9186
+ "type": "button",
9187
+ "level": "danger",
9188
+ "label": "批量删除",
9189
+ "actionType": "ajax",
9190
+ "confirmText": "确定要删除吗",
9191
+ "className": "hidden",
9192
+ "id": "batchDelete",
9193
+ "api": getBatchDelete(objectSchema.name),
9194
+ }
9195
+ // {
9196
+ // "label": "批量修改",
9197
+ // "actionType": "dialog",
9198
+ // "dialog": {
9199
+ // "title": "批量编辑",
9200
+ // "name": "sample-bulk-edit",
9201
+ // "body": {
9202
+ // "type": "form",
9203
+ // "api": "https://3xsw4ap8wah59.cfc-execute.bj.baidubce.com/api/amis-mock/sample/bulkUpdate2",
9204
+ // "controls": [
9205
+ // {
9206
+ // "type": "hidden",
9207
+ // "name": "ids"
9208
+ // },
9209
+ // {
9210
+ // "type": "text",
9211
+ // "name": "name",
9212
+ // "label": "Name"
9213
+ // }
9214
+ // ]
9215
+ // }
9216
+ // }
9217
+ // }
9218
+ ]
9219
+ }
8905
9220
 
8906
- if(api.data.$self.additionalFilters){
8907
- filters.push(api.data.$self.additionalFilters)
9221
+ async function getObjectCRUD(objectSchema, fields, options){
9222
+ // console.time('getObjectCRUD');
9223
+ const { top, perPage, showDisplayAs = false, displayAs, crudClassName = "" } = options;
9224
+ const nonpaged = objectSchema.paging && objectSchema.paging.enabled === false;
9225
+ const isTreeObject = objectSchema.enable_tree;
9226
+ const bulkActions = getBulkActions(objectSchema);
9227
+ const bodyProps = {
9228
+ // toolbar: getToolbar(),
9229
+ // headerToolbar: getObjectHeaderToolbar(objectSchema, options.formFactor, {showDisplayAs}),
9230
+ headerToolbarClassName: "px-4 py-2 border-gray-300 bg-gray-100 border-solid border-b",
9231
+ footerToolbar: getObjectFooterToolbar(objectSchema, options.formFactor, {
9232
+ disableStatistics: options.queryCount === false
9233
+ }),
9234
+ filter: options.filterVisible !== false && await getObjectFilter(objectSchema, fields, options),
9235
+ };
9236
+ if(options.formFactor !== 'SMALL' || ["split"].indexOf(options.displayAs) == -1){
9237
+ Object.assign(bodyProps, {
9238
+ bulkActions: options.bulkActions != false ? bulkActions : false
9239
+ });
8908
9240
  }
8909
-
8910
- var pageSize = api.data.pageSize || 10;
8911
- var pageNo = api.data.pageNo || 1;
8912
- var skip = (pageNo - 1) * pageSize;
8913
- var orderBy = api.data.orderBy || '';
8914
- var orderDir = api.data.orderDir || '';
8915
- var sort = orderBy + ' ' + orderDir;
8916
- sort = orderBy ? sort : "${sort}";
8917
- var allowSearchFields = ${JSON.stringify(searchableFields)};
8918
- if(api.data.$term){
8919
- filters = [["name", "contains", "'+ api.data.$term +'"]];
8920
- }else if(selfData.op === 'loadOptions' && selfData.value){
8921
- filters = [["${valueField.name}", "=", selfData.value]];
9241
+ // yml里配置的 不分页和enable_tree:true 优先级最高,组件中输入的top次之。
9242
+ options.queryCount = true;
9243
+ if(nonpaged || isTreeObject){
9244
+ options.top = 5000;
9245
+ bodyProps.footerToolbar = [];
9246
+ options.queryCount = true; // 禁止翻页的时候, 需要查找总数
9247
+ }else if(top){
9248
+ bodyProps.footerToolbar = [];
9249
+ if(options.isRelated){
9250
+ options.queryCount = true;
9251
+ }else {
9252
+ options.queryCount = false;
9253
+ }
8922
9254
  }
8923
- var searchableFilter = SteedosUI.getSearchFilter(selfData) || [];
9255
+ // console.log(`getObjectHeaderToolbar====2===>`, options.filterVisible)
9256
+ bodyProps.headerToolbar = getObjectHeaderToolbar(objectSchema, options.formFactor, {
9257
+ showDisplayAs,
9258
+ hiddenCount: options.queryCount === false,
9259
+ headerToolbarItems: options.headerToolbarItems,
9260
+ filterVisible: options.filterVisible
9261
+ });
8924
9262
 
8925
- if(searchableFilter.length > 0){
8926
- if(filters.length > 0 ){
8927
- filters = [filters, 'and', searchableFilter];
8928
- }else{
8929
- filters = searchableFilter;
8930
- }
8931
- }
8932
9263
 
8933
- if(allowSearchFields){
8934
- allowSearchFields.forEach(function(key){
8935
- const keyValue = selfData[key];
8936
- if(_.isString(keyValue)){
8937
- filters.push([key, "contains", keyValue]);
8938
- }else if(_.isArray(keyValue) || _.isBoolean(keyValue) || keyValue){
8939
- filters.push([key, "=", keyValue]);
9264
+ let body = null;
9265
+ const id = `listview_${objectSchema.name}`;
9266
+ if(options.formFactor === 'SMALL' && false){
9267
+ delete bodyProps.bulkActions;
9268
+ delete bodyProps.headerToolbar;
9269
+ delete bodyProps.footerToolbar;
9270
+ const card = await getCardSchema(fields, Object.assign({idFieldName: objectSchema.idFieldName, labelFieldName: objectSchema.NAME_FIELD_KEY || 'name'}, options, {actions: false}));
9271
+ body = Object.assign({}, card , {
9272
+ type: 'crud',
9273
+ primaryField: '_id',
9274
+ id: id,
9275
+ name: id,
9276
+ keepItemSelectionOnPageChange: false,
9277
+ api: await getTableApi(objectSchema, fields, options),
9278
+ hiddenOn: options.tableHiddenOn,
9279
+ },
9280
+ bodyProps
9281
+ );
9282
+ }else {
9283
+ let labelFieldName = objectSchema.NAME_FIELD_KEY || 'name';
9284
+ // organizations 对象的历史遗留问题, fullname 被标记为了 名称字段. 在此处特殊处理.
9285
+ if(objectSchema.name === 'organizations'){
9286
+ labelFieldName = 'name';
9287
+ }
9288
+ const table = await getTableSchema$1(fields, Object.assign({idFieldName: objectSchema.idFieldName, labelFieldName: labelFieldName, permissions:objectSchema.permissions,enable_inline_edit:objectSchema.enable_inline_edit}, options));
9289
+ delete table.mode;
9290
+ //image与avatar需要在提交修改时特别处理
9291
+ const imageNames = ___default__default["default"].compact(___default__default["default"].map(___default__default["default"].filter(fields, (field) => ["image","avatar"].includes(field.type)), 'name'));
9292
+ const quickSaveApiRequestAdaptor = `
9293
+ var graphqlOrder = "";
9294
+ var imageNames = ${JSON.stringify(imageNames)};
9295
+ api.data.rowsDiff.forEach(function (item, index) {
9296
+ for(key in item){
9297
+ if(_.includes(imageNames, key)){
9298
+ if(typeof item[key] == "string"){
9299
+ const match = item[key].match(/\\/([^\\/]+)$/);
9300
+ item[key] = match && match.length > 1?match[1]:"";
9301
+ }else{
9302
+ item[key] = _.map(item[key], function(ele){
9303
+ const match = ele.match(/\\/([^\\/]+)$/);
9304
+ return match && match.length > 1?match[1]:"";
9305
+ })
9306
+ }
8940
9307
  }
9308
+ }
9309
+ const itemOrder = 'update' + index + ':' + api.data.objectName + '__update(id:"' + item._id + '", doc:' + JSON.stringify(JSON.stringify(_.omit(item, '_id'))) + ') {_id}';
9310
+ graphqlOrder += itemOrder;
8941
9311
  })
8942
- }
8943
-
8944
- if(selfData.__keywords && allowSearchFields){
8945
- const keywordsFilters = [];
8946
- allowSearchFields.forEach(function(key, index){
8947
- const keyValue = selfData.__keywords;
8948
- if(keyValue){
8949
- keywordsFilters.push([key, "contains", keyValue]);
8950
- if(index < allowSearchFields.length - 1){
8951
- keywordsFilters.push('or');
8952
- }
9312
+ graphqlOrder = 'mutation {' + graphqlOrder + '}';
9313
+ return {
9314
+ ...api,
9315
+ data: {
9316
+ query: graphqlOrder
8953
9317
  }
8954
- })
8955
- filters.push(keywordsFilters);
8956
- }
8957
- api.data.query = api.data.query.replace(/{__filters}/g, JSON.stringify(filters)).replace('{__top}', pageSize).replace('{__skip}', skip).replace('{__sort}', sort.trim());
8958
- delete api.data.$term;
8959
- delete api.data.filter;
8960
- delete api.data.pageSize;
8961
- delete api.data.pageNo;
8962
- delete api.data.orderBy;
8963
- delete api.data.orderDir;
8964
- return api;
8965
- `;
8966
- api.adaptor = `
8967
- window.postMessage(Object.assign({type: "listview.loaded"}), "*");
8968
- const setDataToComponentId = "${setDataToComponentId}";
8969
- if(setDataToComponentId){
8970
- SteedosUI.getRef(api.body.$self.scopeId)?.getComponentById(setDataToComponentId)?.setData({$count: payload.data.count})
8971
- }
8972
- const rows = payload.data.rows || [];
8973
- const selfData = api.data.$self;
8974
- const events = rows.map(function(n){
8975
- return {
8976
- id: n["${idFieldName}"],
8977
- title: n["${calendarOptions.textExpr}"],
8978
- start: n["${calendarOptions.startDateExpr}"],
8979
- end: n["${calendarOptions.endDateExpr}"],
8980
- allDay: n["${calendarOptions.allDayExpr}"],
8981
- extendedProps: n
8982
- }
8983
- });
8984
- const successCallback = selfData.successCallback;
8985
- const failureCallback = selfData.failureCallback;
8986
- successCallback(events);
8987
- return payload;
8988
- `;
8989
- return api;
8990
- }
9318
+ }
9319
+ `;
8991
9320
 
8992
- function getCalendarRecordPermissionsApi(mainObject, recordId) {
8993
- const api = getRecordPermissionsApi(mainObject, recordId, { alias: 'rows', limit: 1, fields: ["allowEdit"] });
8994
- api.data.$self = "$$";
8995
- api.adaptor = `
8996
- const rows = payload.data.rows || [];
8997
- const selfData = api.data.$self;
8998
- const revert = selfData.revert;
8999
- const recordPermissions = rows[0] && rows[0].recordPermissions;
9000
- const editable = !!(recordPermissions && recordPermissions.allowEdit);
9001
- if(!editable){
9002
- // 没有权限时还原
9003
- revert && revert();
9321
+ body = Object.assign({}, table, {
9322
+ type: 'crud',
9323
+ primaryField: '_id',
9324
+ affixHeader: false,
9325
+ id: id,
9326
+ name: id,
9327
+ keepItemSelectionOnPageChange: true,
9328
+ api: await getTableApi(objectSchema, fields, options),
9329
+ hiddenOn: options.tableHiddenOn,
9330
+ autoFillHeight: options.isRelated ? false : true,
9331
+ className: `flex-auto ${crudClassName || ""}`,
9332
+ bodyClassName: "bg-white",
9333
+ crudClassName: crudClassName,
9334
+ quickSaveApi: {
9335
+ url: `\${context.rootUrl}/graphql`,
9336
+ method: "post",
9337
+ dataType: "json",
9338
+ headers: {
9339
+ Authorization: "Bearer ${context.tenantId},${context.authToken}",
9340
+ },
9341
+ requestAdaptor: quickSaveApiRequestAdaptor,
9342
+ },
9343
+ rowClassNameExpr: options.rowClassNameExpr
9344
+ },
9345
+ bodyProps,
9346
+ );
9004
9347
  }
9005
- payload.data.editable = editable;
9006
- return payload;
9007
- `;
9008
- return api;
9009
- }
9010
-
9011
- function getCalendarRecordSaveApi(object, calendarOptions) {
9012
- const formData = {};
9013
- const idFieldName = object.idFieldName || "_id";
9014
- formData[idFieldName] = "${event.data.event.id}";
9015
- const nameFieldKey = object.NAME_FIELD_KEY || "name";
9016
- formData[nameFieldKey] = "${event.data.event.title}";
9017
- formData[calendarOptions.startDateExpr] = "${event.data.event.start}";
9018
- formData[calendarOptions.endDateExpr] = "${event.data.event.end}";
9019
- formData[calendarOptions.allDayExpr] = "${event.data.event.allDay}";
9020
- // formData[calendarOptions.textExpr] = "${event.data.event.title}";
9021
- const apiData = {
9022
- objectName: "${objectName}",
9023
- $: formData,
9024
- $self: "$$"
9025
- };
9026
- const saveDataTpl = `
9027
- const formData = api.data.$;
9028
- const objectName = api.data.objectName;
9029
- let query = \`mutation{record: \${objectName}__update(id: "\${formData.${idFieldName}}", doc: {__saveData}){${idFieldName}}}\`;
9030
- delete formData.${idFieldName};
9031
- let __saveData = JSON.stringify(JSON.stringify(formData));
9032
- `;
9033
- const requestAdaptor = `
9034
- ${saveDataTpl}
9035
- api.data.query = query.replace('{__saveData}', __saveData);
9036
- return api;
9037
- `;
9038
9348
 
9039
- return {
9040
- method: 'post',
9041
- url: getApi$2(),
9042
- data: apiData,
9043
- requestAdaptor: requestAdaptor,
9044
- adaptor: `
9045
- if(payload.errors){
9046
- payload.status = 2;
9047
- payload.msg = payload.errors[0].message;
9048
- const revert = api.data.$self.event.data.revert;
9049
- revert && revert();
9349
+ const defaults = options.defaults;
9350
+ if (defaults) {
9351
+ const listSchema = defaults.listSchema || {};
9352
+ body = defaultsDeep({}, listSchema, body);
9353
+ const headerSchema = defaults.headerSchema;
9354
+ const footerSchema = defaults.footerSchema;
9355
+ if (headerSchema || footerSchema) {
9356
+ let wrappedBody = [body];
9357
+ if (headerSchema) {
9358
+ if(___default__default["default"].isArray(headerSchema)){
9359
+ wrappedBody = ___default__default["default"].union(headerSchema,wrappedBody);
9360
+ }
9361
+ else {
9362
+ wrappedBody.unshift(headerSchema);
9363
+ }
9050
9364
  }
9051
- return payload;
9052
- `,
9053
- headers: {
9054
- Authorization: "Bearer ${context.tenantId},${context.authToken}"
9365
+ if (footerSchema) {
9366
+ if(___default__default["default"].isArray(footerSchema)){
9367
+ wrappedBody = ___default__default["default"].union(wrappedBody,footerSchema);
9368
+ }
9369
+ else {
9370
+ wrappedBody.push(footerSchema);
9371
+ }
9372
+ }
9373
+ body = wrappedBody;
9374
+ }
9375
+ }
9376
+ // console.timeEnd('getObjectCRUD');
9377
+ // TODO: data应该只留loaded,其他属性都改为从上层传递下来
9378
+ return {
9379
+ type: 'service',
9380
+ className: '',
9381
+ id: `service_${id}`,
9382
+ name: `page`,
9383
+ data: {
9384
+ objectName: objectSchema.name,
9385
+ // _id: null,
9386
+ recordPermissions: objectSchema.permissions,
9387
+ uiSchema: objectSchema,
9388
+ // loaded: false //crud接收适配器中设置为true,否则就是刷新浏览器第一次加载
9389
+ },
9390
+ body: body
9055
9391
  }
9056
- };
9057
9392
  }
9058
9393
 
9059
- /**
9060
- * 列表视图Calendar amisSchema
9061
- * @param {*} objectSchema 对象UISchema
9062
- * @returns amisSchema
9063
- */
9064
- async function getObjectCalendar(objectSchema, calendarOptions, options) {
9065
- const permissions = objectSchema.permissions;
9066
- if (!options) {
9067
- options = {};
9068
- }
9069
-
9070
- calendarOptions = Object.assign({}, DEFAULT_CALENDAR_OPTIONS, ___default.omitBy(calendarOptions, ___default.isNil));
9394
+ const getGlobalData = (mode)=>{
9395
+ const user = getSteedosAuth();
9396
+ return {mode: mode, user: user, spaceId: user.spaceId, userId: user.userId}
9397
+ };
9071
9398
 
9072
- const titleFields = calendarOptions.title || [
9073
- calendarOptions.startDateExpr,
9074
- calendarOptions.endDateExpr,
9075
- calendarOptions.allDayExpr,
9076
- calendarOptions.textExpr
9077
- ];
9078
- let fields = [];
9079
- ___default.each(titleFields, function (n) {
9080
- if (objectSchema.fields[n]) {
9081
- fields.push(objectSchema.fields[n]);
9399
+ const getFormFields = (objectSchema, formProps)=>{
9400
+ /**
9401
+ * fieldsExtend: 重写字段定义
9402
+ * fields: 包含的字段
9403
+ * excludedFields: 排除的字段
9404
+ */
9405
+ const { fieldsExtend, fields: includedFields, excludedFields } = formProps;
9406
+
9407
+ let fields = {};
9408
+ // 以uiSchema fields 为基础, 遍历字段, 并更新字段定义
9409
+ ___default__default["default"].forEach(objectSchema.fields, (field, fieldName)=>{
9410
+ if(!lodash.has(field, "name")){
9411
+ field.name = fieldName;
9412
+ }
9413
+ if(fieldsExtend && fieldsExtend[fieldName]){
9414
+ fields[field.name] = Object.assign({}, field, fieldsExtend[fieldName], {name: field.name});
9415
+ }else {
9416
+ fields[field.name] = field;
9082
9417
  }
9083
9418
  });
9084
9419
 
9085
- if (objectSchema.fields[calendarOptions.allDayExpr]) {
9086
- fields.push(objectSchema.fields[calendarOptions.allDayExpr]);
9420
+ if(!___default__default["default"].isEmpty(includedFields) && ___default__default["default"].isArray(includedFields)){
9421
+ const includedFieldsMap = {};
9422
+ ___default__default["default"].each(includedFields, (fName, index)=>{
9423
+ if(fields[fName]){
9424
+ includedFieldsMap[fName] = Object.assign({}, fields[fName], {sort_no: index});
9425
+ }
9426
+ });
9427
+ fields = includedFieldsMap;
9087
9428
  }
9088
9429
 
9089
- let sort = options.sort;
9090
- if (!sort) {
9091
- const sortField = options.sortField;
9092
- const sortOrder = options.sortOrder;
9093
- if (sortField) {
9094
- let sortStr = sortField + ' ' + sortOrder || 'asc';
9095
- sort = sortStr;
9096
- }
9097
- }
9098
- let initialView = calendarOptions.currentView;
9099
- if (initialView) {
9100
- // day, week, month, agenda
9101
- switch (initialView) {
9102
- case "day":
9103
- initialView = "timeGridDay";
9104
- break;
9105
- case "week":
9106
- initialView = "timeGridWeek";
9107
- break;
9108
- case "month":
9109
- initialView = "dayGridMonth";
9110
- break;
9111
- case "agenda":
9112
- initialView = "listWeek";
9113
- break;
9114
- }
9115
- }
9116
- else {
9117
- initialView = "timeGridWeek";
9430
+ if(!___default__default["default"].isEmpty(excludedFields) && ___default__default["default"].isArray(excludedFields)){
9431
+ ___default__default["default"].each(excludedFields, (fName)=>{
9432
+ delete fields[fName];
9433
+ });
9118
9434
  }
9119
9435
 
9120
- options.calendarOptions = calendarOptions;
9121
- const api = await getCalendarApi(objectSchema, fields, options);
9436
+ return lodash.sortBy(___default__default["default"].values(fields), "sort_no");
9437
+ };
9122
9438
 
9123
- const onGetEventsScript = `
9124
- const api = ${JSON.stringify(api)};
9125
- event.data.calendarOptions = ${JSON.stringify(calendarOptions)};
9126
- doAction({
9127
- "actionType": 'ajax',
9128
- "args": {
9129
- "api": api
9439
+ async function getObjectForm(objectSchema, ctx){
9440
+ const { recordId, formFactor, layout = formFactor === 'SMALL' ? 'normal' : "normal", labelAlign, tabId, appId, defaults } = ctx;
9441
+ const fields = ___default__default["default"].values(objectSchema.fields);
9442
+ const formFields = getFormFields(objectSchema, ctx);
9443
+ const formSchema = defaults && defaults.formSchema || {};
9444
+ if(___default__default["default"].has(formSchema, 'className')){
9445
+ formSchema.className = 'steedos-amis-form';
9446
+ }
9447
+ const amisSchema = {
9448
+ type: 'service',
9449
+ className: 'p-0',
9450
+ name: `page_edit_${recordId}`,
9451
+ api: await getEditFormInitApi(objectSchema, recordId, fields, ctx),
9452
+ data:{
9453
+ editFormInited: false
9130
9454
  },
9131
- });
9132
- `;
9455
+ // data: {global: getGlobalData('edit'), recordId: recordId, objectName: objectSchema.name, context: {rootUrl: getRootUrl(), tenantId: getTenantId(), authToken: getAuthToken()}},
9456
+ initApi: null,
9457
+ initFetch: null ,
9458
+ body: [defaultsDeep({}, formSchema, {
9459
+ type: "form",
9460
+ mode: layout,
9461
+ data: {
9462
+ "&": "${initialValues}"
9463
+ },
9464
+ labelAlign,
9465
+ persistData: false,
9466
+ resetAfterSubmit: true,
9467
+ preventEnterSubmit: true,
9468
+ promptPageLeave: true,
9469
+ canAccessSuperData: false,
9470
+ name: `form_edit_${recordId}`,
9471
+ debug: false,
9472
+ title: "",
9473
+ submitText: "", // amis 表单不显示提交按钮, 表单提交由项目代码接管
9474
+ api: await getSaveApi(objectSchema, recordId, fields, ctx),
9475
+ initFetch: recordId != 'new',
9476
+ body: await getFormBody(fields, formFields, ctx),
9477
+ panelClassName:'m-0 sm:rounded-lg shadow-none border-none',
9478
+ bodyClassName: 'p-0',
9479
+ className: 'steedos-amis-form',
9480
+ hiddenOn: "${editFormInited != true}",
9481
+ onEvent: {
9482
+ "submitSucc": {
9483
+ "weight": 0,
9484
+ "actions": [
9485
+ {
9486
+ "actionType": "broadcast",
9487
+ "args": {
9488
+ "eventName": `@data.changed.${objectSchema.name}`
9489
+ },
9490
+ "data": {
9491
+ "objectName": `${objectSchema.name}`,
9492
+ "displayAs": "${displayAs}"
9493
+ }
9494
+ },
9495
+ {
9496
+ "actionType": "broadcast",
9497
+ "args": {
9498
+ "eventName": "@data.changed.${_master.objectName}"
9499
+ },
9500
+ "data": {
9501
+ "objectName": "${_master.objectName}",
9502
+ "_isRelated": "${_isRelated || _master._isRelated}"
9503
+ },
9504
+ "expression": `\${_master.objectName != '${objectSchema.name}' && _master.objectName}`
9505
+ },
9506
+ // {
9507
+ // "actionType": "custom",
9508
+ // "script": "debugger;"
9509
+ // },
9510
+ // {
9511
+ // "args": {},
9512
+ // "actionType": "closeDialog"
9513
+ // }
9514
+ ]
9515
+ }
9516
+ }
9517
+ })]
9518
+ };
9519
+ if(formSchema.id){
9520
+ amisSchema.id = `service-${formSchema.id}`;
9521
+ }
9522
+ return amisSchema;
9523
+ }
9133
9524
 
9134
- const onSelectScript = `
9135
- const data = event.data;
9136
- const doc = {};
9137
- doc["${calendarOptions.startDateExpr}"] = data.start;
9138
- doc["${calendarOptions.endDateExpr}"] = data.end;
9139
- doc["${calendarOptions.allDayExpr}"] = data.allDay;
9140
- doc["${calendarOptions.textExpr}"] = data.title;
9141
- // ObjectForm会认作用域下的变量值
9142
- // TODO: 待组件支持initValues属性后应该改掉,不应该通过data直接传值
9143
- // TODO: 全天事件属性传入doc了但是没有生效,需要手动在ObjectForm中勾选全天事件
9144
- const title = "新建 ${objectSchema.label}";
9145
- doAction(
9146
- {
9147
- "actionType": "dialog",
9148
- "dialog": {
9149
- "type": "dialog",
9150
- "title": title,
9151
- "body": [
9152
- {
9153
- "type": "steedos-object-form",
9154
- "objectApiName": "\${objectName}",
9155
- "mode": "edit",
9156
- "defaultData": doc,
9157
- "onEvent": {
9158
- "submitSucc": {
9159
- "weight": 0,
9525
+ async function getObjectDetail(objectSchema, recordId, ctx){
9526
+ const { formFactor, layout = formFactor === 'SMALL' ? 'normal' : "normal", labelAlign, formInitProps } = ctx;
9527
+ const fields = ___default__default["default"].values(objectSchema.fields);
9528
+ const formFields = getFormFields(objectSchema, ctx);
9529
+ const serviceId = `service_detail_page`;
9530
+ return {
9531
+ type: 'service',
9532
+ name: `page_readonly_${recordId}`,
9533
+ id: serviceId,
9534
+ data: {global: getGlobalData('read'), context: {rootUrl: getRootUrl(), tenantId: getTenantId(), authToken: getAuthToken()}},
9535
+ api: await getReadonlyFormInitApi(objectSchema, recordId, fields, formInitProps),
9536
+ body: [
9537
+ {
9538
+ "type": "wrapper", //form 的 hiddenOn 会导致 form onEvent 异常, 使用wrapper包裹一次form,并在wrapper上控制显隐
9539
+ hiddenOn: "${recordLoaded != true}",
9540
+ "className": "p-0 m-0",
9541
+ "body": {
9542
+ type: "form",
9543
+ mode: layout,
9544
+ labelAlign,
9545
+ persistData: false,
9546
+ promptPageLeave: false,
9547
+ name: `form_readonly_${recordId}`,
9548
+ debug: false,
9549
+ title: "",
9550
+ data: {
9551
+ "formData": "$$"
9552
+ },
9553
+ wrapWithPanel: false,
9554
+ body: await getFormBody(___default.map(fields, (field)=>{field.readonly = true; return field;}), ___default.map(formFields, (field)=>{field.readonly = true; return field;}), Object.assign({}, ctx, {showSystemFields: true})),
9555
+ className: 'steedos-amis-form bg-white',
9556
+ actions: [], // 不显示表单默认的提交按钮
9557
+ onEvent: {
9558
+ [`@data.changed.${objectSchema.name}`]: { // 由于amis service 组件的 onEvent 存在bug ,此处借助form来刷新 上层 service https://github.com/baidu/amis/issues/6294
9160
9559
  "actions": [
9161
9560
  {
9561
+ "actionType": "reload",
9562
+ "componentId": serviceId,
9563
+ "expression": "this.__deletedRecord != true"
9564
+ },
9565
+ {
9566
+ // "args": {
9567
+ // "url": "/app/${appId}/${objectName}/grid/${side_listview_id}",
9568
+ // "blank": false
9569
+ // },
9162
9570
  "actionType": "custom",
9163
- "script": "event.data.view?.calendar.refetchEvents();"
9571
+ "script": "Steedos.goBack()",
9572
+ "expression": "this.__deletedRecord === true"
9164
9573
  }
9165
9574
  ]
9166
9575
  }
9167
9576
  }
9168
- }
9169
- ],
9170
- "closeOnEsc": false,
9171
- "closeOnOutside": false,
9172
- "showCloseButton": true,
9173
- "size": "lg"
9174
- }
9175
- });
9176
- `;
9177
-
9178
- const onEventClickScript = `
9179
- const data = event.data;
9180
- const eventData = data.event;
9181
- const appId = data.appId;
9182
- const objectName = data.objectName;
9183
- const eventId = data.event && data.event.id;
9184
- doAction({
9185
- "actionType": "dialog",
9186
- "dialog": {
9187
- "type": "dialog",
9188
- "title": "",
9189
- "body": [
9190
- {
9191
- "type": "steedos-record-detail",
9192
- "objectApiName": "\${objectName}",
9193
- "recordId": data.event && data.event.id
9194
- }
9195
- ],
9196
- "closeOnEsc": false,
9197
- "closeOnOutside": false,
9198
- "showCloseButton": true,
9199
- "size": "lg",
9200
- "actions": []
9201
- }
9202
- });
9203
- `;
9204
-
9205
- const recordId = "${event.id}";
9206
- const recordPermissionsApi = getCalendarRecordPermissionsApi(objectSchema, recordId);
9207
- const recordSaveApi = getCalendarRecordSaveApi(objectSchema, calendarOptions);
9208
-
9209
- const businessHours = {
9210
- daysOfWeek: [1, 2, 3, 4, 5],
9211
- startTime: '08:00',
9212
- endTime: '18:00',
9213
- };
9214
- if (!___default.isEmpty(calendarOptions.startDayHour)) {
9215
- businessHours.startTime = `${calendarOptions.startDayHour}:00`;
9216
- }
9217
- if (!___default.isEmpty(calendarOptions.endDayHour)) {
9218
- businessHours.endTime = `${calendarOptions.endDayHour}:00`;
9219
- }
9220
-
9221
- const onEvent = {
9222
- "getEvents": {
9223
- "weight": 0,
9224
- "actions": [
9225
- {
9226
- "componentId": "",
9227
- "args": {
9228
- },
9229
- "actionType": "custom",
9230
- "script": onGetEventsScript
9231
- }
9232
- ]
9233
- },
9234
- "select": {
9235
- "weight": 0,
9236
- "actions": [
9237
- {
9238
- "componentId": "",
9239
- "args": {
9240
- },
9241
- "actionType": "custom",
9242
- "script": onSelectScript
9243
- }
9244
- ]
9245
- },
9246
- "eventClick": {
9247
- "weight": 0,
9248
- "actions": [
9249
- {
9250
- "componentId": "",
9251
- "args": {
9252
- },
9253
- "actionType": "custom",
9254
- "script": onEventClickScript
9255
- }
9256
- ]
9257
- },
9258
- "eventAdd": {
9259
- "weight": 0,
9260
- "actions": [
9261
- {
9262
- "componentId": "",
9263
- "args": {
9264
9577
  },
9265
- "actionType": "custom",
9266
- "script": "console.log('eventAdd'); console.log(event);"
9267
- }
9268
- ]
9269
- },
9270
- "eventChange": {
9271
- "weight": 0,
9272
- "actions": [
9273
- {
9274
- "actionType": 'ajax',
9275
- "args": {
9276
- "api": recordPermissionsApi
9277
- }
9278
- },
9279
- {
9280
- "actionType": "toast",
9281
- "expression": "!event.data.editable",
9282
- "args": {
9283
- "msgType": "error",
9284
- "msg": "您没有编辑该记录的权限!",
9285
- "position": "top-center"
9286
9578
  }
9287
- },
9288
- {
9289
- "actionType": 'ajax',
9290
- "expression": "event.data.editable",
9291
- "args": {
9292
- "api": recordSaveApi,
9293
- "messages": {
9294
- "success": objectSchema.label + "修改成功",
9295
- "failed": objectSchema.label + "修改失败!"
9579
+ ],
9580
+ onEvent: {
9581
+ "fetchInited": {
9582
+ "weight": 0,
9583
+ "actions": [
9584
+ {
9585
+ actionType: 'broadcast',
9586
+ eventName: "recordLoaded",
9587
+ args: {
9588
+ eventName: "recordLoaded"
9589
+ },
9590
+ data: {
9591
+ objectName: "${event.data.__objectName}",
9592
+ record: "${event.data.__record}"
9593
+ },
9594
+ expression: "${event.data.__response.error != true}"
9595
+ },
9596
+ {
9597
+ "actionType": "setValue",
9598
+ "args": {
9599
+ value: {
9600
+ "recordLoaded": true,
9601
+ }
9602
+ },
9603
+ expression: "${event.data.__response.error != true}"
9296
9604
  }
9605
+ ]
9297
9606
  }
9298
9607
  }
9299
- ]
9300
- },
9301
- "eventRemove": {
9302
- "weight": 0,
9303
- "actions": [
9304
- {
9305
- "componentId": "",
9306
- "args": {
9307
- },
9308
- "actionType": "custom",
9309
- "script": "console.log('eventRemove'); console.log(event);"
9310
- }
9311
- ]
9312
- },
9313
- "eventsSet": {
9314
- "weight": 0,
9315
- "actions": [
9316
- {
9317
- "componentId": "",
9318
- "args": {
9319
- },
9320
- "actionType": "custom",
9321
- "script": "console.log('eventsSet'); console.log(event);"
9322
- }
9323
- ]
9324
- }
9325
- };
9326
-
9327
- Object.assign(onEvent, options.onEvent);
9328
-
9329
- const config = options.config || {};
9330
- if(config.eventContent && typeof config.eventContent === "string"){
9331
- const hasReturn = /\breturn\b/.test(config.eventContent);
9332
- if(hasReturn){
9333
- try {
9334
- // 如果是包括return语句的字符串,则按函数解析,见 https://fullcalendar.io/docs/content-injection
9335
- let fn = new Function("arg", config.eventContent);
9336
- config.eventContent = fn;
9337
- } catch (e) {
9338
- console.warn(e);
9339
- }
9340
- }
9341
- }
9342
-
9343
- if(config.noEventsContent && typeof config.noEventsContent === "string"){
9344
- const hasReturn = /\breturn\b/.test(config.noEventsContent);
9345
- if(hasReturn){
9346
- try {
9347
- // 如果是包括return语句的字符串,则按函数解析,见 https://fullcalendar.io/docs/content-injection
9348
- let fn = new Function("arg", config.noEventsContent);
9349
- config.noEventsContent = fn;
9350
- } catch (e) {
9351
- console.warn(e);
9352
- }
9353
9608
  }
9354
- }
9355
-
9356
- const amisSchema = {
9357
- "type": "steedos-fullcalendar",
9358
- "label": "",
9359
- "name": "fullcalendar",
9360
- "placeholder":"${additionalFilters}",//用于触发reload
9361
- "editable": permissions.allowEdit,
9362
- "selectable": permissions.allowCreate,
9363
- "selectMirror": permissions.allowCreate,
9364
- "initialView": initialView,
9365
- "businessHours": businessHours,
9366
- ...config,
9367
- "onEvent": onEvent
9368
- };
9369
- return amisSchema;
9370
9609
  }
9371
9610
 
9372
9611
  /*
@@ -9788,8 +10027,8 @@ async function getRelatedListSchema(
9788
10027
  /*
9789
10028
  * @Author: baozhoutao@steedos.com
9790
10029
  * @Date: 2022-07-05 15:55:39
9791
- * @LastEditors: baozhoutao@steedos.com
9792
- * @LastEditTime: 2023-04-28 11:11:29
10030
+ * @LastEditors: 殷亮辉 yinlianghui@hotoa.com
10031
+ * @LastEditTime: 2023-06-04 17:36:49
9793
10032
  * @Description:
9794
10033
  */
9795
10034
 
@@ -10120,7 +10359,8 @@ async function getListSchema(
10120
10359
  "requestAdaptor": listView.requestAdaptor,
10121
10360
  "adaptor": listView.adaptor,
10122
10361
  "headerToolbarItems": ctx.headerToolbarItems,
10123
- "filterVisible": ctx.filterVisible
10362
+ "filterVisible": ctx.filterVisible,
10363
+ "rowClassNameExpr": ctx.rowClassNameExpr
10124
10364
  };
10125
10365
  return {
10126
10366
  uiSchema,
@@ -13710,11 +13950,11 @@ var SteedosSkeleton = function (props) {
13710
13950
  };
13711
13951
 
13712
13952
  var AmisObjectForm = function (props) { return __awaiter(void 0, void 0, void 0, function () {
13713
- var $schema, recordId, defaultData, mode, layout, labelAlign, appId, fieldsExtend, _a, excludedFields, _b, fields, _c, className, initApiRequestAdaptor, initApiAdaptor, apiRequestAdaptor, apiAdaptor, objectApiName, schemaKeys, formSchema, defaults, options, globalData, amisSchema, uiSchema, schema, schema, formData;
13953
+ var $schema, recordId, defaultData, mode, layout, labelAlign, appId, fieldsExtend, _a, excludedFields, _b, fields, _c, className, initApiRequestAdaptor, initApiAdaptor, apiRequestAdaptor, apiAdaptor, enableTabs, tabsMode, objectApiName, schemaKeys, formSchema, defaults, options, globalData, amisSchema, uiSchema, schema, schema, formData;
13714
13954
  return __generator(this, function (_d) {
13715
13955
  switch (_d.label) {
13716
13956
  case 0:
13717
- $schema = props.$schema, recordId = props.recordId, defaultData = props.defaultData, mode = props.mode, layout = props.layout, labelAlign = props.labelAlign, appId = props.appId, fieldsExtend = props.fieldsExtend, _a = props.excludedFields, excludedFields = _a === void 0 ? null : _a, _b = props.fields, fields = _b === void 0 ? null : _b, _c = props.className, className = _c === void 0 ? "" : _c, initApiRequestAdaptor = props.initApiRequestAdaptor, initApiAdaptor = props.initApiAdaptor, apiRequestAdaptor = props.apiRequestAdaptor, apiAdaptor = props.apiAdaptor;
13957
+ $schema = props.$schema, recordId = props.recordId, defaultData = props.defaultData, mode = props.mode, layout = props.layout, labelAlign = props.labelAlign, appId = props.appId, fieldsExtend = props.fieldsExtend, _a = props.excludedFields, excludedFields = _a === void 0 ? null : _a, _b = props.fields, fields = _b === void 0 ? null : _b, _c = props.className, className = _c === void 0 ? "" : _c, initApiRequestAdaptor = props.initApiRequestAdaptor, initApiAdaptor = props.initApiAdaptor, apiRequestAdaptor = props.apiRequestAdaptor, apiAdaptor = props.apiAdaptor, enableTabs = props.enableTabs, tabsMode = props.tabsMode;
13718
13958
  objectApiName = props.objectApiName || "space_users";
13719
13959
  schemaKeys = ___default.difference(___default.keys($schema), ["type", "mode", "layout", "defaultData"]);
13720
13960
  formSchema = ___default.pick(props, schemaKeys);
@@ -13744,7 +13984,9 @@ var AmisObjectForm = function (props) { return __awaiter(void 0, void 0, void 0,
13744
13984
  initApiRequestAdaptor: initApiRequestAdaptor,
13745
13985
  initApiAdaptor: initApiAdaptor,
13746
13986
  apiRequestAdaptor: apiRequestAdaptor,
13747
- apiAdaptor: apiAdaptor
13987
+ apiAdaptor: apiAdaptor,
13988
+ enableTabs: enableTabs,
13989
+ tabsMode: tabsMode
13748
13990
  }))];
13749
13991
  case 1:
13750
13992
  schema = _d.sent();
@@ -13782,14 +14024,14 @@ var AmisObjectForm = function (props) { return __awaiter(void 0, void 0, void 0,
13782
14024
  }); };
13783
14025
 
13784
14026
  var AmisObjectListView = function (props) { return __awaiter(void 0, void 0, void 0, function () {
13785
- var $schema, top, perPage, _a, showHeader, data, defaultData, _b, className, crudClassName, _c, showDisplayAs, sideSchema, _e, filterVisible, headerToolbarItems, headerSchema, ctx, listName, defaults, objectApiName, displayAs, formFactor, isMobile, uiSchema, listView, schemaKeys, listSchema, setDataToComponentId, amisSchemaData, listViewId, listViewSchemaProps, serviceData;
14027
+ var $schema, top, perPage, _a, showHeader, data, defaultData, _b, className, crudClassName, _c, showDisplayAs, sideSchema, _e, filterVisible, headerToolbarItems, rowClassNameExpr, headerSchema, ctx, listName, defaults, objectApiName, displayAs, formFactor, isMobile, uiSchema, listView, schemaKeys, listSchema, setDataToComponentId, amisSchemaData, listViewId, listViewSchemaProps, serviceData;
13786
14028
  var _f;
13787
14029
  return __generator(this, function (_g) {
13788
14030
  switch (_g.label) {
13789
14031
  case 0:
13790
14032
  // console.time('AmisObjectListView')
13791
14033
  console.log("AmisObjectListView props", props);
13792
- $schema = props.$schema, top = props.top, perPage = props.perPage, _a = props.showHeader, showHeader = _a === void 0 ? true : _a, data = props.data, defaultData = props.defaultData, _b = props.className, className = _b === void 0 ? "" : _b, crudClassName = props.crudClassName, _c = props.showDisplayAs, showDisplayAs = _c === void 0 ? false : _c, sideSchema = props.sideSchema, props.columnsTogglable, _e = props.filterVisible, filterVisible = _e === void 0 ? true : _e, headerToolbarItems = props.headerToolbarItems;
14034
+ $schema = props.$schema, top = props.top, perPage = props.perPage, _a = props.showHeader, showHeader = _a === void 0 ? true : _a, data = props.data, defaultData = props.defaultData, _b = props.className, className = _b === void 0 ? "" : _b, crudClassName = props.crudClassName, _c = props.showDisplayAs, showDisplayAs = _c === void 0 ? false : _c, sideSchema = props.sideSchema, props.columnsTogglable, _e = props.filterVisible, filterVisible = _e === void 0 ? true : _e, headerToolbarItems = props.headerToolbarItems, rowClassNameExpr = props.rowClassNameExpr;
13793
14035
  headerSchema = props.headerSchema;
13794
14036
  ctx = props.ctx;
13795
14037
  listName = (defaultData === null || defaultData === void 0 ? void 0 : defaultData.listName) || (data === null || data === void 0 ? void 0 : data.listName) || (props === null || props === void 0 ? void 0 : props.listName);
@@ -13870,7 +14112,7 @@ var AmisObjectListView = function (props) { return __awaiter(void 0, void 0, voi
13870
14112
  }
13871
14113
  amisSchemaData = Object.assign({}, data, defaultData);
13872
14114
  listViewId = (ctx === null || ctx === void 0 ? void 0 : ctx.listViewId) || amisSchemaData.listViewId;
13873
- listViewSchemaProps = __assign$2(__assign$2({ top: top, perPage: perPage, showHeader: showHeader, defaults: defaults }, ctx), { listViewId: listViewId, setDataToComponentId: setDataToComponentId, filterVisible: filterVisible, showDisplayAs: showDisplayAs, displayAs: displayAs, headerToolbarItems: headerToolbarItems });
14115
+ listViewSchemaProps = __assign$2(__assign$2({ top: top, perPage: perPage, showHeader: showHeader, defaults: defaults }, ctx), { listViewId: listViewId, setDataToComponentId: setDataToComponentId, filterVisible: filterVisible, showDisplayAs: showDisplayAs, displayAs: displayAs, headerToolbarItems: headerToolbarItems, rowClassNameExpr: rowClassNameExpr });
13874
14116
  if (!headerSchema) {
13875
14117
  headerSchema = getObjectListHeader$1(uiSchema, listName, ctx);
13876
14118
  }