@steedos/service-plugin-amis 2.3.0-beta.8 → 2.3.0

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,201 @@
1
+ /*
2
+ * @Description: 提供amis选人组件需要的数据接口
3
+ */
4
+
5
+ const objectql = require("@steedos/objectql");
6
+ const _ = require("lodash");
7
+ const clone = require("clone");
8
+
9
+
10
+ module.exports = {
11
+ name: "amis-metadata-space_users",
12
+ mixins: [],
13
+ /**
14
+ * Settings
15
+ */
16
+ settings: {
17
+
18
+ },
19
+
20
+ /**
21
+ * Dependencies
22
+ */
23
+ dependencies: [],
24
+
25
+ /**
26
+ * Actions
27
+ */
28
+ actions: {
29
+ getSpaceUsersOptions: {
30
+ rest: {
31
+ method: "GET",
32
+ path: "/space_users/options"
33
+ },
34
+ async handler(ctx) {
35
+ const options = await this.getSpaceUsersOptions(ctx);
36
+ return { status: 0, data: { options } }
37
+ }
38
+ }
39
+ },
40
+
41
+ /**
42
+ * Events
43
+ */
44
+ events: {
45
+
46
+ },
47
+
48
+ /**
49
+ * Methods
50
+ */
51
+ methods: {
52
+ /**
53
+ 1.当没有传入参数,即第一次请求接口时返回如下格式的数据:
54
+ [
55
+ {
56
+ "leftOptions": [
57
+ {
58
+ "label": "总公司",
59
+ "value": 1,
60
+ "defer": true
61
+ }
62
+ ],
63
+ "children": [
64
+ {
65
+ "ref": 1,
66
+ "defer": true
67
+ },
68
+ {
69
+ "ref": 2,
70
+ "defer": true
71
+ },
72
+ {
73
+ "ref": 3,
74
+ "defer": true
75
+ },
76
+ {
77
+ "ref": 4,
78
+ "defer": true
79
+ },
80
+ {
81
+ "ref": 5,
82
+ "defer": true
83
+ },
84
+ {
85
+ "ref": 6,
86
+ "defer": true
87
+ }
88
+ ]
89
+ }
90
+ ]
91
+ 2.当传入def参数值时,表示展开左侧组织树某个组织,此时返回如下格式的数据:
92
+ [
93
+ {
94
+ "label": "部门 A",
95
+ "value": 2
96
+ },
97
+ {
98
+ "label": "部门 B",
99
+ "value": 3,
100
+ "defer": true
101
+ },
102
+ {
103
+ "label": "部门 C",
104
+ "value": 4
105
+ }
106
+ ]
107
+ 2.当传入ref参数值时,表示点击左侧某个组织,按此组织过滤右侧人员列表,此时返回如下格式的数据:
108
+ [
109
+ {
110
+ "label": "用户 1",
111
+ "value": "user1"
112
+ },
113
+ {
114
+ "label": "用户 2",
115
+ "value": "user2"
116
+ }
117
+ ]
118
+ */
119
+ getSpaceUsersOptions: {
120
+ async handler(ctx) {
121
+ const userSession = ctx.meta.user;
122
+ const spaceId = userSession.spaceId;
123
+ // 有 dep 值则是懒加载部门树,有 ref 值则是懒加载人员,否则按第一次加载返回第一个 option作为select的基本配置
124
+ // 需要懒加载的项通过返回相关项的 defer 为 true 来标记。左右两部分都支持懒加载。
125
+ // 参考 https://aisuda.bce.baidu.com/amis/zh-CN/components/form/select#%E4%BA%BA%E5%91%98%E7%82%B9%E9%80%89
126
+ const dep = ctx.params.dep;
127
+ const ref = ctx.params.ref;
128
+ const valueField = ctx.params.valueField || "user";//user or _id
129
+ const term = ctx.params.term;
130
+ if(dep){
131
+ // 有 dep 值则是懒加载部门树,返回展开后的部门列表
132
+ const fields = "_id,name,children".split(",");
133
+ const filters = [['space', '=', spaceId], ['parent', '=', dep]];
134
+ const orgs = await objectql.getObject('organizations').find({filters: filters, fields: fields});
135
+ const reOptions = _.map(orgs, (org)=>{
136
+ return {
137
+ value: org._id,
138
+ label: org.name,
139
+ defer: !!(org.children && org.children.length)
140
+ }
141
+ });
142
+ return reOptions;
143
+ }
144
+ else if(ref || term){
145
+ // 有 ref 值则是懒加载人员,返回按ref值过滤后的人员列表
146
+ const fields = "_id,name,user".split(",");
147
+ const filters = [['space', '=', spaceId], ['user_accepted', '=', true]];
148
+ if(term){
149
+ const fieldsForSearch = ["name", "username", "email", "mobile"];
150
+ const termFilters = [];
151
+ fieldsForSearch.forEach(function(field){
152
+ termFilters.push([field, 'contains', term]);
153
+ termFilters.push("or");
154
+ });
155
+ termFilters.pop();
156
+ filters.push(termFilters);
157
+ }
158
+ else{
159
+ filters.push(['organizations_parents', '=', ref]);
160
+ }
161
+ const sus = await objectql.getObject('space_users').find({filters: filters, fields: fields});
162
+ const reOptions = _.map(sus, (su)=>{
163
+ return {
164
+ value: su[valueField],
165
+ label: su.name
166
+ }
167
+ });
168
+ return reOptions;
169
+ }
170
+ else{
171
+ // 接口返回的选项中,第一个 option 是以下这种格式时,
172
+ // 也会把 options[0].leftOptions 当成 leftOptions
173
+ // options[0].children 当 options。
174
+ // 同时 options[0].leftDefaultValue 可以用来配置左侧选项的默认值。
175
+ const reOptions = [{
176
+ children: [],
177
+ leftOptions: [],
178
+ leftDefaultValue: ''
179
+ }];
180
+ const fields = "_id,name,children".split(",");
181
+ const filters = [['space', '=', spaceId], ['parent', '=', null]];
182
+ const rootOrgs = await objectql.getObject('organizations').find({filters: filters, fields: fields});
183
+ reOptions[0].leftOptions = _.map(rootOrgs, (org)=>{
184
+ return {
185
+ value: org._id,
186
+ label: org.name,
187
+ defer: !!(org.children && org.children.length)
188
+ }
189
+ });
190
+ reOptions[0].children = _.map(rootOrgs, (org)=>{
191
+ return {
192
+ ref: org._id,
193
+ defer: !!(org.children && org.children.length)
194
+ }
195
+ });
196
+ return reOptions;
197
+ }
198
+ }
199
+ }
200
+ }
201
+ };
@@ -6,6 +6,7 @@ const AmisFormInputs = [
6
6
  'text',
7
7
  'date',
8
8
  'file',
9
+ 'avatar',
9
10
  'image',
10
11
  'datetime',
11
12
  'time',
@@ -172,6 +173,50 @@ function getSelectFieldOptions(field){
172
173
  return options;
173
174
  }
174
175
 
176
+ function convertSFieldToAmisFilesField(field,readonly){
177
+ const type = field.type;
178
+ let table_name;
179
+ let fieldType = type;
180
+ if(type === 'avatar'){
181
+ table_name = 'avatars';
182
+ fieldType = "image";
183
+ }else if(type === 'image'){
184
+ table_name = 'images';
185
+ }else if(type === 'file'){
186
+ table_name = 'files';
187
+ }
188
+ const rootUrl = Meteor.absoluteUrl(`/api/files/${table_name}/`);
189
+ let convertData = {
190
+ type: getAmisStaticFieldType(fieldType, readonly),
191
+ receiver: {
192
+ method: "post",
193
+ url: `\${context.rootUrl}/s3/${table_name}`,
194
+ adaptor: `
195
+ var rootUrl = ${JSON.stringify(rootUrl)};
196
+ payload = {
197
+ status: response.status == 200 ? 0 : response.status,
198
+ msg: response.statusText,
199
+ data: {
200
+ value: payload._id,
201
+ name: payload.original.name,
202
+ url: rootUrl + payload._id,
203
+ }
204
+ }
205
+ return payload;
206
+ `,
207
+ headers: {
208
+ Authorization: "Bearer ${context.tenantId},${context.authToken}"
209
+ }
210
+ }
211
+ }
212
+ if(field.multiple){
213
+ convertData.multiple = true;
214
+ convertData.joinValues = false;
215
+ convertData.extractValue = true;
216
+ }
217
+ return convertData;
218
+ }
219
+
175
220
  function convertSFieldToAmisField(field, readonly) {
176
221
  // 创建人和修改人、创建时间和修改时间不显示
177
222
  if(_.include(OMIT_FIELDS, field.name)){
@@ -315,67 +360,14 @@ function convertSFieldToAmisField(field, readonly) {
315
360
  type: getAmisStaticFieldType('email', readonly)
316
361
  }
317
362
  break;
363
+ case 'avatar':
364
+ convertData = convertSFieldToAmisFilesField(field,readonly);
365
+ break;
318
366
  case 'image':
319
- rootUrl = Meteor.absoluteUrl('/api/files/images/');
320
- convertData = {
321
- type: getAmisStaticFieldType('image', readonly),
322
- receiver: {
323
- method: "post",
324
- url: "${context.rootUrl}/s3/images",
325
- adaptor: `
326
- var rootUrl = ${JSON.stringify(rootUrl)};
327
- payload = {
328
- status: response.status == 200 ? 0 : response.status,
329
- msg: response.statusText,
330
- data: {
331
- value: payload._id,
332
- filename: payload.original.name,
333
- url: rootUrl + payload._id,
334
- }
335
- }
336
- return payload;
337
- `,
338
- headers: {
339
- Authorization: "Bearer ${context.tenantId},${context.authToken}"
340
- }
341
- }
342
- }
343
- if(field.multiple){
344
- convertData.multiple = true;
345
- convertData.joinValues = false;
346
- convertData.extractValue = true;
347
- }
367
+ convertData = convertSFieldToAmisFilesField(field,readonly);
348
368
  break;
349
369
  case 'file':
350
- rootUrl = Meteor.absoluteUrl('/api/files/files/');
351
- convertData = {
352
- type: getAmisStaticFieldType('file', readonly),
353
- receiver: {
354
- method: "post",
355
- url: "${context.rootUrl}/s3/files",
356
- adaptor: `
357
- var rootUrl = ${JSON.stringify(rootUrl)};
358
- payload = {
359
- status: response.status == 200 ? 0 : response.status,
360
- msg: response.statusText,
361
- data: {
362
- value: payload._id,
363
- name: payload.original.name,
364
- url: rootUrl + payload._id,
365
- }
366
- }
367
- return payload;
368
- `,
369
- headers: {
370
- Authorization: "Bearer ${context.tenantId},${context.authToken}"
371
- }
372
- }
373
- }
374
- if(field.multiple){
375
- convertData.multiple = true;
376
- convertData.joinValues = false;
377
- convertData.extractValue = true;
378
- }
370
+ convertData = convertSFieldToAmisFilesField(field,readonly);
379
371
  break;
380
372
  case 'formula':
381
373
  //TODO
@@ -69,13 +69,13 @@ function getSaveQuery(object, recordId, fields, options){
69
69
  }
70
70
 
71
71
  /*
72
- img字段值移除URL前缀使其保存时正常保存id,而不是url。
72
+ img/avatar字段值移除URL前缀使其保存时正常保存id,而不是url。
73
73
  */
74
74
  function getScriptForRemoveUrlPrefixForImgFields(fields){
75
75
  let imgFieldsKeys = [];
76
76
  let imgFields = {};
77
77
  fields.forEach((item)=>{
78
- if(item.type === 'image'){
78
+ if(item.type === 'image' || item.type === 'avatar' ){
79
79
  imgFieldsKeys.push(item.name);
80
80
  imgFields[item.name] = {
81
81
  name: item.name,
@@ -85,12 +85,13 @@ function getConvertDataScriptStr(fields){
85
85
  function getScriptForAddUrlPrefixForImgFields(fields){
86
86
  let imgFieldsKeys = [];
87
87
  let imgFields = {};
88
- let rootUrl = Meteor.absoluteUrl('/api/files/images/');
88
+ let rootUrl = Meteor.absoluteUrl('/api/files/');
89
89
  fields.forEach((item)=>{
90
- if(item.type === 'image'){
90
+ if(item.type === 'image' || item.type === 'avatar'){
91
91
  imgFieldsKeys.push(item.name);
92
92
  imgFields[item.name] = {
93
93
  name: item.name,
94
+ type: item.type,
94
95
  multiple: item.multiple
95
96
  };
96
97
  }
@@ -106,12 +107,19 @@ function getScriptForAddUrlPrefixForImgFields(fields){
106
107
  imgFieldsKeys.forEach((item)=>{
107
108
  let imgFieldValue = data[item];
108
109
  if(imgFieldValue && imgFieldValue.length){
109
- if(imgFields[item].multiple){
110
+ let fieldProps = imgFields[item];
111
+ let table_name;
112
+ if(fieldProps.type === 'image'){
113
+ table_name = 'images';
114
+ }else{
115
+ table_name = 'avatars';
116
+ }
117
+ if(fieldProps.multiple){
110
118
  if(imgFieldValue instanceof Array){
111
- data[item] = imgFieldValue.map((value)=>{ return rootUrl + value});
119
+ data[item] = imgFieldValue.map((value)=>{ return rootUrl + table_name + '/' + value});
112
120
  }
113
121
  }else{
114
- data[item] = rootUrl + imgFieldValue;
122
+ data[item] = rootUrl + table_name + '/' + imgFieldValue;
115
123
  }
116
124
  }
117
125
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steedos/service-plugin-amis",
3
- "version": "2.3.0-beta.8",
3
+ "version": "2.3.0",
4
4
  "main": "package.service.js",
5
5
  "scripts": {
6
6
  "build": "node .scripts/build.tailwind.js"
@@ -10,5 +10,5 @@
10
10
  "publishConfig": {
11
11
  "access": "public"
12
12
  },
13
- "gitHead": "d0bfd52568ee68e3af0f251c06bd8169e823851f"
13
+ "gitHead": "b00e79e6fb8549b2fabed7b6cd6d4847775ba5df"
14
14
  }
@@ -52,7 +52,7 @@ body{
52
52
  min-width: 100px;
53
53
  }
54
54
 
55
- .steedos-amis-form .antd-Collapse .antd-Form--normal{
55
+ .steedos-amis-form .antd-Collapse .antd-Form--normal, .antd-Form--normal .antd-Tabs .antd-Tabs-content .antd-Tabs-pane .form-content{
56
56
  display: grid!important;
57
57
  grid-template-columns: repeat(2,minmax(0,1fr))!important;
58
58
  grid-row-gap: 1rem!important;