free-fe-core-modules 0.1.10 → 0.1.12

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.
@@ -101,11 +101,40 @@
101
101
 
102
102
  <script>
103
103
  import { computed, defineComponent, getCurrentInstance, ref } from 'vue';
104
+ import { useRoute } from 'vue-router';
104
105
  import { useFreeField, freeFieldProps } from '../composible/useFreeField.js';
105
106
  import { useFormValidator} from '../../composible/useFormValidator.js';
106
107
  import { useUploader } from '../composible/useUploader.js';
107
108
  import PdfViewer from './pdfviewer.js';
108
109
 
110
+ function parseStaticResourceParams(paramStr, route) {
111
+ if (!paramStr || paramStr.trim().length <= 0) {
112
+ return '';
113
+ }
114
+
115
+ let finalParamStr = paramStr || '';
116
+
117
+ const paramList = paramStr.match(/\{[^\}]+\}/g);
118
+ const paramValuesMap = {};
119
+ for (let i = 0; i < paramList.length; i += 1) {
120
+ const varItem = paramList[i];
121
+ if (paramValuesMap[varItem]) {
122
+ continue;
123
+ }
124
+
125
+ const varName = varItem.replace('{', '').replace('}', '');
126
+ const varValue = Object.nestValue(route, varName) || '';
127
+
128
+ console.log('varName, varValue', varName, varValue);
129
+
130
+ finalParamStr = finalParamStr.replace(new RegExp(varItem, 'g'), varValue);
131
+
132
+ paramValuesMap[varItem] = 1;
133
+ }
134
+
135
+ return finalParamStr;
136
+ }
137
+
109
138
  export default defineComponent({
110
139
  name: 'InputFieldFile',
111
140
  props: {
@@ -146,6 +175,27 @@ export default defineComponent({
146
175
  Name: 'Options.PdfViewerVersion',
147
176
  Default: '',
148
177
  },
178
+ {
179
+ Type: 'String',
180
+ Label: '可访问用户',
181
+ Name: 'Options.staticResourceUsers',
182
+ Placeholder: '逗号分隔的用户ID列表,self表示当前用户,比如:user1ID,self,user3ID',
183
+ Default: '',
184
+ },
185
+ {
186
+ Type: 'String',
187
+ Label: '可访问来源',
188
+ Name: 'Options.staticResourceReferers',
189
+ Placeholder: '逗号分隔的来源列表,支持正则表达式。比如:/admin/f/case/{params.id}/(2|3|4|5)',
190
+ Default: '',
191
+ },
192
+ {
193
+ Type: 'String',
194
+ Label: '所需权限',
195
+ Name: 'Options.staticResourcePerms',
196
+ Placeholder: '逗号分隔的API路径列表,不支持正则表达式!比如:/api/case/{params.id}/2/view,/api/case/{params.id}/3/view',
197
+ Default: '',
198
+ },
149
199
  ],
150
200
  Description: '',
151
201
  },
@@ -194,10 +244,28 @@ export default defineComponent({
194
244
  return isValid;
195
245
  };
196
246
 
247
+ const route = useRoute();
197
248
  const factoryFn = () => {
249
+ // 静态资源访问权限控制
250
+ const {staticResourcePerms, staticResourceReferers, staticResourceUsers} = props.Field.Options || {};
251
+
198
252
  return {
199
253
  url: props.Field.url || `${vm.ctx.config.baseUrl}/upload`,
200
254
  fieldName: 'file',
255
+ formFields: [
256
+ {
257
+ name: 'users',
258
+ value: staticResourceUsers || '',
259
+ },
260
+ {
261
+ name: 'perms',
262
+ value: parseStaticResourceParams(staticResourcePerms, route) || '',
263
+ },
264
+ {
265
+ name: 'refs',
266
+ value: parseStaticResourceParams(staticResourceReferers, route) || '',
267
+ }
268
+ ],
201
269
  };
202
270
  };
203
271
 
@@ -123,11 +123,40 @@
123
123
 
124
124
  <script>
125
125
  import { computed, defineComponent, getCurrentInstance, ref } from 'vue';
126
+ import { useRoute } from 'vue-router';
126
127
  import { useFreeField, freeFieldProps } from '../composible/useFreeField.js';
127
128
  import { useFormValidator} from '../../composible/useFormValidator.js';
128
129
  import { useUploader } from '../composible/useUploader.js';
129
130
  import PdfViewer from './pdfviewer.js';
130
131
 
132
+ function parseStaticResourceParams(paramStr, route) {
133
+ if (!paramStr || paramStr.trim().length <= 0) {
134
+ return '';
135
+ }
136
+
137
+ let finalParamStr = paramStr || '';
138
+
139
+ const paramList = paramStr.match(/\{[^\}]+\}/g);
140
+ const paramValuesMap = {};
141
+ for (let i = 0; i < paramList.length; i += 1) {
142
+ const varItem = paramList[i];
143
+ if (paramValuesMap[varItem]) {
144
+ continue;
145
+ }
146
+
147
+ const varName = varItem.replace('{', '').replace('}', '');
148
+ const varValue = Object.nestValue(route, varName) || '';
149
+
150
+ console.log('varName, varValue', varName, varValue);
151
+
152
+ finalParamStr = finalParamStr.replace(new RegExp(varItem, 'g'), varValue);
153
+
154
+ paramValuesMap[varItem] = 1;
155
+ }
156
+
157
+ return finalParamStr;
158
+ }
159
+
131
160
  export default defineComponent({
132
161
  name: 'InputFieldFileList',
133
162
  fieldInfo: {
@@ -186,6 +215,27 @@ export default defineComponent({
186
215
  Name: 'Options.PdfViewerVersion',
187
216
  Default: '',
188
217
  },
218
+ {
219
+ Type: 'String',
220
+ Label: '可访问用户',
221
+ Name: 'Options.staticResourceUsers',
222
+ Placeholder: '逗号分隔的用户ID列表,self表示当前用户,比如:user1ID,self,user3ID',
223
+ Default: '',
224
+ },
225
+ {
226
+ Type: 'String',
227
+ Label: '可访问来源',
228
+ Name: 'Options.staticResourceReferers',
229
+ Placeholder: '逗号分隔的来源列表,支持正则表达式。比如:/admin/f/case/{params.id}/(2|3|4|5)',
230
+ Default: '',
231
+ },
232
+ {
233
+ Type: 'String',
234
+ Label: '所需权限',
235
+ Name: 'Options.staticResourcePerms',
236
+ Placeholder: '逗号分隔的API路径列表,不支持正则表达式!比如:/api/case/{params.id}/2/view,/api/case/{params.id}/3/view',
237
+ Default: '',
238
+ },
189
239
  ],
190
240
  Description: '',
191
241
  },
@@ -238,10 +288,28 @@ export default defineComponent({
238
288
  return isValid;
239
289
  };
240
290
 
291
+ const route = useRoute();
241
292
  const factoryFn = () => {
293
+ // 静态资源访问权限控制
294
+ const {staticResourcePerms, staticResourceReferers, staticResourceUsers} = props.Field.Options || {};
295
+
242
296
  return {
243
297
  url: props.Field.url || `${vm.ctx.config.baseUrl}/upload`,
244
298
  fieldName: 'file',
299
+ formFields: [
300
+ {
301
+ name: 'users',
302
+ value: staticResourceUsers || '',
303
+ },
304
+ {
305
+ name: 'perms',
306
+ value: parseStaticResourceParams(staticResourcePerms, route) || '',
307
+ },
308
+ {
309
+ name: 'refs',
310
+ value: parseStaticResourceParams(staticResourceReferers, route) || '',
311
+ }
312
+ ],
245
313
  };
246
314
  };
247
315
 
@@ -111,10 +111,39 @@
111
111
 
112
112
  <script>
113
113
  import { defineComponent, getCurrentInstance, ref } from 'vue';
114
+ import { useRoute } from 'vue-router';
114
115
  import { useFreeField, freeFieldProps } from '../composible/useFreeField.js';
115
116
  import { useFormValidator} from '../../composible/useFormValidator.js';
116
117
  import { useUploader } from '../composible/useUploader.js';
117
118
 
119
+ function parseStaticResourceParams(paramStr, route) {
120
+ if (!paramStr || paramStr.trim().length <= 0) {
121
+ return '';
122
+ }
123
+
124
+ let finalParamStr = paramStr || '';
125
+
126
+ const paramList = paramStr.match(/\{[^\}]+\}/g);
127
+ const paramValuesMap = {};
128
+ for (let i = 0; i < paramList.length; i += 1) {
129
+ const varItem = paramList[i];
130
+ if (paramValuesMap[varItem]) {
131
+ continue;
132
+ }
133
+
134
+ const varName = varItem.replace('{', '').replace('}', '');
135
+ const varValue = Object.nestValue(route, varName) || '';
136
+
137
+ console.log('varName, varValue', varName, varValue);
138
+
139
+ finalParamStr = finalParamStr.replace(new RegExp(varItem, 'g'), varValue);
140
+
141
+ paramValuesMap[varItem] = 1;
142
+ }
143
+
144
+ return finalParamStr;
145
+ }
146
+
118
147
  export default defineComponent({
119
148
  name: 'InputFieldImage',
120
149
  fieldInfo: {
@@ -140,6 +169,27 @@ export default defineComponent({
140
169
  Label: '不使用缩略图',
141
170
  Name: 'Options.NoThumb',
142
171
  },
172
+ {
173
+ Type: 'String',
174
+ Label: '可访问用户',
175
+ Name: 'Options.staticResourceUsers',
176
+ Placeholder: '逗号分隔的用户ID列表,self表示当前用户,比如:user1ID,self,user3ID',
177
+ Default: '',
178
+ },
179
+ {
180
+ Type: 'String',
181
+ Label: '可访问来源',
182
+ Name: 'Options.staticResourceReferers',
183
+ Placeholder: '逗号分隔的来源列表,支持正则表达式。比如:/admin/f/case/{params.id}/(2|3|4|5)',
184
+ Default: '',
185
+ },
186
+ {
187
+ Type: 'String',
188
+ Label: '所需权限',
189
+ Name: 'Options.staticResourcePerms',
190
+ Placeholder: '逗号分隔的API路径列表,不支持正则表达式!比如:/api/case/{params.id}/2/view,/api/case/{params.id}/3/view',
191
+ Default: '',
192
+ },
143
193
  ],
144
194
  Description: '',
145
195
  },
@@ -190,10 +240,28 @@ export default defineComponent({
190
240
  return isValid;
191
241
  };
192
242
 
243
+ const route = useRoute();
193
244
  const factoryFn = () => {
245
+ // 静态资源访问权限控制
246
+ const {staticResourcePerms, staticResourceReferers, staticResourceUsers} = props.Field.Options || {};
247
+
194
248
  return {
195
249
  url: props.Field.url || `${vm.ctx.config.baseUrl}/upload`,
196
250
  fieldName: 'file',
251
+ formFields: [
252
+ {
253
+ name: 'users',
254
+ value: staticResourceUsers || '',
255
+ },
256
+ {
257
+ name: 'perms',
258
+ value: parseStaticResourceParams(staticResourcePerms, route) || '',
259
+ },
260
+ {
261
+ name: 'refs',
262
+ value: parseStaticResourceParams(staticResourceReferers, route) || '',
263
+ }
264
+ ],
197
265
  };
198
266
  };
199
267
 
@@ -103,10 +103,39 @@
103
103
 
104
104
  <script>
105
105
  import { computed, defineComponent, getCurrentInstance, ref } from 'vue';
106
+ import { useRoute } from 'vue-router';
106
107
  import { useFreeField, freeFieldProps } from '../composible/useFreeField.js';
107
108
  import { useFormValidator} from '../../composible/useFormValidator.js';
108
109
  import { useUploader } from '../composible/useUploader.js';
109
110
 
111
+ function parseStaticResourceParams(paramStr, route) {
112
+ if (!paramStr || paramStr.trim().length <= 0) {
113
+ return '';
114
+ }
115
+
116
+ let finalParamStr = paramStr || '';
117
+
118
+ const paramList = paramStr.match(/\{[^\}]+\}/g);
119
+ const paramValuesMap = {};
120
+ for (let i = 0; i < paramList.length; i += 1) {
121
+ const varItem = paramList[i];
122
+ if (paramValuesMap[varItem]) {
123
+ continue;
124
+ }
125
+
126
+ const varName = varItem.replace('{', '').replace('}', '');
127
+ const varValue = Object.nestValue(route, varName) || '';
128
+
129
+ console.log('varName, varValue', varName, varValue);
130
+
131
+ finalParamStr = finalParamStr.replace(new RegExp(varItem, 'g'), varValue);
132
+
133
+ paramValuesMap[varItem] = 1;
134
+ }
135
+
136
+ return finalParamStr;
137
+ }
138
+
110
139
  export default defineComponent({
111
140
  name: 'InputFieldImageList',
112
141
  fieldInfo: {
@@ -132,6 +161,27 @@ export default defineComponent({
132
161
  Name: 'Options.MaxTotal',
133
162
  Default: '50m',
134
163
  },
164
+ {
165
+ Type: 'String',
166
+ Label: '可访问用户',
167
+ Name: 'Options.staticResourceUsers',
168
+ Placeholder: '逗号分隔的用户ID列表,self表示当前用户,比如:user1ID,self,user3ID',
169
+ Default: '',
170
+ },
171
+ {
172
+ Type: 'String',
173
+ Label: '可访问来源',
174
+ Name: 'Options.staticResourceReferers',
175
+ Placeholder: '逗号分隔的来源列表,支持正则表达式。比如:/admin/f/case/{params.id}/(2|3|4|5)',
176
+ Default: '',
177
+ },
178
+ {
179
+ Type: 'String',
180
+ Label: '所需权限',
181
+ Name: 'Options.staticResourcePerms',
182
+ Placeholder: '逗号分隔的API路径列表,不支持正则表达式!比如:/api/case/{params.id}/2/view,/api/case/{params.id}/3/view',
183
+ Default: '',
184
+ },
135
185
  ],
136
186
  Description: '',
137
187
  },
@@ -181,10 +231,28 @@ export default defineComponent({
181
231
  return isValid;
182
232
  };
183
233
 
234
+ const route = useRoute();
184
235
  const factoryFn = () => {
236
+ // 静态资源访问权限控制
237
+ const {staticResourcePerms, staticResourceReferers, staticResourceUsers} = props.Field.Options || {};
238
+
185
239
  return {
186
240
  url: props.Field.url || `${vm.ctx.config.baseUrl}/upload`,
187
241
  fieldName: 'file',
242
+ formFields: [
243
+ {
244
+ name: 'users',
245
+ value: staticResourceUsers || '',
246
+ },
247
+ {
248
+ name: 'perms',
249
+ value: parseStaticResourceParams(staticResourcePerms, route) || '',
250
+ },
251
+ {
252
+ name: 'refs',
253
+ value: parseStaticResourceParams(staticResourceReferers, route) || '',
254
+ }
255
+ ],
188
256
  };
189
257
  };
190
258
 
@@ -53,7 +53,7 @@
53
53
  :key="fIndex"
54
54
  :Field="{...f, ReadOnly: Field.ReadOnly || f.ReadOnly}"
55
55
  :values="fieldData.value"
56
- @input="cellChanged(f)"
56
+ @input="cellChanged(f, $event)"
57
57
  ref="fieldsToValid"
58
58
  ></free-field>
59
59
  </span>
@@ -64,7 +64,7 @@
64
64
  <free-field
65
65
  :Field="{...r[rk].List[0], ReadOnly: Field.ReadOnly || r[rk].List[0].ReadOnly}"
66
66
  :values="fieldData.value"
67
- @input="cellChanged(r[rk].List[0])"
67
+ @input="cellChanged(r[rk].List[0], $event)"
68
68
  borderless
69
69
  ref="fieldToValid"
70
70
  ></free-field>
@@ -359,8 +359,10 @@ export default defineComponent({
359
359
  columns,
360
360
  summaryContent,
361
361
 
362
- cellChanged: (f) => {
362
+ cellChanged: (f, subF) => {
363
+ emit('input', subF);
363
364
  emit('input', f);
365
+ // emit('input'); // we have this in v2.0, is it necessary?
364
366
  },
365
367
  localRows: computed(() => {
366
368
  if (!props.Field?.Options?.Rows) return [];
@@ -58,6 +58,11 @@
58
58
  skin: isDark ? 'oxide-dark' : 'oxide',
59
59
  content_css: isDark ? 'dark' : '',
60
60
  promotion: false,
61
+ content_style: 'body[data-mce-placeholder]::before { white-space: pre-wrap; }',
62
+
63
+ convert_urls: false, // 禁止转换 URL
64
+ relative_urls: false, // 禁止使用相对 URL
65
+ remove_script_host: false // 保留主机名
61
66
  }"
62
67
  initial-value
63
68
  model-events
@@ -366,7 +371,7 @@ export default defineComponent({
366
371
  },
367
372
  }).then((res) => {
368
373
  if (res && res.data && res.data.id) {
369
- resolve(`${vm.ctx.config.imageUrlBase}${res.data.id}`);
374
+ resolve(`${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ''}${this.ctx.config.imageUrlBase}${res.data.id}${this.Field.Options?.UploadedImageUrlArgs || ''}`);
370
375
  } else {
371
376
  reject({
372
377
  message: '上传失败',
@@ -2,7 +2,7 @@
2
2
  <div class="free-field-row row" :class="rowClasses" v-if="Field">
3
3
  <free-field
4
4
  v-for="(field, idx) in Field.Options?.Fields"
5
- :Field="field"
5
+ :Field="{...field, ReadOnly: Field.ReadOnly || field.ReadOnly}"
6
6
  :values="fieldData.value"
7
7
  :key="idx"
8
8
  ref="fieldsToValidate"
@@ -60,6 +60,19 @@
60
60
  </template>
61
61
  </q-select>
62
62
  <slot name="warning"></slot>
63
+ <div v-if="selectedOptionsExtra.length">
64
+ <free-field
65
+ @click.stop
66
+ @keydown.stop
67
+ @keypress.stop
68
+ @keyup.stop
69
+ @input="innerExtraFieldInput(fld)"
70
+ v-for="(fld, idx) in selectedOptionsExtra" :key="idx"
71
+ :Field="{...fld, ReadOnly: Field.ReadOnly || fld.ReadOnly}"
72
+ :values="values"
73
+ ref="fieldToValid">
74
+ </free-field>
75
+ </div>
63
76
  </span>
64
77
  <span v-else class="free-field-select-ascheck row items-start no-wrap">
65
78
  <span :class="`field-label ${(Field.Label && Field.Label.trim().length)
@@ -77,20 +90,51 @@
77
90
  <div class="free-field--error-tag" v-if="hasError">
78
91
  <e-icon name="error"></e-icon>
79
92
  </div>
80
- <q-checkbox v-for="(option, index) in Field.Options" :class="{
81
- checked: checked.includes(option.Value),
82
- 'with-inner-extra': option.InnerExtra?.length,
83
- }" :key="index" hide-bottom-space :label="option.Label || ''" v-model="checked" :val="option.Value"
84
- :disable="Field.ReadOnly" @update:modelValue="checkChanged(option.Value)"
85
- :checked-icon="checkedIcon(option)">
86
- <q-tooltip v-if="option.opt?.Tooltip" anchor="bottom middle">
87
- {{ $t(option.opt.Tooltip) || '' }}
88
- </q-tooltip>
89
- <div class="option-inner-extra" v-if="option.InnerExtra?.length">
90
- <free-field v-for="(fld, idx) in option.InnerExtra || []" :key="idx" :Field="fld"
91
- :values="data"></free-field>
92
- </div>
93
- </q-checkbox>
93
+
94
+ <div
95
+ class="option-item"
96
+ :class="{
97
+ padding: option.opt?.PaddingLeft,
98
+ }"
99
+ v-for="(option, index) in Field.Options"
100
+ :key="index" >
101
+
102
+ <div
103
+ class="just-a-label"
104
+ v-if="option.opt?.asLabel">{{ option.Label }}</div>
105
+
106
+ <q-checkbox
107
+ v-else
108
+ :class="{
109
+ checked: checked.includes(option.Value),
110
+ 'with-inner-extra': option.InnerExtra?.length,
111
+ }"
112
+ hide-bottom-space
113
+ :label="option.Label || ''"
114
+ v-model="checked"
115
+ :val="option.Value"
116
+ :disable="Field.ReadOnly"
117
+ @update:modelValue="checkChanged(option.Value)"
118
+ :checked-icon="checkedIcon(option)">
119
+ <q-tooltip v-if="option.opt?.Tooltip" anchor="bottom middle">
120
+ {{ $t(option.opt.Tooltip) || '' }}
121
+ </q-tooltip>
122
+ <div class="option-inner-extra"
123
+ v-if="(fieldData === option?.Value || (fieldData && fieldData.indexOf && (fieldData.indexOf(option?.Value) >= 0))) && option.InnerExtra?.length">
124
+ <free-field
125
+ @click.stop
126
+ @keydown.stop
127
+ @keypress.stop
128
+ @keyup.stop
129
+ @input="innerExtraFieldInput(fld)"
130
+ v-for="(fld, idx) in option.InnerExtra || []" :key="idx"
131
+ :Field="{...fld, ReadOnly: Field.ReadOnly || fld.ReadOnly}"
132
+ :values="values"
133
+ ref="fieldToValid">
134
+ </free-field>
135
+ </div>
136
+ </q-checkbox>
137
+ </div>
94
138
  </div>
95
139
  </span>
96
140
  </span>
@@ -288,6 +332,7 @@ export default defineComponent({
288
332
  (valueList || []).forEach((vl) => {
289
333
  const theOpt = props.Field.Options.find((opt) => opt.Value === vl);
290
334
  if (theOpt) labelList.push(theOpt.Label || fieldData.value);
335
+ else labelList.push(vl);
291
336
  });
292
337
 
293
338
  return labelList.join(',');
@@ -414,10 +459,26 @@ export default defineComponent({
414
459
 
415
460
  const localOptions = ref(props.Field.Options || []);
416
461
 
462
+ const selectedOptionsExtra = computed(() => {
463
+ let opts = [];
464
+ if (fieldData.value) {
465
+ if (props.Field.Multiple) {
466
+ const vals = Array.isArray(fieldData.value) ? fieldData.value : (`${fieldData.value}`).split(',');
467
+ opts = (localOptions.value || []).filter((opt) => vals.indexOf(opt.Value) >= 0);
468
+ }
469
+
470
+ opts = (localOptions.value || []).filter((opt) => opt.Value === fieldData.value);
471
+ }
472
+
473
+ return opts.map((opt) => opt.Extra).flat();
474
+ });
475
+
476
+
417
477
  return {
418
478
  fieldData,
419
479
  setFieldData,
420
480
  localOptions,
481
+ selectedOptionsExtra,
421
482
 
422
483
  hasError,
423
484
  checked,
@@ -448,6 +509,11 @@ export default defineComponent({
448
509
  });
449
510
  })
450
511
  },
512
+
513
+ innerExtraFieldInput: (fld) => {
514
+ selfValidate();
515
+ emit('input', fld);
516
+ },
451
517
  };
452
518
  },
453
519
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "free-fe-core-modules",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "main": "index.js",
5
5
  "repository": "https://github.com/freeeis/free-fe-core-modules.git",
6
6
  "author": "zhiquan",