@steedos/service-plugin-amis 2.6.1-beta.7 → 2.6.2-beta.2

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.
@@ -69,14 +69,18 @@
69
69
  options: amisLib.OptionsControl,
70
70
  };
71
71
 
72
- const amisComps = lodash.filter(Builder.registry['meta-components'], function(item){ return item.componentName && item.amis?.render});
72
+ const amisComps = lodash.filter(Builder.registry['meta-components'], function(item){ return item.componentName && item.amis && item.amis.render});
73
73
 
74
74
  lodash.each(amisComps,(comp)=>{
75
75
  const Component = Builder.components.find(item => item.name === comp.componentName);
76
- if (Component && !AmisRenderers.includes(comp.amis?.render.type)){
76
+ var type = null;
77
+ if(comp.amis){
78
+ type = comp.amis.render.type
79
+ }
80
+ if (Component && !AmisRenderers.includes(type)){
77
81
  try {
78
82
  let AmisWrapper = Component.class
79
- AmisRenderers.push(comp.amis?.render.type);
83
+ AmisRenderers.push(type);
80
84
  if(comp.componentType === 'amisSchema'){
81
85
  let amisReact = amisRequire('react');
82
86
  AmisWrapper = function(props){
@@ -98,17 +102,18 @@
98
102
  }, [JSON.stringify($schema)]) //, JSON.stringify(props.data)
99
103
 
100
104
  if (!schema)
101
- return render('body', {
102
- "type": "wrapper",
103
- "className": "h-full flex items-center justify-center",
104
- "body": {
105
- "type": "spinner",
106
- "show": true
107
- }
108
- })
105
+ return;
106
+ // return render('body', {
107
+ // "type": "wrapper",
108
+ // "className": "h-full flex items-center justify-center",
109
+ // "body": {
110
+ // "type": "spinner",
111
+ // "show": true
112
+ // }
113
+ // })
109
114
 
110
115
  if (props.env.enableAMISDebug && schema) {
111
- console.groupCollapsed(`[steedos render ${comp.amis?.render.type}]`);
116
+ console.groupCollapsed(`[steedos render ${type}]`);
112
117
  console.trace('Component: ', props, 'Generated Amis Schema: ', schema);
113
118
  console.groupEnd();
114
119
  }
@@ -221,6 +226,17 @@
221
226
  // }
222
227
  // return div;
223
228
  // },
229
+ // 如果这里不配置env.notify,那么会走amis 默认的env.notify,它会造成随机把toast组件dom插入到不同的scope容器内(应该是插入到最后一个加载的scope),这在苹果手机上可能会造成弹出的通知z-index不生效的情况,出现通知被档住的问题
230
+ notify: (type, msg)=>{
231
+ var tpl = msg.props && msg.props.schema.tpl;
232
+ if(tpl){
233
+ SteedosUI.message[type](tpl)
234
+ }else if(typeof msg == 'string'){
235
+ SteedosUI.message[type](msg)
236
+ }else{
237
+ console.warn('notify', type, msg)
238
+ }
239
+ },
224
240
  jumpTo: (to, action) => {
225
241
  if (to === 'goBack') {
226
242
  return window.history.back();
@@ -235,8 +251,13 @@
235
251
 
236
252
  // 主要是支持 nav 中的跳转
237
253
  if (action && to && action.target) {
238
- window.open(to, action.target);
239
- return;
254
+ if(Meteor.isCordova && to.indexOf('http') != 0){
255
+ window.open(Steedos.absoluteUrl(to), action.target);
256
+ return;
257
+ }else{
258
+ window.open(to, action.target);
259
+ return;
260
+ }
240
261
  }
241
262
 
242
263
  if (/^https?:\/\//.test(to)) {
@@ -247,6 +268,34 @@
247
268
  },
248
269
  theme: 'antd',
249
270
  isCurrentUrl: isCurrentUrl,
271
+ requestAdaptor: (config)=>{
272
+ // url是相对路径
273
+ if(config.url && (!/^http[s]?:\/\//i.test(config.url))){
274
+ if(Meteor.isCordova){
275
+ config.url = Meteor.absoluteUrl(config.url)
276
+ }
277
+
278
+ if(!config.headers){
279
+ config.headers = {}
280
+ }
281
+
282
+ if(!config.headers.Authorization && Builder.settings.context && Builder.settings.context.tenantId && Builder.settings.context.authToken){
283
+ config.headers.Authorization = `Bearer ${Builder.settings.context.tenantId},${Builder.settings.context.authToken}`;
284
+ }
285
+ }else if(config.url && Meteor.isCordova && Builder.settings.context && Builder.settings.context.rootUrl && config.url.startsWith(Builder.settings.context.rootUrl)){
286
+ // 是绝对路径,且是cordova环境, 且以root url开头, 则自动处理认证
287
+ if(Meteor.isCordova){
288
+ if(!config.headers){
289
+ config.headers = {}
290
+ }
291
+
292
+ if(!config.headers.Authorization && Builder.settings.context && Builder.settings.context.tenantId && Builder.settings.context.authToken){
293
+ config.headers.Authorization = `Bearer ${Builder.settings.context.tenantId},${Builder.settings.context.authToken}`;
294
+ }
295
+ }
296
+ }
297
+ return config;
298
+ }
250
299
  };
251
300
  // 已弃用
252
301
  const AmisRender = function (props) {
@@ -306,6 +355,8 @@
306
355
  };
307
356
 
308
357
  window.renderAmis = function (root, schema, data, env) {
358
+ // console.log("===window.renderAmis===root, env===", root, env);
359
+ // console.log("===window.renderAmis===data===", data);
309
360
  const refName = schema.name || schema.id;
310
361
  if(SteedosUI.refs[refName]){
311
362
  if(SteedosUI.refs[refName].unmount){
@@ -2,7 +2,7 @@
2
2
  * @Author: baozhoutao@steedos.com
3
3
  * @Date: 2022-05-20 17:42:20
4
4
  * @LastEditors: baozhoutao@steedos.com
5
- * @LastEditTime: 2022-10-28 11:01:51
5
+ * @LastEditTime: 2023-08-22 22:36:38
6
6
  * @Description: 提供辅助函数
7
7
  */
8
8
  (function(){
@@ -97,7 +97,7 @@
97
97
  [
98
98
  React17.createElement(SteedosUI.components.Button, {
99
99
  onClick: function(){
100
- SteedosUI.getRef(pageName)?.close();
100
+ SteedosUI.getRef(pageName) && SteedosUI.getRef(pageName).close();
101
101
  }
102
102
  } , t('cancel')),
103
103
  React17.createElement(SteedosUI.components.Button, {
@@ -132,7 +132,7 @@
132
132
  if (error) {
133
133
  return console.log("error", error);
134
134
  } else if (result) {
135
- SteedosUI.getRef(pageName)?.close();
135
+ SteedosUI.getRef(pageName) && SteedosUI.getRef(pageName).close();
136
136
  return Session.set("filter_items", filter_items);
137
137
  }
138
138
  });
@@ -141,7 +141,7 @@
141
141
  const formValues = window.amisScopes[pageName].getComponentByName("filtersForm").getValues();
142
142
  const filters = window.amisConvert.conditionsToFilters(formValues.filters);
143
143
  Session.set("filter_items", filters);
144
- SteedosUI.getRef(pageName)?.close();
144
+ SteedosUI.getRef(pageName) && SteedosUI.getRef(pageName).close();
145
145
  },
146
146
  type: 'primary'
147
147
  } , canSave ? t('save'): t('apply'))
@@ -245,7 +245,7 @@
245
245
  },
246
246
  {
247
247
  "actionType": "custom",
248
- "script": "\n const { recordId, listViewId } = context.props.data;\n const data = event.data;\n const appId = data.appId;\n const objectName = data.objectName;\n // 在记录详细界面时isRecordDetail为true\n // TODO: isRecordDetail这个判断需要优化\n const isRecordDetail = data._isRelated;\n if(recordId){\n // 编辑记录时,刷新主表单\n doAction({\n componentId: `detail_${recordId}`,\n actionType: \"reload\",\n expression: `!${listViewId}`\n });\n }\n else if(!isRecordDetail){\n // 在列表视图界面新建记录时跳转到详细页面\n const jumpTo = event.context.env && event.context.env.jumpTo;\n if(jumpTo){\n const newRecordId = data.result.data?.recordId;\n jumpTo(\"/app/\" + appId + \"/\" + objectName + \"/view/\" + newRecordId);\n }\n }\n "
248
+ "script": "\n const { recordId, listViewId } = context.props.data;\n const data = event.data;\n const appId = data.appId;\n const objectName = data.objectName;\n // 在记录详细界面时isRecordDetail为true\n // TODO: isRecordDetail这个判断需要优化\n const isRecordDetail = data._isRelated;\n if(recordId){\n // 编辑记录时,刷新主表单\n doAction({\n componentId: `detail_${recordId}`,\n actionType: \"reload\",\n expression: `!${listViewId}`\n });\n }\n else if(!isRecordDetail){\n // 在列表视图界面新建记录时跳转到详细页面\n const jumpTo = event.context.env && event.context.env.jumpTo;\n if(jumpTo){\n var _data$result$data;const newRecordId = (_data$result$data = data.result.data) === null || _data$result$data === void 0 ? void 0 : _data$result$data.recordId;\n jumpTo(\"/app/\" + appId + \"/\" + objectName + \"/view/\" + newRecordId);\n }\n }\n "
249
249
  }
250
250
  ]
251
251
  }
@@ -1,42 +1,306 @@
1
1
  {
2
- "type": "page",
3
- "title": "Welcome to Steedos",
4
- "body": [
5
- {
6
- "type": "steedos-object-form",
7
- "className": "sm:border sm:shadow sm:rounded sm:border-gray-300 bg-white p-4",
8
- "label": "对象表单",
9
- "objectApiName": "apps",
10
- "recordId": "${recordId}",
11
- "mode": "edit",
12
- "fieldsExtend": "{\n \"tab_items\": {\n \"amis\": {\n \"name\": \"tab_items\",\n \"type\": \"crud\",\n \"source\": \"\\${tab_items}\",\n \"strictMode\": true,\n \"affixHeader\": false,\n \"editable\": true,\n \"addable\": false,\n \"removable\": true,\n \"draggable\": false,\n \"headerToolbarClassName\": \"px-1 pb-3\",\n \"columns\": [\n {\n \"name\": \"index\",\n \"label\": \"\\${'apps.apps_form.tab_number'| t}\",\n \"type\": \"tpl\",\n \"tpl\": \"\\${index+1}\",\n \"className\": \"w-10\",\n \"id\": \"u:c59784421c37\"\n },\n {\n \"name\": \"tab_name_label\",\n \"label\": \"\\${'apps.apps_form.tab' | t}\",\n \"type\": \"tpl\",\n \"id\": \"u:b95c69a1cd84\",\n \"tpl\": \"\\${tabs_options|filter:value:equals:tab_name|pick:label}\"\n },\n {\n \"name\": \"group\",\n \"label\": \"\\${'apps.apps_form.tab_grouping' | t}\",\n \"id\": \"u:e532b1949676\",\n \"quickEdit\": {\n \"type\": \"select\",\n \"name\": \"group\",\n \"className\": \"m-0\",\n \"onEvent\": {\n \"change\": {\n \"actions\": [\n {\n \"actionType\": \"custom\",\n \"script\": \"const tabGroupKey = \\\"group\\\";const getTabsSortFun = function (groupNames) { return function (m, n) { var tempM = !!m[tabGroupKey] ? 1 : 0; var tempN = !!n[tabGroupKey] ? 1 : 0; if (!m[tabGroupKey] || !n[tabGroupKey]) { return tempM - tempN; } return groupNames.indexOf(m[tabGroupKey]) - groupNames.indexOf(n[tabGroupKey]); };};const quickEidtSaveForTab = function (input, prop_name) { const currentPropValue = input.value; const rowValue = input.__super; const formValue = input.__super.__super.__super; const tab_name = rowValue.tab_name; rowValue[prop_name] = currentPropValue; delete rowValue.index; let newTabs = formValue.tab_items.map(function (item) { if (item.tab_name == tab_name) { return Object.assign({}, item, rowValue); } else { return item; } }); const tabGroups = input.__super.__super.tab_groups; const groupNames = _.compact(_.map(tabGroups, \\\"group_name\\\")); if (groupNames && groupNames.length) { newTabs.sort(getTabsSortFun(groupNames)); } return { tab_items: newTabs }};const eventData = event.data;const newTabTtemsProp = quickEidtSaveForTab(eventData, \\\"group\\\");setTimeout(function () { doAction({ actionType: 'setValue', componentId: \\\"object_form\\\", args: { value: newTabTtemsProp } });},300);\"\n }\n ]\n }\n },\n \"source\": \"\\${tab_groups|pick:group_name}\",\n \"checkAll\": false,\n \"selectFirst\": false,\n \"searchable\": true,\n \"clearable\": true,\n \"id\": \"u:8b3d6979e884\",\n \"multiple\": false,\n \"mode\": \"inline\"\n },\n \"placeholder\": \"-\"\n },\n {\n \"name\": \"tab_name_desktop\",\n \"label\": \"\\${'apps.apps_form.tab_desktop' | t}\",\n \"type\": \"tpl\",\n \"id\": \"u:b95c69a1cd84\",\n \"tpl\": \"\\${tabs_options|filter:value:equals:tab_name|first|pick:desktop|isTrue:'✔':'✘'}\",\n \"placeholder\": \"-\",\n \"remark\": \"\\${'apps.apps_form.tab_desktop_remark' | t}\"\n },\n {\n \"name\": \"tab_name_mobile\",\n \"label\": \"\\${'apps.apps_form.tab_mobile' | t}\",\n \"type\": \"tpl\",\n \"id\": \"u:b95c69a1cd84\",\n \"tpl\": \"\\${tabs_options|filter:value:equals:tab_name|first|pick:mobile|isTrue:'✔':'✘'}\",\n \"placeholder\": \"-\",\n \"remark\": \"\\${'apps.apps_form.tab_mobile_remark' | t}\"\n }\n ],\n \"headerToolbar\": [\n {\n \"type\": \"service\",\n \"id\": \"tabs-options-service\",\n \"body\": [\n {\n \"type\": \"button\",\n \"id\": \"u:a35a2276145d\",\n \"label\": \"${'apps.apps_form.tab_generate' | t}\",\n \"onEvent\": {\n \"click\": {\n \"actions\": [\n {\n \"script\": \"const appId = null; const page = Steedos.Page.getPage('app', appId, null, null, 'generate_object_tabs'); if (page && page.schema) { const pageSchema = JSON.parse(page.schema); let formSchema = pageSchema.body[0]; formSchema.canAccessSuperData = false; formSchema.wrapWithPanel = false; formSchema.className = 'steedos-amis-form'; const title = t('apps.apps_form.tab_generate_title'); doAction({ 'actionType': 'dialog', 'dialog': { 'type': 'dialog', 'title': title, 'body': formSchema, 'size': 'lg' } }); }\",\n \"actionType\": \"custom\"\n }\n ],\n \"weight\": 0\n }\n },\n \"tpl\": \"内容\"\n },\n {\n \"type\": \"button\",\n \"label\": \"${'apps.apps_form.tab_set' | t}\",\n \"id\": \"u:853b890ab524\",\n \"actionType\": \"dialog\",\n \"dialog\": {\n \"type\": \"dialog\",\n \"title\": \"${'apps.apps_form.tab_set' | t}\",\n \"body\": [\n {\n \"type\": \"transfer\",\n \"name\": \"picked_tabs\",\n \"value\": \"\\${tab_items|pick:tab_name}\",\n \"sortable\": true,\n \"source\": \"\\${tabs_options}\",\n \"searchable\": true,\n \"id\": \"u:f2d36873abd1\"\n }\n ],\n \"onEvent\": {\n \"confirm\": {\n \"actions\": [\n {\n \"actionType\": \"custom\",\n \"script\": \"const tabGroupKey = 'group';const getTabsSortFun = function (groupNames) { return function (m, n) { var tempM = !!m[tabGroupKey] ? 1 : 0; var tempN = !!n[tabGroupKey] ? 1 : 0; if (!m[tabGroupKey] || !n[tabGroupKey]) { return tempM - tempN; } return groupNames.indexOf(m[tabGroupKey]) - groupNames.indexOf(n[tabGroupKey]); };};const clearTabs = function (input) { return { tab_items: [] }};const convertDataForTabs = function (input) { let pickedTabs = input.picked_tabs || []; const superTabs = _.keyBy(input.__super.__super.tab_items, 'tab_name'); if (typeof pickedTabs === 'string') { pickedTabs = pickedTabs.split(','); } const tabOptions = _.keyBy(input.__super.tabs_options, 'value'); const convertedTabs = pickedTabs.map(function (tab_name) { const superTab = superTabs[tab_name]; if (superTab) { return superTab; } else { const tabOption = tabOptions[tab_name]; return { tab_name: tab_name, group: tabOption.group } } }); const tabGroups = input.__super.__super.tab_groups; const groupNames = _.compact(_.map(tabGroups, 'group_name')); if (groupNames && groupNames.length) { convertedTabs.sort(getTabsSortFun(groupNames)); } return { tab_items: convertedTabs }};const eventData = event.data;doAction({ actionType: 'setValue', componentId: 'object_form', args: { value: convertDataForTabs(eventData) }});doAction({ actionType: 'setValue', componentId: 'tabs-options-service', args: { value: convertDataForTabs(eventData) }});\"\n }\n ]\n }\n },\n \"size\": \"lg\",\n \"id\": \"u:9c93896a73cf\",\n \"closeOnEsc\": false,\n \"closeOnOutside\": false,\n \"showCloseButton\": true,\n \"showErrorMsg\": true,\n \"showLoading\": true,\n \"dataMapSwitch\": false\n }\n },\n {\n \"type\": \"button\",\n \"label\": \"${'apps.apps_form.tab_grouping_set' | t}\",\n \"actionType\": \"dialog\",\n \"dialog\": {\n \"title\": \"${'apps.apps_form.tab_grouping_set' | t}\",\n \"body\": [\n {\n \"type\": \"input-table\",\n \"name\": \"setting_groups\",\n \"value\": \"\\${tab_groups}\",\n \"addable\": true,\n \"draggable\": true,\n \"editable\": true,\n \"needConfirm\": false,\n \"columns\": [\n {\n \"name\": \"group_name\",\n \"label\": \"${'apps.apps_form.tab_grouping_name' | t}\",\n \"id\": \"u:383c7744b499\"\n },\n {\n \"name\": \"default_open\",\n \"label\": \"${'apps.apps_form.tab_grouping_open' | t}\",\n \"id\": \"u:7a243c84ed66\",\n \"type\": \"checkbox\",\n \"value\": true\n }\n ],\n \"removable\": true,\n \"id\": \"setting_groups\"\n }\n ],\n \"onEvent\": {\n \"confirm\": {\n \"actions\": [\n {\n \"actionType\": \"custom\",\n \"script\": \"const tabGroupKey = 'group';const getTabsSortFun = function (groupNames) { return function (m, n) { var tempM = !!m[tabGroupKey] ? 1 : 0; var tempN = !!n[tabGroupKey] ? 1 : 0; if (!m[tabGroupKey] || !n[tabGroupKey]) { return tempM - tempN; } return groupNames.indexOf(m[tabGroupKey]) - groupNames.indexOf(n[tabGroupKey]); };};const clearTabs = function (input) { return { tab_items: [] }};const convertDataForGroups = function(input) { const settingGroups = input.setting_groups || []; const convertedGroups = _.uniqBy(settingGroups.map(function (item) { return { group_name: item.group_name, default_open: item.default_open } }), 'group_name'); const groupNames = _.compact(_.map(convertedGroups, 'group_name')); const tab_items = input.tab_items; tab_items?.sort(getTabsSortFun(groupNames)); return { tab_groups: convertedGroups, tab_items: tab_items }};const eventData = event.data;doAction({ actionType: 'setValue', componentId: 'object_form', args: { value: convertDataForGroups(eventData) }});\"\n }\n ]\n }\n },\n \"type\": \"dialog\",\n \"size\": \"lg\",\n \"id\": \"setting_groups\",\n \"closeOnEsc\": false,\n \"closeOnOutside\": false,\n \"showCloseButton\": true,\n \"showErrorMsg\": true,\n \"showLoading\": true,\n \"dataMapSwitch\": false\n },\n \"id\": \"u:111b043b193c\"\n }\n ],\n \"messages\": \"\",\n \"api\": {\n \"method\": \"post\",\n \"url\": \"\\${context.rootUrl}/graphql\",\n \"adaptor\": \" let data = payload.data; data.tabs_options = []; if (data.options && data.options.length) { data.tabs_options = data.options.map(function (option) { option.label = option.label + '(' + option.value + ')'; return option; }); } if (!api.body.recordId) { const defaultValues = { is_creator: true, mobile: true, visible: true, sort: 9100 } ;data = Object.assign({}, data, defaultValues); } delete data.options ;payload.data = data; return payload; \",\n \"data\": {\n \"query\": \"{options:tabs{_id label:label value:name,type,object,desktop,mobile}}\",\n \"recordId\": \"\\${recordId}\"\n },\n \"headers\": {\n \"Authorization\": \"Bearer \\${context.tenantId},\\${context.authToken}\"\n }\n }\n }\n ]\n }\n },\n \"objects\": {\n \"amis\": {\n \"name\": \"objects\",\n \"type\": \"select\",\n \"className\": \"m-0\",\n \"labelClassName\": \"text-left\",\n \"id\": \"u:4e5047e44905\",\n \"joinValues\": false,\n \"extractValue\": true,\n \"labelField\": \"label\",\n \"valueField\": \"value\",\n \"multiple\": true,\n \"checkAll\": false,\n \"searchable\": true,\n \"menuTpl\": \"\",\n \"source\": {\n \"method\": \"get\",\n \"url\": \"${context.rootUrl}/service/api/amis-metadata-objects/objects/options\",\n \"headers\": {\n \"Authorization\": \"Bearer ${context.tenantId},${context.authToken}\"\n }\n },\n \"autoComplete\": \"\"\n }\n },\n \"mobile_objects\": {\n \"amis\": {\n \"name\": \"mobile_objects\",\n \"type\": \"select\",\n \"className\": \"m-0\",\n \"labelClassName\": \"text-left\",\n \"id\": \"u:cfaeb2f857a8\",\n \"joinValues\": false,\n \"extractValue\": true,\n \"labelField\": \"label\",\n \"valueField\": \"value\",\n \"multiple\": true,\n \"checkAll\": false,\n \"searchable\": true,\n \"menuTpl\": \"\",\n \"source\": {\n \"method\": \"get\",\n \"url\": \"${context.rootUrl}/service/api/amis-metadata-objects/objects/options\",\n \"messages\": {},\n \"headers\": {\n \"Authorization\": \"Bearer ${context.tenantId},${context.authToken}\"\n }\n },\n \"autoComplete\": \"\"\n }\n }\n}",
13
- "enableTabs": true,
14
- "debug": false,
15
- "initApiRequestAdaptor": "",
16
- "initApiAdaptor": "var data = payload.data;\nif (data.tab_items && !_.isArray(data.tab_items)) {\n // 数据库中存储的是对象格式而不是数组,转换为数组用于界面显示\n let arrTabItems = [];\n _.each(data.tab_items, function (n, k) {\n n.tab_name = k;\n delete n.index;\n arrTabItems.push(n);\n });\n data.tab_items = arrTabItems;\n}\nif (data._id && !data.tab_items) {\n const tabOptions = data.tabs_options || [];\n const tabItems = [];\n // 把应用中原来tabs属性值添加到新的tab_items属性的默认值中\n if (data.tabs && data.tabs.length) {\n data.tabs.forEach(function (item) {\n tabItems.push({ tab_name: item });\n });\n }\n const pushObjectsToTabItems = function (objects) {\n objects.forEach(function (item) {\n // 已经有绑定到指定对象的选项卡就不添加\n let existObjectItem = !!tabItems.find(function (tabItem) {\n return !!tabOptions.find(function (option) {\n return tabItem.tab_name === tabItem.value && option.object === item;\n });\n });\n if (existObjectItem) {\n return;\n }\n // 找到指向指定对象的选项卡\n let tempOption = tabOptions.find(function (option) {\n return option.type === \"object\" && option.object === item;\n });\n if (!tempOption) {\n return;\n }\n // 选项卡名称如果重复了就不添加\n let existTabItem = !!tabItems.find(function (tabItem) {\n return tabItem.tab_name === tempOption.value;\n });\n if (existTabItem) {\n return;\n }\n if (tempOption) {\n tabItems.push({ tab_name: tempOption.value });\n }\n });\n }\n // 把应用中原来objects属性值添加到新的tab_items属性的默认值中\n if (data.objects && data.objects.length) {\n pushObjectsToTabItems(data.objects);\n }\n // 把应用中原来mobile_objects属性值添加到新的tab_items属性的默认值中\n if (data.mobile_objects && data.mobile_objects.length) {\n pushObjectsToTabItems(data.mobile_objects);\n }\n data.tab_items = tabItems;\n}\n\npayload.data = data;\ndelete payload.extensions;\nreturn payload;\n ",
17
- "apiRequestAdaptor": "delete formData.tabs_options;\nconst recordId = formData.recordId;\n\n// 新加字段tab_items,值同步回传到老字段tabs中兼容老UI界面\nformData.tabs = [];\nif (formData.tab_items && formData.tab_items.length) { \n formData.tabs = formData.tab_items.map(function (item) { return item.tab_name; });\n}\n\n/*\ntab_items存储为:\ntab_items: {\n test1:{\n group:\"xxx\"\n },\n test3:{\n group:\"yyy\"\n }\n}\n而不是:\ntab_items: [\n {\n \"index\":1,\n \"group\":\"xxx\"\n },\n {\n \"index\":2,\n \"group\":\"yyy\"\n }\n]\n*/\nif (formData.tab_items) { \n formData.tab_items = _.keyBy(formData.tab_items, \"tab_name\")\n let tempIndex = 0;\n _.each(formData.tab_items, function (n, k) {\n tempIndex++;\n n.index = tempIndex;\n delete n.tab_name;\n });\n}\n\nquery = `mutation{record: ${objectName}__insert(doc: {__saveData}){_id}}`;\nif(recordId){\n query = `mutation{record: ${objectName}__update(id: \"${recordId}\", doc: {__saveData}){_id}}`;\n};\n__saveData = JSON.stringify(JSON.stringify(formData));\n\napi.data = {query: query.replace('{__saveData}', __saveData)};\nreturn api;\n",
18
- "apiAdaptor": "",
19
- "form": {
20
- "id": "object_form"
2
+ "type": "page",
3
+ "title": "Welcome to Steedos",
4
+ "body": [
5
+ {
6
+ "type": "steedos-object-form",
7
+ "className": "sm:border sm:rounded sm:border-gray-300 bg-white p-4",
8
+ "label": "对象表单",
9
+ "objectApiName": "apps",
10
+ "recordId": "${recordId}",
11
+ "mode": "edit",
12
+ "fieldsExtend": {
13
+ "tab_items": {
14
+ "amis": {
15
+ "name": "tab_items",
16
+ "type": "crud",
17
+ "source": "${tab_items}",
18
+ "strictMode": true,
19
+ "affixHeader": false,
20
+ "editable": true,
21
+ "addable": false,
22
+ "removable": true,
23
+ "draggable": false,
24
+ "headerToolbarClassName": "px-1 pb-3",
25
+ "columns": [
26
+ {
27
+ "name": "index",
28
+ "label": "${'apps.apps_form.tab_number'| t}",
29
+ "type": "tpl",
30
+ "tpl": "${index+1}",
31
+ "className": "w-10",
32
+ "id": "u:c59784421c37"
33
+ },
34
+ {
35
+ "name": "tab_name_label",
36
+ "label": "${'apps.apps_form.tab' | t}",
37
+ "type": "tpl",
38
+ "id": "u:b95c69a1cd84",
39
+ "tpl": "${tabs_options|filter:value:equals:tab_name|pick:label}"
40
+ },
41
+ {
42
+ "name": "group",
43
+ "label": "${'apps.apps_form.tab_grouping' | t}",
44
+ "id": "u:e532b1949676",
45
+ "quickEdit": {
46
+ "type": "select",
47
+ "name": "group",
48
+ "className": "m-0",
49
+ "onEvent": {
50
+ "change": {
51
+ "actions": [
52
+ {
53
+ "actionType": "custom",
54
+ "script": "const tabGroupKey = \"group\";const getTabsSortFun = function (groupNames) { return function (m, n) { var tempM = !!m[tabGroupKey] ? 1 : 0; var tempN = !!n[tabGroupKey] ? 1 : 0; if (!m[tabGroupKey] || !n[tabGroupKey]) { return tempM - tempN; } return groupNames.indexOf(m[tabGroupKey]) - groupNames.indexOf(n[tabGroupKey]); };};const quickEidtSaveForTab = function (input, prop_name) { const currentPropValue = input.value; const rowValue = input.__super; const formValue = input.__super.__super.__super; const tab_name = rowValue.tab_name; rowValue[prop_name] = currentPropValue; delete rowValue.index; let newTabs = formValue.tab_items.map(function (item) { if (item.tab_name == tab_name) { return Object.assign({}, item, rowValue); } else { return item; } }); const tabGroups = input.__super.__super.tab_groups; const groupNames = _.compact(_.map(tabGroups, \"group_name\")); if (groupNames && groupNames.length) { newTabs.sort(getTabsSortFun(groupNames)); } return { tab_items: newTabs }};const eventData = event.data;const newTabTtemsProp = quickEidtSaveForTab(eventData, \"group\");setTimeout(function () { doAction({ actionType: 'setValue', componentId: \"object_form\", args: { value: newTabTtemsProp } });},300);"
55
+ }
56
+ ]
57
+ }
58
+ },
59
+ "source": "${tab_groups|pick:group_name}",
60
+ "checkAll": false,
61
+ "selectFirst": false,
62
+ "searchable": true,
63
+ "clearable": true,
64
+ "id": "u:8b3d6979e884",
65
+ "multiple": false,
66
+ "mode": "inline"
67
+ },
68
+ "placeholder": "-"
69
+ },
70
+ {
71
+ "name": "tab_name_desktop",
72
+ "label": "${'apps.apps_form.tab_desktop' | t}",
73
+ "type": "tpl",
74
+ "id": "u:b95c69a1cd84",
75
+ "tpl": "${tabs_options|filter:value:equals:tab_name|first|pick:desktop|isTrue:'✔':'✘'}",
76
+ "placeholder": "-",
77
+ "remark": "${'apps.apps_form.tab_desktop_remark' | t}"
78
+ },
79
+ {
80
+ "name": "tab_name_mobile",
81
+ "label": "${'apps.apps_form.tab_mobile' | t}",
82
+ "type": "tpl",
83
+ "id": "u:b95c69a1cd84",
84
+ "tpl": "${tabs_options|filter:value:equals:tab_name|first|pick:mobile|isTrue:'✔':'✘'}",
85
+ "placeholder": "-",
86
+ "remark": "${'apps.apps_form.tab_mobile_remark' | t}"
87
+ }
88
+ ],
89
+ "headerToolbar": [
90
+ {
91
+ "type": "service",
92
+ "id": "tabs-options-service",
93
+ "body": [
94
+ {
95
+ "type": "button",
96
+ "id": "u:a35a2276145d",
97
+ "label": "${'apps.apps_form.tab_generate' | t}",
98
+ "onEvent": {
99
+ "click": {
100
+ "actions": [
101
+ {
102
+ "script": "const appId = null; const page = Steedos.Page.getPage('app', appId, null, null, 'generate_object_tabs'); if (page && page.schema) { const pageSchema = JSON.parse(page.schema); let formSchema = pageSchema.body[0]; formSchema.canAccessSuperData = false; formSchema.wrapWithPanel = false; formSchema.className = 'steedos-amis-form'; const title = t('apps.apps_form.tab_generate_title'); doAction({ 'actionType': 'dialog', 'dialog': { 'type': 'dialog', 'title': title, 'body': formSchema, 'size': 'lg' } }); }",
103
+ "actionType": "custom"
104
+ }
105
+ ],
106
+ "weight": 0
107
+ }
108
+ },
109
+ "tpl": "内容"
110
+ },
111
+ {
112
+ "type": "button",
113
+ "label": "${'apps.apps_form.tab_set' | t}",
114
+ "id": "u:853b890ab524",
115
+ "actionType": "dialog",
116
+ "dialog": {
117
+ "type": "dialog",
118
+ "title": "${'apps.apps_form.tab_set' | t}",
119
+ "body": [
120
+ {
121
+ "type": "transfer",
122
+ "name": "picked_tabs",
123
+ "value": "${tab_items|pick:tab_name}",
124
+ "sortable": true,
125
+ "source": "${tabs_options}",
126
+ "searchable": true,
127
+ "id": "u:f2d36873abd1"
128
+ }
129
+ ],
130
+ "onEvent": {
131
+ "confirm": {
132
+ "actions": [
133
+ {
134
+ "actionType": "custom",
135
+ "script": "const tabGroupKey = 'group';const getTabsSortFun = function (groupNames) { return function (m, n) { var tempM = !!m[tabGroupKey] ? 1 : 0; var tempN = !!n[tabGroupKey] ? 1 : 0; if (!m[tabGroupKey] || !n[tabGroupKey]) { return tempM - tempN; } return groupNames.indexOf(m[tabGroupKey]) - groupNames.indexOf(n[tabGroupKey]); };};const clearTabs = function (input) { return { tab_items: [] }};const convertDataForTabs = function (input) { let pickedTabs = input.picked_tabs || []; const superTabs = _.keyBy(input.__super.__super.tab_items, 'tab_name'); if (typeof pickedTabs === 'string') { pickedTabs = pickedTabs.split(','); } const tabOptions = _.keyBy(input.__super.tabs_options, 'value'); const convertedTabs = pickedTabs.map(function (tab_name) { const superTab = superTabs[tab_name]; if (superTab) { return superTab; } else { const tabOption = tabOptions[tab_name]; return { tab_name: tab_name, group: tabOption.group } } }); const tabGroups = input.__super.__super.tab_groups; const groupNames = _.compact(_.map(tabGroups, 'group_name')); if (groupNames && groupNames.length) { convertedTabs.sort(getTabsSortFun(groupNames)); } return { tab_items: convertedTabs }};const eventData = event.data;doAction({ actionType: 'setValue', componentId: 'object_form', args: { value: convertDataForTabs(eventData) }});doAction({ actionType: 'setValue', componentId: 'tabs-options-service', args: { value: convertDataForTabs(eventData) }});"
136
+ }
137
+ ]
138
+ }
139
+ },
140
+ "size": "lg",
141
+ "id": "u:9c93896a73cf",
142
+ "closeOnEsc": false,
143
+ "closeOnOutside": false,
144
+ "showCloseButton": true,
145
+ "showErrorMsg": true,
146
+ "showLoading": true,
147
+ "dataMapSwitch": false
148
+ }
149
+ },
150
+ {
151
+ "type": "button",
152
+ "label": "${'apps.apps_form.tab_grouping_set' | t}",
153
+ "actionType": "dialog",
154
+ "dialog": {
155
+ "title": "${'apps.apps_form.tab_grouping_set' | t}",
156
+ "body": [
157
+ {
158
+ "type": "input-table",
159
+ "name": "setting_groups",
160
+ "value": "${tab_groups}",
161
+ "addable": true,
162
+ "draggable": true,
163
+ "editable": true,
164
+ "needConfirm": false,
165
+ "columns": [
166
+ {
167
+ "name": "group_name",
168
+ "label": "${'apps.apps_form.tab_grouping_name' | t}",
169
+ "id": "u:383c7744b499"
170
+ },
171
+ {
172
+ "name": "default_open",
173
+ "label": "${'apps.apps_form.tab_grouping_open' | t}",
174
+ "id": "u:7a243c84ed66",
175
+ "type": "checkbox",
176
+ "value": true
177
+ }
178
+ ],
179
+ "removable": true,
180
+ "id": "setting_groups"
181
+ }
182
+ ],
183
+ "onEvent": {
184
+ "confirm": {
185
+ "actions": [
186
+ {
187
+ "actionType": "custom",
188
+ "script": "const tabGroupKey = 'group';const getTabsSortFun = function (groupNames) { return function (m, n) { var tempM = !!m[tabGroupKey] ? 1 : 0; var tempN = !!n[tabGroupKey] ? 1 : 0; if (!m[tabGroupKey] || !n[tabGroupKey]) { return tempM - tempN; } return groupNames.indexOf(m[tabGroupKey]) - groupNames.indexOf(n[tabGroupKey]); };};const clearTabs = function (input) { return { tab_items: [] }};const convertDataForGroups = function(input) { const settingGroups = input.setting_groups || []; const convertedGroups = _.uniqBy(settingGroups.map(function (item) { return { group_name: item.group_name, default_open: item.default_open } }), 'group_name'); const groupNames = _.compact(_.map(convertedGroups, 'group_name')); const tab_items = input.tab_items; tab_items?.sort(getTabsSortFun(groupNames)); return { tab_groups: convertedGroups, tab_items: tab_items }};const eventData = event.data;doAction({ actionType: 'setValue', componentId: 'object_form', args: { value: convertDataForGroups(eventData) }});"
189
+ }
190
+ ]
191
+ }
192
+ },
193
+ "type": "dialog",
194
+ "size": "lg",
195
+ "id": "setting_groups",
196
+ "closeOnEsc": false,
197
+ "closeOnOutside": false,
198
+ "showCloseButton": true,
199
+ "showErrorMsg": true,
200
+ "showLoading": true,
201
+ "dataMapSwitch": false
202
+ },
203
+ "id": "u:111b043b193c"
204
+ }
205
+ ],
206
+ "messages": {},
207
+ "api": {
208
+ "method": "post",
209
+ "url": "${context.rootUrl}/graphql",
210
+ "adaptor": "let data = payload.data;\ndata.tabs_options = [];\nif (data.options && data.options.length) {\n data.tabs_options = data.options.map(function (option) {\n option.label = option.label + '(' + option.value + ')';\n return option;\n });\n}\nif (!api.body.recordId) {\n const defaultValues = {\n is_creator: true,\n mobile: true,\n visible: true,\n sort: 9100\n };\n data = Object.assign({}, data, defaultValues);\n}\ndelete data.options;\npayload.data = data;\nreturn payload; ",
211
+ "data": {
212
+ "query": "{options:tabs{_id label:label value:name,type,object,desktop,mobile}}",
213
+ "recordId": "${recordId}"
214
+ },
215
+ "headers": {
216
+ "Authorization": "Bearer ${context.tenantId},${context.authToken}"
217
+ },
218
+ "messages": {},
219
+ "requestAdaptor": ""
220
+ }
221
+ }
222
+ ]
223
+ }
21
224
  },
22
- "id": "u:e1c1a841d373"
23
- }
24
- ],
25
- "regions": [
26
- "body"
27
- ],
28
- "data": {
29
- "objectName": "apps",
30
- "initialValues": {
225
+ "objects": {
226
+ "amis": {
227
+ "name": "objects",
228
+ "type": "select",
229
+ "className": "m-0",
230
+ "labelClassName": "text-left",
231
+ "id": "u:4e5047e44905",
232
+ "joinValues": false,
233
+ "extractValue": true,
234
+ "labelField": "label",
235
+ "valueField": "value",
236
+ "multiple": true,
237
+ "checkAll": false,
238
+ "searchable": true,
239
+ "menuTpl": "",
240
+ "source": {
241
+ "method": "get",
242
+ "url": "${context.rootUrl}/service/api/amis-metadata-objects/objects/options",
243
+ "headers": {
244
+ "Authorization": "Bearer ${context.tenantId},${context.authToken}"
245
+ }
246
+ },
247
+ "autoComplete": ""
248
+ }
249
+ },
250
+ "mobile_objects": {
251
+ "amis": {
252
+ "name": "mobile_objects",
253
+ "type": "select",
254
+ "className": "m-0",
255
+ "labelClassName": "text-left",
256
+ "id": "u:cfaeb2f857a8",
257
+ "joinValues": false,
258
+ "extractValue": true,
259
+ "labelField": "label",
260
+ "valueField": "value",
261
+ "multiple": true,
262
+ "checkAll": false,
263
+ "searchable": true,
264
+ "menuTpl": "",
265
+ "source": {
266
+ "method": "get",
267
+ "url": "${context.rootUrl}/service/api/amis-metadata-objects/objects/options",
268
+ "messages": {},
269
+ "headers": {
270
+ "Authorization": "Bearer ${context.tenantId},${context.authToken}"
271
+ }
272
+ },
273
+ "autoComplete": ""
274
+ }
275
+ }
276
+ },
277
+ "enableTabs": true,
278
+ "debug": false,
279
+ "initApiRequestAdaptor": "",
280
+ "initApiAdaptor": "var data = payload.data;\nif (data.tab_items && !_.isArray(data.tab_items)) {\n // 数据库中存储的是对象格式而不是数组,转换为数组用于界面显示\n let arrTabItems = [];\n _.each(data.tab_items, function (n, k) {\n n.tab_name = k;\n delete n.index;\n arrTabItems.push(n);\n });\n data.tab_items = arrTabItems;\n}\nif (data._id && !data.tab_items) {\n const tabOptions = data.tabs_options || [];\n const tabItems = [];\n // 把应用中原来tabs属性值添加到新的tab_items属性的默认值中\n if (data.tabs && data.tabs.length) {\n data.tabs.forEach(function (item) {\n tabItems.push({ tab_name: item });\n });\n }\n const pushObjectsToTabItems = function (objects) {\n objects.forEach(function (item) {\n // 已经有绑定到指定对象的选项卡就不添加\n let existObjectItem = !!tabItems.find(function (tabItem) {\n return !!tabOptions.find(function (option) {\n return tabItem.tab_name === tabItem.value && option.object === item;\n });\n });\n if (existObjectItem) {\n return;\n }\n // 找到指向指定对象的选项卡\n let tempOption = tabOptions.find(function (option) {\n return option.type === \"object\" && option.object === item;\n });\n if (!tempOption) {\n return;\n }\n // 选项卡名称如果重复了就不添加\n let existTabItem = !!tabItems.find(function (tabItem) {\n return tabItem.tab_name === tempOption.value;\n });\n if (existTabItem) {\n return;\n }\n if (tempOption) {\n tabItems.push({ tab_name: tempOption.value });\n }\n });\n }\n // 把应用中原来objects属性值添加到新的tab_items属性的默认值中\n if (data.objects && data.objects.length) {\n pushObjectsToTabItems(data.objects);\n }\n // 把应用中原来mobile_objects属性值添加到新的tab_items属性的默认值中\n if (data.mobile_objects && data.mobile_objects.length) {\n pushObjectsToTabItems(data.mobile_objects);\n }\n data.tab_items = tabItems;\n}\n\npayload.data = data;\ndelete payload.extensions;\nreturn payload;\n ",
281
+ "apiRequestAdaptor": "delete formData.tabs_options;\nconst recordId = formData.recordId;\n\n// 新加字段tab_items,值同步回传到老字段tabs中兼容老UI界面\nformData.tabs = [];\nif (formData.tab_items && formData.tab_items.length) { \n formData.tabs = formData.tab_items.map(function (item) { return item.tab_name; });\n}\n\n/*\ntab_items存储为:\ntab_items: {\n test1:{\n group:\"xxx\"\n },\n test3:{\n group:\"yyy\"\n }\n}\n而不是:\ntab_items: [\n {\n \"index\":1,\n \"group\":\"xxx\"\n },\n {\n \"index\":2,\n \"group\":\"yyy\"\n }\n]\n*/\nif (formData.tab_items) { \n formData.tab_items = _.keyBy(formData.tab_items, \"tab_name\")\n let tempIndex = 0;\n _.each(formData.tab_items, function (n, k) {\n tempIndex++;\n n.index = tempIndex;\n delete n.tab_name;\n });\n}\n\nquery = `mutation{record: ${objectName}__insert(doc: {__saveData}){_id}}`;\nif(recordId){\n query = `mutation{record: ${objectName}__update(id: \"${recordId}\", doc: {__saveData}){_id}}`;\n};\n__saveData = JSON.stringify(JSON.stringify(formData));\n\napi.data = {query: query.replace('{__saveData}', __saveData)};\nreturn api;\n",
282
+ "apiAdaptor": "",
283
+ "form": {
284
+ "id": "object_form"
31
285
  },
32
- "appId": "builder",
33
- "title": "",
34
- "context": {
35
- "rootUrl": "http://127.0.0.1:5800",
36
- "tenantId": "649bd0e96d6ec67c19dca38f",
37
- "userId": "30e565d1-f2d3-4bb7-8895-8a16ab436c1a",
38
- "authToken": "b65ec19a85dcf7899b663b85f65c606c05e2ab73d86482c299904d9ebdc81211c0cd407df26ac43fbfea20"
39
- }
40
- },
41
- "id": "u:de840f3523f2"
42
- }
286
+ "id": "u:e1c1a841d373",
287
+ "tabsMode": "line"
288
+ }
289
+ ],
290
+ "regions": [
291
+ "body"
292
+ ],
293
+ "data": {
294
+ "objectName": "apps",
295
+ "initialValues": {},
296
+ "appId": "builder",
297
+ "title": "",
298
+ "context": {
299
+ "rootUrl": "http://127.0.0.1:5800",
300
+ "tenantId": "64a4d6dd7fe9acaf8c330a37",
301
+ "userId": "683e09cd-8482-4034-bd29-5a30643e6c0f",
302
+ "authToken": "2906ff4353c25cfe291352f899ba3446aa5577f3de7ad60e1aa500c60dee7ca6fb446412f1c9693775b4cc"
303
+ }
304
+ },
305
+ "id": "u:de840f3523f2"
306
+ }