@dhccmobile/vue3-lo-form 2.1.0 → 2.1.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhccmobile/vue3-lo-form",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "VUE3动态表单",
5
5
  "private": false,
6
6
  "main": "dist/vue3-lo-form.umd.js",
package/src/App.vue CHANGED
@@ -102,7 +102,7 @@
102
102
  </div>
103
103
  <div class="lo-input">
104
104
  <!--styleMode="credit-rd" :formId="'773549593606574080'"-->
105
- <dy-form v-if="showForm" :formId="'984119606230257664'" v-model:edit="formApi.edit" :formApi="formApi" @change="onChange($event)" @click="onClick($event)" @focus="onFocus($event)" @blur="onBlur($event)" @addon-before="onAddonBeforeHandler($event)" @addon-after="onAddonAfterHandler($event)" @add-item="selectAddItem($event)">
105
+ <dy-form v-if="showForm" :formId="'1153352233392410624'" v-model:edit="formApi.edit" :formApi="formApi" @change="onChange($event)" @click="onClick($event)" @focus="onFocus($event)" @blur="onBlur($event)" @addon-before="onAddonBeforeHandler($event)" @addon-after="onAddonAfterHandler($event)" @add-item="selectAddItem($event)">
106
106
  <template #combinationSelector="{ control, onChange }">
107
107
  <div class="lo-custom-control-box">
108
108
  <a-input v-model:value="control.formControl.value" @input="onChange(control.formControl)" v-if="control && control.formControl" />
@@ -45,7 +45,7 @@ export type NfFormTheme = "default" | "gray";
45
45
  },
46
46
  })
47
47
  export default class DyForm extends Vue {
48
- @Prop({ default: "刘波", type: String }) formId: string | undefined;
48
+ @Prop() formId: string | undefined;
49
49
  @Prop() mode: NfFormMode | undefined;
50
50
  @Prop({ type: String, default: "default" }) styleMode!: NfStyleMode;
51
51
  @Prop() srcDesForm: DesForm | undefined;
@@ -99,7 +99,7 @@ export default class DyForm extends Vue {
99
99
  * @date 2022/4/6 14:17
100
100
  */
101
101
  @Watch("formValidateStateResetMark")
102
- onPropFormValidateStateResetHandler(newVal: any): void {
102
+ onPropFormValidateStateResetHandler(): void {
103
103
  if ((this as any)._provided) {
104
104
  ((this as any)._provided as any).provideInjectData.formValidateStateResetMark = this.formValidateStateResetMark;
105
105
  }
@@ -116,7 +116,7 @@ export default class DyForm extends Vue {
116
116
  @Watch("metaRefresh")
117
117
  @Watch("refreshCheckFeedbackFlag")
118
118
  @Watch("widthCompatibleMode")
119
- onPropHandler(newVal: any): void {
119
+ onPropHandler(): void {
120
120
  if (this) {
121
121
  this.provideInjectData.edit = this.edit;
122
122
  this.provideInjectData.labelSpan = this.labelSpan;
@@ -129,7 +129,8 @@ export default class DyForm extends Vue {
129
129
 
130
130
  get loFormTheme(): string {
131
131
  const win: any = window;
132
- const themes = ["default", "gray"];
132
+ // 默认, 灰度, 某北某方,label换行
133
+ const themes = ["default", "gray", "nitic", "labelWrap"];
133
134
  const formTheme = themes.indexOf(this.formTheme) > -1 ? this.formTheme : win.$loFormTheme;
134
135
  return themes.indexOf(formTheme) > -1 ? formTheme : themes[0];
135
136
  }
@@ -183,8 +184,10 @@ export default class DyForm extends Vue {
183
184
  */
184
185
  private initDesForm(): void {
185
186
  if (this.formId != null && this.formId !== "") {
186
- this.desForm = formToolsService.loadResource(this.formId);
187
- this.formatDesForm();
187
+ formToolsService.initResource(this.formId).then((form: any) => {
188
+ this.desForm = form;
189
+ this.formatDesForm();
190
+ });
188
191
  }
189
192
  }
190
193
 
@@ -16,7 +16,7 @@
16
16
  :class="{
17
17
  ['form-model-item-' + controlAttr.boundProperty]: true,
18
18
  ['form-model-item-' + control.code]: true,
19
- 'lo-form-model-item-textarea-box': control.code === formFieldType.Textarea.code,
19
+ 'lo-form-model-item-textarea-box lo-theme-textarea-box': control.code === formFieldType.Textarea.code,
20
20
  'lo-form-item-mobile': isMobileBrowser(),
21
21
  }"
22
22
  >
@@ -344,6 +344,7 @@
344
344
  @focus="onFocus($event)"
345
345
  @blur="onBlur($event)"
346
346
  @addon-before="onAddonBeforeHandler($event)"
347
+ @addon-after="onAddonAfterHandler($event)"
347
348
  @add-item="selectAddItem($event)"
348
349
  @fixFormLayout="onHideControl"
349
350
  >
@@ -786,7 +787,7 @@ export default class DvFormLayout extends Vue {
786
787
  } else if (this.provideInjectData.controlSpan) {
787
788
  return this.provideInjectData.controlSpan;
788
789
  } else {
789
- return 0;
790
+ return "none";
790
791
  }
791
792
  }
792
793
 
@@ -961,6 +962,7 @@ export default class DvFormLayout extends Vue {
961
962
  for (let i = 0; i < index; i++) {
962
963
  data += "0";
963
964
  }
965
+ data = this.countDecimalPlaces(data, controlAttr.decimalPlaces);
964
966
  }
965
967
  // 金额后缀不依赖于是否设置了小数位
966
968
  if (controlAttr.zoomType !== ZoomType.automatic.code && data != null && data != "" && controlAttr.unit) {
@@ -1037,6 +1039,39 @@ export default class DvFormLayout extends Vue {
1037
1039
  return data;
1038
1040
  }
1039
1041
 
1042
+ /**
1043
+ * 数字小数位数计算
1044
+ * @author JiangTao
1045
+ * @since 2026-04-16 16:40:23
1046
+ */
1047
+ countDecimalPlaces(data: string | number, decimalPlaces: number | undefined): string {
1048
+ // 1. 安全处理
1049
+ const digits = decimalPlaces ?? 0;
1050
+ const str = String(data).trim();
1051
+ if (!str) return digits > 0 ? `0.${"0".repeat(digits)}` : "0";
1052
+
1053
+ // 2. 判断是否有小数
1054
+ const hasDot = str.includes(".");
1055
+ const intPart = hasDot ? str.split(".")[0] : str;
1056
+ const decimalPart = hasDot ? str.split(".")[1] : "";
1057
+
1058
+ // 3. 拼接成纯数字用于四舍五入计算
1059
+ const pureNumStr = intPart.replace(/,/g, "") + (hasDot ? "." + decimalPart : "");
1060
+ const num = parseFloat(pureNumStr);
1061
+ if (isNaN(num)) return intPart + (digits > 0 ? `.${"0".repeat(digits)}` : "");
1062
+
1063
+ // 4. 四舍五入保留 digits 位
1064
+ const factor = Math.pow(10, digits);
1065
+ const rounded = (Math.round(num * factor) / factor).toFixed(digits);
1066
+
1067
+ // 5. 拆分四舍五入后的整数与小数
1068
+ const [, roundedDecimal = ""] = rounded.split(".");
1069
+
1070
+ // 6. 最终结果:原始整数部分 + 处理后的小数部分
1071
+ if (digits <= 0) return intPart;
1072
+ return `${intPart}.${roundedDecimal}`;
1073
+ }
1074
+
1040
1075
  /**
1041
1076
  * @description: 支持的上传类型
1042
1077
  * @author ChenRui
package/src/main.ts CHANGED
@@ -9,8 +9,8 @@ const app = createApp(App);
9
9
  app.config.performance = true;
10
10
  app
11
11
  .use(VueLoForm, {
12
- url: "http://82.156.213.34:8080",
13
- appId: "1009549397931601920",
12
+ url: "https://portal-test.fotic.com.cn:1443/dy-form",
13
+ appId: "1144982574721011712",
14
14
  onlySimpleLoadConfig: false,
15
15
  loadMode: "dynamic",
16
16
  desApiAddr: "http://82.156.213.34:8080/ms-loong/api/v1/des-cache-info/xxx-yyy-zzz",
@@ -703,6 +703,34 @@ class FormToolsService {
703
703
  }
704
704
  }
705
705
 
706
+ initResource(formId: string): Promise<void | DesForm> {
707
+ if (this.desForms.length === 0) {
708
+ return new Promise((resolve, reject) => {
709
+ Promise.all([dictStore.getDicts(), dictStore.getTreeDicts(), dictStore.getMapDicts(), dictStore.getMapTreeDicts(), formStore.getForms()]).then(([dicts, treeDicts, mapDicts, mapTreeDicts, forms]: any[]) => {
710
+ this.desForms = forms;
711
+ this.sysDictDetailOptions = dicts;
712
+ this.sysDictTreeDetailOptions = treeDicts;
713
+ this.mapSysDictDetailOptions = mapDicts;
714
+ this.mapSysDictTreeDetailOptions = mapTreeDicts;
715
+ const desForm: DesForm | undefined = this.desForms.find((item) => item.formId === formId);
716
+ if (desForm != null) {
717
+ resolve(formBeanUtilsService.copy(desForm));
718
+ return formBeanUtilsService.copy(desForm);
719
+ } else {
720
+ reject(new DesForm({ formId: formId }));
721
+ }
722
+ });
723
+ });
724
+ } else {
725
+ const desForm: DesForm | undefined = this.desForms.find((item) => item.formId === formId);
726
+ if (desForm != null) {
727
+ return Promise.resolve(formBeanUtilsService.copy(desForm));
728
+ } else {
729
+ return Promise.reject(new DesForm({ formId: formId }));
730
+ }
731
+ }
732
+ }
733
+
706
734
  /**
707
735
  * @description: rest客户端
708
736
  * @author ChenRui
@@ -193,3 +193,9 @@
193
193
  .ant-select-arrow {
194
194
  z-index: 10;
195
195
  }
196
+ /** 下拉框占位符的样式 */
197
+ .ant-select-selection-placeholder {
198
+ display: flex !important;
199
+ align-items: center !important;
200
+ justify-content: start;
201
+ }
@@ -0,0 +1,371 @@
1
+ .ant-form-horizontal {
2
+ .lo-control-container {
3
+ /**非编辑状态下的样式*/
4
+ .is-disable-input {
5
+ :deep(.ant-form-item-control) {
6
+ border-radius: 5px;
7
+ border: rgba(229,229,229, 0.7) 1px solid;
8
+ }
9
+ }
10
+ .lo-control-box {
11
+ .ant-form-item {
12
+ display: flex;
13
+ flex-direction: row;
14
+ height: 100%;
15
+ :deep {
16
+ .ant-form-item-control {
17
+ min-height: 40px;
18
+ //box-shadow: 0 0 0 1px rgba(229,229,229, 0.5);
19
+ margin-top: 1px;
20
+ }
21
+ .ant-form-item-label {
22
+ position: relative;
23
+ //box-shadow: 0 0 0 1px #fff;
24
+ background-color: transparent;
25
+ z-index: 1;
26
+ label {
27
+ display: block;
28
+ width: 100%;
29
+ height: auto;
30
+ white-space: pre-wrap;
31
+ word-break: break-all;
32
+ line-height: normal;
33
+ padding: 8px 0;
34
+ }
35
+ }
36
+ .ant-input,
37
+ .ant-input-affix-wrapper,
38
+ .ant-select-selector,
39
+ .ant-picker,
40
+ .ant-btn,
41
+ .ant-input-number {
42
+ border-radius: .5rem;
43
+ min-height: 40px;
44
+ max-height: 40px;
45
+ padding: 0 6px;
46
+ height: 100%;
47
+ color: #333333;
48
+ }
49
+ .ant-input-number-input, input[type=search] {
50
+ min-height: 40px;
51
+ padding: 0;
52
+ height: 100%;
53
+ color: #333333;
54
+ }
55
+ .ant-input-number-group,
56
+ .ant-input-number-group-wrapper,
57
+ .ant-input-number-input-wrap {
58
+ width: 100%;
59
+ height: 100%;
60
+ }
61
+ .ant-picker-input > input {
62
+ color: #333333;
63
+ }
64
+ .ant-radio-group {
65
+ padding: 0 6px;
66
+ margin: auto 0;
67
+ }
68
+ .ant-checkbox-group {
69
+ padding: 8px 6px;
70
+ }
71
+ .ant-picker-suffix, .ant-select-arrow {
72
+ width: 40px;
73
+ }
74
+ .ant-picker-suffix {
75
+ text-align: center;
76
+ margin-right: -6px;
77
+ }
78
+ .ant-select-arrow {
79
+ display: flex;
80
+ align-items: center;
81
+ justify-content: center;
82
+ height: 100%;
83
+ top: 5px;
84
+ right: 0;
85
+ z-index: 10;
86
+ }
87
+ .ant-form-item-control-input-content {
88
+ display: flex;
89
+ align-items: center;
90
+ }
91
+ .ant-form-item-control-input, .ant-form-item-control-input-content {
92
+ height: 100%;
93
+ align-items: center;
94
+ }
95
+ .ant-input:focus,
96
+ .ant-input-number-focused,
97
+ .ant-picker-focused,
98
+ .ant-select-focused:not(.ant-select-disabled).ant-select:not(.ant-select-customize-input) .ant-select-selector {
99
+ box-shadow: 0 0 0 1px #4094f3;
100
+ z-index: 10;
101
+ }
102
+ .ant-select-disabled.ant-select:not(.ant-select-customize-input) .ant-select-selector,
103
+ .ant-picker-input > input[disabled],
104
+ .ant-input-number-disabled,
105
+ .ant-input[disabled] {
106
+ color: #666666;
107
+ background-color: #fbfbfb;
108
+ }
109
+ .ant-picker-disabled {
110
+ background-color: #fbfbfb;
111
+ }
112
+ .ant-form-item-explain-error {
113
+ line-height: 24px;
114
+ color: #ff2d4b;
115
+ font-size: 12px;
116
+ padding: 0 6px;
117
+ background: rgba(255, 45, 75, 0.2)
118
+ }
119
+ .ant-select-selection-item {
120
+ display: inline-flex;
121
+ align-items: center;
122
+ }
123
+ .ant-select-selection-overflow {
124
+ padding-right: 40px;
125
+ }
126
+ .ant-select-multiple {
127
+ .ant-select-selection-search {
128
+ margin-start: 0;
129
+ margin-inline-start: 0;
130
+ }
131
+ .ant-select-selection-placeholder {
132
+ left: 6px;
133
+ right: 40px;
134
+ }
135
+ }
136
+ .ant-select-single {
137
+ .ant-select-selection-item,
138
+ .ant-select-selection-search {
139
+ position: absolute;
140
+ left: 6px;
141
+ right: 40px;
142
+ top: 0;
143
+ bottom: 0;
144
+ }
145
+ }
146
+ }
147
+ }
148
+ :deep .ant-form-item-has-error {
149
+ .ant-input:focus,
150
+ .ant-input-number-focused,
151
+ .ant-picker-focused,
152
+ .ant-select-focused:not(.ant-select-disabled).ant-select:not(.ant-select-customize-input) .ant-select-selector {
153
+ box-shadow: 0 0 0 1px #ff194c;
154
+ color: #ff194c;
155
+ z-index: 10;
156
+ }
157
+ }
158
+ }
159
+ }
160
+ }
161
+ .lo-control-container {
162
+ box-sizing: border-box;
163
+ margin-bottom: 1.5rem;
164
+ .lo-control-box {
165
+ height: 100%;
166
+ .ant-form-item {
167
+ margin-bottom: 0;
168
+ .lo-select {
169
+ :deep {
170
+ .ant-select-selection-selected-value {
171
+ width: 100%;
172
+ white-space: nowrap;
173
+ text-overflow: ellipsis;
174
+ overflow: hidden;
175
+ word-break: break-all;
176
+ }
177
+ }
178
+ &.lo-select-multiple-suffix-icon {
179
+ :deep {
180
+ .ant-select-arrow {
181
+ margin: 0;
182
+ height: 100%;
183
+ top: 0;
184
+ right: 0;
185
+ width: fit-content;
186
+ .ant-select-arrow-icon {
187
+ height: 100%;
188
+ display: flex;
189
+ align-items: center;
190
+ }
191
+ }
192
+ }
193
+ }
194
+ }
195
+ .lo-label-sub-type-icon {
196
+ color: #3fb5eb;
197
+ cursor: pointer;
198
+ margin-left: 4px;
199
+ margin-bottom: 3px;
200
+ display: inline-block;
201
+ :deep {
202
+ svg {
203
+ display: inline-block;
204
+ margin-bottom: -2.5px;
205
+ }
206
+ }
207
+ }
208
+ .lo-label-history-icon {
209
+ display: inline-block;
210
+ line-height: 0;
211
+ margin-left: 4px;
212
+ margin-bottom: 3px;
213
+ cursor: pointer;
214
+ font-size: 14px;
215
+ }
216
+ .lo-label-tips-icon {
217
+ color: #4094f3;
218
+ cursor: pointer;
219
+ font-size: 14px !important;
220
+ margin-left: 4px;
221
+ }
222
+ :deep {
223
+ .ant-form-item-label {
224
+ label {
225
+ color: #333333;
226
+ }
227
+ }
228
+ .ant-form-item-control-wrapper {
229
+ flex-grow: 1;
230
+ color: #333333;
231
+ }
232
+ }
233
+ :deep {
234
+ .ant-input-group-addon, .ant-input-number-group-addon {
235
+ width: 40px;
236
+ min-height: 38px;
237
+ position: absolute;
238
+ right: 2px;
239
+ top: 1px;
240
+ border: none;
241
+ z-index: 999;
242
+ &:active {
243
+ opacity: .7;
244
+ }
245
+ }
246
+ }
247
+ .addon-icon {
248
+ display: flex;
249
+ align-items: center;
250
+ justify-content: center;
251
+ width: 100%;
252
+ height: 100%;
253
+ font-size: 15px;
254
+ cursor: pointer;
255
+ background-color: #fff;
256
+ }
257
+ .addon-inner {
258
+ display: flex;
259
+ align-items: center;
260
+ justify-content: center;
261
+ position: absolute;
262
+ width: 100%;
263
+ height: 100%;
264
+ top: 0;
265
+ left: 0;
266
+ cursor: pointer;
267
+ color: #999999;
268
+ background-color: #f2f2f2;
269
+ }
270
+ .addon-inner:active {
271
+ background: rgba(240, 240, 240, 0.3);
272
+ }
273
+ }
274
+ .lo-textarea-count {
275
+ position: absolute;
276
+ line-height: 10px;
277
+ right: 0;
278
+ color: rgba(0, 0, 0, 0.45);
279
+ }
280
+ .lo-input-number-box {
281
+ width: 100%;
282
+ :deep {
283
+ .ant-input-number {
284
+ width: 100%;
285
+ }
286
+ }
287
+ &.lo-with-unit {
288
+ :deep {
289
+ .ant-input-number {
290
+ border-top-right-radius: 0;
291
+ border-bottom-right-radius: 0;
292
+ border-right: 0;
293
+ .ant-input-number-handler-wrap {
294
+ border-top-right-radius: 0;
295
+ border-bottom-right-radius: 0;
296
+ opacity: 1;
297
+ }
298
+ }
299
+ .ant-dropdown-trigger {
300
+ border-top-left-radius: 0;
301
+ border-bottom-left-radius: 0;
302
+ }
303
+ }
304
+ &.lo-unit-1 {
305
+ :deep {
306
+ .ant-input-number {
307
+ width: calc(100% - 50px);
308
+ }
309
+ .ant-dropdown-trigger {
310
+ min-width: 50px;
311
+ }
312
+ }
313
+ }
314
+ &.lo-unit-2 {
315
+ :deep {
316
+ .ant-input-number {
317
+ width: calc(100% - 80px);
318
+ }
319
+ .ant-dropdown-trigger {
320
+ min-width: 80px;
321
+ }
322
+ }
323
+ }
324
+ &.lo-unit-3 {
325
+ :deep {
326
+ .ant-input-number {
327
+ width: calc(100% - 110px);
328
+ }
329
+ .ant-dropdown-trigger {
330
+ min-width: 110px;
331
+ }
332
+ }
333
+ }
334
+ }
335
+ }
336
+ .lo-input-content {
337
+ align-items: center;
338
+ overflow: hidden;
339
+ text-overflow: ellipsis;
340
+ color: #333333;
341
+ font-size: 14px;
342
+ padding: 0 6px;
343
+ }
344
+ .lo-control-text {
345
+ white-space: pre-wrap;
346
+ word-break: break-all;
347
+ line-height: 22px;
348
+ }
349
+ }
350
+
351
+ :deep .ant-select-multiple .ant-select-selection-item {
352
+ height: 40px !important;
353
+ margin: 0 4px 0 0 !important;
354
+ }
355
+ }
356
+ .lo-empty-layout-container {
357
+ box-sizing: border-box;
358
+ display: grid;
359
+ border: none;
360
+ }
361
+ .lo-general-layout-container {
362
+ box-sizing: border-box;
363
+ display: grid;
364
+ grid-column-start: 1;
365
+ }
366
+ :deep .ant-form-item-label > label.ant-form-item-no-colon::after {
367
+ display: none;
368
+ }
369
+ .ant-input-textarea {
370
+ width: 100%;
371
+ }