@steedos/standard-object-database 2.7.7 → 2.7.8-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.
@@ -0,0 +1,35 @@
1
+ /*
2
+ * @Author: baozhoutao@steedos.com
3
+ * @Date: 2024-08-29 09:36:15
4
+ * @LastEditors: baozhoutao@steedos.com
5
+ * @LastEditTime: 2024-09-05 16:26:51
6
+ * @Description:
7
+ */
8
+ module.exports = {
9
+
10
+ design_fields_layout: function(object_name, record_id, item_element) {
11
+ var record = this.record || Creator.getObjectById(record_id);
12
+ if (record && record.record) {
13
+ record = record.record;
14
+ }
15
+ if (!record) {
16
+ return toastr.error("未找到记录");
17
+ }
18
+
19
+ window.open(Creator.getRelativeUrl("/api/amisObjectFieldsDesign?oid=" + record_id+`&assetUrls=${Builder.settings.assetUrls}`));
20
+ },
21
+ design_fields_layoutVisible: function(object_name, record_id, record_permissions, data) {
22
+ var record = data && data.record;
23
+ if (!Creator.isSpaceAdmin()) {
24
+ return false
25
+ }
26
+ if (!record) {
27
+ record = Creator.odata.get("objects", record_id, "is_deleted");
28
+ }
29
+
30
+ if (record && !record.is_deleted && record.name != 'users' && record.created) {
31
+ return true;
32
+ }
33
+ }
34
+
35
+ }
@@ -0,0 +1,5 @@
1
+ name: design_fields_layout
2
+ is_enable: true
3
+ label: 设计字段布局
4
+ 'on': record_more
5
+ sort: 80
@@ -0,0 +1,411 @@
1
+ <!--
2
+ * @Author: baozhoutao@steedos.com
3
+ * @Date: 2022-06-02 17:45:15
4
+ * @LastEditors: baozhoutao@steedos.com
5
+ * @LastEditTime: 2024-09-04 18:09:08
6
+ * @Description:
7
+ -->
8
+ <html>
9
+ <head>
10
+ <script src="/unpkg.com/@steedos-builder/fiddle@0.0.5/dist/builder-fiddle.umd.js"></script>
11
+ <script src="/unpkg.com/axios@0.26.1/dist/axios.min.js"></script>
12
+ <script src="https://unpkg.steedos.cn/flowbite@2.3.0/dist/flowbite.min.js"></script>
13
+ <script src="https://cdn.tailwindcss.com"></script>
14
+ </head>
15
+
16
+ <body>
17
+ <!-- Main modal -->
18
+ <div id="fieldLayoutModal" tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
19
+ <div class="relative p-4 w-full max-w-2xl max-h-full">
20
+ <!-- Modal content -->
21
+ <div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
22
+ <!-- Modal header -->
23
+ <div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600">
24
+ <h3 class="text-xl font-semibold text-gray-900 dark:text-white">
25
+ 字段保存结果
26
+ </h3>
27
+ <button type="button" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white" data-modal-hide="fieldLayoutModal">
28
+ <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
29
+ <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
30
+ </svg>
31
+ <span class="sr-only">Close modal</span>
32
+ </button>
33
+ </div>
34
+ <!-- Modal body -->
35
+ <div class="p-4 md:p-5 space-y-4">
36
+ <ul class="space-y-4 text-gray-500 list-disc list-inside dark:text-gray-400" id="fieldLayoutList">
37
+ </ul>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ <builder-fiddle host="<%=builderHost%>"></builder-fiddle>
43
+ <script>
44
+ const useOpenAPI= <%=(useOpenAPI === "true" || useOpenAPI === true)%>;
45
+ const settings = {
46
+ assetUrls: "<%=assetUrls%>",
47
+ rootUrl: "<%=rootUrl%>",
48
+ userId: "<%=userId%>",
49
+ tenantId: "<%=tenantId%>",
50
+ authToken: "<%=authToken%>",
51
+ messageOnly: true,
52
+ useOpenAPI: useOpenAPI,
53
+ oid: "<%=id%>",
54
+ pageId: "<%=id%>",
55
+ hiddenDeploy: true
56
+ };
57
+
58
+ let comp = document.querySelector("builder-fiddle");
59
+
60
+ // set the modal menu element
61
+ const $targetEl = document.getElementById('fieldLayoutModal');
62
+ // options with default values
63
+ const options = {
64
+ placement: 'top-center',
65
+ backdrop: 'dynamic',
66
+ backdropClasses:
67
+ 'bg-gray-900/50 dark:bg-gray-900/80 fixed inset-0 z-40',
68
+ closable: true,
69
+ onHide: () => {
70
+ console.log('modal is hidden');
71
+ },
72
+ onShow: () => {
73
+ console.log('modal is shown');
74
+ },
75
+ onToggle: () => {
76
+ console.log('modal has been toggled');
77
+ },
78
+ };
79
+ // instance options object
80
+ const instanceOptions = {
81
+ id: 'fieldLayoutModal',
82
+ override: true
83
+ };
84
+ const modal = new Flowbite.default.Modal($targetEl, options, instanceOptions);
85
+
86
+ const loadPage = async () => {
87
+ const { assetUrls, rootUrl, userId, tenantId, authToken, oid } = settings;
88
+
89
+ // 如果传入 steedos rooturl
90
+ if (rootUrl && !authToken) return;
91
+
92
+ const initialContent = {
93
+ type: "page",
94
+ title: "Welcome to Steedos",
95
+ body: [],
96
+ regions: ["body"],
97
+ data: {
98
+ objectName: "space_users",
99
+ recordId: "",
100
+ initialValues: {},
101
+ appId: "builder",
102
+ title: "",
103
+ context: {
104
+ rootUrl,
105
+ userId,
106
+ tenantId,
107
+ authToken,
108
+ },
109
+ },
110
+ };
111
+
112
+ if (oid) {
113
+ const result = await axios.get(
114
+ `${rootUrl}/service/api/object_fields/amis/design/schema?oid=${oid}`,
115
+ {
116
+ withCredentials: true,
117
+ headers: { Authorization: `Bearer ${tenantId},${authToken}` },
118
+ }
119
+ );
120
+ if (result?.data) {
121
+ let schema = result.data.schema || initialContent;
122
+
123
+ // let objectName = result.data.object_name;
124
+ // let pageType = result.data.type;
125
+ if (typeof schema === "string") {
126
+ schema = JSON.parse(schema);
127
+ }
128
+
129
+ if (!schema.data) {
130
+ schema.data = {};
131
+ }
132
+
133
+ if (!schema.data.context) {
134
+ schema.data.context = {};
135
+ }
136
+
137
+ // schema.data.objectName = objectName;
138
+
139
+ schema.data.context.rootUrl = rootUrl;
140
+ schema.data.context.tenantId = tenantId;
141
+ schema.data.context.userId = userId;
142
+ schema.data.context.authToken = authToken;
143
+ schema.data.context.user = <%- JSON.stringify(userSession) %>;
144
+
145
+ // if (objectName && pageType === "record") {
146
+ // const record = await axios.get(
147
+ // `${rootUrl}/api/v4/${objectName}?$orderby=modified&$top=1`,
148
+ // {
149
+ // withCredentials: true,
150
+ // headers: { Authorization: `Bearer ${tenantId},${authToken}` },
151
+ // }
152
+ // );
153
+ // const value = record?.data?.value;
154
+ // if (value?.length > 0) {
155
+ // schema.data.recordId = value[0]._id;
156
+ // }
157
+ // }
158
+
159
+ return schema || initialContent
160
+ }
161
+ } else {
162
+ return initialContent
163
+ }
164
+ };
165
+
166
+ const savePage = async (data) => {
167
+ const { rootUrl, userId, tenantId, authToken, oid } = settings;
168
+
169
+ if (!oid) {
170
+ return;
171
+ }
172
+
173
+ // 保存schema时,清理context下的认证信息
174
+ const schema = JSON.parse(
175
+ JSON.stringify(data.data.AmisSchema, null, 4)
176
+ );
177
+ if (schema.data && typeof schema.data.context === 'object' ) {
178
+ delete schema.data.context
179
+ }
180
+
181
+ try {
182
+ delete schema.data.recordId;
183
+ delete schema.data.objectName;
184
+ } catch (error) {
185
+
186
+ }
187
+
188
+ return await axios.post(
189
+ `${rootUrl}/service/api/object_fields/amis/design/schema?oid=${oid}`,
190
+ {
191
+ withCredentials: true,
192
+ schema: schema,
193
+ },
194
+ {
195
+ headers: { Authorization: `Bearer ${tenantId},${authToken}` },
196
+ }
197
+ )
198
+ .catch(function (error) {
199
+ // handle error
200
+ console.log(error);
201
+ });
202
+ };
203
+ window.addEventListener('message', function (event) {
204
+ const { data } = event;
205
+ if (data) {
206
+ if(data.type === 'builder.loaded'){
207
+ comp.messageFrame('builder.EditorPropsChanged', { editorProps : JSON.stringify({
208
+ onDndAccept: function(event){
209
+ console.log(`onDndAccept===>`, event);
210
+ return true;
211
+ },
212
+ onInit: function(){
213
+ // 创建一个新的 style 元素
214
+ var style = document.createElement('style');
215
+ style.type="text/css";
216
+ style.media="screen";
217
+ // 将 CSS 样式写入 style 元素
218
+ style.innerHTML = `
219
+ .ae-RendererList-groupWrap .ae-RendererList-group:nth-child(n+3) {
220
+ display: none;
221
+ }
222
+ .ae-RendererList-groupWrap .ae-RendererList-head:nth-child(n+2) {
223
+ display: none !important;
224
+ }
225
+ .ae-RendererList-tabs-header .antd-Tabs-link:nth-child(n+2) {
226
+ display: none !important;
227
+ }
228
+ `;
229
+
230
+ // 将 style 元素插入到 head 中
231
+ document.head.appendChild(style);
232
+ },
233
+ disableBultinPlugin: false,
234
+ disablePluginList2: function(id, plugin){
235
+ if(lodash.includes([
236
+ "FlexPlugin",
237
+ "GridPlugin",
238
+ "ContainerPlugin",
239
+ "Layout_free_container",
240
+ "Layout_fixed_top",
241
+ "Layout_fixed",
242
+ "CollapseGroupPlugin",
243
+ "PanelPlugin",
244
+ "TabsPlugin",
245
+ "SwitchContainerPlugin",
246
+ "CRUDPlugin",
247
+ "Table2Plugin",
248
+ "TableCRUDPlugin",
249
+ "FormPlugin",
250
+ "ServicePlugin",
251
+ // "TextControlPlugin",
252
+ // "TextareaControlPlugin",
253
+ // "NumberControlPlugin",
254
+ // "SelectControlPlugin",
255
+ // "NestedSelectControlPlugin",
256
+ // "ChainedSelectControlPlugin",
257
+ // "DropDownButtonPlugin",
258
+ // "CheckboxesControlPlugin",
259
+ // "RadiosControlPlugin",
260
+ // "CheckboxControlPlugin",
261
+ // "DateControlPlugin",
262
+ // "DateRangeControlPlugin",
263
+ // "FileControlPlugin",
264
+ // "ImageControlPlugin",
265
+ // "ExcelControlPlugin",
266
+ // "TreeControlPlugin",
267
+ // "TagControlPlugin",
268
+ // "ListControlPlugin",
269
+ // "ButtonGroupControlPlugin",
270
+ // "ButtonToolbarControlPlugin",
271
+ // "PickerControlPlugin",
272
+ // "SwitchControlPlugin",
273
+ // "RangeControlPlugin",
274
+ // "RateControlPlugin",
275
+ // "CityControlPlugin",
276
+ // "TransferPlugin",
277
+ // "TabsTransferPlugin",
278
+ // "ColorControlPlugin",
279
+ // "ConditionBilderPlugin",
280
+ // "FieldSetControlPlugin",
281
+ // "ComboControlPlugin",
282
+ // "InputGroupControlPlugin",
283
+ // "TableControlPlugin",
284
+ // "MatrixControlPlugin",
285
+ // "RichTextControlPlugin",
286
+ // "DiffEditorControlPlugin",
287
+ // "CodeEditorControlPlugin",
288
+ // "SearchBoxPlugin",
289
+ // "KVControlPlugin",
290
+ // "RepeatControlPlugin",
291
+ // "UUIDControlPlugin",
292
+ // "LocationControlPlugin",
293
+ // "SubFormControlPlugin",
294
+ // "HiddenControlPlugin",
295
+ // "SignaturePlugin",
296
+ // "StaticControlPlugin",
297
+ "ButtonPlugin",
298
+ "ButtonGroupPlugin",
299
+ "NavPlugin",
300
+ "AnchorNavPlugin",
301
+ "TooltipWrapperPlugin",
302
+ "AlertPlugin",
303
+ "WizardPlugin",
304
+ "TableViewPlugin",
305
+ "WebComponentPlugin",
306
+ "AudioPlugin",
307
+ "VideoPlugin",
308
+ "CustomPlugin",
309
+ "TasksPlugin",
310
+ "EachPlugin",
311
+ "PropertyPlugin",
312
+ "IFramePlugin",
313
+ "QRCodePlugin",
314
+ "TplPlugin",
315
+ "IconPlugin",
316
+ "LinkPlugin",
317
+ "ListPlugin",
318
+ "List2Plugin",
319
+ "MappingPlugin",
320
+ "AvatarPlugin",
321
+ "CardPlugin",
322
+ "Card2Plugin",
323
+ "CardsPlugin",
324
+ "TablePlugin",
325
+ "TableCell2Plugin",
326
+ "ChartPlugin",
327
+ "SparklinePlugin",
328
+ "CarouselPlugin",
329
+ "ImagePlugin",
330
+ "ImagesPlugin",
331
+ "DatePlugin",
332
+ "TimePlugin",
333
+ "DatetimePlugin",
334
+ "CalendarPlugin",
335
+ "TagPlugin",
336
+ "JsonPlugin",
337
+ "ProgressPlugin",
338
+ "StatusPlugin",
339
+ "StepsPlugin",
340
+ "TimelinePlugin",
341
+ // "DividerPlugin",
342
+ // "CodeViewPlugin",
343
+ // "MarkdownPlugin",
344
+ // "CollapsePlugin",
345
+ "OfficeViewerPlugin",
346
+ "PdfViewerPlugin",
347
+ "LogPlugin",
348
+ "ActionPlugin",
349
+ "TableCellPlugin",
350
+ "ArrayControlPlugin",
351
+ "ControlPlugin",
352
+ "DateTimeControlPlugin",
353
+ "DateTimeRangeControlPlugin",
354
+ "EmailControlPlugin",
355
+ "FormulaControlPlugin",
356
+ "GroupControlPlugin",
357
+ "ItemPlugin",
358
+ "MonthControlPlugin",
359
+ "MonthRangeControlPlugin",
360
+ "PasswordControlPlugin",
361
+ "InputQuarterPlugin",
362
+ "QuarterRangePlugin",
363
+ "TimeControlPlugin",
364
+ "TimeRangeControlPlugin",
365
+ "TreeSelectControlPlugin",
366
+ "URLControlPlugin",
367
+ "YearControlPlugin",
368
+ "YearRangeControlPlugin",
369
+ "BreadcrumbPlugin",
370
+ "CustomRegionPlugin",
371
+ "DialogPlugin",
372
+ "DrawerPlugin",
373
+ "HBoxPlugin",
374
+ "ListItemPlugin",
375
+ "OperationPlugin",
376
+ // "PagePlugin",
377
+ "PaginationPlugin",
378
+ "PlainPlugin",
379
+ "ResetPlugin",
380
+ "SubmitPlugin",
381
+ "WrapperPlugin",
382
+ "ColumnToggler"
383
+ ]
384
+ ,id)){
385
+ return true;
386
+ }
387
+ return false
388
+ }
389
+ }, (key, value) => {
390
+ if (typeof value === 'function') {
391
+ return value.toString();
392
+ }
393
+ return value;
394
+ })} )
395
+ }
396
+ if (data.type === 'builder.loadContent') {
397
+ loadPage().then((content)=>{
398
+ comp.messageFrame('builder.contentChanged', { AmisSchema : content } )
399
+ })
400
+ }
401
+ if (data.type === 'builder.saveContent') {
402
+ savePage(data.data).then(()=>{
403
+ comp.messageFrame('builder.contentSaved')
404
+ })
405
+ }
406
+ }
407
+ })
408
+ comp.settings = settings;
409
+ </script>
410
+ </body>
411
+ </html>
@@ -0,0 +1,76 @@
1
+ /*
2
+ * @Author: baozhoutao@steedos.com
3
+ * @Date: 2022-04-04 16:34:28
4
+ * @Description:
5
+ */
6
+ const express = require('express');
7
+ const router = express.Router();
8
+ const core = require('@steedos/core');
9
+ const ejs = require('ejs');
10
+ const fs = require('fs');
11
+ const _ = require('lodash');
12
+ const path = require('path');
13
+ const objectql = require('@steedos/objectql');
14
+
15
+ const getPublicAssetUrls = function(assetUrls){
16
+ const values = _.map(_.split(assetUrls), (item)=>{
17
+ if(_.startsWith(item, '/')){
18
+ return Meteor.absoluteUrl(item) ;
19
+ }else{
20
+ return item;
21
+ }
22
+ })
23
+ return _.join(values, ',')
24
+ }
25
+
26
+ router.get('/api/amisObjectFieldsDesign', core.requireAuthentication, async function (req, res) {
27
+ try {
28
+ res.set('Content-Type', 'text/html');
29
+ const userSession = req.user;
30
+ let assetUrls = getPublicAssetUrls(req.query.assetUrls);
31
+ const assetUrl = `assetUrl=${assetUrls.split(',').join("&assetUrl=")}&`;
32
+
33
+ // const dataContext = {
34
+ // rootUrl: __meteor_runtime_config__.ROOT_URL,
35
+ // tenantId: userSession.spaceId,
36
+ // userId: userSession.userId,
37
+ // authToken: userSession.authToken
38
+ // }
39
+ let locale = "zh-CN";
40
+ if (req.query.locale == "en-us") {
41
+ locale = "en-US";
42
+ } else if (req.query.locale == "zh-cn") {
43
+ locale = "zh-CN";
44
+ }
45
+ const retUrl = __meteor_runtime_config__.ROOT_URL + '/app/admin/objects/view/' + req.query.oid
46
+ const steedosBuilderUrl = process.env.STEEDOS_BUILDER_URL || 'https://builder.steedos.cn';
47
+ const builderHost = `${steedosBuilderUrl}/object?${assetUrl}retUrl=${retUrl}&locale=${locale}&isObjectDesign=1&pType=objectDesign`;
48
+
49
+ const filename = __dirname+'/object_fields_design.ejs'
50
+ const data = {
51
+ builderHost,
52
+ assetUrls,
53
+ rootUrl: __meteor_runtime_config__.ROOT_URL,
54
+ tenantId: userSession.spaceId,
55
+ userId: userSession.userId,
56
+ authToken: userSession.authToken,
57
+ userSession: userSession,
58
+ id: req.query.oid,
59
+ useOpenAPI: process.env.STEEDOS_PUBLIC_USE_OPEN_API
60
+ }
61
+ const options = {}
62
+ ejs.renderFile(filename, data, options, function(err, str){
63
+ if(err){
64
+ console.log(`err`, err)
65
+ }
66
+ // str => Rendered HTML string
67
+ res.send(str);
68
+ });
69
+
70
+ } catch (error) {
71
+ console.log(error)
72
+ res.status(500).send({ message: error.message });
73
+ }
74
+
75
+ });
76
+ exports.default = router;
@@ -6,12 +6,11 @@ const register = require("@steedos/metadata-registrar");
6
6
  const steedosI18n = require("@steedos/i18n");
7
7
  const _ = require("lodash");
8
8
  const clone = require("clone");
9
-
9
+ const serviceObjectMixin = require('@steedos/service-object-mixin');
10
10
  // 默认值字段代码:services/standard-object-database/main/default/services/object_fields.service.js
11
-
12
11
  module.exports = {
13
12
  name: "object_fields",
14
- mixins: [],
13
+ mixins: [serviceObjectMixin],
15
14
  /**
16
15
  * Settings
17
16
  */
@@ -38,6 +37,27 @@ module.exports = {
38
37
  const data = await this.getDefaultValueSchema(ctx);
39
38
  return { status: 0, msg: "", data: data }
40
39
  }
40
+ },
41
+ getAmisDesignSchema: {
42
+ // 需要传 objectName, targetObject(非必填), field_name 参数进来。
43
+ rest: {
44
+ method: "GET",
45
+ path: "/amis/design/schema"
46
+ },
47
+ async handler(ctx) {
48
+ const schema = await this.getAmisDesignSchema(ctx);
49
+ return { status: 0, msg: "", schema: schema }
50
+ }
51
+ },
52
+ saveAmisDesignSchema: {
53
+ rest: {
54
+ method: "POST",
55
+ path: "/amis/design/schema"
56
+ },
57
+ async handler(ctx) {
58
+ const data = await this.saveAmisDesignSchema(ctx);
59
+ return { status: 0, msg: "", data: data}
60
+ }
41
61
  }
42
62
  },
43
63
 
@@ -243,6 +263,201 @@ module.exports = {
243
263
  body
244
264
  }
245
265
  }
266
+ },
267
+ getAmisDesignSchema: {
268
+ async handler(ctx) {
269
+ // console.log('ctx==>', ctx);
270
+ const userSession = ctx.meta.user;
271
+ const lng = userSession.language || 'zh-CN';
272
+ const oid = ctx.params.oid || 'text';
273
+
274
+ const object = await this.getObject("objects").findOne(oid);
275
+
276
+ if(object){
277
+
278
+ const groups = object.field_groups;
279
+
280
+ const getGroup = (groupName)=>{
281
+ if(groupName == 'undefined' || groupName == 'null'){
282
+ groupName = '';
283
+ }
284
+ return _.find(groups, (group)=>{
285
+ return group.group_name === groupName;
286
+ }) || {group_name: groupName}
287
+ }
288
+
289
+ const objectName = object.name;
290
+ let objectFields = await this.getObject('object_fields').find({filters: [['object', '=', objectName]]});
291
+
292
+ _.map(objectFields, (objectField)=>{
293
+ if(!objectField.group){
294
+ objectField.group = '基本信息'
295
+ }
296
+ })
297
+
298
+ return {
299
+ type: 'steedos-object',
300
+ name: objectName,
301
+ label: object.label,
302
+ description: object.description,
303
+ data: {
304
+ objectName
305
+ },
306
+ className: "steedos-amis-form steedos-field-layout-page m-4",
307
+ body: _.map(_.groupBy(_.orderBy(objectFields, function(o) { return o.sort_no || 100 }), 'group'), (items, groupName)=>{
308
+ const group = getGroup(groupName)
309
+ return {
310
+ type: 'steedos-field-group',
311
+ title: group.group_name,
312
+ collapsed: group.collapsed,
313
+ visible_on: group.visible_on,
314
+ body: _.map(items, (field)=>{
315
+ return {
316
+ type: `sfield-${field.type}`,
317
+ config: Object.assign({amis: {name: field.name}}, field)
318
+ }
319
+ })
320
+ }
321
+ })
322
+ }
323
+ }
324
+
325
+ }
326
+ },
327
+ saveAmisDesignSchema: {
328
+ async handler(ctx) {
329
+ // console.log('ctx==>', ctx);
330
+ const userSession = ctx.meta.user;
331
+
332
+ if(!userSession.is_space_admin){
333
+ return {
334
+ message: '无权限'
335
+ }
336
+ }
337
+
338
+
339
+ const lng = userSession.language || 'zh-CN';
340
+ // TODO 必须是管理员
341
+
342
+ const oid = ctx.params.oid || 'text';
343
+ const schema = ctx.params.schema;
344
+ const object = await this.getObject("objects").findOne(oid);
345
+ const fields = [];
346
+ const groups = [];
347
+ const objectSet = {
348
+ name: schema.name,
349
+ label: schema.label,
350
+ description: schema.description
351
+ };
352
+ if(!object){
353
+ return {}
354
+ }
355
+ let sort_no = 50;
356
+ _.each(schema.body, (group)=>{
357
+ if(group.type === 'steedos-field-group'){
358
+ const groupName = group.title;
359
+ _.each(group.body, (field)=>{
360
+ if(_.startsWith(field.type, 'sfield-')){
361
+ fields.push(Object.assign({}, field.config, {group: groupName, sort_no}));
362
+ sort_no += 50;
363
+ }
364
+ })
365
+ groups.push({
366
+ group_name: group.title,
367
+ collapsed: group.collapsed,
368
+ visible_on: group.visible_on
369
+ })
370
+ }else if(_.startsWith(field.type, 'sfield-')){
371
+ fields.push(Object.assign({}, field.config, {sort_no}));
372
+ sort_no += 50;
373
+ }
374
+ })
375
+
376
+ objectSet.field_groups = groups;
377
+
378
+ const object_fields = await this.getObject('object_fields');
379
+ const dbFields = await object_fields.directFind({filters: ['object','=', object.name]});
380
+
381
+ let insertFields = _.differenceBy(fields, dbFields, 'name').map(field => field.name);
382
+ let updateFields = _.intersectionBy(fields, dbFields, 'name').map(field => field.name);
383
+ let deleteFields = _.differenceBy(dbFields, fields, 'name').map(field => field.name);
384
+
385
+ // 用于记录成功和失败的字段
386
+ const log = {
387
+ insert: {
388
+ success: [],
389
+ error: []
390
+ },
391
+ update: {
392
+ success: [],
393
+ error: []
394
+ },
395
+ delete: {
396
+ success: [],
397
+ error: []
398
+ }
399
+ };
400
+
401
+ // 循环需要增加的字段
402
+ for (const fieldName of insertFields) {
403
+ try {
404
+ const newId = await object_fields._makeNewID();
405
+ const now = new Date();
406
+ const field = _.find(fields, { name: fieldName });
407
+ await object_fields.directInsert(Object.assign({}, field, {
408
+ _id: newId,
409
+ owner: userSession.userId,
410
+ space: userSession.spaceId,
411
+ object: object.name,
412
+ created: now,
413
+ modified: now,
414
+ created_by: userSession.userId,
415
+ modified_by: userSession.userId,
416
+ company_id: userSession.company_id,
417
+ company_ids: userSession.company_ids
418
+ }));
419
+ log.insert.success.push(fieldName);
420
+ } catch (e) {
421
+ log.insert.error.push(fieldName);
422
+ console.error(`新增字段 ${fieldName} 时出错:`, e);
423
+ }
424
+ }
425
+
426
+ // 循环需要修改的字段
427
+ const now = new Date();
428
+ for (const fieldName of updateFields) {
429
+ try {
430
+ const field = _.find(fields, { name: fieldName });
431
+ const id = _.find(dbFields, { name: fieldName })._id;
432
+ const submitField = _.omit(field, ['name', '_name']);
433
+ await object_fields.directUpdate(id, Object.assign({}, submitField, {
434
+ modified: now,
435
+ modified_by: userSession.userId
436
+ }));
437
+ log.update.success.push(fieldName);
438
+ } catch (e) {
439
+ log.update.error.push(fieldName);
440
+ console.log(`dbFields`, fieldName, dbFields)
441
+ console.error(`更新字段 ${fieldName} 时出错:`, e);
442
+ }
443
+ }
444
+ // 循环需要删除的字段
445
+ for (const fieldName of deleteFields) {
446
+ try {
447
+ const id = _.find(dbFields, { name: fieldName })._id;
448
+ await object_fields.directDelete(id);
449
+ log.delete.success.push(fieldName);
450
+ } catch (e) {
451
+ log.delete.error.push(fieldName);
452
+ console.error(`删除字段 ${fieldName} 时出错:`, e);
453
+ }
454
+ }
455
+ //label和修改时间未实时生效
456
+ const objectConn = await this.getObject('objects');
457
+ const current_object = await objectConn.findOne({filters:[["name","=",object.name]]});
458
+ await objectConn.update(current_object._id, Object.assign({}, objectSet, {reload_time: new Date()}))
459
+ return log;
460
+ }
246
461
  }
247
462
  }
248
463
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steedos/standard-object-database",
3
- "version": "2.7.7",
3
+ "version": "2.7.8-beta.2",
4
4
  "main": "package.service.js",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -12,14 +12,14 @@
12
12
  "description": "steedos package",
13
13
  "dependencies": {
14
14
  "@steedos-widgets/amis-lib": "^1.0.22",
15
- "@steedos/metadata-core": "2.7.7",
16
- "@steedos/service-object-mixin": "2.7.7",
17
- "@steedos/standard-objects": "2.7.7",
15
+ "@steedos/metadata-core": "2.7.8-beta.2",
16
+ "@steedos/service-object-mixin": "2.7.8-beta.2",
17
+ "@steedos/standard-objects": "2.7.8-beta.2",
18
18
  "amis-formula": "~6.3.0",
19
19
  "clone": "^2.1.2",
20
20
  "moleculer-bullmq": "3.0.0"
21
21
  },
22
22
  "repository": {},
23
23
  "license": "MIT",
24
- "gitHead": "82b87061344ebe4c6a9dbd258e8891fcc39bfdc6"
24
+ "gitHead": "d915768c87aaa7bc026623a4953d6f39c5ddace1"
25
25
  }