@steedos-labs/plugin-workflow 3.0.25 → 3.0.27
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.
- package/designer/README.md +110 -0
- package/main/default/objects/flows/flows.object.yml +18 -0
- package/main/default/objects/instance_tasks/buttons/instance_new.button.yml +4 -1
- package/main/default/objects/instances/buttons/instance_new.button.yml +4 -1
- package/main/default/objects/instances/buttons/instance_return.button.yml +11 -0
- package/main/default/pages/flow_selector.page.amis.json +1 -1
- package/main/default/pages/flow_selector_mobile.page.amis.json +5 -0
- package/main/default/pages/flow_selector_mobile.page.yml +7 -0
- package/main/default/pages/page_instance_print.page.amis.json +7 -1
- package/main/default/routes/am.router.js +28 -0
- package/main/default/routes/api_workflow_ai_design.router.js +184 -0
- package/main/default/routes/api_workflow_next_step_users.router.js +4 -0
- package/main/default/routes/designer-v2.router.js +62 -0
- package/package.json +13 -1
- package/public/workflow/index.css +40 -0
- package/src/util/templateConverter.js +151 -1
- package/AI_PLUGIN_GUIDE.md +0 -939
- package/APPROVAL_COMMENTS_OPERATIONS.md +0 -673
- package/APPROVAL_COMMENTS_UPGRADE.md +0 -854
- package/README_TEMPLATE.md +0 -222
- package/convert-templates.js +0 -51
- package/run.js +0 -388
package/package.json
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steedos-labs/plugin-workflow",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.27",
|
|
4
4
|
"main": "package.service.js",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"files": [
|
|
7
|
+
"main",
|
|
8
|
+
"src",
|
|
9
|
+
"designer/dist",
|
|
10
|
+
"public/applications",
|
|
11
|
+
"public/office",
|
|
12
|
+
"public/workflow",
|
|
13
|
+
"package.service.js",
|
|
14
|
+
"package.service.yml",
|
|
15
|
+
"LICENSE.txt",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
6
18
|
"scripts": {
|
|
7
19
|
"build:watch": "tsc --watch",
|
|
8
20
|
"release": "npm publish --registry https://registry.npmjs.org && npx cnpm sync @steedos-labs/plugin-workflow",
|
|
@@ -529,6 +529,13 @@ tbody .color-priority-muted *{
|
|
|
529
529
|
box-shadow: none;
|
|
530
530
|
}
|
|
531
531
|
|
|
532
|
+
.steedos-instance-style-table .antd-RadiosControl{
|
|
533
|
+
margin-left: 0.5rem !important;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.steedos-instance-style-table .antd-CheckboxesControl{
|
|
537
|
+
margin-left: 0.5rem !important;
|
|
538
|
+
}
|
|
532
539
|
|
|
533
540
|
.instances-sidebar .steedos-listview-change-button > button > .fa-caret-down{
|
|
534
541
|
display: none;
|
|
@@ -556,6 +563,12 @@ tbody .color-priority-muted *{
|
|
|
556
563
|
height: calc(100vh - 101px);
|
|
557
564
|
}
|
|
558
565
|
|
|
566
|
+
@media (max-width: 768px){
|
|
567
|
+
.steedos-instance-detail-wrapper{
|
|
568
|
+
height: calc(100vh - 64px);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
559
572
|
.steedos-amis-instance-view-body .antd-Panel-title{
|
|
560
573
|
font-size: 14px;
|
|
561
574
|
font-weight: 500;
|
|
@@ -627,6 +640,25 @@ tbody .color-priority-muted *{
|
|
|
627
640
|
border: none !important;
|
|
628
641
|
}
|
|
629
642
|
|
|
643
|
+
.steedos-instance-style-table .instance-form .td-childfield {
|
|
644
|
+
padding: 0 !important;
|
|
645
|
+
border: 1px solid black !important;
|
|
646
|
+
}
|
|
647
|
+
.steedos-instance-style-table .instance-form .td-childfield .antd-Table{
|
|
648
|
+
margin-bottom: 0px !important;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
.steedos-instance-style-table .instance-form .td-childfield .antd-Table .antd-Table-operationCell {
|
|
652
|
+
border: none !important;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
.steedos-instance-style-table .instance-form .td-childfield .antd-Table td:first-child {
|
|
656
|
+
border-right: none !important;
|
|
657
|
+
}
|
|
658
|
+
.steedos-instance-style-table .antd-Select-value{
|
|
659
|
+
white-space: unset !important;
|
|
660
|
+
}
|
|
661
|
+
|
|
630
662
|
|
|
631
663
|
/* 1. 基础设置:合并边框并去掉表格容器的外边框 */
|
|
632
664
|
.instance-form .antd-Table-table {
|
|
@@ -751,6 +783,14 @@ tbody .color-priority-muted *{
|
|
|
751
783
|
}
|
|
752
784
|
}
|
|
753
785
|
|
|
786
|
+
.antd-Combo-form .antd-Form-row .antd-Form-col{
|
|
787
|
+
margin-bottom: 0.75rem !important;
|
|
788
|
+
}
|
|
789
|
+
.antd-Combo-form .antd-Form-row .antd-Form-col .antd-Form-rowInner > div{
|
|
790
|
+
flex: 1;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
|
|
754
794
|
/* .steedos-instance-detail-wrapper{
|
|
755
795
|
height: auto !important;
|
|
756
796
|
}
|
|
@@ -28,6 +28,22 @@ function getFieldLabel(fieldDef, fieldName) {
|
|
|
28
28
|
return fieldName;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
const getArgumentsList = (func)=>{
|
|
32
|
+
let funcString;
|
|
33
|
+
if (typeof func === 'function') {
|
|
34
|
+
funcString = func.toString();
|
|
35
|
+
} else {
|
|
36
|
+
funcString = func;
|
|
37
|
+
}
|
|
38
|
+
const regExp = /function\s*\w*\(([\s\S]*?)\)/;
|
|
39
|
+
if (regExp.test(funcString)) {
|
|
40
|
+
const argList = RegExp.$1.split(',');
|
|
41
|
+
return argList.map(arg => arg.replace(/\s/g, ''));
|
|
42
|
+
} else {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
31
47
|
function fieldToAmis(fieldName, fieldDef, schema, isColumn = false, isPrint = false) {
|
|
32
48
|
// Handle section type special case
|
|
33
49
|
if (fieldDef && fieldDef.type === 'section') {
|
|
@@ -85,6 +101,126 @@ function fieldToAmis(fieldName, fieldDef, schema, isColumn = false, isPrint = fa
|
|
|
85
101
|
case 'checkbox': type = 'checkboxes'; break;
|
|
86
102
|
case 'select': type = 'select'; break;
|
|
87
103
|
case 'lookup': type = 'select'; break; // Simplified for now
|
|
104
|
+
case 'odata':
|
|
105
|
+
type = 'select';
|
|
106
|
+
const field = fieldDef;
|
|
107
|
+
const inTable = isColumn;
|
|
108
|
+
const argsName = getArgumentsList(field.filters);
|
|
109
|
+
let labelField = field.formula ? field.formula.substr(1, field.formula.length - 2) : 'name';
|
|
110
|
+
if(labelField.indexOf(".") > -1){
|
|
111
|
+
labelField = labelField.substr(labelField.indexOf(".") + 1);
|
|
112
|
+
}
|
|
113
|
+
config.multiple = field.is_multiselect;
|
|
114
|
+
|
|
115
|
+
// Compress script to single line to avoid JSON parsing issues with control characters
|
|
116
|
+
const adaptorScript = `
|
|
117
|
+
return (async () => {
|
|
118
|
+
let options = _.map(payload.value, (item)=>{
|
|
119
|
+
const value = item;
|
|
120
|
+
item["@label"] = item["${labelField}"];
|
|
121
|
+
delete item['@odata.editLink'];
|
|
122
|
+
delete item['@odata.etag'];
|
|
123
|
+
delete item['@odata.id'];
|
|
124
|
+
return {
|
|
125
|
+
label: item["@label"],
|
|
126
|
+
value: value
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
if(api.selectedIds && api.selectedIds.length > 0){
|
|
131
|
+
const loadedIds = options.map(function(opt){ return opt.value._id; });
|
|
132
|
+
const missingIds = api.selectedIds.filter(function(id){ return !loadedIds.includes(id); });
|
|
133
|
+
if(missingIds.length > 0){
|
|
134
|
+
const baseUrl = api.baseUrl;
|
|
135
|
+
const idFilter = missingIds.map(function(id){ return "_id eq '" + id + "'"; }).join(" or ");
|
|
136
|
+
const fetchUrl = baseUrl + (baseUrl.indexOf('?') > -1 ? '&' : '?') + "$filter=" + idFilter;
|
|
137
|
+
try {
|
|
138
|
+
const response = await fetch(fetchUrl, {});
|
|
139
|
+
const data = await response.json();
|
|
140
|
+
if (data && data.value) {
|
|
141
|
+
const missingOptions = _.map(data.value, (item) => {
|
|
142
|
+
const value = item;
|
|
143
|
+
item["@label"] = item["${labelField}"];
|
|
144
|
+
delete item['@odata.editLink'];
|
|
145
|
+
delete item['@odata.etag'];
|
|
146
|
+
delete item['@odata.id'];
|
|
147
|
+
return { label: item["@label"], value: value };
|
|
148
|
+
});
|
|
149
|
+
options.unshift(...missingOptions);
|
|
150
|
+
}
|
|
151
|
+
} catch (e) {
|
|
152
|
+
console.error("Failed to fetch missing values", e);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
payload.data = { options: options };
|
|
157
|
+
return payload;
|
|
158
|
+
})();
|
|
159
|
+
`.replace(/\s+/g, ' ');
|
|
160
|
+
|
|
161
|
+
const filtersStr = field.filters ? _.replace(field.filters, /_.pluck/g, '_.map') : '';
|
|
162
|
+
const requestAdaptorScript = `
|
|
163
|
+
const filters = \`${filtersStr}\`;
|
|
164
|
+
let url = \`${field.url}\`;
|
|
165
|
+
api.baseUrl = url;
|
|
166
|
+
if(filters){
|
|
167
|
+
let joinKey = url.indexOf('?') > 0 ? '&' : '?';
|
|
168
|
+
let _filter = [];
|
|
169
|
+
if(filters.startsWith('function(') || filters.startsWith('function (')){
|
|
170
|
+
const argsName = ${JSON.stringify(argsName)};
|
|
171
|
+
const fun = eval('_fun='+filters);
|
|
172
|
+
const funArgs = [];
|
|
173
|
+
for(const item of argsName){
|
|
174
|
+
funArgs.push(context[item]);
|
|
175
|
+
}
|
|
176
|
+
_filter = fun.apply({}, funArgs);
|
|
177
|
+
}else{
|
|
178
|
+
_filter = filters;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const val = context.value || _.get(context, '${field.code}');
|
|
182
|
+
let ids = [];
|
|
183
|
+
if(val){
|
|
184
|
+
const values = Array.isArray(val) ? val : [val];
|
|
185
|
+
ids = values.map((v) => v && (v._id || v)).filter((v) => typeof v === 'string');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
ids = _.uniq(ids);
|
|
189
|
+
api.selectedIds = ids;
|
|
190
|
+
|
|
191
|
+
if(context.term){
|
|
192
|
+
_filter = \`(\${_filter}) and contains(name, '\${context.term}')\`;
|
|
193
|
+
}
|
|
194
|
+
joinKey = url.indexOf('?') > 0 ? '&' : '?';
|
|
195
|
+
api.url = url + joinKey + "$filter=" + _filter;
|
|
196
|
+
}else{
|
|
197
|
+
api.url = url;
|
|
198
|
+
}
|
|
199
|
+
api.query = {};
|
|
200
|
+
return api;
|
|
201
|
+
`.replace(/\s+/g, ' ');
|
|
202
|
+
|
|
203
|
+
config.autoComplete = {
|
|
204
|
+
url: field.url.indexOf('?') < 0 ? `${field.url}?term=\${term}` : `${field.url}&term=\${term}`,
|
|
205
|
+
method: "get",
|
|
206
|
+
dataType: "json",
|
|
207
|
+
adaptor: adaptorScript,
|
|
208
|
+
requestAdaptor: requestAdaptorScript
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// Only add trackExpression if there are dependent fields (argsName)
|
|
212
|
+
if (argsName && argsName.length > 0) {
|
|
213
|
+
// Use simpler tracking without |json to avoid potential newline issues in stringified objects
|
|
214
|
+
config.autoComplete.trackExpression = _.join(_.map(argsName, (item) => `\${${item}}`), '-');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
config.source = _.cloneDeep(config.autoComplete);
|
|
218
|
+
// trackExpression is needed in source to react to dependency changes
|
|
219
|
+
|
|
220
|
+
if(!inTable){
|
|
221
|
+
config.searchable = true;
|
|
222
|
+
}
|
|
223
|
+
break;
|
|
88
224
|
case 'table':
|
|
89
225
|
type = 'steedos-input-table';
|
|
90
226
|
config.columnsTogglable = false;
|
|
@@ -287,7 +423,13 @@ function convertTemplate(content, fields, isPrint) {
|
|
|
287
423
|
});
|
|
288
424
|
|
|
289
425
|
// --- Sub-phase 2c: Convert afFieldLabelText ---
|
|
290
|
-
newContent = newContent.replace(/\{\{afFieldLabelText\s+name=["'](.+?)["']\}\}/g,
|
|
426
|
+
newContent = newContent.replace(/\{\{afFieldLabelText\s+name=["'](.+?)["']\}\}/g, (match, name) => {
|
|
427
|
+
const fieldDef = findFieldDef(fields, name);
|
|
428
|
+
if (fieldDef && fieldDef.is_required) {
|
|
429
|
+
return `${name}<span class="antd-Form-star" style="display: \${record.step.permissions['${name}'] == 'editable' ? 'inline' : 'none'}">*</span>`;
|
|
430
|
+
}
|
|
431
|
+
return name;
|
|
432
|
+
});
|
|
291
433
|
|
|
292
434
|
// --- Sub-phase 2d: Convert instanceSignText ---
|
|
293
435
|
newContent = newContent.replace(/\{\{>\s*instanceSignText\s+([\s\S]+?)\}\}/g, (match, args) => {
|
|
@@ -334,6 +476,14 @@ function convertTemplate(content, fields, isPrint) {
|
|
|
334
476
|
return `{% amis %}\n${JSON.stringify(amisSchema, null, 2)}\n{% endamis %}`;
|
|
335
477
|
});
|
|
336
478
|
|
|
479
|
+
// --- Sub-phase 2e: Add header for tr-child-table ---
|
|
480
|
+
// Extract dynamic title from td-childfield-xxx class if present
|
|
481
|
+
newContent = newContent.replace(/(<tr[^>]*class\s*=\s*["'][^"']*tr-child-table[^"']*["'][^>]*>[\s\S]*?class\s*=\s*["'][^"']*?td-childfield-)([^\s"']+)/gi,
|
|
482
|
+
(match, beforeName, name) => {
|
|
483
|
+
return `<tr><td colspan="10" style="background:#f1f1f1" class="font-bold">${name}</td></tr>${beforeName}${name}`;
|
|
484
|
+
}
|
|
485
|
+
);
|
|
486
|
+
|
|
337
487
|
return newContent;
|
|
338
488
|
}
|
|
339
489
|
|