@neatui/nuxt 0.1.0 → 1.0.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.
Files changed (85) hide show
  1. package/BUILD.md +128 -0
  2. package/IMPORT_GUIDE.md +142 -0
  3. package/README.md +98 -1
  4. package/SSR_COMPATIBILITY.md +201 -0
  5. package/USAGE.md +291 -0
  6. package/nuxt.config.example.ts +37 -0
  7. package/package.json +34 -11
  8. package/src/components/basic/IDraggable.vue +87 -65
  9. package/src/components/basic/IFollowView.vue +32 -23
  10. package/src/components/basic/IRouterView.vue +38 -23
  11. package/src/components/basic/IScrollView.vue +11 -7
  12. package/src/components/basic/Icon.vue +17 -17
  13. package/src/components/basic/LayerView/Layer.vue +33 -106
  14. package/src/components/basic/follow.ts +133 -0
  15. package/src/components/display/Calendar.vue +14 -14
  16. package/src/components/display/CalendarReg.vue +14 -14
  17. package/src/components/display/Image.vue +8 -8
  18. package/src/components/display/PhotoEditor.vue +36 -36
  19. package/src/components/display/PhotoViewer.vue +8 -8
  20. package/src/components/display/Tree.vue +6 -6
  21. package/src/components/display/TreeView.vue +4 -4
  22. package/src/components/display/index.ts +2 -2
  23. package/src/components/form/Cascader.vue +19 -19
  24. package/src/components/form/Checkbox.vue +64 -0
  25. package/src/components/form/DatePicker.vue +6 -7
  26. package/src/components/form/DateRangePicker@v3.vue +4 -4
  27. package/src/components/form/DateRangeView@v3.vue +18 -19
  28. package/src/components/form/DateView.vue +14 -14
  29. package/src/components/form/DateView@v2.vue +14 -14
  30. package/src/components/form/DateView@v3.vue +331 -318
  31. package/src/components/form/ImgUpload.vue +7 -7
  32. package/src/components/form/Input@v3.vue +11 -11
  33. package/src/components/form/MoreSelect@v3.vue +87 -17
  34. package/src/components/form/MoreSelectList.vue +8 -8
  35. package/src/components/form/MoreSelectPanel@v3.vue +3 -3
  36. package/src/components/form/MoreSelectPicker.vue +7 -7
  37. package/src/components/form/MoreSelectTags.vue +8 -8
  38. package/src/components/form/PageMoreSelect.vue +14 -14
  39. package/src/components/form/PageSelect.vue +16 -16
  40. package/src/components/form/SearchMoreSelect.vue +12 -12
  41. package/src/components/form/SearchSelect@v3.vue +3 -3
  42. package/src/components/form/Select@v3.vue +229 -23
  43. package/src/components/form/SelectList.vue +8 -8
  44. package/src/components/form/SelectPicker.vue +6 -6
  45. package/src/components/form/SelectTags.vue +7 -7
  46. package/src/components/form/SelectTree/SelectTree@v1.vue +5 -5
  47. package/src/components/form/Switch.vue +38 -103
  48. package/src/components/form/TextArea.vue +18 -18
  49. package/src/components/form/Textarea@v2.vue +275 -0
  50. package/src/components/form/TimeView.vue +14 -14
  51. package/src/components/form/Upload.vue +806 -297
  52. package/src/components/form/date.ts +321 -0
  53. package/src/components/form/index.ts +7 -5
  54. package/src/components/form/number.ts +3 -0
  55. package/src/components/form/type.ts +224 -0
  56. package/src/components/icon/OrderIcon.vue +113 -0
  57. package/src/components/loader/FormLoader/FormLoader@v2.vue +193 -195
  58. package/src/components/loader/FormLoader/FormLoader@v3.vue.backup +372 -291
  59. package/src/components/loader/FormLoader/FormRender@v3.vue.backup +4 -0
  60. package/src/components/loader/FormLoader/NodeLoader.vue +85 -0
  61. package/src/components/loader/FormLoader@v1/FormLoader.vue +1 -1
  62. package/src/components/loader/FormLoader@v1/FormRender.vue +49 -24
  63. package/src/components/loader/LayerLoader/LayerLoader.vue +318 -0
  64. package/src/components/loader/LayerLoader/index.ts +2 -0
  65. package/src/components/loader/LayerLoader/style.scss +77 -0
  66. package/src/components/loader/LimitLoader/LimitLoader@v3.vue +39 -28
  67. package/src/components/loader/MoveLoader/MoveLoader.vue +628 -0
  68. package/src/components/loader/MoveLoader/index.ts +2 -0
  69. package/src/components/loader/MoveLoader/style.scss +77 -0
  70. package/src/components/loader/TableLoader/TableLoader.vue +227 -195
  71. package/src/components/loader/TableLoader/TableRender.vue +141 -0
  72. package/src/components/loader/TableLoader/index.ts +47 -0
  73. package/src/components/loader/index.ts +3 -2
  74. package/src/components/tools/Pagination@a.vue +17 -18
  75. package/src/components/tools/Pagination@b.vue +16 -16
  76. package/src/index.ts +2 -1
  77. package/src/module.ts +169 -0
  78. package/src/runtime/types.d.ts +36 -0
  79. package/src/store/{myui.ts → frame.ts} +4 -4
  80. package/src/utils/theme.ts +14 -0
  81. package/tsconfig.json +1 -1
  82. package/src/components/loader/FormLoader/index.ts +0 -2
  83. package/src/components/loader/LimitLoader/LimitLoader.vue.backup +0 -131
  84. package/src/components/loader/LimitLoader/LimitLoader@v2.vue.backup +0 -174
  85. package/src/components/loader/TableLoader/TableColView.vue +0 -115
@@ -1,318 +1,399 @@
1
1
  <template>
2
- <slot>
3
- <div class="n-sl-sub" :ui-row="rows">
4
- <template v-for="(col, idx) in state.form" :key="idx">
5
- <div v-if="!col.clear" :ui-flex="`${vertical ? 'col xm' : 'row xt'}`" :id="col._fid" :ui-col="col.media" v-bind="{ ...(col.attrs || {}) }">
6
- <h5 v-if="vertical" class="o-ls" :style="`${col.rules?.some((validator:any) => validator.required)?'text-indent: -1em':''}`">
7
- <b class="co-risk pr" style="left: 0.1em" v-if="col.rules?.some((validator:any) => validator.required)">﹡</b>{{ col.label }}:
8
- </h5>
9
- <p v-else class="ar nr-sm flex-fixed o-ls" :class="`${clh({ ...(col.model[1] || {}) })}`" :style="`width:${state._lw + 'em'}; max-width:50%;`">
10
- <b class="co-risk" v-if="col.rules?.some((validator:any) => validator.required)">﹡</b>{{ col.label }}:
11
- </p>
12
- <Select
13
- v-if="col.model[0] === 'Select'"
14
- class="full-w"
15
- :interacted="interacted"
16
- :options="col.enums"
17
- v-model="col.data[col.field]"
18
- :rules="col?.rules"
19
- v-bind="{ ...(col.model[1] || {}) }"
20
- ></Select>
21
- <SelectList
22
- v-else-if="col.model[0] === 'SelectList'"
23
- class="full-w"
24
- :interacted="interacted"
25
- :options="col.enums"
26
- v-model="col.data[col.field]"
27
- :rules="col?.rules"
28
- v-bind="{ ...(col.model[1] || {}) }"
29
- />
30
- <SelectTags
31
- v-else-if="col.model[0] === 'SelectTags'"
32
- class="full-w"
33
- :interacted="interacted"
34
- :options="col.enums"
35
- v-model="col.data[col.field]"
36
- :rules="col?.rules"
37
- v-bind="{ ...(col.model[1] || {}) }"
38
- />
39
- <SelectPicker
40
- v-else-if="col.model[0] === 'SelectPicker'"
41
- class="full-w"
42
- :interacted="interacted"
43
- :options="col.enums"
44
- v-model="col.data[col.field]"
45
- :rules="col?.rules"
46
- v-bind="{ ...(col.model[1] || {}) }"
47
- />
48
- <SearchSelect
49
- v-else-if="col.model[0] === 'SearchSelect'"
50
- class="full-w"
51
- :interacted="interacted"
52
- :options="col.enums"
53
- :rules="col.rules"
54
- v-model="col.data[col.field]"
55
- v-bind="{ ...(col.model[1] || {}) }"
56
- />
57
- <MoreSelect
58
- v-else-if="col.model[0] === 'MoreSelect'"
59
- class="full-w"
60
- :interacted="interacted"
61
- :options="col.enums"
62
- :rules="col.rules"
63
- v-model="col.data[col.field]"
64
- v-bind="{ ...(col.model[1] || {}) }"
65
- />
66
- <MoreSelectList
67
- v-else-if="col.model[0] === 'MoreSelectList'"
68
- class="full-w"
69
- :interacted="interacted"
70
- :options="col.enums"
71
- :rules="col.rules"
72
- v-model="col.data[col.field]"
73
- v-bind="{ ...(col.model[1] || {}) }"
74
- />
75
- <MoreSelectTags
76
- v-else-if="col.model[0] === 'MoreSelectTags'"
77
- class="full-w"
78
- :interacted="interacted"
79
- :options="col.enums"
80
- :rules="col.rules"
81
- v-model="col.data[col.field]"
82
- v-bind="{ ...(col.model[1] || {}) }"
83
- />
84
- <MoreSelectPicker
85
- v-else-if="col.model[0] === 'MoreSelectPicker'"
86
- class="full-w"
87
- :interacted="interacted"
88
- :options="col.enums"
89
- :rules="col.rules"
90
- v-model="col.data[col.field]"
91
- v-bind="{ ...(col.model[1] || {}) }"
92
- />
93
- <SearchMoreSelect
94
- v-else-if="col.model[0] === 'SearchMoreSelect'"
95
- class="full-w"
96
- :interacted="interacted"
97
- :options="col.enums"
98
- :rules="col.rules"
99
- v-model="col.data[col.field]"
100
- v-bind="{ ...(col.model[1] || {}) }"
101
- />
102
- <PageSelect
103
- v-else-if="col.model[0] === 'PageSelect'"
104
- class="full-w"
105
- :interacted="interacted"
106
- :options="col.enums"
107
- :rules="col.rules"
108
- v-model="col.data[col.field]"
109
- v-bind="{ ...(col.model[1] || {}) }"
110
- />
111
- <DatePicker
112
- v-else-if="col.model[0] === 'DatePicker'"
113
- class="full-w"
114
- :interacted="interacted"
115
- :rules="col.rules"
116
- v-model="col.data[col.field]"
117
- v-bind="{ ...(col.model[1] || {}) }"
118
- />
119
- <ImgUpload v-else-if="col.model[0] === 'ImgUpload'" :interacted="interacted" :rules="col.rules" v-model="col.data[col.field]" v-bind="{ ...(col.model[1] || {}) }" />
120
- <TextArea
121
- v-else-if="col.model[0] === 'TextArea'"
122
- :interacted="interacted"
123
- :rules="col.rules"
124
- v-model="col.data[col.field]"
125
- v-bind="{ ...(col.model[1] || {}) }"
126
- ></TextArea>
127
- <Switch v-else-if="col.model[0] === 'Switch'" :interacted="interacted" :rules="col.rules" v-model="col.data[col.field]" v-bind="{ ...(col.model[1] || {}) }" />
128
- <Tree v-else-if="col.model[0] === 'Tree'" :interacted="interacted" :rules="col.rules" v-model="col.data[col.field]" v-bind="{ ...(col.model[1] || {}) }" />
129
- <Cascader
130
- v-else-if="col.model[0] === 'Cascader'"
131
- class="full-w"
132
- :interacted="interacted"
133
- :rules="col.rules"
134
- v-model="col.data[col.field]"
135
- :options="col.enums"
136
- v-bind="{ ...(col.model[1] || {}) }"
137
- />
138
- <Input v-else class="full-w" :interacted="interacted" :rules="col.rules" v-model="col.data[col.field]" v-bind="{ ...(col.model[1] || {}) }" />
2
+ <div class="form-loader n-sm-sub" :data-level="level" ui-row="">
3
+ <template v-for="(node, i1) in $nodes" :key="i1">
4
+ <div v-if="!node.clear" :key="i1" class="form-loader-item" :class="node.model[0] === 'Blank' ? 'form-loader-item-none n-no' : ''" :id="node._fid" :ui-col="node.media">
5
+ <!-- 字段外部上面插入其它内容 -->
6
+ <div class="flex-fixed" v-if="node.other && node.other.mt" v-bind="node.other.mt.attrs">
7
+ <template v-for="(item, idx) in node?.other?.mt?.child || []">
8
+ <div
9
+ v-if="!item.clear"
10
+ :key="idx"
11
+ v-html="item.value"
12
+ v-bind="item.attrs"
13
+ v-on="event({ col: item, node, data: data[node.field], idx: i1, fun: { fAdd, fDel, _rows } })"
14
+ ></div>
15
+ </template>
139
16
  </div>
140
- </template>
17
+ <div class="flex-block" ui-flex="row lt">
18
+ <!-- 字段外部左边插入其他内容 -->
19
+ <div class="flex-fixed" v-if="node.other && node.other.ml" v-bind="node.other.ml.attrs">
20
+ <template v-for="(item, idx) in node?.other?.ml?.child || []">
21
+ <div
22
+ v-if="!item.clear"
23
+ :key="idx"
24
+ v-html="item.value"
25
+ v-bind="item.attrs"
26
+ v-on="event({ col: item, node, data: data[node.field], idx: i1, fun: { fAdd, fDel, _rows } })"
27
+ ></div>
28
+ </template>
29
+ </div>
30
+ <!-- 字段主体 -->
31
+ <div class="flex-block">
32
+ <div
33
+ :id="`form${index + '' ? '-' + index : ''}-field-${node.field || '*'}`"
34
+ v-bind="node.attrs"
35
+ v-on="event({ col: node, node, data, idx: i1, fun: { fAdd, fDel, _rows } })"
36
+ :data-level="level"
37
+ data-node="child"
38
+ >
39
+ <slot :name="node.field" :node="node" :data="data">
40
+ <div
41
+ v-if="node.label[0] !== '*'"
42
+ :class="`form-loader-label ${node.vertical ? 'flex-block' : 'flex-fixed nr-sm'} o-ls nt-ss`"
43
+ :style="labelcss(node)"
44
+ ui-flex="row xm"
45
+ >
46
+ <slot v-if="slots.includes(`${node.field}-label`)" :name="`${node.field}-label`"></slot>
47
+ <slot v-else name="every-label" :node="node" :data="data">
48
+ <template v-if="node.label[0]">
49
+ <h6 class="flex-block pr o-lm" style="padding-top: 2px" v-if="node.vertical" v-bind="node.label[1]">
50
+ <template v-if="node.label[0] === '*'"></template>
51
+ <template v-else>
52
+ <b v-if="node.rules.some((v) => v.required)" class="co-risk">﹡</b><span>{{ node.label[0] }}</span>
53
+ </template>
54
+ </h6>
55
+ <h6 v-else class="flex-block ar pr o-lm" style="padding-top: 2px" v-bind="node.label[1]">
56
+ <template v-if="node.label[0] === '*'"></template>
57
+ <template v-else>
58
+ <b v-if="node.rules.some((v) => v.required)" class="co-risk">﹡</b><span>{{ node.label[0] }}</span>
59
+ </template>
60
+ </h6>
61
+ </template>
62
+ </slot>
63
+ </div>
64
+ <div class="flex-block" ui-flex="col xm">
65
+ <!-- 字段内部上边插入其他内容 -->
66
+ <div class="flex-fixed" v-if="node.other && node.other.nt" v-bind="node.other.nt.attrs">
67
+ <template v-for="(item, idx) in node?.other?.nt?.child || []">
68
+ <div
69
+ v-if="!item.clear"
70
+ :key="idx"
71
+ v-html="item.value"
72
+ v-bind="item.attrs"
73
+ v-on="event({ col: item, node, data: data[node.field], idx: i1, fun: { fAdd, fDel, _rows } })"
74
+ ></div>
75
+ </template>
76
+ </div>
77
+ <div ui-flex="row lt">
78
+ <!-- 字段内部左边插入其他内容 -->
79
+ <div class="flex-fixed" v-if="node.other && node.other.nl" v-bind="node.other.nl.attrs">
80
+ <template v-for="(item, idx) in node?.other?.nl?.child || []">
81
+ <div
82
+ v-if="!item.clear"
83
+ :key="idx"
84
+ v-html="item.value"
85
+ v-bind="item.attrs"
86
+ v-on="event({ col: item, node, data: data[node.field], idx: i1, fun: { fAdd, fDel, _rows } })"
87
+ ></div>
88
+ </template>
89
+ </div>
90
+ <div class="flex-block">
91
+ <template v-if="node.array">
92
+ <template v-if="isArray(node.array.lists)">
93
+ <div v-if="data[node.field].length" class="form-loader-group-array flex-block n-sm-sub" ui-row="">
94
+ <div v-for="(item, i2) in data[node.field]" :key="i2" class="form-loader-array-item full">
95
+ <div class="flex-fixed" v-if="node.array.other && node.array.other.ml" v-bind="node.array.other.ml.attrs">
96
+ <template v-if="node.array.other.mt.child && isArray(node.array.other.mt.child)">
97
+ <div
98
+ v-for="(item, idx) in node.array.other.mt.child"
99
+ v-if="!item.clear"
100
+ :key="idx"
101
+ v-html="item.value"
102
+ v-bind="item.attrs"
103
+ v-on="event({ col: item, node, data: data[node.field], idx: i2, fun: { fAdd, fDel, _rows } })"
104
+ ></div>
105
+ </template>
106
+ </div>
107
+ <div class="full" ui-flex="row xt">
108
+ <div class="flex-fixed" v-if="node.array.other && node.array.other.ml" v-bind="node.array.other.ml.attrs">
109
+ <template v-if="node.array.other.ml.child && isArray(node.array.other.ml.child)">
110
+ <div
111
+ v-for="(item, idx) in node.array.other.ml.child"
112
+ v-if="!item.clear"
113
+ :key="idx"
114
+ v-html="item.value"
115
+ v-bind="item.attrs"
116
+ v-on="event({ col: item, node, data: data[node.field], idx: i2, fun: { fAdd, fDel, _rows } })"
117
+ ></div>
118
+ </template>
119
+ </div>
120
+ <div class="flex-block" v-bind="node.array.attrs">
121
+ <FormLoader
122
+ v-model:form="node.array.lists"
123
+ v-model:data="item"
124
+ :parentNode="node"
125
+ v-model:parent="data[node.field]"
126
+ v-model:fulldata="data"
127
+ :rows="rows"
128
+ :level="level + 1"
129
+ :index="i2"
130
+ :debug="debug"
131
+ :mode="mode"
132
+ :interacted="interacted"
133
+ :slots="slots"
134
+ :globalLabelWidth="lw"
135
+ :cache="cache"
136
+ >
137
+ <!-- 通用插槽 -->
138
+ <template v-slot:every-label="slotprops"><slot name="every-label" v-bind="slotprops"></slot></template>
139
+ <template v-slot:array-label="slotprops"><slot name="array-label" v-bind="slotprops"></slot></template>
140
+ <template v-slot:child-label="slotprops"><slot name="child-label" v-bind="slotprops"></slot></template>
141
+
142
+ <!-- Vue 3 支持动态插槽,不需要手动遍历 -->
143
+ <template v-for="slotName in slots" :key="slotName" v-slot:[slotName]="slotprops">
144
+ <slot :name="slotName" v-bind="slotprops"></slot>
145
+ </template>
146
+ </FormLoader>
147
+ </div>
148
+ <div class="flex-fixed" v-if="node.array.other && node.array.other.mr" v-bind="node.array.other.mr.attrs">
149
+ <template v-for="(item, idx) in node?.array?.other?.mr?.child || []">
150
+ <div
151
+ v-if="!item.clear"
152
+ :key="idx"
153
+ v-html="item.value"
154
+ v-bind="item.attrs"
155
+ v-on="event({ col: item, node, data: data[node.field], idx: i2, fun: { fAdd, fDel, _rows } })"
156
+ ></div>
157
+ </template>
158
+ </div>
159
+ </div>
160
+ <div class="flex-fixed" v-if="node.array.other && node.array.other.ml" v-bind="node.array.other.ml.attrs">
161
+ <template v-if="node.array.other.mb.child && isArray(node.array.other.mb.child)">
162
+ <div
163
+ v-for="(item, idx) in node.array.other.mb.child"
164
+ v-if="!item.clear"
165
+ :key="idx"
166
+ v-html="item.value"
167
+ v-bind="item.attrs"
168
+ v-on="event({ col: item, node, data: data[node.field], idx: i2, fun: { fAdd, fDel, _rows } })"
169
+ ></div>
170
+ </template>
171
+ </div>
172
+ </div>
173
+ </div>
174
+ </template>
175
+ <div v-else v-html="err(`配置错误:Field: ${node.field} 配置了属性值 [array.lists] 必须是一个数组`)"></div>
176
+ </template>
177
+ <template v-else-if="node.child">
178
+ <template v-if="isArray(node.child)">
179
+ <FormLoader
180
+ class="flex-block form-loader-group-child"
181
+ v-model:form="node.child"
182
+ v-model:data="form._data"
183
+ v-model:fulldata="data"
184
+ :rows="rows"
185
+ :level="level + 1"
186
+ :debug="debug"
187
+ :mode="mode"
188
+ :interacted="interacted"
189
+ :slots="slots"
190
+ :globalLabelWidth="lw"
191
+ :cache="cache"
192
+ >
193
+ <!-- 通用插槽 -->
194
+ <template v-slot:every-label="slotprops"><slot name="every-label" v-bind="slotprops"></slot></template>
195
+ <template v-slot:array-label="slotprops"><slot name="array-label" v-bind="slotprops"></slot></template>
196
+ <template v-slot:child-label="slotprops"><slot name="child-label" v-bind="slotprops"></slot></template>
197
+
198
+ <template v-for="slotName in slots" :key="slotName" v-slot:[slotName]="slotprops">
199
+ <slot :name="slotName" v-bind="slotprops"></slot>
200
+ </template>
201
+ </FormLoader>
202
+ </template>
203
+ <div v-else v-html="err(`配置错误:Field: ${node.field} 配置了属性值 [child] 必须是一个数组`)"></div>
204
+ </template>
205
+ <template v-else>
206
+ <FormRender v-model:node="node" v-model:data="data" :interacted="interacted" :data-field="node.field" :mode="mode">
207
+ <template v-slot:[`${node.field}-value`]="slotprops">
208
+ <slot :name="`${node.field}-value`" v-bind="slotprops"></slot>
209
+ </template>
210
+ </FormRender>
211
+ </template>
212
+ </div>
213
+ <!-- 字段内部右边插入其他内容 -->
214
+ <div class="flex-fixed" v-if="node.other && node.other.nr" v-bind="node.other.nr.attrs">
215
+ <template v-for="(item, idx) in node?.other?.nr?.child || []">
216
+ <div
217
+ v-if="!item.clear"
218
+ :key="idx"
219
+ v-html="item.value"
220
+ v-bind="item.attrs"
221
+ v-on="event({ col: item, parentNode, node, data: parent, idx: i1, index, fun: { fAdd, fDel, _rows } })"
222
+ ></div>
223
+ </template>
224
+ </div>
225
+ </div>
226
+ <!-- 字段内部下边插入其他内容 -->
227
+ <div class="flex-fixed" v-if="node.other && node.other.nb" v-bind="node.other.nb.attrs">
228
+ <template v-for="(item, idx) in node?.other?.nb?.child || []">
229
+ <div
230
+ v-if="!item.clear"
231
+ :key="idx"
232
+ v-html="item.value"
233
+ v-bind="item.attrs"
234
+ v-on="event({ col: item, node, data: data[node.field], idx: i1, fun: { fAdd, fDel, _rows } })"
235
+ ></div>
236
+ </template>
237
+ </div>
238
+ </div>
239
+ </slot>
240
+ </div>
241
+ </div>
242
+ <!-- 字段外部右边插入其他内容 -->
243
+ <div class="flex-fixed" v-if="node.other && node.other.mr && !node.other.mr.clear" v-bind="node.other.mr.attrs">
244
+ <template v-for="(item, idx) in node?.other?.mr?.child || []">
245
+ <div
246
+ v-if="!item.clear"
247
+ :key="idx"
248
+ v-html="item.value"
249
+ v-bind="item.attrs"
250
+ v-on="event({ col: item, node, data: data[node.field], idx: i1, fun: { fAdd, fDel, _rows } })"
251
+ ></div>
252
+ </template>
253
+ </div>
254
+ </div>
255
+ <!-- 字段外部下边插入其他内容 -->
256
+ <div class="flex-fixed" v-if="node.other && node.other.mb" v-bind="node.other.mb.attrs">
257
+ <template v-for="(item, idx) in node?.other?.mb?.child || []">
258
+ <div
259
+ v-if="!item.clear"
260
+ :key="idx"
261
+ v-html="item.value"
262
+ v-bind="item.attrs"
263
+ v-on="event({ col: item, node, data: data[node.field], idx: i1, fun: { fAdd, fDel, _rows } })"
264
+ ></div>
265
+ </template>
266
+ </div>
267
+ </div>
268
+ </template>
269
+ <div v-if="slots.submit" class="full-x" ui-flex="row lm">
270
+ <div class="flex-fixed" :style="labelcss($nodes)">&nbsp;</div>
271
+ <div class="flex-block"><slot name="submit"></slot></div>
141
272
  </div>
142
- </slot>
273
+ </div>
143
274
  </template>
144
275
  <script setup lang="ts">
145
- import { watch, ref, reactive, onUnmounted, computed } from 'vue';
146
- import { useRoute, useRouter } from 'vue-router';
147
- import { isString, isObject, isFunction, deepcopy, isArray } from '@fekit/utils';
148
- import {
149
- Input,
150
- Switch,
151
- TextArea,
152
- Select,
153
- SelectList,
154
- SelectTags,
155
- SelectPicker,
156
- SearchSelect,
157
- PageSelect,
158
- MoreSelect,
159
- MoreSelectList,
160
- MoreSelectTags,
161
- MoreSelectPicker,
162
- DatePicker,
163
- SearchMoreSelect,
164
- ImgUpload,
165
- Cascader
166
- } from '../../form';
167
- import { Tree } from '../../display';
276
+ import { computed, reactive, useSlots, withDefaults } from 'vue';
277
+ import { deepcopy, isObject, isArray, isFunction } from '@fekit/utils';
168
278
 
169
- const route: any = useRoute();
279
+ const slots = useSlots();
170
280
 
171
- // 计算Label行高
172
- const clh = ({ sz = '' }: any = {}) => {
173
- const lhs: any = { xs: 'lh-sm', s: 'lh-mm', m: 'lh-ls', l: 'lh-ll', xl: 'lh-xl' };
174
- return lhs[sz] || 'lh-ls';
175
- };
176
-
177
- // 计算Label宽度
178
- function clw(label: any = '') {
179
- let emWidth = 0;
180
- if (isString(label)) {
181
- for (let i = 0; i < label.length; i++) {
182
- const char = label[i];
183
- if (/^[\u4e00-\u9fa5]+$/.test(char)) {
184
- emWidth += 1;
185
- } else {
186
- emWidth += 0.5;
187
- }
188
- }
189
- }
190
- return emWidth;
191
- }
192
-
193
- interface FormParam {
194
- label: string | (() => string);
195
- field: string | (() => string);
196
- paths: string | (() => string);
197
- model?: string | Array<any> | (() => string | Array<any>);
198
- enums?: Array<any> | (() => string | Array<any>);
199
- rules?: Array<any> | (() => string | Array<any>);
200
- event?: Array<any> | (() => string | Array<any>);
201
- attrs?: Array<any> | (() => string | Array<any>);
202
- value?: any | (() => any);
203
- clear?: boolean | (() => boolean);
281
+ interface NodeProps {
282
+ label?: string | ((data: any) => string);
283
+ field?: string | ((data: any) => string);
284
+ model?: string | ((data: any) => string);
285
+ attrs?: Record<string, any> | ((data: any) => Record<string, any>);
286
+ rules?: Record<string, any> | ((data: any) => Record<string, any>);
287
+ clear?: boolean | ((data: any) => boolean);
288
+ media?: string | ((data: any) => string);
204
289
  }
205
290
 
206
- /**
207
- * 入参说明
208
- * form 表单结构
209
- * data 表单数据
210
- * rows 栅格系统
211
- * idx 如果表单是数组的话这里传入下标
212
- * vertical 是否垂直排列
213
- * interacted 用户是否交互
214
- */
215
-
216
- // 类型
217
291
  interface Props {
218
- form: Array<FormParam>;
292
+ form: NodeProps[];
219
293
  data: object;
220
- rows?: string;
221
- idx?: string | number;
222
- vertical?: boolean;
223
- interacted?: boolean;
294
+ level?: number | ((data: any) => number);
295
+ index?: number | ((data: any) => number);
224
296
  }
225
- // 入参
226
- const props: any = withDefaults(defineProps<Props>(), {
227
- form: () => [],
297
+ const props = withDefaults(defineProps<Props>(), {
298
+ node: () => [],
228
299
  data: () => ({}),
229
- rows: 'mob-24 pad-12 dpc-8',
230
- idx: '',
231
- vertical: false,
232
- interacted: false
300
+ level: 0,
301
+ index: 0,
233
302
  });
234
303
 
235
- const state: any = reactive({
236
- funs: [],
237
- form: [],
238
- _lw: 6
304
+ const state = reactive({
305
+ globalLabelWidth: 0,
306
+ lw: 0,
239
307
  });
240
308
 
241
- // 更新表单结构
242
- watch(
243
- [() => props.form, () => props.data, () => props.idx],
244
- () => {
245
- state.form = props.form.map((item: any) => {
246
- // 计算宽度
247
- const _w = clw(item.label) + 2;
248
- if (_w > state._lw) {
249
- state._lw = _w;
250
- }
251
-
252
- // 函数处理
253
- if (isObject(item)) {
254
- for (const key in item) {
255
- const val = item[key] || {};
256
- // 处理函数
257
- if (isFunction(val)) {
258
- item[key] = val(props.data, props.form, route);
259
- // console.log(250, key, val);
260
- // state.funs.push({ item, key, fun: val });
261
- }
262
- // 对象处理
263
- // if (isObject(val) && isFunction(val.setup)) {
264
- // state.funs.push({ item, key, val: val.value, fun: val.setup });
265
- // }
266
- }
267
- }
309
+ const $nodes = computed(() => {
310
+ const _nodes = deepcopy(props.form);
311
+ return _nodes.map((node: any) => {
312
+ return node;
313
+ });
314
+ });
268
315
 
269
- // 添加ID
270
- item._fid = `form-${props.idx !== '' ? props.idx + '-' : ''}field-${item.field}`;
316
+ const event = ({ col, node, data, idx = null, fun } = {}) => {
317
+ const _event = { ...col.event } || {};
271
318
 
272
- // 模型处理
273
- if (item.model) {
274
- if (isString(item.model)) {
275
- item.model = [item.model, { verify: false }];
319
+ // 代理交互
320
+ if (col.proxy) {
321
+ if (col.proxy === 'array-add-btn' && node.array) {
322
+ if (node.array) {
323
+ // 合并配置事件与代理事件
324
+ if (fun.fAdd) {
325
+ const _click = _event.click;
326
+ _event.click = function (...args) {
327
+ if (isFunction(_click)) {
328
+ _click.apply(this, args);
329
+ }
330
+ fun.fAdd(node, data, idx);
331
+ };
276
332
  }
277
333
  } else {
278
- item.model = ['Input', { verify: false }];
334
+ console.warn('数组新增按钮代理`array-add-btn`需配置在`array`下');
279
335
  }
280
- if (item.model[1] && !Object.prototype.hasOwnProperty.call(item.model[1], 'verify')) {
281
- item.model[1].verify = false;
336
+ }
337
+ if (col.proxy === 'array-del-btn') {
338
+ if (node.array) {
339
+ // 合并配置事件与代理事件
340
+ if (fun.fDel) {
341
+ const _click = _event.click;
342
+ _event.click = function (...args) {
343
+ if (isFunction(_click)) {
344
+ _click.apply(this, args);
345
+ }
346
+ fun.fDel(node, data, idx);
347
+ };
348
+ }
349
+ } else {
350
+ console.warn('数组删除按钮代理`array-del-btn`需配置在`array`下');
282
351
  }
352
+ }
283
353
 
284
- // 数据路径
285
- item.data = props.data;
286
- (item.paths?.split('.') || [])?.forEach((i: any) => {
287
- if (item.data[i]) {
288
- item.data = item.data[i];
289
- }
290
- });
354
+ if (col.proxy === 'array-add-sub' && node.array) {
355
+ if (node.array) {
356
+ console.log(784, node, data);
357
+ // 合并配置事件与代理事件
358
+ // if (fun.fAdd) {
359
+ // const _click = _event.click;
360
+ // _event.click = function(...args) {
361
+ // if (isFunction(_click)) {
362
+ // _click.apply(this, args);
363
+ // }
364
+ // fun.fAdd(node, data[node.field], idx);
365
+ // };
366
+ // }
367
+ } else {
368
+ console.warn('数组新增按钮代理`array-add-btn`需配置在`array`下');
369
+ }
370
+ }
371
+ }
291
372
 
292
- // 函数处理
293
- return item;
294
- });
295
- },
296
- { deep: true, immediate: true }
297
- );
373
+ if (isObject(_event)) {
374
+ for (const key in _event) {
375
+ const fun = _event[key];
376
+ if (isFunction(fun)) {
377
+ _event[key] = (...args) => {
378
+ return fun({ node: col, data, idx, formloader: this }, ...args);
379
+ };
380
+ }
381
+ }
382
+ }
383
+ return { ..._event };
384
+ };
298
385
 
299
- watch(
300
- () => state.funs,
301
- () => {
302
- // 监听列表
303
- // state.funs.map(({ item = {}, key = '', val = '', fun = () => {} }: any = {}) => {
304
- // console.log(280, item);
305
- // const v = fun(props.data, item, route);
306
- // if (v instanceof Promise) {
307
- // item[key] = val;
308
- // v.then((res: any) => {
309
- // item[key] = res;
310
- // });
311
- // } else {
312
- // item[key] = v;
313
- // }
314
- // });
315
- },
316
- { deep: true, immediate: true }
317
- );
386
+ const labelcss = (nodes: any) => {
387
+ if (nodes.vertical) {
388
+ // 竖向
389
+ return ``;
390
+ } else if (nodes.transverse) {
391
+ // 横向不固定宽度
392
+ return ``;
393
+ } else {
394
+ // 横向
395
+ const _w = Math.max(state.globalLabelWidth, state.lw);
396
+ return `width:${_w}em; max-width:50%;`;
397
+ }
398
+ };
318
399
  </script>